commit a76c24aeba9b3fc966d0b53584136ad0c756b500
parent 247cd235c06c4ab32cbc274ff1b65233d0bfcabe
Author: Matt Demanett <matt@demanett.net>
Date: Sat, 14 Apr 2018 22:43:38 -0400
Fix feedback FM.
Diffstat:
10 files changed, 25 insertions(+), 35 deletions(-)
diff --git a/res-src/FMOp-src.svg b/res-src/FMOp-src.svg
@@ -316,13 +316,13 @@
<text font-size="6pt" letter-spacing="1px" transform="translate(1 40)">V/OCT</text>
</g>
<g transform="translate(34 0)">
- <use id="GATE_INPUT" xlink:href="#input" transform="translate(3 5)" />
- <text font-size="6pt" letter-spacing="1px" transform="translate(3 40)">GATE</text>
- </g>
- <g transform="translate(66 0)">
<use id="FM_INPUT" xlink:href="#input" transform="translate(3 5)" />
<text font-size="6pt" letter-spacing="1px" transform="translate(8.5 40)">FM</text>
</g>
+ <g transform="translate(66 0)">
+ <use id="GATE_INPUT" xlink:href="#input" transform="translate(3 5)" />
+ <text font-size="6pt" letter-spacing="1px" transform="translate(3 40)">GATE</text>
+ </g>
<g transform="translate(98 0)">
<use id="AUDIO_OUTPUT" xlink:href="#output" transform="translate(3 5)" />
<text font-size="6pt" letter-spacing="1px" transform="translate(6 40)">OUT</text>
diff --git a/res/FMOp.svg b/res/FMOp.svg
Binary files differ.
diff --git a/src/EightFO.cpp b/src/EightFO.cpp
@@ -92,7 +92,7 @@ void EightFO::step() {
_phase0Offset = phaseOffset(params[PHASE0_PARAM], inputs[PHASE0_INPUT], basePhase0Offset);
}
- _phasor.next();
+ _phasor.advancePhase();
bool useSample = true;
++_sampleStep;
if (_sampleStep >= _sampleSteps) {
diff --git a/src/FMOp.cpp b/src/FMOp.cpp
@@ -105,7 +105,10 @@ void FMOp::step() {
feedback *= envelope;
}
- float offset = feedback * _phasor._phase;
+ float offset = 0.0f;
+ if (feedback > 0.001f) {
+ offset = feedback * _feedbackDelayedSample;
+ }
if (inputs[FM_INPUT].active) {
offset += inputs[FM_INPUT].value * _depth * 2.0f;
}
@@ -119,7 +122,7 @@ void FMOp::step() {
if (_levelEnvelopeOn) {
out *= envelope;
}
- outputs[AUDIO_OUTPUT].value = amplitude * out;
+ outputs[AUDIO_OUTPUT].value = _feedbackDelayedSample = amplitude * out;
}
struct FMOpWidget : ModuleWidget {
@@ -156,8 +159,8 @@ struct FMOpWidget : ModuleWidget {
auto levelInputPosition = Vec(79.0, 274.0);
auto sustainInputPosition = Vec(111.0, 274.0);
auto pitchInputPosition = Vec(15.0, 318.0);
- auto gateInputPosition = Vec(47.0, 318.0);
- auto fmInputPosition = Vec(79.0, 318.0);
+ auto fmInputPosition = Vec(47.0, 318.0);
+ auto gateInputPosition = Vec(79.0, 318.0);
auto audioOutputPosition = Vec(111.0, 318.0);
diff --git a/src/FMOp.hpp b/src/FMOp.hpp
@@ -54,6 +54,7 @@ struct FMOp : Module {
static constexpr int oversample = 8;
int _steps = 0;
float _feedback = 0.0f;
+ float _feedbackDelayedSample = 0.0f;
float _depth = 0.0f;
float _level = 0.0f;
bool _envelopeOn = false;
diff --git a/src/LFO.cpp b/src/LFO.cpp
@@ -77,7 +77,7 @@ void LFO::step() {
}
}
- _phasor.next();
+ _phasor.advancePhase();
bool useSample = true;
++_sampleStep;
if (_sampleStep >= _sampleSteps) {
diff --git a/src/Test.cpp b/src/Test.cpp
@@ -297,26 +297,12 @@ void Test::step() {
#elif FEEDBACK_PM
_carrier.setSampleRate(engineGetSampleRate());
_carrier.setFrequency(oscillatorPitch());
- float feedback = params[PARAM3_PARAM].value;
- if (inputs[CV3_INPUT].active) {
- feedback *= clamp(inputs[CV3_INPUT].value, 0.0f, 10.0f) / 10.0f;
+ float feedback = params[PARAM2_PARAM].value;
+ if (inputs[CV2_INPUT].active) {
+ feedback *= clamp(inputs[CV2_INPUT].value, 0.0f, 10.0f) / 10.0f;
}
- // feedback *= 10.0f;
-
- // no delay:
- feedback *= _carrier.next();
-
- // // 1 sample:
- // feedback *= _carrier.current();
- // _carrier.next();
-
- // // 2 samples averaged:
- // float feedbackSample = _carrier.current();
- // _carrier.next();
- // feedback *= (_feedbackSample + feedbackSample) / 2.0f;
- // _feedbackSample = feedbackSample;
-
- outputs[OUT_OUTPUT].value = _carrierOutput.nextFromPhasor(_carrier, Phasor::radiansToPhase(feedback)) * 5.0f;
+ _carrier.advancePhase();
+ outputs[OUT_OUTPUT].value = _feedbackSample = _carrier.nextFromPhasor(_carrier, Phasor::radiansToPhase(feedback * _feedbackSample)) * 5.0f;
#elif EG
_envelope.setSampleRate(engineGetSampleRate());
diff --git a/src/Test.hpp b/src/Test.hpp
@@ -15,10 +15,10 @@ extern Model* modelTest;
// #define SINEBANK 1
// #define OVERSAMPLING 1
// #define OVERSAMPLED_BL 1
-#define ANTIALIASING 1
+// #define ANTIALIASING 1
// #define FM 1
// #define PM 1
-// #define FEEDBACK_PM 1
+#define FEEDBACK_PM 1
// #define EG 1
// #define TABLES 1
@@ -158,8 +158,7 @@ struct Test : Module {
SineTableOscillator _modulator;
SineTableOscillator _carrier;
#elif FEEDBACK_PM
- Phasor _carrier;
- SineTableOscillator _carrierOutput;
+ SineTableOscillator _carrier;
float _feedbackSample = 0.0f;
#elif EG
ADSR _envelope;
diff --git a/src/XCO.cpp b/src/XCO.cpp
@@ -131,7 +131,7 @@ void XCO::step() {
float sawOut = 0.0f;
float triangleOut = 0.0f;
float sineOut = 0.0f;
- float sineFeedbackOffset = sineFeedback ? Phasor::radiansToPhase(_sineFeedback * _phasor._phase) : 0.0f;
+ float sineFeedbackOffset = sineFeedback ? Phasor::radiansToPhase(_sineFeedback * _sineFeedbackDelayedSample) : 0.0f;
if (squareOversample || sawOversample || triangleOversample || sineOversample) {
for (int i = 0; i < oversample; ++i) {
@@ -185,7 +185,7 @@ void XCO::step() {
outputs[SQUARE_OUTPUT].value = squareOut;
outputs[SAW_OUTPUT].value = sawOut;
outputs[TRIANGLE_OUTPUT].value = triangleOut;
- outputs[SINE_OUTPUT].value = sineOut;
+ outputs[SINE_OUTPUT].value = _sineFeedbackDelayedSample = sineOut;
outputs[MIX_OUTPUT].value = squareOut + sawOut + triangleOut + sineOut;
}
diff --git a/src/XCO.hpp b/src/XCO.hpp
@@ -78,6 +78,7 @@ struct XCO : Module {
bool _fmLinearMode = false;
float _triangleSampleWidth = 0.0f;
float _sineFeedback = 0.0f;
+ float _sineFeedbackDelayedSample = 0.0f;
float _squarePhaseOffset = 0.0f;
float _sawPhaseOffset = 0.0f;
float _trianglePhaseOffset = 0.0f;