/* (c) by polprog 2018 released on 3-clause BSD license version 1.0 Minimal FIR implementation, based on a structure buffer holds the values of sample delay blocks, weights hold the weighted average weights, [void (*tick)(...) currently unused] Demo program in main() shows an impulse response of a filter that has the weights set by 1/x function. For microcontroller implementation its possible and advisable to do the maths with [u]ints not floats. */ #include #include #include #include typedef struct filter { int filtersize; float* buffer; float* weights; float output; void (*tick)(struct filter, float); //tick is a ptr to a function(filter) returning void } filter_t; filter_t filter_init(int size){ printf("Initializing filter of size %d...\n", size); filter_t filter; filter.filtersize = size; filter.buffer = malloc(sizeof(float) * size); assert(filter.buffer != NULL); filter.weights = malloc(sizeof(float) * size); assert(filter.weights != NULL); filter.output = 0; for(int i = 0; i < filter.filtersize; i++){ filter.buffer[i] = 0; } return filter; } void print_filter_state(filter_t* filter){ printf("Filter state:\nsize=%d\n", 8); printf("buffer=\n[ "); for(int i = 0; i < filter->filtersize; i++){ printf("%f ", filter->buffer[i]); } printf("]\nweights=\n[ "); for(int i = 0; i < filter->filtersize; i++){ printf("%f ", filter->weights[i]); } printf("]\n\n\t\toutput=%f\n\n", filter->output); } void filter_init_weights_hyperbolic(filter_t* filter){ printf("initializing weights hyperbolically...\n"); for(int i = 0; i < filter->filtersize; i++){ filter->weights[i] = (1/ ((float) i+1)); } } void filter_tick(filter_t* filter, float input){ //shift buffer one place right, advancing time for(int i = filter->filtersize-1; i > 0; i--){ filter->buffer[i] = filter->buffer[i-1]; } //insert input to zeroth field filter->buffer[0] = input; //do the maths (weighted average) float output; for(int i = 0; i < filter->filtersize; i++){ output += filter->buffer[i] * filter->weights[i]; } output /= filter->filtersize; filter->output = output; } int main(){ filter_t filter; filter = filter_init(8); //create a filter of length = 8; print_filter_state(&filter); //set up weights - weight(x) = 1/x filter_init_weights_hyperbolic(&filter); print_filter_state(&filter); printf("\n------\n"); print_filter_state(&filter); //send an impulse (dirac's delta) printf("\n\n\t---Impulse!---\n\n"); filter_tick(&filter, 1); //let the time go on for a while for(int i = 0; i <10; i++){ print_filter_state(&filter); filter_tick(&filter, 0); } }