1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-02 08:39:46 +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 "AudacityApp.h"
#include "TrackArtist.h"
#include "AudacityApp.h"
#include "float_cast.h"
#include <math.h>
@ -1749,8 +1749,9 @@ void TrackArtist::DrawSpectrum(WaveTrack *track,
return;
}
WaveTrackCache cache(track);
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,
wxDC & dc,
const wxRect & r,
@ -1830,6 +1831,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrack *track,
bool autocorrelation,
bool logF)
{
const WaveTrack *const track = cache.GetTrack();
enum { MONOCHROME_LINE = 230, COLORED_LINE = 0 };
enum { DASH_LENGTH = 10 /* pixels */ };
@ -1962,7 +1965,7 @@ void TrackArtist::DrawClipSpectrum(WaveTrack *track,
float *freq = new float[mid.width * half];
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);
int ifreq = lrint(rate/2);

View File

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

View File

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

View File

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