BogaudioModules

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

Chirp.cpp (5021B)


      1 
      2 #include "Chirp.hpp"
      3 #include "vco_base.hpp"
      4 #include "dsp/pitch.hpp"
      5 
      6 void Chirp::Engine::reset() {
      7 	trigger.reset();
      8 	eocPulseGen.process(10.0f);
      9 }
     10 
     11 void Chirp::Engine::sampleRateChange(float sr) {
     12 	chirp.setSampleRate(sr);
     13 	ampSL.setParams(sr, Chirp::cycleSlewSeconds * 1000.0f, -Amplifier::minDecibels);
     14 }
     15 
     16 void Chirp::reset() {
     17 	for (int c = 0; c < _channels; ++c) {
     18 		_engines[c]->reset();
     19 	}
     20 }
     21 
     22 void Chirp::sampleRateChange() {
     23 	float sr = APP->engine->getSampleRate();
     24 	_sampleTime = 1.0f / sr;
     25 	for (int c = 0; c < _channels; ++c) {
     26 		_engines[c]->sampleRateChange(sr);
     27 	}
     28 }
     29 
     30 bool Chirp::active() {
     31 	return outputs[OUT_OUTPUT].isConnected() || outputs[EOC_OUTPUT].isConnected();
     32 }
     33 
     34 int Chirp::channels() {
     35 	return inputs[FREQUENCY1_INPUT].getChannels();
     36 }
     37 
     38 void Chirp::addChannel(int c) {
     39 	_engines[c] = new Engine();
     40 	_engines[c]->reset();
     41 	_engines[c]->sampleRateChange(APP->engine->getSampleRate());
     42 }
     43 
     44 void Chirp::removeChannel(int c) {
     45 	delete _engines[c];
     46 	_engines[c] = NULL;
     47 }
     48 
     49 void Chirp::modulate() {
     50 	_exponential = params[EXPONENTIAL_PARAM].getValue() > 0.5f;
     51 	_loop = params[LOOP_PARAM].getValue() > 0.5f;
     52 }
     53 
     54 void Chirp::modulateChannel(int c) {
     55 	Engine& e = *_engines[c];
     56 
     57 	float time = clamp(params[TIME_PARAM].getValue(), 0.0f, 1.0f);
     58 	if (inputs[TIME_INPUT].isConnected()) {
     59 		time *= clamp(inputs[TIME_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f);
     60 	}
     61 	time *= time;
     62 	time *= maxTimeSeconds - minTimeSeconds;
     63 	time += minTimeSeconds;
     64 
     65 	float maxF = roundf(maxFrequencyNyquistRatio * APP->engine->getSampleRate());
     66 	float f1 = params[FREQUENCY1_PARAM].getValue();
     67 	if (inputs[FREQUENCY1_INPUT].isConnected()) {
     68 		f1 += clamp(inputs[FREQUENCY1_INPUT].getPolyVoltage(c), -5.0f, 5.0f);
     69 	}
     70 	f1 = cvToFrequency(f1);
     71 	f1 = clamp(f1, minFrequency, maxF);
     72 
     73 	float f2 = params[FREQUENCY2_PARAM].getValue();
     74 	if (inputs[FREQUENCY2_INPUT].isConnected()) {
     75 		f2 += clamp(inputs[FREQUENCY2_INPUT].getPolyVoltage(c), -5.0f, 5.0f);
     76 	}
     77 	f2 = cvToFrequency(f2);
     78 	f2 = clamp(f2, minFrequency, maxF);
     79 
     80 	e.chirp.setParams(f1, f2, time, !_exponential);
     81 }
     82 
     83 void Chirp::processChannel(const ProcessArgs& args, int c) {
     84 	Engine& e = *_engines[c];
     85 
     86 	bool triggered = e.trigger.process(params[TRIGGER_PARAM].getValue()*5.0f + inputs[TRIGGER_INPUT].getPolyVoltage(c));
     87 	if (!_run) {
     88 		if (triggered || _loop) {
     89 			_run = true;
     90 			e.chirp.reset();
     91 		}
     92 	}
     93 
     94 	float out = 0.0f;
     95 	if (_run) {
     96 		out = e.chirp.next() * 5.0f;
     97 		if (e.chirp.isCycleComplete()) {
     98 			_run = false;
     99 			e.eocPulseGen.trigger(0.001f);
    100 			e.targetAmplitude = 0.0f;
    101 		}
    102 		else if (e.chirp.isCycleNearlyComplete(cycleSlewSeconds)) {
    103 			e.targetAmplitude = Amplifier::minDecibels;
    104 		}
    105 
    106 		e.amp.setLevel(e.ampSL.next(e.targetAmplitude));
    107 		out = e.amp.next(out);
    108 	}
    109 
    110 	outputs[OUT_OUTPUT].setChannels(_channels);
    111 	outputs[OUT_OUTPUT].setVoltage(out, c);
    112 	outputs[EOC_OUTPUT].setChannels(_channels);
    113 	outputs[EOC_OUTPUT].setVoltage(e.eocPulseGen.process(_sampleTime) * 5.0f, c);
    114 }
    115 
    116 struct ChirpWidget : BGModuleWidget {
    117 	static constexpr int hp = 5;
    118 
    119 	ChirpWidget(Chirp* module) {
    120 		setModule(module);
    121 		box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
    122 		setPanel(box.size, "Chirp");
    123 		createScrews();
    124 
    125 		// generated by svg_widgets.rb
    126 		auto timeParamPosition = Vec(18.5, 46.0);
    127 		auto frequency1ParamPosition = Vec(24.5, 122.0);
    128 		auto frequency2ParamPosition = Vec(24.5, 179.0);
    129 		auto triggerParamPosition = Vec(10.0, 216.0);
    130 		auto exponentialParamPosition = Vec(59.5, 218.0);
    131 		auto loopParamPosition = Vec(59.5, 232.0);
    132 
    133 		auto frequency1InputPosition = Vec(10.5, 251.0);
    134 		auto frequency2InputPosition = Vec(40.5, 251.0);
    135 		auto timeInputPosition = Vec(10.5, 288.0);
    136 		auto triggerInputPosition = Vec(10.5, 325.0);
    137 
    138 		auto eocOutputPosition = Vec(40.5, 288.0);
    139 		auto outOutputPosition = Vec(40.5, 325.0);
    140 		// end generated by svg_widgets.rb
    141 
    142 		addParam(createParam<Knob38>(timeParamPosition, module, Chirp::TIME_PARAM));
    143 		addParam(createParam<Knob26>(frequency1ParamPosition, module, Chirp::FREQUENCY1_PARAM));
    144 		addParam(createParam<Knob26>(frequency2ParamPosition, module, Chirp::FREQUENCY2_PARAM));
    145 		addParam(createParam<Button18>(triggerParamPosition, module, Chirp::TRIGGER_PARAM));
    146 		addParam(createParam<IndicatorButtonGreen9>(exponentialParamPosition, module, Chirp::EXPONENTIAL_PARAM));
    147 		addParam(createParam<IndicatorButtonGreen9>(loopParamPosition, module, Chirp::LOOP_PARAM));
    148 
    149 		addInput(createInput<Port24>(frequency1InputPosition, module, Chirp::FREQUENCY1_INPUT));
    150 		addInput(createInput<Port24>(frequency2InputPosition, module, Chirp::FREQUENCY2_INPUT));
    151 		addInput(createInput<Port24>(timeInputPosition, module, Chirp::TIME_INPUT));
    152 		addInput(createInput<Port24>(triggerInputPosition, module, Chirp::TRIGGER_INPUT));
    153 
    154 		addOutput(createOutput<Port24>(eocOutputPosition, module, Chirp::EOC_OUTPUT));
    155 		addOutput(createOutput<Port24>(outOutputPosition, module, Chirp::OUT_OUTPUT));
    156 	}
    157 };
    158 
    159 Model* modelChirp = createModel<Chirp, ChirpWidget>("Bogaudio-Chirp", "CHIRP", "Swept-sine oscillator", "Oscillator", "Polyphonic");