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:
parent
952a22c8b1
commit
afa2fe9fb4
@ -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);
|
||||
|
108
src/WaveClip.cpp
108
src/WaveClip.cpp
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user