1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-18 17:10:55 +02:00

Split apart the loops that update the spectrogram cache and that use it

This commit is contained in:
unknown 2015-06-01 16:27:42 -04:00
parent ee600ce30b
commit ecb97e9c58

View File

@ -1822,24 +1822,22 @@ void TrackArtist::DrawSpectrum(WaveTrack *track,
}
}
inline
static float sumFreqValues(
const float *freq, int x, int half, float bin0, float bin1,
bool autocorrelation, int range, int gain)
static inline float findValue
(float *spectrum, float bin0, float bin1, int half,
bool autocorrelation, int gain, int range)
{
const int x0 = x * half;
float value;
#if 0
// Averaging method
if (int(bin1) == int(bin0)) {
value = freq[x0+int(bin0)];
value = spectrum[int(bin0)];
} else {
float binwidth= bin1 - bin0;
value = freq[x0 + int(bin0)] * (1.f - bin0 + (int)bin0);
value = spectrum[int(bin0)] * (1.f - bin0 + (int)bin0);
bin0 = 1 + int (bin0);
while (bin0 < int(bin1)) {
value += freq[x0 + int(bin0)];
value += spectrum[int(bin0)];
bin0 += 1.0;
}
// Do not reference past end of freq array.
@ -1847,17 +1845,18 @@ static float sumFreqValues(
bin1 -= 1.0;
}
value += freq[x0 + int(bin1)] * (bin1 - int(bin1));
value += spectrum[int(bin1)] * (bin1 - int(bin1));
value /= binwidth;
}
#else
half;
// Maximum method, and no apportionment of any single bins over multiple pixel rows
// See Bug971
int bin = floor(0.5 + bin0);
const int limitBin = floor(0.5 + bin1);
value = freq[x0 + bin];
value = spectrum[bin];
while (++bin < limitBin)
value = std::max(value, freq[x0 + bin]);
value = std::max(value, spectrum[bin]);
#endif
if (!autocorrelation) {
// Last step converts dB to a 0.0-1.0 range
@ -1952,6 +1951,12 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
bool updated = clip->GetSpectrogram(cache, freq, where, mid.width,
t0, pps, autocorrelation);
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS
int fftSkipPoints = gPrefs->Read(wxT("/Spectrum/FFTSkipPoints"), 0L);
int fftSkipPoints1 = fftSkipPoints + 1;
#endif //EXPERIMENTAL_FFT_SKIP_POINTS
int ifreq = lrint(rate/2);
int maxFreq;
@ -1975,67 +1980,21 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
minFreq = 1.0;
}
bool usePxCache = false;
if( !updated && clip->mSpecPxCache->valid && (clip->mSpecPxCache->len == mid.height * mid.width)
#ifdef EXPERIMENTAL_FFT_Y_GRID
&& mFftYGrid==fftYGridOld
#endif //EXPERIMENTAL_FFT_Y_GRID
#ifdef EXPERIMENTAL_FIND_NOTES
&& mFftFindNotes==fftFindNotesOld
&& mFindNotesMinA==findNotesMinAOld
&& mNumberOfMaxima==findNotesNOld
&& mFindNotesQuantize==findNotesQuantizeOld
#endif
) {
usePxCache = true;
}
else {
delete clip->mSpecPxCache;
clip->mSpecPxCache = new SpecPxCache(mid.width * mid.height);
usePxCache = false;
clip->mSpecPxCache->valid = true;
#ifdef EXPERIMENTAL_FIND_NOTES
fftFindNotesOld=mFftFindNotes;
findNotesMinAOld=mFindNotesMinA;
findNotesNOld=mNumberOfMaxima;
findNotesQuantizeOld=mFindNotesQuantize;
#endif
}
// PRL: Must the following two be integers?
int minSamples = int((double)minFreq * (double)windowSize / rate + 0.5); // units are fft bins
int maxSamples = int((double)maxFreq * (double)windowSize / rate + 0.5);
float binPerPx = float(maxSamples - minSamples) / float(mid.height);
float selBinLo = freqLo * (double)windowSize / rate;
float selBinHi = freqHi * (double)windowSize / rate;
float selBinCenter =
((freqLo < 0 || freqHi < 0) ? -1 : sqrt(freqLo * freqHi))
* (double)windowSize / rate;
int x = 0;
sampleCount w1 = (sampleCount) ((t0*rate + x *rate *tstep) + .5);
const float
// e=exp(1.0f),
f = rate / 2.0f / half,
lmin = logf(float(minFreq)),
lmax = logf(float(maxFreq)),
#ifdef EXPERIMENTAL_FIND_NOTES
log2=logf(2.0f),
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS
lmins=logf(float(minFreq)/(mFftSkipPoints+1)),
lmaxs=logf(float(maxFreq)/(mFftSkipPoints+1)),
#else //!EXPERIMENTAL_FFT_SKIP_POINTS
lmins=lmin,
lmaxs=lmax,
#endif //EXPERIMENTAL_FFT_SKIP_POINTS
#endif //EXPERIMENTAL_FIND_NOTES
scale=lmax-lmin /*,
expo=exp(scale)*/ ;
scale = lmax - lmin;
#ifdef EXPERIMENTAL_FFT_Y_GRID
const float
log2 = logf(2.0f),
scale2 = (lmax - lmin) / log2,
lmin2 = lmin / log2;
@ -2055,6 +2014,42 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
}
#endif //EXPERIMENTAL_FFT_Y_GRID
if (!updated && clip->mSpecPxCache->valid && (clip->mSpecPxCache->len == mid.height * mid.width)
#ifdef EXPERIMENTAL_FFT_Y_GRID
&& mFftYGrid==fftYGridOld
#endif //EXPERIMENTAL_FFT_Y_GRID
#ifdef EXPERIMENTAL_FIND_NOTES
&& mFftFindNotes==fftFindNotesOld
&& mFindNotesMinA==findNotesMinAOld
&& mNumberOfMaxima==findNotesNOld
&& mFindNotesQuantize==findNotesQuantizeOld
#endif
) {
// cache is up to date
}
else {
delete clip->mSpecPxCache;
clip->mSpecPxCache = new SpecPxCache(mid.width * mid.height);
clip->mSpecPxCache->valid = true;
#ifdef EXPERIMENTAL_FIND_NOTES
fftFindNotesOld=mFftFindNotes;
findNotesMinAOld=mFindNotesMinA;
findNotesNOld=mNumberOfMaxima;
findNotesQuantizeOld=mFindNotesQuantize;
#endif
#ifdef EXPERIMENTAL_FIND_NOTES
const float
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS
lmins = logf(float(minFreq) / (mFftSkipPoints + 1)),
lmaxs = logf(float(maxFreq) / (mFftSkipPoints + 1)),
#else //!EXPERIMENTAL_FFT_SKIP_POINTS
lmins = lmin,
lmaxs = lmax,
#endif //EXPERIMENTAL_FFT_SKIP_POINTS
;
#endif //EXPERIMENTAL_FIND_NOTES
#ifdef EXPERIMENTAL_FIND_NOTES
int maxima[128];
float maxima0[128], maxima1[128];
@ -2073,58 +2068,18 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
int *indexes = new int[maxTableSize];
#endif //EXPERIMENTAL_FIND_NOTES
while (x < mid.width)
{
sampleCount w0 = w1;
w1 = (sampleCount) ((t0*rate + (x+1) *rate *tstep) + .5);
// TODO: The logF and non-logF case are very similar.
// They should be merged and simplified.
if (!logF)
for (int x = 0; x < mid.width; ++x)
{
if (!logF) {
for (int yy = 0; yy < mid.height; yy++) {
float bin0 = float(yy) * binPerPx + minSamples;
float bin1 = float(yy + 1) * binPerPx + minSamples;
// For spectral selection, determine what colour
// set to use. We use a darker selection if
// in both spectral range and time range.
AColor::ColorGradientChoice selected =
AColor::ColorGradientUnselected;
// If we are in the time selected range, then we may use a different color set.
if (ssel0 <= w0 && w1 < ssel1)
{
bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) ||
(track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay));
selected = ChooseColorSet( bin0, bin1, selBinLo, selBinCenter, selBinHi, x/DASH_LENGTH, isSpectral );
}
unsigned char rv, gv, bv;
float value;
if(!usePxCache) {
value = sumFreqValues(freq, x, half, bin0, bin1,
autocorrelation, range, gain);
const float value = findValue
(freq + half * x, bin0, bin1, half, autocorrelation, gain, range);
clip->mSpecPxCache->values[x * mid.height + yy] = value;
}
else
value = clip->mSpecPxCache->values[x * mid.height + yy];
GetColorGradient(value, selected, mIsGrayscale, &rv, &gv, &bv);
int px = ((mid.height - 1 - yy) * mid.width + x) * 3;
data[px++] = rv;
data[px++] = gv;
data[px] = bv;
}
}
else //logF
{
unsigned char rv, gv, bv;
float value;
else {
#ifdef EXPERIMENTAL_FIND_NOTES
int maximas=0;
if (!usePxCache && mFftFindNotes) {
@ -2184,6 +2139,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
}
}
int it=0;
int oldBin0=-1;
bool inMaximum = false;
#endif //EXPERIMENTAL_FIND_NOTES
@ -2203,18 +2159,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
if (yy3<0)
yy3=0;
float bin1 = float(yy3);
AColor::ColorGradientChoice selected =
AColor::ColorGradientUnselected;
// If we are in the time selected range, then we may use a different color set.
if (ssel0 <= w0 && w1 < ssel1)
{
bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) ||
(track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay));
selected = ChooseColorSet( bin0, bin1, selBinLo, selBinCenter, selBinHi, x/DASH_LENGTH, isSpectral );
}
if(!usePxCache) {
float value;
#ifdef EXPERIMENTAL_FIND_NOTES
if (mFftFindNotes) {
@ -2243,14 +2188,101 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
value = minColor;
} else
#endif //EXPERIMENTAL_FIND_NOTES
value=sumFreqValues(freq, x, half, bin0, bin1,
autocorrelation, range, gain);
clip->mSpecPxCache->values[x * mid.height + yy] = value;
{
value = findValue
(freq + half * x, bin0, bin1, half, autocorrelation, gain, range);
}
else
value = clip->mSpecPxCache->values[x * mid.height + yy];
clip->mSpecPxCache->values[x * mid.height + yy] = value;
yy2 = yy2_base;
} // each y
} // is logF
} // each x
} // updating cache
float selBinLo = freqLo * (double)windowSize / rate;
float selBinHi = freqHi * (double)windowSize / rate;
float selBinCenter =
((freqLo < 0 || freqHi < 0) ? -1 : sqrt(freqLo * freqHi))
* (double)windowSize / rate;
sampleCount w1 = sampleCount(0.5 + rate *
t0
);
for (int x = 0; x < mid.width; ++x)
{
sampleCount w0 = w1;
w1 = sampleCount(0.5 + rate *
(t0 + (x+1) * tstep)
);
// TODO: The logF and non-logF case are very similar.
// They should be merged and simplified.
if (!logF)
{
for (int yy = 0; yy < mid.height; yy++) {
float bin0 = float (yy) * binPerPx + minSamples;
float bin1 = float (yy + 1) * binPerPx + minSamples;
// For spectral selection, determine what colour
// set to use. We use a darker selection if
// in both spectral range and time range.
AColor::ColorGradientChoice selected =
AColor::ColorGradientUnselected;
// If we are in the time selected range, then we may use a different color set.
if (ssel0 <= w0 && w1 < ssel1)
{
bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) ||
(track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay));
selected = ChooseColorSet( bin0, bin1, selBinLo, selBinCenter, selBinHi, x/DASH_LENGTH, isSpectral );
}
unsigned char rv, gv, bv;
const float value =
clip->mSpecPxCache->values[x * mid.height + yy];
GetColorGradient(value, selected, mIsGrayscale, &rv, &gv, &bv);
int px = ((mid.height - 1 - yy) * mid.width + x) * 3;
data[px++] = rv;
data[px++] = gv;
data[px] = bv;
}
}
else //logF
{
double yy2_base=exp(lmin)/f;
float yy2 = yy2_base;
double exp_scale_per_height = exp(scale/mid.height);
for (int yy = 0; yy < mid.height; yy++) {
if (int(yy2)>=half)
yy2=half-1;
if (yy2<0)
yy2=0;
float bin0 = float(yy2);
yy2_base *= exp_scale_per_height;
float yy3 = yy2_base;
if (int(yy3)>=half)
yy3=half-1;
if (yy3<0)
yy3=0;
float bin1 = float(yy3);
AColor::ColorGradientChoice selected =
AColor::ColorGradientUnselected;
// If we are in the time selected range, then we may use a different color set.
if (ssel0 <= w0 && w1 < ssel1)
{
bool isSpectral = ((track->GetDisplay() == WaveTrack::SpectralSelectionDisplay) ||
(track->GetDisplay() == WaveTrack::SpectralSelectionLogDisplay));
selected = ChooseColorSet( bin0, bin1, selBinLo, selBinCenter, selBinHi, x/DASH_LENGTH, isSpectral );
}
const float value = clip->mSpecPxCache->values[x * mid.height + yy];
yy2 = yy2_base;
unsigned char rv, gv, bv;
GetColorGradient(value, selected, mIsGrayscale, &rv, &gv, &bv);
#ifdef EXPERIMENTAL_FFT_Y_GRID
@ -2265,10 +2297,9 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
data[px++] = rv;
data[px++] = gv;
data[px] = bv;
}
}
x++;
}
} // each y
} // logF
} // each x
// If we get to this point, the clip is actually visible on the
// screen, so remember the display rectangle.