commit 405193687ea68bc76ab6d8d32aa93ec713dc6e75
parent 5e0d39c205a97068fb668330091d2a71f7be547a
Author: Matt Demanett <matt@demanett.net>
Date: Mon, 10 Jan 2022 22:59:30 -0500
Fix pops/glitches in oscillator pulse outputs when using audio rate PWM. #193
Diffstat:
2 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -171,10 +171,15 @@ void SquareOscillator::setPulseWidth(float pw) {
else if (pw <= minPulseWidth) {
pw = minPulseWidth;
}
- _pulseWidth = cyclePhase * pw;
+ _nextPulseWidth = cyclePhase * pw;
}
float SquareOscillator::nextForPhase(phase_t phase) {
+ phase_t cycle = phase / cyclePhase;
+ if (_lastCycle != cycle) {
+ _lastCycle = cycle;
+ _pulseWidth = _nextPulseWidth;
+ }
phase %= cyclePhase;
if (positive) {
@@ -205,19 +210,27 @@ void BandLimitedSquareOscillator::setPulseWidth(float pw, bool dcCorrection) {
else if (pw <= minPulseWidth) {
pw = minPulseWidth;
}
- _pulseWidth = cyclePhase * pw;
+ _nextPulseWidth = cyclePhase * pw;
if (pw > 0.5) {
- _offset = 2.0f * pw - 1.0f;
+ _nextOffset = 2.0f * pw - 1.0f;
}
else {
- _offset = -(1.0f - 2.0f * pw);
+ _nextOffset = -(1.0f - 2.0f * pw);
}
- _dcOffset = _dcCorrection ? 1.0f - 2.0f * pw : 0.0f;
+ _nextDcOffset = _dcCorrection ? 1.0f - 2.0f * pw : 0.0f;
}
float BandLimitedSquareOscillator::nextForPhase(phase_t phase) {
+ phase_t cycle = phase / cyclePhase;
+ if (_lastCycle != cycle) {
+ _lastCycle = cycle;
+ _pulseWidth = _nextPulseWidth;
+ _offset = _nextOffset;
+ _dcOffset = _nextDcOffset;
+ }
+
float sample = -BandLimitedSawOscillator::nextForPhase(phase);
sample += BandLimitedSawOscillator::nextForPhase(phase - _pulseWidth);
return sample + _offset + _dcOffset;
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -219,7 +219,8 @@ struct SquareOscillator : Phasor {
static constexpr float maxPulseWidth = 1.0f - minPulseWidth;
static constexpr float defaultPulseWidth = 0.5f;
float _pulseWidthInput;
- phase_t _pulseWidth = cyclePhase * defaultPulseWidth;
+ phase_t _lastCycle = -1;
+ phase_t _pulseWidth = cyclePhase * defaultPulseWidth, _nextPulseWidth = cyclePhase * defaultPulseWidth;
bool positive = true;
SquareOscillator(
@@ -239,9 +240,10 @@ struct BandLimitedSquareOscillator : BandLimitedSawOscillator {
const float maxPulseWidth = 1.0f - minPulseWidth;
float _pulseWidthInput= -1.0f;
bool _dcCorrection = false;
- phase_delta_t _pulseWidth;
- float _offset;
- float _dcOffset;
+ phase_t _lastCycle = -1;
+ phase_delta_t _pulseWidth = 0, _nextPulseWidth = 0;
+ float _offset = 0.0f, _nextOffset = 0.0f;
+ float _dcOffset = 0.0f, _nextDcOffset = 0.0f;
BandLimitedSquareOscillator(
float sampleRate = 1000.0f,