Sound like great progress and thanks for sharing paper which I'll get a read at over the weekend. If you were willing to share your modified moog object any time that would be much appreciated
Cheers Paul
No problem. Here's my first draft. Not optimised or carefully checked yet, but sounds pretty good to me and is light on CPU.
//-----------------------------------------------------------
// Huovilainen New Moog (HNM) model as per CMJ jun 2006
// Implemented as Teensy Audio Library compatible object
// Richard van Hoesel, Feb. 5 2021, v.1.0
// please retain this header if you use this code.
//-----------------------------------------------------------
#include <math.h>
#include <stdint.h>
class HNMoog : public AudioStream
{
public:
HNMoog() : AudioStream(1,inputQueueArray) {};
void SetCutoff(float FC);
void SetResonance(float reson);
void SetDrive(float drive);
double LPF(double s, int i);
virtual void update(void);
private:
double alpha = 1.0;
double beta[4] = {0};
double z0[4] = {0};
double z1[4] = {0};
double K;
double Q=3;
double overdrive = 1.0;
double cutoff, Fbase;
audio_block_t *inputQueueArray[1];
};
void HNMoog::SetDrive(float drive)
{
overdrive = drive;
}
double HNMoog:: LPF(double s, int i)
{
float ft = s * (1/1.3) + (0.3/1.3) * z0
- z1 ;
ft = ft * alpha + z1;
z1= ft;
z0=s;
return ft;
}
void HNMoog::SetCutoff(float c)
{
cutoff = c;
double wc = 2.0 * MOOG_PI * cutoff / 44100;
double wc2 = wc*wc;
double G = 0.9892 * wc - 0.4324 * wc2 + 0.1381 * wc * wc2 - 0.0202*wc2*wc2;
alpha = G;
};
void HNMoog::SetResonance(float res)
{ // maps resonance = 0->1 to K = 0 -> 4
K = 4.0 * res;
};
void HNMoog::update(void)
{
audio_block_t *block;
float FCmod, filter_out;
block = receiveWritable(0);
if (!block)
return;
for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++)
{
float input = block->data * (1.0/32768) ;
double u = input - (z1[3] - 0.5*input) * K;
u = fast_tanh(overdrive * u);
double stage1 = LPF(u,0);
double stage2 = LPF(stage1,1);
double stage3 = LPF(stage2,2);
double stage4 = LPF(stage3,3);
block->data = stage4 * 32767.0 ;
}
transmit(block);
release(block);
}