1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-15 23:59:37 +02:00

Keep FFT windows for Spectrograms in one place in SpectrogramSettings...

... not redundantly in each WaveClip.
This commit is contained in:
Paul Licameli 2015-06-04 10:40:21 -04:00
parent 952a22c8b1
commit afa2fe9fb4
5 changed files with 144 additions and 115 deletions

View File

@ -2,15 +2,15 @@
#define __realfftf_h
#define fft_type float
typedef struct FFTParamType {
struct FFTParam {
int *BitReversed;
fft_type *SinTable;
int Points;
#ifdef EXPERIMENTAL_EQ_SSE_THREADED
int pow2Bits;
#endif
} FFTParam;
#define HFFT FFTParam *
};
typedef FFTParam * HFFT;
HFFT InitializeFFT(int);
void EndFFT(HFFT);

View File

@ -336,7 +336,7 @@ public:
#ifdef EXPERIMENTAL_USE_REALFFTF
#include "FFT.h"
static void ComputeSpectrumUsingRealFFTf(float *buffer, HFFT hFFT, float *window, int len, float *out)
static void ComputeSpectrumUsingRealFFTf(float *buffer, HFFT hFFT, const float *window, int len, float *out)
{
int i;
if(len > hFFT->Points*2)
@ -371,13 +371,6 @@ WaveClip::WaveClip(DirManager *projDirManager, sampleFormat format, int rate)
mSequence = new Sequence(projDirManager, format);
mEnvelope = new Envelope();
mWaveCache = new WaveCache(0);
#ifdef EXPERIMENTAL_USE_REALFFTF
mWindowType = -1;
mWindowSize = -1;
hFFT = NULL;
mWindow = NULL;
#endif
mZeroPaddingFactor = 1;
mSpecCache = new SpecCache();
mSpecPxCache = new SpecPxCache(1);
mAppendBuffer = NULL;
@ -400,13 +393,6 @@ WaveClip::WaveClip(const WaveClip& orig, DirManager *projDirManager)
mEnvelope->SetOffset(orig.GetOffset());
mEnvelope->SetTrackLen(((double)orig.mSequence->GetNumSamples()) / orig.mRate);
mWaveCache = new WaveCache(0);
#ifdef EXPERIMENTAL_USE_REALFFTF
mWindowType = -1;
mWindowSize = -1;
hFFT = NULL;
mWindow = NULL;
#endif
mZeroPaddingFactor = 1;
mSpecCache = new SpecCache();
mSpecPxCache = new SpecPxCache(1);
@ -429,12 +415,6 @@ WaveClip::~WaveClip()
delete mWaveCache;
delete mSpecCache;
delete mSpecPxCache;
#ifdef EXPERIMENTAL_USE_REALFFTF
if(hFFT != NULL)
EndFFT(hFFT);
if(mWindow != NULL)
delete[] mWindow;
#endif
if (mAppendBuffer)
DeleteSamples(mAppendBuffer);
@ -820,67 +800,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
return true;
}
namespace
{
enum { WINDOW, TWINDOW, DWINDOW };
void RecreateWindow(
float *&window, int which, int fftLen,
int padding, int windowType, int windowSize, double &scale)
{
if (window != NULL)
delete[] window;
// Create the requested window function
window = new float[fftLen];
int ii;
wxASSERT(windowSize % 2 == 0);
const int endOfWindow = padding + windowSize;
// Left and right padding
for (ii = 0; ii < padding; ++ii) {
window[ii] = 0.0;
window[fftLen - ii - 1] = 0.0;
}
// Default rectangular window in the middle
for (; ii < endOfWindow; ++ii)
window[ii] = 1.0;
// Overwrite middle as needed
switch (which) {
case WINDOW:
WindowFunc(windowType, windowSize, window + padding);
// NewWindowFunc(windowType, windowSize, extra, window + padding);
break;
case TWINDOW:
wxASSERT(false);
#if 0
// Future, reassignment
NewWindowFunc(windowType, windowSize, extra, window + padding);
for (int ii = padding, multiplier = -windowSize / 2; ii < endOfWindow; ++ii, ++multiplier)
window[ii] *= multiplier;
break;
#endif
case DWINDOW:
wxASSERT(false);
#if 0
// Future, reassignment
DerivativeOfWindowFunc(windowType, windowSize, extra, window + padding);
break;
#endif
default:
wxASSERT(false);
}
// Scale the window function to give 0dB spectrum for 0dB sine tone
if (which == WINDOW) {
scale = 0.0;
for (ii = padding; ii < endOfWindow; ++ii)
scale += window[ii];
if (scale > 0)
scale = 2.0 / scale;
}
for (ii = padding; ii < endOfWindow; ++ii)
window[ii] *= scale;
}
}
void WaveClip::ComputeSpectrogramGainFactors(int fftLen, int frequencyGain, std::vector<float> &gainFactors)
{
if (frequencyGain > 0) {
@ -921,6 +840,11 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
#else
const int zeroPaddingFactor = 1;
#endif
#ifdef EXPERIMENTAL_USE_REALFFTF
settings.CacheWindows();
const HFFT &hFFT = settings.hFFT;
const float *const &window = settings.window;
#endif
// FFT length may be longer than the window of samples that affect results
// because of zero padding done for increased frequency resolution
@ -928,24 +852,6 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
const int half = fftLen / 2;
const int padding = (windowSize * (zeroPaddingFactor - 1)) / 2;
#ifdef EXPERIMENTAL_USE_REALFFTF
// Update the FFT and window if necessary
if((mWindowType != windowType) || (mWindowSize != windowSize)
|| (hFFT == NULL) || (mWindow == NULL) || (fftLen != hFFT->Points * 2)
|| (mZeroPaddingFactor != zeroPaddingFactor)) {
mWindowType = windowType;
mWindowSize = windowSize;
if(hFFT != NULL)
EndFFT(hFFT);
hFFT = InitializeFFT(fftLen);
double scale;
RecreateWindow(mWindow, WINDOW, fftLen, padding, mWindowType, mWindowSize, scale);
}
#endif // EXPERIMENTAL_USE_REALFFTF
mZeroPaddingFactor = zeroPaddingFactor;
const bool match =
mSpecCache &&
mSpecCache->dirty == mDirty &&
@ -1119,7 +1025,7 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
mRate, &mSpecCache->freq[half * x],
autocorrelation, windowType);
} else {
ComputeSpectrumUsingRealFFTf(useBuffer, hFFT, mWindow, fftLen, &mSpecCache->freq[half * x]);
ComputeSpectrumUsingRealFFTf(useBuffer, hFFT, window, fftLen, &mSpecCache->freq[half * x]);
}
#else // EXPERIMENTAL_USE_REALFFTF
ComputeSpectrum(buffer, windowSize, windowSize,

View File

@ -307,14 +307,6 @@ protected:
WaveCache *mWaveCache;
ODLock mWaveCacheMutex;
SpecCache *mSpecCache;
#ifdef EXPERIMENTAL_USE_REALFFTF
// Variables used for computing the spectrum
HFFT hFFT;
float *mWindow;
int mWindowType;
int mWindowSize;
#endif
int mZeroPaddingFactor;
samplePtr mAppendBuffer;
sampleCount mAppendBufferLen;

View File

@ -370,6 +370,8 @@ BEGIN_EVENT_TABLE(SpectrumPrefs, PrefsPanel)
END_EVENT_TABLE()
SpectrogramSettings::SpectrogramSettings()
: hFFT(0)
, window(0)
{
UpdatePrefs();
}
@ -382,6 +384,8 @@ SpectrogramSettings& SpectrogramSettings::defaults()
void SpectrogramSettings::UpdatePrefs()
{
bool destroy = false;
minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), -1L);
maxFreq = gPrefs->Read(wxT("/Spectrum/MaxFreq"), 8000L);
@ -401,13 +405,26 @@ void SpectrogramSettings::UpdatePrefs()
gain = gPrefs->Read(wxT("/Spectrum/Gain"), 20L);
frequencyGain = gPrefs->Read(wxT("/Spectrum/FrequencyGain"), 0L);
windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256);
const int newWindowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256);
if (newWindowSize != windowSize) {
destroy = true;
windowSize = newWindowSize;
}
#ifdef EXPERIMENTAL_ZERO_PADDED_SPECTROGRAMS
zeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1);
const int newZeroPaddingFactor = gPrefs->Read(wxT("/Spectrum/ZeroPaddingFactor"), 1);
if (newZeroPaddingFactor != zeroPaddingFactor) {
destroy = true;
zeroPaddingFactor = newZeroPaddingFactor;
}
#endif
gPrefs->Read(wxT("/Spectrum/WindowType"), &windowType, 3);
int newWindowType;
gPrefs->Read(wxT("/Spectrum/WindowType"), &newWindowType, 3);
if (newWindowType != windowType) {
destroy = true;
windowType = newWindowType;
}
isGrayscale = (gPrefs->Read(wxT("/Spectrum/Grayscale"), 0L) != 0);
@ -425,4 +442,105 @@ void SpectrogramSettings::UpdatePrefs()
numberOfMaxima = gPrefs->Read(wxT("/Spectrum/FindNotesN"), 5L);
findNotesQuantize = (gPrefs->Read(wxT("/Spectrum/FindNotesQuantize"), 0L) != 0);
#endif //EXPERIMENTAL_FIND_NOTES
if (destroy)
DestroyWindows();
}
SpectrogramSettings::~SpectrogramSettings()
{
DestroyWindows();
}
void SpectrogramSettings::DestroyWindows()
{
#ifdef EXPERIMENTAL_USE_REALFFTF
if (hFFT != NULL) {
EndFFT(hFFT);
hFFT = NULL;
}
if (window != NULL) {
delete[] window;
window = NULL;
}
#endif
}
namespace
{
enum { WINDOW, TWINDOW, DWINDOW };
void RecreateWindow(
float *&window, int which, int fftLen,
int padding, int windowType, int windowSize, double &scale)
{
if (window != NULL)
delete[] window;
// Create the requested window function
window = new float[fftLen];
int ii;
wxASSERT(windowSize % 2 == 0);
const int endOfWindow = padding + windowSize;
// Left and right padding
for (ii = 0; ii < padding; ++ii) {
window[ii] = 0.0;
window[fftLen - ii - 1] = 0.0;
}
// Default rectangular window in the middle
for (; ii < endOfWindow; ++ii)
window[ii] = 1.0;
// Overwrite middle as needed
switch (which) {
case WINDOW:
WindowFunc(windowType, windowSize, window + padding);
// NewWindowFunc(windowType, windowSize, extra, window + padding);
break;
case TWINDOW:
wxASSERT(false);
#if 0
// Future, reassignment
NewWindowFunc(windowType, windowSize, extra, window + padding);
for (int ii = padding, multiplier = -windowSize / 2; ii < endOfWindow; ++ii, ++multiplier)
window[ii] *= multiplier;
break;
#endif
case DWINDOW:
wxASSERT(false);
#if 0
// Future, reassignment
DerivativeOfWindowFunc(windowType, windowSize, extra, window + padding);
break;
#endif
default:
wxASSERT(false);
}
// Scale the window function to give 0dB spectrum for 0dB sine tone
if (which == WINDOW) {
scale = 0.0;
for (ii = padding; ii < endOfWindow; ++ii)
scale += window[ii];
if (scale > 0)
scale = 2.0 / scale;
}
for (ii = padding; ii < endOfWindow; ++ii)
window[ii] *= scale;
}
}
void SpectrogramSettings::CacheWindows() const
{
#ifdef EXPERIMENTAL_USE_REALFFTF
if (hFFT == NULL || window == NULL) {
double scale;
const int fftLen = windowSize * zeroPaddingFactor;
const int padding = (windowSize * (zeroPaddingFactor - 1)) / 2;
if (hFFT != NULL)
EndFFT(hFFT);
hFFT = InitializeFFT(fftLen);
RecreateWindow(window, WINDOW, fftLen, padding, windowType, windowSize, scale);
}
#endif // EXPERIMENTAL_USE_REALFFTF
}

View File

@ -30,6 +30,8 @@
#include "PrefsPanel.h"
struct FFTParam;
class SpectrumPrefs:public PrefsPanel
{
public:
@ -76,8 +78,11 @@ struct SpectrogramSettings
{
static SpectrogramSettings &defaults();
SpectrogramSettings();
~SpectrogramSettings();
void UpdatePrefs();
void DestroyWindows();
void CacheWindows() const;
int minFreq;
int maxFreq;
@ -111,6 +116,14 @@ struct SpectrogramSettings
bool numberOfMaxima;
bool findNotesQuantize;
#endif //EXPERIMENTAL_FIND_NOTES
// Following fields are derived from preferences.
#ifdef EXPERIMENTAL_USE_REALFFTF
// Variables used for computing the spectrum
mutable FFTParam *hFFT;
mutable float *window;
#endif
};
#endif