Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/PvOscBank.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 "PvOscBank.h"
00020 
00021 using std::ostringstream;
00022 using namespace Marsyas;
00023 
00024 PvOscBank::PvOscBank(mrs_string name):MarSystem("PvOscBank",name)
00025 {
00026   //type_ = "PvOscBank";
00027   //name_ = name;
00028 
00029   psize_ = 0;
00030   size_ = 0;
00031   PS_ = 0;
00032 
00033   addControls();
00034 }
00035 
00036 
00037 PvOscBank::PvOscBank(const PvOscBank& a):MarSystem(a)
00038 {
00039   ctrl_analysisphases_ = getctrl("mrs_realvec/analysisphases");
00040   ctrl_frequencies_ = getctrl("mrs_realvec/frequencies");
00041   ctrl_regions_ = getctrl("mrs_realvec/regions");
00042   ctrl_peaks_ = getctrl("mrs_realvec/peaks");
00043 
00044   ctrl_phaselock_ = getctrl("mrs_bool/phaselock");
00045   ctrl_onsetsAudible_ = getctrl("mrs_bool/onsetsAudible");
00046   ctrl_rmsIn_ = getctrl("mrs_real/rmsIn");
00047 
00048   psize_ = 0;
00049   PS_ = 0;
00050 }
00051 
00052 
00053 PvOscBank::~PvOscBank()
00054 {
00055 }
00056 
00057 MarSystem*
00058 PvOscBank::clone() const
00059 {
00060   return new PvOscBank(*this);
00061 }
00062 
00063 void
00064 PvOscBank::addControls()
00065 {
00066   addctrl("mrs_natural/Interpolation", MRS_DEFAULT_SLICE_NSAMPLES/4);
00067   setctrlState("mrs_natural/Interpolation", true);
00068   addctrl("mrs_real/PitchShift", 1.0);
00069   setctrlState("mrs_real/PitchShift", true);
00070   addctrl("mrs_real/SynthesisThreshold", 0.0);
00071   setctrlState("mrs_real/SynthesisThreshold", true);
00072   addctrl("mrs_natural/winSize", MRS_DEFAULT_SLICE_NSAMPLES);
00073   setctrlState("mrs_natural/winSize", true);
00074 
00075 
00076   addctrl("mrs_realvec/analysisphases", realvec(), ctrl_analysisphases_);
00077   addctrl("mrs_realvec/frequencies", realvec(), ctrl_frequencies_);
00078   addctrl("mrs_realvec/regions", realvec(), ctrl_regions_);
00079   addctrl("mrs_realvec/peaks", realvec(), ctrl_peaks_);
00080   addctrl("mrs_bool/phaselock", false, ctrl_phaselock_);
00081   addctrl("mrs_bool/onsetsAudible", true, ctrl_onsetsAudible_);
00082   addctrl("mrs_real/rmsIn", 0.0, ctrl_rmsIn_);
00083 }
00084 
00085 void
00086 PvOscBank::myUpdate(MarControlPtr sender)
00087 {
00088   mrs_natural t;
00089   (void) sender;  //suppress warning of unused parameter(s)
00090   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/winSize"));
00091   setctrl("mrs_natural/onObservations", (mrs_natural)1);
00092   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00093 
00094   inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>();
00095   inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00096 
00097   size_ = inObservations_/2;
00098   temp_.create(getctrl("mrs_natural/winSize")->to<mrs_natural>());
00099 
00100 
00101 
00102   if (size_ != psize_)
00103   {
00104     {
00105       MarControlAccessor acc(ctrl_analysisphases_);
00106       mrs_realvec& analysisphases = acc.to<mrs_realvec>();
00107       analysisphases.create(size_);
00108     }
00109 
00110     {
00111       MarControlAccessor acc(ctrl_frequencies_);
00112       mrs_realvec& frequencies = acc.to<mrs_realvec>();
00113       frequencies.create(size_);
00114     }
00115 
00116     {
00117       MarControlAccessor acc(ctrl_regions_);
00118       mrs_realvec& regions = acc.to<mrs_realvec>();
00119       regions.create(size_);
00120     }
00121 
00122     {
00123       MarControlAccessor acc(ctrl_peaks_);
00124       mrs_realvec& peaks = acc.to<mrs_realvec>();
00125       peaks.create(size_);
00126     }
00127 
00128 
00129 
00130 
00131     lastamp_.stretch(size_);
00132     magnitudes_.stretch(size_);
00133 
00134 
00135 
00136     lastfreq_.stretch(size_);
00137     index_.stretch(size_);
00138     N_ = size_;
00139     L_ = 8192;
00140     table_.stretch(L_+2);           // leave some head-room for numerical errors
00141 
00142     for (t=0; t < L_; t++)
00143     {
00144       table_(t) = N_ * cos(TWOPI * t/L_);
00145     }
00146   }
00147 
00148   psize_ = size_;
00149 
00150 
00151   P_ = getctrl("mrs_real/PitchShift")->to<mrs_real>();
00152   I_ = getctrl("mrs_natural/Interpolation")->to<mrs_natural>();
00153   S_ = getctrl("mrs_real/SynthesisThreshold")->to<mrs_real>();
00154   R_ = getctrl("mrs_real/osrate")->to<mrs_real>();
00155 }
00156 
00157 
00158 
00159 int
00160 PvOscBank::subband(int bin)
00161 {
00162   int si = 0;
00163 
00164   if (bin  < 16)
00165     si = 0;
00166   else if ((bin >= 16) && (bin < 32))
00167     si = 1;
00168   else if (bin < 512)
00169     si = (int)(log(bin*1.0) / log(2.0))-3;
00170   else if (bin > 512)
00171     si = 6;
00172   return si;
00173 }
00174 
00175 
00176 bool
00177 PvOscBank::isPeak(int bin, mrs_realvec& magnitudes, mrs_real maxAmp)
00178 {
00179   bool res = true;
00180 
00181   int h = subband(bin);
00182   h = 2;
00183   if ((bin > 2) && (bin <= size_-2))
00184     for (int i = bin-h; i < bin+h; ++i)
00185     {
00186       if (magnitudes(bin) < magnitudes(i))
00187         res = false;
00188     }
00189   if (magnitudes(bin) < 0.005 * maxAmp)
00190     res = false;
00191   if (bin == 0)
00192     res = true;
00193   return res;
00194 }
00195 
00196 
00197 void
00198 PvOscBank::myProcess(realvec& in, realvec& out)
00199 {
00200 
00201 
00202   mrs_natural c,t;
00203   MarControlAccessor acc(ctrl_frequencies_);
00204   mrs_realvec& frequencies = acc.to<mrs_realvec>();
00205 
00206   MarControlAccessor  acc1(ctrl_analysisphases_);
00207   mrs_realvec& analysisphases = acc1.to<mrs_realvec>();
00208 
00209 
00210   MarControlAccessor  acc2(ctrl_regions_);
00211   mrs_realvec& regions = acc2.to<mrs_realvec>();
00212 
00213 
00214   MarControlAccessor  acc3(ctrl_peaks_);
00215   mrs_realvec& peaks = acc3.to<mrs_realvec>();
00216 
00217   if (PS_ > 1.0)
00218     NP_ = (mrs_natural)(N_/PS_);
00219   else
00220     NP_ = N_;
00221 
00222 
00223 
00224   peaks.setval(0.0);
00225 
00226 
00227   for (t=0; t < NP_; t++)
00228   {
00229     frequencies(t) =  in(2*t+1,0);
00230   }
00231   PS_ = P_;
00232   Iinv_ = (mrs_real)(1.0 / I_);
00233   Pinc_ = PS_ * L_ / TWOPI;
00234   Nw_ = getctrl("mrs_natural/winSize")->to<mrs_natural>();
00235   mrs_real maxAmp =0.0;
00236 
00237   for (t=0; t < NP_; t++)
00238   {
00239     magnitudes_(t) =  in(2*t,0);
00240     if (magnitudes_(t) > maxAmp)
00241       maxAmp = magnitudes_(t);
00242     if (t==0)
00243       magnitudes_(t) = 0.0;
00244     if (t==size_)
00245       magnitudes_(t) = 0.0;
00246 
00247 
00248     while (analysisphases(t) > PI)
00249       analysisphases(t) -= TWOPI;
00250     while (analysisphases(t) < -PI)
00251       analysisphases(t) += TWOPI;
00252 
00253   }
00254 
00255   for (int i=0; i < size_; ++i)
00256   {
00257     regions(i) = i;
00258   }
00259 
00260 
00261 
00262   // calculate regions of influence
00263   int previous_peak=0;
00264   int peak = 0;
00265   for (t=0; t < NP_; t++)
00266   {
00267     if (isPeak(t, magnitudes_, maxAmp))
00268     {
00269 
00270       // calculate significant peaks and corresponding
00271       // non-overlapping intervals
00272       peak = t;
00273 
00274       if (peak-previous_peak == 1)
00275         regions(peak) = peak;
00276       else
00277       {
00278         for (int j=previous_peak; j< previous_peak + (int)((peak-previous_peak)/2.0); j++)
00279         {
00280           regions(j) = previous_peak;
00281         }
00282 
00283         for (int j= previous_peak + (int)((peak-previous_peak)/2.0); j < peak; j++)
00284         {
00285           regions(j) = peak;
00286         }
00287       }
00288       previous_peak = peak;
00289     }
00290 
00291   }
00292 
00293 
00294 
00295   mrs_real factor = 1;
00296   for (t=0; t < NP_; t++)
00297   {
00298 
00299     while (analysisphases(t) > PI)
00300       analysisphases(t) -= TWOPI;
00301     while (analysisphases(t) < -PI)
00302       analysisphases(t) += TWOPI;
00303 
00304     // if (ctrl_phaselock_->to<bool>() == true)
00305     // {
00306     // if (t == 0)
00307     // cout << "PHASELOCKED" << endl;
00308 
00309     // index_(t) = analysisphases(t);
00310     // factor = 2.25;
00311     // factor = 1.5;
00312     // }
00313   }
00314 
00315   factor = 1.5;
00316 
00317   for (t=0; t < NP_; t++)
00318   {
00319     frequencies(t) *= Pinc_;
00320 
00321     f_ = lastfreq_(t);
00322     finc_ = (frequencies(t) - f_) * Iinv_;
00323 
00324     //if ((magnitudes_(t) < 1.0e-06)||(magnitudes_(t) < 0.01 * maxAmp))
00325     if (magnitudes_(t) < 1.0e-07)
00326     {
00327       magnitudes_(t) = 0.0;
00328       a_ = lastamp_(t);
00329       ainc_ = (magnitudes_(t) - a_)*Iinv_;
00330     }
00331     else
00332     {
00333       a_ = lastamp_(t);
00334       ainc_ = (magnitudes_(t) - a_)*Iinv_;
00335     }
00336 
00337     if (t == regions(t))
00338     {
00339       address_ = index_((mrs_natural)regions(t));
00340     }
00341     else
00342     {
00343       address_ = index_(t);
00344     }
00345 
00346 
00347     while (address_ >= L_)
00348       address_ -= L_;
00349     while (address_ < 0)
00350       address_ += L_;
00351 
00352 
00353 
00354     if (ainc_ != 0.0 || a_ != 0.0)
00355     {
00356       peaks(t) = magnitudes_(t);
00357 
00358       // accumulate I samples from each oscillator
00359       // into output slice
00360       for (c=0; c < I_; ++c)
00361       {
00362         naddress_ = (mrs_natural)address_;
00363         temp_(c) += a_  * factor * table_(naddress_);
00364         address_ += f_;
00365 
00366         while (address_ >= L_)
00367           address_ -= L_;
00368         while (address_ < 0)
00369           address_ += L_;
00370 
00371         a_ += ainc_;
00372         f_ += finc_;
00373       }
00374 
00375     }
00376 
00377     index_(t) = address_;
00378     lastamp_(t) = magnitudes_(t);
00379     lastfreq_(t) = frequencies(t);
00380 
00381   }
00382 
00383   ctrl_phaselock_->setValue(false);
00384 
00385 
00386 
00387   for (t=0; t < Nw_; t++)
00388     out(0,t) = temp_(t);
00389   for  (t=0; t < Nw_-I_; t++)
00390     temp_(t) = temp_(t+I_);
00391   for (t=Nw_-I_; t<Nw_; t++)
00392     temp_(t) = 0.0;
00393 
00394 
00395 
00396 
00397 }