95 lines
2.5 KiB
C++
95 lines
2.5 KiB
C++
#pragma once
|
|
#include <JuceHeader.h>
|
|
|
|
enum class BlepWave : int { Sine = 0, Saw, Square, Triangle };
|
|
|
|
class BlepOsc
|
|
{
|
|
public:
|
|
void prepare (double sampleRate)
|
|
{
|
|
sr = juce::jmax (1.0, sampleRate);
|
|
setFrequency ((float) freq);
|
|
resetPhase();
|
|
}
|
|
void setWave (BlepWave w) { wave = w; }
|
|
void setFrequency (float f)
|
|
{
|
|
const float nyquist = 0.5f * (float) sr;
|
|
freq = juce::jlimit (0.0f, juce::jmax (0.0f, nyquist), f);
|
|
inc = freq / (float) sr;
|
|
}
|
|
void resetPhase (float p = 0.0f)
|
|
{
|
|
phase = juce::jlimit (0.0f, 1.0f, p);
|
|
z1 = 0.0f;
|
|
}
|
|
|
|
inline float process()
|
|
{
|
|
// phase in [0..1)
|
|
float out = 0.0f;
|
|
float t = phase;
|
|
phase += inc;
|
|
if (phase >= 1.0f) phase -= 1.0f;
|
|
|
|
switch (wave)
|
|
{
|
|
case BlepWave::Sine: out = std::sin (2.0f * juce::MathConstants<float>::pi * t); break;
|
|
|
|
case BlepWave::Saw:
|
|
{
|
|
// naive saw in [-1..1]
|
|
float s = 2.0f * t - 1.0f;
|
|
// apply BLEP at the discontinuity crossing t=0
|
|
s -= polyBlep (t, inc);
|
|
out = s;
|
|
} break;
|
|
|
|
case BlepWave::Square:
|
|
{
|
|
float s = (t < 0.5f ? 1.0f : -1.0f);
|
|
// rising edge at 0.0, falling at 0.5
|
|
s += polyBlep (t, inc) - polyBlep (std::fmod (t + 0.5f, 1.0f), inc);
|
|
out = s;
|
|
} break;
|
|
|
|
case BlepWave::Triangle:
|
|
{
|
|
// integrate the BLEP square for band-limited tri
|
|
float sq = (t < 0.5f ? 1.0f : -1.0f);
|
|
sq += polyBlep (t, inc) - polyBlep (std::fmod (t + 0.5f, 1.0f), inc);
|
|
// leaky integrator to keep DC under control
|
|
z1 = z1 + (sq - z1) * inc;
|
|
out = 2.0f * z1; // scale
|
|
} break;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
private:
|
|
// PolyBLEP as in Valimäki/Huovilainen
|
|
static inline float polyBlep (float t, float dt)
|
|
{
|
|
// t in [0..1)
|
|
if (t < dt)
|
|
{
|
|
t /= dt;
|
|
return t + t - t * t - 1.0f;
|
|
}
|
|
else if (t > 1.0f - dt)
|
|
{
|
|
t = (t - 1.0f) / dt;
|
|
return t * t + t + t + 1.0f;
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
double sr = 44100.0;
|
|
float freq = 440.0f, inc = 440.0f / 44100.0f;
|
|
float phase = 0.0f;
|
|
float z1 = 0.0f;
|
|
BlepWave wave = BlepWave::Sine;
|
|
};
|