commit 089e3cf463a63599471a47bcb12530ce462908de
parent 1a6789342ec35b4cd9c150e5c97d1e324dfefa69
Author: Matt Demanett <matt@demanett.net>
Date: Wed, 10 Feb 2021 23:11:12 -0500
Stepped random oscillator; oscillators minor cleanups; widened oscillator phase_t.
Diffstat:
7 files changed, 146 insertions(+), 60 deletions(-)
diff --git a/src/EightFO.cpp b/src/EightFO.cpp
@@ -143,7 +143,7 @@ void EightFO::processChannel(const ProcessArgs& args, int c) {
}
Phasor::phase_delta_t EightFO::phaseOffset(int c, Param& p, Input& i, Phasor::phase_delta_t baseOffset) {
- float o = p.getValue() * Phasor::maxPhase / 2.0f;
+ float o = p.getValue() * Phasor::cyclePhase / 2.0f;
if (i.isConnected()) {
o *= clamp(i.getPolyVoltage(c) / 5.0f, -1.0f, 1.0f);
}
diff --git a/src/Sine.cpp b/src/Sine.cpp
@@ -90,7 +90,7 @@ void Sine::processChannel(const ProcessArgs& args, int c) {
if (inputs[PHASE_INPUT].isConnected()) {
phaseOffset *= clamp(inputs[PHASE_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f);
}
- e.additionalPhaseOffset = -phaseOffset * 0.5f * Phasor::maxPhase;
+ e.additionalPhaseOffset = -phaseOffset * 0.5f * Phasor::cyclePhase;
VCOBase::processChannel(args, c);
diff --git a/src/Test.cpp b/src/Test.cpp
@@ -511,6 +511,30 @@ void Test::processAll(const ProcessArgs& args) {
float in = inputs[IN_INPUT].getVoltage();
outputs[OUT_OUTPUT].setVoltage(_smoother.next(in));
+#elif STEPPED_RANDOM
+ const float octaves = 7.0f;
+ float frequency = params[PARAM1_PARAM].getValue();
+ frequency *= 2.0f;
+ frequency -= 1.0f;
+ frequency *= octaves;
+ frequency += inputs[CV1_INPUT].getVoltage();
+ frequency = clamp(frequency, -octaves, octaves);
+ // frequency -= 4.0f;
+ frequency = cvToFrequency(frequency);
+ frequency = std::min(frequency, 0.49f*APP->engine->getSampleRate());
+
+ _stepped.setSampleRate(APP->engine->getSampleRate());
+ _stepped.setFrequency(frequency);
+ if (_trigger.next(inputs[CV3_INPUT].getVoltage())) {
+ _stepped.resetPhase();
+ }
+ outputs[OUT_OUTPUT].setVoltage(_stepped.next() * 5.0f);
+
+ if ((_stepped._phase / SteppedRandomOscillator::cyclePhase) > (_lastPhase / SteppedRandomOscillator::cyclePhase)) {
+ _lastPhase = _stepped._phase;
+ _lastNoise = _noise.next() * 5.0f;
+ }
+ outputs[OUT2_OUTPUT].setVoltage(_lastNoise);
#endif
}
diff --git a/src/Test.hpp b/src/Test.hpp
@@ -32,7 +32,8 @@ extern Model* modelTest;
// #define INTEGRATOR 1
// #define RANDOMWALK 1
// #define DCBLOCKER 1
-#define LFO_SMOOTHER 1
+// #define LFO_SMOOTHER 1
+#define STEPPED_RANDOM 1
#include "pitch.hpp"
#ifdef LPF
@@ -107,6 +108,9 @@ extern Model* modelTest;
#elif LFO_SMOOTHER
#include "dsp/signal.hpp"
#include "dsp/pitch.hpp"
+#elif STEPPED_RANDOM
+#include "dsp/oscillator.hpp"
+#include "dsp/noise.hpp"
#else
#error what
#endif
@@ -262,6 +266,12 @@ struct Test : BGModule {
float next(float sample);
};
Smoother _smoother;
+#elif STEPPED_RANDOM
+ PositiveZeroCrossing _trigger;
+ SteppedRandomOscillator _stepped;
+ SteppedRandomOscillator::phase_t _lastPhase = 0;
+ WhiteNoiseGenerator _noise;
+ float _lastNoise = 0.0f;
#endif
Test()
diff --git a/src/XCO.cpp b/src/XCO.cpp
@@ -285,7 +285,7 @@ Phasor::phase_delta_t XCO::phaseOffset(int c, Param& param, Input& input) {
if (input.isConnected()) {
v *= clamp(input.getPolyVoltage(c) / 5.0f, -1.0f, 1.0f);
}
- return -v * Phasor::maxPhase / 2.0f;
+ return -v * Phasor::cyclePhase / 2.0f;
}
float XCO::level(int c, Param& param, Input& input) {
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -1,5 +1,6 @@
#include "oscillator.hpp"
+#include "noise.hpp"
using namespace bogaudio::dsp;
@@ -13,7 +14,7 @@ void Phasor::setSampleWidth(float sw) {
if (_sampleWidth != sw) {
_sampleWidth = sw;
if (_sampleWidth > 0.001f) {
- _samplePhase = _sampleWidth * (float)maxPhase;
+ _samplePhase = _sampleWidth * (float)cyclePhase;
}
else {
_samplePhase = 0;
@@ -38,40 +39,35 @@ float Phasor::nextFromPhasor(const Phasor& phasor, phase_delta_t offset) {
if (_samplePhase > 0) {
offset -= offset % _samplePhase;
}
- return _nextForPhase(offset);
+ return nextForPhase(offset);
}
void Phasor::_update() {
- _delta = ((phase_delta_t)((_frequency / _sampleRate) * maxPhase)) % maxPhase;
+ _delta = ((phase_delta_t)((_frequency / _sampleRate) * cyclePhase)) % cyclePhase;
}
float Phasor::_next() {
advancePhase();
if (_samplePhase > 0) {
- return _nextForPhase(_phase - (_phase % _samplePhase));
+ return nextForPhase(_phase - (_phase % _samplePhase));
}
- return _nextForPhase(_phase);
+ return nextForPhase(_phase);
}
-float Phasor::_nextForPhase(phase_t phase) {
+float Phasor::nextForPhase(phase_t phase) {
return phase;
}
-float TablePhasor::_nextForPhase(phase_t phase) {
+float TablePhasor::nextForPhase(phase_t phase) {
if (_tableLength >= 1024) {
- int i = (((((uint64_t)phase) << 16) / maxPhase) * _tableLength) >> 16;
- if (i >= _tableLength) {
- i %= _tableLength;
- }
+ int i = (((((uint64_t)phase) << 16) / cyclePhase) * _tableLength) >> 16;
+ i %= _tableLength;
return _table.value(i);
}
- float fi = (phase / (float)maxPhase) * _tableLength;
- int i = (int)fi;
- if (i >= _tableLength) {
- i %= _tableLength;
- }
+ float fi = (phase / (float)cyclePhase) * _tableLength;
+ int i = (int)fi % _tableLength;
float v1 = _table.value(i);
float v2 = _table.value(i + 1 == _tableLength ? 0 : i + 1);
return v1 + (fi - i)*(v2 - v1);
@@ -98,8 +94,8 @@ float SineOscillator::_next() {
}
-float SawOscillator::_nextForPhase(phase_t phase) {
- return (phase / (float)maxPhase) * 2.0f - 1.0f;
+float SawOscillator::nextForPhase(phase_t phase) {
+ return ((phase % cyclePhase) / (float)cyclePhase) * 2.0f - 1.0f;
}
@@ -118,8 +114,8 @@ void SaturatingSawOscillator::setSaturation(float saturation) {
}
}
-float SaturatingSawOscillator::_nextForPhase(phase_t phase) {
- float sample = SawOscillator::_nextForPhase(phase);
+float SaturatingSawOscillator::nextForPhase(phase_t phase) {
+ float sample = SawOscillator::nextForPhase(phase);
if (_saturation >= 0.1f) {
sample = _tanhf.value(sample * _saturation * M_PI) * _saturationNormalization;
}
@@ -141,10 +137,12 @@ void BandLimitedSawOscillator::_update() {
_qd = q * _delta;
}
-float BandLimitedSawOscillator::_nextForPhase(phase_t phase) {
- float sample = SaturatingSawOscillator::_nextForPhase(phase);
- if (phase > maxPhase - _qd) {
- float i = (maxPhase - phase) / (float)_qd;
+float BandLimitedSawOscillator::nextForPhase(phase_t phase) {
+ phase %= cyclePhase;
+
+ float sample = SaturatingSawOscillator::nextForPhase(phase);
+ if (phase > cyclePhase - _qd) {
+ float i = (cyclePhase - phase) / (float)_qd;
i = (1.0f - i) * _halfTableLen;
sample -= _table.value((int)i);
}
@@ -170,10 +168,12 @@ void SquareOscillator::setPulseWidth(float pw) {
else if (pw <= minPulseWidth) {
pw = minPulseWidth;
}
- _pulseWidth = maxPhase * pw;
+ _pulseWidth = cyclePhase * pw;
}
-float SquareOscillator::_nextForPhase(phase_t phase) {
+float SquareOscillator::nextForPhase(phase_t phase) {
+ phase %= cyclePhase;
+
if (positive) {
if (phase >= _pulseWidth) {
positive = false;
@@ -201,7 +201,7 @@ void BandLimitedSquareOscillator::setPulseWidth(float pw) {
else if (pw <= minPulseWidth) {
pw = minPulseWidth;
}
- _pulseWidth = maxPhase * pw;
+ _pulseWidth = cyclePhase * pw;
if (pw > 0.5) {
_offset = 2.0f * pw - 1.0f;
@@ -211,25 +211,65 @@ void BandLimitedSquareOscillator::setPulseWidth(float pw) {
}
}
-float BandLimitedSquareOscillator::_nextForPhase(phase_t phase) {
- float sample = -BandLimitedSawOscillator::_nextForPhase(phase);
- sample += BandLimitedSawOscillator::_nextForPhase(phase - _pulseWidth);
+float BandLimitedSquareOscillator::nextForPhase(phase_t phase) {
+ float sample = -BandLimitedSawOscillator::nextForPhase(phase);
+ sample += BandLimitedSawOscillator::nextForPhase(phase - _pulseWidth);
return sample + _offset;
}
-float TriangleOscillator::_nextForPhase(phase_t phase) {
- float p = (phase / (float)maxPhase) * 4.0f;
- if (phase < quarterMaxPhase) {
+float TriangleOscillator::nextForPhase(phase_t phase) {
+ phase %= cyclePhase;
+
+ float p = (phase / (float)cyclePhase) * 4.0f;
+ if (phase < quarterCyclePhase) {
return p;
}
- if (phase < threeQuartersMaxPhase) {
+ if (phase < threeQuartersCyclePhase) {
return 2.0f - p;
}
return p - 4.0f;
}
+SteppedRandomOscillator::SteppedRandomOscillator(
+ float sampleRate,
+ float frequency,
+ phase_t seed
+)
+: Phasor(sampleRate, frequency)
+, _n(4096)
+, _k(4093) // prime less than _n
+{
+ if (seed == 0) {
+ _seed = Seeds::getInstance().next();
+ }
+ else {
+ _seed = seed;
+ }
+
+ WhiteNoiseGenerator noise;
+ _t = new float[_n];
+ for (phase_t i = 0; i < _n; ++i) {
+ _t[i] = noise.next();
+ }
+}
+
+SteppedRandomOscillator::~SteppedRandomOscillator() {
+ delete[] _t;
+}
+
+void SteppedRandomOscillator::resetPhase() {
+ _phase -= _phase % cyclePhase;
+ _phase += cyclePhase;
+}
+
+float SteppedRandomOscillator::nextForPhase(phase_t phase) {
+ phase_t i = phase / cyclePhase;
+ return _t[(_seed + i + (_seed + i) % _k) % _n];
+}
+
+
void SineBankOscillator::setPartial(int i, float frequencyRatio, float amplitude) {
setPartialFrequencyRatio(i, frequencyRatio);
setPartialAmplitude(i, amplitude);
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -56,9 +56,9 @@ struct OscillatorGenerator : Oscillator, Generator {
};
struct Phasor : OscillatorGenerator {
- typedef uint32_t phase_t;
+ typedef uint64_t phase_t;
typedef int64_t phase_delta_t;
- static constexpr phase_t maxPhase = UINT32_MAX;
+ static constexpr phase_t cyclePhase = 1L << 32;
static constexpr float twoPI = 2.0f * M_PI;
static constexpr float maxSampleWidth = 0.25f;
@@ -87,19 +87,18 @@ struct Phasor : OscillatorGenerator {
}
void setSampleWidth(float sw);
- void resetPhase();
+ virtual void resetPhase();
void setPhase(float radians);
void syncPhase(const Phasor& phasor);
float nextFromPhasor(const Phasor& phasor, phase_delta_t offset = 0);
- inline float nextForPhase(phase_t phase) { return _nextForPhase(phase); }
+ virtual float nextForPhase(phase_t phase);
virtual void _update();
inline void advancePhase() { _phase += _delta; }
inline void advancePhase(int n) { assert(n > 0); _phase += n * _delta; }
float _next() override final;
- virtual float _nextForPhase(phase_t phase);
- inline static phase_delta_t radiansToPhase(float radians) { return (radians / twoPI) * maxPhase; }
- inline static float phaseToRadians(phase_t phase) { return (phase / (float)maxPhase) * twoPI; }
+ inline static phase_delta_t radiansToPhase(float radians) { return (radians / twoPI) * cyclePhase; }
+ inline static float phaseToRadians(phase_t phase) { return (phase / (float)cyclePhase) * twoPI; }
};
struct TablePhasor : Phasor {
@@ -117,7 +116,7 @@ struct TablePhasor : Phasor {
{
}
- float _nextForPhase(phase_t phase) override;
+ float nextForPhase(phase_t phase) override;
};
struct SineOscillator : OscillatorGenerator {
@@ -168,7 +167,7 @@ struct SawOscillator : Phasor {
{
}
- float _nextForPhase(phase_t phase) override;
+ float nextForPhase(phase_t phase) override;
};
struct SaturatingSawOscillator : SawOscillator {
@@ -187,14 +186,13 @@ struct SaturatingSawOscillator : SawOscillator {
}
void setSaturation(float saturation);
-
- float _nextForPhase(phase_t phase) override;
+ float nextForPhase(phase_t phase) override;
};
struct BandLimitedSawOscillator : SaturatingSawOscillator {
int _quality;
const Table& _table;
- phase_delta_t _qd = 0;
+ phase_t _qd = 0;
float _halfTableLen;
BandLimitedSawOscillator(
@@ -212,9 +210,8 @@ struct BandLimitedSawOscillator : SaturatingSawOscillator {
}
void setQuality(int quality);
-
void _update() override;
- float _nextForPhase(phase_t phase) override;
+ float nextForPhase(phase_t phase) override;
};
struct SquareOscillator : Phasor {
@@ -222,7 +219,7 @@ struct SquareOscillator : Phasor {
static constexpr float maxPulseWidth = 1.0f - minPulseWidth;
static constexpr float defaultPulseWidth = 0.5f;
float _pulseWidthInput;
- phase_t _pulseWidth = maxPhase * defaultPulseWidth;
+ phase_t _pulseWidth = cyclePhase * defaultPulseWidth;
bool positive = true;
SquareOscillator(
@@ -234,8 +231,7 @@ struct SquareOscillator : Phasor {
}
void setPulseWidth(float pw);
-
- float _nextForPhase(phase_t phase) override;
+ float nextForPhase(phase_t phase) override;
};
struct BandLimitedSquareOscillator : BandLimitedSawOscillator {
@@ -257,13 +253,12 @@ struct BandLimitedSquareOscillator : BandLimitedSawOscillator {
}
void setPulseWidth(float pw);
-
- float _nextForPhase(phase_t phase) override;
+ float nextForPhase(phase_t phase) override;
};
struct TriangleOscillator : Phasor {
- const phase_t quarterMaxPhase = maxPhase * 0.25f;
- const phase_t threeQuartersMaxPhase = maxPhase * 0.75f;
+ const phase_t quarterCyclePhase = cyclePhase * 0.25f;
+ const phase_t threeQuartersCyclePhase = cyclePhase * 0.75f;
TriangleOscillator(
float sampleRate = 1000.0f,
@@ -273,7 +268,24 @@ struct TriangleOscillator : Phasor {
{
}
- float _nextForPhase(phase_t phase) override;
+ float nextForPhase(phase_t phase) override;
+};
+
+struct SteppedRandomOscillator : Phasor {
+ const phase_t _n;
+ const phase_t _k;
+ float* _t = NULL;
+ phase_t _seed;
+
+ SteppedRandomOscillator(
+ float sampleRate = 1000.0f,
+ float frequency = 100.0f,
+ phase_t seed = 0
+ );
+ ~SteppedRandomOscillator();
+
+ void resetPhase() override;
+ float nextForPhase(phase_t phase) override;
};
struct SineBankOscillator : Oscillator {