Update of /cvsroot/audacity/audacity-src/src In directory sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv5360/src
Modified Files: Spectrum.cpp Spectrum.h TrackArtist.cpp WaveClip.cpp WaveClip.h Log Message: Spectrogram view revisited. Spectrum, WaveClip and TrackArtist fiddled with to improve vertical zooming/resizing speed. Vertical manipulation of a track improved significantly. Horizontal movement dis-improved by about 10% at high FFT resoultions. Index: Spectrum.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/Spectrum.cpp,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- Spectrum.cpp 2 Jan 2007 01:05:13 -0000 1.13 +++ Spectrum.cpp 24 Jan 2007 01:13:33 -0000 1.14 @@ -33,15 +33,15 @@ #endif -bool ComputeSpectrum(float * data, int width, int height, - int maxFreq, int minFreq, int windowSize, - double rate, float *grayscaleOut, +bool ComputeSpectrum(float * data, int width, + int windowSize, + double rate, float *output, bool autocorrelation, int windowFunc) { if (width < windowSize) return false; - if (!data || !grayscaleOut) + if (!data || !output) return true; float *processed = new float[windowSize]; @@ -92,15 +92,7 @@ windows++; } - int minSamples = int (minFreq * windowSize / rate + 0.5); // units here are fft bins - int maxSamples = int (maxFreq * windowSize / rate + 0.5); - if (minSamples < 0.) - minSamples = 0.; - if (maxSamples > half) - maxSamples = half; - if (autocorrelation) { - maxSamples = half; // Peak Pruning as described by Tolonen and Karjalainen, 2000 /* @@ -108,7 +100,7 @@ It should be safe, as indexes refer only to current and previous elements, that have already been clipped, etc... */ - for (i = 0; i < maxSamples; i++) { + for (i = 0; i < half; i++) { // Clip at zero, copy to temp array if (processed[i] < 0.0) processed[i] = float(0.0); @@ -123,26 +115,17 @@ // Clip at zero again if (processed[i] < 0.0) processed[i] = float(0.0); - - // Find new max: only for i>0: unused!?! - /* - if(i) { - if (processed[i] > max) - max = processed[i]; - } - */ } - // Reverse and scale - for (i = 0; i < maxSamples; i++) + for (i = 0; i < half; i++) in[i] = processed[i] / (windowSize / 4); - for (i = 0; i < maxSamples; i++) - processed[maxSamples - 1 - i] = in[i]; + for (i = 0; i < half; i++) + processed[half - 1 - i] = in[i]; } else { // Convert to decibels // But do it safely; -Inf is nobody's friend - for (i = minSamples; i < maxSamples; i++){ + for (i = 0; i < half; i++){ float temp=(processed[i] / windowSize / windows); if (temp > 0.0) processed[i] = 10*log10(temp); @@ -151,42 +134,8 @@ } } - // Finally, put it into bins in grayscaleOut[], normalized to a 0.0-1.0 scale - float binPerPx = float(maxSamples - minSamples) / float(height); - for (i = 0; i < height; i++) { - float bin0 = float (i) * binPerPx + minSamples; - float bin1 = float (i + 1) * binPerPx + minSamples; - - float value; - - if (int (bin1) == int (bin0)) - value = processed[int (bin0)]; - else { - float binwidth= bin1 - bin0; - value = processed[int (bin0)] * (1.f - bin0 + (int)bin0); - - bin0 = 1 + int (bin0); - while (bin0 < int (bin1)) { - value += processed[int (bin0)]; - bin0 += 1.0; - } - value += processed[int (bin1)] * (bin1 - int (bin1)); - - value /= binwidth; - } - - if (!autocorrelation) { - // Last step converts dB to a 0.0-1.0 range - value = (value + 80.0) / 80.0; - } - - if (value > 1.0) - value = float(1.0); - if (value < 0.0) - value = float(0.0); - - grayscaleOut[i] = value; - } + for(i=0;i<half;i++) + output[i] = processed[i]; delete[]in; delete[]out; delete[]out2; Index: WaveClip.h =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/WaveClip.h,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- WaveClip.h 20 Nov 2006 13:54:38 -0000 1.16 +++ WaveClip.h 24 Jan 2007 01:13:33 -0000 1.17 @@ -101,7 +101,7 @@ bool GetWaveDisplay(float *min, float *max, float *rms, sampleCount *where, int numPixels, double t0, double pixelsPerSecond); bool GetSpectrogram(float *buffer, sampleCount *where, - int numPixels, int height, + int numPixels, double t0, double pixelsPerSecond, bool autocorrelation); bool GetMinMax(float *min, float *max, double t0, double t1); Index: WaveClip.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/WaveClip.cpp,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -r1.25 -r1.26 --- WaveClip.cpp 2 Jan 2007 01:05:13 -0000 1.25 +++ WaveClip.cpp 24 Jan 2007 01:13:33 -0000 1.26 @@ -72,19 +72,16 @@ class SpecCache { public: - SpecCache(int cacheLen, int viewHeight, bool autocorrelation) + SpecCache(int cacheLen, int half, bool autocorrelation) { windowTypeOld = -1; - maxFreqPrefOld = -1; - minFreqPrefOld = -1; windowSizeOld = -1; dirty = -1; start = -1.0; pps = 0.0; len = cacheLen; ac = autocorrelation; - height = viewHeight; - freq = new float[len*height]; + freq = new float[len*half]; where = new sampleCount[len+1]; } @@ -95,11 +92,8 @@ } int windowTypeOld; - int maxFreqPrefOld; - int minFreqPrefOld; int windowSizeOld; int dirty; - int height; bool ac; sampleCount len; double start; @@ -379,42 +373,31 @@ } bool WaveClip::GetSpectrogram(float *freq, sampleCount *where, - int numPixels, int height, + int numPixels, double t0, double pixelsPerSecond, bool autocorrelation) { int windowType; - bool autoMaxFrequency; - - int minFreqPref = gPrefs->Read(wxT("/Spectrum/MinFreq"), 0L); - int maxFreqPref = gPrefs->Read(wxT("/Spectrum/MaxFreq"), 8000L); int windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); - gPrefs->Read(wxT("/Spectrum/AutoMaxFrequency"), &autoMaxFrequency, false); + int half = windowSize/2; gPrefs->Read(wxT("/Spectrum/WindowType"), &windowType, 3); - if (autoMaxFrequency) { - // automatically set frequency to half of sampling rate - maxFreqPref=int(mRate/2); - } if (mSpecCache && mSpecCache->windowTypeOld == windowType && - mSpecCache->maxFreqPrefOld == maxFreqPref && - mSpecCache->minFreqPrefOld == minFreqPref && mSpecCache->windowSizeOld == windowSize && mSpecCache->dirty == mDirty && mSpecCache->start == t0 && mSpecCache->ac == autocorrelation && - mSpecCache->height == height && mSpecCache->len >= numPixels && mSpecCache->pps == pixelsPerSecond) { - memcpy(freq, mSpecCache->freq, numPixels*height*sizeof(float)); + memcpy(freq, mSpecCache->freq, numPixels*half*sizeof(float)); memcpy(where, mSpecCache->where, (numPixels+1)*sizeof(sampleCount)); return true; } SpecCache *oldCache = mSpecCache; - mSpecCache = new SpecCache(numPixels, height, autocorrelation); + mSpecCache = new SpecCache(numPixels, half, autocorrelation); mSpecCache->pps = pixelsPerSecond; mSpecCache->start = t0; @@ -435,11 +418,8 @@ // possible if (oldCache->dirty == mDirty && oldCache->windowTypeOld == windowType && - oldCache->maxFreqPrefOld == maxFreqPref && - oldCache->minFreqPrefOld == minFreqPref && oldCache->windowSizeOld == windowSize && oldCache->pps == pixelsPerSecond && - oldCache->height == height && oldCache->ac == autocorrelation && oldCache->where[0] < mSpecCache->where[mSpecCache->len] && oldCache->where[oldCache->len] > mSpecCache->where[0]) { @@ -455,9 +435,9 @@ if (ox >= 0 && ox < oldCache->len && mSpecCache->where[x] == oldCache->where[ox]) { - for (sampleCount i = 0; i < (sampleCount)height; i++) - mSpecCache->freq[height * x + i] = - oldCache->freq[height * ox + i]; + for (sampleCount i = 0; i < (sampleCount)half; i++) + mSpecCache->freq[half * x + i] = + oldCache->freq[half * ox + i]; recalc[x] = false; } @@ -466,8 +446,6 @@ float *buffer = new float[windowSize]; mSpecCache->windowTypeOld = windowType; - mSpecCache->maxFreqPrefOld = maxFreqPref; - mSpecCache->minFreqPrefOld = minFreqPref; mSpecCache->windowSizeOld = windowSize; for (x = 0; x < mSpecCache->len; x++) @@ -479,8 +457,8 @@ if (start <= 0 || start >= mSequence->GetNumSamples()) { - for (i = 0; i < (sampleCount)height; i++) - mSpecCache->freq[height * x + i] = 0; + for (i = 0; i < (sampleCount)half; i++) + mSpecCache->freq[half * x + i] = 0; } else @@ -503,9 +481,8 @@ if (len > 0) mSequence->Get((samplePtr)adj, floatSample, start, len); - ComputeSpectrum(buffer, windowSize, height, - maxFreqPref, minFreqPref, windowSize, - mRate, &mSpecCache->freq[height * x], + ComputeSpectrum(buffer, windowSize, windowSize, + mRate, &mSpecCache->freq[half * x], autocorrelation, windowType); } } @@ -515,9 +492,8 @@ delete oldCache; mSpecCache->dirty = mDirty; - memcpy(freq, mSpecCache->freq, numPixels*height*sizeof(float)); + memcpy(freq, mSpecCache->freq, numPixels*half*sizeof(float)); memcpy(where, mSpecCache->where, (numPixels+1)*sizeof(sampleCount)); - return true; } Index: TrackArtist.cpp =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/TrackArtist.cpp,v retrieving revision 1.88 retrieving revision 1.89 diff -u -d -r1.88 -r1.89 --- TrackArtist.cpp 2 Jan 2007 01:05:13 -0000 1.88 +++ TrackArtist.cpp 24 Jan 2007 01:13:33 -0000 1.89 @@ -1415,10 +1415,12 @@ if (!image)return; unsigned char *data = image->GetData(); - float *freq = new float[mid.width * mid.height]; + int windowSize = gPrefs->Read(wxT("/Spectrum/FFTSize"), 256); + int half = windowSize/2; + float *freq = new float[mid.width * half]; sampleCount *where = new sampleCount[mid.width+1]; - if (!clip->GetSpectrogram(freq, where, mid.width, mid.height, + if (!clip->GetSpectrogram(freq, where, mid.width, t0, pps, autocorrelation)) { delete image; delete[] where; @@ -1428,28 +1430,60 @@ bool isGrayscale = false; gPrefs->Read(wxT("/Spectrum/Grayscale"), &isGrayscale, false); + int maxFreq = gPrefs->Read(wxT("/Spectrum/MaxFreq"), rate/2.); + int minFreq = gPrefs->Read(wxT("/Spectrum/MinFreq"), 0L); + int minSamples = int (minFreq * windowSize / rate + 0.5); // units here are fft bins + int maxSamples = int (maxFreq * windowSize / rate + 0.5); + float binPerPx = float(maxSamples - minSamples) / float(mid.height); int x = 0; sampleCount w1 = (sampleCount) ((t0*rate + x *rate *tstep) + .5); while (x < mid.width) { - sampleCount w0 = w1; w1 = (sampleCount) ((t0*rate + (x+1) *rate *tstep) + .5); - float *spec = &freq[mid.height * x]; - for (int yy = 0; yy < mid.height; yy++) { bool selflag = (ssel0 <= w0 && w1 < ssel1); unsigned char rv, gv, bv; - GetColorGradient(spec[mid.height - 1 - yy], - selflag, isGrayscale, &rv, &gv, &bv); + float bin0 = float (yy) * binPerPx + minSamples; + float bin1 = float (yy + 1) * binPerPx + minSamples; - data[(yy * mid.width + x) * 3] = rv; - data[(yy * mid.width + x) * 3 + 1] = gv; - data[(yy * mid.width + x) * 3 + 2] = bv; - } + float value; + + if (int (bin1) == int (bin0)) + value = freq[half * x + int (bin0)]; + else { + float binwidth= bin1 - bin0; + value = freq[half * x + int (bin0)] * (1.f - bin0 + (int)bin0); + + bin0 = 1 + int (bin0); + while (bin0 < int (bin1)) { + value += freq[half * x + int (bin0)]; + bin0 += 1.0; + } + value += freq[half * x + int (bin1)] * (bin1 - int (bin1)); + + value /= binwidth; + } + + if (!autocorrelation) { + // Last step converts dB to a 0.0-1.0 range + value = (value + 80.0) / 80.0; + } + + if (value > 1.0) + value = float(1.0); + if (value < 0.0) + value = float(0.0); + GetColorGradient(value, selflag, isGrayscale, &rv, &gv, &bv); + + int px = ((mid.height - 1 - yy) * mid.width + x) * 3; + data[px++] = rv; + data[px++] = gv; + data[px] = bv; + } x++; } Index: Spectrum.h =================================================================== RCS file: /cvsroot/audacity/audacity-src/src/Spectrum.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- Spectrum.h 2 Jan 2007 01:05:13 -0000 1.6 +++ Spectrum.h 24 Jan 2007 01:13:33 -0000 1.7 @@ -18,11 +18,10 @@ a function of frequency, for some block of audio data. width: the number of samples - height: the desired number of frequencies + calculates windowSize/2 frequency samples */ -bool ComputeSpectrum(float * data, int width, int height, - int maxFrequency, int minFrequency, int windowSize, +bool ComputeSpectrum(float * data, int width, int windowSize, double rate, float *out, bool autocorrelation, int windowFunc=3); #endif ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ Audacity-cvs mailing list Audacity-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/audacity-cvs