commit 2aeb0c15671fad693e43ec88e1722d0d34e140d7
parent 4c9d6c319b0b27dfbd7c2163938f333eb9a43d39
Author: Matt Demanett <matt@demanett.net>
Date: Thu, 18 Jan 2018 00:19:37 -0500
Add functions for pitch calculations in dsp lib; refactor Reftone to use them; implement Detune.
Diffstat:
3 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/src/Detune.cpp b/src/Detune.cpp
@@ -1,5 +1,8 @@
#include "bogaudio.hpp"
+#include "dsp/pitch.hpp"
+
+using namespace bogaudio::dsp;
struct Detune : Module {
enum ParamsIds {
@@ -31,15 +34,52 @@ struct Detune : Module {
reset();
}
- virtual void reset() override;
virtual void step() override;
};
-void Detune::reset() {
-}
-
void Detune::step() {
- lights[QUANTIZE_LIGHT].value = params[QUANTIZE_PARAM].value == 1.0;
+ if (!(outputs[OUT_PLUS_OUTPUT].active || outputs[OUT_MINUS_OUTPUT].active || outputs[THRU_OUTPUT].active)) {
+ return;
+ }
+
+ float cents = params[CENTS_PARAM].value;
+ if (inputs[CV_INPUT].active) {
+ cents *= clampf(inputs[CV_INPUT].value, 0.0, 10.0) / 10.0;
+ }
+ if (params[QUANTIZE_PARAM].value > 0.5) {
+ cents = roundf(cents);
+ }
+ cents /= 100.0;
+
+ if (inputs[IN_INPUT].active) {
+ float cv = inputs[IN_INPUT].value;
+ outputs[THRU_OUTPUT].value = cv;
+ if (cents < 0.001) {
+ outputs[OUT_PLUS_OUTPUT].value = cv;
+ outputs[OUT_MINUS_OUTPUT].value = cv;
+ }
+ else {
+ float semitone = cvToSemitone(cv);
+ outputs[OUT_PLUS_OUTPUT].value = semitoneToCV(semitone + cents);
+ outputs[OUT_MINUS_OUTPUT].value = semitoneToCV(semitone - cents);
+ }
+ }
+ else {
+ const float frequency = 440.0;
+ const float cv = frequencyToCV(frequency);
+ const float semitone = frequencyToSemitone(frequency);
+ outputs[THRU_OUTPUT].value = cv;
+ if (cents < 0.001) {
+ outputs[OUT_PLUS_OUTPUT].value = cv;
+ outputs[OUT_MINUS_OUTPUT].value = cv;
+ }
+ else {
+ outputs[OUT_PLUS_OUTPUT].value = semitoneToCV(semitone + cents);
+ outputs[OUT_MINUS_OUTPUT].value = semitoneToCV(semitone - cents);
+ }
+ }
+
+ lights[QUANTIZE_LIGHT].value = params[QUANTIZE_PARAM].value > 0.5;
}
@@ -74,7 +114,7 @@ DetuneWidget::DetuneWidget() {
// end generated by svg_widgets.rb
{
- auto w = createParam<Knob26>(centsParamPosition, module, Detune::CENTS_PARAM, 0.0, 10.0, 0.0);
+ auto w = createParam<Knob26>(centsParamPosition, module, Detune::CENTS_PARAM, 0.0, 50.0, 0.0);
dynamic_cast<Knob*>(w)->snap = true;
addParam(w);
}
diff --git a/src/Reftone.cpp b/src/Reftone.cpp
@@ -1,6 +1,7 @@
#include "bogaudio.hpp"
#include "dsp/oscillator.hpp"
+#include "dsp/pitch.hpp"
using namespace bogaudio::dsp;
@@ -46,18 +47,17 @@ struct Reftone : Module {
};
void Reftone::step() {
- const float f0 = 261.626;
- const int f0Pitch = 0;
- const int f0Octave = 4;
- const float twelfthRootTwo = 1.0594630943592953;
+ // C4 -- the pitch.hpp reference frequency -- in knob values:
+ const int referencePitch = 0;
+ const int referenceOctave = 4;
_pitch = clampf(params[PITCH_PARAM].value, 0.0, 11.0);
_octave = clampf(params[OCTAVE_PARAM].value, 1.0, 8.0);
_fine = clampf(params[FINE_PARAM].value, -0.99, 0.99);
- _frequency = f0*powf(twelfthRootTwo, 12*(_octave - f0Octave) + (_pitch - f0Pitch) + _fine);
+ _frequency = semitoneToFrequency(referenceSemitone + 12*(_octave - referenceOctave) + (_pitch - referencePitch) + _fine);
if (outputs[CV_OUTPUT].active) {
- outputs[CV_OUTPUT].value = log2f(_frequency / f0);
+ outputs[CV_OUTPUT].value = frequencyToCV(_frequency);
}
else {
outputs[CV_OUTPUT].value = 0.0;
diff --git a/src/dsp/pitch.hpp b/src/dsp/pitch.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+namespace bogaudio {
+namespace dsp {
+
+const float referenceFrequency = 261.626; // C4; frequency at which Rack 1v/octave CVs are zero.
+const float referenceSemitone = 60.0; // C4; value of C4 in semitones is arbitrary here, so have it match midi note numbers when rounded to integer.
+const float twelfthRootTwo = 1.0594630943592953;
+const float logTwelfthRootTwo = logf(1.0594630943592953);
+
+inline float frequencyToSemitone(float frequency) {
+ return logf(frequency / referenceFrequency) / logTwelfthRootTwo + referenceSemitone;
+}
+
+inline float semitoneToFrequency(float semitone) {
+ return powf(twelfthRootTwo, semitone - referenceSemitone) * referenceFrequency;
+}
+
+inline float frequencyToCV(float frequency) {
+ return log2f(frequency / referenceFrequency);
+}
+
+inline float cvToFrequency(float cv) {
+ return powf(2.0, cv) * referenceFrequency;
+}
+
+inline float cvToSemitone(float cv) {
+ return frequencyToSemitone(cvToFrequency(cv));
+}
+
+inline float semitoneToCV(float semitone) {
+ return frequencyToCV(semitoneToFrequency(semitone));
+}
+
+} // namespace dsp
+} // namespace bogaudio