100 lines
3.3 KiB
C++
100 lines
3.3 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
GraphComponent.h
|
|
Created: 4 Jul 2025 11:43:57pm
|
|
Author: timot
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm> // for std::minmax_element
|
|
#include "AudioBufferQueue.h"
|
|
|
|
//==============================================================================
|
|
template <typename SampleType>
|
|
class GraphComponent : public juce::Component,
|
|
private juce::Timer
|
|
{
|
|
public:
|
|
//==============================================================================
|
|
GraphComponent(SampleType minIn, SampleType maxIn, int numPointsIn)
|
|
: min(minIn), max(maxIn), numPoints(numPointsIn)
|
|
{
|
|
x.resize(numPoints);
|
|
y.resize(numPoints);
|
|
setFramesPerSecond(30);
|
|
// func will be set via setFunction before paint; provide a safe default
|
|
func = [](SampleType) noexcept { return SampleType(); };
|
|
}
|
|
|
|
//==============================================================================
|
|
void setFramesPerSecond(int framesPerSecond)
|
|
{
|
|
jassert(framesPerSecond > 0 && framesPerSecond < 1000);
|
|
startTimerHz(framesPerSecond);
|
|
}
|
|
|
|
//==============================================================================
|
|
void setFunction(const std::function<SampleType(SampleType)>& f) { func = f; }
|
|
|
|
//==============================================================================
|
|
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 < (size_t)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;
|
|
|
|
g.drawLine({ px_prev, py_prev, px_next, py_next });
|
|
}
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
void resized() override {}
|
|
|
|
private:
|
|
//==============================================================================
|
|
std::vector<SampleType> x, y;
|
|
SampleType minY{ SampleType() }, maxY{ SampleType(1) };
|
|
SampleType min{}, max{};
|
|
int numPoints{};
|
|
std::function<SampleType(SampleType)> func;
|
|
bool hasData = false;
|
|
|
|
//==============================================================================
|
|
void timerCallback() override
|
|
{
|
|
const SampleType step = (max - min) / (SampleType)(numPoints - 1);
|
|
|
|
for (int i = 0; i < numPoints; i++)
|
|
{
|
|
x[(size_t)i] = min + step * (SampleType)i;
|
|
y[(size_t)i] = func(x[(size_t)i]);
|
|
}
|
|
|
|
auto p = std::minmax_element(y.begin(), y.end());
|
|
minY = *p.first;
|
|
maxY = *p.second;
|
|
|
|
hasData = true;
|
|
repaint();
|
|
}
|
|
};
|