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:
commit
30c61f648d
167
src/WaveClip.cpp
167
src/WaveClip.cpp
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user