You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

73 lines
2.4 KiB
C

#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "filter.h"
void filter_init(struct Filter *filter, float cutoff, float resonance) {
memset(filter, 0, sizeof(struct Filter));
filter->cutoff = cutoff;
filter->resonance = resonance;
}
void filter_set_cutoff(struct Filter *filter, float cutoff) {
filter->cutoff = cutoff;
if(filter->cutoff > 0.9) filter->cutoff = 0.9;
else if(filter->cutoff < 0.0) filter->cutoff = 0.0;
}
void filter_set_resonance(struct Filter *filter, float resonance) {
filter->resonance = resonance;
}
// http://www.musicdsp.org/showone.php?id=25
// float filter_sample(struct Filter *filter, float input) {
// float q = 1.0f - filter->cutoff;
// float p = filter->cutoff + 0.8f * filter->cutoff * q;
// float f = p + p - 1.0f;
// q = filter->resonance * (1.0f + 0.5f * q * (1.0f - q + 5.6f * q * q));
// #define OVERSAMPLE 2
// float output = 0;
// for(int i = 0; i < OVERSAMPLE; i++) {
// input -= q * filter->b4; //feedback
// float t1 = filter->b1; filter->b1 = (input + filter->b0) * p - filter->b1 * f;
// float t2 = filter->b2; filter->b2 = (filter->b1 + t1) * p - filter->b2 * f;
// t1 = filter->b3; filter->b3 = (filter->b2 + t2) * p - filter->b3 * f;
// filter->b4 = (filter->b3 + t1) * p - filter->b4 * f;
// filter->b4 = filter->b4 - filter->b4 * filter->b4 * filter->b4 * 0.166667f; //clipping
// filter->b0 = input;
// output += filter->b4;
// }
// return output / (float)OVERSAMPLE;
// }
// mad's filter code
float filter_sample(struct Filter *filter, float input) {
if(++filter->last_calc >= 16) {
filter->last_calc = 0;
filter->cutoff_calc = pow(0.5, 8.5 - filter->cutoff * 8);
filter->resonance_calc = pow(0.5, (1.0 - filter->resonance) * 4.5);
}
float cutoff = filter->cutoff_calc;
float resonance = filter->resonance_calc;
#define OVERSAMPLE 2
float output = 0;
for(int i = 0; i < OVERSAMPLE; i++) {
float in = filter->resonance_input;
if(in > 1) in = 1;
if(in < -1) in = -1;
in = 1.5*in - 0.5*in*in*in;
in = input - in;
filter->stage_1 += (in - filter->stage_1) * cutoff;
filter->stage_2 += (filter->stage_1 - filter->stage_2) * cutoff;
filter->stage_3 += (filter->stage_2 - filter->stage_3) * cutoff;
filter->stage_4 += (filter->stage_3 - filter->stage_4) * cutoff;
output += filter->stage_4;
filter->resonance_input = output * resonance;
}
return output / OVERSAMPLE;
}