Marsyas  0.5.0-beta1
/Users/jleben/code/marsyas/src/marsyas/marsystems/PeakSynthOscBank.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 "PeakSynthOscBank.h"
00020 #include <marsyas/peakView.h>
00021 
00022 
00023 using std::ostringstream;
00024 using std::cout;
00025 using std::endl;
00026 
00027 using namespace Marsyas;
00028 
00029 PeakSynthOscBank::PeakSynthOscBank(mrs_string name):MarSystem("PeakSynthOscBank",name)
00030 {
00031   psize_ = 0;
00032   size_ = 0;
00033 
00034   addControls();
00035 }
00036 
00037 PeakSynthOscBank::PeakSynthOscBank(const PeakSynthOscBank& a):MarSystem(a)
00038 {
00039   ctrl_harmonize_ = getctrl("mrs_realvec/harmonize");
00040 }
00041 
00042 PeakSynthOscBank::~PeakSynthOscBank()
00043 {
00044 }
00045 
00046 MarSystem*
00047 PeakSynthOscBank::clone() const
00048 {
00049   return new PeakSynthOscBank(*this);
00050 }
00051 
00052 void
00053 PeakSynthOscBank::addControls()
00054 {
00055   addctrl("mrs_natural/Interpolation", MRS_DEFAULT_SLICE_NSAMPLES/4);
00056   setctrlState("mrs_natural/Interpolation", true);
00057   addctrl("mrs_real/PitchShift", 1.0);
00058   setctrlState("mrs_real/PitchShift", true);
00059   addctrl("mrs_real/SynthesisThreshold", 0.0);
00060   setctrlState("mrs_real/SynthesisThreshold", true);
00061   addctrl("mrs_realvec/harmonize", realvec(), ctrl_harmonize_);
00062   setctrlState("mrs_realvec/harmonize", true);
00063 }
00064 
00065 void
00066 PeakSynthOscBank::myUpdate(MarControlPtr sender)
00067 {
00068   (void) sender;  //suppress warning of unused parameter(s)
00069   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/Interpolation"));
00070   setctrl("mrs_natural/onObservations", (mrs_natural)1);
00071   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00072 
00073   inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00074 
00075   nbH_ = (ctrl_harmonize_->to<mrs_realvec>().getSize()-1)/2;
00076   // replace this !!
00077   if (!nbH_)
00078   {
00079     MarControlAccessor acc(ctrl_harmonize_, NOUPDATE);
00080     realvec& harmonize = acc.to<mrs_realvec>();
00081     harmonize.stretch(3);
00082     harmonize(1) = 1.0;
00083     harmonize(2) = 1.0;
00084   }
00085 
00086   size_ = 2048*nbH_;
00087 
00088   //if (size_ != psize_)
00089   {
00090     lastamp_.stretch(size_);
00091     nextamp_.stretch(size_);
00092     lastfreq_.stretch(size_);
00093     nextfreq_.stretch(size_);
00094     index_.stretch(size_);
00095     nextindex_.stretch(size_);
00096     N_ = inObservations_/peakView::nbPkParameters;
00097 
00098     L_ = 8192;
00099     table_.stretch(L_);
00100 
00101     for (mrs_natural t=0; t < L_; t++)
00102     {
00103       table_(t) =  cos(TWOPI * t/L_);
00104     }
00105     psize_ = size_;
00106   }
00107   // N_ = inObservations_/nbPkParameters;
00108   P_ = getctrl("mrs_real/PitchShift")->to<mrs_real>();
00109   I_ = getctrl("mrs_natural/Interpolation")->to<mrs_natural>();
00110   S_ = getctrl("mrs_real/SynthesisThreshold")->to<mrs_real>();
00111   R_ = getctrl("mrs_real/osrate")->to<mrs_real>();
00112 }
00113 
00114 void
00115 PeakSynthOscBank::myProcess(realvec& in, realvec& out)
00116 {
00117   mrs_natural t,c;
00118   out.setval(0.0);
00119 
00120   if (P_ > 1.0)
00121     NP_ = (mrs_natural)(N_/P_);
00122   else
00123     NP_ = N_;
00124 
00125   Iinv_ = (mrs_real)(1.0 / I_);
00126   Pinc_ = P_ * L_ / R_;
00127 
00128   nextamp_.setval(0);
00129   nextfreq_.setval(0);
00130   nextindex_.setval(0);
00131 
00132   // FIXME This line defines a (possibly) unused variable
00133   // bool flag = false;
00134 
00135   if(nbH_)
00136   {
00137     for(mrs_natural j=0 ; j<nbH_ ; j++)
00138     {
00139       mrs_real mulF = ctrl_harmonize_->to<mrs_realvec>()(1+j*2);
00140       mrs_real mulA = ctrl_harmonize_->to<mrs_realvec>()(2+j*2);
00141 
00142       for (t=0; t < NP_; t++)
00143       {
00144         mrs_natural index = (mrs_natural) ceil(in(t)/R_*2048*2+0.5);
00145         if (in(t) == 0.0 || index >= 2048)
00146           break;
00147         index+=j*2048;
00148 
00149         /* save current values for next iteration */
00150 
00151         if(nextfreq_(index))
00152         {
00153           cout << "PROBLEM"<<endl;
00154         }
00155         nextamp_(index) = in(t+NP_)*mulA;
00156         nextfreq_(index) = in(t)*Pinc_*mulF;
00157       }
00158     }
00159   }
00160 
00161   for (mrs_natural t=0; t < nextamp_.getSize(); t++)
00162   {
00163     // cout << endl << index << endl;
00164     if(lastfreq_(t) && nextfreq_(t))
00165     {
00166       f_ = lastfreq_(t);
00167       finc_ = (nextfreq_(t) - f_)*Iinv_;
00168     }
00169     else if(nextfreq_(t))
00170     {
00171       f_ = nextfreq_(t);
00172       finc_=0;
00173     }
00174     else
00175     {
00176       f_ = lastfreq_(t);
00177       finc_=0;
00178     }
00179 
00180     a_ = lastamp_(t);
00181     ainc_ = (nextamp_(t) - a_)*Iinv_;
00182 
00183     address_ = index_(t);
00184 
00185     /* avoid extra computing */
00186     if ((a_ != 0.0 || ainc_!=0.0))
00187     {
00188       // accumulate I samples from each oscillator
00189       // into output slice
00190       for (c=0; c < I_; ++c)
00191       {
00192         naddress_ = (mrs_natural)address_ % L_;
00193         out(0, c) += a_ * table_(naddress_);
00194         address_ += f_;
00195 
00196         while (address_ >= L_)
00197           address_ -= L_;
00198         while (address_ < 0)
00199           address_ += L_;
00200 
00201         a_ += ainc_;
00202         f_ += finc_;
00203       }
00204       // move down one parenthesis
00205     }
00206     nextindex_(t) = address_;
00207   }
00208 
00209   lastamp_ = nextamp_;
00210   lastfreq_ = nextfreq_;
00211   index_ = nextindex_;
00212 }