After a week of heavy development on Germination X, and with a fast approaching performance, it seemed the time to dive back into Gameboy DS homebrew and get the bits and pieces of assembler code I’d been playing with together into something I could build more sounds from.

After getting the low level stuff working properly, I got busy making a bunch of audio scenes that I can trigger from Betablocker DS code.

Mostly I’m doing wavetable based things, with lots of frequency and ring modulation. I was also pleased to find this simple resonant filter thanks to the ever fabulous musicdsp archive (and thanks to Paul Kellett for originally posting it):

// set feedback amount given f and q between 0 and 1 fb = q + q/(1.0 - f); // for each sample... buf0 = buf0 + f * (in - buf0 + fb * (buf0 - buf1)); buf1 = buf1 + f * (buf0 - buf1); out = buf1;

The next step was to read Jasper Vijn’s excellent explanation of fixed point maths which I’ve used a bit on the Android but not really totally understood before. Mobile devices tend to only have integer maths at the hardware level, so if we restrict the calculations to fixed point it’s much faster and kinder to batteries than the floating point equivalent. Here is the fixed point version of the filter:

// we are using .10 fixed point (10 bits for the fractional part) #define FX_SHIFT 10 // convert an int into to it's fixed representation inline s32 fx(s32 i) { return i<<FX_SHIFT; } // multiply two fixed point numbers (returns fixed point) inline s32 fxmul(s32 a, s32 b) { return (a*b)>>FX_SHIFT; } // f is cutoff frequecy, q is resonance, s is the filter state void lpf(s16* dst, s16* src, u32 length, s16 f, s16 q, s16 *s) { u32 fb = q+fxmul(q,fx(1)-f); for (u32 i=0; i<length; ++i) { s[0]+=fxmul(f,src[i]-s[0]+fxmul(fb,s[0]-s[1])); s[1]+=fxmul(f,s[0]-s[1]); dst[i]=s[1]; } }

This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

In your filter example, I have two questions:

1. the function to calculate fb multiplies q*(1.0-f). Shouldn’t it be q/(1.0-f)?

2. the main loop uses s[0] and s[1]. Shouldn’t this be indexed by a variable?

Hi Brad – the feedback calculation is indeed wrong, well spotted. The s array is the state of the filter, so there are only two values (I think means it’s a two pole filter?). I’ll check the sound for the feedback calc, I hadn’t noticed anything but it can be hard to tell with the gameboy :)

Actually, the state is during the one sample time. It will change for every sample. So you need to save it off to a buffer which is the filtered result.

I don’t think so – it’s like a running average isn’t it? A bit like a two sample delay – so the output is copied from the last one each sample (dst[i]=s[1];)