1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00

Don't invalidate SpecCache for changes of min, max, gain or range...

... because those do not affect it.  They only affect the SpecPxCache.

Did other things to that class:  renamed fields, new constructors.
This commit is contained in:
Paul Licameli 2015-06-03 23:02:37 -04:00
parent 77a79c727c
commit 38f24a42ef
3 changed files with 118 additions and 83 deletions

View File

@ -2021,6 +2021,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
#endif //EXPERIMENTAL_FFT_Y_GRID #endif //EXPERIMENTAL_FFT_Y_GRID
if (!updated && clip->mSpecPxCache->valid && (clip->mSpecPxCache->len == mid.height * mid.width) if (!updated && clip->mSpecPxCache->valid && (clip->mSpecPxCache->len == mid.height * mid.width)
&& gain == clip->mSpecPxCache->gain
&& range == clip->mSpecPxCache->range
#ifdef EXPERIMENTAL_FFT_Y_GRID #ifdef EXPERIMENTAL_FFT_Y_GRID
&& mFftYGrid==fftYGridOld && mFftYGrid==fftYGridOld
#endif //EXPERIMENTAL_FFT_Y_GRID #endif //EXPERIMENTAL_FFT_Y_GRID
@ -2037,6 +2039,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
delete clip->mSpecPxCache; delete clip->mSpecPxCache;
clip->mSpecPxCache = new SpecPxCache(mid.width * mid.height); clip->mSpecPxCache = new SpecPxCache(mid.width * mid.height);
clip->mSpecPxCache->valid = true; clip->mSpecPxCache->valid = true;
clip->mSpecPxCache->gain = gain;
clip->mSpecPxCache->range = range;
#ifdef EXPERIMENTAL_FIND_NOTES #ifdef EXPERIMENTAL_FIND_NOTES
fftFindNotesOld=mFftFindNotes; fftFindNotesOld=mFftFindNotes;
findNotesMinAOld=mFindNotesMinA; findNotesMinAOld=mFindNotesMinA;

View File

@ -254,26 +254,58 @@ protected:
class SpecCache { class SpecCache {
public: public:
SpecCache(int cacheLen, int half, bool autocorrelation)
{ // Make invalid cache
minFreqOld = -1; SpecCache()
maxFreqOld = -1; : len(-1)
gainOld = -1; , ac(false)
rangeOld = -1; , pps(-1.0)
windowTypeOld = -1; , start(-1.0)
windowSizeOld = -1; , windowType(-1)
zeroPaddingFactorOld = 1; , windowSize(-1)
frequencyGainOld = false; , zeroPaddingFactor(-1)
, frequencyGain(-1)
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS #ifdef EXPERIMENTAL_FFT_SKIP_POINTS
fftSkipPointsOld = -1; , fftSkipPoints(-1);
#endif //EXPERIMENTAL_FFT_SKIP_POINTS #endif //EXPERIMENTAL_FFT_SKIP_POINTS
dirty = -1;
start = -1.0; , freq(NULL)
pps = 0.0; , where(NULL)
len = cacheLen;
ac = autocorrelation; , dirty(-1)
freq = len ? new float[len*half] : 0; {
where = new sampleCount[len+1]; }
// Make valid cache, to be filled in
SpecCache(int cacheLen, bool autocorrelation,
double pps_, double start_, int windowType_, int windowSize_,
int zeroPaddingFactor_, int frequencyGain_
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS
, int fftSkipPoints_
#endif
)
: len(cacheLen)
, ac(autocorrelation)
, pps(pps_)
, start(start_)
, windowType(windowType_)
, windowSize(windowSize_)
, zeroPaddingFactor(zeroPaddingFactor_)
, frequencyGain(frequencyGain_)
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS
, fftSkipPoints(fftSkipPoints_);
#endif //EXPERIMENTAL_FFT_SKIP_POINTS
// len columns, and so many rows, column-major.
// Don't take column literally -- this isn't pixel data yet, it's the
// raw data to be mapped onto the display.
, freq(len ? new float[len * ((windowSize * zeroPaddingFactor) / 2)] : 0)
// Sample counts corresponding to the columns, and to one past the end.
, where(new sampleCount[len + 1])
, dirty(-1)
{
where[0] = 0; where[0] = 0;
} }
@ -283,24 +315,21 @@ public:
delete[] where; delete[] where;
} }
int minFreqOld; const sampleCount len;
int maxFreqOld; const bool ac;
int gainOld; const double pps;
int rangeOld; const double start;
int windowTypeOld; const int windowType;
int windowSizeOld; const int windowSize;
int zeroPaddingFactorOld; const int zeroPaddingFactor;
int frequencyGainOld; const int frequencyGain;
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS #ifdef EXPERIMENTAL_FFT_SKIP_POINTS
int fftSkipPointsOld; const int fftSkipPoints;
#endif //EXPERIMENTAL_FFT_SKIP_POINTS #endif //EXPERIMENTAL_FFT_SKIP_POINTS
float *const freq;
sampleCount *const where;
int dirty; int dirty;
bool ac;
sampleCount len;
double start;
double pps;
sampleCount *where;
float *freq;
}; };
#ifdef EXPERIMENTAL_USE_REALFFTF #ifdef EXPERIMENTAL_USE_REALFFTF
@ -347,7 +376,7 @@ WaveClip::WaveClip(DirManager *projDirManager, sampleFormat format, int rate)
mWindow = NULL; mWindow = NULL;
#endif #endif
mZeroPaddingFactor = 1; mZeroPaddingFactor = 1;
mSpecCache = new SpecCache(0, 1, false); mSpecCache = new SpecCache();
mSpecPxCache = new SpecPxCache(1); mSpecPxCache = new SpecPxCache(1);
mAppendBuffer = NULL; mAppendBuffer = NULL;
mAppendBufferLen = 0; mAppendBufferLen = 0;
@ -376,7 +405,7 @@ WaveClip::WaveClip(const WaveClip& orig, DirManager *projDirManager)
mWindow = NULL; mWindow = NULL;
#endif #endif
mZeroPaddingFactor = 1; mZeroPaddingFactor = 1;
mSpecCache = new SpecCache(0, 1, false); mSpecCache = new SpecCache();
mSpecPxCache = new SpecPxCache(1); mSpecPxCache = new SpecPxCache(1);
for (WaveClipList::compatibility_iterator it=orig.mCutLines.GetFirst(); it; it=it->GetNext()) for (WaveClipList::compatibility_iterator it=orig.mCutLines.GetFirst(); it; it=it->GetNext())
@ -499,7 +528,8 @@ namespace {
inline inline
void findCorrection(const sampleCount oldWhere[], int oldLen, int newLen, void findCorrection(const sampleCount oldWhere[], int oldLen, int newLen,
double t0, double rate, double samplesPerPixel, double t0, double rate, double samplesPerPixel,
double &oldWhere0, double &denom, long &oldX0, long &oldXLast, double &correction) double &oldWhere0, double &denom, long &oldX0, long &oldXLast, double &correction,
bool &overlap)
{ {
// Mitigate the accumulation of location errors // Mitigate the accumulation of location errors
// in copies of copies of ... of caches. // in copies of copies of ... of caches.
@ -533,6 +563,7 @@ void findCorrection(const sampleCount oldWhere[], int oldLen, int newLen,
denom < 0.5) denom < 0.5)
{ {
correction = 0.0; correction = 0.0;
overlap = false;
} }
else else
{ {
@ -540,6 +571,7 @@ void findCorrection(const sampleCount oldWhere[], int oldLen, int newLen,
const double correction0 = where0 - guessWhere0; const double correction0 = where0 - guessWhere0;
correction = std::max(-samplesPerPixel, std::min(samplesPerPixel, correction0)); correction = std::max(-samplesPerPixel, std::min(samplesPerPixel, correction0));
wxASSERT(correction == correction0); wxASSERT(correction == correction0);
overlap = true;
} }
} }
@ -598,26 +630,32 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
return true; return true;
} }
WaveCache *oldCache = mWaveCache; std::auto_ptr<WaveCache> oldCache(mWaveCache);
mWaveCache = 0;
mWaveCache = new WaveCache(numPixels);
mWaveCache->pps = pixelsPerSecond;
mWaveCache->rate = mRate;
mWaveCache->start = t0;
double tstep = 1.0 / pixelsPerSecond;
double samplesPerPixel = mRate * tstep;
double oldWhere0 = 0; double oldWhere0 = 0;
double denom = 0; double denom = 0;
long oldX0 = 0, oldXLast = 0; long oldX0 = 0, oldXLast = 0;
double correction = 0.0; double correction = 0.0;
bool overlap = false;
const double tstep = 1.0 / pixelsPerSecond;
const double samplesPerPixel = mRate * tstep;
if (match && if (match &&
oldCache->len > 0) { oldCache->len > 0) {
findCorrection(oldCache->where, oldCache->len, mWaveCache->len, findCorrection(oldCache->where, oldCache->len, numPixels,
t0, mRate, samplesPerPixel, t0, mRate, samplesPerPixel,
oldWhere0, denom, oldX0, oldXLast, correction); oldWhere0, denom, oldX0, oldXLast, correction, overlap);
} }
if (!overlap)
oldCache.reset(0);
mWaveCache = new WaveCache(numPixels);
mWaveCache->pps = pixelsPerSecond;
mWaveCache->rate = mRate;
mWaveCache->start = t0;
fillWhere(mWaveCache->where, mWaveCache->len, 0.0, correction, fillWhere(mWaveCache->where, mWaveCache->len, 0.0, correction,
t0, mRate, samplesPerPixel); t0, mRate, samplesPerPixel);
@ -630,7 +668,7 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
// Optimization: if the old cache is good and overlaps // Optimization: if the old cache is good and overlaps
// with the current one, re-use as much of the cache as // with the current one, re-use as much of the cache as
// possible // possible
if (match && if (match && overlap &&
denom >= 0.5 && denom >= 0.5 &&
oldX0 < oldCache->len && oldX0 < oldCache->len &&
oldXLast > oldCache->start) { oldXLast > oldCache->start) {
@ -763,7 +801,6 @@ bool WaveClip::GetWaveDisplay(WaveDisplay &display, double t0,
} }
mWaveCache->dirty = mDirty; mWaveCache->dirty = mDirty;
delete oldCache;
memcpy(min, mWaveCache->min, numPixels*sizeof(float)); memcpy(min, mWaveCache->min, numPixels*sizeof(float));
memcpy(max, mWaveCache->max, numPixels*sizeof(float)); memcpy(max, mWaveCache->max, numPixels*sizeof(float));
@ -867,10 +904,6 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
double t0, double pixelsPerSecond, double t0, double pixelsPerSecond,
bool autocorrelation) bool autocorrelation)
{ {
int minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), 0L);
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 windowType;
int windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); int windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256);
@ -909,16 +942,12 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
const bool match = const bool match =
mSpecCache && mSpecCache &&
mSpecCache->dirty == mDirty && mSpecCache->dirty == mDirty &&
mSpecCache->minFreqOld == minFreq && mSpecCache->windowType == windowType &&
mSpecCache->maxFreqOld == maxFreq && mSpecCache->windowSize == windowSize &&
mSpecCache->rangeOld == range && mSpecCache->zeroPaddingFactor == zeroPaddingFactor &&
mSpecCache->gainOld == gain && mSpecCache->frequencyGain == frequencyGain &&
mSpecCache->windowTypeOld == windowType &&
mSpecCache->windowSizeOld == windowSize &&
mSpecCache->zeroPaddingFactorOld == zeroPaddingFactor &&
mSpecCache->frequencyGainOld == frequencyGain &&
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS #ifdef EXPERIMENTAL_FFT_SKIP_POINTS
mSpecCache->fftSkipPointsOld == fftSkipPoints && mSpecCache->fftSkipPoints == fftSkipPoints &&
#endif //EXPERIMENTAL_FFT_SKIP_POINTS #endif //EXPERIMENTAL_FFT_SKIP_POINTS
mSpecCache->ac == autocorrelation && mSpecCache->ac == autocorrelation &&
mSpecCache->pps == pixelsPerSecond; mSpecCache->pps == pixelsPerSecond;
@ -931,14 +960,11 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
return false; //hit cache completely return false; //hit cache completely
} }
SpecCache *oldCache = mSpecCache; std::auto_ptr<SpecCache> oldCache(mSpecCache);
mSpecCache = 0;
mSpecCache = new SpecCache(numPixels, half, autocorrelation); bool *recalc = new bool[numPixels + 1];
mSpecCache->pps = pixelsPerSecond; std::fill(&recalc[0], &recalc[numPixels + 1], true);
mSpecCache->start = t0;
bool *recalc = new bool[mSpecCache->len + 1];
std::fill(&recalc[0], &recalc[mSpecCache->len + 1], true);
const double tstep = 1.0 / pixelsPerSecond; const double tstep = 1.0 / pixelsPerSecond;
const double samplesPerPixel = mRate * tstep; const double samplesPerPixel = mRate * tstep;
@ -949,21 +975,33 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
double denom = 0; double denom = 0;
long oldX0 = 0, oldXLast = 0; long oldX0 = 0, oldXLast = 0;
double correction = 0.0; double correction = 0.0;
bool overlap = false;
if (match && if (match &&
oldCache->len > 0) { oldCache->len > 0) {
findCorrection(oldCache->where, oldCache->len, mSpecCache->len, findCorrection(oldCache->where, oldCache->len, numPixels,
t0, mRate, samplesPerPixel, t0, mRate, samplesPerPixel,
oldWhere0, denom, oldX0, oldXLast, correction); oldWhere0, denom, oldX0, oldXLast, correction, overlap);
} }
if (!overlap)
oldCache.reset(0);
mSpecCache = new SpecCache(
numPixels, autocorrelation, pixelsPerSecond, t0,
windowType, windowSize, zeroPaddingFactor, frequencyGain
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS
, fftSkipPoints
#endif
);
fillWhere(mSpecCache->where, mSpecCache->len, 0.5, correction, fillWhere(mSpecCache->where, mSpecCache->len, 0.5, correction,
t0, mRate, samplesPerPixel); t0, mRate, samplesPerPixel);
// Optimization: if the old cache is good and overlaps // Optimization: if the old cache is good and overlaps
// with the current one, re-use as much of the cache as // with the current one, re-use as much of the cache as
// possible // possible
if (match && if (match && overlap &&
denom >= 0.5 && denom >= 0.5 &&
oldX0 < oldCache->len && oldX0 < oldCache->len &&
oldXLast > oldCache->start) { oldXLast > oldCache->start) {
@ -988,7 +1026,6 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
float *useBuffer = 0; float *useBuffer = 0;
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS #ifdef EXPERIMENTAL_FFT_SKIP_POINTS
float *buffer = new float[fftLen*fftSkipPoints1]; float *buffer = new float[fftLen*fftSkipPoints1];
mSpecCache->fftSkipPointsOld = fftSkipPoints;
#else //!EXPERIMENTAL_FFT_SKIP_POINTS #else //!EXPERIMENTAL_FFT_SKIP_POINTS
float *buffer = new float[fftLen]; float *buffer = new float[fftLen];
#endif //EXPERIMENTAL_FFT_SKIP_POINTS #endif //EXPERIMENTAL_FFT_SKIP_POINTS
@ -998,15 +1035,6 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
buffer[fftLen - ii - 1] = 0.0; buffer[fftLen - ii - 1] = 0.0;
} }
mSpecCache->minFreqOld = minFreq;
mSpecCache->maxFreqOld = maxFreq;
mSpecCache->gainOld = gain;
mSpecCache->rangeOld = range;
mSpecCache->windowTypeOld = windowType;
mSpecCache->windowSizeOld = windowSize;
mSpecCache->zeroPaddingFactorOld = zeroPaddingFactor;
mSpecCache->frequencyGainOld = frequencyGain;
std::vector<float> gainFactors; std::vector<float> gainFactors;
ComputeSpectrogramGainFactors(fftLen, frequencyGain, gainFactors); ComputeSpectrogramGainFactors(fftLen, frequencyGain, gainFactors);
@ -1101,7 +1129,6 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
delete[]buffer; delete[]buffer;
delete[]recalc; delete[]recalc;
delete oldCache;
mSpecCache->dirty = mDirty; mSpecCache->dirty = mDirty;
memcpy(freq, mSpecCache->freq, numPixels*half*sizeof(float)); memcpy(freq, mSpecCache->freq, numPixels*half*sizeof(float));
@ -1759,7 +1786,7 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
// Invalidate the spectrum display cache // Invalidate the spectrum display cache
if (mSpecCache) if (mSpecCache)
delete mSpecCache; delete mSpecCache;
mSpecCache = new SpecCache(0, 1, false); mSpecCache = new SpecCache();
} }
return !error; return !error;

View File

@ -43,6 +43,7 @@ public:
len = cacheLen; len = cacheLen;
values = new float[len]; values = new float[len];
valid = false; valid = false;
range = gain = -1;
} }
~SpecPxCache() ~SpecPxCache()
@ -53,6 +54,9 @@ public:
sampleCount len; sampleCount len;
float *values; float *values;
bool valid; bool valid;
int range;
int gain;
}; };
class WaveClip; class WaveClip;