commit b9de1058b50ed44df3b6b8d540f208081ed65776
parent a76c24aeba9b3fc966d0b53584136ad0c756b500
Author: Matt Demanett <matt@demanett.net>
Date: Sun, 15 Apr 2018 14:42:29 -0400
Integer phasors.
Diffstat:
8 files changed, 101 insertions(+), 179 deletions(-)
diff --git a/src/EightFO.cpp b/src/EightFO.cpp
@@ -109,15 +109,15 @@ void EightFO::step() {
updateOutput(useSample, outputs[PHASE0_OUTPUT], _phase0Offset, _phase0Sample, _phase0Active);
}
-float EightFO::phaseOffset(Param& p, Input& i, float baseOffset) {
- float o = p.value * Phasor::maxPhase;
+Phasor::phase_delta_t EightFO::phaseOffset(Param& p, Input& i, Phasor::phase_delta_t baseOffset) {
+ float o = p.value * Phasor::maxPhase / 2.0f;
if (i.active) {
o *= clamp(i.value / 5.0f, -1.0f, 1.0f);
}
return baseOffset - o;
}
-void EightFO::updateOutput(bool useSample, Output& output, float& offset, float& sample, bool& active) {
+void EightFO::updateOutput(bool useSample, Output& output, Phasor::phase_delta_t& offset, float& sample, bool& active) {
if (output.active) {
if (useSample && active) {
output.value = sample;
diff --git a/src/EightFO.hpp b/src/EightFO.hpp
@@ -73,14 +73,14 @@ struct EightFO : Module {
const int modulationSteps = 100;
const float amplitude = 5.0f;
- const float basePhase7Offset = Phasor::radiansToPhase(1.75f * M_PI);
- const float basePhase6Offset = Phasor::radiansToPhase(1.5f * M_PI);
- const float basePhase5Offset = Phasor::radiansToPhase(1.25f * M_PI);
- const float basePhase4Offset = Phasor::radiansToPhase(M_PI);
- const float basePhase3Offset = Phasor::radiansToPhase(0.75f * M_PI);
- const float basePhase2Offset = Phasor::radiansToPhase(0.5f * M_PI);
- const float basePhase1Offset = Phasor::radiansToPhase(0.25f * M_PI);
- const float basePhase0Offset = Phasor::radiansToPhase(0.0f);
+ const Phasor::phase_delta_t basePhase7Offset = Phasor::radiansToPhase(1.75f * M_PI);
+ const Phasor::phase_delta_t basePhase6Offset = Phasor::radiansToPhase(1.5f * M_PI);
+ const Phasor::phase_delta_t basePhase5Offset = Phasor::radiansToPhase(1.25f * M_PI);
+ const Phasor::phase_delta_t basePhase4Offset = Phasor::radiansToPhase(M_PI);
+ const Phasor::phase_delta_t basePhase3Offset = Phasor::radiansToPhase(0.75f * M_PI);
+ const Phasor::phase_delta_t basePhase2Offset = Phasor::radiansToPhase(0.5f * M_PI);
+ const Phasor::phase_delta_t basePhase1Offset = Phasor::radiansToPhase(0.25f * M_PI);
+ const Phasor::phase_delta_t basePhase0Offset = Phasor::radiansToPhase(0.0f);
int _modulationStep = 0;
Wave _wave = NO_WAVE;
@@ -97,14 +97,14 @@ struct EightFO : Module {
SawOscillator _ramp;
SquareOscillator _square;
- float _phase7Offset = 0.0f;
- float _phase6Offset = 0.0f;
- float _phase5Offset = 0.0f;
- float _phase4Offset = 0.0f;
- float _phase3Offset = 0.0f;
- float _phase2Offset = 0.0f;
- float _phase1Offset = 0.0f;
- float _phase0Offset = 0.0f;
+ Phasor::phase_delta_t _phase7Offset = 0.0f;
+ Phasor::phase_delta_t _phase6Offset = 0.0f;
+ Phasor::phase_delta_t _phase5Offset = 0.0f;
+ Phasor::phase_delta_t _phase4Offset = 0.0f;
+ Phasor::phase_delta_t _phase3Offset = 0.0f;
+ Phasor::phase_delta_t _phase2Offset = 0.0f;
+ Phasor::phase_delta_t _phase1Offset = 0.0f;
+ Phasor::phase_delta_t _phase0Offset = 0.0f;
float _phase7Sample = 0.0f;
float _phase6Sample = 0.0f;
@@ -132,8 +132,8 @@ struct EightFO : Module {
virtual void onReset() override;
virtual void onSampleRateChange() override;
virtual void step() override;
- float phaseOffset(Param& p, Input& i, float baseOffset);
- void updateOutput(bool useSample, Output& output, float& offset, float& sample, bool& active);
+ Phasor::phase_delta_t phaseOffset(Param& p, Input& i, Phasor::phase_delta_t baseOffset);
+ void updateOutput(bool useSample, Output& output, Phasor::phase_delta_t& offset, float& sample, bool& active);
};
} // namespace bogaudio
diff --git a/src/FMOp.cpp b/src/FMOp.cpp
@@ -112,10 +112,9 @@ void FMOp::step() {
if (inputs[FM_INPUT].active) {
offset += inputs[FM_INPUT].value * _depth * 2.0f;
}
- offset = Phasor::radiansToPhase(offset);
for (int i = 0; i < oversample; ++i) {
_phasor.advancePhase();
- _buffer[i] = _sineTable.nextFromPhasor(_phasor, offset);
+ _buffer[i] = _sineTable.nextFromPhasor(_phasor, Phasor::radiansToPhase(offset));
}
float out = _decimator.next(oversample, _buffer);
out *= _level;
diff --git a/src/VCO.cpp b/src/VCO.cpp
@@ -56,7 +56,7 @@ void VCO::step() {
}
float frequency = _baseHz;
- float phaseOffset = 0.0f;
+ Phasor::phase_delta_t phaseOffset = 0;
if (inputs[FM_INPUT].active && _fmDepth > 0.01f) {
float fm = inputs[FM_INPUT].value * _fmDepth;
if (_fmLinearMode) {
diff --git a/src/XCO.cpp b/src/XCO.cpp
@@ -84,7 +84,7 @@ void XCO::step() {
}
float frequency = _baseHz;
- float phaseOffset = 0.0f;
+ Phasor::phase_delta_t phaseOffset = 0;
if (inputs[FM_INPUT].active && _fmDepth > 0.01f) {
float fm = inputs[FM_INPUT].value * _fmDepth;
if (_fmLinearMode) {
@@ -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 * _sineFeedbackDelayedSample) : 0.0f;
+ Phasor::phase_delta_t sineFeedbackOffset = sineFeedback ? Phasor::radiansToPhase(_sineFeedback * _sineFeedbackDelayedSample) : 0.0f;
if (squareOversample || sawOversample || triangleOversample || sineOversample) {
for (int i = 0; i < oversample; ++i) {
@@ -189,12 +189,12 @@ void XCO::step() {
outputs[MIX_OUTPUT].value = squareOut + sawOut + triangleOut + sineOut;
}
-float XCO::phaseOffset(Param& param, Input& input) {
+Phasor::phase_delta_t XCO::phaseOffset(Param& param, Input& input) {
float v = param.value;
if (input.active) {
v *= clamp(input.value / 5.0f, -1.0f, 1.0f);
}
- return -v;
+ return -v * Phasor::maxPhase / 2.0f;
}
float XCO::level(Param& param, Input& input) {
diff --git a/src/XCO.hpp b/src/XCO.hpp
@@ -79,10 +79,10 @@ struct XCO : Module {
float _triangleSampleWidth = 0.0f;
float _sineFeedback = 0.0f;
float _sineFeedbackDelayedSample = 0.0f;
- float _squarePhaseOffset = 0.0f;
- float _sawPhaseOffset = 0.0f;
- float _trianglePhaseOffset = 0.0f;
- float _sinePhaseOffset = 0.0f;
+ Phasor::phase_delta_t _squarePhaseOffset = 0.0f;
+ Phasor::phase_delta_t _sawPhaseOffset = 0.0f;
+ Phasor::phase_delta_t _trianglePhaseOffset = 0.0f;
+ Phasor::phase_delta_t _sinePhaseOffset = 0.0f;
float _squareMix = 1.0f;
float _sawMix = 1.0f;
float _triangleMix = 1.0f;
@@ -113,7 +113,7 @@ struct XCO : Module {
virtual void onReset() override;
virtual void onSampleRateChange() override;
virtual void step() override;
- float phaseOffset(Param& param, Input& input);
+ Phasor::phase_delta_t phaseOffset(Param& param, Input& input);
float level(Param& param, Input& input);
void setSampleRate(float sampleRate);
void setFrequency(float frequency);
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -14,10 +14,10 @@ void Phasor::setSampleWidth(float sw) {
if (_sampleWidth != sw) {
_sampleWidth = sw;
if (_sampleWidth > 0.001f) {
- _samplePhase = _sampleWidth * maxPhase;
+ _samplePhase = _sampleWidth * (float)maxPhase;
}
else {
- _samplePhase = 0.0f;
+ _samplePhase = 0;
}
}
}
@@ -26,104 +26,37 @@ void Phasor::setPhase(float radians) {
_phase = radiansToPhase(radians);
}
-float Phasor::nextFromPhasor(const Phasor& phasor, float offset) {
- float p = phasor._phase + offset;
- while (p >= maxPhase) {
- p -= maxPhase;
+float Phasor::nextFromPhasor(const Phasor& phasor, phase_delta_t offset) {
+ offset += phasor._phase;
+ if (_samplePhase > 0) {
+ offset -= offset % _samplePhase;
}
- while (p < 0.0f) {
- p += maxPhase;
- }
-
- if (_samplePhase > 0.0f) {
- p -= fmodf(p, _samplePhase);
- }
- return _nextForPhase(p);
+ return _nextForPhase(offset);
}
void Phasor::_update() {
- _delta = (_frequency / _sampleRate) * maxPhase;
- if (_delta >= maxPhase) {
- _delta -= maxPhase;
- if (_delta >= maxPhase) {
- _delta = fmodf(_delta, maxPhase);
- }
- }
- else if (_delta < 0.0f) {
- _delta += maxPhase;
- if (_delta < 0.0f) {
- _delta = maxPhase - fmodf(-_delta, maxPhase);
- }
- }
-}
-
-float Phasor::nextForPhase(float phase) {
- while (phase >= maxPhase) {
- phase -= maxPhase;
- }
- while (phase < 0.0f) {
- phase += maxPhase;
- }
- return _nextForPhase(phase);
-}
-
-void Phasor::advancePhase() {
- _phase += _delta;
- if (_phase >= maxPhase) {
- _phase -= maxPhase;
- }
- if (_phase < 0.0f) {
- _phase += maxPhase;
- }
- assert(_phase >= 0.0f);
- 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;
- if (_phase >= maxPhase) {
- _phase -= maxPhase;
- }
- assert(_phase < maxPhase);
+ _delta = ((phase_delta_t)((_frequency / _sampleRate) * maxPhase)) % maxPhase;
}
float Phasor::_next() {
advancePhase();
- if (_samplePhase > 0.0f) {
- return _nextForPhase(_phase - fmodf(_phase, _samplePhase));
+ if (_samplePhase > 0) {
+ return _nextForPhase(_phase - (_phase % _samplePhase));
}
return _nextForPhase(_phase);
}
-float Phasor::_nextForPhase(float phase) {
+float Phasor::_nextForPhase(phase_t phase) {
return phase;
}
-float TablePhasor::_nextForPhase(float phase) {
- while (phase >= maxPhase) {
- phase -= maxPhase;
- }
- while (phase < 0.0f) {
- phase += maxPhase;
- }
-
- float fi = phase * (_tableLength / 2);
+float TablePhasor::_nextForPhase(phase_t phase) {
+ float fi = (phase / (float)maxPhase) * _tableLength;
int i = (int)fi;
+ if (i >= _tableLength) {
+ i %= _tableLength;
+ }
float v1 = _table.value(i);
if (_tableLength >= 1024) {
return v1;
@@ -153,8 +86,8 @@ float SineOscillator::_next() {
}
-float SawOscillator::_nextForPhase(float phase) {
- return phase - halfMaxPhase;
+float SawOscillator::_nextForPhase(phase_t phase) {
+ return (phase / (float)maxPhase) * 2.0f - 1.0f;
}
@@ -171,7 +104,7 @@ void SaturatingSawOscillator::setSaturation(float saturation) {
}
}
-float SaturatingSawOscillator::_nextForPhase(float phase) {
+float SaturatingSawOscillator::_nextForPhase(phase_t phase) {
float sample = SawOscillator::_nextForPhase(phase);
if (_saturation >= 0.1f) {
sample = tanhf(sample * _saturation * M_PI) * _saturationNormalization;
@@ -194,15 +127,15 @@ void BandLimitedSawOscillator::_update() {
_qd = q * _delta;
}
-float BandLimitedSawOscillator::_nextForPhase(float phase) {
+float BandLimitedSawOscillator::_nextForPhase(phase_t phase) {
float sample = SaturatingSawOscillator::_nextForPhase(phase);
if (phase > maxPhase - _qd) {
- float i = (maxPhase - phase) / _qd;
+ float i = (maxPhase - phase) / (float)_qd;
i = (1.0f - i) * _halfTableLen;
sample -= _table.value((int)i);
}
else if (phase < _qd) {
- float i = phase / _qd;
+ float i = phase / (float)_qd;
i *= _halfTableLen - 1;
i += _halfTableLen;
sample -= _table.value((int)i);
@@ -218,18 +151,15 @@ void SquareOscillator::setPulseWidth(float pw) {
_pulseWidthInput = pw;
if (pw >= maxPulseWidth) {
- _pulseWidth = maxPulseWidth;
+ pw = maxPulseWidth;
}
else if (pw <= minPulseWidth) {
- _pulseWidth = minPulseWidth;
- }
- else {
- _pulseWidth = pw;
+ pw = minPulseWidth;
}
- _pulseWidth *= maxPhase;
+ _pulseWidth = maxPhase * pw;
}
-float SquareOscillator::_nextForPhase(float phase) {
+float SquareOscillator::_nextForPhase(phase_t phase) {
if (positive) {
if (phase >= _pulseWidth) {
positive = false;
@@ -252,44 +182,37 @@ void BandLimitedSquareOscillator::setPulseWidth(float pw) {
_pulseWidthInput = pw;
if (pw >= maxPulseWidth) {
- _pulseWidth = maxPulseWidth;
+ pw = maxPulseWidth;
}
else if (pw <= minPulseWidth) {
- _pulseWidth = minPulseWidth;
+ pw = minPulseWidth;
}
- else {
- _pulseWidth = pw;
- }
- _pulseWidth *= maxPhase;
+ _pulseWidth = maxPhase * pw;
- if (_pulseWidth >= 1.0f) {
- _offset = _pulseWidth - 1.0f;
+ if (pw > 0.5) {
+ _offset = 2.0f * pw - 1.0f;
}
else {
- _offset = -(1.0f - _pulseWidth);
+ _offset = -(1.0f - 2.0f * pw);
}
}
-float BandLimitedSquareOscillator::_nextForPhase(float phase) {
+float BandLimitedSquareOscillator::_nextForPhase(phase_t phase) {
float sample = -BandLimitedSawOscillator::_nextForPhase(phase);
- phase -= _pulseWidth;
- if (phase < 0.0f) {
- phase += maxPhase;
- }
- sample += BandLimitedSawOscillator::_nextForPhase(phase);
+ sample += BandLimitedSawOscillator::_nextForPhase(phase - _pulseWidth);
return sample + _offset;
}
-float TriangleOscillator::_nextForPhase(float phase) {
- float p = maxPhase * phase;
+float TriangleOscillator::_nextForPhase(phase_t phase) {
+ float p = (phase / (float)maxPhase) * 4.0f;
if (phase < quarterMaxPhase) {
return p;
}
if (phase < threeQuartersMaxPhase) {
- return maxPhase - p;
+ return 2.0f - p;
}
- return p - twiceMaxPhase;
+ return p - 4.0f;
}
@@ -346,10 +269,10 @@ void SineBankOscillator::_frequencyChanged() {
}
}
-float SineBankOscillator::next(float phaseOffset) {
+float SineBankOscillator::next(Phasor::phase_t phaseOffset) {
float next = 0.0;
for (Partial& p : _partials) {
- p.sine.advancePhasePositive();
+ p.sine.advancePhase();
if (p.frequency < _maxPartialFrequency && (p.amplitude > 0.001 || p.amplitude < -0.001 || p.amplitudeSteps > 0)) {
if (p.amplitudeSteps > 0) {
if (p.amplitudeSteps == 1) {
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <stdlib.h>
+#include <stdint.h>
#include <math.h>
#include <vector>
@@ -54,13 +55,16 @@ struct OscillatorGenerator : Oscillator, Generator {
};
struct Phasor : OscillatorGenerator {
- static constexpr float maxPhase = 2.0f;
+ typedef uint32_t phase_t;
+ typedef int64_t phase_delta_t;
+ static constexpr phase_t maxPhase = UINT32_MAX;
+ static constexpr float twoPI = 2.0f * M_PI;
static constexpr float maxSampleWidth = 0.25f;
- float _delta;
- double _phase = 0.0;
+ phase_delta_t _delta;
+ phase_t _phase = 0;
float _sampleWidth = 0.0f;
- float _samplePhase = 0.0f;
+ phase_t _samplePhase = 0;
Phasor(
float sampleRate = 1000.0f,
@@ -81,19 +85,18 @@ struct Phasor : OscillatorGenerator {
_update();
}
- void setSampleWidth(float sw); // fraction of maxPhase.
+ void setSampleWidth(float sw);
void setPhase(float radians);
- float nextFromPhasor(const Phasor& phasor, float offset = 0.0f); // offset is not radians, but local phase.
- float nextForPhase(float phase); // local phase, not radians.
+ float nextFromPhasor(const Phasor& phasor, phase_delta_t offset = 0);
+ inline float nextForPhase(phase_t phase) { return _nextForPhase(phase); }
virtual void _update();
- void advancePhase();
- void advancePhase(int n);
- void advancePhasePositive();
+ inline void advancePhase() { _phase += _delta; }
+ inline void advancePhase(int n) { assert(n > 0); _phase += n * _delta; }
virtual float _next() override final;
- virtual float _nextForPhase(float phase);
+ virtual float _nextForPhase(phase_t phase);
- inline static float radiansToPhase(float radians) { return radians / M_PI; }
- inline static float phaseToRadians(float phase) { return phase * M_PI; }
+ inline static phase_delta_t radiansToPhase(float radians) { return (radians / twoPI) * maxPhase; }
+ inline static float phaseToRadians(phase_t phase) { return (phase / (float)maxPhase) * twoPI; }
};
struct TablePhasor : Phasor {
@@ -111,7 +114,7 @@ struct TablePhasor : Phasor {
{
}
- virtual float _nextForPhase(float phase) override;
+ virtual float _nextForPhase(phase_t phase) override;
};
struct SineOscillator : OscillatorGenerator {
@@ -154,8 +157,6 @@ struct SineTableOscillator : TablePhasor {
};
struct SawOscillator : Phasor {
- const float halfMaxPhase = 0.5f * maxPhase;
-
SawOscillator(
float sampleRate = 1000.0f,
float frequency = 100.0f
@@ -164,7 +165,7 @@ struct SawOscillator : Phasor {
{
}
- virtual float _nextForPhase(float phase) override;
+ virtual float _nextForPhase(phase_t phase) override;
};
struct SaturatingSawOscillator : SawOscillator {
@@ -183,13 +184,13 @@ struct SaturatingSawOscillator : SawOscillator {
void setSaturation(float saturation);
- virtual float _nextForPhase(float phase) override;
+ virtual float _nextForPhase(phase_t phase) override;
};
struct BandLimitedSawOscillator : SaturatingSawOscillator {
int _quality;
const Table& _table;
- float _qd = 0.0f;
+ phase_delta_t _qd = 0;
float _halfTableLen;
BandLimitedSawOscillator(
@@ -209,14 +210,14 @@ struct BandLimitedSawOscillator : SaturatingSawOscillator {
void setQuality(int quality);
virtual void _update() override;
- virtual float _nextForPhase(float phase) override;
+ virtual float _nextForPhase(phase_t phase) override;
};
struct SquareOscillator : Phasor {
const float minPulseWidth = 0.03f;
const float maxPulseWidth = 1.0f - minPulseWidth;
float _pulseWidthInput;
- float _pulseWidth = 0.5;
+ phase_t _pulseWidth = maxPhase / 2;
bool positive = true;
SquareOscillator(
@@ -229,14 +230,14 @@ struct SquareOscillator : Phasor {
void setPulseWidth(float pw);
- virtual float _nextForPhase(float phase) override;
+ virtual float _nextForPhase(phase_t phase) override;
};
struct BandLimitedSquareOscillator : BandLimitedSawOscillator {
const float minPulseWidth = 0.03f;
const float maxPulseWidth = 1.0f - minPulseWidth;
float _pulseWidthInput;
- float _pulseWidth;
+ phase_delta_t _pulseWidth;
float _offset;
BandLimitedSquareOscillator(
@@ -252,13 +253,12 @@ struct BandLimitedSquareOscillator : BandLimitedSawOscillator {
void setPulseWidth(float pw);
- virtual float _nextForPhase(float phase) override;
+ virtual float _nextForPhase(phase_t phase) override;
};
struct TriangleOscillator : Phasor {
- const float quarterMaxPhase = 0.25f * maxPhase;
- const float threeQuartersMaxPhase = 0.75f * maxPhase;
- const float twiceMaxPhase = 2.0f * maxPhase;
+ const phase_t quarterMaxPhase = maxPhase * 0.25f;
+ const phase_t threeQuartersMaxPhase = maxPhase * 0.75f;
TriangleOscillator(
float sampleRate = 1000.0f,
@@ -268,7 +268,7 @@ struct TriangleOscillator : Phasor {
{
}
- virtual float _nextForPhase(float phase) override;
+ virtual float _nextForPhase(phase_t phase) override;
};
struct SineBankOscillator : Oscillator {
@@ -323,7 +323,7 @@ struct SineBankOscillator : Oscillator {
virtual void _sampleRateChanged() override;
virtual void _frequencyChanged() override;
- float next(float phaseOffset = 0.0f); // Phasor "phase", not radians.
+ float next(Phasor::phase_t phaseOffset = 0.0f);
};
} // namespace dsp