WIP
This commit is contained in:
parent
d42f63388e
commit
caffec76a4
1
config
1
config
|
@ -32,4 +32,5 @@ source "scripts/paths"
|
|||
|
||||
# Project-specific variables below.
|
||||
[ -z "${CC}" ] && CC="gcc"
|
||||
[ -z "${CXX}" ] && CXX="g++"
|
||||
[ -z "${CFLAGS}" ] && CFLAGS="-g -O2 -W -Wall"
|
||||
|
|
|
@ -9,6 +9,16 @@
|
|||
#define HEADER_libfirpp
|
||||
|
||||
// standard includes, or includes needed for type declarations
|
||||
#include <vector>
|
||||
|
||||
/*! \defgroup libfirpp C++ library */
|
||||
|
||||
/*! \brief All %FIR library functions and classes.
|
||||
|
||||
\ingroup libfirpp
|
||||
|
||||
*/
|
||||
namespace FIR {
|
||||
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* libfir/src/libfir++/000_TopSource.cc
|
||||
*
|
||||
* Copyright: ©2014, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
// "fir.h" includes <complex.h>, which uses a preprocessor define on the
|
||||
// symbol complex. We need to include it first so that it gets its required
|
||||
// define, and then clear it up before including anything that pulls in the
|
||||
// C++ header <complex>.
|
||||
#include "fir.h"
|
||||
#undef complex
|
||||
|
||||
#include "fir++.h"
|
||||
|
||||
// Below are all the includes used throughout the library.
|
||||
|
||||
namespace FIR {
|
||||
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
|
@ -0,0 +1,47 @@
|
|||
/* libfir/src/libfir++/100_fir.h
|
||||
*
|
||||
* Copyright: ©2014, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*! \defgroup libfirpp_fir Basic FIR filtering
|
||||
|
||||
\ingroup libfirpp
|
||||
|
||||
\todo need our own symmetry enum
|
||||
\todo forward declares
|
||||
\todo coefficient query
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*! \brief Basic FIR filter object.
|
||||
|
||||
\ingroup libfirpp_fir
|
||||
|
||||
*/
|
||||
class Filter {
|
||||
public:
|
||||
Filter(int ncoeff, double* coeff,
|
||||
enum fir_symmetry symm = fir_symmetry_none);
|
||||
Filter(const Filter& other);
|
||||
Filter(const std::vector<double>& coeff,
|
||||
enum fir_symmetry symm = fir_symmetry_none);
|
||||
virtual ~Filter();
|
||||
|
||||
private:
|
||||
struct fir_filter_t* fi_;
|
||||
|
||||
// disallow assignment
|
||||
Filter& operator=(const Filter& other);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||
*/
|
|
@ -5,6 +5,8 @@
|
|||
* License: GPLv3
|
||||
*/
|
||||
|
||||
} // end namespace FIR
|
||||
|
||||
#endif
|
||||
|
||||
/* options for text editors
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
/* libfir/src/libfir++/TopSource.cpp
|
||||
/* libfir/src/libfir++/999_BottomSource.cc
|
||||
*
|
||||
* Copyright: ©2014, Laurence Withers.
|
||||
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||
* License: GPLv3
|
||||
*/
|
||||
|
||||
#include "fir++.h"
|
||||
|
||||
// Below are all the includes used throughout the library.
|
||||
} // end namespace FIR
|
||||
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4
|
|
@ -6,6 +6,8 @@
|
|||
# libfirpp_DEP_CFLAGS
|
||||
# libfirpp_DEP_LIBS
|
||||
|
||||
build_target libfir
|
||||
|
||||
if [ -z ${libfirpp_BUILT} ]
|
||||
then
|
||||
libfirpp_BASE=libfir++
|
||||
|
@ -15,7 +17,7 @@ then
|
|||
libfirpp_DEP_CFLAGS="" # @TODO@ cflags
|
||||
libfirpp_DEP_LIBS="" # @TODO@ libs
|
||||
SO_EXTRA="${libfirpp_DEP_CFLAGS} ${libfirpp_DEP_LIBS} -lstdc++ -lc \
|
||||
-D_GNU_SOURCE"
|
||||
${libfir} -D_GNU_SOURCE"
|
||||
|
||||
echo "Building library ${libfirpp}..."
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ then
|
|||
MONOLITHIC_SOURCE="$(find src/libfir++/ -name '*.h' | sort)"
|
||||
make_monolithic ${HDR} Ch || return 1
|
||||
|
||||
MONOLITHIC_SOURCE="$(find src/libfir++/ -name '*.cpp' | sort)"
|
||||
MONOLITHIC_SOURCE="$(find src/libfir++/ -name '*.cc' | sort)"
|
||||
make_monolithic ${SRC} C || return 1
|
||||
|
||||
libfirpp_MONOLITHIC=1
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \defgroup libfir C library */
|
||||
|
||||
/* standard includes, or includes needed for type declarations */
|
||||
|
||||
/* options for text editors
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
/* Below are all the includes used throughout the library. */
|
||||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -48,8 +48,14 @@ symm_setup(struct fir_filter_t* fi, int delay)
|
|||
struct fir_filter_t*
|
||||
fir_filter_new(const double* coeff, int ncoeff, enum fir_symmetry symm)
|
||||
{
|
||||
struct fir_filter_t* fi = malloc(sizeof(*fi));
|
||||
struct fir_filter_t* fi;
|
||||
|
||||
if(ncoeff < 1) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fi = malloc(sizeof(*fi));
|
||||
fi->coeff = malloc(sizeof(double) * ncoeff);
|
||||
memcpy(fi->coeff, coeff, sizeof(double) * ncoeff);
|
||||
fi->ncoeff = ncoeff;
|
||||
|
|
|
@ -7,29 +7,112 @@
|
|||
|
||||
|
||||
|
||||
/*! \defgroup libfir_fir Basic FIR filtering
|
||||
|
||||
\ingroup libfir
|
||||
|
||||
Routines in this section provide the basic building blocks for %FIR filter use:
|
||||
allocation/build from coefficients, cloning, and the filter operation itself.
|
||||
|
||||
*/
|
||||
/*!@{*/
|
||||
|
||||
|
||||
|
||||
/* opaque structure */
|
||||
struct fir_filter_t;
|
||||
|
||||
|
||||
|
||||
/*! \brief %FIR filter symmetry.
|
||||
|
||||
The library extensively takes advantage of the symmetry that is often present
|
||||
in %FIR filter coefficient sets.
|
||||
|
||||
*/
|
||||
enum fir_symmetry {
|
||||
/*! \brief No symmetry. */
|
||||
fir_symmetry_none,
|
||||
|
||||
/*! \brief Odd symmetry (odd total number of points). */
|
||||
fir_symmetry_odd,
|
||||
|
||||
/*! \brief Even symmetry (even total number of points). */
|
||||
fir_symmetry_even,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*! \brief Allocate %FIR filter instance.
|
||||
|
||||
\param coeff Pointer to array of coefficients.
|
||||
\param ncoeff Number of coefficients in \a coeff (must be ≥ 1).
|
||||
\param symm Whether there is any symmetry.
|
||||
\returns Newly-allocated filter object.
|
||||
\retval 0 on error (and see \a errno).
|
||||
|
||||
Allocates a new %FIR filter based on the given set of coefficients \a coeff.
|
||||
If the coefficient set is known to have odd symmetry of \a N points, then
|
||||
pass \a ncoeff as \a (N+1)/2 (and this is the number of entries in \a coeff
|
||||
that are read). If the coefficient set is known to have even symmetry of \a N
|
||||
points, then pass \a ncoeff as \a N/2.
|
||||
|
||||
The contents of \a coeff are copied so it is not necessary to keep the original
|
||||
array in order to run the filter.
|
||||
|
||||
*/
|
||||
struct fir_filter_t* fir_filter_new(const double* coeff, int ncoeff,
|
||||
enum fir_symmetry symm);
|
||||
|
||||
|
||||
|
||||
/*! \brief Free %FIR filter instance.
|
||||
|
||||
\param fi Filter object (may be 0).
|
||||
\returns Newly-allocated filter object.
|
||||
|
||||
Frees all memory associated with the filter object \a fi. Does nothing if
|
||||
passed a null pointer.
|
||||
|
||||
*/
|
||||
void fir_filter_free(struct fir_filter_t* fi);
|
||||
|
||||
|
||||
|
||||
/*! \brief Clone %FIR filter instance.
|
||||
|
||||
\param fi Filter object to clone.
|
||||
|
||||
Clones the %FIR filter object \a fi, returning a new %FIR filter object that
|
||||
is ready to use. The new copy will have its own copy of the required
|
||||
coefficients and does not hold any reference to the original.
|
||||
|
||||
Note that filter state (i.e. previous samples) is not copied; the new filter
|
||||
will be fresh.
|
||||
|
||||
*/
|
||||
struct fir_filter_t* fir_filter_clone(const struct fir_filter_t* fi);
|
||||
|
||||
|
||||
|
||||
/*! \brief Run %FIR filter.
|
||||
|
||||
\param fi Filter object.
|
||||
\param x Input sample.
|
||||
\returns Output sample.
|
||||
|
||||
This function runs the filter for the given input sample \a x, returning an
|
||||
output sample \a y. If this is the very first sample after creation (either via
|
||||
\ref fir_filter_new() or \ref fir_filter_clone()), then this sample will be
|
||||
considered as the steady-state value and the previous-sample values stored in
|
||||
\a fi will be initialised to \a x.
|
||||
|
||||
*/
|
||||
double fir_filter(struct fir_filter_t* fi, double x);
|
||||
|
||||
|
||||
|
||||
/*!@}*/
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4
|
||||
vim: expandtab:ts=4:sw=4:syntax=ch.doxygen
|
||||
*/
|
||||
|
|
|
@ -8,11 +8,16 @@
|
|||
|
||||
|
||||
struct fir_filter_t*
|
||||
fir_sinc_lowpass(int npoints, double corner)
|
||||
fir_sinc_lowpass(int npoints, double corner, double gain)
|
||||
{
|
||||
double* coeff, t;
|
||||
double* coeff, t, sum = 0;
|
||||
int i, spoints;
|
||||
|
||||
if(npoints < 1) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find number of points after taking symmetry into account */
|
||||
spoints = (npoints + 1) / 2;
|
||||
coeff = alloca(sizeof(double) * spoints);
|
||||
|
@ -21,13 +26,21 @@ fir_sinc_lowpass(int npoints, double corner)
|
|||
for(i = 0; i < spoints; ++i) {
|
||||
if((i * 2 + 1) == npoints) {
|
||||
coeff[i] = 1;
|
||||
sum += 1; /* not 2, as we don't repeat this coeff */
|
||||
} else {
|
||||
t = i + 0.5 - npoints * 0.5;
|
||||
t *= corner * 2;
|
||||
coeff[i] = sin(t) / t;
|
||||
sum += coeff[i] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* normalise gain */
|
||||
gain /= sum;
|
||||
for(i = 0; i < spoints; ++i) {
|
||||
coeff[i] *= gain;
|
||||
}
|
||||
|
||||
return fir_filter_new(coeff, spoints,
|
||||
(npoints & 1) ? fir_symmetry_odd : fir_symmetry_even);
|
||||
}
|
||||
|
|
|
@ -7,10 +7,41 @@
|
|||
|
||||
|
||||
|
||||
struct fir_filter_t* fir_sinc_lowpass(int npoints, double corner);
|
||||
/*! \defgroup libfir_common Common filter types
|
||||
|
||||
\ingroup libfir
|
||||
|
||||
Routines in this section instantiate %FIR filters using algorithms to build
|
||||
commonly-used types of filter, such as brickwall low-pass etc.
|
||||
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
||||
/*!@{*/
|
||||
|
||||
|
||||
|
||||
/*! \brief Brickwall low-pass linear phase: sinc filter.
|
||||
|
||||
\param npoints Number of points required (≥1).
|
||||
\param corner Corner frequency as fraction of sample rate.
|
||||
\param gain Gain of filter.
|
||||
\returns Newly-allocated %FIR filter.
|
||||
|
||||
Builds a truncated-sinc filter which has a low-pass, brickwall effect (cutoff
|
||||
at \a corner, which is a fraction of sampling rate, i.e. 0 < \a corner <
|
||||
0.5).
|
||||
|
||||
The number of points \a npoints is a trade-off between accuracy of filter (an
|
||||
ideal sinc filter would have an infinite number of points) and computation time.
|
||||
\a npoints may be odd or even; symmetry will be exploited in either case.
|
||||
|
||||
The DC gain of the filter is normalised to \a gain, which is often 1.0.
|
||||
|
||||
*/
|
||||
struct fir_filter_t* fir_sinc_lowpass(int npoints, double corner, double gain);
|
||||
|
||||
|
||||
|
||||
/*!@}*/
|
||||
/* options for text editors
|
||||
vim: expandtab:ts=4:sw=4:syntax=ch.doxygen
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue