Marsyas
0.6.0-alpha
|
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 }