Add C++ wrapper library
This commit adds libiir++, a C++ wrapper library which provides a true object-oriented interface. The library has two primary objects, Coeff (coefficient set) and Filter (filter instance) which are implemented internally using the C objects. The C++ implementation does produce additional copies of various bits of information at setup time in order to better support querying the structure of the filter at runtime. This is intended to be useful for a future Python extension that will provide a filter experimentation lab.
This commit is contained in:
parent
ccc5bc6738
commit
911b3eab3d
1
config
1
config
|
@ -33,4 +33,5 @@ source "scripts/paths"
|
||||||
|
|
||||||
# Project-specific variables below.
|
# Project-specific variables below.
|
||||||
[ -z "${CC}" ] && CC="gcc"
|
[ -z "${CC}" ] && CC="gcc"
|
||||||
|
[ -z "${CXX}" ] && CXX="g++"
|
||||||
[ -z "${CFLAGS}" ] && CFLAGS="-g -O2 -W -Wall"
|
[ -z "${CFLAGS}" ] && CFLAGS="-g -O2 -W -Wall"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
lib c++ libiir++ iir++.h
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* libiir/src/libiir++/000_TopHeader.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HEADER_libiirpp
|
||||||
|
#define HEADER_libiirpp
|
||||||
|
|
||||||
|
// standard includes, or includes needed for type declarations
|
||||||
|
#include <complex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// forward declares of opaque C structures (to avoid pulling in header)
|
||||||
|
extern "C" {
|
||||||
|
struct iir_coeff_t;
|
||||||
|
struct iir_filter_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \defgroup libiirpp C++ library */
|
||||||
|
|
||||||
|
/*! \brief All %IIR library functions and classes.
|
||||||
|
|
||||||
|
\ingroup libiirpp
|
||||||
|
|
||||||
|
*/
|
||||||
|
namespace IIR {
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* libiir/src/libiir++/000_TopSource.cc
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "iir++.h"
|
||||||
|
#include "iir.h"
|
||||||
|
|
||||||
|
// iir.h includes <complex.h>, which #defines complex to _Complex. That's fine
|
||||||
|
// for the C header above, but will mess with our code definitions below.
|
||||||
|
#undef complex
|
||||||
|
|
||||||
|
// Below are all the includes used throughout the library.
|
||||||
|
|
||||||
|
namespace IIR {
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4
|
||||||
|
*/
|
|
@ -0,0 +1,80 @@
|
||||||
|
/* libiir/src/libiir++/100_Coeff.cc
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff::Coeff(int nc, const double* c, int nd, const double* d)
|
||||||
|
{
|
||||||
|
cc_ = iir_coeff_new(nc, c, nd, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff::Coeff(const struct iir_coeff_t* cc)
|
||||||
|
{
|
||||||
|
cc_ = iir_coeff_copy(cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff::Coeff(const Coeff& other)
|
||||||
|
{
|
||||||
|
cc_ = iir_coeff_copy(other.cc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff::~Coeff()
|
||||||
|
{
|
||||||
|
iir_coeff_free(cc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Coeff::nc() const
|
||||||
|
{
|
||||||
|
return iir_coeff_get_nc(cc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
Coeff::c(int idx) const
|
||||||
|
{
|
||||||
|
return iir_coeff_get_c(cc_, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Coeff::nd() const
|
||||||
|
{
|
||||||
|
return iir_coeff_get_nd(cc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
Coeff::d(int idx) const
|
||||||
|
{
|
||||||
|
return iir_coeff_get_d(cc_, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::complex<double>
|
||||||
|
Coeff::response(double freq) const
|
||||||
|
{
|
||||||
|
return std::complex<double>(iir_response_c(cc_, freq));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,122 @@
|
||||||
|
/* libiir/src/libiir++/100_Coeff.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \defgroup libiirpp_coeff Coefficient handling
|
||||||
|
|
||||||
|
\ingroup libiirpp
|
||||||
|
|
||||||
|
A set of coefficients for a single stage %IIR filter is represented by an
|
||||||
|
instance of the \ref Coeff class. This class is often instantiated through
|
||||||
|
one of the common filter generator functions (see \ref libiirpp_common_filters).
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief %IIR filter coefficient set
|
||||||
|
|
||||||
|
\ingroup libiirpp_coeff
|
||||||
|
|
||||||
|
An instance of this class represents the set of coefficients used to implement
|
||||||
|
a single-phase %IIR filter. See \ref iir_structure for more information.
|
||||||
|
|
||||||
|
*/
|
||||||
|
class Coeff {
|
||||||
|
public:
|
||||||
|
/*! \brief Constructor with raw coefficients.
|
||||||
|
|
||||||
|
\param nc Number of \a c coefficients, ≥ 1.
|
||||||
|
\param c Array of \a c coefficients.
|
||||||
|
\param nd Number of \a d coefficients, ≥ 1.
|
||||||
|
\param d Array of \a d coefficients.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Coeff(int nc, const double* c, int nd, const double* d);
|
||||||
|
|
||||||
|
/*! \brief Constructor from C library object.
|
||||||
|
|
||||||
|
\param cc Pointer to existing coefficient object.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Coeff(const struct iir_coeff_t* cc);
|
||||||
|
|
||||||
|
/*! \brief Copy constructor.
|
||||||
|
|
||||||
|
\param other Object to copy.
|
||||||
|
|
||||||
|
Performs a full deep copy of the set of coefficients from \a other.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Coeff(const Coeff& other);
|
||||||
|
|
||||||
|
/*! \brief Destructor. */
|
||||||
|
virtual ~Coeff();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Count number of \a c coefficients.
|
||||||
|
|
||||||
|
\returns Number of \a c coefficients, ≥ 1.
|
||||||
|
|
||||||
|
*/
|
||||||
|
int nc() const;
|
||||||
|
|
||||||
|
/*! \brief Retrieve \a c coefficient by index.
|
||||||
|
|
||||||
|
\param idx Index of coefficient (0 ≤ \a idx < \ref nc()).
|
||||||
|
\returns Value of \a c coefficient at index \a idx.
|
||||||
|
|
||||||
|
*/
|
||||||
|
double c(int idx) const;
|
||||||
|
|
||||||
|
/*! \brief Count number of \a d coefficients.
|
||||||
|
|
||||||
|
\returns Number of \a d coefficients, ≥ 1.
|
||||||
|
|
||||||
|
*/
|
||||||
|
int nd() const;
|
||||||
|
|
||||||
|
/*! \brief Retrieve \a d coefficient by index.
|
||||||
|
|
||||||
|
\param idx Index of coefficient (0 ≤ \a idx < \ref nd()).
|
||||||
|
\returns Value of \a d coefficient at index \a idx.
|
||||||
|
|
||||||
|
*/
|
||||||
|
double d(int idx) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Evaluate response of filter at given frequency.
|
||||||
|
|
||||||
|
\param freq Frequency (0 ≤ \a freq ≤ 1).
|
||||||
|
\returns Complex response of filter at given frequency.
|
||||||
|
|
||||||
|
Returns the steady-state response of the filter to a pure input signal of
|
||||||
|
the given frequency. \a freq is expressed as a fraction of the intended
|
||||||
|
sampling rate (with 0.5 being the Nyquist frequency).
|
||||||
|
|
||||||
|
*/
|
||||||
|
std::complex<double> response(double freq) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// allow the Filter class to access cc_ directly
|
||||||
|
friend class Filter;
|
||||||
|
|
||||||
|
// our internal representation is the C object
|
||||||
|
struct iir_coeff_t* cc_;
|
||||||
|
|
||||||
|
// disallow assignment; object is immutable
|
||||||
|
Coeff& operator=(const Coeff& other);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,104 @@
|
||||||
|
/* libiir/src/libiir++/200_Filter.cc
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::Filter(const Coeff& coeff)
|
||||||
|
{
|
||||||
|
coeff_.push_back(new Coeff(coeff));
|
||||||
|
fi_ = iir_filter_new(coeff.cc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::Filter(const Filter& other)
|
||||||
|
{
|
||||||
|
for(int pos = 0, max = other.coeff_.size(); pos < max; ++pos) {
|
||||||
|
Coeff* cc = new Coeff(*other.coeff_[pos]);
|
||||||
|
coeff_.push_back(cc);
|
||||||
|
|
||||||
|
if(!pos) fi_ = iir_filter_new(cc->cc_);
|
||||||
|
else iir_filter_chain(fi_, cc->cc_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::Filter(const char* desc)
|
||||||
|
{
|
||||||
|
fi_ = iir_parse(desc);
|
||||||
|
if(!fi_) return;
|
||||||
|
|
||||||
|
for(int pos = 0, max = iir_filter_coeff_sets(fi_); pos < max; ++pos) {
|
||||||
|
struct iir_coeff_t* c = iir_filter_coeff_set(fi_, pos);
|
||||||
|
coeff_.push_back(new Coeff(c));
|
||||||
|
iir_coeff_free(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Filter::~Filter()
|
||||||
|
{
|
||||||
|
for(int pos = 0, max = coeff_.size(); pos < max; ++pos) delete coeff_[pos];
|
||||||
|
iir_filter_free(fi_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Filter::valid() const
|
||||||
|
{
|
||||||
|
return fi_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
Filter::f(double x)
|
||||||
|
{
|
||||||
|
return iir_filter(fi_, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Filter::numCoeffSet() const
|
||||||
|
{
|
||||||
|
return coeff_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Coeff&
|
||||||
|
Filter::getCoeffSet(int idx) const
|
||||||
|
{
|
||||||
|
return *(coeff_[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Filter::chainCoeffSet(const Coeff& coeff)
|
||||||
|
{
|
||||||
|
coeff_.push_back(new Coeff(coeff));
|
||||||
|
iir_filter_chain(fi_, coeff.cc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::complex<double>
|
||||||
|
Filter::response(double freq) const
|
||||||
|
{
|
||||||
|
return iir_response(fi_, freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,152 @@
|
||||||
|
/* libiir/src/libiir++/200_Filter.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \defgroup libiirpp_filter Basic IIR filtering
|
||||||
|
|
||||||
|
\ingroup libiirpp
|
||||||
|
|
||||||
|
An instance of the \ref Filter class represents the structure and state of an
|
||||||
|
%IIR filter. It may be built up with \ref Coeff instances or parsed from a
|
||||||
|
user-supplied string (see \ref string_desc).
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief %IIR filter coefficient set
|
||||||
|
|
||||||
|
\ingroup libiirpp_filter
|
||||||
|
|
||||||
|
An instance of this class contains both a copy of the set of coefficients used
|
||||||
|
in each filter stage (of which there may be multiple), and all of the state
|
||||||
|
(i.e. previous inputs and outputs) associated with each stage.
|
||||||
|
|
||||||
|
*/
|
||||||
|
class Filter {
|
||||||
|
public:
|
||||||
|
/*! \brief Construct from coefficient set.
|
||||||
|
|
||||||
|
\param coeff Coefficient set.
|
||||||
|
|
||||||
|
This constructor builds a filter chain with one stage. Additional stages may
|
||||||
|
be added via \ref chainCoeffSet(). This constructor will always result in a
|
||||||
|
valid object.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Filter(const Coeff& coeff);
|
||||||
|
|
||||||
|
/*! \brief Copy constructor.
|
||||||
|
|
||||||
|
\param other Filter to copy.
|
||||||
|
|
||||||
|
Copies the structure (but not the state) of the filter \a other. This
|
||||||
|
constructor will always result in a valid object.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Filter(const Filter& other);
|
||||||
|
|
||||||
|
/*! \brief Construct from filter description string.
|
||||||
|
|
||||||
|
\param desc Description string.
|
||||||
|
|
||||||
|
This constructor will parse the description string \a desc (see
|
||||||
|
\ref string_desc for details on what is accepted) and build up a filter
|
||||||
|
as described.
|
||||||
|
|
||||||
|
If the parsing step fails, then \ref valid() will return false and the
|
||||||
|
object must not be used (no other functions except the destructor will be
|
||||||
|
safe to call).
|
||||||
|
|
||||||
|
*/
|
||||||
|
Filter(const char* desc);
|
||||||
|
|
||||||
|
/*! \brief Destructor. */
|
||||||
|
virtual ~Filter();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Determine whether object is valid.
|
||||||
|
|
||||||
|
\retval true if object is valid.
|
||||||
|
\retval false if object is not valid.
|
||||||
|
|
||||||
|
A Filter object might not be valid if it was constructed from a description
|
||||||
|
string that contained an error. In that case this function will return
|
||||||
|
\a false and the object should not be used (no other functions except the
|
||||||
|
destructor will be safe to call).
|
||||||
|
|
||||||
|
*/
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief %Filter a sample.
|
||||||
|
|
||||||
|
\param x Sample.
|
||||||
|
\returns %Filter output.
|
||||||
|
|
||||||
|
Injects a single sample into the filter and returns the output value.
|
||||||
|
|
||||||
|
*/
|
||||||
|
double f(double x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Retrieve number of coefficient sets.
|
||||||
|
|
||||||
|
\returns Number of sets in use (≥1).
|
||||||
|
|
||||||
|
*/
|
||||||
|
int numCoeffSet() const;
|
||||||
|
|
||||||
|
/*! \brief Retrieve coefficient set.
|
||||||
|
|
||||||
|
\param idx Index of set (0 ≤ \a idx < \ref numCoeffSet()).
|
||||||
|
\returns Reference to coefficient set.
|
||||||
|
|
||||||
|
*/
|
||||||
|
const Coeff& getCoeffSet(int idx) const;
|
||||||
|
|
||||||
|
/*! \brief Add another set of coefficients to the filter chain.
|
||||||
|
|
||||||
|
\param coeff Coefficient set to add.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void chainCoeffSet(const Coeff& coeff);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Evaluate response of filter at given frequency.
|
||||||
|
|
||||||
|
\param freq Frequency (0 ≤ \a freq ≤ 1).
|
||||||
|
\returns Complex response of filter at given frequency.
|
||||||
|
|
||||||
|
Returns the steady-state response of the filter to a pure input signal of
|
||||||
|
the given frequency. \a freq is expressed as a fraction of the intended
|
||||||
|
sampling rate (with 0.5 being the Nyquist frequency).
|
||||||
|
|
||||||
|
*/
|
||||||
|
std::complex<double> response(double freq) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// one entry per set of coefficients, in order of execution
|
||||||
|
std::vector<const Coeff*> coeff_;
|
||||||
|
|
||||||
|
// the C object has both state and its own copy of the coefficients
|
||||||
|
struct iir_filter_t* fi_;
|
||||||
|
|
||||||
|
// disallow assignment
|
||||||
|
Filter& operator=(const Filter& other);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* libiir/src/libiir++/300_common_filters.cc
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff
|
||||||
|
ButterworthLowPass(int order, double gain, double corner)
|
||||||
|
{
|
||||||
|
struct iir_coeff_t* cc = iir_butterworth_lowpass(order, gain, corner);
|
||||||
|
Coeff ret(cc);
|
||||||
|
iir_coeff_free(cc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff
|
||||||
|
ButterworthHighPass(int order, double gain, double corner)
|
||||||
|
{
|
||||||
|
struct iir_coeff_t* cc = iir_butterworth_highpass(order, gain, corner);
|
||||||
|
Coeff ret(cc);
|
||||||
|
iir_coeff_free(cc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff
|
||||||
|
ButterworthBandPass(int order, double gain, double corner1, double corner2)
|
||||||
|
{
|
||||||
|
struct iir_coeff_t* cc = iir_butterworth_bandpass(order, gain, corner1,
|
||||||
|
corner2);
|
||||||
|
Coeff ret(cc);
|
||||||
|
iir_coeff_free(cc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coeff
|
||||||
|
ButterworthBandStop(int order, double gain, double corner1, double corner2)
|
||||||
|
{
|
||||||
|
struct iir_coeff_t* cc = iir_butterworth_bandstop(order, gain, corner1,
|
||||||
|
corner2);
|
||||||
|
Coeff ret(cc);
|
||||||
|
iir_coeff_free(cc);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,144 @@
|
||||||
|
/* libiir/src/libiir++/300_common_filters.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \defgroup libiirpp_common_filters Common types of IIR filter
|
||||||
|
|
||||||
|
\ingroup libiirpp
|
||||||
|
|
||||||
|
Routines in this section can be used to build a coefficient set that matches a
|
||||||
|
common %IIR filter type. These can be passed to the \ref Filter class to build
|
||||||
|
up an actual instance of a filter.
|
||||||
|
|
||||||
|
\note It is common to build higher-order filters by chaining together several
|
||||||
|
lower-order filters. The functions in this section do not do that directly,
|
||||||
|
but are intended to build the individual components of a chain. See
|
||||||
|
\ref Filter::Filter(const char*) for an interface which performs this
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*!@{*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief nth-order Butterworth low-pass
|
||||||
|
|
||||||
|
\param order Order of filter (≥1).
|
||||||
|
\param gain Linear gain of filter.
|
||||||
|
\param corner Corner frequency expressed as a fraction of Nyquist
|
||||||
|
(0 ≤ \a corner ≤ 1).
|
||||||
|
|
||||||
|
\returns %IIR filter coefficient set.
|
||||||
|
|
||||||
|
Uses the Exstrom labs code to compute the coefficients of an nth-order (param
|
||||||
|
\a order) Butterworth-type low pass filter with gain \a gain and corner
|
||||||
|
frequency \a corner.
|
||||||
|
|
||||||
|
Note it is recommended to chain multiple filters together to build anything
|
||||||
|
greater than a 4th-order filter. This function won't do that directly for you.
|
||||||
|
\a gain will usually be set to be 1.0.
|
||||||
|
|
||||||
|
The corner frequency corner is expressed as a fraction of the sampling
|
||||||
|
frequency (which is of course not known by the %IIR code). It should lie between
|
||||||
|
0 (0Hz) and 1 (the Nyquist frequency, or ½ the sampling frequency).
|
||||||
|
|
||||||
|
*/
|
||||||
|
Coeff ButterworthLowPass(int order, double gain, double corner);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief nth-order Butterworth high-pass
|
||||||
|
|
||||||
|
\param order Order of filter (≥1).
|
||||||
|
\param gain Linear gain of filter.
|
||||||
|
\param corner Corner frequency expressed as a fraction of Nyquist
|
||||||
|
(0 ≤ \a corner ≤ 1).
|
||||||
|
|
||||||
|
\returns %IIR filter coefficient set.
|
||||||
|
|
||||||
|
Uses the Exstrom labs code to compute the coefficients of an nth-order (param
|
||||||
|
\a order) Butterworth-type high pass filter with gain \a gain and corner
|
||||||
|
frequency \a corner.
|
||||||
|
|
||||||
|
Note it is recommended to chain multiple filters together to build anything
|
||||||
|
greater than a 4th-order filter. This function won't do that directly for you.
|
||||||
|
\a gain will usually be set to be 1.0.
|
||||||
|
|
||||||
|
The corner frequency corner is expressed as a fraction of the sampling
|
||||||
|
frequency (which is of course not known by the %IIR code). It should lie between
|
||||||
|
0 (0Hz) and 1 (the Nyquist frequency, or ½ the sampling frequency).
|
||||||
|
|
||||||
|
*/
|
||||||
|
Coeff ButterworthHighPass(int order, double gain, double corner);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief nth-order Butterworth band-pass
|
||||||
|
|
||||||
|
\param order Order of filter (≥1).
|
||||||
|
\param gain Linear gain of filter.
|
||||||
|
\param corner1 Low corner frequency expressed as a fraction of Nyquist
|
||||||
|
(0 ≤ \a corner ≤ 1).
|
||||||
|
\param corner2 High corner frequency expressed as a fraction of Nyquist
|
||||||
|
(0 ≤ \a corner ≤ 1).
|
||||||
|
|
||||||
|
\returns %IIR filter coefficient set.
|
||||||
|
|
||||||
|
Uses the Exstrom labs code to compute the coefficients of an nth-order (param
|
||||||
|
\a order) Butterworth-type band pass filter with gain \a gain and corner
|
||||||
|
frequencies \a corner1 and \a corner2.
|
||||||
|
|
||||||
|
Note it is recommended to chain multiple filters together to build anything
|
||||||
|
greater than a 4th-order filter. This function won't do that directly for you.
|
||||||
|
\a gain will usually be set to be 1.0.
|
||||||
|
|
||||||
|
The corner frequencies \a corner1 and \a corner2 are expressed as a fraction of
|
||||||
|
the sampling frequency (which is of course not known by the %IIR code). They
|
||||||
|
should lie between 0 (0Hz) and 1 (the Nyquist frequency, or ½ the sampling
|
||||||
|
frequency), and \a corner2 should be greater than \a corner1.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Coeff ButterworthBandPass(int order, double gain, double corner1,
|
||||||
|
double corner2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief nth-order Butterworth band-stop
|
||||||
|
|
||||||
|
\param order Order of filter (≥1).
|
||||||
|
\param gain Linear gain of filter.
|
||||||
|
\param corner1 Low corner frequency expressed as a fraction of Nyquist
|
||||||
|
(0 ≤ \a corner ≤ 1).
|
||||||
|
\param corner2 High corner frequency expressed as a fraction of Nyquist
|
||||||
|
(0 ≤ \a corner ≤ 1).
|
||||||
|
|
||||||
|
\returns %IIR filter coefficient set.
|
||||||
|
|
||||||
|
Uses the Exstrom labs code to compute the coefficients of an nth-order (param
|
||||||
|
\a order) Butterworth-type band stop filter with gain \a gain and corner
|
||||||
|
frequencies \a corner1 and \a corner2.
|
||||||
|
|
||||||
|
Note it is recommended to chain multiple filters together to build anything
|
||||||
|
greater than a 4th-order filter. This function won't do that directly for you.
|
||||||
|
\a gain will usually be set to be 1.0.
|
||||||
|
|
||||||
|
The corner frequencies \a corner1 and \a corner2 are expressed as a fraction of
|
||||||
|
the sampling frequency (which is of course not known by the %IIR code). They
|
||||||
|
should lie between 0 (0Hz) and 1 (the Nyquist frequency, or ½ the sampling
|
||||||
|
frequency), and \a corner2 should be greater than \a corner1.
|
||||||
|
|
||||||
|
*/
|
||||||
|
Coeff ButterworthBandStop(int order, double gain, double corner1,
|
||||||
|
double corner2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!@}*/
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* libiir/src/libiir++/999_BottomHeader.h
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // end namespace IIR
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4:syntax=cpp.doxygen
|
||||||
|
*/
|
|
@ -0,0 +1,12 @@
|
||||||
|
/* libiir/src/libiir++/999_BottomSource.cpp
|
||||||
|
*
|
||||||
|
* Copyright: ©2014, Laurence Withers.
|
||||||
|
* Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
* License: GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // end namspace IIR
|
||||||
|
|
||||||
|
/* options for text editors
|
||||||
|
vim: expandtab:ts=4:sw=4
|
||||||
|
*/
|
|
@ -0,0 +1 @@
|
||||||
|
source src/libiir++/build.lib
|
|
@ -0,0 +1 @@
|
||||||
|
source src/libiir++/build.install-lib
|
|
@ -0,0 +1,35 @@
|
||||||
|
build_target libiir++
|
||||||
|
|
||||||
|
# make paths (this is for Gentoo in particular)
|
||||||
|
build_dir_tree "${LIBDIR}" || return 1
|
||||||
|
build_dir_tree "${BINDIR}" || return 1
|
||||||
|
build_dir_tree "${INCLUDEDIR}" || return 1
|
||||||
|
|
||||||
|
# install library
|
||||||
|
echo "Installing libraries into '${LIBDIR}'"
|
||||||
|
install_file ${libiirpp} ${LIBDIR} 0755 || return 1
|
||||||
|
BASE="${libiirpp_BASE}.so"
|
||||||
|
MAJOR="${BASE}.${SOMAJOR}"
|
||||||
|
MICRO="${MAJOR}.${SOMICRO}"
|
||||||
|
install_symlink "${BASE}" "${MICRO}" "${LIBDIR}"
|
||||||
|
|
||||||
|
# install header
|
||||||
|
echo "Installing header file '${libiirpp_HEADER}' into ${INCLUDEDIR}"
|
||||||
|
install_header ${libiirpp_HEADER} ${INCLUDEDIR} 0644 || return 1
|
||||||
|
|
||||||
|
# install config script
|
||||||
|
echo "Installing config script into ${PKGCONFDIR}"
|
||||||
|
CONFFILE="${INSTALL_PREFIX}${BINDIR}/libiir++-config"
|
||||||
|
|
||||||
|
do_cmd rm -f "${CONFFILE}"
|
||||||
|
do_cmd_redir "${CONFFILE}" sed \
|
||||||
|
-e "s,@VERSION@,${VERSION}," \
|
||||||
|
-e "s,@LIB_DIR@,${LIBDIR}," \
|
||||||
|
-e "s,@INCLUDE_DIR@,${INCLUDEDIR}," \
|
||||||
|
-e "s,@DEP_CFLAGS@,${libiirpp_DEP_CFLAGS}," \
|
||||||
|
-e "s,@DEP_LIBS@,${libiirpp_DEP_LIBS}," \
|
||||||
|
src/libiir++/config-script
|
||||||
|
do_cmd chmod 0644 "${CONFFILE}"
|
||||||
|
print_success "Done"
|
||||||
|
|
||||||
|
# vim: syntax=sh:expandtab:ts=4:sw=4
|
|
@ -0,0 +1,58 @@
|
||||||
|
# These are external variables, and shouldn't clash with anything else
|
||||||
|
# libiirpp
|
||||||
|
# libiirpp_BUILT
|
||||||
|
# libiirpp_HEADER
|
||||||
|
# libiirpp_BASE
|
||||||
|
# libiirpp_DEP_CFLAGS
|
||||||
|
# libiirpp_DEP_LIBS
|
||||||
|
|
||||||
|
build_target libiir
|
||||||
|
|
||||||
|
if [ -z ${libiirpp_BUILT} ]
|
||||||
|
then
|
||||||
|
libiirpp_BASE=libiir++
|
||||||
|
source src/libiir++/soversion
|
||||||
|
|
||||||
|
libiirpp="obj/${libiirpp_BASE}.so.${SOMAJOR}.${SOMICRO}"
|
||||||
|
libiirpp_DEP_CFLAGS=""
|
||||||
|
libiirpp_DEP_LIBS="${libiir}"
|
||||||
|
SO_EXTRA="${libiirpp_DEP_CFLAGS} ${libiirpp_DEP_LIBS} -lstdc++ -lc \
|
||||||
|
-D_GNU_SOURCE"
|
||||||
|
|
||||||
|
echo "Building library ${libiirpp}..."
|
||||||
|
|
||||||
|
do_cmd source src/libiir++/build.monolithic || return 1
|
||||||
|
|
||||||
|
MODIFIED=0
|
||||||
|
for test in ${MONOLITHIC_TESTS} ${HDR} ${SRC}
|
||||||
|
do
|
||||||
|
if [ ${test} -nt ${libiirpp} ]
|
||||||
|
then
|
||||||
|
MODIFIED=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${MODIFIED} -ne 0 ]
|
||||||
|
then
|
||||||
|
echo " Compiling"
|
||||||
|
|
||||||
|
SONAME="${libiirpp_BASE}.so.${SOMAJOR}"
|
||||||
|
do_cmd ${CXX} ${CFLAGS} -Iobj -shared -fpic -o "${libiirpp}" \
|
||||||
|
-Wl,-soname,${SONAME} \
|
||||||
|
${SRC} ${SO_EXTRA} || return 1
|
||||||
|
|
||||||
|
# make tests work
|
||||||
|
do_cmd ln -sf $(basename ${libiirpp}) obj/${SONAME} || return 1
|
||||||
|
|
||||||
|
print_success "Library built"
|
||||||
|
else
|
||||||
|
print_success "Library up to date"
|
||||||
|
fi
|
||||||
|
|
||||||
|
libiirpp_BUILT=1
|
||||||
|
libiirpp_HEADER=${HDR}
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# vim: syntax=sh:expandtab:ts=4:sw=4
|
|
@ -0,0 +1,21 @@
|
||||||
|
# These are external variables, and shouldn't clash with anything else
|
||||||
|
# libiirpp_MONOLITHIC
|
||||||
|
|
||||||
|
SRC="obj/libiir++.cpp"
|
||||||
|
HDR="obj/iir++.h"
|
||||||
|
|
||||||
|
MONOLITHIC_TESTS="src/libiir++/build.lib src/libiir++/build.monolithic"
|
||||||
|
|
||||||
|
if [ -z "${libiirpp_MONOLITHIC}" ]
|
||||||
|
then
|
||||||
|
MONOLITHIC_SOURCE="$(find src/libiir++/ -name '*.h' | sort)"
|
||||||
|
make_monolithic ${HDR} Ch || return 1
|
||||||
|
|
||||||
|
MONOLITHIC_SOURCE="$(find src/libiir++/ -name '*.cc' | sort)"
|
||||||
|
make_monolithic ${SRC} C || return 1
|
||||||
|
|
||||||
|
libiirpp_MONOLITHIC=1
|
||||||
|
MONOLITHIC_DOC="${MONOLITHIC_DOC} ${HDR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# vim: syntax=sh:expandtab:ts=4:sw=4
|
|
@ -0,0 +1,97 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# libiir/src/libiir++/config-script
|
||||||
|
#
|
||||||
|
# libiir++-config template. Variables are finalised at install time.
|
||||||
|
#
|
||||||
|
dep_cflags="@DEP_CFLAGS@"
|
||||||
|
dep_libs="@DEP_LIBS@"
|
||||||
|
include_dir="@INCLUDE_DIR@"
|
||||||
|
include_dir_set="no"
|
||||||
|
lib_dir="@LIB_DIR@"
|
||||||
|
lib_dir_set="no"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: libiir++-config [options]
|
||||||
|
Options:
|
||||||
|
[--version]
|
||||||
|
[--libs]
|
||||||
|
[--libdir[=DIR]]
|
||||||
|
[--cflags]
|
||||||
|
[--includedir[=DIR]]
|
||||||
|
EOF
|
||||||
|
exit $1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[ $# -eq 0 ] && usage 1 1>&2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
-*=*)
|
||||||
|
optarg="$(echo "$1" | sed 's/[-_a-zA-Z0-9]*=//')"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
optarg=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
--libdir=*)
|
||||||
|
lib_dir="${optarg}"
|
||||||
|
lib_dir_set="yes"
|
||||||
|
;;
|
||||||
|
|
||||||
|
--libdir)
|
||||||
|
echo_lib_dir="yes"
|
||||||
|
;;
|
||||||
|
|
||||||
|
--includedir=*)
|
||||||
|
include_dir="${optarg}"
|
||||||
|
include_dir_set="yes"
|
||||||
|
;;
|
||||||
|
|
||||||
|
--includedir)
|
||||||
|
echo_include_dir="yes"
|
||||||
|
;;
|
||||||
|
|
||||||
|
--version)
|
||||||
|
echo "@VERSION@"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
--cflags)
|
||||||
|
[ "${include_dir}" != "/usr/include" ] && includes="-I${include_dir}"
|
||||||
|
echo_cflags="yes"
|
||||||
|
;;
|
||||||
|
|
||||||
|
--libs)
|
||||||
|
echo_libs="yes"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
usage 1 1>&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[ "${echo_prefix}" == "yes" ] && echo "${prefix}"
|
||||||
|
[ "${echo_exec_prefix}" == "yes" ] && echo "${exec_prefix}"
|
||||||
|
[ "${echo_cflags}" == "yes" ] && echo "${dep_cflags} ${includes}"
|
||||||
|
[ "${echo_libs}" == "yes" ] && echo "${dep_libs} -L${lib_dir} -liir++"
|
||||||
|
true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# kate:
|
|
@ -0,0 +1,15 @@
|
||||||
|
# libiir/src/libiir++/soversion
|
||||||
|
#
|
||||||
|
# Copyright: ©2014, Laurence Withers.
|
||||||
|
# Author: Laurence Withers <l@lwithers.me.uk>
|
||||||
|
# License: GPLv3
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# SOMAJOR is included in the library's soname, and needs to be bumped
|
||||||
|
# after a binary-incompatible release. It is a single integer.
|
||||||
|
SOMAJOR=0
|
||||||
|
|
||||||
|
# SOMICRO is bumped every time there is a binary-compatible release.
|
||||||
|
SOMICRO=0
|
Loading…
Reference in New Issue