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