BogaudioModules

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

VU.cpp (4462B)


      1 
      2 #include "VU.hpp"
      3 
      4 void VU::sampleRateChange() {
      5 	float sr = APP->engine->getSampleRate();
      6 	_lRms.setSampleRate(sr);
      7 	_rRms.setSampleRate(sr);
      8 	_lPeakRms.setSampleRate(sr);
      9 	_rPeakRms.setSampleRate(sr);
     10 	_lPeakSlew.setParams(sr, 750.0f, 1.0f);
     11 	_rPeakSlew.setParams(sr, 750.0f, 1.0f);
     12 }
     13 
     14 void VU::processAll(const ProcessArgs& args) {
     15 	float left = inputs[L_INPUT].getVoltageSum();
     16 	outputs[L_OUTPUT].setChannels(inputs[L_INPUT].getChannels());
     17 	outputs[L_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages());
     18 
     19 	float right = 0.0f;
     20 	if (inputs[R_INPUT].isConnected()) {
     21 		right = inputs[R_INPUT].getVoltageSum();
     22 		outputs[R_OUTPUT].setChannels(inputs[R_INPUT].getChannels());
     23 		outputs[R_OUTPUT].writeVoltages(inputs[R_INPUT].getVoltages());
     24 	}
     25 	else {
     26 		right = left;
     27 		outputs[R_OUTPUT].setChannels(inputs[L_INPUT].getChannels());
     28 		outputs[R_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages());
     29 	}
     30 
     31 	_lLevel = _lRms.next(left) / 5.0f;
     32 	_rLevel = _rRms.next(right) / 5.0f;
     33 
     34 	float lPeak = _lPeakRms.next(fabsf(left)) / 5.0f;
     35 	if (lPeak < _lPeakLevel) {
     36 		if (!_lPeakFalling) {
     37 			_lPeakFalling = true;
     38 			_lPeakSlew._last = _lPeakLevel;
     39 		}
     40 		lPeak = _lPeakSlew.next(lPeak);
     41 	}
     42 	else {
     43 		_lPeakFalling = false;
     44 	}
     45 	_lPeakLevel = lPeak;
     46 
     47 	float rPeak = _rPeakRms.next(fabsf(right)) / 5.0f;
     48 	if (rPeak < _rPeakLevel) {
     49 		if (!_rPeakFalling) {
     50 			_rPeakFalling = true;
     51 			_rPeakSlew._last = _rPeakLevel;
     52 		}
     53 		rPeak = _rPeakSlew.next(rPeak);
     54 	}
     55 	else {
     56 		_rPeakFalling = false;
     57 	}
     58 	_rPeakLevel = rPeak;
     59 }
     60 
     61 struct VUDisplay : LightEmittingWidget<OpaqueWidget> {
     62 	struct Level {
     63 		float db;
     64 		NVGcolor color;
     65 		Level(float db, const NVGcolor& color) : db(db), color(color) {}
     66 	};
     67 
     68 	const NVGcolor bgColor = nvgRGBA(0xaa, 0xaa, 0xaa, 0xff);
     69 	VU* _module;
     70 	std::vector<Level> _levels;
     71 
     72 	VUDisplay(VU* module) : _module(module) {
     73 		for (int i = 1; i <= 36; ++i) {
     74 			float db = 12.0f - i*2.0f;
     75 			_levels.push_back(Level(db, decibelsToColor(db)));
     76 		}
     77 	}
     78 
     79 	bool isLit() override {
     80 		return _module && !_module->isBypassed();
     81 	}
     82 
     83 	void draw(const DrawArgs& args) override {
     84 		nvgSave(args.vg);
     85 		for (int i = 0; i < 180; i += 5) {
     86 			drawBox(args, i, true);
     87 			nvgFillColor(args.vg, bgColor);
     88 			nvgFill(args.vg);
     89 
     90 			drawBox(args, i, false);
     91 			nvgFillColor(args.vg, bgColor);
     92 			nvgFill(args.vg);
     93 		}
     94 		nvgRestore(args.vg);
     95 	}
     96 
     97 	void drawLit(const DrawArgs& args) override {
     98 		assert(_module);
     99 		float lDb = amplitudeToDecibels(_module->_lLevel);
    100 		float rDb = amplitudeToDecibels(_module->_rLevel);
    101 		float lPeakDb = amplitudeToDecibels(_module->_lPeakLevel);
    102 		float rPeakDb = amplitudeToDecibels(_module->_rPeakLevel);
    103 
    104 		nvgSave(args.vg);
    105 		for (int i = 0; i < 180; i += 5) {
    106 			const Level& l = _levels.at(i / 5);
    107 
    108 			if (lPeakDb > l.db && lPeakDb < l.db + 2.0f) {
    109 				drawBox(args, i, true);
    110 				nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
    111 				nvgFill(args.vg);
    112 			}
    113 			if (lDb > l.db) {
    114 				drawBox(args, i, true);
    115 				nvgFillColor(args.vg, l.color);
    116 				nvgFill(args.vg);
    117 			}
    118 
    119 			if (rPeakDb > l.db && rPeakDb < l.db + 2.0f) {
    120 				drawBox(args, i, false);
    121 				nvgFillColor(args.vg, nvgRGBA(0x00, 0xdd, 0xff, 0xff));
    122 				nvgFill(args.vg);
    123 			}
    124 			if (rDb > l.db) {
    125 				drawBox(args, i, false);
    126 				nvgFillColor(args.vg, l.color);
    127 				nvgFill(args.vg);
    128 			}
    129 		}
    130 		nvgRestore(args.vg);
    131 	}
    132 
    133 	void drawBox(const DrawArgs& args, int offset, bool left) {
    134 		nvgBeginPath(args.vg);
    135 		nvgRect(args.vg, left ? 3 : 10, offset + 1, 5, 4);
    136 	}
    137 };
    138 
    139 struct VUWidget : BGModuleWidget {
    140 	static constexpr int hp = 3;
    141 
    142 	VUWidget(VU* module) {
    143 		setModule(module);
    144 		box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
    145 		setPanel(box.size, "VU");
    146 		createScrews();
    147 
    148 		{
    149 			auto display = new VUDisplay(module);
    150 			display->box.pos = Vec(13.5, 16.5);
    151 			display->box.size = Vec(18, 180);
    152 			addChild(display);
    153 		}
    154 
    155 		// generated by svg_widgets.rb
    156 		auto lInputPosition = Vec(10.5, 203.0);
    157 		auto rInputPosition = Vec(10.5, 238.0);
    158 
    159 		auto lOutputPosition = Vec(10.5, 276.0);
    160 		auto rOutputPosition = Vec(10.5, 311.0);
    161 		// end generated by svg_widgets.rb
    162 
    163 		addInput(createInput<Port24>(lInputPosition, module, VU::L_INPUT));
    164 		addInput(createInput<Port24>(rInputPosition, module, VU::R_INPUT));
    165 
    166 		addOutput(createOutput<Port24>(lOutputPosition, module, VU::L_OUTPUT));
    167 		addOutput(createOutput<Port24>(rOutputPosition, module, VU::R_OUTPUT));
    168 	}
    169 };
    170 
    171 Model* modelVU = bogaudio::createModel<VU, VUWidget>("Bogaudio-VU", "VU", "Stereo signal meter", "Visual");