WIP
This commit is contained in:
parent
caffec76a4
commit
739ef26da3
|
@ -11,6 +11,11 @@
|
|||
// standard includes, or includes needed for type declarations
|
||||
#include <vector>
|
||||
|
||||
// forward declares, allowing us to avoid including the C library header
|
||||
extern "C" {
|
||||
struct fir_filter_t;
|
||||
}
|
||||
|
||||
/*! \defgroup libfirpp C++ library */
|
||||
|
||||
/*! \brief All %FIR library functions and classes.
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "fir++.h"
|
||||
|
||||
// Below are all the includes used throughout the library.
|
||||
#include <alloca.h>
|
||||
|
||||
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. */
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -46,7 +46,7 @@ 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)
|
||||
fir_filter_new(int ncoeff, const double* coeff, enum fir_symmetry symm)
|
||||
{
|
||||
struct fir_filter_t* fi;
|
||||
|
||||
|
@ -107,7 +107,7 @@ fir_filter_free(struct fir_filter_t* 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);
|
||||
struct fir_filter_t* out = fir_filter_new(fi->ncoeff, fi->coeff, fi->symm);
|
||||
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
|
||||
vim: expandtab:ts=4:sw=4
|
||||
*/
|
||||
|
|
|
@ -45,8 +45,8 @@ enum fir_symmetry {
|
|||
|
||||
/*! \brief Allocate %FIR filter instance.
|
||||
|
||||
\param coeff Pointer to array of coefficients.
|
||||
\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.
|
||||
\returns Newly-allocated filter object.
|
||||
\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.
|
||||
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
|
@ -82,6 +82,7 @@ void fir_filter_free(struct fir_filter_t* fi);
|
|||
/*! \brief Clone %FIR filter instance.
|
||||
|
||||
\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
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
return fir_filter_new(coeff, spoints,
|
||||
return fir_filter_new(spoints, coeff,
|
||||
(npoints & 1) ? fir_symmetry_odd : fir_symmetry_even);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue