WIP
This commit is contained in:
		
							parent
							
								
									679b37dc35
								
							
						
					
					
						commit
						d42f63388e
					
				| 
						 | 
				
			
			@ -8,6 +8,10 @@
 | 
			
		|||
#include "fir.h"
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
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_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}..."
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue