I'm implementing some basic mooog filter code from musicdsp.org and the gain increase caused by the resonance is causing distortion. I don't want to simply reduce the dynamic range of the input because that would reduce quality and also the overall volume when Q is not turned up. So how is this normally handled ? I've heard about clipping the feedback, but not sure how that would apply in my case.
Full class code below, it's a fixed point implementation, hence all the >>16's...
Thanks all!
Code: Select all
#include "AudioStream.h"
class MoogFilter : public AudioStream
{
public:
MoogFilter()
: AudioStream(1, inputQueueArray){ }
virtual void update(void);
virtual void calc(void);
float FREQ = 0.5;
float Q = 0.5;
uint16_t f = 22000;
uint16_t q = 32768;
int32_t y1,y2,y3,y4,oldy1,oldy2,oldy3,x,oldx;
float t1,t2,k,p,r;
int32_t K,P,R;
int16_t outpoot;
private:
audio_block_t *inputQueueArray[1];
};
//#endif
///////////////////////////////////////////////////
//#include "utility/dspinst.h"
void MoogFilter::update(void)
{
audio_block_t *block;
block = receiveWritable();
if (!block) return;
for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
// process input
x = (int32_t)block->data[i] - ((R * y4)>>16);
// four cascaded one-pole filters
y1 = ((x*P)>>16) + ((oldx*P)>>16) - ((K*y1)>>16);
y2 = ((y1*P)>>16) + ((oldy1*P)>>16) - ((K*y2)>>16);
y3 = ((y2*P)>>16) + ((oldy2*P)>>16) - ((K*y3)>>16);
y4 = ((y3*P)>>16) + ((oldy3*P)>>16) - ((K*y4)>>16);
// clipper band limited sigmoid
y4 -= ((((y4 * y4)>>16)*y4)>>16) /6;
oldx = x; oldy1 = y1; oldy2 = y2; oldy3 = y3;
outpoot = (int16_t)y4; //}}
block->data[i]=outpoot;
}
transmit(block);
release(block);
}
//Calcs p, k, t1, t2 & r
void MoogFilter::calc(){
FREQ=(f/65535.0);
Q=(q/65535.0);
// empirical tuning
p = FREQ * (1.8 - (0.8 * FREQ));
// k = p + p - T(1.0);
// A much better tuning seems to be:
k = 2.0 * sin(FREQ * 3.1415926535897931 * 0.5) - 1.0;
t1 = (1.0 - p) * 1.386249;
t2 = 12.0 + (t1 * t1);
r = Q * (t2 + (6.0 * t1)) / (t2 - (6.0 * t1));
R=(int32_t)(r*65536);
K=(int32_t)(k*65536);
P=(int32_t)(p*65536);
}