Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/Delay.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 "../common_source.h"
00020 #include "Delay.h"
00021 
00022 using std::ostringstream;
00023 using std::vector;
00024 
00025 using namespace Marsyas;
00026 
00027 //#define MTLB_DBG_LOG
00028 
00029 static inline mrs_natural   wrapCursor (mrs_natural unwrappedCursor, mrs_natural cursorMask)
00030 {
00031   // add delay line length to have a sort-of dealing with negative indices as well; should be a while loop really
00032   return (unwrappedCursor + (cursorMask+1)) & cursorMask;
00033 }
00034 
00035 static inline mrs_real  getValue (mrs_natural obs, mrs_real index, mrs_realvec& buffer, mrs_natural cursorMask)
00036 {
00037   mrs_natural integer = (mrs_natural)index + ((index < 0)? -1 : 0);
00038   mrs_real  frac    = index - integer;
00039   mrs_real  retVal  = buffer(obs, wrapCursor (integer, cursorMask));
00040 
00041   return retVal + frac * (buffer(obs, wrapCursor (integer+1, cursorMask))-retVal);
00042 }
00043 
00044 Delay::Delay(mrs_string name):MarSystem("Delay",name)
00045 {
00046 
00047   delayInSamples_.create(0);
00048   writeCursor_  = 0;
00049 
00050   cursorMask_   = 1;
00051 
00052   addControls();
00053 }
00054 
00055 
00056 Delay::~Delay()
00057 {
00058 }
00059 
00060 
00061 MarSystem*
00062 Delay::clone() const
00063 {
00064   return new Delay(*this);
00065 }
00066 
00067 Delay::Delay(const Delay& a) : MarSystem(a)
00068 {
00069   addControls();
00070   maxDelayLengthInSamples_ = getctrl("mrs_real/maxDelaySamples")->to<mrs_real>(); // maximum delay in samples
00071   delayInSamples_   =  getctrl("mrs_realvec/delaySamples")->to<mrs_realvec>(); // delay in samples
00072 }
00073 
00074 void
00075 Delay::addControls()
00076 {
00077   mrs_realvec tmp(1);
00078   tmp(0)    = 0;
00079   addctrl("mrs_real/maxDelaySamples", 32.0); // maximum delay in samples
00080   addctrl("mrs_real/maxDelaySeconds", 0.0); // maximum delay in seconds
00081   addctrl("mrs_real/delaySamples", 0.0); // delay in samples
00082   addctrl("mrs_real/delaySeconds", 0.0); // delay in seconds
00083   addctrl("mrs_realvec/delaySamples", tmp); // delay in samples
00084   addctrl("mrs_realvec/delaySeconds", tmp); // delay in samples
00085   setctrlState("mrs_real/maxDelaySamples", true);
00086   setctrlState("mrs_real/maxDelaySeconds", true);
00087   setctrlState("mrs_real/delaySeconds", true);
00088   setctrlState("mrs_real/delaySamples", true);
00089   setctrlState("mrs_realvec/delaySeconds", true);
00090   setctrlState("mrs_realvec/delaySamples", true);
00091 }
00092 
00093 
00094 void
00095 Delay::myUpdate(MarControlPtr sender)
00096 {
00097   (void) sender;  //suppress warning of unused parameter(s)
00098   MRSDIAG("Delay.cpp - Delay:myUpdate");
00099 
00100   // for the following controls, check whether they have changed and update dependent controls accordingly
00101   if (samples2Seconds (maxDelayLengthInSamples_) != getctrl ("mrs_real/maxDelaySeconds")->to<mrs_real>())
00102   {
00103     maxDelayLengthInSamples_    = seconds2Samples (getctrl ("mrs_real/maxDelaySeconds")->to<mrs_real>());
00104     setctrl("mrs_real/maxDelaySamples", maxDelayLengthInSamples_);
00105     buffer_.stretch (getctrl("mrs_natural/inObservations")->to<mrs_natural>(),
00106                      nextPowOfTwo((mrs_natural(.1+ceil(maxDelayLengthInSamples_))+1)));
00107     buffer_.setval(0);
00108   }
00109   if (maxDelayLengthInSamples_ != getctrl ("mrs_real/maxDelaySamples")->to<mrs_real>())
00110   {
00111     maxDelayLengthInSamples_    = getctrl ("mrs_real/maxDelaySamples")->to<mrs_real>();
00112     setctrl("mrs_real/maxDelaySeconds", samples2Seconds (maxDelayLengthInSamples_));
00113     buffer_.stretch (getctrl("mrs_natural/inObservations")->to<mrs_natural>(),
00114                      nextPowOfTwo((mrs_natural(.1+ceil(maxDelayLengthInSamples_))+1)));
00115     buffer_.setval(0);
00116   }
00117 
00118   if (samples2Seconds (singleDelayInSamples_) != getctrl ("mrs_real/delaySeconds")->to<mrs_real>())
00119   {
00120     mrs_realvec tmp(1);
00121     singleDelayInSamples_   = seconds2Samples (getctrl ("mrs_real/delaySeconds")->to<mrs_real>());
00122     MRSASSERT(singleDelayInSamples_ >= 0);
00123     MRSASSERT(singleDelayInSamples_ <= maxDelayLengthInSamples_);
00124 
00125     setctrl("mrs_real/delaySamples", singleDelayInSamples_);
00126 
00127     // update vector
00128     tmp(0)                  = singleDelayInSamples_;
00129     setctrl("mrs_realvec/delaySamples", tmp);
00130   }
00131   if (singleDelayInSamples_ != getctrl ("mrs_real/delaySamples")->to<mrs_real>())
00132   {
00133     mrs_realvec tmp(1);
00134     singleDelayInSamples_   = getctrl ("mrs_real/delaySamples")->to<mrs_real>();
00135     MRSASSERT(singleDelayInSamples_ >= 0);
00136     MRSASSERT(singleDelayInSamples_ <= maxDelayLengthInSamples_);
00137 
00138     setctrl("mrs_real/delaySeconds", samples2Seconds (singleDelayInSamples_));
00139 
00140     // update vector
00141     tmp(0)                  = singleDelayInSamples_;
00142     setctrl("mrs_realvec/delaySamples", tmp);
00143   }
00144 
00145   if (delayInSamples_ != getctrl ("mrs_realvec/delaySamples")->to<mrs_realvec>())
00146   {
00147     delayInSamples_ = getctrl ("mrs_realvec/delaySamples")->to<mrs_realvec>();
00148     setctrl("mrs_realvec/delaySeconds", samples2Seconds (delayInSamples_));
00149   }
00150   if (samples2Seconds (delayInSamples_) != getctrl ("mrs_realvec/delaySeconds")->to<mrs_realvec>())
00151   {
00152     delayInSamples_ = seconds2Samples (getctrl ("mrs_realvec/delaySeconds")->to<mrs_realvec>());
00153     setctrl("mrs_realvec/delaySamples", delayInSamples_);
00154   }
00155 
00156   // allocate the delay line
00157   buffer_.stretch (getctrl("mrs_natural/inObservations")->to<mrs_natural>(),
00158                    nextPowOfTwo((mrs_natural(.1+ceil(maxDelayLengthInSamples_))+1)));
00159   cursorMask_   = buffer_.getCols () - 1;       // to ensure an efficient wrap around, buffer
00160   //length will be a power of two
00161   if (prevDelayInSamples_.getSize () != delayInSamples_.getSize ())
00162   {
00163     // only do this update if needed...
00164     ctrlIncrement_.stretch (delayInSamples_.getSize (), delayInSamples_.getCols ());
00165     prevDelayInSamples_ = delayInSamples_;
00166 
00167     // initialize the delay line
00168     buffer_.stretch (getctrl("mrs_natural/inObservations")->to<mrs_natural>(),
00169                      nextPowOfTwo((mrs_natural(.1+ceil(maxDelayLengthInSamples_))+1)));
00170     buffer_.setval(0);
00171     writeCursor_    = 0;
00172 
00173     // set output names
00174     vector<mrs_string> indiChannels = stringSplit (getctrl("mrs_string/inObsNames")->to<mrs_string>(), ",");
00175     ostringstream   outNames;
00176     for (mrs_natural c = 0; c < getctrl("mrs_natural/inObservations")->to<mrs_natural>(); ++c)
00177       for (mrs_natural i = 0; i < delayInSamples_.getSize (); ++i)
00178       {
00179         outNames << indiChannels.at(c) << "-delay_" << i << ",";
00180       }
00181     setctrl("mrs_string/onObsNames", outNames.str());
00182   }
00183 
00184 
00185   setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00186   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00187   setctrl("mrs_natural/onObservations",
00188           (mrs_natural) delayInSamples_.getSize () * getctrl("mrs_natural/inObservations")->to<mrs_natural>());
00189 
00190 }
00191 
00192 
00193 void
00194 Delay::myProcess(realvec& in, realvec& out)
00195 {
00196   mrs_natural k, numDelayLines = delayInSamples_.getSize ();
00197   mrs_natural o,t;
00198   // first, get the interpolated delay update (linear interpolation only)
00199   getLinearInterPInc (prevDelayInSamples_, delayInSamples_, ctrlIncrement_, inSamples_);
00200 
00201 #ifdef MARSYAS_MATLAB
00202 #ifdef MTLB_DBG_LOG
00203   MATLAB_PUT(in, "in");
00204   MATLAB_EVAL("figure(41),subplot(211),plot(in'),axis('tight'),grid on, title('in')");
00205 #endif
00206 #endif
00207 
00208   for (t = 0; t < inSamples_; t++)
00209   {
00210     for (o=0; o < inObservations_; o++)
00211     {
00212       // write new sample to buffer
00213       buffer_(o, writeCursor_)  = in(o,t);
00214       for (k = 0; k < numDelayLines; k++)
00215       {
00216         // read sample from buffer
00217         out(k+o*numDelayLines,t) = getValue (o, writeCursor_ - (prevDelayInSamples_(k) + t*ctrlIncrement_(k)), buffer_, cursorMask_);
00218       }
00219 
00220     }
00221     writeCursor_    = wrapCursor (++writeCursor_, cursorMask_);
00222   }
00223 
00224   prevDelayInSamples_   = delayInSamples_;
00225 
00226 
00227 #ifdef MARSYAS_MATLAB
00228 #ifdef MTLB_DBG_LOG
00229   MATLAB_PUT(out, "out");
00230   MATLAB_EVAL("figure(41),subplot(212),plot(out'),axis('tight'),grid on, title('out')");
00231 #endif
00232 #endif
00233 }
00234 
00235 void Delay::getLinearInterPInc (const mrs_realvec startVal, const mrs_realvec stopVal,
00236                                 mrs_realvec &incVal, const mrs_natural numSamples)
00237 {
00238   incVal    = (stopVal - startVal);
00239   incVal    /= (1.0*numSamples);
00240 }
00241 
00242 mrs_natural Delay::nextPowOfTwo (mrs_natural value)
00243 {
00244   mrs_natural    order = 0;
00245 
00246   while (value>>order)
00247     order++;
00248 
00249   if (!order)
00250     return value;
00251 
00252   if (!(value%(1<<(order-1))))
00253     order--;
00254 
00255   order = (order < 1)? 1 : order;
00256 
00257   return (1<<(order));
00258 }
00259 
00260 mrs_real Delay::samples2Seconds (mrs_real samples)
00261 {
00262   if (israte_ > 0)
00263     return samples / israte_;
00264   else
00265     return 0;
00266 }
00267 mrs_real Delay::seconds2Samples (mrs_real seconds)
00268 {
00269   return seconds * israte_;
00270 }
00271 mrs_realvec Delay::samples2Seconds (mrs_realvec samples)
00272 {
00273   for (mrs_natural i = 0; i < samples.getSize (); ++i)
00274     samples(i)  = samples(i)/ israte_;
00275 
00276   return samples;
00277 }
00278 mrs_realvec Delay::seconds2Samples (mrs_realvec seconds)
00279 {
00280   for (mrs_natural i = 0; i < seconds.getSize (); ++i)
00281     seconds(i)  = seconds(i) * israte_;
00282 
00283   return seconds;
00284 }