#pragma once #include #include namespace monostep { enum class Waveform : int { sine = 0, triangle = 1, saw = 2, square = 3 }; inline float frac (float x) { return x - std::floor (x); } inline float polyBlep (float t, float dt) { if (t < dt) { t /= dt; return t + t - t * t - 1.0f; } if (t > 1.0f - dt) { t = (t - 1.0f) / dt; return t * t + t + t + 1.0f; } return 0.0f; } inline float renderWave (Waveform w, float phase, float inc) { switch (w) { case Waveform::sine: return std::sin (phase * 6.283185307179586f); case Waveform::triangle: { const float f = frac (phase); return 4.0f * std::min (f, 1.0f - f) - 1.0f; } case Waveform::saw: { const float f = frac (phase); return (2.0f * f - 1.0f) - polyBlep (f, inc); } case Waveform::square: { const float f = frac (phase); float v = (f < 0.5f) ? 1.0f : -1.0f; v += polyBlep (f, inc); v -= polyBlep (frac (f + 0.5f), inc); return v; } } return 0.0f; } } // namespace monostep