From 7d12e6ef9d9b43edea5d8cd010786e2c1b1bc795 Mon Sep 17 00:00:00 2001 From: "Simon A. Eugster" Date: Mon, 6 Dec 2010 16:57:05 +0000 Subject: [PATCH] Audio Spectrum: * kiss_fft configuration is cached as well for better performance * Actual window size is shown in the widget (may differ from the selected window size due to limiting sampling rate) * Showing some ToolTips, removed Realtime option * Comments added svn path=/trunk/kdenlive/; revision=5141 --- src/audioscopes/audiospectrum.cpp | 66 ++++++++++++++++++------------- src/audioscopes/audiospectrum.h | 22 ++++++++--- src/widgets/audiospectrum_ui.ui | 41 +++++++++++++++++-- 3 files changed, 91 insertions(+), 38 deletions(-) diff --git a/src/audioscopes/audiospectrum.cpp b/src/audioscopes/audiospectrum.cpp index 2475094c..c9986f9d 100644 --- a/src/audioscopes/audiospectrum.cpp +++ b/src/audioscopes/audiospectrum.cpp @@ -36,6 +36,7 @@ const QString AudioSpectrum::directions[] = {"North", "Northeast", "East", "Sou AudioSpectrum::AudioSpectrum(QWidget *parent) : AbstractAudioScopeWidget(false, parent), + m_fftCfgs(), m_windowFunctions(), m_freqMax(10000), m_customFreq(false), @@ -54,6 +55,7 @@ AudioSpectrum::AudioSpectrum(QWidget *parent) : m_menu->addSeparator(); m_menu->addAction(m_aResetHz); + m_menu->removeAction(m_aRealtime); ui->windowSize->addItem("256", QVariant(256)); @@ -66,21 +68,25 @@ AudioSpectrum::AudioSpectrum(QWidget *parent) : ui->windowFunction->addItem(i18n("Hamming window"), FFTTools::Window_Hamming); - m_cfg = kiss_fftr_alloc(ui->windowSize->itemData(ui->windowSize->currentIndex()).toInt(), 0,0,0); - - bool b = true; - b &= connect(ui->windowSize, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateCfg())); b &= connect(m_aResetHz, SIGNAL(triggered()), this, SLOT(slotResetMaxFreq())); Q_ASSERT(b); + + ui->labelFFTSize->setToolTip(i18n("The maximum window size is limited by the number of samples per frame.")); + ui->windowSize->setToolTip(i18n("A bigger window improves the accuracy at the cost of computational power.")); + ui->windowFunction->setToolTip(i18n("The rectangular window function is good for signals with equal signal strength (narrow peak), but creates more smearing. See Window function on Wikipedia.")); + AbstractScopeWidget::init(); } AudioSpectrum::~AudioSpectrum() { writeConfig(); - free(m_cfg); + QHash::iterator i; + for (i = m_fftCfgs.begin(); i != m_fftCfgs.end(); i++) { + free(*i); + } delete m_aResetHz; } @@ -138,31 +144,41 @@ QImage AudioSpectrum::renderAudioScope(uint, const QVector audioFrame, QTime start = QTime::currentTime(); - bool customCfg = false; - kiss_fftr_cfg myCfg = m_cfg; + + // Determine the window size to use. It should be + // * not bigger than the number of samples actually available + // * divisible by 2 int fftWindow = ui->windowSize->itemData(ui->windowSize->currentIndex()).toInt(); if (fftWindow > num_samples) { fftWindow = num_samples; - customCfg = true; } if ((fftWindow & 1) == 1) { fftWindow--; - customCfg = true; } - if (customCfg) { + + // Show the window size used, for information + ui->labelFFTSizeNumber->setText(QVariant(fftWindow).toString()); + + // Get the kiss_fft configuration from the config cache + // or build a new configuration if the requested one is not available. + kiss_fftr_cfg myCfg; + const QString signature = cfgSignature(fftWindow); + if (m_fftCfgs.contains(signature)) { +#ifdef DEBUG_AUDIOSPEC + qDebug() << "Re-using FFT configuration with size " << fftWindow; +#endif + myCfg = m_fftCfgs.value(signature); + } else { +#ifdef DEBUG_AUDIOSPEC + qDebug() << "Creating FFT configuration with size " << fftWindow; +#endif myCfg = kiss_fftr_alloc(fftWindow, 0,0,0); + m_fftCfgs.insert(signature, myCfg); } float data[fftWindow]; float freqSpectrum[fftWindow/2]; - int16_t maxSig = 0; - for (int i = 0; i < fftWindow; i++) { - if (audioFrame.data()[i*num_channels] > maxSig) { - maxSig = audioFrame.data()[i*num_channels]; - } - } - // Prepare frequency space vector. The resulting FFT vector is only half as long. kiss_fft_cpx freqData[fftWindow/2]; @@ -303,10 +319,6 @@ QImage AudioSpectrum::renderAudioScope(uint, const QVector audioFrame, } #endif - if (customCfg) { - free(myCfg); - } - return spectrum; } else { emit signalScopeRenderingFinished(0, 1); @@ -392,13 +404,6 @@ QRect AudioSpectrum::scopeRect() { return m_scopeRect; } - -void AudioSpectrum::slotUpdateCfg() -{ - free(m_cfg); - m_cfg = kiss_fftr_alloc(ui->windowSize->itemData(ui->windowSize->currentIndex()).toInt(), 0,0,0); -} - void AudioSpectrum::slotResetMaxFreq() { m_customFreq = false; @@ -547,6 +552,11 @@ void AudioSpectrum::mouseReleaseEvent(QMouseEvent *event) AbstractAudioScopeWidget::mouseReleaseEvent(event); } +const QString AudioSpectrum::cfgSignature(const int size) +{ + return QString("s%1").arg(size); +} + #ifdef DEBUG_AUDIOSPEC #undef DEBUG_AUDIOSPEC diff --git a/src/audioscopes/audiospectrum.h b/src/audioscopes/audiospectrum.h index c3547972..45c21007 100644 --- a/src/audioscopes/audiospectrum.h +++ b/src/audioscopes/audiospectrum.h @@ -8,6 +8,12 @@ * (at your option) any later version. * ***************************************************************************/ +/** + Displays a spectral power distribution of audio samples. + The frequency distribution is calculated by means of a Fast Fourier Transformation. + For more information see Wikipedia:FFT and the code comments. +*/ + #ifndef AUDIOSPECTRUM_H #define AUDIOSPECTRUM_H @@ -53,12 +59,12 @@ protected: private: Ui::AudioSpectrum_UI *ui; - kiss_fftr_cfg m_cfg; - QHash > m_windowFunctions; + QHash m_fftCfgs; // FFT cfg cache + QHash > m_windowFunctions; // Window function cache QAction *m_aResetHz; - // Contains the plot only; m_scopeRect contains text and widgets as well + /** Contains the plot only; m_scopeRect contains text and widgets as well */ QRect m_innerScopeRect; /** Lower bound for the dB value to display */ @@ -66,13 +72,18 @@ private: /** Upper bound (max: 0) */ int m_dBmax; - /** Maximum frequency (depends on the sampling rate) - Stored for the HUD painter */ + /** Maximum frequency (limited by the sampling rate if determined automatically). + Stored for the painters. */ uint m_freqMax; /** The user has chosen a custom frequency. */ bool m_customFreq; + /** Returns a signature for a kiss_fft configuration + used as a hash in the cache */ + static const QString cfgSignature(const int size); + + ///// Movement detection ///// const int m_rescaleMinDist; const float m_rescaleVerticalThreshold; @@ -88,7 +99,6 @@ private: private slots: - void slotUpdateCfg(); void slotResetMaxFreq(); }; diff --git a/src/widgets/audiospectrum_ui.ui b/src/widgets/audiospectrum_ui.ui index 39dcb349..27f8bab7 100644 --- a/src/widgets/audiospectrum_ui.ui +++ b/src/widgets/audiospectrum_ui.ui @@ -14,10 +14,10 @@ Form - + - + Qt::Horizontal @@ -30,7 +30,7 @@ - + Qt::Vertical @@ -43,9 +43,42 @@ - + + + + + + + + True FFT size: + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + + -- 2.39.2