FMOp.hpp (4137B)
1 #pragma once 2 3 #include "bogaudio.hpp" 4 #include "dsp/envelope.hpp" 5 #include "dsp/filters/resample.hpp" 6 #include "dsp/oscillator.hpp" 7 #include "dsp/signal.hpp" 8 9 using namespace bogaudio::dsp; 10 11 extern Model* modelFMOp; 12 13 namespace bogaudio { 14 15 struct FMOp : BGModule { 16 enum ParamsIds { 17 RATIO_PARAM, 18 FINE_PARAM, 19 ATTACK_PARAM, 20 DECAY_PARAM, 21 SUSTAIN_PARAM, 22 RELEASE_PARAM, 23 DEPTH_PARAM, 24 FEEDBACK_PARAM, 25 LEVEL_PARAM, 26 ENV_TO_LEVEL_PARAM, 27 ENV_TO_FEEDBACK_PARAM, 28 ENV_TO_DEPTH_PARAM, 29 NUM_PARAMS 30 }; 31 32 enum InputsIds { 33 SUSTAIN_INPUT, 34 DEPTH_INPUT, 35 FEEDBACK_INPUT, 36 LEVEL_INPUT, 37 PITCH_INPUT, 38 GATE_INPUT, 39 FM_INPUT, 40 NUM_INPUTS 41 }; 42 43 enum OutputsIds { 44 AUDIO_OUTPUT, 45 NUM_OUTPUTS 46 }; 47 48 enum LightsIds { 49 ATTACK_LIGHT, 50 DECAY_LIGHT, 51 SUSTAIN_LIGHT, 52 RELEASE_LIGHT, 53 NUM_LIGHTS 54 }; 55 56 static constexpr float amplitude = 5.0f; 57 static constexpr int oversample = 8; 58 static constexpr float oversampleMixIncrement = 0.01f; 59 60 struct Engine { 61 float feedback = 0.0f; 62 float feedbackDelayedSample = 0.0f; 63 float depth = 0.0f; 64 float level = 0.0f; 65 bool envelopeOn = false; 66 float maxFrequency = 0.0f; 67 float buffer[oversample]; 68 float oversampleMix = 0.0f; 69 dsp::ADSR envelope; 70 Phasor phasor; 71 SineTableOscillator sineTable; 72 CICDecimator decimator; 73 Trigger gateTrigger; 74 bogaudio::dsp::SlewLimiter feedbackSL; 75 bogaudio::dsp::SlewLimiter depthSL; 76 bogaudio::dsp::SlewLimiter levelSL; 77 bogaudio::dsp::SlewLimiter sustainSL; 78 Amplifier amplifier; 79 80 Engine() : envelope(true) {} 81 82 void reset(); 83 void sampleRateChange(); 84 }; 85 86 SineTableOscillator::Interpolation _interpolation = SineTableOscillator::INTERPOLATION_OFF; 87 bool _linearLevel = false; 88 bool _antiAliasFeedback = true; 89 bool _antiAliasDepth = true; 90 bool _levelEnvelopeOn = false; 91 bool _feedbackEnvelopeOn = false; 92 bool _depthEnvelopeOn = false; 93 int _attackLightSum; 94 int _decayLightSum; 95 int _sustainLightSum; 96 int _releaseLightSum; 97 Engine* _engines[maxChannels] {}; 98 99 struct RatioParamQuantity : ParamQuantity { 100 float getDisplayValue() override; 101 void setDisplayValue(float v) override; 102 }; 103 104 struct LevelParamQuantity : AmplifierParamQuantity { 105 bool isLinear() override; 106 }; 107 108 FMOp() { 109 config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); 110 configParam<RatioParamQuantity>(RATIO_PARAM, -1.0f, 1.0f, 0.0f, "Frequency ratio"); 111 configParam(FINE_PARAM, -1.0f, 1.0f, 0.0f, "Fine tune", " cents", 0.0f, 100.0f); 112 configParam<EnvelopeSegmentParamQuantity>(ATTACK_PARAM, 0.0f, 1.0f, 0.141421f, "Attack", " s"); 113 configParam<EnvelopeSegmentParamQuantity>(DECAY_PARAM, 0.0f, 1.0f, SQUARE_ROOT_ONE_TENTH, "Decay", " s"); 114 configParam(SUSTAIN_PARAM, 0.0f, 1.0f, 1.0f, "Sustain", "%", 0.0f, 100.0f); 115 configParam<EnvelopeSegmentParamQuantity>(RELEASE_PARAM, 0.0f, 1.0f, SQUARE_ROOT_ONE_TENTH, "Release", " s"); 116 configParam(DEPTH_PARAM, 0.0f, 1.0f, 0.0f, "FM depth", "%", 0.0f, 100.0f); 117 configParam(FEEDBACK_PARAM, 0.0f, 1.0f, 0.0f, "Feedback", "%", 0.0f, 100.0f); 118 configParam<LevelParamQuantity>(LEVEL_PARAM, 0.0f, 1.0f, 1.0f, "Level"); 119 configButton(ENV_TO_LEVEL_PARAM, "Level follows envelope"); 120 configButton(ENV_TO_FEEDBACK_PARAM, "Feedback follows envelope"); 121 configButton(ENV_TO_DEPTH_PARAM, "FM depth follows envelope"); 122 123 configInput(SUSTAIN_INPUT, "Sustain CV"); 124 configInput(DEPTH_INPUT, "Depth CV"); 125 configInput(FEEDBACK_INPUT, "Feedback CV"); 126 configInput(LEVEL_INPUT, "Level CV"); 127 configInput(PITCH_INPUT, "Pitch (1V/octave)"); 128 configInput(GATE_INPUT, "Gate"); 129 configInput(FM_INPUT, "Frequency modulation"); 130 131 configOutput(AUDIO_OUTPUT, "Signal"); 132 } 133 134 void reset() override; 135 void sampleRateChange() override; 136 json_t* saveToJson(json_t* root) override; 137 void loadFromJson(json_t* root) override; 138 bool active() override; 139 int channels() override; 140 void addChannel(int c) override; 141 void removeChannel(int c) override; 142 void modulate() override; 143 void modulateChannel(int c) override; 144 void processAlways(const ProcessArgs& args) override; 145 void processChannel(const ProcessArgs& args, int c) override; 146 void postProcessAlways(const ProcessArgs& args) override; 147 }; 148 149 } // namespace bogaudio