BogaudioModules

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

parametric_eq.cpp (4593B)


      1 
      2 #include "parametric_eq.hpp"
      3 #include "dsp/pitch.hpp"
      4 
      5 const float PEQChannel::maxDecibels = 6.0f;
      6 const float PEQChannel::minDecibels = Amplifier::minDecibels;
      7 constexpr float PEQChannel::maxFrequency;
      8 constexpr float PEQChannel::minFrequency;
      9 const float PEQChannel::maxFrequencySemitone = frequencyToSemitone(PEQChannel::maxFrequency);
     10 const float PEQChannel::minFrequencySemitone = frequencyToSemitone(PEQChannel::minFrequency);
     11 
     12 void PEQChannel::setSampleRate(float sampleRate) {
     13 	_sampleRate = sampleRate;
     14 	_levelSL.setParams(sampleRate, 0.05f, maxDecibels - minDecibels);
     15 	_frequencySL.setParams(sampleRate, 0.5f, frequencyToSemitone(maxFrequency - minFrequency));
     16 	_bandwidthSL.setParams(sampleRate, 0.05f, MultimodeFilter::maxQbw - MultimodeFilter::minQbw);
     17 	_rms.setSampleRate(sampleRate);
     18 }
     19 
     20 void PEQChannel::setFilterMode(MultimodeFilter::Mode mode) {
     21 	_mode = mode;
     22 	_poles = _mode == MultimodeFilter::BANDPASS_MODE ? 4 : 12;
     23 }
     24 
     25 void PEQChannel::modulate() {
     26 	float level = clamp(_levelParam.getValue(), 0.0f, 1.0f);
     27 	if (_levelInput.isConnected()) {
     28 		level *= clamp(_levelInput.getPolyVoltage(_c) / 10.0f, 0.0f, 1.0f);
     29 	}
     30 	level *= maxDecibels - minDecibels;
     31 	level += minDecibels;
     32 	_amplifier.setLevel(_levelSL.next(level));
     33 
     34 	float fcv = 0.0f;
     35 	if (_frequency1Input.isConnected()) {
     36 		fcv += clamp(_frequency1Input.getPolyVoltage(_c) / 5.0f, -1.0f, 1.0f);
     37 	}
     38 	if (_frequency2Input.isConnected()) {
     39 		float cv = clamp(_frequency2Input.getPolyVoltage(_c) / 5.0f, -1.0f, 1.0f);
     40 		if (_frequencyCv2Param) {
     41 			cv *= _frequencyCv2Param->getValue();
     42 		}
     43 		fcv += cv;
     44 	}
     45 	fcv *= _frequencyCv1Param.getValue();
     46 	if (_fullFrequencyMode) {
     47 		fcv *= maxFrequencySemitone - minFrequencySemitone;
     48 	}
     49 	else {
     50 		fcv *= 12.0f;
     51 	}
     52 
     53 	frequency = _frequencyParam.getValue();
     54 	frequency *= frequency;
     55 	frequency *= maxFrequency;
     56 	frequency = clamp(frequency, minFrequency, maxFrequency);
     57 	frequency = frequencyToSemitone(frequency);
     58 	frequency += fcv;
     59 	frequency = clamp(frequency, minFrequencySemitone, maxFrequencySemitone);
     60 	frequency = semitoneToFrequency(_frequencySL.next(frequency));
     61 
     62 	bandwidth = MultimodeFilter::minQbw;
     63 	if (_mode == MultimodeFilter::BANDPASS_MODE) {
     64 		bandwidth = clamp(_bandwidthParam.getValue(), 0.0f, 1.0f);
     65 		if (_bandwidthInput && _bandwidthInput->isConnected()) {
     66 			bandwidth *= clamp(_bandwidthInput->getPolyVoltage(_c) / 10.0f, 0.0f, 1.0f);
     67 		}
     68 		bandwidth = MultimodeFilter::minQbw + bandwidth * (MultimodeFilter::maxQbw - MultimodeFilter::minQbw);
     69 	}
     70 	_filter->setParams(
     71 		_sampleRate,
     72 		MultimodeFilter::BUTTERWORTH_TYPE,
     73 		_poles,
     74 		_mode,
     75 		frequency,
     76 		bandwidth,
     77 		MultimodeFilter::PITCH_BANDWIDTH_MODE
     78 	);
     79 }
     80 
     81 void PEQChannel::next(float sample) {
     82 	out = _amplifier.next(_filter->next(sample));
     83 	rms = _rms.next(out / 5.0f);
     84 }
     85 
     86 
     87  void PEQEngine::setFrequencyMode(bool full) {
     88 	 for (int i = 0; i < _n; ++i) {
     89 		 _channels[i]->setFrequencyMode(full);
     90 	 }
     91  }
     92 
     93  void PEQEngine::setSampleRate(float sr) {
     94 	for (int i = 0; i < _n; ++i) {
     95 		_channels[i]->setSampleRate(sr);
     96 	}
     97 }
     98 
     99 void PEQEngine::modulate() {
    100 	for (int i = 0; i < _n; ++i) {
    101 		_channels[i]->modulate();
    102 	}
    103 }
    104 
    105 float PEQEngine::next(float sample, float* rmsSums) {
    106 	bandwidth = _channels[1]->bandwidth; // take from any bandpass-only channel.
    107 	float out = 0.0f;
    108 	for (int i = 0; i < _n; ++i) {
    109 		PEQChannel& c = *_channels[i];
    110 		c.next(sample);
    111 		out += outs[i] = c.out;
    112 		frequencies[i] = c.frequency;
    113 		rmsSums[i] += c.rms;
    114 	}
    115 	return _saturator.next(out);
    116 }
    117 
    118 
    119 float PEQXFBase::scaleEF(float ef, float frequency, float bandwidth) {
    120 	bandwidth = (bandwidth - MultimodeFilter::minQbw) / (MultimodeFilter::maxQbw - MultimodeFilter::minQbw);
    121 	bandwidth *= MultimodeFilter::maxBWPitch;
    122 	float minf = std::max(0.0f, powf(2.0f, -bandwidth) * frequency);
    123 	float maxf = std::min(PEQChannel::maxFrequency, powf(2.0f, bandwidth) * frequency);
    124 	float scale = (2.0f * (maxf - minf)) / PEQChannel::maxFrequency;
    125 	scale = 1.0f / scale;
    126 	scale = sqrtf(scale); // FIXME: someday prove this is correct.
    127 	return 2.0f * scale * ef;
    128 }
    129 
    130 
    131 #define BAND_EXCLUDE "band_exclude"
    132 
    133 json_t* BandExcludeModule::saveToJson(json_t* root) {
    134 	json_object_set_new(root, BAND_EXCLUDE, json_boolean(_bandExclude));
    135 	return root;
    136 }
    137 
    138 void BandExcludeModule::loadFromJson(json_t* root) {
    139 	json_t* be = json_object_get(root, BAND_EXCLUDE);
    140 	if (be) {
    141 		_bandExclude = json_is_true(be);
    142 	}
    143 }
    144 
    145 
    146 void BandExcludeModuleWidget::contextMenu(Menu* menu) {
    147 	auto m = dynamic_cast<BandExcludeModule*>(module);
    148 	assert(m);
    149 	menu->addChild(new BoolOptionMenuItem("Exclude direct-output bands from mix", [m]() { return &m->_bandExclude; }));
    150 }