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:
parent
ee600ce30b
commit
ecb97e9c58
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user