Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/Accumulator.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 "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 }