BogaudioModules

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

Inv.cpp (4849B)


      1 
      2 #include "Inv.hpp"
      3 
      4 #define SAVE_LATCHED_TO_PATCH "save_latched_to_patch"
      5 #define LATCHED_STATE1 "latched_state1"
      6 #define LATCHED_STATE2 "latched_state2"
      7 
      8 void Inv::reset() {
      9 	for (int c = 0; c < maxChannels; ++c) {
     10 		_trigger[0][c].reset();
     11 		_trigger[1][c].reset();
     12 	}
     13 }
     14 
     15 json_t* Inv::saveToJson(json_t* root) {
     16 	json_object_set_new(root, SAVE_LATCHED_TO_PATCH, json_boolean(_saveLatchedToPatch));
     17 	if (_saveLatchedToPatch) {
     18 		if (_latch[0]) {
     19 			json_t* a = json_array();
     20 			for (int c = 0; c < maxChannels; ++c) {
     21 				json_array_append_new(a, json_boolean(_latchedHigh[0][c]));
     22 			}
     23 			json_object_set_new(root, LATCHED_STATE1, a);
     24 		}
     25 
     26 		if (_latch[1]) {
     27 			json_t* a = json_array();
     28 			for (int c = 0; c < maxChannels; ++c) {
     29 				json_array_append_new(a, json_boolean(_latchedHigh[1][c]));
     30 			}
     31 			json_object_set_new(root, LATCHED_STATE2, a);
     32 		}
     33 	}
     34 	return root;
     35 }
     36 
     37 void Inv::loadFromJson(json_t* root) {
     38 	json_t* sl = json_object_get(root, SAVE_LATCHED_TO_PATCH);
     39 	if (sl) {
     40 		_saveLatchedToPatch = json_is_true(sl);
     41 		if (_saveLatchedToPatch) {
     42 			json_t* a1 = json_object_get(root, LATCHED_STATE1);
     43 			if (a1 && json_array_size(a1) == maxChannels) {
     44 				for (int c = 0; c < maxChannels; ++c) {
     45 					json_t* ls = json_array_get(a1, c);
     46 					if (ls && json_is_true(ls)) {
     47 						_latchedHigh[0][c] = true;
     48 					}
     49 				}
     50 			}
     51 
     52 			json_t* a2 = json_object_get(root, LATCHED_STATE2);
     53 			if (a2 && json_array_size(a2) == maxChannels) {
     54 				for (int c = 0; c < maxChannels; ++c) {
     55 					json_t* ls = json_array_get(a2, c);
     56 					if (ls && json_is_true(ls)) {
     57 						_latchedHigh[1][c] = true;
     58 					}
     59 				}
     60 			}
     61 		}
     62 	}
     63 }
     64 
     65 void Inv::modulate() {
     66 	_latch[0] = params[LATCH1_PARAM].getValue() > 0.5f;
     67 	_latch[1] = params[LATCH2_PARAM].getValue() > 0.5f;
     68 }
     69 
     70 void Inv::processAll(const ProcessArgs& args) {
     71 	processDual(0);
     72 	processDual(1);
     73 }
     74 
     75 void Inv::processDual(int i) {
     76 	int channels = inputs[IN1_INPUT + 2 * i].getChannels();
     77 	outputs[OUT1_OUTPUT + i].setChannels(channels);
     78 	int lightsOn = 0;
     79 
     80 	for (int c = 0; c < channels; ++c) {
     81 		bool triggered = _trigger[i][c].process(params[GATE1_PARAM + 2 * i].getValue() + inputs[GATE1_INPUT + 2 * i].getPolyVoltage(c));
     82 		if (_latch[i]) {
     83 			if (triggered) {
     84 				_latchedHigh[i][c] = !_latchedHigh[i][c];
     85 			}
     86 		}
     87 		else {
     88 			_latchedHigh[i][c] = false;
     89 		}
     90 
     91 		float in = inputs[IN1_INPUT + 2 * i].getPolyVoltage(c);
     92 		if (_latchedHigh[i][c] || (!_latch[i] && _trigger[i][c].isHigh())) {
     93 			in = -in;
     94 			++lightsOn;
     95 		}
     96 		outputs[OUT1_OUTPUT + i].setVoltage(in, c);
     97 	}
     98 
     99 	float red = lights[HIGH1_LIGHT + 2 * i].value = lightsOn / (float)channels;
    100 	lights[LOW1_LIGHT + 2 * i].value = 1.0f - red;
    101 }
    102 
    103 struct InvWidget : BGModuleWidget {
    104 	static constexpr int hp = 3;
    105 
    106 	InvWidget(Inv* module) {
    107 		setModule(module);
    108 		box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
    109 		setPanel(box.size, "Inv");
    110 		createScrews();
    111 
    112 		// generated by svg_widgets.rb
    113 		auto gate1ParamPosition = Vec(13.5, 22.0);
    114 		auto latch1ParamPosition = Vec(29.5, 82.0);
    115 		auto gate2ParamPosition = Vec(13.5, 187.0);
    116 		auto latch2ParamPosition = Vec(29.5, 247.0);
    117 
    118 		auto gate1InputPosition = Vec(10.5, 44.0);
    119 		auto in1InputPosition = Vec(10.5, 96.0);
    120 		auto gate2InputPosition = Vec(10.5, 209.0);
    121 		auto in2InputPosition = Vec(10.5, 261.0);
    122 
    123 		auto out1OutputPosition = Vec(10.5, 134.0);
    124 		auto out2OutputPosition = Vec(10.5, 299.0);
    125 
    126 		auto low1LightPosition = Vec(10.5, 160.3);
    127 		auto low2LightPosition = Vec(10.5, 325.3);
    128 		// end generated by svg_widgets.rb
    129 
    130 		addParam(createParam<Button18>(gate1ParamPosition, module, Inv::GATE1_PARAM));
    131 		addParam(createParam<IndicatorButtonGreen9>(latch1ParamPosition, module, Inv::LATCH1_PARAM));
    132 		addParam(createParam<Button18>(gate2ParamPosition, module, Inv::GATE2_PARAM));
    133 		addParam(createParam<IndicatorButtonGreen9>(latch2ParamPosition, module, Inv::LATCH2_PARAM));
    134 
    135 		addInput(createInput<Port24>(gate1InputPosition, module, Inv::GATE1_INPUT));
    136 		addInput(createInput<Port24>(in1InputPosition, module, Inv::IN1_INPUT));
    137 		addInput(createInput<Port24>(gate2InputPosition, module, Inv::GATE2_INPUT));
    138 		addInput(createInput<Port24>(in2InputPosition, module, Inv::IN2_INPUT));
    139 
    140 		addOutput(createOutput<Port24>(out1OutputPosition, module, Inv::OUT1_OUTPUT));
    141 		addOutput(createOutput<Port24>(out2OutputPosition, module, Inv::OUT2_OUTPUT));
    142 
    143 		addChild(createLight<BGSmallLight<GreenRedLight>>(low1LightPosition, module, Inv::LOW1_LIGHT));
    144 		addChild(createLight<BGSmallLight<GreenRedLight>>(low2LightPosition, module, Inv::LOW2_LIGHT));
    145 	}
    146 
    147 	void contextMenu(Menu* menu) override {
    148 		auto m = dynamic_cast<Inv*>(module);
    149 		assert(m);
    150 		menu->addChild(new BoolOptionMenuItem("Save latched state to patch", [m]() { return &m->_saveLatchedToPatch; }));
    151 	}
    152 };
    153 
    154 Model* modelInv = createModel<Inv, InvWidget>("Bogaudio-Inv", "INV", "Dual signal inverter", "Logic", "Dual", "Polyphonic");