1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-03 17:19:43 +02:00

Merge remote-tracking branch 'upstream-audacity/master' into QuickPlay2

This commit is contained in:
Steve Daulton 2015-04-17 17:58:48 +01:00
commit 30c61f648d

View File

@ -48,11 +48,12 @@ public:
start = -1.0;
pps = 0.0;
len = cacheLen;
min = new float[len];
max = new float[len];
rms = new float[len];
bl = new int[len];
min = len ? new float[len] : 0;
max = len ? new float[len] : 0;
rms = len ? new float[len] : 0;
bl = len ? new int[len] : 0;
where = new sampleCount[len+1];
where[0] = 0;
numODPixels=0;
}
@ -233,8 +234,9 @@ public:
pps = 0.0;
len = cacheLen;
ac = autocorrelation;
freq = new float[len*half];
freq = len ? new float[len*half] : 0;
where = new sampleCount[len+1];
where[0] = 0;
}
~SpecCache()
@ -297,14 +299,14 @@ WaveClip::WaveClip(DirManager *projDirManager, sampleFormat format, int rate)
mRate = rate;
mSequence = new Sequence(projDirManager, format);
mEnvelope = new Envelope();
mWaveCache = new WaveCache(1);
mWaveCache = new WaveCache(0);
#ifdef EXPERIMENTAL_USE_REALFFTF
mWindowType = -1;
mWindowSize = -1;
hFFT = NULL;
mWindow = NULL;
#endif
mSpecCache = new SpecCache(1, 1, false);
mSpecCache = new SpecCache(0, 1, false);
mSpecPxCache = new SpecPxCache(1);
mAppendBuffer = NULL;
mAppendBufferLen = 0;
@ -325,14 +327,14 @@ WaveClip::WaveClip(const WaveClip& orig, DirManager *projDirManager)
mEnvelope->Paste(0.0, orig.mEnvelope);
mEnvelope->SetOffset(orig.GetOffset());
mEnvelope->SetTrackLen(((double)orig.mSequence->GetNumSamples()) / orig.mRate);
mWaveCache = new WaveCache(1);
mWaveCache = new WaveCache(0);
#ifdef EXPERIMENTAL_USE_REALFFTF
mWindowType = -1;
mWindowSize = -1;
hFFT = NULL;
mWindow = NULL;
#endif
mSpecCache = new SpecCache(1, 1, false);
mSpecCache = new SpecCache(0, 1, false);
mSpecPxCache = new SpecPxCache(1);
for (WaveClipList::compatibility_iterator it=orig.mCutLines.GetFirst(); it; it=it->GetNext())
@ -439,7 +441,7 @@ void WaveClip::DeleteWaveCache()
mWaveCacheMutex.Lock();
if(mWaveCache!=NULL)
delete mWaveCache;
mWaveCache = new WaveCache(1);
mWaveCache = new WaveCache(0);
mWaveCacheMutex.Unlock();
}
@ -526,15 +528,43 @@ bool WaveClip::GetWaveDisplay(float *min, float *max, float *rms,int* bl,
mWaveCache->rate = mRate;
mWaveCache->start = t0;
double tstep = 1.0 / pixelsPerSecond;
double samplesPerPixel = mRate * tstep;
sampleCount x;
sampleCount oldWhere0 = 0;
sampleCount denom = 0;
int oldX0 = 0, oldXLast = 0;
double error = 0.0;
if (oldCache->len > 0) {
oldWhere0 = oldCache->where[1] - samplesPerPixel;
const sampleCount oldWhereLast(floor(0.5 +
oldWhere0 + oldCache->len * samplesPerPixel
));
denom = oldWhereLast - oldWhere0;
for (x = 0; x < mWaveCache->len + 1; x++) {
mWaveCache->where[x] =
(sampleCount) floor(t0 * mRate +
((double) x) * mRate * tstep + 0.5);
// Mitigate the accumulation of location errors
// in copies of copies of ... of caches.
if (denom > 0)
{
const double guessWhere0 = t0 * mRate;
oldX0 = floor(0.5 + oldCache->len * (guessWhere0 - oldWhere0) / denom);
const double where0 =
(sampleCount)floor(0.5 + oldWhere0 + double(oldX0) * samplesPerPixel);
error = where0 - guessWhere0; // should be in (-samplesPerPixel, samplesPerPixel)
wxASSERT(-samplesPerPixel <= error && error <= samplesPerPixel);
oldXLast = floor(0.5 + oldCache->len * (
(where0 + double(mWaveCache->len) * samplesPerPixel - oldWhere0)
/ denom
));
}
}
// Be careful to make the first value non-negative
mWaveCache->where[0] = sampleCount(std::max(0.0, floor(0.5 + error + t0 * mRate)));
for (sampleCount x = 1; x < mWaveCache->len + 1; x++)
mWaveCache->where[x] = sampleCount(
floor(0.5 + error + t0 * mRate + double(x) * samplesPerPixel)
);
//mchinen: I think s0 - s1 represents the range of samples that we will need to look up. likewise p0-p1 the number of pixels.
sampleCount s0 = mWaveCache->where[0];
sampleCount s1 = mWaveCache->where[mWaveCache->len];
@ -544,10 +574,11 @@ bool WaveClip::GetWaveDisplay(float *min, float *max, float *rms,int* bl,
// Optimization: if the old cache is good and overlaps
// with the current one, re-use as much of the cache as
// possible
if (oldCache->dirty == mDirty &&
if (denom > 0 &&
oldCache->dirty == mDirty &&
oldCache->pps == pixelsPerSecond &&
oldCache->where[0] < mWaveCache->where[mWaveCache->len] &&
oldCache->where[oldCache->len] > mWaveCache->where[0]) {
oldX0 < oldCache->len &&
oldXLast > oldCache->start) {
//now we are assuming the entire range is covered by the old cache and reducing s1/s0 as we find out otherwise.
s0 = mWaveCache->where[mWaveCache->len]; //mchinen:s0 is the min sample covered up to by the wave cache. will shrink if old doen't overlap
@ -576,23 +607,15 @@ bool WaveClip::GetWaveDisplay(float *min, float *max, float *rms,int* bl,
}
oldCache->ClearInvalidRegions();
for (x = 0; x < mWaveCache->len; x++)
for (sampleCount x = 0; x < mWaveCache->len; x++)
{
//if we hit a cached column, load it up.
const double whereX = t0 * mRate + ((double)x) * samplesPerPixel;
const double oxd = (double(oldCache->len) * (whereX - oldWhere0)) / denom;
int ox = floor(0.5 + oxd);
//below is regular cache access.
if (mWaveCache->where[x] >= oldCache->where[0] &&
mWaveCache->where[x] <= oldCache->where[oldCache->len - 1]) {
//if we hit an invalid region, load it up.
int ox =
int ((double (oldCache->len) *
(mWaveCache->where[x] -
oldCache->where[0])) /(oldCache->where[oldCache->len] -
oldCache->where[0]) + 0.5);
if (ox >= 0 && ox < oldCache->len) {
mWaveCache->min[x] = oldCache->min[ox];
mWaveCache->max[x] = oldCache->max[ox];
mWaveCache->rms[x] = oldCache->rms[ox];
@ -795,22 +818,55 @@ bool WaveClip::GetSpectrogram(float *freq, sampleCount *where,
mSpecCache->pps = pixelsPerSecond;
mSpecCache->start = t0;
sampleCount x;
bool *recalc = new bool[mSpecCache->len + 1];
for (x = 0; x < mSpecCache->len + 1; x++) {
const double tstep = 1.0 / pixelsPerSecond;
const double samplesPerPixel = mRate * tstep;
sampleCount oldWhere0 = 0;
sampleCount denom = 0;
int oldX0 = 0, oldXLast = 0;
double error = 0.0;
if (oldCache->len > 0) {
oldWhere0 = oldCache->where[1] - samplesPerPixel;
const sampleCount oldWhereLast(floor(0.5 +
oldWhere0 + oldCache->len * samplesPerPixel
));
denom = oldWhereLast - oldWhere0;
// Mitigate the accumulation of location errors
// in copies of copies of ... of caches.
if (denom > 0)
{
const double guessWhere0 = t0 * mRate;
oldX0 = floor(0.5 + oldCache->len * (guessWhere0 - oldWhere0) / denom);
const double where0 =
(sampleCount)floor(0.5 + oldWhere0 + double(oldX0) * samplesPerPixel);
error = where0 - guessWhere0; // should be in (-samplesPerPixel, samplesPerPixel)
oldXLast = floor(0.5 + oldCache->len * (
(where0 + double(mWaveCache->len) * samplesPerPixel - oldWhere0)
/ denom
));
}
}
// Be careful to make the first value non-negative
recalc[0] = true;
mSpecCache->where[0] = sampleCount(std::max(0.0, floor(1.0 + error + t0 * mRate)));
for (sampleCount x = 1; x < mSpecCache->len + 1; x++) {
recalc[x] = true;
// purposely offset the display 1/2 bin to the left (as compared
// to waveform display to properly center response of the FFT
mSpecCache->where[x] =
(sampleCount)floor((t0*mRate) + (x*mRate/pixelsPerSecond) + 1.);
sampleCount(floor(1.0 + error + t0 * mRate + double(x) * samplesPerPixel));
}
// Optimization: if the old cache is good and overlaps
// with the current one, re-use as much of the cache as
// possible
if (oldCache->dirty == mDirty &&
if (denom > 0 &&
oldCache->dirty == mDirty &&
oldCache->minFreqOld == minFreq &&
oldCache->maxFreqOld == maxFreq &&
oldCache->rangeOld == range &&
@ -823,27 +879,24 @@ bool WaveClip::GetSpectrogram(float *freq, sampleCount *where,
#endif //EXPERIMENTAL_FFT_SKIP_POINTS
oldCache->pps == pixelsPerSecond &&
oldCache->ac == autocorrelation &&
oldCache->where[0] < mSpecCache->where[mSpecCache->len] &&
oldCache->where[oldCache->len] > mSpecCache->where[0]) {
for (x = 0; x < mSpecCache->len; x++)
if (mSpecCache->where[x] >= oldCache->where[0] &&
mSpecCache->where[x] <= oldCache->where[oldCache->len]) {
int ox = (int) ((double (oldCache->len) *
(mSpecCache->where[x] - oldCache->where[0]))
/ (oldCache->where[oldCache->len] -
oldCache->where[0]) + 0.5);
if (ox >= 0 && ox < oldCache->len &&
mSpecCache->where[x] == oldCache->where[ox]) {
oldX0 < oldCache->len &&
oldXLast > oldCache->start) {
for (sampleCount x = 0; x < mSpecCache->len; x++) {
//if we hit a cached column, load it up.
const double whereX = t0 * mRate + ((double)x) * samplesPerPixel;
const double oxd = (double(oldCache->len) * (whereX - oldWhere0)) / denom;
int ox = floor(0.5 + oxd);
//below is regular cache access.
if (ox >= 0 && ox < oldCache->len) {
if (mSpecCache->where[x] >= oldCache->where[0] &&
mSpecCache->where[x] <= oldCache->where[oldCache->len]) {
for (sampleCount i = 0; i < (sampleCount)half; i++)
mSpecCache->freq[half * x + i] =
oldCache->freq[half * ox + i];
mSpecCache->freq[half * x + i] = oldCache->freq[half * ox + i];
recalc[x] = false;
}
}
}
}
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS
@ -866,12 +919,12 @@ bool WaveClip::GetSpectrogram(float *freq, sampleCount *where,
// scaled such that 1000 Hz gets a gain of 0dB
double factor = 0.001*(double)mRate/(double)windowSize;
gainfactor = new float[half];
for(x = 0; x < half; x++) {
for(sampleCount x = 0; x < half; x++) {
gainfactor[x] = frequencygain*log10(factor * x);
}
}
for (x = 0; x < mSpecCache->len; x++)
for (sampleCount x = 0; x < mSpecCache->len; x++)
if (recalc[x]) {
sampleCount start = mSpecCache->where[x];
@ -1602,11 +1655,11 @@ bool WaveClip::Resample(int rate, ProgressDialog *progress)
delete mWaveCache;
mWaveCache = NULL;
}
mWaveCache = new WaveCache(1);
mWaveCache = new WaveCache(0);
// Invalidate the spectrum display cache
if (mSpecCache)
delete mSpecCache;
mSpecCache = new SpecCache(1, 1, false);
mSpecCache = new SpecCache(0, 1, false);
}
return !error;