- Notifications
You must be signed in to change notification settings - Fork145
DSP IIR realtime filter library written in C++
License
berndporr/iir1
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
- High performance
- Realtime sample in - sample out processing
- Butterworth, RBJ, Chebychev filters
- Lowpass, highpass, bandpass and bandstop filters
- Template based header-only filter functions
- Cross platform: Linux, Windows and Mac
An infinite impulse response (IIR) filter library forLinux, Mac OSX and Windowswhich implements Butterworth, RBJ, Chebychev filtersand can easily import coefficients generated by Python (scipy).
The filter processes the data sample by sample for realtimeprocessing.
It uses templates to allocate the required memory so thatit can run without any malloc / new commands.Memory is allocated at compile timeso that there is never the risk of memory leaks.
All realtime filter code is in the header files which guaranteesefficient integration into the main program and the compilercan optimise both filter code and main program at the same time.
Add the following include statement to your code:
#include "Iir.h"
The general coding approach is that first the filter isinstantiated specifying its order, then theparameters are set with the functionsetup
andthen it's ready to be used for sample by sample realtime filtering.
The idea is to allocate the memory of thefilter at compile time with a template argument to avoid any newcommands. This prevents memory leaks and can be optimised at compiletime. Theorder
provided to the template (for example here for alowpass filter):
Iir::Butterworth::LowPass<order> f;
is used as the default order by thesetup
command belowbut can be overridden by a lower order if required.
All filters are available as lowpass, highpass, bandpass and bandstop/notchfilters. Butterworth / Chebyshev offer also low/high/band-shelves withspecified passband gain and 0dB gain in the stopband.
The frequencies can either be analogue ones against the sampling rateor normalised ones between 0..1/2 where 1/2 is the Nyquist frequency. Notethat normalised frequencies are simply f = F/Fs and are in units of 1/samples.Internally the library uses normalised frequencies and the setup commandssimply divide by the sampling rate if given. Choose between:
setup
: sampling rate and the analogue cutoff frequenciessetupN
: normalised frequencies in 1/samples between f = 0..1/2 where 1/2 = Nyquist.
By defaultsetup
uses the order supplied by the template argument butcan be overridden by lower filter orders.
See the header files in\iir
or the documentation for the argumentsof thesetup
commands.
The examples below are for lowpass filters:
- Butterworth --
Butterworth.h
Standard filter suitable for most applications. Monotonic response.
const int order = 4; // 4th order (=2 biquads)Iir::Butterworth::LowPass<order> f;const float samplingrate = 1000; // Hzconst float cutoff_frequency = 5; // Hzf.setup (samplingrate, cutoff_frequency);
or specify a normalised frequency between 0..1/2:
f.setupN(norm_cutoff_frequency);
- Chebyshev Type I --
ChebyshevI.h
With permissible passband ripple in dB.
Iir::ChebyshevI::LowPass<order> f;const float passband_ripple_in_db = 5;f.setup (samplingrate, cutoff_frequency, passband_ripple_in_dB);
or specify a normalised frequency between 0..1/2:
f.setupN(norm_cutoff_frequency,passband_ripple_in_dB);
- Chebyshev Type II --
ChebyshevII.h
With worst permissible stopband rejection in dB.
Iir::ChebyshevII::LowPass<order> f;double stopband_ripple_in_dB = 20;f.setup (samplingrate, cutoff_frequency, stopband_ripple_in_dB);
or specify a normalised frequency between 0..1/2:
f.setupN(norm_cutoff_frequency,stopband_ripple_in_dB);
- RBJ --
RBJ.h
2nd order filters with cutoff and Q factor.
Iir::RBJ::LowPass f;const float cutoff_frequency = 100;const float Q_factor = 5;f.setup (samplingrate, cutoff_frequency, Q_factor);
or specify a normalised frequency between 0..1/2:
f.setupN(norm_cutoff_frequency, Q_factor);
- Designing filters with Python's scipy.signal --
Custom.h
######### Python# See "elliptic_design.py" for the complete code.from scipy import signalorder = 4sos = signal.ellip(order, 5, 40, 0.2, 'low', output='sos')print(sos) # copy/paste the coefficients over & replace [] with {}///////// C++// part of "iirdemo.cpp"const double coeff[][6] = {{1.665623674062209972e-02, -3.924801366970616552e-03, 1.665623674062210319e-02, 1.000000000000000000e+00, -1.715403014004022175e+00, 8.100474793174089472e-01},{1.000000000000000000e+00, -1.369778997100624895e+00, 1.000000000000000222e+00, 1.000000000000000000e+00, -1.605878925999785656e+00, 9.538657786383895054e-01}};const int nSOS = sizeof(coeff) / sizeof(coeff[0]); // here: nSOS = 2 = order / 2Iir::Custom::SOSCascade<nSOS> cust(coeff);
Samples are processed one by one. In the example belowa samplex
is processed with thefilter
command and then saved iny
. The types ofx
andy
can either befloat or double(integer is also allowed but is still processed internally as floating point):
y = f.filter(x);
This is then repeated for every incoming sample in aloop or event handler.
Invalid values provided tosetup()
will throwan exception. Parameters provided tosetup()
whichresult in coefficients being NAN will alsothrow an exception.
You can switch off exeption handling by definingIIR1_NO_EXCEPTIONS
via cmake or in your program.
If you use cmake as your build system then just addto yourCMakeLists.txt
the following lines for the dynamic library:
find_package(iir)target_link_libraries(... iir::iir)
or for the static one:
find_package(iir)target_link_libraries(... iir::iir_static)
Link it against the dynamic library(Unix/Mac:-liir
, Windows:iir.lib
)or the static library (Unix/Mac:libiir_static.a
,Windows:libiir_static.lib
).
If you are using Ubuntu LTS then you caninstall this library as a pre-compiled package.
Add this repository to your system:
sudo add-apt-repository ppa:berndporr/dsp
Then install the packages:
- Library files:
sudo apt install iir1
- Development files:
sudo apt install iir1-dev
It's available for 64 bit Intel and 32,64 bit ARM (Raspberry PI etc).The documentation of the development package and the example programs are in:
/usr/share/doc/iir1-dev/
The build tool iscmake
which generates the make- or projectfiles for the different platforms.cmake
is available forLinux, Windows and Mac. It also compiles directly on aRaspberry PI.
Run
cmake .
which generates the Makefile. Then run:
makesudo make install
which installs it under/usr/local/lib
and/usr/local/include
.
Both gcc and clang have been tested.
cmake -G "Visual Studio 16 2019" -A x64 .
Seecmake
for the different build-options. Above is for a 64 bit build.Then start Visual C++ and open the solution. This will createthe DLL and the LIB files. Under Windows it's highly recommendedto use the static library and link it into the application program.
Run unit tests by typingmake test
or justctest
.These test if after a delta pulse all filters relax to zero,that their outputs never become NaN and if the Direct Form I&II filters calculateexpected sequences by comparing them from results createdby the output of scipy'ssosfilt
.
You can disable the generation of tests by settingIIR1_BUILD_TESTING
to off.
The easiest way to learn is from the examples which are in thedemo
directory. A delta pulse as a test signal is sent into the differentfilters and saved in a file. With the Python scriptplot_impulse_fresponse.py
you can then plot the frequency responses.
You can disable the compilation of the demos by settingIIR1_BUILD_DEMO
to off.
Also the directory containing the unit tests provides examples forevery filter type.
A PDF of all classes, methods and in particularsetup
functionsis in thedocs/pdf
directory.
The online documentation is here:http://berndporr.github.io/iir1
These responses have been generated byiirdemo.cpp
in the/demo/
directory and then plotted withplot_impulse_fresponse.py
.
This library has been further developed from Vinnie Falco'sgreat original work which can be found here:
https://github.com/vinniefalco/DSPFilters
While the original library processes audio arrays thislibrary has been adapted to do fast realtime processing sampleby sample. Thesetup
command won't require the filter order and instead remembersit from the template argument. The class structure hasbeen simplified and all functions documented for doxygen.Instead of having assert() statements this libary throwsexceptions in case a parameter is wrong. Any filter designrequiring optimisation (for example Ellipic filters) hasbeen removed and instead a function has been added which can import easilycoefficients from scipy.
Bernd Porr --http://www.berndporr.me.uk
About
DSP IIR realtime filter library written in C++