Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions DemoPlugin/PluginEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@

//-------------------------------------------------------------------------------------------------------

SpectrumAnalyzerAudioProcessorEditor::SpectrumAnalyzerAudioProcessorEditor(juce::AudioProcessor &p, vsa::AudioBufferFifo<float> &source)
SpectrumAnalyzerAudioProcessorEditor::SpectrumAnalyzerAudioProcessorEditor(juce::AudioProcessor &p,
vsa::AudioBufferFifo<float> &source)
: juce::AudioProcessorEditor(p)
, m_analyzer(source)
, m_thread("fft")
, m_analyzer(source, m_thread)
{
m_thread.startThread();
setSize(1000, 400);
addAndMakeVisible(m_analyzer);
m_analyzer.startTimerHz(60);
}

//-------------------------------------------------------------------------------------------------------

SpectrumAnalyzerAudioProcessorEditor::~SpectrumAnalyzerAudioProcessorEditor() = default;
SpectrumAnalyzerAudioProcessorEditor::~SpectrumAnalyzerAudioProcessorEditor()
{
m_thread.removeAllClients();
m_thread.stopThread(100);
}

//-------------------------------------------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion DemoPlugin/PluginEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class SpectrumAnalyzerAudioProcessorEditor final : public juce::AudioProcessorEd
void resized() override;

private:
juce::TimeSliceThread m_thread;
vsa::SpectrumAnalyzerComponent m_analyzer;
};

//-------------------------------------------------------------------------------------------------------

51 changes: 12 additions & 39 deletions Modules/vsa_spectrum_analyzer/SpectrumAnalyzer/SpectrumAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,55 @@

//-----------------------------------------------------------------------------

class vsa::SpectrumAnalyzer::SpectrumAnalyzerTimeSliceThread : public juce::TimeSliceThread
{
public:
SpectrumAnalyzerTimeSliceThread() : juce::TimeSliceThread("fft") { startThread(); }
~SpectrumAnalyzerTimeSliceThread() override { stopThread(100); }
};

//-----------------------------------------------------------------------------

void vsa::SpectrumAnalyzer::init()
{
const int fftSize = m_fft.getSize() * 2;
const int stepSize = fftSize / static_cast<int>(m_buffers.size());
for(const auto &[index, buffer] : juce::enumerate(m_buffers))
for (const auto &[index, buffer] : juce::enumerate(m_buffers))
{
buffer.setSize(static_cast<std::size_t>(fftSize));
const int writeSize = stepSize * static_cast<int>(index);
if (writeSize != 0)
buffer.skip(writeSize);
}

m_thread->addTimeSliceClient(this);
}

//-----------------------------------------------------------------------------

vsa::SpectrumAnalyzer::SpectrumAnalyzer(vsa::AudioBufferFifo<float> &source)
vsa::SpectrumAnalyzer::SpectrumAnalyzer(vsa::AudioBufferFifo<float> &source, juce::TimeSliceThread &thread, int fftSize)
: m_audioFifoFloat(&source)
, m_fft(fftSize)
{
thread.addTimeSliceClient(this);
init();
}

//-----------------------------------------------------------------------------

vsa::SpectrumAnalyzer::SpectrumAnalyzer(vsa::AudioBufferFifo<double> &source)
vsa::SpectrumAnalyzer::SpectrumAnalyzer(vsa::AudioBufferFifo<double> &source, juce::TimeSliceThread &thread, int fftSize)
: m_audioFifoDouble(&source)
, m_fft(fftSize)
{
thread.addTimeSliceClient(this);
init();
}

//-----------------------------------------------------------------------------

vsa::SpectrumAnalyzer::~SpectrumAnalyzer()
{
m_thread->removeTimeSliceClient(this);
}

//-----------------------------------------------------------------------------

