Marsyas
0.6.0-alpha
|
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 }