A Collection of Useful C++ Classes for Signal Processing
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
It looks like an issue with your <complex> header. I am not sure why that would be causing a problem. Not only does it compile for me under Visual Studio 2008, but I am also cross-compiling it with g++ under MinGW (which is much more strict).
Is anyone else having this problem? Or can anyone shed an insight into what the problem is now?
Is anyone else having this problem? Or can anyone shed an insight into what the problem is now?
-
- Banned
- 12368 posts since 30 Apr, 2002 from i might peeramid
my c++ experience is platform-finite (dsp in an sdk only). i have no experience and little knowledge regarding the conventional distribution of resources.
i'm looking for code for an elliptic/cauer lowpass, bandpass, anything elliptic/cauer, because i think it will give me the phase response i'm looking for. unfortunately, sourceforge suddenly seems to require that i update my browser in order to use it as a resource. i can't tell you how i feel about that
does your package contain code, or is the distribution of the algorithm limited, eg. the classes are contained in a .dll or something?
i'm looking for code for an elliptic/cauer lowpass, bandpass, anything elliptic/cauer, because i think it will give me the phase response i'm looking for. unfortunately, sourceforge suddenly seems to require that i update my browser in order to use it as a resource. i can't tell you how i feel about that
does your package contain code, or is the distribution of the algorithm limited, eg. the classes are contained in a .dll or something?
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
It is a single .h header file containing all the source code.xoxos wrote:does your package contain code, or is the distribution of the algorithm limited, eg. the classes are contained in a .dll or something?
I just finished rewriting the classes, and there are only a couple of filters actually implemented as concrete cascades. But all the response types are there. For elliptic you can make your own class from the building blocks I have provided. For example:
Code: Select all
template<int order, int channels>
struct EllipticBandPass : public EllipticBp<order>, public CascadeFilter<order, channels>
{
EllipticBandPass() : CascadeFilter<order, channels>( this ) { }
void Setup( CalcT centerFreq, CalcT normWidth )
{
Spec spec;
spec.order=order;
spec.centerFreq=centerFreq;
spec.normWidth=normWidth;
spec.sampleRate=1;
EllipticBp<order>::Setup( spec );
}
};
The code is distributed under the MIT License which means UNLIMITED COMMERCIAL USE, i.e. all-you-can-eat at the DSP Buffet.
-
- Banned
- 12368 posts since 30 Apr, 2002 from i might peeramid
i'm looking at the phase response for trumpet bell modeling. not sure if it's an effective technique.
thanks for all the chat on this too, it's jogged my comprehension.
this kitchen has a history of honourable chefs.
thanks for all the chat on this too, it's jogged my comprehension.
this kitchen has a history of honourable chefs.
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
I have released version 0.8.4 of this library. It is located here:
http://sourceforge.net/projects/dspfilterscpp/
The changes:
- Rewrote entire class hierarchy
- Templatized classes have been pushed farther down the derivation hierarchy
- Code for non templatized classes has been moved into a .cpp file.
- Low-pass analog prototypes for Butterworth, Chebyshev, Inverse Chebyshev, and Elliptic responses are each represented by their own class.
- A Butterworth low-shelf analog prototype is also provided. (Can anyone point me to the Chebyshevs and Elliptic shelves?)
- Low pass to low pass, Low pass to high pass, low pass to band pass, and low pass to band stop transformations are each encapsulated and represented by their own class.
- A Layout of poles and zeros is represented by its own class. This allows the computation of the analog prototype to be saved and re-used for speed.
- The set of all possible filter parameters is encapsulated in a single structure and passed to all classes. This allows specifications to be cached and re-used, or compared against for changes.
- Filter order can now be specified at run-time. Storage classes allow specification of a 'maxorder' (i.e. provide sufficient state storage for order from 1 up to maxorder).
- As in the original design, there is no dynamic memory allocation (i.e. calls to new/delete).
- Each concept of IIR filtering is mapped cleanly to one corresponding class in the library.
- Top down programming design allows the entire process of designing and realizing a digital filter to take place in the body of a single function (this allows for any type of optimization at any level).
- Functional programming style, no side effects from function calls and elimination of most state variables.
- A small lightweight class is provided for determining if processor specific optimizations are available (MSVC only)
- Processing template definitions moved to the .cpp file, and the explicit template instantiation model is used, with float and double available (you can add more at the bottom of the source file if needed).
- Some bug fixes to utility functions, and a few trivial utility functions added.
The Elliptic prototype implementation is fairly rough there are hard coded limits on the order, and it consumes a lot of memory (something like 12 kilobytes) even if the order is low. I plan on fixing this. There are also plenty of optimizations that can be performed, like moving constant expressions out of loops, re-using the poles of the analog prototypes, partial recomputation when only a subset of filter parameters change, etc... I will get to that shortly.
For now, everything in there should work. These filters have been tested:
BiquadLowPass
BiquadHighPass
BiquadBandPass1
BiquadBandPass2
BiquadBandStop
BiquadAllPass
BiquadLowShelf
BiquadHighShelf
BiquadPeak
ButterLowPass
ButterHighPass
ButterBandPass
ButterBandStop
ButterLowShelf
ButterHighShelf
ButterPeak
ChebyILowPass
ChebyIHighPass
ChebyIBandPass
ChebyIBandStop
ChebyIILowPass
ChebyIIHighPass
ChebyIIBandPass
ChebyIIBandStop
EllipticLowPass
EllipticHighPass
EllipticBandPass
EllipticBandStop
None of this would have been possible without the insights and help from the members here as well as the contributions upon which portions of the library were built. Thanks!
http://sourceforge.net/projects/dspfilterscpp/
The changes:
- Rewrote entire class hierarchy
- Templatized classes have been pushed farther down the derivation hierarchy
- Code for non templatized classes has been moved into a .cpp file.
- Low-pass analog prototypes for Butterworth, Chebyshev, Inverse Chebyshev, and Elliptic responses are each represented by their own class.
- A Butterworth low-shelf analog prototype is also provided. (Can anyone point me to the Chebyshevs and Elliptic shelves?)
- Low pass to low pass, Low pass to high pass, low pass to band pass, and low pass to band stop transformations are each encapsulated and represented by their own class.
- A Layout of poles and zeros is represented by its own class. This allows the computation of the analog prototype to be saved and re-used for speed.
- The set of all possible filter parameters is encapsulated in a single structure and passed to all classes. This allows specifications to be cached and re-used, or compared against for changes.
- Filter order can now be specified at run-time. Storage classes allow specification of a 'maxorder' (i.e. provide sufficient state storage for order from 1 up to maxorder).
- As in the original design, there is no dynamic memory allocation (i.e. calls to new/delete).
- Each concept of IIR filtering is mapped cleanly to one corresponding class in the library.
- Top down programming design allows the entire process of designing and realizing a digital filter to take place in the body of a single function (this allows for any type of optimization at any level).
- Functional programming style, no side effects from function calls and elimination of most state variables.
- A small lightweight class is provided for determining if processor specific optimizations are available (MSVC only)
- Processing template definitions moved to the .cpp file, and the explicit template instantiation model is used, with float and double available (you can add more at the bottom of the source file if needed).
- Some bug fixes to utility functions, and a few trivial utility functions added.
The Elliptic prototype implementation is fairly rough there are hard coded limits on the order, and it consumes a lot of memory (something like 12 kilobytes) even if the order is low. I plan on fixing this. There are also plenty of optimizations that can be performed, like moving constant expressions out of loops, re-using the poles of the analog prototypes, partial recomputation when only a subset of filter parameters change, etc... I will get to that shortly.
For now, everything in there should work. These filters have been tested:
BiquadLowPass
BiquadHighPass
BiquadBandPass1
BiquadBandPass2
BiquadBandStop
BiquadAllPass
BiquadLowShelf
BiquadHighShelf
BiquadPeak
ButterLowPass
ButterHighPass
ButterBandPass
ButterBandStop
ButterLowShelf
ButterHighShelf
ButterPeak
ChebyILowPass
ChebyIHighPass
ChebyIBandPass
ChebyIBandStop
ChebyIILowPass
ChebyIIHighPass
ChebyIIBandPass
ChebyIIBandStop
EllipticLowPass
EllipticHighPass
EllipticBandPass
EllipticBandStop
None of this would have been possible without the insights and help from the members here as well as the contributions upon which portions of the library were built. Thanks!
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
Just want to note that I am compiling it under MinGw using g++ without errors.
-
- KVRian
- 646 posts since 18 Feb, 2006 from California
Only error in compilation was the definition of Int64. Meeloo's suggestion makes sense, but this is very minor. Other than that it compiled without error in XCode.
I tested a few filters and they seem to work. I hear a lot of crackling when changing frequency on ButterLowPass and ChebyILowPass, but I have to put these filters through the paces more thoroughly before making any more comments.
Nice work, beautiful stuff. I'll be trying to figure out what you've done for a very long time!
Usage question:
Say I want a stereo ButterLowPass with max order 30, but to set the order to 4 and freq to 1k at runtime: Do I understand correctly about the usage if I want to be able to change order at runtime?
Code: Select all
Dsp::ButterLowPass<30,2> butterLowPass;
Dsp::Spec spec;
spec.order=4;
spec.cutoffFreq=1000.f / sampleRate;
spec.sampleRate=1;
butterLowPass.ButterLp::Setup(spec);
butterLowPass.Process(nFrames, interleavedBuffer);
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
Yes that is exactly right. Also note you could use:asomers wrote:Say I want a stereo ButterLowPass with max order 30, but to set the order to 4 and freq to 1k at runtime: Do I understand correctly about the usage if I want to be able to change order at runtime?
Code: Select all
Dsp::ButterLowPass<30,2> butterLowPass; Dsp::Spec spec; spec.order=4; spec.cutoffFreq=1000.f / sampleRate; spec.sampleRate=1; butterLowPass.ButterLp::Setup(spec); butterLowPass.Process(nFrames, interleavedBuffer);
Code: Select all
spec.cutoffFreq=1000.f;
spec.sampleRate=sampleRate;
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
I don't hear crackling when changing the frequency but I do hear zippering, especially when going from high frequency to low frequency in a very short time interval (tested with a ButterLowPass of order 8 ). I'm using Direct Form I. This is a consequence of the realization form and that the history information contains leftover spectral energy from the previous state. I've tried all sorts of tricks to fix it including munging the history array on parameter changes but nothing seems to work. I am hoping that the lattice / ladder form implementation (currently missing, anyone have any links I can read?) will fix it.
Sorry about the obtuse method of using the spec. i.e. having to prefix the call to Setup() with the filter type (i.e. ::ButterLp::Setup()). I will find a way around that.
Keep in mind this is still beta (0.8.4). It is being worked on. The major interfaces won't be changing much though, and the class hierarchy is very near its final form.
Last night I got the Chebyshev I Low shelf prototype mostly working (just having some trouble with the ripple specification). I'll have the Chebyshev type II soon. I have the formulas for elliptic shelf but they are pretty daunting. For fun I will try implementing Bessel type responses completely on my own that should be interesting.
There are some changes I can make to the archticture of representing roots that will allow for very uniform treatment of prototypes and their transformations, this will shrink the code a good bit.
And there are still tons of optimizations left, I am saving that for when I have all the filter types done (still need ChebyIILowShelf, ChebyIIHighShelf, ChebyIIPeaking, EllipticLowShelf, EllipticHighShelf, EllipticPeaking, all Bessel).
Sorry about the obtuse method of using the spec. i.e. having to prefix the call to Setup() with the filter type (i.e. ::ButterLp::Setup()). I will find a way around that.
Keep in mind this is still beta (0.8.4). It is being worked on. The major interfaces won't be changing much though, and the class hierarchy is very near its final form.
Last night I got the Chebyshev I Low shelf prototype mostly working (just having some trouble with the ripple specification). I'll have the Chebyshev type II soon. I have the formulas for elliptic shelf but they are pretty daunting. For fun I will try implementing Bessel type responses completely on my own that should be interesting.
There are some changes I can make to the archticture of representing roots that will allow for very uniform treatment of prototypes and their transformations, this will shrink the code a good bit.
And there are still tons of optimizations left, I am saving that for when I have all the filter types done (still need ChebyIILowShelf, ChebyIIHighShelf, ChebyIIPeaking, EllipticLowShelf, EllipticHighShelf, EllipticPeaking, all Bessel).
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
Updated to 0.8.5
After much study I was able to rewrite the low pass and low shelf analog prototypes to generate poles and zeroes entirely in the s-domain. This was as per Martin's suggestion of allowing positive and negative infinity as representations for the roots. Thanks to this feature, it was possible to completely generalize the construction of digital filters. It works with the following template:
Where Proto is the analog prototype. Currently Butter, ButterShelf, ChebyI, ChebyIShelf, ChebyII, ChebyIIShelf, and Elliptic are defined.
Trans is the transformation, one of LowPass, HighPass, BandPass, or BandStop.
This means that the addition of new filters is as easy as designing the analog prototype in terms of poles and zeroes (allowing infinity and negative infinity as defined values), and then adding a few lines to instantiate templates. For example:
I am happy with this interface so the class hiearchy is unlikley to change from now on. There is some fine-tuning that needs to be done with filter parameter specification. There are still lots of optimizations, so I will continue to work on this.
There is no redudant code or repeated filter formulas anywhere. Each algorithm is neatly encapsulated into a single class and maps directly to IIR concepts. A top down, functional programming model allows the building blocks to be re-assembled in different ways and allowing for full optimizations. And best of all, the library allocates no memory.
New filters added:
ChebyILowShelf
ChebyIHighSelf
ChebyIEq
ChebyIILowShelf
ChebyIIHighSelf
ChebyIIEq
Summary:
After much study I was able to rewrite the low pass and low shelf analog prototypes to generate poles and zeroes entirely in the s-domain. This was as per Martin's suggestion of allowing positive and negative infinity as representations for the roots. Thanks to this feature, it was possible to completely generalize the construction of digital filters. It works with the following template:
Code: Select all
template<class Proto, class Trans, int maxorder, int channels>
struct Filter : ...
Trans is the transformation, one of LowPass, HighPass, BandPass, or BandStop.
This means that the addition of new filters is as easy as designing the analog prototype in terms of poles and zeroes (allowing infinity and negative infinity as defined values), and then adding a few lines to instantiate templates. For example:
Code: Select all
template<int order, int channels>
struct BesselBandStop : Filter<Bessel, BandStop, 2*order, channels>
{ /*...*/ };
There is no redudant code or repeated filter formulas anywhere. Each algorithm is neatly encapsulated into a single class and maps directly to IIR concepts. A top down, functional programming model allows the building blocks to be re-assembled in different ways and allowing for full optimizations. And best of all, the library allocates no memory.
New filters added:
ChebyILowShelf
ChebyIHighSelf
ChebyIEq
ChebyIILowShelf
ChebyIIHighSelf
ChebyIIEq
Summary:
Code: Select all
- Added the ChebyIShelf prototype
- Renamed ButterPeak to ButterEq
- Added ChebyILowShelf, ChebyIHighShelf, ChebyIEq filters
- Added ChebyIILowSHelf, ChebyIIHighShelf, ChebyIIEq
- Fixed a bug with Cascade::Clear() crashing when getting called before stages are initialized
- Rewrote Design() for ChebyII to work entirely in s-plane, compute zeros, and use simplified formula
- Added methods to transforms to operate on an entire Layout
- Removed the hack for skipping the bilinear transform on Chebyshev Type II zeros
- Generalized construction of all Chebyshev Type II filters
- Added some bilbiographical annotations
- Added Root type for representation of positive and negative infinity
- Generalized all transformations with added support for infinite roots
- Generalized construction of all Butterworth filters
- Generalized construction of all Chebyshev Type I filters
- Generalized construction of all Elliptic filters
- Embedded normalization information into the analog prototypes
- Modified transformations to also transform the normalization frequency
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
What is the proper fix for Int64 ?
-
- KVRian
- 646 posts since 18 Feb, 2006 from California
meeloo wrote:Here is what we use for all posix platforms in libnui:thevinn wrote:What is the typename of the 64 bit integer on mac?
CheersCode: Select all
#include <sys/types.h> #include <ctype.h> typedef int8_t int8; typedef int16_t int16; typedef int32_t int32; typedef int64_t int64; typedef u_int8_t uint8; typedef u_int16_t uint16; typedef u_int32_t uint32; typedef u_int64_t uint64;
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
PROJECT HAS BEEN MOVED
Here is the official location:
http://code.google.com/p/dspfilterscpp/
Google has an easier to use interface for uploading files and managing projects so I switched. It is also faster.
I have updated the version to 0.8.6. New in this release is the source code for a Juce test application that exercises all of the available filters. You can see the brick wall, response, phase, and pole/zero plot. Parameters can be adjusted in real time including order, prototype, and kind of filter.
If you want to play right away I made a windows .exe binary available for download. Or you can build it yourself from the sources (however, you will need to get the JUCE amalgamation source and header directly from the official site).
Code for the test app is MIT-licensed, and includes the Layout class I developed for dynamically adjusting the location of child items in a window when the parent resizes.
As always, feedback and/or constructive criticism is greatly appreciated. Thanks to everyone who has been helping me muddle through this!
Here's a screenshot of the test app:
Here is the official location:
http://code.google.com/p/dspfilterscpp/
Google has an easier to use interface for uploading files and managing projects so I switched. It is also faster.
I have updated the version to 0.8.6. New in this release is the source code for a Juce test application that exercises all of the available filters. You can see the brick wall, response, phase, and pole/zero plot. Parameters can be adjusted in real time including order, prototype, and kind of filter.
If you want to play right away I made a windows .exe binary available for download. Or you can build it yourself from the sources (however, you will need to get the JUCE amalgamation source and header directly from the official site).
Code for the test app is MIT-licensed, and includes the Layout class I developed for dynamically adjusting the location of child items in a window when the parent resizes.
As always, feedback and/or constructive criticism is greatly appreciated. Thanks to everyone who has been helping me muddle through this!
Here's a screenshot of the test app:
-
- KVRian
- 995 posts since 25 Apr, 2005
Looking good thevinn, you're on a roll
**Edit - the demo binary isn't working here, I get an error message saying the application is configured incorrectly and may need reinstalling..
**Edit - the demo binary isn't working here, I get an error message saying the application is configured incorrectly and may need reinstalling..
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
UGH, I linked it with "Multithreaded DLL". I will relink it and upload it again...sorry!!!Caco wrote:**Edit - the demo binary isn't working here, I get an error message saying the application is configured incorrectly and may need reinstalling..
Okay I re-uploaded a new one, v.0.8.6.1 please let me know if it works.
Thanks!