commit 36aefaf5422c61a92f00fbe53f91538a9c5fd63d
parent 92d485cae583ece05e887127b89e6a67b75948d5
Author: Matt Demanett <matt@demanett.net>
Date: Sun, 18 Mar 2018 15:25:19 -0400
Experiment with saw saturation.
Diffstat:
4 files changed, 74 insertions(+), 4 deletions(-)
diff --git a/src/Test.cpp b/src/Test.cpp
@@ -65,6 +65,19 @@ void Test::step() {
_saw2.setQuality(params[PARAM2_PARAM].value * 200);
outputs[OUT2_OUTPUT].value = _saw2.next();
+#elif SATSAW
+ float saturation = params[PARAM2_PARAM].value * 10.0f;
+ _saw.setSampleRate(engineGetSampleRate());
+ _saw.setFrequency(oscillatorPitch());
+ _saw.setSaturation(saturation);
+ outputs[OUT_OUTPUT].value = _saw.next();
+
+ _saw2.setSampleRate(engineGetSampleRate());
+ _saw2.setFrequency(oscillatorPitch());
+ _saw2.setSaturation(saturation);
+ _saw2.setQuality(params[PARAM3_PARAM].value * 200);
+ outputs[OUT2_OUTPUT].value = _saw2.next();
+
#elif TRIANGLE
_triangle.setSampleRate(engineGetSampleRate());
_triangle.setFrequency(oscillatorPitch());
diff --git a/src/Test.hpp b/src/Test.hpp
@@ -7,8 +7,9 @@ extern Model* modelTest;
// #define LPF 1
// #define LPFNOISE 1
// #define SINE 1
-#define SQUARE 1
+// #define SQUARE 1
// #define SAW 1
+#define SATSAW 1
// #define TRIANGLE 1
// #define SINEBANK 1
// #define OVERSAMPLING 1
@@ -30,6 +31,8 @@ extern Model* modelTest;
#include "dsp/oscillator.hpp"
#elif SAW
#include "dsp/oscillator.hpp"
+#elif SATSAW
+#include "dsp/oscillator.hpp"
#elif TRIANGLE
#include "dsp/oscillator.hpp"
#elif SINEBANK
@@ -97,6 +100,9 @@ struct Test : Module {
#elif SAW
SawOscillator _saw;
BandLimitedSawOscillator _saw2;
+#elif SATSAW
+ SaturatingSawOscillator _saw;
+ BandLimitedSawOscillator _saw2;
#elif TRIANGLE
TriangleOscillator _triangle;
#elif SINEBANK
@@ -140,6 +146,9 @@ struct Test : Module {
#elif SAW
, _saw(44100.0, 1000.0, 5.0)
, _saw2(44100.0, 1000.0, 5.0, 8)
+ #elif SATSAW
+ , _saw(44100.0, 1000.0, 5.0)
+ , _saw2(44100.0, 1000.0, 5.0, 8)
#elif TRIANGLE
, _triangle(44100.0, 1000.0, 5.0)
#elif SINEBANK
@@ -174,6 +183,9 @@ struct Test : Module {
#elif SAW
_saw2.setPhase(M_PI);
+#elif SATSAW
+ _saw2.setPhase(M_PI);
+
#elif SINEBANK
const float baseAmplitude = 5.0;
switch (5) {
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -79,6 +79,31 @@ float SawOscillator::_nextForPhase(float phase) {
}
+void SaturatingSawOscillator::setSaturation(float saturation) {
+ if (_saturation != saturation) {
+ assert(saturation >= 0.0f);
+ _saturation = saturation;
+ if (_saturation < 1.0f) {
+ _saturationNormalization = 1.0f / tanhf(_saturation * M_PI);
+ }
+ else {
+ _saturationNormalization = 1.0f;
+ }
+ }
+}
+
+float SaturatingSawOscillator::_nextForPhase(float phase) {
+ float sample = SawOscillator::_nextForPhase(phase);
+ if (_saturation >= 0.1f) {
+ // FIXME: amplitudes, tanh approximation or table.
+ sample /= _amplitude;
+ sample = tanhf(sample * _saturation * M_PI) * _saturationNormalization;
+ sample *= _amplitude;
+ }
+ return sample;
+}
+
+
void BandLimitedSawOscillator::setQuality(int quality) {
if (_quality != quality) {
assert(quality >= 0);
@@ -94,7 +119,7 @@ void BandLimitedSawOscillator::_update() {
}
float BandLimitedSawOscillator::_nextForPhase(float phase) {
- float sample = SawOscillator::_nextForPhase(phase);
+ float sample = SaturatingSawOscillator::_nextForPhase(phase);
if (phase > maxPhase - _qd) {
float i = (maxPhase - phase) / _qd;
i = (1.0f - i) * _halfTableLen;
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -156,7 +156,27 @@ struct SawOscillator : Phasor {
virtual float _nextForPhase(float phase) override;
};
-struct BandLimitedSawOscillator : SawOscillator {
+struct SaturatingSawOscillator : SawOscillator {
+ float _saturation;
+ float _saturationNormalization;
+
+ SaturatingSawOscillator(
+ float sampleRate,
+ float frequency,
+ float amplitude = 1.0f
+ )
+ : SawOscillator(sampleRate, frequency, amplitude)
+ , _saturation(0.0f)
+ , _saturationNormalization(1.0f)
+ {
+ }
+
+ void setSaturation(float saturation);
+
+ virtual float _nextForPhase(float phase) override;
+};
+
+struct BandLimitedSawOscillator : SaturatingSawOscillator {
int _quality;
const Table& _table;
float _qd = 0.0f;
@@ -169,7 +189,7 @@ struct BandLimitedSawOscillator : SawOscillator {
int quality = 5,
const Table& table = StaticBlepTable::table()
)
- : SawOscillator(sampleRate, frequency, amplitude)
+ : SaturatingSawOscillator(sampleRate, frequency, amplitude)
, _quality(quality)
, _table(table)
, _halfTableLen(_table.length() / 2)