1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-25 00:30:07 +02:00

Merge branch 'master' into HEAD

This commit is contained in:
Paul Licameli 2016-08-26 12:42:00 -04:00
commit 8102e1717b
3 changed files with 97 additions and 14 deletions

View File

@ -35,6 +35,7 @@
#include "Project.h"
#include "WaveTrack.h"
#include "FFT.h"
#include "Profiler.h"
#include "prefs/SpectrogramSettings.h"
@ -42,6 +43,17 @@
#include "Experimental.h"
//#undef _OPENMP
#ifdef _OPENMP
#include <omp.h>
#else
// Comment this out if you want to profile non OpenMP builds too.
#undef BEGIN_TASK_PROFILING
#undef END_TASK_PROFILING
#define BEGIN_TASK_PROFILING(TASK_DESCRIPTION)
#define END_TASK_PROFILING(TASK_DESCRIPTION)
#endif
class WaveCache {
public:
WaveCache()
@ -261,7 +273,7 @@ protected:
};
static void ComputeSpectrumUsingRealFFTf
(float *buffer, HFFT hFFT, const float *window, int len, float *out)
(float * __restrict buffer, HFFT hFFT, const float * __restrict window, int len, float * __restrict out)
{
int i;
if(len > hFFT->Points*2)
@ -276,7 +288,7 @@ static void ComputeSpectrumUsingRealFFTf
if(power <= 0)
out[0] = -160.0;
else
out[0] = 10.0*log10(power);
out[0] = 10.0*log10f(power);
for(i=1;i<hFFT->Points;i++) {
const int index = hFFT->BitReversed[i];
const float re = buffer[index], im = buffer[index + 1];
@ -765,7 +777,7 @@ bool SpecCache::CalculateOneSpectrum
double offset, double rate, double pixelsPerSecond,
int lowerBoundX, int upperBoundX,
const std::vector<float> &gainFactors,
float *scratch)
float* __restrict scratch, float* __restrict out) const
{
bool result = false;
const bool reassignment =
@ -790,11 +802,13 @@ bool SpecCache::CalculateOneSpectrum
if (start <= 0 || start >= numSamples) {
if (xx >= 0 && xx < len) {
// Pixel column is out of bounds of the clip! Should not happen.
float *const results = &freq[half * xx];
float *const results = &out[half * xx];
std::fill(results, results + half, 0.0f);
}
}
else {
// We can avoid copying memory when ComputeSpectrum is used below
bool copy = !autocorrelation || (padding > 0) || reassignment;
float *useBuffer = 0;
@ -826,6 +840,7 @@ bool SpecCache::CalculateOneSpectrum
if (myLen > 0) {
useBuffer = (float*)(waveTrackCache.Get(floatSample,
floor(0.5 + start + offset * rate), myLen));
if (copy)
memcpy(adj, useBuffer, myLen * sizeof(float));
}
@ -835,7 +850,7 @@ bool SpecCache::CalculateOneSpectrum
useBuffer = scratch;
if (autocorrelation) {
float *const results = &freq[half * xx];
float *const results = &out[half * xx];
// This function does not mutate useBuffer
ComputeSpectrum(useBuffer, windowSize, windowSize,
rate, results,
@ -916,12 +931,12 @@ bool SpecCache::CalculateOneSpectrum
int correctedX = (floor(0.5 + xx + timeCorrection * pixelsPerSecond / rate));
if (correctedX >= lowerBoundX && correctedX < upperBoundX)
result = true,
freq[half * correctedX + bin] += power;
out[half * correctedX + bin] += power;
}
}
}
else {
float *const results = &freq[half * xx];
float *const results = &out[half * xx];
// Do the FFT. Note that useBuffer is multiplied by the window,
// and the window is initialized with leading and trailing zeroes
@ -938,6 +953,7 @@ bool SpecCache::CalculateOneSpectrum
}
}
}
return result;
}
@ -967,24 +983,65 @@ void SpecCache::Populate
const int half = fftLen / 2;
const size_t bufferSize = fftLen;
std::vector<float> buffer(reassignment ? 3 * bufferSize : bufferSize);
const size_t scratchSize = reassignment ? 3 * bufferSize : bufferSize;
std::vector<float> scratch(scratchSize);
std::vector<float> gainFactors;
if (!autocorrelation)
ComputeSpectrogramGainFactors(fftLen, rate, frequencyGain, gainFactors);
#ifdef _OPENMP
// todo: query # of threads or make it a setting
const int numThreads = 8;
omp_set_num_threads(numThreads);
// We need certain per-thread data for thread safety
// Assumes WaveTrackCache is reentrant since it takes a const* to WaveTrack
struct {
WaveTrackCache* cache;
float* scratch;
} threadLocalStorage[numThreads];
// May as well use existing data for one of the threads
assert(numThreads > 0);
threadLocalStorage[0].cache = &waveTrackCache;
threadLocalStorage[0].scratch = &scratch[0];
for (int i = 1; i < numThreads; i++) {
threadLocalStorage[i].cache = new WaveTrackCache( waveTrackCache.GetTrack() );
threadLocalStorage[i].scratch = new float[scratchSize];
}
#endif
// Loop over the ranges before and after the copied portion and compute anew.
// One of the ranges may be empty.
for (int jj = 0; jj < 2; ++jj) {
const int lowerBoundX = jj == 0 ? 0 : copyEnd;
const int upperBoundX = jj == 0 ? copyBegin : numPixels;
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (auto xx = lowerBoundX; xx < upperBoundX; ++xx)
{
#ifdef _OPENMP
int threadNum = omp_get_thread_num();
assert(threadNum >=0 && threadNum < numThreads);
WaveTrackCache* cache = threadLocalStorage[threadNum].cache;
float* buffer = threadLocalStorage[threadNum].scratch;
#else
WaveTrackCache* cache = &waveTrackCache;
float* buffer = &scratch[0];
#endif
CalculateOneSpectrum(
settings, waveTrackCache, xx, numSamples,
settings, *cache, xx, numSamples,
offset, rate, pixelsPerSecond,
lowerBoundX, upperBoundX,
gainFactors, &buffer[0]);
gainFactors, buffer, &freq[0]);
}
if (reassignment) {
// Need to look beyond the edges of the range to accumulate more
@ -1000,7 +1057,7 @@ void SpecCache::Populate
settings, waveTrackCache, --xx, numSamples,
offset, rate, pixelsPerSecond,
lowerBoundX, upperBoundX,
gainFactors, &buffer[0]);
gainFactors, &scratch[0], &freq[0]);
if (!result)
break;
}
@ -1013,13 +1070,16 @@ void SpecCache::Populate
settings, waveTrackCache, xx++, numSamples,
offset, rate, pixelsPerSecond,
lowerBoundX, upperBoundX,
gainFactors, &buffer[0]);
gainFactors, &scratch[0], &freq[0]);
if (!result)
break;
}
// Now Convert to dB terms. Do this only after accumulating
// power values, which may cross columns with the time correction.
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (auto xx = lowerBoundX; xx < upperBoundX; ++xx) {
float *const results = &freq[half * xx];
const HFFT hFFT = settings.hFFT;
@ -1038,6 +1098,14 @@ void SpecCache::Populate
}
}
}
#ifdef _OPENMP
for (int i = 1; i < numThreads; i++)
{
delete[] threadLocalStorage[i].scratch;
delete threadLocalStorage[i].cache;
}
#endif
}
bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
@ -1045,6 +1113,8 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
int numPixels,
double t0, double pixelsPerSecond) const
{
BEGIN_TASK_PROFILING("GetSpectrogram");
const WaveTrack *const track = waveTrackCache.GetTrack();
const SpectrogramSettings &settings = track->GetSpectrogramSettings();
const bool autocorrelation =
@ -1074,6 +1144,9 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
mSpecCache->len >= numPixels) {
spectrogram = &mSpecCache->freq[0];
where = &mSpecCache->where[0];
END_TASK_PROFILING("GetSpectrogram");
return false; //hit cache completely
}
@ -1125,14 +1198,21 @@ bool WaveClip::GetSpectrogram(WaveTrackCache &waveTrackCache,
half * (copyEnd - copyBegin) * sizeof(float));
}
BEGIN_TASK_PROFILING("Populate");
mSpecCache->Populate
(settings, waveTrackCache, copyBegin, copyEnd, numPixels,
mSequence->GetNumSamples(),
mOffset, mRate, pixelsPerSecond);
END_TASK_PROFILING("Populate");
mSpecCache->dirty = mDirty;
spectrogram = &mSpecCache->freq[0];
where = &mSpecCache->where[0];
END_TASK_PROFILING("GetSpectrogram");
return true;
}

View File

@ -97,7 +97,8 @@ public:
double offset, double rate, double pixelsPerSecond,
int lowerBoundX, int upperBoundX,
const std::vector<float> &gainFactors,
float *scratch);
float* __restrict scratch,
float* __restrict out) const;
void Populate
(const SpectrogramSettings &settings, WaveTrackCache &waveTrackCache,

View File

@ -1667,6 +1667,7 @@ void NumericTextCtrl::OnKeyDown(wxKeyEvent &event)
}
mValueString[digitPosition] = wxChar(keyCode);
ControlsToValue();
Refresh();// Force an update of the control. [Bug 1497]
ValueToControls();
mFocusedDigit = (mFocusedDigit + 1) % (mDigits.GetCount());
Updated();
@ -1686,6 +1687,7 @@ void NumericTextCtrl::OnKeyDown(wxKeyEvent &event)
if (theDigit != wxChar('-'))
theDigit = '0';
ControlsToValue();
Refresh();// Force an update of the control. [Bug 1497]
ValueToControls();
Updated();
}