BogaudioModules

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

Cmp.cpp (5003B)


      1 
      2 #include "Cmp.hpp"
      3 
      4 void Cmp::reset() {
      5 	for (int i = 0; i < maxChannels; ++i) {
      6 		_thresholdState[i] = LOW;
      7 		_windowState[i] = LOW;
      8 	}
      9 }
     10 
     11 bool Cmp::active() {
     12 	return (
     13 		outputs[GREATER_OUTPUT].isConnected() ||
     14 		outputs[LESS_OUTPUT].isConnected() ||
     15 		outputs[EQUAL_OUTPUT].isConnected() ||
     16 		outputs[NOT_EQUAL_OUTPUT].isConnected()
     17 	);
     18 }
     19 
     20 int Cmp::channels() {
     21 	return inputs[A_INPUT].getChannels();
     22 }
     23 
     24 void Cmp::modulate() {
     25 	_highValue = 10.0f;
     26 	_lowValue = 0.0f;
     27 	if (params[OUTPUT_PARAM].getValue() > 0.5f) {
     28 		_highValue = 5.0f;
     29 		_lowValue = -5.0f;
     30 	}
     31 }
     32 
     33 void Cmp::modulateChannel(int c) {
     34 	float lag = params[LAG_PARAM].getValue();
     35 	if (inputs[LAG_INPUT].isConnected()) {
     36 		lag *= clamp(inputs[LAG_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f);
     37 	}
     38 	_lagInSamples[c] = lag * lag * APP->engine->getSampleRate();
     39 }
     40 
     41 void Cmp::processChannel(const ProcessArgs& args, int c) {
     42 	float a = params[A_PARAM].getValue() * 10.0f;
     43 	if (inputs[A_INPUT].isConnected()) {
     44 		a = clamp(a + inputs[A_INPUT].getPolyVoltage(c), -12.0f, 12.0f);
     45 	}
     46 
     47 	float b = params[B_PARAM].getValue() * 10.0f;
     48 	if (inputs[B_INPUT].isConnected()) {
     49 		b = clamp(b + inputs[B_INPUT].getPolyVoltage(c), -12.0f, 12.0f);
     50 	}
     51 
     52 	float window = params[WINDOW_PARAM].getValue();
     53 	if (inputs[WINDOW_INPUT].isConnected()) {
     54 		window *= clamp(inputs[WINDOW_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f);
     55 	}
     56 	window *= 10.0f;
     57 
     58 	stepChannel(
     59 		c,
     60 		a >= b,
     61 		_thresholdState[c],
     62 		_thresholdLag[c],
     63 		outputs[GREATER_OUTPUT],
     64 		outputs[LESS_OUTPUT]
     65 	);
     66 	stepChannel(
     67 		c,
     68 		fabsf(a - b) <= window,
     69 		_windowState[c],
     70 		_windowLag[c],
     71 		outputs[EQUAL_OUTPUT],
     72 		outputs[NOT_EQUAL_OUTPUT]
     73 	);
     74 }
     75 
     76 void Cmp::stepChannel(
     77 	int c,
     78 	bool high,
     79 	State& state,
     80 	int& channelLag,
     81 	Output& highOutput,
     82 	Output& lowOutput
     83 ) {
     84 	switch (state) {
     85 		case LOW: {
     86 			if (high) {
     87 				if (_lagInSamples[c] < 1) {
     88 					state = HIGH;
     89 				}
     90 				else {
     91 					state = LAG_HIGH;
     92 					channelLag = _lagInSamples[c];
     93 				}
     94 			}
     95 			break;
     96 		}
     97 		case HIGH: {
     98 			if (!high) {
     99 				if (_lagInSamples[c] < 1) {
    100 					state = LOW;
    101 				}
    102 				else {
    103 					state = LAG_LOW;
    104 					channelLag = _lagInSamples[c];
    105 				}
    106 			}
    107 			break;
    108 		}
    109 		case LAG_LOW: {
    110 			if (!high) {
    111 				--channelLag;
    112 				if (channelLag == 0) {
    113 					state = LOW;
    114 				}
    115 			}
    116 			else {
    117 				state = HIGH;
    118 			}
    119 			break;
    120 		}
    121 		case LAG_HIGH: {
    122 			if (high) {
    123 				--channelLag;
    124 				if (channelLag == 0) {
    125 					state = HIGH;
    126 				}
    127 			}
    128 			else {
    129 				state = LOW;
    130 			}
    131 			break;
    132 		}
    133 	};
    134 
    135 	highOutput.setChannels(_channels);
    136 	lowOutput.setChannels(_channels);
    137 	switch (state) {
    138 		case LOW:
    139 		case LAG_HIGH: {
    140 			highOutput.setVoltage(_lowValue, c);
    141 			lowOutput.setVoltage(_highValue, c);
    142 			break;
    143 		}
    144 		case HIGH:
    145 		case LAG_LOW: {
    146 			highOutput.setVoltage(_highValue, c);
    147 			lowOutput.setVoltage(_lowValue, c);
    148 			break;
    149 		}
    150 	}
    151 }
    152 
    153 struct CmpWidget : BGModuleWidget {
    154 	static constexpr int hp = 6;
    155 
    156 	CmpWidget(Cmp* module) {
    157 		setModule(module);
    158 		box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
    159 		setPanel(box.size, "Cmp");
    160 		createScrews();
    161 
    162 		// generated by svg_widgets.rb
    163 		auto aParamPosition = Vec(8.0, 46.0);
    164 		auto bParamPosition = Vec(53.0, 46.0);
    165 		auto windowParamPosition = Vec(8.0, 151.0);
    166 		auto lagParamPosition = Vec(53.0, 151.0);
    167 		auto outputParamPosition = Vec(25.5, 251.0);
    168 
    169 		auto aInputPosition = Vec(10.5, 87.0);
    170 		auto bInputPosition = Vec(55.5, 87.0);
    171 		auto windowInputPosition = Vec(10.5, 192.0);
    172 		auto lagInputPosition = Vec(55.5, 192.0);
    173 
    174 		auto greaterOutputPosition = Vec(16.0, 283.0);
    175 		auto lessOutputPosition = Vec(50.0, 283.0);
    176 		auto equalOutputPosition = Vec(16.0, 319.0);
    177 		auto notEqualOutputPosition = Vec(50.0, 319.0);
    178 		// end generated by svg_widgets.rb
    179 
    180 		addParam(createParam<Knob29>(aParamPosition, module, Cmp::A_PARAM));
    181 		addParam(createParam<Knob29>(bParamPosition, module, Cmp::B_PARAM));
    182 		addParam(createParam<Knob29>(windowParamPosition, module, Cmp::WINDOW_PARAM));
    183 		addParam(createParam<Knob29>(lagParamPosition, module, Cmp::LAG_PARAM));
    184 		{
    185 			auto w = createParam<Knob16>(outputParamPosition, module, Cmp::OUTPUT_PARAM);
    186 			auto k = dynamic_cast<SvgKnob*>(w);
    187 			k->minAngle = 3.0f * (M_PI / 8.0f);
    188 			k->maxAngle = 5.0f * (M_PI / 8.0f);
    189 			k->speed = 3.0;
    190 			addParam(w);
    191 		}
    192 
    193 		addInput(createInput<Port24>(aInputPosition, module, Cmp::A_INPUT));
    194 		addInput(createInput<Port24>(bInputPosition, module, Cmp::B_INPUT));
    195 		addInput(createInput<Port24>(windowInputPosition, module, Cmp::WINDOW_INPUT));
    196 		addInput(createInput<Port24>(lagInputPosition, module, Cmp::LAG_INPUT));
    197 
    198 		addOutput(createOutput<Port24>(greaterOutputPosition, module, Cmp::GREATER_OUTPUT));
    199 		addOutput(createOutput<Port24>(lessOutputPosition, module, Cmp::LESS_OUTPUT));
    200 		addOutput(createOutput<Port24>(equalOutputPosition, module, Cmp::EQUAL_OUTPUT));
    201 		addOutput(createOutput<Port24>(notEqualOutputPosition, module, Cmp::NOT_EQUAL_OUTPUT));
    202 	}
    203 };
    204 
    205 Model* modelCmp = bogaudio::createModel<Cmp, CmpWidget>("Bogaudio-Cmp", "CMP", "Window comparator", "Logic", "Polyphonic");