commit 407a5484cdfccaec0fbfbb3b67214904abdb062c
parent aeddb9f698094d2be9a39bd561408dd3a62825e6
Author: Matt Demanett <matt@demanett.net>
Date: Wed, 7 Mar 2018 22:38:03 -0500
Add wavetable sine oscillator; use it in 8FO.
Diffstat:
6 files changed, 88 insertions(+), 5 deletions(-)
diff --git a/src/EightFO.cpp b/src/EightFO.cpp
@@ -116,7 +116,7 @@ void EightFO::updateOutput(bool useSample, Output& output, float& offset, float&
assert(false);
}
case SINE_WAVE: {
- v = sinf((_phasor._phase + offset) * M_PI); // FIXME
+ v = _sine.nextFromPhasor(_phasor, offset);
break;
}
case TRIANGLE_WAVE: {
diff --git a/src/EightFO.hpp b/src/EightFO.hpp
@@ -95,6 +95,7 @@ struct EightFO : Module {
SchmittTrigger _resetTrigger;
Phasor _phasor;
+ SineTableOscillator _sine;
TriangleOscillator _triangle;
SawOscillator _ramp;
SquareOscillator _square;
@@ -129,6 +130,7 @@ struct EightFO : Module {
EightFO()
: Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS)
, _phasor(engineGetSampleRate(), 1.0f)
+ , _sine(0.0f, 0.0f)
, _triangle(0.0f, 0.0f)
, _ramp(0.0f, 0.0f)
, _square(0.0f, 0.0f)
diff --git a/src/Test.cpp b/src/Test.cpp
@@ -37,7 +37,7 @@ void Test::step() {
_sine2.setSampleRate(engineGetSampleRate());
_sine2.setFrequency(oscillatorPitch());
- outputs[OUT2_OUTPUT].value = 5.0f * powf(_sine2.next(), 5.0f);
+ outputs[OUT2_OUTPUT].value = _sine2.next();
#elif SQUARE
_square.setSampleRate(engineGetSampleRate());
diff --git a/src/Test.hpp b/src/Test.hpp
@@ -74,7 +74,7 @@ struct Test : Module {
LowPassFilter _lpf;
#elif SINE
SineOscillator _sine;
- SineOscillator _sine2;
+ SineTableOscillator _sine2;
#elif SQUARE
SquareOscillator _square;
#elif SAW
@@ -99,7 +99,7 @@ struct Test : Module {
, _lpf(44100.0, 1000.0, 1.0)
#elif SINE
, _sine(44100.0, 1000.0, 5.0)
- , _sine2(44100.0, 1000.0, 1.0, M_PI/1.0f)
+ , _sine2(44100.0, 1000.0, 5.0)
#elif SQUARE
, _square(44100.0, 1000.0, 5.0)
#elif SAW
@@ -117,7 +117,10 @@ struct Test : Module {
{
onReset();
-#ifdef SINEBANK
+#ifdef SINE
+ _sine2.setPhase(M_PI);
+
+#elif SINEBANK
const float baseAmplitude = 5.0;
switch (5) {
case 1: {
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -39,6 +39,32 @@ float Phasor::_nextForPhase(float phase) {
}
+void TablePhasor::generate() {
+ if (!_table) {
+ _table = new float[_length] {};
+ _generate();
+ }
+}
+
+float TablePhasor::_nextForPhase(float phase) {
+ if (!_table) {
+ generate();
+ }
+
+ while (phase >= maxPhase) {
+ phase -= maxPhase;
+ }
+ while (phase < 0.0f) {
+ phase += maxPhase;
+ }
+ float fi = phase * (_length / 2);
+ int i = (int)fi;
+ float v1 = _table[i];
+ float v2 = _table[i + 1 == _length ? 0 : i + 1];
+ return _amplitude * (v1 + (fi - i)*(v2 - v1));
+}
+
+
// A New Recursive Quadrature Oscillator, Martin Vicanek, 2015 - http://vicanek.de/articles/QuadOsc.pdf
void SineOscillator::setPhase(double phase) {
_x = cos(phase);
@@ -59,6 +85,14 @@ float SineOscillator::_next() {
}
+void SineTableOscillator::_generate() {
+ const float twoPI = 2.0f * M_PI;
+ for (int i = 0; i < _length; ++i) {
+ _table[i] = sinf(twoPI * (i / (float)_length));
+ }
+}
+
+
float SawOscillator::_nextForPhase(float phase) {
return _amplitude * (phase - halfMaxPhase);
}
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdint.h>
+#include <assert.h>
#include <vector>
#include "base.hpp"
@@ -77,6 +78,36 @@ struct Phasor : OscillatorGenerator {
static float phaseToRadians(float phase) { return phase * M_PI; }
};
+struct TablePhasor : Phasor {
+ int _length = 0;
+ float* _table = NULL;
+ float _amplitude;
+
+ TablePhasor(
+ double sampleRate,
+ double frequency,
+ float amplitude = 1.0f,
+ int n = 10
+ )
+ : Phasor(sampleRate, frequency)
+ , _amplitude(amplitude)
+ {
+ assert(n > 0);
+ assert(n <= 16);
+ _length = 1 << n;
+ }
+ virtual ~TablePhasor() {
+ if (_table) {
+ delete[] _table;
+ }
+ }
+
+ void generate();
+ virtual void _generate() = 0;
+
+ virtual float _nextForPhase(float phase) override;
+};
+
struct SineOscillator : OscillatorGenerator {
double _k1, _k2;
double _x;
@@ -109,6 +140,19 @@ struct SineOscillator : OscillatorGenerator {
virtual float _next() override;
};
+struct SineTableOscillator : TablePhasor {
+ SineTableOscillator(
+ float sampleRate,
+ float frequency,
+ float amplitude = 1.0
+ )
+ : TablePhasor(sampleRate, frequency, amplitude)
+ {
+ }
+
+ virtual void _generate() override;
+};
+
struct SawOscillator : Phasor {
const float halfMaxPhase = 0.5f * maxPhase;
float _amplitude;