summaryrefslogtreecommitdiff
path: root/nyqstk/src/Filter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'nyqstk/src/Filter.cpp')
-rw-r--r--nyqstk/src/Filter.cpp236
1 files changed, 236 insertions, 0 deletions
diff --git a/nyqstk/src/Filter.cpp b/nyqstk/src/Filter.cpp
new file mode 100644
index 0000000..59cabbe
--- /dev/null
+++ b/nyqstk/src/Filter.cpp
@@ -0,0 +1,236 @@
+/***************************************************/
+/*! \class Filter
+ \brief STK filter class.
+
+ This class implements a generic structure that
+ can be used to create a wide range of filters.
+ It can function independently or be subclassed
+ to provide more specific controls based on a
+ particular filter type.
+
+ In particular, this class implements the standard
+ difference equation:
+
+ a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] -
+ a[1]*y[n-1] - ... - a[na]*y[n-na]
+
+ If a[0] is not equal to 1, the filter coefficients
+ are normalized by a[0].
+
+ The \e gain parameter is applied at the filter
+ input and does not affect the coefficient values.
+ The default gain value is 1.0. This structure
+ results in one extra multiply per computed sample,
+ but allows easy control of the overall filter gain.
+
+ by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
+*/
+/***************************************************/
+
+#include "Filter.h"
+#include <stdio.h>
+
+using namespace Nyq;
+
+Filter :: Filter()
+{
+ // The default constructor should setup for pass-through.
+ gain_ = 1.0;
+ b_.push_back( 1.0 );
+ a_.push_back( 1.0 );
+
+ inputs_.push_back( 0.0 );
+ outputs_.push_back( 0.0 );
+}
+
+Filter :: Filter( std::vector<StkFloat> &bCoefficients, std::vector<StkFloat> &aCoefficients )
+{
+ // Check the arguments.
+ if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
+ errorString_ << "Filter: a and b coefficient vectors must both have size > 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( aCoefficients[0] == 0.0 ) {
+ errorString_ << "Filter: a[0] coefficient cannot == 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ gain_ = 1.0;
+ b_ = bCoefficients;
+ a_ = aCoefficients;
+
+ inputs_ = std::vector<StkFloat> ( b_.size() );
+ outputs_ = std::vector<StkFloat> ( a_.size() );
+ this->clear();
+}
+
+Filter :: ~Filter()
+{
+}
+
+void Filter :: clear(void)
+{
+ unsigned int i;
+ for (i=0; i<inputs_.size(); i++)
+ inputs_[i] = 0.0;
+ for (i=0; i<outputs_.size(); i++)
+ outputs_[i] = 0.0;
+}
+
+void Filter :: setCoefficients( std::vector<StkFloat> &bCoefficients, std::vector<StkFloat> &aCoefficients, bool clearState )
+{
+ // Check the arguments.
+ if ( bCoefficients.size() == 0 || aCoefficients.size() == 0 ) {
+ errorString_ << "Filter::setCoefficients: a and b coefficient vectors must both have size > 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( aCoefficients[0] == 0.0 ) {
+ errorString_ << "Filter::setCoefficients: a[0] coefficient cannot == 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( b_.size() != bCoefficients.size() ) {
+ b_ = bCoefficients;
+ inputs_.clear();
+ inputs_ = std::vector<StkFloat> ( b_.size() );
+ }
+ else {
+ for ( unsigned int i=0; i<b_.size(); i++ ) b_[i] = bCoefficients[i];
+ }
+
+ if ( a_.size() != aCoefficients.size() ) {
+ a_ = aCoefficients;
+ outputs_.clear();
+ outputs_ = std::vector<StkFloat> ( a_.size() );
+ }
+ else {
+ for ( unsigned int i=0; i<a_.size(); i++ ) a_[i] = aCoefficients[i];
+ }
+
+ if ( clearState ) this->clear();
+
+ // Scale coefficients by a[0] if necessary
+ if ( a_[0] != 1.0 ) {
+ unsigned int i;
+ for ( i=0; i<b_.size(); i++ ) b_[i] /= a_[0];
+ for ( i=1; i<a_.size(); i++ ) a_[i] /= a_[0];
+ }
+}
+
+void Filter :: setNumerator( std::vector<StkFloat> &bCoefficients, bool clearState )
+{
+ // Check the argument.
+ if ( bCoefficients.size() == 0 ) {
+ errorString_ << "Filter::setNumerator: coefficient vector must have size > 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( b_.size() != bCoefficients.size() ) {
+ b_ = bCoefficients;
+ inputs_.clear();
+ inputs_ = std::vector<StkFloat> ( b_.size() );
+ }
+ else {
+ for ( unsigned int i=0; i<b_.size(); i++ ) b_[i] = bCoefficients[i];
+ }
+
+ if ( clearState ) this->clear();
+}
+
+void Filter :: setDenominator( std::vector<StkFloat> &aCoefficients, bool clearState )
+{
+ // Check the argument.
+ if ( aCoefficients.size() == 0 ) {
+ errorString_ << "Filter::setDenominator: coefficient vector must have size > 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( aCoefficients[0] == 0.0 ) {
+ errorString_ << "Filter::setDenominator: a[0] coefficient cannot == 0!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( a_.size() != aCoefficients.size() ) {
+ a_ = aCoefficients;
+ outputs_.clear();
+ outputs_ = std::vector<StkFloat> ( a_.size() );
+ }
+ else {
+ for ( unsigned int i=0; i<a_.size(); i++ ) a_[i] = aCoefficients[i];
+ }
+
+ if ( clearState ) this->clear();
+
+ // Scale coefficients by a[0] if necessary
+ if ( a_[0] != 1.0 ) {
+ unsigned int i;
+ for ( i=0; i<b_.size(); i++ ) b_[i] /= a_[0];
+ for ( i=1; i<a_.size(); i++ ) a_[i] /= a_[0];
+ }
+}
+
+void Filter :: setGain(StkFloat gain)
+{
+ gain_ = gain;
+}
+
+StkFloat Filter :: getGain(void) const
+{
+ return gain_;
+}
+
+StkFloat Filter :: lastOut(void) const
+{
+ return outputs_[0];
+}
+
+StkFloat Filter :: tick( StkFloat input )
+{
+ unsigned int i;
+
+ outputs_[0] = 0.0;
+ inputs_[0] = gain_ * input;
+ for (i=b_.size()-1; i>0; i--) {
+ outputs_[0] += b_[i] * inputs_[i];
+ inputs_[i] = inputs_[i-1];
+ }
+ outputs_[0] += b_[0] * inputs_[0];
+
+ for (i=a_.size()-1; i>0; i--) {
+ outputs_[0] += -a_[i] * outputs_[i];
+ outputs_[i] = outputs_[i-1];
+ }
+
+ return outputs_[0];
+}
+
+
+StkFrames& Filter :: tick( StkFrames& frames, unsigned int channel )
+{
+ if ( channel >= frames.channels() ) {
+ errorString_ << "Filter::tick(): channel and StkFrames arguments are incompatible!";
+ handleError( StkError::FUNCTION_ARGUMENT );
+ }
+
+ if ( frames.channels() == 1 ) {
+ for ( unsigned int i=0; i<frames.frames(); i++ )
+ frames[i] = tick( frames[i] );
+ }
+ else if ( frames.interleaved() ) {
+ unsigned int hop = frames.channels();
+ unsigned int index = channel;
+ for ( unsigned int i=0; i<frames.frames(); i++ ) {
+ frames[index] = tick( frames[index] );
+ index += hop;
+ }
+ }
+ else {
+ unsigned int iStart = channel * frames.frames();
+ for ( unsigned int i=0; i<frames.frames(); i++, iStart++ )
+ frames[iStart] = tick( frames[iStart] );
+ }
+
+ return frames;
+}