Is there some general way to perform the task given in the question? I have a filter given as follows:

Tdouble MoogVCF::run(double input, double fc, double res)
  double f = fc * 1.16;
  double fb = res * (1.0 - 0.15 * f * f);
  input -= out4 * fb;
  input *= 0.35013 * (f*f)*(f*f);
  out1 = input + 0.3 * in1 + (1 - f) * out1; // Pole 1
  in1  = input;
  out2 = out1 + 0.3 * in2 + (1 - f) * out2;  // Pole 2
  in2  = out1;
  out3 = out2 + 0.3 * in3 + (1 - f) * out3;  // Pole 3
  in3  = out2;
  out4 = out3 + 0.3 * in4 + (1 - f) * out4;  // Pole 4
  in4  = out3;
  return out4;

It's a 4th order IIR low pass filter which works in a feedback loop that generates a nice resonance. It sounds great, but my only problem is that my current CPU is too slow to handle it. It has no FPU and floating point operations take approx. 10x more cycles. I was thinking about converting it into fixed point arithmetic but after long time spent over a piece of paper and calculator I just gave up. Nothing seems to work. Do you know of any method with which I could convert the coefficients and add some bitshifts to make it a fixed point arithmetic filter?

I have 16bit DAC so the samples I process are 16 bit signed but the CPU is 32 bit so the filter can operate on 32bit integers.

  • $\begingroup$ Does your CPU include a fixed-point multiplier? I've used that, you need to substitute your C products by some assembly code. $\endgroup$ – Juancho Jun 14 '17 at 17:44
  • $\begingroup$ It's Atmel SAM3x8E based on ARM Cortex M4. I think it should have it. Regardless - I'm looking for some general conversion rule for this. I was trying to premultiply the coefficients by bitshifting and then shifting back, but it's not so trivial and it's easy to make mistake. Is there some program that could do that for me? $\endgroup$ – Max Walczak Jun 14 '17 at 18:28
  • 1
    $\begingroup$ you might want to first model your 4-pole Moog (with "regeneration") as an analog filter, find out where the poles and zeros (on the $s$-plane) are, then use a method like the bilinear transform to make it into a digital filter with poles and zeros in the $z$-plane. then you want to consider how fixed-point mathematics is done, in general, in a computer. lotsa discussion about that. $\endgroup$ – robert bristow-johnson Jun 14 '17 at 19:48
  • $\begingroup$ Does your compiler support 16 bit short floats? $\endgroup$ – user28715 Jun 15 '17 at 19:13
  • $\begingroup$ Unfortunately no, it doesn't :( Or at least I'm not aware of it. The whole board is Arduino Due and it has SAM3x8E microcontroller based on ARM Cortex M-3 $\endgroup$ – Max Walczak Jun 15 '17 at 19:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.