From ba5738446c246487bf73f1914b4fa37bbb41f752 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 3 Jun 2015 13:11:17 -0400 Subject: [PATCH] Bug1009: Correct interaction of Zero Padding and Frequency Gain... ... also an excuse to pull out a function I will want to reuse in a later project. The real fix was simply to use fftLen not windowSize. --- src/WaveClip.cpp | 45 +++++++++++++++++++++++++++------------------ src/WaveClip.h | 7 +++++++ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index c42e75ba5..94be7305d 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -842,6 +842,25 @@ void RecreateWindow( } } +void WaveClip::ComputeSpectrogramGainFactors(int fftLen, int frequencyGain, std::vector &gainFactors) +{ + if (frequencyGain > 0) { + // Compute a frequency-dependent gain factor + // scaled such that 1000 Hz gets a gain of 0dB + + // This is the reciprocal of the bin number of 1000 Hz: + const double factor = ((double)mRate / (double)fftLen) / 1000.0; + + const int half = fftLen / 2; + gainFactors.reserve(half); + // Don't take logarithm of zero! Let bin 0 replicate the gain factor for bin 1. + gainFactors.push_back(frequencyGain*log10(factor)); + for (sampleCount x = 1; x < half; x++) { + gainFactors.push_back(frequencyGain*log10(factor * x)); + } + } +} + bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache, float *freq, sampleCount *where, int numPixels, @@ -852,7 +871,7 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache, int maxFreq = gPrefs->Read(wxT("/Spectrum/MaxFreq"), 8000L); int range = gPrefs->Read(wxT("/Spectrum/Range"), 80L); int gain = gPrefs->Read(wxT("/Spectrum/Gain"), 20L); - int frequencygain = gPrefs->Read(wxT("/Spectrum/FrequencyGain"), 0L); + int frequencyGain = gPrefs->Read(wxT("/Spectrum/FrequencyGain"), 0L); int windowType; int windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); #ifdef EXPERIMENTAL_FFT_SKIP_POINTS @@ -897,7 +916,7 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache, mSpecCache->windowTypeOld == windowType && mSpecCache->windowSizeOld == windowSize && mSpecCache->zeroPaddingFactorOld == zeroPaddingFactor && - mSpecCache->frequencyGainOld == frequencygain && + mSpecCache->frequencyGainOld == frequencyGain && #ifdef EXPERIMENTAL_FFT_SKIP_POINTS mSpecCache->fftSkipPointsOld == fftSkipPoints && #endif //EXPERIMENTAL_FFT_SKIP_POINTS @@ -986,18 +1005,10 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache, mSpecCache->windowTypeOld = windowType; mSpecCache->windowSizeOld = windowSize; mSpecCache->zeroPaddingFactorOld = zeroPaddingFactor; - mSpecCache->frequencyGainOld = frequencygain; + mSpecCache->frequencyGainOld = frequencyGain; - float *gainfactor = NULL; - if(frequencygain > 0) { - // Compute a frequency-dependant gain factor - // scaled such that 1000 Hz gets a gain of 0dB - double factor = 0.001*(double)mRate/(double)windowSize; - gainfactor = new float[half]; - for(sampleCount x = 0; x < half; x++) { - gainfactor[x] = frequencygain*log10(factor * x); - } - } + std::vector gainFactors; + ComputeSpectrogramGainFactors(fftLen, frequencyGain, gainFactors); for (sampleCount x = 0; x < mSpecCache->len; x++) if (recalc[x]) { @@ -1080,16 +1091,14 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache, mRate, &mSpecCache->freq[half * x], autocorrelation, windowType); #endif // EXPERIMENTAL_USE_REALFFTF - if(gainfactor) { - // Apply a frequency-dependant gain factor + if (!gainFactors.empty()) { + // Apply a frequency-dependent gain factor for(i=0; ifreq[half * x + i] += gainfactor[i]; + mSpecCache->freq[half * x + i] += gainFactors[i]; } } } - if(gainfactor) - delete[] gainfactor; delete[]buffer; delete[]recalc; delete oldCache; diff --git a/src/WaveClip.h b/src/WaveClip.h index 3c2de5d85..86eeaec07 100644 --- a/src/WaveClip.h +++ b/src/WaveClip.h @@ -29,6 +29,8 @@ #include #include +#include + class Envelope; class WaveCache; class WaveTrackCache; @@ -187,6 +189,11 @@ public: * calculations and Contrast */ bool GetWaveDisplay(WaveDisplay &display, double t0, double pixelsPerSecond, bool &isLoadingOD); + void ComputeSpectrogramGainFactors( + int fftLen, + int frequencyGain, // db/decade + std::vector &gainFactors + ); bool GetSpectrogram(WaveTrackCache &cache, float *buffer, sampleCount *where, int numPixels,