Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/ShiftInput.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 "ShiftInput.h"
00020 
00021 using namespace std;
00022 using namespace Marsyas;
00023 
00024 ShiftInput::ShiftInput(mrs_string name): MarSystem("ShiftInput", name)
00025 {
00026   winSize_ = 0;
00027   hopSize_ = 0;
00028   addControls();
00029 }
00030 
00031 ShiftInput::~ShiftInput()
00032 {
00033 }
00034 
00035 ShiftInput::ShiftInput(const ShiftInput& a): MarSystem(a)
00036 {
00037   winSize_ = 0;
00038   hopSize_ = 0;
00039 
00040   ctrl_reset_ = getctrl("mrs_bool/reset");
00041   ctrl_winSize_ = getctrl("mrs_natural/winSize");
00042 
00043   ctrl_clean_ = getctrl("mrs_bool/clean");
00044   ctrl_lowCleanLimit_ = getctrl("mrs_real/lowCleanLimit");
00045   ctrl_highCleanLimit_ = getctrl("mrs_real/highCleanLimit");
00046 }
00047 
00048 MarSystem*
00049 ShiftInput::clone() const
00050 {
00051   return new ShiftInput(*this);
00052 }
00053 
00054 void
00055 ShiftInput::addControls()
00056 {
00057   // The control for the window size.
00058   addControl("mrs_natural/winSize", (mrs_natural)MRS_DEFAULT_SLICE_NSAMPLES, ctrl_winSize_);
00059   setControlState("mrs_natural/winSize", true);
00060 
00061   // The control to reset the internal buffer, set to true so the buffer
00062   // itself is properly initialized later.
00063   addControl("mrs_bool/reset", true, ctrl_reset_);
00064 
00065   // Clean control for partially cleaning the buffer at any point of the analysis
00066   // The low and high clean limits (as a portion of the buffer size) are given by
00067   // lowCleanLimit and highCleanLimit controls
00068   addControl("mrs_bool/clean", false, ctrl_clean_);
00069   addControl("mrs_real/lowCleanLimit", 0.0, ctrl_lowCleanLimit_);
00070   addControl("mrs_real/highCleanLimit", 1.0, ctrl_highCleanLimit_);
00071 }
00072 
00073 void
00074 ShiftInput::myUpdate(MarControlPtr sender)
00075 {
00076   (void) sender;  //suppress warning of unused parameter(s)
00077 
00078   // Cache the window and hop size for use in myProcess().
00079   winSize_ = ctrl_winSize_->to<mrs_natural>();
00080   hopSize_ = ctrl_inSamples_->to<mrs_natural>();
00081 
00082   // If the hop size is smaller than the window size, we need buffering to
00083   // handle the overlap between successive windows.
00084   // When the hop size is larger than the window size, we don't have overlap
00085   // and don't need buffering.
00086   if (hopSize_ < winSize_)
00087   {
00088     outSavedData_.stretch(ctrl_inObservations_->to<mrs_natural>(), winSize_ - hopSize_);
00089     if (hopSize_ == 0) {
00090       addToStabilizingDelay_ = 0;
00091     } else {
00092       mrs_natural full = (mrs_natural) (((mrs_real) winSize_ / hopSize_));
00093       addToStabilizingDelay_ = ((mrs_natural) ceil(((mrs_real) winSize_ / hopSize_)-full)) + full - 1;
00094       //cout<<winSize_ <<"\t"<<hopSize_ <<"\t"<< (mrs_real) winSize_ / hopSize_<<"\t"<<full<<"\t"<<addToStabilizingDelay_<<endl;
00095     }
00096   } else {
00097     addToStabilizingDelay_ = 0;
00098   }
00099 
00100   // Update the output stream format.
00101   ctrl_onSamples_->setValue(ctrl_winSize_, NOUPDATE);
00102   ctrl_onObservations_->setValue(ctrl_inObservations_, NOUPDATE);
00103   ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00104 
00105   // Update the onObsNames string.
00106   ostringstream prefix_oss;
00107   prefix_oss << "HopSize" << hopSize_ << "_WinSize" << winSize_ << "_";
00108   mrs_string onObsNames = obsNamesAddPrefix(ctrl_inObsNames_->to<mrs_string>(), prefix_oss.str());
00109   ctrl_onObsNames_->setValue(onObsNames, NOUPDATE);
00110 }
00111 
00112 void
00113 ShiftInput::myProcess(realvec& in, realvec& out)
00114 {
00115   mrs_natural t,o;
00116 
00117 
00118   for (o = 0; o<inObservations_; ++o)
00119   {
00120     if (hopSize_ < winSize_)
00121     {
00122       // When the hop size is smaller than the window size, we have to work
00123       // with a buffer.
00124 
00125       // Check if we must clear the audio buffer (due to a reset call).
00126       // TODO: shouldn't this be done in myUpdate?
00127       if (ctrl_reset_->to<mrs_bool>())
00128       {
00129         outSavedData_.setval(0.0);
00130         ctrl_reset_->setValue(false);
00131       }
00132 
00133       // Check if requested a call for a partial clean of the buffer
00134       // TODO: shouldn't this be done in myUpdate?
00135       if(ctrl_clean_->to<mrs_bool>())
00136       {
00137         // round up with ceil()
00138         mrs_natural lowCleanLimit = (mrs_natural) ceil(winSize_
00139                                     * getctrl("mrs_real/lowCleanLimit")->to<mrs_real>());
00140         mrs_natural highCleanLimit = (mrs_natural) (lowCleanLimit + (ceil( winSize_
00141                                      * getctrl("mrs_real/highCleanLimit")->to<mrs_real>()
00142                                                                          ) - lowCleanLimit));
00143 
00144         for (t = lowCleanLimit; t < highCleanLimit; t++)
00145           outSavedData_(o, t) = 0.0;
00146 
00147         ctrl_clean_->setValue(false);
00148       }
00149 
00150       // TODO: this can be done more efficiently with a circular buffer
00151       // instead of shifting the buffer data all the time.
00152 
00153       // First part of output: copy the buffered data.
00154       for (t = 0; t < winSize_ - hopSize_; t++)
00155       {
00156         out(o, t) = outSavedData_(o, t);
00157       }
00158       // Second part of output: copy the new data from the input.
00159       for (t = winSize_ - hopSize_; t < winSize_; t++)
00160       {
00161         out(o, t) = in(o, t - (winSize_ - hopSize_));
00162       }
00163       // Store part of the output to the buffer for the next time.
00164       for (t = 0; t < winSize_ - hopSize_; t++)
00165       {
00166         outSavedData_(o, t) = out(o, t + hopSize_);
00167       }
00168     }
00169     else
00170     {
00171       // When the hop size is larger than the window size, we just need to
00172       // copy the first onSamples_ samples and discard the rest.
00173       for (t = 0; t < onSamples_; ++t)
00174       {
00175         out(o, t) = in(o, t);
00176       }
00177     }
00178   }
00179 
00180   //used for toy_with_onsets.m (DO NOT DELETE! - COMMENT INSTEAD)
00181   // MATLAB_PUT(in, "ShiftInput_in");
00182   // MATLAB_PUT(out, "ShiftInput_out");
00183   // MATLAB_EVAL("size(ShiftInput_in)");
00184 
00185 //  MATLAB_EVAL("plot(ShiftInput_in)");
00186 //  getchar();
00187 //  MATLAB_EVAL("plot(ShiftInput_out)");
00188 //  getchar();
00189 
00190 }