/* ============================================================================== GraphComponent.h Created: 4 Jul 2025 11:43:57pm Author: timot ============================================================================== */ #pragma once #include "AudioBufferQueue.h" //============================================================================== template class GraphComponent : public juce::Component, private juce::Timer { public: //============================================================================== GraphComponent(SampleType min, SampleType max, int numPoints): func(func), min(min), max(max), numPoints(numPoints) { x.resize(numPoints); y.resize(numPoints); setFramesPerSecond(30); } //============================================================================== void setFramesPerSecond(int framesPerSecond) { jassert(framesPerSecond > 0 && framesPerSecond < 1000); startTimerHz(framesPerSecond); } //============================================================================== void setFunction(const std::function& func) { this->func = func; } //============================================================================== void paint(juce::Graphics& g) override { g.fillAll(juce::Colours::black); g.setColour(juce::Colours::white); auto area = getLocalBounds(); if (hasData && area.isFinite()) { auto h = (SampleType)area.getHeight(); auto w = (SampleType)area.getWidth(); for (size_t i = 1; i < numPoints; ++i) { auto px_prev = ((x[i - 1] - min) / (max - min)) * w; auto py_prev = h - ((y[i - 1] - minY) / (maxY - minY)) * h; auto px_next = ((x[i] - min) / (max - min)) * w; auto py_next = h - ((y[i] - minY) / (maxY - minY)) * h; juce::Line line(juce::Point(px_prev, py_prev), juce::Point(px_next, py_next)); g.drawLine(line); } } } //============================================================================== void resized() override {} private: //============================================================================== std::vector x, y; SampleType minY, maxY; SampleType min, max; int numPoints; std::function func; bool hasData = false; //============================================================================== void timerCallback() override { float step = (max - min) / (SampleType)(numPoints - 1); for (int i = 0; i < numPoints; i++) { x[i] = min + step * (SampleType)i; y[i] = func(x[i]); } auto p = minmax_element(y.begin(), y.end()); minY = *p.first; maxY = *p.second; hasData = true; repaint(); } //============================================================================== /*static void plot(const SampleType* data, size_t numSamples, juce::Graphics& g, juce::Rectangle rect, SampleType scaler = SampleType(1), SampleType offset = SampleType(0)) { auto w = rect.getWidth(); auto h = rect.getHeight(); auto right = rect.getRight(); auto center = rect.getBottom() - offset; auto gain = h * scaler; for (size_t i = 1; i < numSamples; ++i) g.drawLine({ juce::jmap(SampleType(i - 1), SampleType(0), SampleType(numSamples - 1), SampleType(right - w), SampleType(right)), center - gain * data[i - 1], juce::jmap(SampleType(i), SampleType(0), SampleType(numSamples - 1), SampleType(right - w), SampleType(right)), center - gain * data[i] }); }*/ };