WIP
This commit is contained in:
parent
caffec76a4
commit
739ef26da3
|
@ -11,6 +11,11 @@
|
||||||
// standard includes, or includes needed for type declarations
|
// standard includes, or includes needed for type declarations
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// forward declares, allowing us to avoid including the C library header
|
||||||
|
extern "C" {
|
||||||
|
struct fir_filter_t;
|
||||||
|
}
|
||||||
|
|
||||||
/*! \defgroup libfirpp C++ library */
|
/*! \defgroup libfirpp C++ library */
|
||||||
|
|
||||||
/*! \brief All %FIR library functions and classes.
|
/*! \brief All %FIR library functions and classes.
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#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>
|
||||||
|
|
||||||
namespace FIR {
|
namespace FIR {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* libfir/src/libfir++/100_Filter.cc
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::Filter(int ncoeff, const double* coeff, Symmetry symm)
|
||||||
|
{
|
||||||
|
fi_ = fir_filter_new(ncoeff, coeff, static_cast<enum fir_symmetry>(symm));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::Filter(const Filter& other)
|
||||||
|
{
|
||||||
|
fi_ = fir_filter_clone(other.fi_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::Filter(const std::vector<double>& coeff, Symmetry symm)
|
||||||
|
{
|
||||||
|
int ncoeff = coeff.size();
|
||||||
|
double* cc = static_cast<double*>(alloca(ncoeff * sizeof(double)));
|
||||||
|
|
||||||
|
for(int i = 0; i < ncoeff; ++i) cc[i] = coeff[i];
|
||||||
|
fi_ = fir_filter_new(ncoeff, cc, static_cast<enum fir_symmetry>(symm));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::~Filter()
|
||||||
|
{
|
||||||
|
fir_filter_free(fi_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
Filter::f(double x)
|
||||||
|
{
|
||||||
|
return fir_filter(fi_, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Symmetry
|
||||||
|
Filter::symmetry() const
|
||||||
|
{
|
||||||
|
return static_cast<Symmetry>(fir_filter_get_symmetry(fi_));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Filter::ncoeff() const
|
||||||
|
{
|
||||||
|
return fir_filter_get_ncoeff(fi_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
Filter::coeff(int idx) const
|
||||||
|
{
|
||||||
|
return fir_filter_get_coeff(fi_, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4
|
||||||
|
*/
|
|
@ -0,0 +1,155 @@
|
||||||
|
/* libfir/src/libfir++/100_Filter.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \defgroup libfirpp_fir Basic FIR filtering
|
||||||
|
|
||||||
|
\ingroup libfirpp
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief %FIR filter symmetry.
|
||||||
|
|
||||||
|
\ingroup libfirpp_fir
|
||||||
|
|
||||||
|
The library extensively takes advantage of the symmetry that is often present
|
||||||
|
in %FIR filter coefficient sets.
|
||||||
|
|
||||||
|
\note The numeric constants match those used in \ref libfir, so it is possible
|
||||||
|
to pass them directly between the libraries as required.
|
||||||
|
|
||||||
|
*/
|
||||||
|
enum Symmetry {
|
||||||
|
/*! \brief No symmetry. */
|
||||||
|
SymmetryNone,
|
||||||
|
|
||||||
|
/*! \brief Odd symmetry (odd total number of points). */
|
||||||
|
SymmetryOdd,
|
||||||
|
|
||||||
|
/*! \brief Even symmetry (even total number of points). */
|
||||||
|
SymmetryEven,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Basic FIR filter object.
|
||||||
|
|
||||||
|
\ingroup libfirpp_fir
|
||||||
|
|
||||||
|
*/
|
||||||
|
class Filter {
|
||||||
|
public:
|
||||||
|
/*! \brief Construct new filter.
|
||||||
|
|
||||||
|
\param ncoeff Number of coefficients in array \a coeff.
|
||||||
|
\param coeff Pointer to array of %FIR filter coefficients.
|
||||||
|
\param symm Whether coefficients are symmetric or not.
|
||||||
|
|
||||||
|
Builds a new filter. The number of coefficients \a ncoeff should reflect the
|
||||||
|
number of elements in the array \a coeff. If the filter is symmetric, the
|
||||||
|
actual %FIR filter itself will consist of \a 2*ncoeff (even symmetry) or
|
||||||
|
\a 2*ncoeff-1 (odd symmetry) points, as the symmetrical coefficients are
|
||||||
|
not passed.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Filter(int ncoeff, const double* coeff, Symmetry symm = SymmetryNone);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Construct filter by copying coefficients from another instance.
|
||||||
|
|
||||||
|
\param other Filter to copy coefficients from.
|
||||||
|
|
||||||
|
Constructs a new filter object which copies the coefficients (but not the
|
||||||
|
state, i.e. previous sample values) from the filter object \a other.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Filter(const Filter& other);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Construct new filter.
|
||||||
|
|
||||||
|
\param coeff Array of coefficients.
|
||||||
|
\param symm Whether coefficients are symmetric or not.
|
||||||
|
|
||||||
|
Builds a new filter. If the filter coefficient set is symmetric, then
|
||||||
|
\a coeff should only contain the non-repeated elements.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Filter(const std::vector<double>& coeff, Symmetry symm = SymmetryNone);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Destructor (frees underlying memory). */
|
||||||
|
virtual ~Filter();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Filter a sample.
|
||||||
|
|
||||||
|
\param x Input sample.
|
||||||
|
\returns Filter output.
|
||||||
|
|
||||||
|
Filters a sample. If this is the very first sample passed to the instance
|
||||||
|
after construction, it will be taken as the steady-state DC input and the
|
||||||
|
filter primed appropriately.
|
||||||
|
|
||||||
|
*/
|
||||||
|
double f(double x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Query filter's symmetry.
|
||||||
|
|
||||||
|
\returns Symmetry of filter.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Symmetry symmetry() const;
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Query number of coefficients in filter.
|
||||||
|
|
||||||
|
\returns Number of coefficients.
|
||||||
|
|
||||||
|
This function returns the number of coefficients. It ignores symmetry, so it
|
||||||
|
returns the total number of coefficients regardless of whether symmetry has
|
||||||
|
allowed us to store only half of them.
|
||||||
|
|
||||||
|
*/
|
||||||
|
int ncoeff() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Retrieve value of coefficient from filter.
|
||||||
|
|
||||||
|
\param idx Index of coefficient (0 ≤ \a idx < \ref ncoeff()).
|
||||||
|
\returns Value of coefficient.
|
||||||
|
|
||||||
|
This function retrieves the coefficient at \a idx. This works even for
|
||||||
|
coefficients that are not actually stored due to symmetry.
|
||||||
|
|
||||||
|
*/
|
||||||
|
double coeff(int idx) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
|
@ -1,47 +0,0 @@
|
||||||
/* 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
|
|
||||||
*/
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
/* Below are all the includes used throughout the library. */
|
/* Below are all the includes used throughout the library. */
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -46,7 +46,7 @@ symm_setup(struct fir_filter_t* fi, int delay)
|
||||||
|
|
||||||
|
|
||||||
struct fir_filter_t*
|
struct fir_filter_t*
|
||||||
fir_filter_new(const double* coeff, int ncoeff, enum fir_symmetry symm)
|
fir_filter_new(int ncoeff, const double* coeff, enum fir_symmetry symm)
|
||||||
{
|
{
|
||||||
struct fir_filter_t* fi;
|
struct fir_filter_t* fi;
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ fir_filter_free(struct fir_filter_t* fi)
|
||||||
struct fir_filter_t*
|
struct fir_filter_t*
|
||||||
fir_filter_clone(const struct fir_filter_t* fi)
|
fir_filter_clone(const struct fir_filter_t* fi)
|
||||||
{
|
{
|
||||||
struct fir_filter_t* out = fir_filter_new(fi->coeff, fi->ncoeff, fi->symm);
|
struct fir_filter_t* out = fir_filter_new(fi->ncoeff, fi->coeff, fi->symm);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +157,59 @@ fir_filter(struct fir_filter_t* fi, double x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum fir_symmetry
|
||||||
|
fir_filter_get_symmetry(const struct fir_filter_t* fi)
|
||||||
|
{
|
||||||
|
return fi->symm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
fir_filter_get_ncoeff(const struct fir_filter_t* fi)
|
||||||
|
{
|
||||||
|
switch(fi->symm) {
|
||||||
|
case fir_symmetry_none:
|
||||||
|
return fi->ncoeff;
|
||||||
|
|
||||||
|
case fir_symmetry_odd:
|
||||||
|
return 2 * fi->ncoeff + 1;
|
||||||
|
|
||||||
|
case fir_symmetry_even:
|
||||||
|
return 2 * fi->ncoeff;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(0);
|
||||||
|
return fir_symmetry_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
fir_filter_get_coeff(const struct fir_filter_t* fi, int idx)
|
||||||
|
{
|
||||||
|
switch(fi->symm) {
|
||||||
|
case fir_symmetry_none:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case fir_symmetry_odd:
|
||||||
|
if(idx >= fi->ncoeff) {
|
||||||
|
idx = 2 * (fi->ncoeff - 1) - idx;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case fir_symmetry_even:
|
||||||
|
if(idx >= fi->ncoeff) {
|
||||||
|
idx = 2 * fi->ncoeff - 1 - idx;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fi->coeff[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* options for text editors
|
/* options for text editors
|
||||||
vim: expandtab:ts=4:sw=4
|
vim: expandtab:ts=4:sw=4
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,8 +45,8 @@ enum fir_symmetry {
|
||||||
|
|
||||||
/*! \brief Allocate %FIR filter instance.
|
/*! \brief Allocate %FIR filter instance.
|
||||||
|
|
||||||
\param coeff Pointer to array of coefficients.
|
|
||||||
\param ncoeff Number of coefficients in \a coeff (must be ≥ 1).
|
\param ncoeff Number of coefficients in \a coeff (must be ≥ 1).
|
||||||
|
\param coeff Pointer to array of coefficients.
|
||||||
\param symm Whether there is any symmetry.
|
\param symm Whether there is any symmetry.
|
||||||
\returns Newly-allocated filter object.
|
\returns Newly-allocated filter object.
|
||||||
\retval 0 on error (and see \a errno).
|
\retval 0 on error (and see \a errno).
|
||||||
|
@ -61,7 +61,7 @@ The contents of \a coeff are copied so it is not necessary to keep the original
|
||||||
array in order to run the filter.
|
array in order to run the filter.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
struct fir_filter_t* fir_filter_new(const double* coeff, int ncoeff,
|
struct fir_filter_t* fir_filter_new(int ncoeff, const double* coeff,
|
||||||
enum fir_symmetry symm);
|
enum fir_symmetry symm);
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ void fir_filter_free(struct fir_filter_t* fi);
|
||||||
/*! \brief Clone %FIR filter instance.
|
/*! \brief Clone %FIR filter instance.
|
||||||
|
|
||||||
\param fi Filter object to clone.
|
\param fi Filter object to clone.
|
||||||
|
\returns Newly-allocated filter object.
|
||||||
|
|
||||||
Clones the %FIR filter object \a fi, returning a new %FIR filter object that
|
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
|
is ready to use. The new copy will have its own copy of the required
|
||||||
|
@ -112,6 +113,44 @@ double fir_filter(struct fir_filter_t* fi, double x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Find symmetry of filter.
|
||||||
|
|
||||||
|
\param fi Filter object.
|
||||||
|
\returns Symmetry.
|
||||||
|
|
||||||
|
*/
|
||||||
|
enum fir_symmetry fir_filter_get_symmetry(const struct fir_filter_t* fi);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Find number of coefficients in filter.
|
||||||
|
|
||||||
|
\param fi Filter object.
|
||||||
|
\returns Number of coefficients.
|
||||||
|
|
||||||
|
This function returns the number of coefficients. It ignores symmetry, so it
|
||||||
|
returns the total number of coefficients regardless of whether symmetry has
|
||||||
|
allowed us to store only half of them.
|
||||||
|
|
||||||
|
*/
|
||||||
|
int fir_filter_get_ncoeff(const struct fir_filter_t* fi);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Retrieve value of coefficient from filter.
|
||||||
|
|
||||||
|
\param fi Filter object.
|
||||||
|
\param idx Index of coefficient (0 ≤ \a idx < \ref fir_filter_get_ncoeff()).
|
||||||
|
\returns Value of coefficient.
|
||||||
|
|
||||||
|
This function retrieves the coefficient at \a idx. This works even for
|
||||||
|
coefficients that are not actually stored due to symmetry.
|
||||||
|
|
||||||
|
*/
|
||||||
|
double fir_filter_get_coeff(const struct fir_filter_t* fi, int idx);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!@}*/
|
/*!@}*/
|
||||||
/* options for text editors
|
/* options for text editors
|
||||||
vim: expandtab:ts=4:sw=4:syntax=ch.doxygen
|
vim: expandtab:ts=4:sw=4:syntax=ch.doxygen
|
||||||
|
|
|
@ -41,7 +41,7 @@ fir_sinc_lowpass(int npoints, double corner, double gain)
|
||||||
coeff[i] *= gain;
|
coeff[i] *= gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fir_filter_new(coeff, spoints,
|
return fir_filter_new(spoints, coeff,
|
||||||
(npoints & 1) ? fir_symmetry_odd : fir_symmetry_even);
|
(npoints & 1) ? fir_symmetry_odd : fir_symmetry_even);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue