1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-11 06:04:55 +02:00

Use WaveTrackCache for spectrograms

Zooming-in of spectrograms (or other view changes that invalidate the
whole pixel cache of the WaveClip) used to do at least one opening and
closing of a block file for each column of pixels.  With this change,
open each block file not more than once for each repopulation of the
cache.

Improved speed may be more noticeable on less powerful computers, or when
the audio file is in a slower storage device.
This commit is contained in:
Paul Licameli 2015-05-26 18:11:36 -04:00
parent bdc2839112
commit e6ccd51326
4 changed files with 54 additions and 28 deletions

View File

@ -143,8 +143,8 @@ audio tracks.
*//*******************************************************************/ *//*******************************************************************/
#include "Audacity.h" #include "Audacity.h"
#include "AudacityApp.h"
#include "TrackArtist.h" #include "TrackArtist.h"
#include "AudacityApp.h"
#include "float_cast.h" #include "float_cast.h"
#include <math.h> #include <math.h>
@ -1749,8 +1749,9 @@ void TrackArtist::DrawSpectrum(WaveTrack *track,
return; return;
} }
WaveTrackCache cache(track);
for (WaveClipList::compatibility_iterator it = track->GetClipIterator(); it; it = it->GetNext()) { for (WaveClipList::compatibility_iterator it = track->GetClipIterator(); it; it = it->GetNext()) {
DrawClipSpectrum(track, it->GetData(), dc, r, viewInfo, autocorrelation, logF); DrawClipSpectrum(cache, it->GetData(), dc, r, viewInfo, autocorrelation, logF);
} }
} }
@ -1822,7 +1823,7 @@ AColor::ColorGradientChoice ChooseColorSet( float bin0, float bin1, float selBin
void TrackArtist::DrawClipSpectrum(WaveTrack *track, void TrackArtist::DrawClipSpectrum(WaveTrackCache &cache,
WaveClip *clip, WaveClip *clip,
wxDC & dc, wxDC & dc,
const wxRect & r, const wxRect & r,
@ -1830,6 +1831,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrack *track,
bool autocorrelation, bool autocorrelation,
bool logF) bool logF)
{ {
const WaveTrack *const track = cache.GetTrack();
enum { MONOCHROME_LINE = 230, COLORED_LINE = 0 }; enum { MONOCHROME_LINE = 230, COLORED_LINE = 0 };
enum { DASH_LENGTH = 10 /* pixels */ }; enum { DASH_LENGTH = 10 /* pixels */ };
@ -1962,7 +1965,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrack *track,
float *freq = new float[mid.width * half]; float *freq = new float[mid.width * half];
sampleCount *where = new sampleCount[mid.width+1]; sampleCount *where = new sampleCount[mid.width+1];
bool updated = clip->GetSpectrogram(freq, where, mid.width, bool updated = clip->GetSpectrogram(cache, freq, where, mid.width,
t0, pps, autocorrelation); t0, pps, autocorrelation);
int ifreq = lrint(rate/2); int ifreq = lrint(rate/2);

View File

@ -29,6 +29,7 @@ class wxHashTable;
class Track; class Track;
class WaveTrack; class WaveTrack;
class WaveTrackCache;
class WaveClip; class WaveClip;
class NoteTrack; class NoteTrack;
class LabelTrack; class LabelTrack;
@ -141,7 +142,7 @@ class AUDACITY_DLL_API TrackArtist {
bool drawEnvelope, bool drawSamples, bool drawSliders, bool drawEnvelope, bool drawSamples, bool drawSliders,
bool dB, bool muted); bool dB, bool muted);
void DrawClipSpectrum(WaveTrack *track, WaveClip *clip, void DrawClipSpectrum(WaveTrackCache &cache, WaveClip *clip,
wxDC & dc, const wxRect & r, const ViewInfo *viewInfo, wxDC & dc, const wxRect & r, const ViewInfo *viewInfo,
bool autocorrelation, bool logF); bool autocorrelation, bool logF);

View File

@ -25,6 +25,8 @@ drawing). Cache's the Spectrogram frequency samples.
*//*******************************************************************/ *//*******************************************************************/
#include "WaveClip.h"
#include <math.h> #include <math.h>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -32,7 +34,6 @@ drawing). Cache's the Spectrogram frequency samples.
#include "Spectrum.h" #include "Spectrum.h"
#include "Prefs.h" #include "Prefs.h"
#include "WaveClip.h"
#include "Envelope.h" #include "Envelope.h"
#include "Resample.h" #include "Resample.h"
#include "Project.h" #include "Project.h"
@ -753,7 +754,8 @@ bool WaveClip::GetWaveDisplay(float *min, float *max, float *rms,int* bl,
return true; return true;
} }
bool WaveClip::GetSpectrogram(float *freq, sampleCount *where, bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
float *freq, sampleCount *where,
int numPixels, int numPixels,
double t0, double pixelsPerSecond, double t0, double pixelsPerSecond,
bool autocorrelation) bool autocorrelation)
@ -912,6 +914,7 @@ bool WaveClip::GetSpectrogram(float *freq, sampleCount *where,
} }
} }
float *useBuffer;
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS #ifdef EXPERIMENTAL_FFT_SKIP_POINTS
float *buffer = new float[windowSize*fftSkipPoints1]; float *buffer = new float[windowSize*fftSkipPoints1];
mSpecCache->fftSkipPointsOld = fftSkipPoints; mSpecCache->fftSkipPointsOld = fftSkipPoints;
@ -952,6 +955,7 @@ bool WaveClip::GetSpectrogram(float *freq, sampleCount *where,
} }
else else
{ {
bool copy = !autocorrelation;
float *adj = buffer; float *adj = buffer;
start -= windowSize >> 1; start -= windowSize >> 1;
@ -960,23 +964,32 @@ bool WaveClip::GetSpectrogram(float *freq, sampleCount *where,
*adj++ = 0; *adj++ = 0;
len += start; len += start;
start = 0; start = 0;
copy = true;
} }
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS #ifdef EXPERIMENTAL_FFT_SKIP_POINTS
copy = true;
if (start + len*fftSkipPoints1 > mSequence->GetNumSamples()) { if (start + len*fftSkipPoints1 > mSequence->GetNumSamples()) {
int newlen = (mSequence->GetNumSamples() - start)/fftSkipPoints1; int newlen = (mSequence->GetNumSamples() - start)/fftSkipPoints1;
for (i = newlen*fftSkipPoints1; i < (sampleCount)len*fftSkipPoints1; i++) for (i = newlen*fftSkipPoints1; i < (sampleCount)len*fftSkipPoints1; i++)
adj[i] = 0;
len = newlen;
}
#else //!EXPERIMENTAL_FFT_SKIP_POINTS #else //!EXPERIMENTAL_FFT_SKIP_POINTS
if (start + len > mSequence->GetNumSamples()) { if (start + len > mSequence->GetNumSamples()) {
int newlen = mSequence->GetNumSamples() - start; int newlen = mSequence->GetNumSamples() - start;
for (i = newlen; i < (sampleCount)len; i++) for (i = newlen; i < (sampleCount)len; i++)
#endif //EXPERIMENTAL_FFT_SKIP_POINTS
adj[i] = 0; adj[i] = 0;
len = newlen; len = newlen;
copy = true;
} }
#endif //EXPERIMENTAL_FFT_SKIP_POINTS
if (len > 0) if (len > 0) {
#ifdef EXPERIMENTAL_FFT_SKIP_POINTS #ifdef EXPERIMENTAL_FFT_SKIP_POINTS
mSequence->Get((samplePtr)adj, floatSample, start, len*fftSkipPoints1); useBuffer = (float*)(waveTrackCache.Get(floatSample,
floor(0.5 + start + mOffset * mRate),
len * fftSkipPoints1));
memmove(adj, useBuffer, len * fftSkipPoints1 * sizeof(float));
if (fftSkipPoints) { if (fftSkipPoints) {
// TODO: (maybe) alternatively change Get to include skipping of points // TODO: (maybe) alternatively change Get to include skipping of points
int j=0; int j=0;
@ -986,16 +999,23 @@ bool WaveClip::GetSpectrogram(float *freq, sampleCount *where,
} }
} }
#else //!EXPERIMENTAL_FFT_SKIP_POINTS #else //!EXPERIMENTAL_FFT_SKIP_POINTS
mSequence->Get((samplePtr)adj, floatSample, start, len); useBuffer = (float*)(waveTrackCache.Get(floatSample,
floor(0.5 + start + mOffset * mRate), len));
if (copy)
memmove(adj, useBuffer, len * sizeof(float));
#endif //EXPERIMENTAL_FFT_SKIP_POINTS #endif //EXPERIMENTAL_FFT_SKIP_POINTS
}
if (copy)
useBuffer = buffer;
#ifdef EXPERIMENTAL_USE_REALFFTF #ifdef EXPERIMENTAL_USE_REALFFTF
if(autocorrelation) { if(autocorrelation) {
ComputeSpectrum(buffer, windowSize, windowSize, ComputeSpectrum(useBuffer, windowSize, windowSize,
mRate, &mSpecCache->freq[half * x], mRate, &mSpecCache->freq[half * x],
autocorrelation, windowType); autocorrelation, windowType);
} else { } else {
ComputeSpectrumUsingRealFFTf(buffer, hFFT, mWindow, mWindowSize, &mSpecCache->freq[half * x]); ComputeSpectrumUsingRealFFTf(useBuffer, hFFT, mWindow, mWindowSize, &mSpecCache->freq[half * x]);
} }
#else // EXPERIMENTAL_USE_REALFFTF #else // EXPERIMENTAL_USE_REALFFTF
ComputeSpectrum(buffer, windowSize, windowSize, ComputeSpectrum(buffer, windowSize, windowSize,

View File

@ -31,6 +31,7 @@
class Envelope; class Envelope;
class WaveCache; class WaveCache;
class WaveTrackCache;
class SpecCache; class SpecCache;
class SpecPxCache { class SpecPxCache {
@ -140,7 +141,8 @@ public:
* calculations and Contrast */ * calculations and Contrast */
bool GetWaveDisplay(float *min, float *max, float *rms,int* bl, sampleCount *where, bool GetWaveDisplay(float *min, float *max, float *rms,int* bl, sampleCount *where,
int numPixels, double t0, double pixelsPerSecond, bool &isLoadingOD); int numPixels, double t0, double pixelsPerSecond, bool &isLoadingOD);
bool GetSpectrogram(float *buffer, sampleCount *where, bool GetSpectrogram(WaveTrackCache &cache,
float *buffer, sampleCount *where,
int numPixels, int numPixels,
double t0, double pixelsPerSecond, double t0, double pixelsPerSecond,
bool autocorrelation); bool autocorrelation);