80 lines
2.8 KiB
C++
80 lines
2.8 KiB
C++
#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
|