BogaudioModules

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

Mix2.cpp (5566B)


      1 
      2 #include "Mix2.hpp"
      3 
      4 #define POLY_OFFSET "poly_channel_offset"
      5 
      6 json_t* Mix2::saveToJson(json_t* root) {
      7 	json_object_set_new(root, POLY_OFFSET, json_integer(_polyChannelOffset));
      8 	return root;
      9 }
     10 
     11 void Mix2::loadFromJson(json_t* root) {
     12 	json_t* o = json_object_get(root, POLY_OFFSET);
     13 	if (o) {
     14 		_polyChannelOffset = json_integer_value(o);
     15 	}
     16 }
     17 
     18 void Mix2::sampleRateChange() {
     19 	float sr = APP->engine->getSampleRate();
     20 	for (int c = 0; c < _channels; ++c) {
     21 		_engines[c]->left.setSampleRate(sr);
     22 		_engines[c]->right.setSampleRate(sr);
     23 	}
     24 }
     25 
     26 bool Mix2::active() {
     27 	return outputs[L_OUTPUT].isConnected() || outputs[R_OUTPUT].isConnected();
     28 }
     29 
     30 int Mix2::channels() {
     31 	if (_polyChannelOffset >= 0) {
     32 		return 1;
     33 	}
     34 	return inputs[L_INPUT].getChannels();
     35 }
     36 
     37 void Mix2::addChannel(int c) {
     38 	_engines[c] = new Engine(
     39 		params[LEVEL_PARAM],
     40 		params[MUTE_PARAM],
     41 		inputs[LEVEL_INPUT],
     42 		inputs[MUTE_INPUT]
     43 	);
     44 }
     45 
     46 void Mix2::removeChannel(int c) {
     47 	delete _engines[c];
     48 	_engines[c] = NULL;
     49 }
     50 
     51 void Mix2::processAlways(const ProcessArgs& args) {
     52 	_leftRmsSum = 0.0f;
     53 	_rightRmsSum = 0.0f;
     54 }
     55 
     56 void Mix2::processChannel(const ProcessArgs& args, int c) {
     57 	Engine& e = *_engines[c];
     58 
     59 	float left = 0.0f;
     60 	if (_polyChannelOffset >= 0) {
     61 		left = inputs[L_INPUT].getPolyVoltage(_polyChannelOffset);
     62 	}
     63 	else {
     64 		left = inputs[L_INPUT].getVoltage(c);
     65 	}
     66 	e.left.next(left, false, c, _linearCV);
     67 	_leftRmsSum += e.left.rms;
     68 	outputs[L_OUTPUT].setChannels(_channels);
     69 	outputs[L_OUTPUT].setVoltage(e.left.out, c);
     70 
     71 	float right = left;
     72 	if (inputs[R_INPUT].isConnected()) {
     73 		right = inputs[R_INPUT].getVoltage(c);
     74 	}
     75 	else if (_polyChannelOffset >= 0) {
     76 		right = inputs[L_INPUT].getPolyVoltage(_polyChannelOffset + 1);
     77 	}
     78 	e.right.next(right, false, c, _linearCV);
     79 	_rightRmsSum += e.right.rms;
     80 	outputs[R_OUTPUT].setChannels(_channels);
     81 	outputs[R_OUTPUT].setVoltage(e.right.out, c);
     82 }
     83 
     84 void Mix2::postProcessAlways(const ProcessArgs& args) {
     85 	_leftRms = _leftRmsSum * _inverseChannels;
     86 	_rightRms = _rightRmsSum * _inverseChannels;
     87 }
     88 
     89 void Mix2::processBypass(const ProcessArgs& args) {
     90 	outputs[L_OUTPUT].setChannels(inputs[L_INPUT].getChannels());
     91 	outputs[L_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages());
     92 	if (inputs[R_INPUT].isConnected()) {
     93 		outputs[R_OUTPUT].setChannels(inputs[R_INPUT].getChannels());
     94 		outputs[R_OUTPUT].writeVoltages(inputs[R_INPUT].getVoltages());
     95 	}
     96 	else {
     97 		outputs[R_OUTPUT].setChannels(inputs[L_INPUT].getChannels());
     98 		outputs[R_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages());
     99 	}
    100 }
    101 
    102 struct Mix2Widget : LinearCVMixerWidget {
    103 	static constexpr int hp = 5;
    104 
    105 	Mix2Widget(Mix2* module) {
    106 		setModule(module);
    107 		box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
    108 		setPanel(box.size, "Mix2");
    109 		createScrews();
    110 
    111 		// generated by svg_widgets.rb
    112 		auto levelParamPosition = Vec(28.5, 32.0);
    113 		auto muteParamPosition = Vec(28.5, 197.0);
    114 
    115 		auto levelInputPosition = Vec(10.5, 244.0);
    116 		auto muteInputPosition = Vec(40.5, 244.0);
    117 		auto lInputPosition = Vec(10.5, 280.0);
    118 		auto rInputPosition = Vec(40.5, 280.0);
    119 
    120 		auto lOutputPosition = Vec(10.5, 320.0);
    121 		auto rOutputPosition = Vec(40.5, 320.0);
    122 		// end generated by svg_widgets.rb
    123 
    124 		{
    125 			auto slider = createParam<VUSlider151>(levelParamPosition, module, Mix2::LEVEL_PARAM);
    126 			if (module) {
    127 				dynamic_cast<VUSlider*>(slider)->setVULevel(&module->_leftRms);
    128 				dynamic_cast<VUSlider*>(slider)->setStereoVULevel(&module->_rightRms);
    129 			}
    130 			addParam(slider);
    131 		}
    132 		addParam(createParam<MuteButton>(muteParamPosition, module, Mix2::MUTE_PARAM));
    133 
    134 		addInput(createInput<Port24>(levelInputPosition, module, Mix2::LEVEL_INPUT));
    135 		addInput(createInput<Port24>(muteInputPosition, module, Mix2::MUTE_INPUT));
    136 		addInput(createInput<Port24>(lInputPosition, module, Mix2::L_INPUT));
    137 		addInput(createInput<Port24>(rInputPosition, module, Mix2::R_INPUT));
    138 
    139 		addOutput(createOutput<Port24>(lOutputPosition, module, Mix2::L_OUTPUT));
    140 		addOutput(createOutput<Port24>(rOutputPosition, module, Mix2::R_OUTPUT));
    141 	}
    142 
    143 	void contextMenu(Menu* menu) override {
    144 		auto m = dynamic_cast<Mix2*>(module);
    145 		assert(m);
    146 		OptionsMenuItem* mi = new OptionsMenuItem("Input 1 poly spread");
    147 		mi->addItem(OptionMenuItem("None (normal polyphonic)", [m]() { return m->_polyChannelOffset == -1; }, [m]() { m->_polyChannelOffset = -1; }));
    148 		mi->addItem(OptionMenuItem("Channels 1-2", [m]() { return m->_polyChannelOffset == 0; }, [m]() { m->_polyChannelOffset = 0; }));
    149 		mi->addItem(OptionMenuItem("Channels 3-4", [m]() { return m->_polyChannelOffset == 2; }, [m]() { m->_polyChannelOffset = 2; }));
    150 		mi->addItem(OptionMenuItem("Channels 5-6", [m]() { return m->_polyChannelOffset == 4; }, [m]() { m->_polyChannelOffset = 4; }));
    151 		mi->addItem(OptionMenuItem("Channels 7-8", [m]() { return m->_polyChannelOffset == 6; }, [m]() { m->_polyChannelOffset = 6; }));
    152 		mi->addItem(OptionMenuItem("Channels 9-10", [m]() { return m->_polyChannelOffset == 8; }, [m]() { m->_polyChannelOffset = 8; }));
    153 		mi->addItem(OptionMenuItem("Channels 11-12", [m]() { return m->_polyChannelOffset == 10; }, [m]() { m->_polyChannelOffset = 10; }));
    154 		mi->addItem(OptionMenuItem("Channels 13-14", [m]() { return m->_polyChannelOffset == 12; }, [m]() { m->_polyChannelOffset = 12; }));
    155 		mi->addItem(OptionMenuItem("Channels 15-16", [m]() { return m->_polyChannelOffset == 14; }, [m]() { m->_polyChannelOffset = 14; }));
    156 		OptionsMenuItem::addToMenu(mi, menu);
    157 	}
    158 };
    159 
    160 Model* modelMix2 = createModel<Mix2, Mix2Widget>("Bogaudio-Mix2", "MIX2", "Stereo fader/amplifier with CV-controllable mute", "VCA", "Polyphonic");