//*********************************************************************************************** //Impromptu Modular: Modules for VCV Rack by Marc Boulé // //This is code from the Fundamental plugin by Andrew Belt //See ./LICENSE.txt for all licenses and see below for the filter code license //*********************************************************************************************** #ifndef FUNDAMENTAL_UTIL_HPP #define FUNDAMENTAL_UTIL_HPP #include "rack.hpp" #include "dsp/functions.hpp" #include "dsp/resampler.hpp" #include "dsp/ode.hpp" #include "dsp/filter.hpp" #include "ImpromptuModular.hpp" using namespace rack; namespace rack_plugin_ImpromptuModular { extern float sawTable[2048];// see end of file extern float triTable[2048];// see end of file // From Fundamental VCF struct LadderFilter { float omega0; float resonance = 1.0f; float state[4]; float input; float lowpass; float highpass; LadderFilter() { reset(); setCutoff(0.f); } void reset() { for (int i = 0; i < 4; i++) { state[i] = 0.f; } } void setCutoff(float cutoff) { omega0 = 2.f*M_PI * cutoff; } void process(float input, float dt); }; // From Fundamental VCO.cpp //template static const int OVERSAMPLE = 8; static const int QUALITY = 8; struct VoltageControlledOscillator { bool analog = false; bool soft = false; float lastSyncValue = 0.0f; float phase = 0.0f; float freq; float pw = 0.5f; float pitch; bool syncEnabled = false; bool syncDirection = false; Decimator sinDecimator; Decimator triDecimator; Decimator sawDecimator; Decimator sqrDecimator; RCFilter sqrFilter; // For analog detuning effect float pitchSlew = 0.0f; int pitchSlewIndex = 0; float sinBuffer[OVERSAMPLE] = {}; float triBuffer[OVERSAMPLE] = {}; float sawBuffer[OVERSAMPLE] = {}; float sqrBuffer[OVERSAMPLE] = {}; void setPitch(float pitchKnob, float pitchCv); void setPulseWidth(float pulseWidth); void process(float deltaTime, float syncValue); float sin() { return sinDecimator.process(sinBuffer); } float tri() { return triDecimator.process(triBuffer); } float saw() { return sawDecimator.process(sawBuffer); } float sqr() { return sqrDecimator.process(sqrBuffer); } float light() { return sinf(2*M_PI * phase); } }; // From Fundamental LFO.cpp struct LowFrequencyOscillator { float phase = 0.0f; float pw = 0.5f; float freq = 1.0f; bool offset = false; bool invert = false; Trigger resetTrigger; LowFrequencyOscillator() {} void setPitch(float pitch) { pitch = fminf(pitch, 8.0f); freq = powf(2.0f, pitch); } void setPulseWidth(float pw_) { const float pwMin = 0.01f; pw = clamp(pw_, pwMin, 1.0f - pwMin); } void setReset(float reset) { if (resetTrigger.process(reset / 0.01f)) { phase = 0.0f; } } void step(float dt) { float deltaPhase = fminf(freq * dt, 0.5f); phase += deltaPhase; if (phase >= 1.0f) phase -= 1.0f; } float sin() { if (offset) return 1.0f - cosf(2*M_PI * phase) * (invert ? -1.0f : 1.0f); else return sinf(2*M_PI * phase) * (invert ? -1.0f : 1.0f); } float tri(float x) { return 4.0f * fabsf(x - roundf(x)); } float tri() { if (offset) return tri(invert ? phase - 0.5f : phase); else return -1.0f + tri(invert ? phase - 0.25f : phase - 0.75f); } float saw(float x) { return 2.0f * (x - roundf(x)); } float saw() { if (offset) return invert ? 2.0f * (1.0f - phase) : 2.0f * phase; else return saw(phase) * (invert ? -1.0f : 1.0f); } float sqr() { float sqr = (phase < pw) ^ invert ? 1.0f : -1.0f; return offset ? sqr + 1.0f : sqr; } float light() { return sinf(2*M_PI * phase); } }; } // namespace rack_plugin_ImpromptuModular #endif