Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/FM.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2006 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 "FM.h"
00020 #include "../common_source.h"
00021 
00022 using std::ostringstream;
00023 using namespace Marsyas;
00024 
00025 #define WAVETABLE_SIZE 16384*4
00026 
00027 // create the wavetable.
00028 FM::FM(mrs_string name) :
00029   MarSystem("FM",name),
00030   wavetable_(WAVETABLE_SIZE),
00031   wavetableSize_(WAVETABLE_SIZE)
00032 {
00033   mrs_real incr = TWOPI / wavetableSize_;
00034 
00035   for (mrs_natural t=0; t < wavetableSize_; ++t)
00036   {
00037     wavetable_(t) = (mrs_real)(0.5 * sin(incr * t));
00038   }
00039 
00040   mIndex_ = 0;
00041   oIndex_ = 0;
00042   addControls();
00043 }
00044 
00045 
00046 FM :: ~FM()
00047 {
00048 }
00049 
00050 
00051 MarSystem* FM::clone() const
00052 {
00053   return new FM(*this);
00054 }
00055 
00056 
00057 void FM::addControls()
00058 {
00059   addctrl("mrs_natural/nChannels",1);
00060 
00061   addctrl("mrs_real/mDepth", 15.0);                     // modulator depth
00062   setctrlState("mrs_real/mDepth",true);
00063 
00064   addctrl("mrs_real/mSpeed", 6.0);                      // modulator speed
00065   setctrlState("mrs_real/mSpeed", true);
00066 
00067   addctrl("mrs_real/cFrequency", 1000.0);           // carrier frequency
00068   setctrlState("mrs_real/cFrequency", true);
00069 
00070   addctrl("mrs_bool/noteon", false);
00071   setctrlState("mrs_bool/noteon", true);
00072 }
00073 
00074 void FM::myUpdate(MarControlPtr sender)
00075 {
00076   (void) sender;  //suppress warning of unused parameter(s)
00077   MRSDIAG("FM.cpp - FM:myUpdate");
00078 
00079   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00080   setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations"));
00081   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00082 
00083   // update the controls for the FM
00084   cFrequency_ = getctrl("mrs_real/cFrequency")->to<mrs_real>();
00085   isRate_ = getctrl("mrs_real/israte")->to<mrs_real>();
00086   mSpeed_ = getctrl("mrs_real/mSpeed")->to<mrs_real>();
00087   mDepth_ = getctrl("mrs_real/mDepth")->to<mrs_real>();
00088   mRate_ = (mSpeed_ * wavetableSize_) / getctrl("mrs_real/israte")->to<mrs_real>();
00089   inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00090 }
00091 
00092 void FM::myProcess( realvec& in, realvec& out )
00093 {
00094   (void) in;
00095   mrs_natural t;
00096   //checkFlow(in,out);
00097 
00098 
00099   register mrs_real mSample_;
00100   register mrs_real oFrequency_;
00101 
00102   if (getctrl("mrs_bool/noteon")->to<mrs_bool>() == false) {
00103     return;
00104   }
00105 
00106   for (t=0; t < inSamples_; t++)
00107   {
00108 
00109     // calculate the modulator output
00110     mSample_ = wavetable_((mrs_natural)mIndex_);
00111     mIndex_ += mRate_;
00112     mSample_ *= mDepth_;
00113 
00114     // calculate any FM and the new output rate
00115     oFrequency_ = cFrequency_ + mSample_;
00116     oRate_ = (oFrequency_ * wavetableSize_) / isRate_;
00117 
00118     out(0,t) = wavetable_((mrs_natural)oIndex_);
00119 
00120     // we are one sample behind in case this index goes off the map
00121     oIndex_ += oRate_;
00122 
00123     while (mIndex_ >= wavetableSize_)
00124     {
00125       mIndex_ -= wavetableSize_;
00126     }
00127 
00128     while (oIndex_ >= wavetableSize_)
00129     {
00130       oIndex_ -= wavetableSize_;
00131     }
00132   }
00133 }