Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/PvOverlapadd.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 "PvOverlapadd.h"
00020 
00021 using std::ostringstream;
00022 using namespace Marsyas;
00023 
00024 PvOverlapadd::PvOverlapadd(mrs_string name):MarSystem("PvOverlapadd",name)
00025 {
00026   //type_ = "PvOverlapadd";
00027   //name_ = name;
00028   n_ = 0;
00029 
00030   addControls();
00031 }
00032 
00033 
00034 PvOverlapadd::PvOverlapadd(const PvOverlapadd& a):MarSystem(a)
00035 {
00036   ctrl_rmsIn_ = getctrl("mrs_real/rmsIn");
00037 }
00038 
00039 
00040 PvOverlapadd::~PvOverlapadd()
00041 {
00042 }
00043 
00044 MarSystem*
00045 PvOverlapadd::clone() const
00046 {
00047   return new PvOverlapadd(*this);
00048 }
00049 
00050 
00051 void
00052 PvOverlapadd::addControls()
00053 {
00054   addctrl("mrs_natural/Time",0);
00055   addctrl("mrs_natural/winSize", MRS_DEFAULT_SLICE_NSAMPLES);
00056   setctrlState("mrs_natural/winSize", true);
00057   addctrl("mrs_natural/FFTSize", MRS_DEFAULT_SLICE_NSAMPLES);
00058   addctrl("mrs_natural/Interpolation", MRS_DEFAULT_SLICE_NSAMPLES /4);
00059   addctrl("mrs_natural/Decimation", MRS_DEFAULT_SLICE_NSAMPLES /4);
00060   addctrl("mrs_real/rmsIn", 0.0, ctrl_rmsIn_);
00061 }
00062 
00063 void
00064 PvOverlapadd::myUpdate(MarControlPtr sender)
00065 {
00066   mrs_natural t;
00067   (void) sender;  //suppress warning of unused parameter(s)
00068   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/winSize"));
00069   setctrl("mrs_natural/onObservations", (mrs_natural)1);
00070   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00071 
00072   mrs_natural N,Nw;
00073   N = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00074   Nw = getctrl("mrs_natural/onSamples")->to<mrs_natural>();
00075   I_ = getctrl("mrs_natural/Interpolation")->to<mrs_natural>();
00076   D_ = getctrl("mrs_natural/Decimation")->to<mrs_natural>();
00077 
00078   n_ = - (Nw * I_) / D_;
00079 
00080 
00081   // create synthesis window
00082   swin_.create(Nw);
00083   awin_.create(Nw);
00084   temp_.stretch(N);
00085   tin_.create(N);
00086 
00087   for ( t=0; t < Nw; t++)
00088   {
00089     awin_(t) = (mrs_real)(0.5 * (1  - cos(TWOPI * t/(Nw-1))));
00090     swin_(t) = (mrs_real)(0.5 * (1  - cos(TWOPI * t/(Nw-1))));
00091 
00092   }
00093   /* when Nw > N also apply interpolating (sinc) windows
00094    * to ensure that window are 0 at increments of N (the
00095    * FFT length) aways from the center of the analysis
00096    * window
00097    */
00098   /* if (Nw > N)
00099      {
00100      mrs_real x;
00101      x = (mrs_real)(-(Nw -1) / 2.0);
00102      for (t=0; t < Nw; t++, x += 1.0)
00103      {
00104      if (x != 0.0)
00105      {
00106      awin_(t) *= N * sin (PI * x/N) / (PI *x);
00107      swin_(t) *= I_ * sin (PI * x/I_) / (PI *x);
00108      }
00109      }
00110      }
00111   */
00112 
00113   /* normalize window for unit gain */
00114   mrs_real sum = (mrs_real)0.0;
00115 
00116   for (t =0; t < Nw; t++)
00117   {
00118     sum += awin_(t);
00119   }
00120 
00121   mrs_real afac = (mrs_real)(2.0/ sum);
00122   mrs_real sfac = Nw > N ? (mrs_real)1.0 /afac : (mrs_real)afac;
00123   awin_ *= afac;
00124   swin_ *= sfac;
00125 
00126 
00127   if (Nw <= N)
00128   {
00129     sum = (mrs_real)0.0;
00130 
00131     for (t = 0; t < Nw; t+= I_)
00132     {
00133       sum += swin_(t) * swin_(t);
00134     }
00135     for (sum = (mrs_real)1.0/sum, t =0; t < Nw; t++)
00136       swin_(t) *= sum;
00137   }
00138 }
00139 
00140 
00141 void
00142 PvOverlapadd::myProcess(realvec& in, realvec& out)
00143 {
00144   mrs_natural t;
00145 
00146   // add assertions for sizes
00147   mrs_natural N,Nw;
00148 
00149   N = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00150   Nw = getctrl("mrs_natural/onSamples")->to<mrs_natural>();
00151   n_ += I_;
00152 
00153   mrs_natural n;
00154   n  = n_;
00155 
00156 
00157   while (n < 0)
00158     n += N;
00159   n %= N;
00160 
00161 
00162   for (t=0; t < Nw; t++)
00163   {
00164     tin_(t) = in(0, t);
00165   }
00166 
00167 
00168   // undo circular shift
00169   int half_Nw_ = Nw/2;
00170   mrs_real tmp;
00171   for (t=0; t < half_Nw_; t++)
00172   {
00173     tmp = tin_(t);
00174     tin_(t) = tin_(t+half_Nw_);
00175     tin_(t+half_Nw_) = tmp;
00176   }
00177 
00178   mrs_real rmsOut = 0.0;
00179 
00180   for (t=0; t < Nw; t++)
00181   {
00182     temp_(t) += (tin_(t) * swin_(t));
00183   }
00184 
00185 
00186   for (t=0; t < N; t++)
00187   {
00188     out(0,t) = temp_(t);
00189     rmsOut += out(0,t) * out(0,t);
00190   }
00191 
00192   rmsOut /= Nw;
00193   rmsOut = sqrt(rmsOut);
00194 
00195 
00196 
00197   /* out *= 0.75 * (rmsIn / rmsOut); */
00198 
00199 
00200   for  (t=0; t < N-I_; t++)
00201     temp_(t) = temp_(t+I_);
00202   for (t=N-I_; t<N; t++)
00203     temp_(t) = 0.0;
00204 
00205 
00206 
00207 
00208 }
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222