diff --git a/Source/Module/modules/audio/analysis/FFTAnalyzerManager.cpp b/Source/Module/modules/audio/analysis/FFTAnalyzerManager.cpp index f95972cea..7cd7bfbd9 100644 --- a/Source/Module/modules/audio/analysis/FFTAnalyzerManager.cpp +++ b/Source/Module/modules/audio/analysis/FFTAnalyzerManager.cpp @@ -22,6 +22,9 @@ FFTAnalyzerManager::FFTAnalyzerManager() : maxDB = addFloatParameter("Max DB", "", 0, -100, 20); selectItemWhenCreated = false; + + //script + scriptObject.getDynamicObject()->setMethod("getFFTData", &FFTAnalyzerManager::getFFTDataFromScript); } FFTAnalyzerManager::~FFTAnalyzerManager() @@ -45,20 +48,35 @@ void FFTAnalyzerManager::process(const float* samples, int numSamples) auto mindB = minDB->floatValue(); auto maxdB = jmax(maxDB->floatValue(), mindB); + float tmpScopeData[scopeSize]; for (int i = 0; i < scopeSize; ++i) // [3] { auto skewedProportionX = 1.0f - std::exp(std::log(1.0f - i / (float)scopeSize) * 0.2f); auto fftDataIndex = jlimit(0, fftSize / 2, (int)(skewedProportionX * fftSize / 2)); auto level = jmap(jlimit(mindB, maxdB, Decibels::gainToDecibels(fftData[fftDataIndex]) - Decibels::gainToDecibels((float)fftSize)), mindB, maxdB, 0.0f, 1.0f); - scopeData[i] = level; // [4] + tmpScopeData[i] = level; // [4] } - for (auto& i : items) i->process(scopeData, scopeSize); + for (auto& i : items) + { + i->process(tmpScopeData, scopeSize); + } + + { + const ScopedLock lock(scopeDataMutex); + memcpy(scopeData, tmpScopeData, sizeof(scopeData)); + } nextFFTBlockReady = false; } } +void FFTAnalyzerManager::copyScopeData(float* scopeData, int maxSize) const +{ + const ScopedLock lock(scopeDataMutex); + memcpy(scopeData, this->scopeData, std::min(maxSize * sizeof(*scopeData), sizeof(this->scopeData))); +} + void FFTAnalyzerManager::pushNextSampleIntoFifo(float sample) { if (fifoIndex == fftSize) // [11] @@ -77,4 +95,26 @@ void FFTAnalyzerManager::pushNextSampleIntoFifo(float sample) InspectableEditor* FFTAnalyzerManager::getEditorInternal(bool isRoot, Array inspectables) { return new FFTAnalyzerManagerEditor(this, isRoot); -} \ No newline at end of file +} + +var FFTAnalyzerManager::getFFTDataFromScript(const var::NativeFunctionArgs& a) +{ + FFTAnalyzerManager* manager = getObjectFromJS(a); + var result; + if (a.numArguments > 0 && a.arguments[0].isArray()) + { + result = a.arguments[0]; + } + else + { + result = Array{}; + } + + Array& resultArray = *result.getArray(); + resultArray.clearQuick(); + + float tmpScopeData[scopeSize]; + manager->copyScopeData(tmpScopeData); + resultArray.addArray(tmpScopeData, scopeSize); + return result; +} diff --git a/Source/Module/modules/audio/analysis/FFTAnalyzerManager.h b/Source/Module/modules/audio/analysis/FFTAnalyzerManager.h index f49e9dfa2..91ee03259 100644 --- a/Source/Module/modules/audio/analysis/FFTAnalyzerManager.h +++ b/Source/Module/modules/audio/analysis/FFTAnalyzerManager.h @@ -30,6 +30,10 @@ class FFTAnalyzerManager : scopeSize = 256 // [3] }; + void process(const float* samples, int numSamples); + void copyScopeData(float* scopeData, int maxSize = scopeSize) const; + +private: dsp::FFT forwardFFT; // [4] dsp::WindowingFunction window; // [5] float fifo[fftSize]; // [6] @@ -37,9 +41,12 @@ class FFTAnalyzerManager : int fifoIndex = 0; // [8] bool nextFFTBlockReady = false; // [9] float scopeData[scopeSize]; // [10] + CriticalSection scopeDataMutex; - void process(const float* samples, int numSamples); void pushNextSampleIntoFifo(float sample); InspectableEditor* getEditorInternal(bool isRoot, Array inspectables = Array()) override; -}; \ No newline at end of file + + //SCRIPT + static var getFFTDataFromScript(const var::NativeFunctionArgs& a); +}; diff --git a/Source/Module/modules/audio/analysis/ui/FFTAnalyzerManagerEditor.cpp b/Source/Module/modules/audio/analysis/ui/FFTAnalyzerManagerEditor.cpp index 174d9a530..85d41324f 100644 --- a/Source/Module/modules/audio/analysis/ui/FFTAnalyzerManagerEditor.cpp +++ b/Source/Module/modules/audio/analysis/ui/FFTAnalyzerManagerEditor.cpp @@ -50,9 +50,11 @@ void FFTAnalyzerManagerEditor::FFTViz::paint(Graphics& g) Path fftPath; fftPath.startNewSubPath(r.getRelativePoint(0.f, 1.0f).toFloat()); + float scopeData[analyzerManager->scopeSize]; + analyzerManager->copyScopeData(scopeData); for (int i = 0; i < analyzerManager->scopeSize; ++i) { - fftPath.lineTo(r.getRelativePoint(i * 1.0f / analyzerManager->scopeSize, 1 - analyzerManager->scopeData[i]).toFloat()); + fftPath.lineTo(r.getRelativePoint(i * 1.0f / analyzerManager->scopeSize, 1 - scopeData[i]).toFloat()); } fftPath.lineTo(r.getRelativePoint(1.0f, 1.0f).toFloat());