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 "Accumulator.h" 00020 #include "../common_source.h" 00021 00022 using std::ostringstream; 00023 using namespace Marsyas; 00024 00025 Accumulator::Accumulator(mrs_string name): MarSystem("Accumulator", name) 00026 { 00027 isComposite_ = true; 00028 addControls(); 00029 00030 keptOnSamples_ = 0; 00031 } 00032 00033 Accumulator::Accumulator(const Accumulator& a): MarSystem(a) 00034 { 00035 ctrl_nTimes_ = getctrl("mrs_natural/nTimes"); 00036 ctrl_maxTimes_ = getctrl("mrs_natural/maxTimes"); 00037 ctrl_minTimes_ = getctrl("mrs_natural/minTimes"); 00038 ctrl_mode_ = getctrl("mrs_string/mode"); 00039 ctrl_flush_ = getctrl("mrs_bool/flush"); 00040 ctrl_timesToKeep_ = getctrl("mrs_natural/timesToKeep"); 00041 keptOnSamples_ = a.keptOnSamples_; 00042 } 00043 00044 Accumulator::~Accumulator() 00045 { 00046 } 00047 00048 MarSystem* 00049 Accumulator::clone() const 00050 { 00051 return new Accumulator(*this); 00052 } 00053 00054 void 00055 Accumulator::addControls() 00056 { 00057 addctrl("mrs_string/mode", "countTicks", ctrl_mode_); 00058 ctrl_mode_->setState(true); 00059 00060 addctrl("mrs_natural/nTimes", 5, ctrl_nTimes_); 00061 ctrl_nTimes_->setState(true); 00062 00063 addctrl("mrs_natural/timesToKeep", 0, ctrl_timesToKeep_); 00064 ctrl_timesToKeep_->setState(true); 00065 00066 addctrl("mrs_bool/flush", false, ctrl_flush_); 00067 00068 addctrl("mrs_natural/maxTimes", 5, ctrl_maxTimes_); 00069 ctrl_maxTimes_->setState(true); 00070 00071 addctrl("mrs_natural/minTimes", 5, ctrl_minTimes_); 00072 ctrl_minTimes_->setState(true); 00073 } 00074 00075 00076 bool 00077 Accumulator::addMarSystem(MarSystem *marsystem) 00078 { 00079 if (marsystems_.size()) { 00080 MarSystem* mySystem = marsystems_[0]; 00081 (void) mySystem; // suppress warning in case the macro is not expanded 00082 00083 MRSWARN("Accumulator::addMarSystem: already added '" 00084 << mySystem->getAbsPath() 00085 << "' to the Accumulator NOT ADDING '" 00086 << marsystem->getName() 00087 << "'."); 00088 return false; 00089 } 00090 return MarSystem::addMarSystem(marsystem); 00091 00092 00093 } 00094 00095 void 00096 Accumulator::myUpdate(MarControlPtr sender) 00097 { 00098 MRSDIAG("Accumulator.cpp - Accumulator:myUpdate"); 00099 00100 mrs_string onObsNames; 00101 00102 childOnSamples_ = 0; 00103 nTimes_ = ctrl_nTimes_->to<mrs_natural>(); 00104 00105 MarSystem::myUpdate(sender); 00106 00107 if (marsystems_.size()) 00108 { 00109 //propagate in flow controls to first (and single) child 00110 marsystems_[0]->setctrl("mrs_natural/inObservations", inObservations_); 00111 marsystems_[0]->setctrl("mrs_natural/inSamples", inSamples_); 00112 marsystems_[0]->setctrl("mrs_real/israte", israte_); 00113 marsystems_[0]->setctrl("mrs_string/inObsNames", inObsNames_); 00114 marsystems_[0]->update(); 00115 00116 childOnSamples_ = marsystems_[0]->getctrl("mrs_natural/onSamples")->to<mrs_natural>(); 00117 //nTimes_ = ctrl_nTimes_->to<mrs_natural>(); 00118 00119 // forward flow propagation 00120 setctrl(ctrl_onSamples_, nTimes_ * childOnSamples_); //dynamic resizing of onSamples! 00121 setctrl(ctrl_onObservations_, 00122 marsystems_[0]->getctrl("mrs_natural/onObservations")->to<mrs_natural>()); 00123 setctrl(ctrl_osrate_, 00124 marsystems_[0]->getctrl("mrs_real/osrate")); 00125 00126 onObsNames = marsystems_[0]->getctrl("mrs_string/onObsNames")->to<mrs_string>(); 00127 } 00128 00129 onObservations_ = ctrl_onObservations_->to<mrs_natural>(); 00130 00131 // Add prefix to the observation names. 00132 ostringstream prefix_oss; 00133 prefix_oss << "Acc" << nTimes_ << "_"; 00134 ctrl_onObsNames_->setValue(obsNamesAddPrefix(onObsNames, prefix_oss.str()), NOUPDATE); 00135 00136 00137 onSamples_ = ctrl_onSamples_->to<mrs_natural>(); 00138 00139 //create temporary buffer for child output 00140 childOut_.stretch(onObservations_, childOnSamples_); 00141 00142 //create internal buffer for accumulating data to send to output 00143 //(set it to the specified maximum + any kept old) 00144 if (ctrl_mode_->to<mrs_string>() == "explicitFlush") 00145 { 00146 tout_.stretch(onObservations_, 00147 (ctrl_timesToKeep_->to<mrs_natural>() + ctrl_maxTimes_->to<mrs_natural>()) * childOnSamples_); 00148 } 00149 else 00150 { 00151 tout_.create(0,0); //no memory is needed in this mode 00152 } 00153 } 00154 00155 void 00156 Accumulator::myProcess(realvec& in, realvec& out) 00157 { 00158 mrs_natural o,c,t; 00159 00160 if (!marsystems_.size()) 00161 { 00162 out = in; 00163 return; 00164 } 00165 00166 if (ctrl_mode_->to<mrs_string>() == "explicitFlush") 00167 { 00168 mrs_natural timesCount = keptOnSamples_/childOnSamples_; 00169 00170 while ((!ctrl_flush_->to<mrs_bool>() && timesCount < ctrl_maxTimes_->to<mrs_natural>()) 00171 || timesCount < ctrl_minTimes_->to<mrs_natural>() 00172 || timesCount <= ctrl_timesToKeep_->to<mrs_natural>()) 00173 { 00174 // child MarSystem should have a control linked to the Accumulator flush control 00175 // so it can signal the end of this loop (e.g. when an onset is detected or some other similar event) 00176 marsystems_[0]->process(in, childOut_); 00177 00178 //accumulate output from child process()into temp buffer 00179 for (o=0; o < onObservations_; o++) 00180 { 00181 for (t = 0; t < childOnSamples_; t++) 00182 { 00183 tout_(o, t + timesCount * childOnSamples_) = childOut_(o,t); 00184 } 00185 } 00186 timesCount++; 00187 } 00188 00189 #ifdef MARSYAS_LOG_DIAGNOSTICS 00190 if (!ctrl_flush_->to<mrs_bool>()) 00191 { 00192 MRWDIAG("Accumulator::myProcess() - maxTimes reached without a flush event!"); 00193 } 00194 #endif 00195 00196 //adjust output number of samples dynamically (this calls update()!!) 00197 //to the number of accumulated samples (minus the ones to keep for next time) 00198 ctrl_nTimes_->setValue(timesCount - ctrl_timesToKeep_->to<mrs_natural>()); 00199 00200 keptOnSamples_ = ctrl_timesToKeep_->to<mrs_natural>() * childOnSamples_; 00201 00202 //copy data in tmp buffer to the output 00203 for (o=0; o < onObservations_; ++o) 00204 { 00205 for (t = 0; t < ctrl_onSamples_->to<mrs_natural>(); ++t) 00206 { 00207 out(o,t) = tout_(o,t); 00208 } 00209 } 00210 00211 00212 //store samples to keep into the beginning of the temp buffer 00213 //for next call to process() 00214 for (t = 0; t < keptOnSamples_; ++t) 00215 { 00216 for (o=0; o < onObservations_; ++o) 00217 { 00218 tout_(o,t) = tout_(o, t + ctrl_onSamples_->to<mrs_natural>()); 00219 } 00220 } 00221 00222 //reset flush flag 00223 ctrl_flush_->setValue(false); 00224 } 00225 else if (ctrl_mode_->to<mrs_string>() == "countTicks") 00226 { 00227 //nTimes_ = ctrl_nTimes_->to<mrs_natural>(); 00228 ctrl_flush_->setValue(false); 00229 for (c = 0; c < nTimes_; ++c) 00230 { 00231 00232 marsystems_[0]->process(in, childOut_); 00233 00234 for (o=0; o < onObservations_; o++) 00235 { 00236 for (t = 0; t < childOnSamples_; t++) 00237 { 00238 out(o, t + c * childOnSamples_) = childOut_(o,t); 00239 } 00240 } 00241 } 00242 ctrl_flush_->setValue(true); 00243 } 00244 00245 //used for toy_with_onsets.m (DO NOT DELETE! - COMMENT INSTEAD) 00246 //MATLAB_PUT(out, "Accum_out"); 00247 //MATLAB_EVAL("segmentData = [segmentData, Accum_out];"); 00248 }