feat(gui): add GUI components and displays
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
#include "FilterDisplay.h"
|
||||
|
||||
namespace serum
|
||||
{
|
||||
|
||||
float FilterDisplay::magnitude (float freqHz, float cutoffHz, float res, int type)
|
||||
{
|
||||
const float w = (cutoffHz > 1.0f) ? freqHz / cutoffHz : 1.0f;
|
||||
const float q = 0.6f + res * 14.0f;
|
||||
const float w2 = w * w;
|
||||
const float denom = std::sqrt ((1.0f - w2) * (1.0f - w2) + (w / q) * (w / q));
|
||||
|
||||
switch ((FilterModel) type)
|
||||
{
|
||||
case FilterModel::LadderHP: return (denom > 1e-6f) ? w2 / denom : 0.0f;
|
||||
case FilterModel::LadderBP: return (denom > 1e-6f) ? (w / q) / denom : 0.0f;
|
||||
case FilterModel::Screamer: return (denom > 1e-6f) ? (w / (q * 0.7f)) / denom : 0.0f;
|
||||
case FilterModel::Comb:
|
||||
return 0.5f + 0.5f * std::cos (2.0f * juce::MathConstants<float>::pi * freqHz / cutoffHz);
|
||||
case FilterModel::Formant:
|
||||
{
|
||||
float m = 0.0f;
|
||||
const float fc[3] = { cutoffHz * 0.5f, cutoffHz * 1.6f, cutoffHz * 3.2f };
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
const float ww = freqHz / fc[i];
|
||||
const float dd = std::sqrt ((1.0f - ww * ww) * (1.0f - ww * ww) + (ww / q) * (ww / q));
|
||||
m += (ww / q) / (dd + 1e-6f);
|
||||
}
|
||||
return m / 3.0f;
|
||||
}
|
||||
case FilterModel::Diode:
|
||||
default:
|
||||
return (denom > 1e-6f) ? 1.0f / denom : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void FilterDisplay::setParams (int t, float c, float r, float d, int s)
|
||||
{
|
||||
type = t; cutoff = c; res = r; drive = d; slope = s;
|
||||
}
|
||||
|
||||
void FilterDisplay::paint (juce::Graphics& g)
|
||||
{
|
||||
const auto b = getLocalBounds().toFloat();
|
||||
g.setColour (juce::Colours::black.withAlpha (0.4f));
|
||||
g.fillRoundedRectangle (b, 4.0f);
|
||||
g.setColour (theme::outline);
|
||||
g.drawRoundedRectangle (b.reduced (0.5f), 4.0f, 1.0f);
|
||||
|
||||
if (! enabled)
|
||||
return;
|
||||
|
||||
const float cutoffHz = maps::cutoffToHz (cutoff);
|
||||
const int n = 300;
|
||||
juce::Path path;
|
||||
path.startNewSubPath (b.getX() + 4.0f, b.getBottom() - 4.0f);
|
||||
|
||||
for (int i = 0; i <= n; ++i)
|
||||
{
|
||||
const float logF = std::log10 (20.0f) + ((float) i / (float) n) * (std::log10 (20000.0f) - std::log10 (20.0f));
|
||||
const float freq = std::pow (10.0f, logF);
|
||||
const float mag = magnitude (freq, cutoffHz, res, type);
|
||||
const float db = juce::Decibels::gainToDecibels (mag + 1e-5f);
|
||||
const float x = b.getX() + 4.0f + ((float) i / (float) n) * (b.getWidth() - 8.0f);
|
||||
const float y = juce::jmap (db, -30.0f, 12.0f, b.getBottom() - 4.0f, b.getY() + 4.0f);
|
||||
path.lineTo (x, y);
|
||||
}
|
||||
|
||||
path.lineTo (b.getRight() - 4.0f, b.getBottom() - 4.0f);
|
||||
path.closeSubPath();
|
||||
|
||||
g.setColour (theme::accent.withAlpha (0.25f));
|
||||
g.fillPath (path);
|
||||
g.setColour (theme::accent);
|
||||
g.strokePath (path, juce::PathStrokeType (1.5f));
|
||||
}
|
||||
|
||||
} // namespace serum
|
||||
Reference in New Issue
Block a user