#pragma once /** * SawOscillator * * Generates a saw wave from 0..1 * Good features: * frequency may be adjusted while running without glitches * can generate a quadrature output * can be configured to do positive and negative frequency */ template class SawOscillatorParams; template class SawOscillatorState; template class SawOscillator { public: static void setFrequency(SawOscillatorParams& params, T freq); static T run(SawOscillatorState& state, const SawOscillatorParams& params); /** * gets the regular output and the quadrature output */ static void runQuadrature(T& out, T& outQuad, SawOscillatorState& state, const SawOscillatorParams& params); }; template inline T SawOscillator::run(SawOscillatorState& state, const SawOscillatorParams& params) { T ret = state.phase; state.phase += params.phaseIncrement; if (state.phase >= 1) { state.phase -= 1; } if (frequencyCanBeNegative && (state.phase < 0)) { state.phase += 1; } return ret; } template inline void SawOscillator::runQuadrature(T& out, T& outQuad, SawOscillatorState& state, const SawOscillatorParams& params) { out = run(state, params); T quad = out + T(.25); if (quad >= 1) { quad -= 1; } outQuad = quad; } template inline void SawOscillator::setFrequency(SawOscillatorParams& params, T freq) { if (frequencyCanBeNegative) { assert(freq >= -.5 && freq < .5); } else { assert(freq >= 0 && freq < .5); } params.phaseIncrement = freq; } template class SawOscillatorParams { public: T phaseIncrement = 0; }; template class SawOscillatorState { public: /** * phase increments from 0...1 */ T phase = 0; };