From: Simon A. Eugster Date: Mon, 13 Dec 2010 08:20:34 +0000 (+0000) Subject: Audio scopes: Only deliver audio when required for better performance when scopes... X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=91430842a9fcc6ad00a18da81928d24ae821ae0a;p=kdenlive Audio scopes: Only deliver audio when required for better performance when scopes are disabled svn path=/trunk/kdenlive/; revision=5172 --- diff --git a/src/audioscopes/ffttools.cpp b/src/audioscopes/ffttools.cpp index 1464c7ef..2ede0fa5 100644 --- a/src/audioscopes/ffttools.cpp +++ b/src/audioscopes/ffttools.cpp @@ -15,7 +15,7 @@ #include "ffttools.h" -// Uncomment for debugging +// Uncomment for debugging, like writing a GNU Octave .m file to /tmp //#define DEBUG_FFTTOOLS #ifdef DEBUG_FFTTOOLS diff --git a/src/audiosignal.cpp b/src/audiosignal.cpp index 6a935869..212e119b 100644 --- a/src/audiosignal.cpp +++ b/src/audiosignal.cpp @@ -18,7 +18,6 @@ ***************************************************************************/ #include "audiosignal.h" -#include "kdenlivesettings.h" #include @@ -42,15 +41,23 @@ AudioSignal::AudioSignal(QWidget *parent): QWidget(parent) col << Qt::darkYellow << Qt::darkYellow << Qt::darkYellow; col << Qt::red << Qt::red; setContextMenuPolicy(Qt::ActionsContextMenu); - QAction *showSignal = new QAction(i18n("Monitor audio signal"), this); - showSignal->setCheckable(true); - showSignal->setChecked(KdenliveSettings::monitor_audio()); - connect(showSignal, SIGNAL(toggled(bool)), this, SLOT(slotSwitchAudioMonitoring(bool))); - addAction(showSignal); + m_aMonitoringEnabled = new QAction(i18n("Monitor audio signal"), this); + m_aMonitoringEnabled->setCheckable(true); + connect(m_aMonitoringEnabled, SIGNAL(toggled(bool)), this, SLOT(slotSwitchAudioMonitoring(bool))); + addAction(m_aMonitoringEnabled); } +AudioSignal::~AudioSignal() +{ + delete m_aMonitoringEnabled; +} + +bool AudioSignal::monitoringEnabled() const +{ + return m_aMonitoringEnabled->isChecked(); +} -void AudioSignal::slotReceiveAudio(const QVector& data, int freq ,int num_channels ,int samples){ +void AudioSignal::slotReceiveAudio(const QVector& data, int, int num_channels, int samples){ int num_samples = samples > 200 ? 200 : samples; @@ -84,6 +91,9 @@ void AudioSignal::showAudio(const QByteArray arr) } void AudioSignal::paintEvent(QPaintEvent* /*e*/) { + if (!m_aMonitoringEnabled->isChecked()) { + return; + } QPainter p(this); //p.begin(); //p.fillRect(0,0,(unsigned char)channels[0]*width()/255,height()/2,QBrush(Qt::SolidPattern)); @@ -111,9 +121,8 @@ void AudioSignal::paintEvent(QPaintEvent* /*e*/) p.end(); } -void AudioSignal::slotSwitchAudioMonitoring(bool isOn) +void AudioSignal::slotSwitchAudioMonitoring(bool) { - KdenliveSettings::setMonitor_audio(isOn); emit updateAudioMonitoring(); } diff --git a/src/audiosignal.h b/src/audiosignal.h index 5a2680a7..9034773c 100644 --- a/src/audiosignal.h +++ b/src/audiosignal.h @@ -31,19 +31,27 @@ class AudioSignal : public QWidget Q_OBJECT public: AudioSignal(QWidget *parent = 0); + ~AudioSignal(); + /** @brief Used for checking whether audio data needs to be delivered */ + bool monitoringEnabled() const; + private: QLabel* label; QByteArray channels,peeks,peekage; QList col; + QAction *m_aMonitoringEnabled; + protected: void paintEvent(QPaintEvent*); + public slots: void showAudio(const QByteArray); void slotReceiveAudio(const QVector&,int,int,int); private slots: - void slotSwitchAudioMonitoring(bool isOn); + void slotSwitchAudioMonitoring(bool isOn); + signals: - void updateAudioMonitoring(); + void updateAudioMonitoring(); }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 238a0fbf..1cdb931b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -112,7 +112,9 @@ #include +// Uncomment for deeper debugging //#define DEBUG_MAINW + #ifdef DEBUG_MAINW #include #endif @@ -247,9 +249,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_vectorscopeDock->setWidget(m_vectorscope); addDockWidget(Qt::TopDockWidgetArea, m_vectorscopeDock); connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), m_vectorscope, SLOT(forceUpdate(bool))); - connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_vectorscopeDock); + connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_vectorscopeDock); m_waveform = new Waveform(m_projectMonitor, m_clipMonitor); m_waveformDock = new QDockWidget(i18n("Waveform"), this); @@ -257,9 +259,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_waveformDock->setWidget(m_waveform); addDockWidget(Qt::TopDockWidgetArea, m_waveformDock); connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), m_waveform, SLOT(forceUpdate(bool))); - connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_waveformDock); + connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_waveformDock); m_RGBParade = new RGBParade(m_projectMonitor, m_clipMonitor); m_RGBParadeDock = new QDockWidget(i18n("RGB Parade"), this); @@ -267,9 +269,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_RGBParadeDock->setWidget(m_RGBParade); addDockWidget(Qt::TopDockWidgetArea, m_RGBParadeDock); connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), m_RGBParade, SLOT(forceUpdate(bool))); - connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_RGBParadeDock); + connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_RGBParadeDock); m_histogram = new Histogram(m_projectMonitor, m_clipMonitor); m_histogramDock = new QDockWidget(i18n("Histogram"), this); @@ -277,9 +279,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_histogramDock->setWidget(m_histogram); addDockWidget(Qt::TopDockWidgetArea, m_histogramDock); connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), m_histogram, SLOT(forceUpdate(bool))); - connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_histogram, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_histogramDock); + connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_histogram, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_histogramDock); m_audiosignal = new AudioSignal; @@ -287,25 +289,27 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_audiosignalDock->setObjectName("audiosignal"); m_audiosignalDock->setWidget(m_audiosignal); addDockWidget(Qt::TopDockWidgetArea, m_audiosignalDock); - connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), m_monitorManager, SLOT(slotUpdateAudioMonitoring())); - /*if (m_projectMonitor) { - connect(m_projectMonitor->render, SIGNAL(showAudioSignal(const QByteArray&)), m_audiosignal, SLOT(showAudio(const QByteArray&))); - } - if (m_clipMonitor) { - connect(m_clipMonitor->render, SIGNAL(showAudioSignal(const QByteArray&)), m_audiosignal, SLOT(showAudio(const QByteArray&))); - }*/ +// connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), m_monitorManager, SLOT(slotUpdateAudioMonitoring())); + connect(m_audiosignalDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), this, SLOT(slotUpdateAudioScopeFrameRequest())); m_audioSpectrum = new AudioSpectrum(); m_audioSpectrumDock = new QDockWidget(i18n("AudioSpectrum"), this); m_audioSpectrumDock->setObjectName(m_audioSpectrum->widgetName()); m_audioSpectrumDock->setWidget(m_audioSpectrum); addDockWidget(Qt::TopDockWidgetArea, m_audioSpectrumDock); + m_audioScopesList.append(m_audioSpectrum); + connect(m_audioSpectrumDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + connect(m_audioSpectrum, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); m_spectrogram = new Spectrogram(); m_spectrogramDock = new QDockWidget(i18n("Spectrogram"), this); m_spectrogramDock->setObjectName(m_spectrogram->widgetName()); m_spectrogramDock->setWidget(m_spectrogram); addDockWidget(Qt::TopDockWidgetArea, m_spectrogramDock); + m_audioScopesList.append(m_spectrogram); + connect(m_audioSpectrumDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + connect(m_audioSpectrum, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); // Connect the audio signal to the audio scope slots bool b = true; @@ -4001,8 +4005,8 @@ void MainWindow::slotMonitorRequestRenderFrame(bool request) m_projectMonitor->render->sendFrameForAnalysis = true; return; } else { - for (int i = 0; i < m_scopesList.count(); i++) { - if (m_scopesList.at(i)->isVisible() && tabifiedDockWidgets(m_scopesList.at(i)).isEmpty() && static_cast(m_scopesList.at(i)->widget())->autoRefreshEnabled()) { + for (int i = 0; i < m_gfxScopesList.count(); i++) { + if (m_gfxScopesList.at(i)->isVisible() && tabifiedDockWidgets(m_gfxScopesList.at(i)).isEmpty() && static_cast(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled()) { request = true; break; } @@ -4016,19 +4020,19 @@ void MainWindow::slotMonitorRequestRenderFrame(bool request) } } -void MainWindow::slotUpdateScopeFrameRequest() +void MainWindow::slotUpdateGfxScopeFrameRequest() { // We need a delay to make sure widgets are hidden after a close event for example - QTimer::singleShot(500, this, SLOT(slotDoUpdateScopeFrameRequest())); + QTimer::singleShot(500, this, SLOT(slotDoUpdateGfxScopeFrameRequest())); } -void MainWindow::slotDoUpdateScopeFrameRequest() +void MainWindow::slotDoUpdateGfxScopeFrameRequest() { // Check scopes bool request = false; - for (int i = 0; i < m_scopesList.count(); i++) { - if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && static_cast(m_scopesList.at(i)->widget())->autoRefreshEnabled()) { - kDebug() << "SCOPE VISIBLE: " << static_cast(m_scopesList.at(i)->widget())->widgetName(); + for (int i = 0; i < m_gfxScopesList.count(); i++) { + if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && static_cast(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled()) { + kDebug() << "SCOPE VISIBLE: " << static_cast(m_gfxScopesList.at(i)->widget())->widgetName(); request = true; break; } @@ -4044,13 +4048,40 @@ void MainWindow::slotDoUpdateScopeFrameRequest() } } +void MainWindow::slotUpdateAudioScopeFrameRequest() +{ + QTimer::singleShot(500, this, SLOT(slotDoUpdateAudioScopeFrameRequest())); +} + +void MainWindow::slotDoUpdateAudioScopeFrameRequest() +{ + bool request = false; + for (int i = 0; i < m_audioScopesList.count(); i++) { + if (!m_audioScopesList.at(i)->visibleRegion().isEmpty() && m_audioScopesList.at(i)->autoRefreshEnabled()) { + kDebug() << "AUDIO SCOPE VISIBLE: " << m_audioScopesList.at(i)->widgetName(); + request = true; + break; + } + } + // Handle audio signal separately (no common interface) + if (!m_audiosignal->visibleRegion().isEmpty() && m_audiosignal->monitoringEnabled()) { + kDebug() << "AUDIO SCOPE VISIBLE: " << "audiosignal"; + request = true; + } +#ifdef DEBUG_MAINW + qDebug() << "Scopes Requesting Audio data: " << request; +#endif + KdenliveSettings::setMonitor_audio(request); + m_monitorManager->slotUpdateAudioMonitoring(); +} + void MainWindow::slotUpdateColorScopes() { bool request = false; - for (int i = 0; i < m_scopesList.count(); i++) { + for (int i = 0; i < m_gfxScopesList.count(); i++) { // Check if we need the renderer to send a new frame for update - if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast(m_scopesList.at(i)->widget())->autoRefreshEnabled())) request = true; - static_cast(m_scopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive()); + if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled())) request = true; + static_cast(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive()); } if (request) { if (m_clipMonitor->isActive()) m_clipMonitor->render->sendFrameUpdate(); @@ -4063,10 +4094,10 @@ void MainWindow::slotOpenStopmotion() if (m_stopmotion == NULL) { m_stopmotion = new StopmotionWidget(m_activeDocument->projectFolder(), m_stopmotion_actions->actions(), this); connect(m_stopmotion, SIGNAL(addOrUpdateSequence(const QString)), m_projectList, SLOT(slotAddOrUpdateSequence(const QString))); - for (int i = 0; i < m_scopesList.count(); i++) { + for (int i = 0; i < m_gfxScopesList.count(); i++) { // Check if we need the renderer to send a new frame for update /*if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast(m_scopesList.at(i)->widget())->autoRefreshEnabled())) request = true;*/ - connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast(m_scopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage))); + connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast(m_gfxScopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage))); //static_cast(m_scopesList.at(i)->widget())->slotMonitorCapture(); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 602441b8..a5f22924 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -70,6 +70,7 @@ class Waveform; class RGBParade; class KActionCollection; class AudioSignal; +class AbstractAudioScopeWidget; class AudioSpectrum; class Spectrogram; @@ -193,7 +194,8 @@ private: KComboBox *m_timecodeFormat; /** This list holds all the scopes used in Kdenlive, allowing to manage some global settings */ - QList m_scopesList; + QList m_gfxScopesList; + QList m_audioScopesList; QMenu *m_videoEffectsMenu; QMenu *m_audioEffectsMenu; @@ -518,9 +520,11 @@ private slots: /** @brief The monitor informs that it needs (or not) to have frames sent by the renderer. */ void slotMonitorRequestRenderFrame(bool request); /** @brief Check if someone needs the render frame sent. */ - void slotUpdateScopeFrameRequest(); + void slotUpdateGfxScopeFrameRequest(); /** @brief Check if someone needs the render frame sent. */ - void slotDoUpdateScopeFrameRequest(); + void slotDoUpdateGfxScopeFrameRequest(); + void slotUpdateAudioScopeFrameRequest(); + void slotDoUpdateAudioScopeFrameRequest(); /** @brief When switching between monitors, update the visible scopes. */ void slotUpdateColorScopes(); /** @brief Switch current monitor to fullscreen. */ diff --git a/src/monitormanager.h b/src/monitormanager.h index aafcd12d..625bc6bf 100644 --- a/src/monitormanager.h +++ b/src/monitormanager.h @@ -60,10 +60,10 @@ public slots: * @ref activateMonitor * @param activateClip whether to activate the clip monitor */ void slotSwitchMonitors(bool activateClip); + void slotUpdateAudioMonitoring(); private slots: void slotRefreshCurrentMonitor(); - void slotUpdateAudioMonitoring(); private: Monitor *m_clipMonitor; diff --git a/src/renderer.cpp b/src/renderer.cpp index 14730eda..203cef2b 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -68,7 +68,9 @@ static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr if (self->sendFrameForAnalysis && frame_ptr->convert_image) { self->emitFrameUpdated(frame); } - if (self->analyseAudio) self->showAudio(frame); + if (self->analyseAudio) { + self->showAudio(frame); + } if (frame.get_double("_speed") == 0.0) { self->emitConsumerStopped(); } else if (frame.get_double("_speed") < 0.0 && mlt_frame_get_position(frame_ptr) <= 0) { @@ -1466,7 +1468,9 @@ void Render::showFrame(Mlt::Frame& frame) void Render::showAudio(Mlt::Frame& frame) { - if (!frame.is_valid() || frame.get_int("test_audio") != 0) return; + if (!frame.is_valid() || frame.get_int("test_audio") != 0) { + return; + } mlt_audio_format audio_format = mlt_audio_s16; int freq = 0; int num_channels = 0;