BogaudioModules

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

XCO.hpp (6443B)


      1 #pragma once
      2 
      3 #include "bogaudio.hpp"
      4 #include "dsp/filters/resample.hpp"
      5 #include "dsp/oscillator.hpp"
      6 #include "dsp/signal.hpp"
      7 
      8 using namespace bogaudio::dsp;
      9 
     10 extern Model* modelXCO;
     11 
     12 namespace bogaudio {
     13 
     14 struct XCO : BGModule {
     15 	enum ParamsIds {
     16 		FREQUENCY_PARAM,
     17 		FINE_PARAM,
     18 		SLOW_PARAM,
     19 		FM_DEPTH_PARAM,
     20 		FM_TYPE_PARAM,
     21 		SQUARE_PW_PARAM,
     22 		SQUARE_PHASE_PARAM,
     23 		SQUARE_MIX_PARAM,
     24 		SAW_SATURATION_PARAM,
     25 		SAW_PHASE_PARAM,
     26 		SAW_MIX_PARAM,
     27 		TRIANGLE_SAMPLE_PARAM,
     28 		TRIANGLE_PHASE_PARAM,
     29 		TRIANGLE_MIX_PARAM,
     30 		SINE_FEEDBACK_PARAM,
     31 		SINE_PHASE_PARAM,
     32 		SINE_MIX_PARAM,
     33 		NUM_PARAMS
     34 	};
     35 
     36 	enum InputsIds {
     37 		FM_INPUT,
     38 		FM_DEPTH_INPUT,
     39 		SQUARE_PW_INPUT,
     40 		SQUARE_PHASE_INPUT,
     41 		SQUARE_MIX_INPUT,
     42 		SAW_SATURATION_INPUT,
     43 		SAW_PHASE_INPUT,
     44 		SAW_MIX_INPUT,
     45 		TRIANGLE_SAMPLE_INPUT,
     46 		TRIANGLE_PHASE_INPUT,
     47 		TRIANGLE_MIX_INPUT,
     48 		SINE_FEEDBACK_INPUT,
     49 		SINE_PHASE_INPUT,
     50 		SINE_MIX_INPUT,
     51 		PITCH_INPUT,
     52 		SYNC_INPUT,
     53 		NUM_INPUTS
     54 	};
     55 
     56 	enum OutputsIds {
     57 		SQUARE_OUTPUT,
     58 		SAW_OUTPUT,
     59 		TRIANGLE_OUTPUT,
     60 		SINE_OUTPUT,
     61 		MIX_OUTPUT,
     62 		NUM_OUTPUTS
     63 	};
     64 
     65 	enum Clipping {
     66 		NO_CLIPPING = 0,
     67 		COMP_CLIPPING,
     68 		SOFT_CLIPPING,
     69 		HARD_CLIPPING
     70 	};
     71 
     72 	struct Engine {
     73 		static constexpr int oversample = 8;
     74 
     75 		float frequency = 0.0f;
     76 		float baseVOct = 0.0f;
     77 		float baseHz = 0.0f;
     78 		float fmDepth = 0.0f;
     79 		float triangleSampleWidth = 0.0f;
     80 		float sineFeedback = 0.0f;
     81 		float sineOMix = 0.0f;
     82 		float sineFeedbackDelayedSample = 0.0f;
     83 		Phasor::phase_delta_t squarePhaseOffset = 0.0f;
     84 		Phasor::phase_delta_t sawPhaseOffset = 0.0f;
     85 		Phasor::phase_delta_t trianglePhaseOffset = 0.0f;
     86 		Phasor::phase_delta_t sinePhaseOffset = 0.0f;
     87 		float squareMix = 1.0f;
     88 		float sawMix = 1.0f;
     89 		float triangleMix = 1.0f;
     90 		float sineMix = 1.0f;
     91 		float lastCycle = 0.0f;
     92 		float minMix = 0.0f;
     93 		float maxMix = 0.0f;
     94 		float mixScale = 0.25;
     95 
     96 		Phasor phasor;
     97 		BandLimitedSquareOscillator square;
     98 		BandLimitedSawOscillator saw;
     99 		TriangleOscillator triangle;
    100 		SineTableOscillator sine;
    101 		CICDecimator squareDecimator;
    102 		CICDecimator sawDecimator;
    103 		CICDecimator triangleDecimator;
    104 		CICDecimator sineDecimator;
    105 		float squareBuffer[oversample];
    106 		float sawBuffer[oversample];
    107 		float triangleBuffer[oversample];
    108 		float sineBuffer[oversample];
    109 		PositiveZeroCrossing syncTrigger;
    110 		Saturator saturator;
    111 
    112 		bogaudio::dsp::SlewLimiter fmDepthSL;
    113 		bogaudio::dsp::SlewLimiter squarePulseWidthSL;
    114 		bogaudio::dsp::SlewLimiter sawSaturationSL;
    115 		bogaudio::dsp::SlewLimiter triangleSampleWidthSL;
    116 		bogaudio::dsp::SlewLimiter sineFeedbackSL;
    117 		bogaudio::dsp::SlewLimiter squareMixSL;
    118 		bogaudio::dsp::SlewLimiter sawMixSL;
    119 		bogaudio::dsp::SlewLimiter triangleMixSL;
    120 		bogaudio::dsp::SlewLimiter sineMixSL;
    121 
    122 		Engine() {
    123 			saw.setQuality(12);
    124 			square.setQuality(12);
    125 		}
    126 
    127 		void reset();
    128 		void sampleRateChange(float sampleRate);
    129 		void setFrequency(float frequency);
    130 	};
    131 
    132 	const float amplitude = 5.0f;
    133 	const float _slowModeOffset = -7.0f;
    134 	const float sineOversampleMixIncrement = 0.01f;
    135 	float _oversampleThreshold = 0.0f;
    136 	bool _slowMode = false;
    137 	bool _fmLinearMode = false;
    138 	bool _dcCorrection = true;
    139 	Clipping _clippingMode = COMP_CLIPPING;
    140 	Engine* _engines[maxChannels] {};
    141 
    142 	struct XCOFrequencyParamQuantity : FrequencyParamQuantity {
    143 		float offset() override;
    144 	};
    145 
    146 	XCO() {
    147 		config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
    148 		configParam<XCOFrequencyParamQuantity>(FREQUENCY_PARAM, -3.0f, 6.0f, 0.0f, "Frequency", " Hz");
    149 		configParam(FINE_PARAM, -1.0f, 1.0f, 0.0f, "Fine tune", " cents", 0.0f, 100.0f);
    150 		configButton(SLOW_PARAM, "Slow mode");
    151 		configParam(FM_DEPTH_PARAM, 0.0f, 1.0f, 0.0f, "FM depth", "%", 0.0f, 100.0f);
    152 		configSwitch(FM_TYPE_PARAM, 0.0f, 1.0f, 1.0f, "FM mode", {"Linear FM", "Exponential FM"});
    153 		configParam(SQUARE_PW_PARAM, -0.97f, 0.97f, 0.0f, "Square wave pulse width", "%", 0.0f, 100.0f);
    154 		configParam(SQUARE_PHASE_PARAM, -1.0f, 1.0f, 0.0f, "Square wave phase", "º", 0.0f, 180.0f);
    155 		configParam(SQUARE_MIX_PARAM, 0.0f, 1.0f, 1.0f, "Square wave mix", "%", 0.0f, 100.0f);
    156 		configParam(SAW_SATURATION_PARAM, 0.0f, 1.0f, 0.0f, "Saw wave saturation", "%", 0.0f, 100.0f);
    157 		configParam(SAW_PHASE_PARAM, -1.0f, 1.0f, 0.0f, "Saw wave phase", "º", 0.0f, 180.0f);
    158 		configParam(SAW_MIX_PARAM, 0.0f, 1.0f, 1.0f, "Saw wave mix", "%", 0.0f, 100.0f);
    159 		configParam(TRIANGLE_SAMPLE_PARAM, 0.0f, 1.0f, 0.0f, "Triangle wave sampling", "%", 0.0f, 100.0f);
    160 		configParam(TRIANGLE_PHASE_PARAM, -1.0f, 1.0f, 0.0f, "Triangle wave phase", "º", 0.0f, 180.0f);
    161 		configParam(TRIANGLE_MIX_PARAM, 0.0f, 1.0f, 1.0f, "Triangle wave mix", "%", 0.0f, 100.0f);
    162 		configParam(SINE_FEEDBACK_PARAM, 0.0f, 1.0f, 0.0f, "Sine wave feedback", "%", 0.0f, 100.0f);
    163 		configParam(SINE_PHASE_PARAM, -1.0f, 1.0f, 0.0f, "Sine wave phase", "º", 0.0f, 180.0f);
    164 		configParam(SINE_MIX_PARAM, 0.0f, 1.0f, 1.0f, "Sine wave mix", "%", 0.0f, 100.0f);
    165 
    166 		configInput(FM_INPUT, "Frequency modulation");
    167 		configInput(FM_DEPTH_INPUT, "FM depth CV");
    168 		configInput(SQUARE_PW_INPUT, "Square pulse width CV");
    169 		configInput(SQUARE_PHASE_INPUT, "Square phase CV");
    170 		configInput(SQUARE_MIX_INPUT, "Square mix CV");
    171 		configInput(SAW_SATURATION_INPUT, "Saw saturation CV");
    172 		configInput(SAW_PHASE_INPUT, "Saw phase CV");
    173 		configInput(SAW_MIX_INPUT, "Saw mix CV");
    174 		configInput(TRIANGLE_SAMPLE_INPUT, "Triangle sample CV");
    175 		configInput(TRIANGLE_PHASE_INPUT, "Triangle phase CV");
    176 		configInput(TRIANGLE_MIX_INPUT, "Triangle mix CV");
    177 		configInput(SINE_FEEDBACK_INPUT, "Sine feedback CV");
    178 		configInput(SINE_PHASE_INPUT, "Sine phase CV");
    179 		configInput(SINE_MIX_INPUT, "Sine mix CV");
    180 		configInput(PITCH_INPUT, "Pitch (1V/octave)");
    181 		configInput(SYNC_INPUT, "Sync");
    182 
    183 		configOutput(SQUARE_OUTPUT, "Square signal");
    184 		configOutput(SAW_OUTPUT, "Saw signal");
    185 		configOutput(TRIANGLE_OUTPUT, "Triangle signal");
    186 		configOutput(SINE_OUTPUT, "Sine signal");
    187 		configOutput(MIX_OUTPUT, "Mixed signal");
    188 	}
    189 
    190 	void reset() override;
    191 	void sampleRateChange() override;
    192 	json_t* saveToJson(json_t* root) override;
    193 	void loadFromJson(json_t* root) override;
    194 	bool active() override;
    195 	int channels() override;
    196 	void addChannel(int c) override;
    197 	void removeChannel(int c) override;
    198 	void modulate() override;
    199 	void modulateChannel(int c) override;
    200 	void processChannel(const ProcessArgs& args, int c) override;
    201 	Phasor::phase_delta_t phaseOffset(int c, Param& param, Input& input);
    202 	float level(int c, Param& param, Input& input);
    203 };
    204 
    205 } // namespace bogaudio