commit 3d4f7c1a481cb2060d574f1174aa810de47dc32e
parent 0569b10136b6d94550319991ff52a0720e4977ed
Author: Matt Demanett <matt@demanett.net>
Date: Tue, 10 Apr 2018 21:17:33 -0400
VCO/XCO fixes.
Diffstat:
6 files changed, 82 insertions(+), 75 deletions(-)
diff --git a/src/VCO.cpp b/src/VCO.cpp
@@ -35,7 +35,7 @@ void VCO::step() {
_baseVOct += clamp(inputs[PITCH_INPUT].value, -5.0f, 5.0f);
}
if (_slowMode) {
- _baseVOct -= 5.0f;
+ _baseVOct -= 7.0f;
}
_baseHz = cvToFrequency(_baseVOct);
@@ -88,29 +88,17 @@ void VCO::step() {
float squareOut = 0.0f;
float sawOut = 0.0f;
float triangleOut = 0.0f;
- _phasor.advancePhase();
- if (mix > 0.0f) {
- if (outputs[SQUARE_OUTPUT].active) {
- squareOut += mix * amplitude * _square.nextFromPhasor(_phasor, phaseOffset);
- }
- if (outputs[SAW_OUTPUT].active) {
- sawOut += mix * amplitude * _saw.nextFromPhasor(_phasor, phaseOffset);
- }
- if (outputs[TRIANGLE_OUTPUT].active) {
- triangleOut += mix * amplitude * _triangle.nextFromPhasor(_phasor, phaseOffset);
- }
- }
if (oMix > 0.0f) {
for (int i = 0; i < oversample; ++i) {
- _oversamplePhasor.advancePhase();
+ _phasor.advancePhase();
if (outputs[SQUARE_OUTPUT].active) {
- _squareBuffer[i] = _square.nextFromPhasor(_oversamplePhasor, phaseOffset);
+ _squareBuffer[i] = _square.nextFromPhasor(_phasor, phaseOffset);
}
if (outputs[SAW_OUTPUT].active) {
- _sawBuffer[i] = _saw.nextFromPhasor(_oversamplePhasor, phaseOffset);
+ _sawBuffer[i] = _saw.nextFromPhasor(_phasor, phaseOffset);
}
if (outputs[TRIANGLE_OUTPUT].active) {
- _triangleBuffer[i] = _saw.nextFromPhasor(_oversamplePhasor, phaseOffset);
+ _triangleBuffer[i] = _triangle.nextFromPhasor(_phasor, phaseOffset);
}
}
if (outputs[SQUARE_OUTPUT].active) {
@@ -124,8 +112,17 @@ void VCO::step() {
}
}
else {
- for (int i = 0; i < oversample; ++i) {
- _oversamplePhasor.advancePhase();
+ _phasor.advancePhase(oversample);
+ }
+ if (mix > 0.0f) {
+ if (outputs[SQUARE_OUTPUT].active) {
+ squareOut += mix * amplitude * _square.nextFromPhasor(_phasor, phaseOffset);
+ }
+ if (outputs[SAW_OUTPUT].active) {
+ sawOut += mix * amplitude * _saw.nextFromPhasor(_phasor, phaseOffset);
+ }
+ if (outputs[TRIANGLE_OUTPUT].active) {
+ triangleOut += mix * amplitude * _triangle.nextFromPhasor(_phasor, phaseOffset);
}
}
@@ -138,7 +135,6 @@ void VCO::step() {
void VCO::setSampleRate(float sampleRate) {
_oversampleThreshold = 0.06f * sampleRate;
_phasor.setSampleRate(sampleRate);
- _oversamplePhasor.setSampleRate(sampleRate);
_square.setSampleRate(sampleRate);
_saw.setSampleRate(sampleRate);
_squareDecimator.setParams(sampleRate, oversample);
@@ -149,8 +145,7 @@ void VCO::setSampleRate(float sampleRate) {
void VCO::setFrequency(float frequency) {
if (_frequency != frequency && frequency < 0.47f * _phasor._sampleRate) {
_frequency = frequency;
- _phasor.setFrequency(_frequency);
- _oversamplePhasor.setFrequency(_frequency / (float)oversample);
+ _phasor.setFrequency(_frequency / (float)oversample);
_square.setFrequency(_frequency);
_saw.setFrequency(_frequency);
}
diff --git a/src/VCO.hpp b/src/VCO.hpp
@@ -56,7 +56,6 @@ struct VCO : Module {
SchmittTrigger _syncTrigger;
Phasor _phasor;
- Phasor _oversamplePhasor;
BandLimitedSquareOscillator _square;
BandLimitedSawOscillator _saw;
TriangleOscillator _triangle;
@@ -71,7 +70,6 @@ struct VCO : Module {
VCO()
: Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS)
, _phasor(0.0f, 1.0f)
- , _oversamplePhasor(0.0f, 1.0f)
, _square(0.0f, 0.0f)
, _saw(0.0f, 0.0f)
, _triangle(0.0f, 0.0f)
diff --git a/src/XCO.cpp b/src/XCO.cpp
@@ -36,7 +36,7 @@ void XCO::step() {
_baseVOct += clamp(inputs[PITCH_INPUT].value, -5.0f, 5.0f);
}
if (_slowMode) {
- _baseVOct -= 5.0f;
+ _baseVOct -= 7.0f;
}
_baseHz = cvToFrequency(_baseVOct);
@@ -59,11 +59,11 @@ void XCO::step() {
}
_saw.setSaturation(saturation * 10.f);
- float sample = params[TRIANGLE_SAMPLE_PARAM].value * Phasor::maxSampleWidth;
+ _triangleSampleWidth = params[TRIANGLE_SAMPLE_PARAM].value * Phasor::maxSampleWidth;
if (inputs[TRIANGLE_SAMPLE_INPUT].active) {
- sample *= clamp(inputs[TRIANGLE_SAMPLE_INPUT].value / 10.0f, 0.0f, 1.0f);
+ _triangleSampleWidth *= clamp(inputs[TRIANGLE_SAMPLE_INPUT].value / 10.0f, 0.0f, 1.0f);
}
- _triangle.setSampleWidth(sample);
+ _triangle.setSampleWidth(_triangleSampleWidth);
_sineFeedback = params[SINE_FEEDBACK_PARAM].value;
if (inputs[SINE_FEEDBACK_INPUT].active) {
@@ -113,70 +113,73 @@ void XCO::step() {
oMix = 0.0f;
}
+ bool triangleSample = _triangleSampleWidth > 0.001f;
+ bool sineFeedback = _sineFeedback > 0.001f;
bool squareActive = outputs[MIX_OUTPUT].active || outputs[SQUARE_OUTPUT].active;
bool sawActive = outputs[MIX_OUTPUT].active || outputs[SAW_OUTPUT].active;
bool triangleActive = outputs[MIX_OUTPUT].active || outputs[TRIANGLE_OUTPUT].active;
bool sineActive = outputs[MIX_OUTPUT].active || outputs[SINE_OUTPUT].active;
+ bool squareOversample = squareActive && oMix > 0.0f;
+ bool sawOversample = sawActive && oMix > 0.0f;
+ bool triangleOversample = triangleActive && (triangleSample || oMix > 0.0f);
+ bool sineOversample = sineActive && sineFeedback;
+ bool squareNormal = squareActive && mix > 0.0f;
+ bool sawNormal = sawActive && mix > 0.0f;
+ bool triangleNormal = triangleActive && !triangleSample && mix > 0.0f;
+ bool sineNormal = sineActive && !sineFeedback;
float squareOut = 0.0f;
float sawOut = 0.0f;
float triangleOut = 0.0f;
float sineOut = 0.0f;
- float sineFeedbackOffset = 0.0f;
- if (_sineFeedback > 0.001f) {
- sineFeedbackOffset = Phasor::radiansToPhase(_sineFeedback * _phasor.next());
- }
- else {
- _phasor.advancePhase();
- }
-
- if (mix > 0.0f) {
- if (squareActive) {
- squareOut += mix * amplitude * _squareMix * _square.nextFromPhasor(_phasor, _squarePhaseOffset + phaseOffset);
- }
- if (sawActive) {
- sawOut += mix * amplitude * _sawMix * _saw.nextFromPhasor(_phasor, _sawPhaseOffset + phaseOffset);
- }
- if (triangleActive) {
- triangleOut += mix * amplitude * _triangleMix * _triangle.nextFromPhasor(_phasor, _trianglePhaseOffset + phaseOffset);
- }
- if (sineActive) {
- sineOut += mix * amplitude * _sineMix * _sine.nextFromPhasor(_phasor, sineFeedbackOffset + _sinePhaseOffset + phaseOffset);
- }
- }
+ float sineFeedbackOffset = sineFeedback ? Phasor::radiansToPhase(_sineFeedback * _phasor._phase) : 0.0f;
- if (oMix > 0.0f) {
+ if (squareOversample || sawOversample || triangleOversample || sineOversample) {
for (int i = 0; i < oversample; ++i) {
- _oversamplePhasor.advancePhase();
- if (squareActive) {
- _squareBuffer[i] = _square.nextFromPhasor(_oversamplePhasor, _squarePhaseOffset + phaseOffset);
+ _phasor.advancePhase();
+ if (squareOversample) {
+ _squareBuffer[i] = _square.nextFromPhasor(_phasor, _squarePhaseOffset + phaseOffset);
}
- if (sawActive) {
- _sawBuffer[i] = _saw.nextFromPhasor(_oversamplePhasor, _sawPhaseOffset + phaseOffset);
+ if (sawOversample) {
+ _sawBuffer[i] = _saw.nextFromPhasor(_phasor, _sawPhaseOffset + phaseOffset);
}
- if (triangleActive) {
- _triangleBuffer[i] = _triangle.nextFromPhasor(_oversamplePhasor, _trianglePhaseOffset + phaseOffset);
+ if (triangleOversample) {
+ _triangleBuffer[i] = _triangle.nextFromPhasor(_phasor, _trianglePhaseOffset + phaseOffset);
}
- if (sineActive) {
- _sineBuffer[i] = _sine.nextFromPhasor(_oversamplePhasor, sineFeedbackOffset + _sinePhaseOffset + phaseOffset);
+ if (sineOversample) {
+ _sineBuffer[i] = _sine.nextFromPhasor(_phasor, sineFeedbackOffset + _sinePhaseOffset + phaseOffset);
}
}
- if (squareActive) {
+ if (squareOversample) {
squareOut += oMix * amplitude * _squareDecimator.next(oversample, _squareBuffer);
}
- if (sawActive) {
+ if (sawOversample) {
sawOut += oMix * amplitude * _sawDecimator.next(oversample, _sawBuffer);
}
- if (triangleActive) {
- triangleOut += oMix * amplitude * _triangleDecimator.next(oversample, _triangleBuffer);
+ if (triangleOversample) {
+ triangleOut += amplitude * _triangleDecimator.next(oversample, _triangleBuffer);
+ if (!triangleSample) {
+ triangleOut *= oMix;
+ }
}
- if (sineActive) {
- sineOut += oMix * amplitude * _sineDecimator.next(oversample, _sineBuffer);
+ if (sineOversample) {
+ sineOut += amplitude * _sineDecimator.next(oversample, _sineBuffer);
}
}
else {
- for (int i = 0; i < oversample; ++i) {
- _oversamplePhasor.advancePhase();
- }
+ _phasor.advancePhase(oversample);
+ }
+
+ if (squareNormal) {
+ squareOut += mix * amplitude * _squareMix * _square.nextFromPhasor(_phasor, _squarePhaseOffset + phaseOffset);
+ }
+ if (sawNormal) {
+ sawOut += mix * amplitude * _sawMix * _saw.nextFromPhasor(_phasor, _sawPhaseOffset + phaseOffset);
+ }
+ if (triangleNormal) {
+ triangleOut += mix * amplitude * _triangleMix * _triangle.nextFromPhasor(_phasor, _trianglePhaseOffset + phaseOffset);
+ }
+ if (sineNormal) {
+ sineOut += amplitude * _sineMix * _sine.nextFromPhasor(_phasor, sineFeedbackOffset + _sinePhaseOffset + phaseOffset);
}
outputs[SQUARE_OUTPUT].value = squareOut;
@@ -205,7 +208,6 @@ float XCO::level(Param& param, Input& input) {
void XCO::setSampleRate(float sampleRate) {
_oversampleThreshold = 0.06f * sampleRate;
_phasor.setSampleRate(sampleRate);
- _oversamplePhasor.setSampleRate(sampleRate);
_square.setSampleRate(sampleRate);
_saw.setSampleRate(sampleRate);
_squareDecimator.setParams(sampleRate, oversample);
@@ -217,8 +219,7 @@ void XCO::setSampleRate(float sampleRate) {
void XCO::setFrequency(float frequency) {
if (_frequency != frequency && frequency < 0.47f * _phasor._sampleRate) {
_frequency = frequency;
- _phasor.setFrequency(_frequency);
- _oversamplePhasor.setFrequency(_frequency / (float)oversample);
+ _phasor.setFrequency(_frequency / (float)oversample);
_square.setFrequency(_frequency);
_saw.setFrequency(_frequency);
}
diff --git a/src/XCO.hpp b/src/XCO.hpp
@@ -76,6 +76,7 @@ struct XCO : Module {
bool _slowMode = false;
float _fmDepth = 0.0f;
bool _fmLinearMode = false;
+ float _triangleSampleWidth = 0.0f;
float _sineFeedback = 0.0f;
float _squarePhaseOffset = 0.0f;
float _sawPhaseOffset = 0.0f;
@@ -88,7 +89,6 @@ struct XCO : Module {
SchmittTrigger _syncTrigger;
Phasor _phasor;
- Phasor _oversamplePhasor;
BandLimitedSquareOscillator _square;
BandLimitedSawOscillator _saw;
TriangleOscillator _triangle;
@@ -105,7 +105,6 @@ struct XCO : Module {
XCO()
: Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS)
, _phasor(0.0f, 1.0f)
- , _oversamplePhasor(0.0f, 1.0f)
, _square(0.0f, 0.0f)
, _saw(0.0f, 0.0f)
, _triangle(0.0f, 0.0f)
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -79,6 +79,19 @@ void Phasor::advancePhase() {
assert(_phase < maxPhase);
}
+void Phasor::advancePhase(int n) {
+ assert(n > 0);
+ _phase += n * _delta;
+ if (_phase >= maxPhase) {
+ _phase -= maxPhase;
+ }
+ if (_phase < 0.0f) {
+ _phase += maxPhase;
+ }
+ assert(_phase >= 0.0f);
+ assert(_phase < maxPhase);
+}
+
void Phasor::advancePhasePositive() {
assert(_delta >= 0.0f);
_phase += _delta;
@@ -161,7 +174,7 @@ void SaturatingSawOscillator::setSaturation(float saturation) {
float SaturatingSawOscillator::_nextForPhase(float phase) {
float sample = SawOscillator::_nextForPhase(phase);
if (_saturation >= 0.1f) {
- sample = tanhf(-sample * _saturation * M_PI) * _saturationNormalization;
+ sample = tanhf(sample * _saturation * M_PI) * _saturationNormalization;
}
return sample;
}
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -87,6 +87,7 @@ struct Phasor : OscillatorGenerator {
float nextForPhase(float phase); // local phase, not radians.
virtual void _update();
void advancePhase();
+ void advancePhase(int n);
void advancePhasePositive();
virtual float _next() override final;
virtual float _nextForPhase(float phase);