I know this question has been asked to hell and back from many people, and that it will probably get downvoted until it's deleted, but please bear with me.
I am designing a sound engine for one of my projects, which needs to support low-pass filtering (no other filtering required, so no need for extremely robust equalization or high-pass filters).
Unfortunately, I'm not exactly well-versed in DSP math (as I'm more a programmer than anything else), so this has been getting tricky.
What I've found by searching on the internet is a "1-RC and C filter" which is implemented as:
// Coefficient computation
// Cutoff and reso are [0,128) integers
c = 0.5^[(128-Cutoff) / 16.0]
r = 0.5^[( 24+Reso) / 16.0]
v0 = (1.0 - r*c)*v0 - c*v1 + c*input
v1 = (1.0 - r*c)*v1 + c*v0
On the same website, I also found that c can be written frequency-wise with the formula
c = 2.0 * sin(Freq * pi/SampRate)
Since I'm only doing variable low-pass filtering with no resonance, this leads to
c = 2.0 * sin(Freq * pi/SampRate)
r = pow(0.5, 24 / 16.0) = 1 / sqrt(8) = ~0.3536
Since the sound engine is mostly MIDI-related, I've used the frequency cutoffs I've found elsewhere on the internet, which led to a relatively simple formula of
CutoffFreq = 250.0 * 32^x
Where x is bound to [0.0,1.0], which leads to a frequency range of 250Hz~8kHz.
However, this is where my issues start.
Let's assume that we're using a maximum cutoff frequency (that is, there should be no filtering on the data) and that I'm mixing at 44.1kHz.
c = 2.0 * sin(8000.0 * pi/44100.0) = ~1.0791
r = 8^(-0.5) = ~0.3536
1.0 - r*c = ~0.6184
Now let's assume the input signal is a basic triangle:
Input[] = {0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 0.8, 0.6, 0.4, 0.2}
Applying the code above leads to
// Beforehand...
v0 = 0.0
v1 = 0.0
// 1st Sample [works okay]
v0 = 0.6184*0.0 - 1.0791*0.0 + 1.0791*0.0 = 0.0
v1 = 0.6184*0.0 + 1.0791*0.0 = 0.0
// 2nd Sample [incorrect]
v0 = 0.6184*0.0 - 1.0791*0.0 + 1.0791*0.2 = ~0.2158
v1 = 0.6184*0.0 + 1.0791*0.2158 = ~0.2329 [residual 0.0329]
// 3rd Sample [more than doubly incorrect]
v0 = 0.6184*0.2158 - 1.0791*0.2329 + 1.0791*0.4 = ~0.3138
v1 = 0.6184*0.2329 + 1.0791*0.3138 = ~0.4826 [residual 0.0826]
As you can see, this doesn't exactly work correctly. In fact, judging from the sound of it, it's as though I had introduced a slight high-pass filter as well as increased resonance slightly.
As such, I was wondering if anyone could offer an explanation a more programming-related person could understand for computing low-pass filter coefficients and equations, as well as shed some light on how to properly implement this.
Thanks in advance.