From d42f63388e64f39586de9d5b798381db9e30aa30 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Wed, 9 Jul 2014 16:52:38 +0000 Subject: [PATCH] WIP --- src/libfir/000_TopSource.c | 4 + src/libfir/100_fir.c | 156 ++++++++++++++++++++++++++++++++ src/libfir/100_fir.h | 35 +++++++ src/libfir/200_common_filters.c | 39 ++++++++ src/libfir/200_common_filters.h | 16 ++++ src/libfir/build.lib | 2 +- 6 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 src/libfir/100_fir.c create mode 100644 src/libfir/100_fir.h create mode 100644 src/libfir/200_common_filters.c create mode 100644 src/libfir/200_common_filters.h diff --git a/src/libfir/000_TopSource.c b/src/libfir/000_TopSource.c index 364de11..2f6be6c 100644 --- a/src/libfir/000_TopSource.c +++ b/src/libfir/000_TopSource.c @@ -8,6 +8,10 @@ #include "fir.h" /* Below are all the includes used throughout the library. */ +#include +#include +#include +#include /* options for text editors vim: expandtab:ts=4:sw=4 diff --git a/src/libfir/100_fir.c b/src/libfir/100_fir.c new file mode 100644 index 0000000..7ebab7c --- /dev/null +++ b/src/libfir/100_fir.c @@ -0,0 +1,156 @@ +/* libfir/src/libfir/100_fir.c + * + * Copyright: ©2014, Laurence Withers. + * Author: Laurence Withers + * License: GPLv3 + */ + + + +struct fir_symm_store { + double* d; + int pos, size; +}; + + + +struct fir_filter_t { + double* coeff; + int ncoeff; + + int primed; + double* x; + int xpos; + + enum fir_symmetry symm; + int nsymm; + struct fir_symm_store* symm_store; +}; + + + +static void +symm_setup(struct fir_filter_t* fi, int delay) +{ + int i; + + fi->symm_store = malloc(sizeof(struct fir_symm_store) * fi->nsymm); + for(i = 0; i < fi->nsymm; ++i) { + fi->symm_store[i].d = malloc(sizeof(double) * delay); + fi->symm_store[i].pos = 0; + fi->symm_store[i].size = delay; + delay -= 2; + } +} + + + +struct fir_filter_t* +fir_filter_new(const double* coeff, int ncoeff, enum fir_symmetry symm) +{ + struct fir_filter_t* fi = malloc(sizeof(*fi)); + + fi->coeff = malloc(sizeof(double) * ncoeff); + memcpy(fi->coeff, coeff, sizeof(double) * ncoeff); + fi->ncoeff = ncoeff; + + fi->primed = 0; + fi->x = malloc(sizeof(double) * ncoeff); + fi->xpos = 0; + + fi->symm = symm; + switch(symm) { + case fir_symmetry_none: + fi->nsymm = 0; + fi->symm_store = 0; + break; + + case fir_symmetry_odd: + fi->nsymm = ncoeff - 1; + symm_setup(fi, 2 * ncoeff - 1); + break; + + case fir_symmetry_even: + fi->nsymm = ncoeff; + symm_setup(fi, 2 * ncoeff); + break; + } + + return fi; +} + + + +void +fir_filter_free(struct fir_filter_t* fi) +{ + int i; + + if(!fi) return; + + for(i = 0; i < fi->nsymm; ++i) free(fi->symm_store[i].d); + free(fi->symm_store); + + free(fi->x); + free(fi->coeff); + free(fi); +} + + + +struct fir_filter_t* +fir_filter_clone(const struct fir_filter_t* fi) +{ + struct fir_filter_t* out = fir_filter_new(fi->coeff, fi->ncoeff, fi->symm); + return out; +} + + + +double +fir_filter(struct fir_filter_t* fi, double x) +{ + int i, xpos, spos; + double p, y = 0; + + if(!fi->primed) { + fi->primed = 1; + for(i = 0; i < fi->ncoeff; ++i) fi->x[i] = x; + for(i = 0; i < fi->nsymm; ++i) { + for(spos = 0; spos < fi->symm_store[i].size; ++spos) { + fi->symm_store[i].d[spos] = x * fi->coeff[i]; + } + } + } + + xpos = fi->xpos; + fi->x[xpos] = x; + + for(i = 0; i < fi->ncoeff; ++i) { + p = fi->x[xpos] * fi->coeff[i]; + y += p; + if(!xpos--) xpos += fi->ncoeff; + + if(i < fi->nsymm) { + spos = fi->symm_store[i].pos; + fi->symm_store[i].d[spos] = p; + if(++spos == fi->symm_store[i].size) spos = 0; + fi->symm_store[i].pos = spos; + } + } + + if(++fi->xpos == fi->ncoeff) fi->xpos = 0; + + for(i = 0; i < fi->nsymm; ++i) { + spos = fi->symm_store[i].pos; + y += fi->symm_store[i].d[spos]; + } + + return y; +} + + + +/* options for text editors +vim: expandtab:ts=4:sw=4 +*/ diff --git a/src/libfir/100_fir.h b/src/libfir/100_fir.h new file mode 100644 index 0000000..b3f28e8 --- /dev/null +++ b/src/libfir/100_fir.h @@ -0,0 +1,35 @@ +/* libfir/src/libfir/100_fir.h + * + * Copyright: ©2014, Laurence Withers. + * Author: Laurence Withers + * License: GPLv3 + */ + + + +struct fir_filter_t; + + + +enum fir_symmetry { + fir_symmetry_none, + fir_symmetry_odd, + fir_symmetry_even, +}; + + + +struct fir_filter_t* fir_filter_new(const double* coeff, int ncoeff, + enum fir_symmetry symm); + +void fir_filter_free(struct fir_filter_t* fi); + +struct fir_filter_t* fir_filter_clone(const struct fir_filter_t* fi); + +double fir_filter(struct fir_filter_t* fi, double x); + + + +/* options for text editors +vim: expandtab:ts=4:sw=4 +*/ diff --git a/src/libfir/200_common_filters.c b/src/libfir/200_common_filters.c new file mode 100644 index 0000000..9916aba --- /dev/null +++ b/src/libfir/200_common_filters.c @@ -0,0 +1,39 @@ +/* libfir/src/libfir/200_common_filters.c + * + * Copyright: ©2014, Laurence Withers. + * Author: Laurence Withers + * License: GPLv3 + */ + + + +struct fir_filter_t* +fir_sinc_lowpass(int npoints, double corner) +{ + double* coeff, t; + int i, spoints; + + /* find number of points after taking symmetry into account */ + spoints = (npoints + 1) / 2; + coeff = alloca(sizeof(double) * spoints); + + /* only fill out for t ≤ 0 */ + for(i = 0; i < spoints; ++i) { + if((i * 2 + 1) == npoints) { + coeff[i] = 1; + } else { + t = i + 0.5 - npoints * 0.5; + t *= corner * 2; + coeff[i] = sin(t) / t; + } + } + + return fir_filter_new(coeff, spoints, + (npoints & 1) ? fir_symmetry_odd : fir_symmetry_even); +} + + + +/* options for text editors +vim: expandtab:ts=4:sw=4 +*/ diff --git a/src/libfir/200_common_filters.h b/src/libfir/200_common_filters.h new file mode 100644 index 0000000..cfd996e --- /dev/null +++ b/src/libfir/200_common_filters.h @@ -0,0 +1,16 @@ +/* libfir/src/libfir/200_common_filters.h + * + * Copyright: ©2014, Laurence Withers. + * Author: Laurence Withers + * License: GPLv3 + */ + + + +struct fir_filter_t* fir_sinc_lowpass(int npoints, double corner); + + + +/* options for text editors +vim: expandtab:ts=4:sw=4 +*/ diff --git a/src/libfir/build.lib b/src/libfir/build.lib index 18181c3..415be8e 100644 --- a/src/libfir/build.lib +++ b/src/libfir/build.lib @@ -14,7 +14,7 @@ then libfir="obj/${libfir_BASE}.so.${SOMAJOR}.${SOMICRO}" libfir_DEP_CFLAGS="" # @TODO@ cflags libfir_DEP_LIBS="" # @TODO@ libs - SO_EXTRA="${libfir_DEP_CFLAGS} ${libfir_DEP_LIBS} -lc \ + SO_EXTRA="${libfir_DEP_CFLAGS} ${libfir_DEP_LIBS} -lc -lm \ -D_GNU_SOURCE -std=gnu99" echo "Building library ${libfir}..."