BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

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