BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

commit 3dce7a876ee0dc9a69fcb73913a7f59019f7183b
parent 0a8d3750a690c1715bfeeb0a01f16ddb55f7dc57
Author: Matt Demanett <matt@demanett.net>
Date:   Wed, 30 May 2018 23:46:07 -0400

LFO/8FO: fix pulse width knobs, such that half knob yields true 50% pulse; RunningAverage DSP and test harness for debugging.

Diffstat:
Msrc/EightFO.cpp | 3++-
Msrc/LFO.cpp | 3++-
Msrc/Test.cpp | 6++++++
Msrc/Test.hpp | 10+++++++++-
Msrc/dsp/signal.cpp | 23+++++++++++++++++------
Msrc/dsp/signal.hpp | 18++++++++++++++----
6 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/src/EightFO.cpp b/src/EightFO.cpp @@ -55,8 +55,9 @@ void EightFO::step() { if (inputs[SAMPLE_PWM_INPUT].active) { pw *= clamp(inputs[SAMPLE_PWM_INPUT].value / 5.0f, -1.0f, 1.0f); } - pw = (pw + 1.0f) / 2.0f; pw *= 1.0f - 2.0f * _square.minPulseWidth; + pw *= 0.5f; + pw += 0.5f; _square.setPulseWidth(pw); _sampleSteps = 1; } diff --git a/src/LFO.cpp b/src/LFO.cpp @@ -50,8 +50,9 @@ void LFO::step() { if (inputs[PW_INPUT].active) { pw *= clamp(inputs[PW_INPUT].value / 5.0f, -1.0f, 1.0f); } - pw = (pw + 1.0f) / 2.0f; pw *= 1.0f - 2.0f * _square.minPulseWidth; + pw *= 0.5f; + pw += 0.5f; _square.setPulseWidth(pw); float sample = params[SAMPLE_PARAM].value; diff --git a/src/Test.cpp b/src/Test.cpp @@ -377,6 +377,12 @@ void Test::step() { outputs[OUT_OUTPUT].value = _rms.next(inputs[IN_INPUT].value); _pef.setSensitivity(sensitivity); outputs[OUT2_OUTPUT].value = _pef.next(inputs[IN_INPUT].value); + +#elif RAVG + if (_reset.process(inputs[CV1_INPUT].value)) { + _average.reset(); + } + outputs[OUT_OUTPUT].value = _average.next(inputs[IN_INPUT].value); #endif } diff --git a/src/Test.hpp b/src/Test.hpp @@ -22,8 +22,9 @@ extern Model* modelTest; // #define FEEDBACK_PM 1 // #define EG 1 // #define TABLES 1 -#define SLEW 1 +// #define SLEW 1 // #define RMS 1 +#define RAVG 1 #include "pitch.hpp" #ifdef LPF @@ -75,6 +76,8 @@ extern Model* modelTest; #include "dsp/signal.hpp" #elif RMS #include "dsp/signal.hpp" +#elif RAVG +#include "dsp/signal.hpp" #else #error what #endif @@ -190,6 +193,9 @@ struct Test : Module { #elif RMS RootMeanSquare _rms; PucketteEnvelopeFollower _pef; +#elif RAVG + RunningAverage _average; + SchmittTrigger _reset; #endif Test() @@ -201,6 +207,8 @@ struct Test : Module { , _cicDecimator(STAGES) #elif TABLES , _table(StaticBlepTable::table(), 44100.0, 1000.0) +#elif RAVG + , _average(engineGetSampleRate(), 1.0f, 1000.0f) #endif { onReset(); diff --git a/src/dsp/signal.cpp b/src/dsp/signal.cpp @@ -48,7 +48,7 @@ float Amplifier::next(float s) { } -void RootMeanSquare::setSampleRate(float sampleRate) { +void RunningAverage::setSampleRate(float sampleRate) { assert(sampleRate > 0.0f); if (_sampleRate != sampleRate) { _sampleRate = sampleRate; @@ -64,7 +64,7 @@ void RootMeanSquare::setSampleRate(float sampleRate) { } } -void RootMeanSquare::setSensitivity(float sensitivity) { +void RunningAverage::setSensitivity(float sensitivity) { assert(sensitivity >= 0.0f); assert(sensitivity <= 1.0f); if (_initialized) { @@ -95,21 +95,32 @@ void RootMeanSquare::setSensitivity(float sensitivity) { _sumN = std::max(_sensitivity * _bufferN, 1.0f); _leadI = 0; _trailI = _bufferN - _sumN; - _sum = 0.0f; + _sum = 0.0; } } -float RootMeanSquare::next(float sample) { +void RunningAverage::reset() { + _sum = 0.0; + std::fill(_buffer, _buffer + _bufferN, 0.0); +} + +float RunningAverage::next(float sample) { _sum -= _buffer[_trailI]; ++_trailI; _trailI %= _bufferN; - _sum += _buffer[_leadI] = sample * sample; + _sum += _buffer[_leadI] = sample; ++_leadI; _leadI %= _bufferN; + return (float)_sum / (float)_sumN; +} + + +float RootMeanSquare::next(float sample) { + float a = RunningAverage::next(sample * sample); if (_sum <= 0.0) { return 0.0f; } - return sqrtf((float)_sum / (float)_sumN); + return sqrtf(a); } diff --git a/src/dsp/signal.hpp b/src/dsp/signal.hpp @@ -38,7 +38,7 @@ struct Amplifier { float next(float s); }; -struct RootMeanSquare { +struct RunningAverage { float _maxDelayMS; float _sampleRate = -1.0f; float _sensitivity = -1.0f; @@ -51,11 +51,11 @@ struct RootMeanSquare { int _trailI = 0; double _sum = 0; - RootMeanSquare(float sampleRate = 1000.0f, float sensitivity = 1.0f, float maxDelayMS = 300.0f) : _maxDelayMS(maxDelayMS) { + RunningAverage(float sampleRate = 1000.0f, float sensitivity = 1.0f, float maxDelayMS = 300.0f) : _maxDelayMS(maxDelayMS) { setSampleRate(sampleRate); setSensitivity(sensitivity); } - ~RootMeanSquare() { + virtual ~RunningAverage() { if (_buffer) { delete[] _buffer; } @@ -63,7 +63,17 @@ struct RootMeanSquare { void setSampleRate(float sampleRate); void setSensitivity(float sensitivity); - float next(float sample); + void reset(); + virtual float next(float sample); +}; + +struct RootMeanSquare : RunningAverage { + RootMeanSquare(float sampleRate = 1000.0f, float sensitivity = 1.0f, float maxDelayMS = 300.0f) + : RunningAverage(sampleRate, sensitivity, maxDelayMS) + { + } + + virtual float next(float sample) override; }; // Puckette 2007, "Theory and Technique"