int vsa::SpectrumAnalyzer::useTimeSlice()
{
if (populateConduitBuffer())
{
for(auto &b : m_buffers)
for (auto &b : m_buffers)
{
b.write(m_conduitBuffer);

if (b.isFftSpanReady())
{
auto fftSpan{ b.getFftSpan() };

m_windowingFunction.multiplyWithWindowingTable(fftSpan.data(), std::min(fftSpan.size(), static_cast<std::size_t>(m_fft.getSize())));
m_windowingFunction.multiplyWithWindowingTable(
fftSpan.data(), std::min(fftSpan.size(), static_cast<std::size_t>(m_fft.getSize())));
m_fft.performFrequencyOnlyForwardTransform(fftSpan.data());

m_analyzerCurve.pushCurve(fftSpan);
Expand All @@ -75,21 +62,6 @@ int vsa::SpectrumAnalyzer::useTimeSlice()
}

//-----------------------------------------------------------------------------

void vsa::SpectrumAnalyzer::startThread()
{
m_thread->startThread();
}

//-----------------------------------------------------------------------------

void vsa::SpectrumAnalyzer::suspendThread()
{
m_thread->stopThread(100);
}

//-----------------------------------------------------------------------------

bool vsa::SpectrumAnalyzer::populateConduitBuffer()
{
if (m_audioFifoFloat && m_audioFifoFloat->getAvailableSamples() > 0)
Expand Down Expand Up @@ -128,7 +100,8 @@ bool vsa::SpectrumAnalyzer::populateConduitBuffer()

vsa::SpectrumAnalyzerCurve::LockedCurve vsa::SpectrumAnalyzer::getAnalyzerCurve()
{
m_analyzerCurve.setSampleRate(m_audioFifoFloat ? m_audioFifoFloat->getSampleRate() : m_audioFifoDouble->getSampleRate());
m_analyzerCurve.setSampleRate(m_audioFifoFloat ? m_audioFifoFloat->getSampleRate()
: m_audioFifoDouble->getSampleRate());

return m_analyzerCurve.getCurve();
}
Expand Down
24 changes: 10 additions & 14 deletions Modules/vsa_spectrum_analyzer/SpectrumAnalyzer/SpectrumAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,21 @@ BEGIN_VSA_NAMESPACE
/**
* @class SpectrumAnalyzer
* @brief runs an fft in a time slice thread over whatever data it gets
*/
*/
class SpectrumAnalyzer : public juce::TimeSliceClient
{
class SpectrumAnalyzerTimeSliceThread;

public:
explicit SpectrumAnalyzer(AudioBufferFifo<float> &source);
explicit SpectrumAnalyzer(AudioBufferFifo<double> &source);
~SpectrumAnalyzer() override;
explicit SpectrumAnalyzer(AudioBufferFifo<float> &source, juce::TimeSliceThread &thread, int fftSize = 11);
explicit SpectrumAnalyzer(AudioBufferFifo<double> &source, juce::TimeSliceThread &thread, int fftSize = 11);
~SpectrumAnalyzer() override = default;

SpectrumAnalyzerCurve::LockedCurve getAnalyzerCurve();

// juce::TimeSliceClient
int useTimeSlice() override;

void startThread();
void suspendThread();

private:
bool populateConduitBuffer();
void init();
Expand All @@ -44,15 +43,12 @@ class SpectrumAnalyzer : public juce::TimeSliceClient

std::array<SpectrumAnalyzerBuffer, 5> m_buffers;


juce::dsp::FFT m_fft{ 11 };
juce::dsp::WindowingFunction<float> m_windowingFunction{ static_cast<std::size_t>(m_fft.getSize()), juce::dsp::WindowingFunction<float>::hann, true };
juce::dsp::FFT m_fft;
juce::dsp::WindowingFunction<float> m_windowingFunction{ static_cast<std::size_t>(m_fft.getSize()),
juce::dsp::WindowingFunction<float>::hann, true };

SpectrumAnalyzerCurve m_analyzerCurve{ m_fft.getSize() };

class SpectrumAnalyzerTimeSliceThread;
juce::SharedResourcePointer<SpectrumAnalyzerTimeSliceThread> m_thread;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SpectrumAnalyzer)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@

//-----------------------------------------------------------------------------

vsa::SpectrumAnalyzerComponent::SpectrumAnalyzerComponent(AudioBufferFifo<float> &source)
: m_fft(source)
vsa::SpectrumAnalyzerComponent::SpectrumAnalyzerComponent(AudioBufferFifo<float> &source, juce::TimeSliceThread &thread, int fftSize)
: m_fft(source, thread, fftSize)
{
}

//-----------------------------------------------------------------------------

vsa::SpectrumAnalyzerComponent::SpectrumAnalyzerComponent(AudioBufferFifo<double>& source)
: m_fft(source)
vsa::SpectrumAnalyzerComponent::SpectrumAnalyzerComponent(AudioBufferFifo<double> &source, juce::TimeSliceThread &thread, int fftSize)
: m_fft(source, thread, fftSize)
{
}

Expand Down Expand Up @@ -41,14 +41,8 @@ float vsa::SpectrumAnalyzerComponent::getPreSmoothingPathHeightMultiplier(float

void vsa::SpectrumAnalyzerComponent::paintAnalyzerCurve(juce::Graphics &g, const juce::Path &p)
{
const auto gradient{
juce::ColourGradient::vertical(
juce::Colours::red,
0.0f,
juce::Colours::red.withAlpha(0.25f),
static_cast<float>(getHeight())
)
};
const auto gradient{ juce::ColourGradient::vertical(juce::Colours::red, 0.0f, juce::Colours::red.withAlpha(0.25f),
static_cast<float>(getHeight())) };
g.setGradientFill(gradient);

g.fillPath(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ BEGIN_VSA_NAMESPACE
* @brief Display a spectrum analyzer from data grabbed from AudioBufferFifo
*
* @see AudioBufferFifo
*/
*/
class SpectrumAnalyzerComponent
: public juce::Component
, public juce::Timer
{
public:
explicit SpectrumAnalyzerComponent(AudioBufferFifo<float> &source);
explicit SpectrumAnalyzerComponent(AudioBufferFifo<double> &source);
explicit SpectrumAnalyzerComponent(AudioBufferFifo<float> &source, juce::TimeSliceThread &thread, int fftSize = 11);
explicit SpectrumAnalyzerComponent(AudioBufferFifo<double> &source, juce::TimeSliceThread &thread, int fftSize = 11);
~SpectrumAnalyzerComponent() override;

void paint(juce::Graphics &g) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ static float getParameterValueFromFrequency(const float frequency)

const float num = std::log(frequency - MinFrequency);
const float den = std::log(MaxFrequency - MinFrequency);
return std::powf(num / den, 2.0f);
return std::pow(num / den, 2.0f);
}

//-----------------------------------------------------------------------------
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,22 @@ m_fifo.pushAudioData(buffer); // push all audio data into the fifo
vsa::SpectrumAnalyzerComponent spectrumAnalyzer{ fifo };
addAndMakeVisible(spectrumAnalyzer);
```

# Adding it to Your Project

SpectrumAnalyzer is organized as a JUCE module.
To use it in your project include the `Modules` directory in `CMakeLists.txt`:

```cmake
add_subdirectory("SpectrumAnalyzer/Modules")
```

Link to the following targets:

```cmake
target_link_libraries("Project"
PRIVATE
vsa::vsa
vsa::vsa_spectrum_analyzer
)
```
7 changes: 7 additions & 0 deletions Tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ FetchContent_MakeAvailable(gtest)

add_executable(Tests Tests.cpp)

target_compile_definitions(
Tests
PUBLIC
JUCE_WEB_BROWSER=0
JUCE_USE_CURL=0
)

target_link_libraries(
Tests

Expand Down
4 changes: 2 additions & 2 deletions Tests/SpectrumAnalyzerTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ TEST(SpectrumAnalyzerTests, SpectrumAnalyzerBufferTest)

float f{ 0.0f };
int loopCount2{ Size };
for(auto f : fftSpan)
for(auto ff : fftSpan)
{
loopCount2--;
EXPECT_EQ(f, f);
EXPECT_EQ(ff, f);
f += 1.0f;
}
EXPECT_EQ(loopCount2, 0);
Expand Down
Loading