Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/SVFilter.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2010 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "SVFilter.h"
00020 #include "../common_source.h"
00021 #include <algorithm>
00022 
00023 using std::min;
00024 using std::max;
00025 using namespace Marsyas;
00026 
00027 
00028 SVFilter::SVFilter(mrs_string name):
00029   MarSystem("SVFilter", name),
00030   type_(0),
00031   res_(0.1),
00032   notch(0.0),
00033   low (0.0),
00034   high(0.0),
00035   band(0.0)
00036 {
00037   addControls();
00038 }
00039 
00040 SVFilter::SVFilter( const SVFilter & other ):
00041   MarSystem(other),
00042   type_(0),
00043   res_(0.1),
00044   notch(0.0),
00045   low (0.0),
00046   high(0.0),
00047   band(0.0)
00048 {}
00049 
00050 SVFilter::~SVFilter()
00051 {
00052 }
00053 
00054 MarSystem*
00055 SVFilter::clone() const
00056 {
00057   return new SVFilter(*this);
00058 }
00059 
00060 void
00061 SVFilter::addControls()
00062 {
00063   addctrl("mrs_real/frequency", 440.0);
00064   addctrl("mrs_real/res", 0.2);
00065   addctrl("mrs_bool/freqin", false);
00066   addctrl("mrs_natural/type", 0);
00067 
00068   setctrlState("mrs_real/frequency", true);
00069   setctrlState("mrs_real/res", true);
00070   setctrlState("mrs_bool/freqin", true);
00071   setctrlState("mrs_natural/type", true);
00072 }
00073 
00074 void
00075 SVFilter::myUpdate(MarControlPtr sender)
00076 {
00077   MRSDIAG("SVFilter.cpp - SVFilter:myUpdate");
00078 
00079   freqIn_ = (getctrl("mrs_bool/freqin")->to<mrs_bool>());
00080   frequency_ = (getctrl("mrs_real/frequency")->to<mrs_real>());
00081   res_ = (getctrl("mrs_real/res")->to<mrs_real>());
00082   israte_ = (getctrl("mrs_real/israte")->to<mrs_real>());
00083 
00084   MarSystem::myUpdate(sender);
00085 }
00086 
00087 void
00088 SVFilter::myProcess(realvec& in, realvec& out)
00089 {
00090   mrs_natural t;
00091     mrs_real fc = frequency_;
00092     mrs_real fs = 44100.0;
00093 
00094     mrs_real drive = 0.02; // keep between 0.0 and 0.1
00095     mrs_real freq = 2.0*sin(PI*min(0.25, fc/(fs*2)));  // the fs*2 is because it's double sampled
00096     mrs_real damp = min(2.0*(1.0 - pow(res_, 0.25)), min(2.0, 2.0/freq - freq*0.5));
00097 
00098   for (t = 0; t < inSamples_; t++)
00099   {
00100         // the fs*2 is because it's double sampled
00101         freq = 2.0*sin(PI*min(0.25, (freqIn_ ? in(1, t)*israte_: fc)/(israte_*2)));
00102         damp = min(2.0*(1.0 - pow(res_, 0.25)), min(2.0, 2.0/freq - freq*0.5));
00103 
00104     notch = in(0, t) - damp*band;
00105     low = low + freq*band;
00106     high = notch - low;
00107     band = freq*high + band - drive*band*band*band;
00108 
00109         switch(type_) {
00110             case 0:
00111                 out(0, t) = 0.5*low; break;
00112             case 1:
00113                 out(0, t) = 0.5*high; break;
00114             case 2:
00115                 out(0, t) = 0.5*band; break;
00116             case 3:
00117                 out(0, t) = 0.5*notch; break;
00118         }
00119 
00120     notch = in(0, t) - damp*band;
00121     low = low + freq*band;
00122     high = notch - low;
00123     band = freq*high + band - drive*band*band*band;
00124 
00125         switch(type_) {
00126             case 0:
00127                 out(0, t) += 0.5*low; break;
00128             case 1:
00129                 out(0, t) += 0.5*high; break;
00130             case 2:
00131                 out(0, t) += 0.5*band; break;
00132             case 3:
00133                 out(0, t) += 0.5*notch; break;
00134         }
00135 
00136   }
00137 }