Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/SoundFileSourceHopper.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2009 Stefaan Lippens
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 "SoundFileSourceHopper.h"
00020 #include "SoundFileSource.h"
00021 #include "MixToMono.h"
00022 #include "ShiftInput.h"
00023 
00024 using namespace std;
00025 using namespace Marsyas;
00026 
00027 SoundFileSourceHopper::SoundFileSourceHopper(mrs_string name) : MarSystem("SoundFileSourceHopper", name)
00028 {
00029 
00031   addControls();
00032 
00033   // Add the MarSystems we need as children.
00034   isComposite_ = true;
00035   addMarSystem(new SoundFileSource("src"));
00036   addMarSystem(new MixToMono("mix2mono"));
00037   addMarSystem(new ShiftInput("hopper"));
00038 
00039   // Provide some shortcuts to SoundFileSource internals.
00040   this->linkControl("mrs_string/filename", "SoundFileSource/src/mrs_string/filename");
00041   this->linkControl("mrs_bool/hasData", "SoundFileSource/src/mrs_bool/hasData");
00042 
00043 }
00044 
00045 SoundFileSourceHopper::SoundFileSourceHopper(const SoundFileSourceHopper& a) : MarSystem(a)
00046 {
00047   isComposite_ = true;
00048   // All member MarControlPtr have to be explicitly reassigned in
00049   // the copy constructor.
00050   ctrl_windowSize_ = getControl("mrs_natural/windowSize");
00051   ctrl_hopSize_ = getControl("mrs_natural/hopSize");
00052   ctrl_mixToMono_ = getControl("mrs_bool/mixToMono");
00053 
00054   // Add the MarSystems we need as children.
00055   isComposite_ = true;
00056   addMarSystem(new SoundFileSource("src"));
00057   addMarSystem(new MixToMono("mix2mono"));
00058   addMarSystem(new ShiftInput("hopper"));
00059 
00060   // Provide some shortcuts to SoundFileSource internals.
00061   this->linkControl("mrs_string/filename", "SoundFileSource/src/mrs_string/filename");
00062   this->linkControl("mrs_bool/hasData", "SoundFileSource/src/mrs_bool/hasData");
00063 
00064 }
00065 
00066 
00067 SoundFileSourceHopper::~SoundFileSourceHopper()
00068 {
00069 }
00070 
00071 MarSystem*
00072 SoundFileSourceHopper::clone() const
00073 {
00074   return new SoundFileSourceHopper(*this);
00075 }
00076 
00077 void
00078 SoundFileSourceHopper::addControls()
00079 {
00081   addControl("mrs_natural/windowSize", (mrs_natural)MRS_DEFAULT_SLICE_NSAMPLES, ctrl_windowSize_);
00082   setControlState("mrs_natural/windowSize", true);
00083 
00084   addControl("mrs_natural/hopSize", (mrs_natural)(MRS_DEFAULT_SLICE_NSAMPLES/2), ctrl_hopSize_);
00085   setControlState("mrs_natural/hopSize", true);
00086 
00087   addControl("mrs_bool/mixToMono", false, ctrl_mixToMono_);
00088   setControlState("mrs_bool/mixToMono", true);
00089 
00090 }
00091 
00098 void
00099 SoundFileSourceHopper::myUpdate(MarControlPtr sender)
00100 {
00101   (void) sender;  //suppress warning of unused parameter(s)
00102   // Set the hop size as window size for the SoundFileSource (and leave the
00103   // other stuff (like osrate, onObservations, ...) up to the SoundFileSource.
00104   // We have to make sure we do this when the SoundFileSource is already
00105   // added to the marsystems_ list.
00106   if (marsystems_.size() >= 1) {
00107     marsystems_[0]->setControl("mrs_natural/inSamples", ctrl_hopSize_);
00108     marsystems_[0]->update();
00109   }
00110 
00111   // Set the window size in the ShiftInput Marsystem (if it is already
00112   // added to the marsystems_ list).
00113   if (marsystems_.size() >= 3) {
00114     marsystems_[2]->setControl("mrs_natural/winSize", ctrl_windowSize_);
00115     marsystems_[2]->update();
00116   }
00117 
00118   // Update data flows in order.
00119   // src and tgt stand for the source and target MarSystems in the for loop.
00120   // Note: if MixToMono is disabled, we skip the MixToMono MarSystem
00121   // (which is at index 1).
00122   mrs_natural i_src = 0;
00123   mrs_natural i_tgt = ctrl_mixToMono_->to<mrs_bool>() ? 1 : 2;
00124   for ( ; i_tgt < (mrs_natural)marsystems_.size(); i_src = i_tgt, i_tgt++) {
00125     // Get the source and target MarSystems.
00126     MarSystem* m_src = marsystems_[i_src];
00127     MarSystem* m_tgt = marsystems_[i_tgt];
00128     // Copy over the control values from source to target.
00129     m_tgt->setctrl(m_tgt->ctrl_inObsNames_, m_src->ctrl_onObsNames_);
00130     m_tgt->setctrl(m_tgt->ctrl_inObservations_, m_src->ctrl_onObservations_);
00131     m_tgt->setctrl(m_tgt->ctrl_inSamples_, m_src->ctrl_onSamples_);
00132     m_tgt->setctrl(m_tgt->ctrl_israte_, m_src->ctrl_osrate_);
00133     // And update the target MarSystem with the new settings.
00134     m_tgt->update();
00135   }
00136 
00137   // Set the container's output controls based on the last internal MarSystem.
00138   MarSystem* m_last = marsystems_[marsystems_.size() - 1];
00139   updControl(ctrl_onObsNames_, m_last->ctrl_onObsNames_, NOUPDATE);
00140   updControl(ctrl_onSamples_, m_last->ctrl_onSamples_, NOUPDATE);
00141   updControl(ctrl_onObservations_, m_last->ctrl_onObservations_, NOUPDATE);
00142   updControl(ctrl_osrate_, m_last->ctrl_osrate_, NOUPDATE);
00143 
00144   // Allocate the appropriate amount of memory for the intermediate slices.
00145   for (size_t i=0; i < marsystems_.size() - 1; ++i)
00146   {
00147     MarSystem* m = marsystems_[i];
00148     MarControlAccessor acc(m->ctrl_processedData_, NOUPDATE);
00149     realvec& processedData = acc.to<mrs_realvec>();
00150     mrs_natural rows = m->ctrl_onObservations_->to<mrs_natural>();
00151     mrs_natural cols = m->ctrl_onSamples_->to<mrs_natural>();
00152     if (processedData.getRows() != rows || processedData.getCols() != cols )
00153     {
00154       processedData.create(rows, cols);
00155     }
00156   }
00157 
00158 }
00159 
00160 void
00161 SoundFileSourceHopper::myProcess(realvec& in, realvec& out)
00162 {
00163   (void) in;
00164 
00165   // First step: do the processing of the SoundFileSource.
00166   MarControlAccessor acc(marsystems_[0]->ctrl_processedData_);
00167   realvec& slice_out = acc.to<mrs_realvec>();
00168   // `slice_out` is the slice that receives the data from the SoundFileSource
00169   // Note that we provide `slice_out` also as input argument of
00170   // this `process` call instead of the traditional realvec `in`.
00171   // We do this to circumvent the (optional) flow check in `process`.
00172   // SoundFileSourceHopper does not use its `inSamples_` attribute
00173   // to set slice sizes, but uses the `hopSize` control instead.
00174   // Consequently, the realvec `in` given as argument from upstream
00175   // (based on the inSamples_ attribute) will typically not match the slice
00176   // size we expect and the flow check will fail. `slice_out` however
00177   // does have the size we expect and because the SoundFileSource just
00178   // ignores its input anyway, we can use this trick here.
00179   marsystems_[0]->process(slice_out, slice_out);
00180 
00181   // The other steps: do the processing of MixToMono (if required)
00182   // and ShiftInput (and maybe more MarSystems).
00183   child_count_t i_prev = 0;
00184   child_count_t i_curr = ctrl_mixToMono_->to<mrs_bool>() ? 1 : 2;
00185   child_count_t child_count = marsystems_.size();
00186   for ( ; i_curr < child_count; i_prev = i_curr, i_curr++) {
00187     MarSystem* m_prev = marsystems_[i_prev];
00188     MarSystem* m_curr = marsystems_[i_curr];
00189 
00190     // Get the processed data slice from the previous MarSystem.
00191     MarControlAccessor acc_prev(m_prev->ctrl_processedData_, true, true);
00192     realvec& data_prev = acc_prev.to<mrs_realvec>();
00193 
00194     if (i_curr < child_count - 1)
00195     {
00196       MarControlAccessor acc_curr(m_curr->ctrl_processedData_);
00197       realvec& data_curr = acc_curr.to<mrs_realvec>();
00198       m_curr->process(data_prev, data_curr);
00199     }
00200     else
00201     {
00202       m_curr->process(data_prev, out);
00203     }
00204 
00205   }
00206 
00207 }