commit b57623d3c35cc9cc1bf900e77b5e720912742f06
parent 8d6cd6d023afd97720d4d470bc1d50a2f97ee4c4
Author: Matt Demanett <matt@demanett.net>
Date: Thu, 4 Jan 2018 21:44:28 -0500
Sine oscillator; use it in Reftone.
Diffstat:
5 files changed, 116 insertions(+), 7 deletions(-)
diff --git a/benchmarks/oscillator.cpp b/benchmarks/oscillator.cpp
@@ -0,0 +1,14 @@
+
+#include <benchmark/benchmark.h>
+
+#include <dsp.hpp>
+
+using namespace bogaudio::dsp;
+
+static void BM_SineOscillator(benchmark::State& state) {
+ SineOscillator o(44100.0, 440.0);
+ for (auto _ : state) {
+ o.next();
+ }
+}
+BENCHMARK(BM_SineOscillator);
diff --git a/src/Reftone.cpp b/src/Reftone.cpp
@@ -1,7 +1,11 @@
#include <string.h>
#include <algorithm>
+
#include "BogaudioModules.hpp"
+#include "dsp/dsp.hpp"
+
+using namespace bogaudio::dsp;
struct Reftone : Module {
enum ParamsIds {
@@ -29,18 +33,21 @@ struct Reftone : Module {
int _octave = 4;
float _fine = 0.0;
float _frequency = 440.0;
+ SineOscillator _sine;
- Reftone() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
- reset();
+ Reftone()
+ : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS)
+ , _sine(engineGetSampleRate(), _frequency)
+ {
+ }
+
+ virtual void onSampleRateChange() override {
+ _sine.setSampleRate(engineGetSampleRate());
}
- virtual void reset() override;
virtual void step() override;
};
-void Reftone::reset() {
-}
-
void Reftone::step() {
const float f0 = 261.626;
const int f0Pitch = 0;
@@ -51,9 +58,10 @@ void Reftone::step() {
_octave = clampf(params[OCTAVE_PARAM].value, 1.0, 8.0);
_fine = clampf(params[FINE_PARAM].value, -0.99, 0.99);
_frequency = f0*powf(twelfthRootTwo, 12*(_octave - f0Octave) + (_pitch - f0Pitch) + _fine);
+ _sine.setFrequency(_frequency);
outputs[CV_OUTPUT].value = log2f(_frequency / f0);
- outputs[OUT_OUTPUT].value = 0.0; // FIXME: sine out.
+ outputs[OUT_OUTPUT].value = _sine.next() * 5.0;
}
diff --git a/src/dsp/dsp.hpp b/src/dsp/dsp.hpp
@@ -3,5 +3,7 @@
#include "base.hpp"
#include "buffer.hpp"
+
#include "analyzer.hpp"
+#include "oscillator.hpp"
#include "noise.hpp"
diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp
@@ -0,0 +1,20 @@
+#include <math.h>
+
+#include "dsp.hpp"
+
+using namespace bogaudio::dsp;
+
+void SineOscillator::updateDeltaTheta() {
+ float sampleTime = 1.0 / _sampleRate;
+ float cycleTime = 1.0 / _frequency;
+ float _deltaTheta = (sampleTime / cycleTime) * 2.0f * M_PI;
+ _sinDeltaTheta = sinf(_deltaTheta);
+ _cosDeltaTheta = cosf(_deltaTheta);
+}
+
+float SineOscillator::_next() {
+ float x2 = _x*_cosDeltaTheta - _y*_sinDeltaTheta;
+ _y = _x*_sinDeltaTheta + _y*_cosDeltaTheta;
+ _x = x2;
+ return _y;
+}
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -0,0 +1,65 @@
+
+namespace bogaudio {
+namespace dsp {
+
+struct OscillatorGenerator : Generator {
+ float _sampleRate;
+ float _frequency;
+
+ OscillatorGenerator(
+ float sampleRate,
+ float frequency
+ )
+ : _sampleRate(sampleRate)
+ , _frequency(frequency)
+ {
+ }
+
+ void setSampleRate(float sampleRate) {
+ if (_sampleRate != sampleRate) {
+ _sampleRate = sampleRate;
+ _sampleRateChanged();
+ }
+ }
+
+ virtual void _sampleRateChanged() {}
+
+ void setFrequency(float frequency) {
+ if (_frequency != frequency) {
+ _frequency = frequency;
+ _frequencyChanged();
+ }
+ }
+
+ virtual void _frequencyChanged() {}
+};
+
+struct SineOscillator : OscillatorGenerator {
+ float _x = 1.0;
+ float _y = 0.0;
+ float _sinDeltaTheta;
+ float _cosDeltaTheta;
+
+ SineOscillator(
+ float sampleRate,
+ float frequency
+ )
+ : OscillatorGenerator(sampleRate, frequency)
+ {
+ updateDeltaTheta();
+ }
+
+ virtual void _sampleRateChanged() override {
+ updateDeltaTheta();
+ }
+
+ virtual void _frequencyChanged() override {
+ updateDeltaTheta();
+ }
+
+ void updateDeltaTheta();
+ virtual float _next() override;
+};
+
+} // namespace dsp
+} // namespace bogaudio