Update: I added better images so you can see the issue better.
My low pass function seems to cause weird spikes every time the signal passes "ground". I've tried numerous input ranges (-1 - 1) (-127 - 128) (0 - 255). The low pass does work but there are always these spikes.
It's not a display issue either because I wrote the data to a file and opened it in audacity and it looks the same.
This is the function. The data is loaded from a wav file and converted to 8bit mono with SDL2. I want it to take the data from wav_buffer, apply the low pass filter, then copy it to loud_buffer. I have images below that show both displays of wav_buffer and loud_buffer.
// for reference
Uint8 *wav_buffer;
int wav_length;
Uint8 *loud_buffer;
const int filter_cutoff = 2000;
const int sRate = 44100;
void low_pass()
{
float prevOutput = 0;
float prevInput = 0;
float x = tanf(M_PI * filter_cutoff / sRate);
float output;
for (int p = 0; p < wav_length; p++)
{
output = x * wav_buffer[p] + x * prevInput - (x-1) * prevOutput;
output /= (x+1);
loud_buffer[p] = output;
prevOutput = output;
prevInput = wav_buffer[p];
}
}
This is the data in wav_buffer. All good here.
and this is loud_buffer after the low_pass function.
Found the solution! I feel kinda dumb now :|
Using Sint8 instead of Uint8 for the input and output is what fixed it. This is clearly specific to SDL datatypes because without those types the previous function worked perfectly.
void low_pass()
{
long double x = tanf(M_PI * filter_cutoff / sRate);
long double output = 128;
Sint8 out; // Sint8 here was the solution :/
Sint8 input; // ^^^
for (int p = 0; p < wav_length; p++)
{
input = wav_buffer[p];
output = x * input + x * output - (x-1) * output;
output /= (x+1);
out = (Sint8)output;
loud_buffer[p] = out;
}
}