commit 0156f1d17b206255129835b0009eb9511cd69a99
parent c4dc8c4a069f0c092c5cd3af439886f3e7b04afe
Author: Matt Demanett <matt@demanett.net>
Date: Fri, 10 Jul 2020 00:26:44 -0400
FFB: replace silly VCA thing with frequency CV.
Diffstat:
4 files changed, 70 insertions(+), 31 deletions(-)
diff --git a/res-src/FFB-src.svg b/res-src/FFB-src.svg
@@ -55,14 +55,14 @@
</g>
</symbol>
- <symbol id="knobguide-mintick" viewBox="0 0 40px 40px">
+ <symbol id="knobguide-centertick" viewBox="0 0 40px 40px">
<g transform="translate(20 20)">
- <g transform="rotate(-240) translate(10 0)">
+ <g transform="rotate(-90) translate(10 0)">
<polyline points="0,0 4,0" stroke-width="1" stroke="#333" />
</g>
- <path d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(0)" />
+ <path d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(20)" />
<path d="M 0 -12.5 A 12.5 12.5 0 0 1 12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(43)" />
- <path d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(0)" />
+ <path d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(-20)" />
<path d="M 0 -12.5 A 12.5 12.5 0 0 0 -12.5 0" stroke="#333" stroke-width="0.5" stroke-linecap="round" fill="none" transform="rotate(-43)" />
</g>
</symbol>
@@ -183,9 +183,9 @@
<!-- <use id="LOWWPASS_LIGHT" xlink:href="#light-small" transform="translate(1 8.5)" /> -->
</g>
<g transform="translate(41 228)">
- <text font-size="6pt" letter-spacing="2px" transform="translate(12.5 6)">CV</text>
+ <text font-size="6pt" letter-spacing="2px" transform="translate(6 6)">FREQ</text>
<use id="CV_PARAM" xlink:href="#knob-smallest" transform="translate(11 18.5)" />
- <use xlink:href="#knobguide-mintick" transform="translate(-1 6.5)" />
+ <use xlink:href="#knobguide-centertick" transform="translate(-1 6.5)" />
</g>
<g transform="translate(80.5 228)">
<text font-size="6pt" letter-spacing="2px" transform="translate(12.5 6)">HP</text>
@@ -203,7 +203,7 @@
</g>
<g transform="translate(32 0)">
<use id="CV_INPUT" xlink:href="#input" transform="translate(3 4)" />
- <text font-size="6pt" letter-spacing="2px" transform="translate(8.5 39)">CV</text>
+ <text font-size="6pt" letter-spacing="2px" transform="translate(5.5 39)">FCV</text>
</g>
</g>
<g transform="translate(13 320)">
diff --git a/res/FFB.svg b/res/FFB.svg
Binary files differ.
diff --git a/src/FFB.cpp b/src/FFB.cpp
@@ -1,34 +1,67 @@
#include "FFB.hpp"
+#include "dsp/pitch.hpp"
void FFB::Engine::sampleRateChange() {
float sr = APP->engine->getSampleRate();
for (int i = 0; i < 14; i++) {
_slews[i].setParams(sr, 1.0f, 1.0f);
}
+ configureBands(sr, _semitonesOffset);
+}
+
+void FFB::Engine::setSemitonesOffset(float semitonesOffset) {
+ if (_semitonesOffset != semitonesOffset) {
+ _semitonesOffset = semitonesOffset;
+ configureBands(APP->engine->getSampleRate(), _semitonesOffset);
+ }
+}
- auto bp = [this, sr](int i, float cutoff) {
+void FFB::Engine::configureBands(float sr, float semitonesOffset) {
+ _lowPass.setParams(
+ sr,
+ MultimodeFilter::BUTTERWORTH_TYPE,
+ 12.0f,
+ MultimodeFilter::LOWPASS_MODE,
+ bandFrequency(0, semitonesOffset),
+ 0.0f
+ );
+ for (int i = 0; i < 12; ++i) {
_bandPasses[i].setParams(
sr,
- cutoff,
+ bandFrequency(i + 1, semitonesOffset),
0.22f / MultimodeFilter::maxBWPitch,
MultimodeFilter::PITCH_BANDWIDTH_MODE
);
+ }
+ _highPass.setParams(
+ sr,
+ MultimodeFilter::BUTTERWORTH_TYPE,
+ 12.0f,
+ MultimodeFilter::HIGHPASS_MODE,
+ bandFrequency(13, semitonesOffset),
+ 0.0f
+ );
+}
+
+float FFB::Engine::bandFrequency(int i, float semitonesOffset) {
+ static const float fs[14] = {
+ 95.0f,
+ 125.0f,
+ 175.0f,
+ 250.0f,
+ 350.0f,
+ 500.0f,
+ 700.0f,
+ 1000.0f,
+ 1400.0f,
+ 2000.0f,
+ 2800.0f,
+ 4000.0f,
+ 5600.0f,
+ 6900.0f
};
- _lowPass.setParams(sr, MultimodeFilter::BUTTERWORTH_TYPE, 12.0f, MultimodeFilter::LOWPASS_MODE, 95.0f, 0.0f);
- bp(0, 125.0f);
- bp(1, 175.0f);
- bp(2, 250.0f);
- bp(3, 350.0f);
- bp(4, 500.0f);
- bp(5, 700.0f);
- bp(6, 1000.0f);
- bp(7, 1400.0f);
- bp(8, 2000.0f);
- bp(9, 2800.0f);
- bp(10, 4000.0f);
- bp(11, 5600.0f);
- _highPass.setParams(sr, MultimodeFilter::BUTTERWORTH_TYPE, 12.0f, MultimodeFilter::HIGHPASS_MODE, 6900.0f, 0.0f);
+ return semitoneToFrequency(frequencyToSemitone(fs[i]) + semitonesOffset);
}
void FFB::sampleRateChange() {
@@ -63,18 +96,19 @@ void FFB::modulate() {
void FFB::modulateChannel(int c) {
Engine& e = *_engines[c];
- float cv = 1.0f;
- if (inputs[CV_INPUT].isConnected()) {
- cv = clamp(inputs[CV_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f);
- cv *= clamp(params[CV_PARAM].getValue(), 0.0f, 1.0f);
- }
-
for (int i = 0; i < 14; ++i) {
- float level = e._slews[i].next(_levels[i] * cv);
+ float level = e._slews[i].next(_levels[i]);
level = 1.0f - level;
level *= Amplifier::minDecibels;
e._amplifiers[i].setLevel(level);
}
+
+ float semitones = clamp(params[CV_PARAM].getValue(), -1.0f, 1.0f);
+ if (inputs[CV_INPUT].isConnected()) {
+ semitones *= clamp(inputs[CV_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f);
+ }
+ semitones *= 12.0f;
+ e.setSemitonesOffset(semitones);
}
void FFB::processChannel(const ProcessArgs& args, int c) {
diff --git a/src/FFB.hpp b/src/FFB.hpp
@@ -52,12 +52,17 @@ struct FFB : BGModule {
MultimodeFilter8 _highPass;
Amplifier _amplifiers[14];
bogaudio::dsp::SlewLimiter _slews[14];
+ float _semitonesOffset = 0.0f;
+ float _bandFrequencies[14] {};
Engine() {
sampleRateChange();
}
void sampleRateChange();
+ void setSemitonesOffset(float semitonesOffset);
+ void configureBands(float sr, float semitonesOffset);
+ float bandFrequency(int i, float semitonesOffset);
};
Engine* _engines[maxChannels] {};
@@ -78,7 +83,7 @@ struct FFB : BGModule {
configParam<AmplifierParamQuantity>(BAND_8_PARAM, 0.0f, 1.0f, 1.0f, "Band 8 level");
configParam<AmplifierParamQuantity>(BAND_12_PARAM, 0.0f, 1.0f, 1.0f, "Band 12 level");
configParam<AmplifierParamQuantity>(LOWPASS_PARAM, 0.0f, 1.0f, 1.0f, "Lowpass level");
- configParam(CV_PARAM, 0.0f, 1.0f, 1.0f, "Level CV", "%", 0.0f, 100.0f);
+ configParam(CV_PARAM, -1.0f, 1.0f, 0.0f, "Frequency offset", " semitones", 0.0f, 12.0f);
configParam<AmplifierParamQuantity>(HIGHPASS_PARAM, 0.0f, 1.0f, 1.0f, "Highpass level");
}