WIP
This commit is contained in:
parent
679b37dc35
commit
d42f63388e
|
@ -8,6 +8,10 @@
|
||||||
#include "fir.h"
|
#include "fir.h"
|
||||||
|
|
||||||
/* Below are all the includes used throughout the library. */
|
/* Below are all the includes used throughout the library. */
|
||||||
|
#include <alloca.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* options for text editors
|
/* options for text editors
|
||||||
vim: expandtab:ts=4:sw=4
|
vim: expandtab:ts=4:sw=4
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* libfir/src/libfir/100_fir.c
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* 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
|
||||||
|
*/
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* libfir/src/libfir/100_fir.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* 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
|
||||||
|
*/
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* libfir/src/libfir/200_common_filters.c
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* 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
|
||||||
|
*/
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* libfir/src/libfir/200_common_filters.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct fir_filter_t* fir_sinc_lowpass(int npoints, double corner);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4
|
||||||
|
*/
|
|
@ -14,7 +14,7 @@ then
|
||||||
libfir="obj/${libfir_BASE}.so.${SOMAJOR}.${SOMICRO}"
|
libfir="obj/${libfir_BASE}.so.${SOMAJOR}.${SOMICRO}"
|
||||||
libfir_DEP_CFLAGS="" # @TODO@ cflags
|
libfir_DEP_CFLAGS="" # @TODO@ cflags
|
||||||
libfir_DEP_LIBS="" # @TODO@ libs
|
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"
|
-D_GNU_SOURCE -std=gnu99"
|
||||||
|
|
||||||
echo "Building library ${libfir}..."
|
echo "Building library ${libfir}..."
|
||||||
|
|
Loading…
Reference in New Issue