CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #ifndef _SMSTransformationChain_ 00023 #define _SMSTransformationChain_ 00024 00025 00026 #include "SegmentTransformation.hxx" 00027 #include "SMSTransformationChainConfig.hxx" 00028 #include "ProcessingComposite.hxx" 00029 #include "ProcessingData.hxx" 00030 #include "InPort.hxx" 00031 #include "OutPort.hxx" 00032 #include "InControlTmplArray.hxx" 00033 #include "ProcessingFactory.hxx" 00034 #include "Array.hxx" 00035 00036 #include "FrameTransformation.hxx" 00037 00038 namespace CLAM { 00039 00044 class SMSTransformationChain: public ProcessingComposite 00045 { 00046 00047 InControlTmplArray<SMSTransformationChain> *mpOnCtrlArray; 00048 00050 Array<Segment*> mpTmpDataArray; 00052 SMSTransformationChainConfig* mpConfig; 00053 Segment* mpChainInput; 00054 Segment* mpChainOutput; 00055 00056 00057 public: 00058 00059 void AttachIn(Segment& data) { mpChainInput = &data; } 00060 void AttachOut(Segment& data) { mpChainOutput = &data; } 00061 00062 SMSTransformationChain() : 00063 mpChainInput(0), 00064 mpChainOutput(0) 00065 { 00066 mpConfig=NULL; 00067 mpOnCtrlArray=NULL; 00068 } 00072 virtual ~SMSTransformationChain(){ 00073 00074 for(int i=0;i<mpTmpDataArray.Size();i++) 00075 if(mpTmpDataArray[i]) delete mpTmpDataArray[i]; 00076 if (mpConfig) delete mpConfig; 00077 00078 for(iterator obj=composite_begin();obj!=composite_end();obj++) 00079 { 00080 delete (*obj); 00081 } 00082 } 00083 00084 virtual bool DoChildren() 00085 { 00086 CLAM_DEBUG_ASSERT(IsRunning(), 00087 "SMSTransformationChain: Do(): Not in execution mode"); 00088 00089 bool result=true; 00090 int i=0; 00091 //We iterate through all chainees and call their Do() 00092 for (iterator obj=composite_begin(); obj!=composite_end(); obj++,i++) 00093 { 00094 Processing & proc = *(*obj); 00095 SegmentTransformation& trans = dynamic_cast<SegmentTransformation&>(proc); 00096 //TODO have a list instead of being a composite 00097 00098 if((*mpOnCtrlArray)[i].GetLastValue()||i==0||i==int(composite_size())-1) 00099 //Note: First and last chainee's will always be active regartheless the value 00100 //of their On control. 00101 { 00102 CLAM_DEBUG_ASSERT(proc.IsRunning(), "child is not running" ); 00103 result &= trans.DoWithSegments(); 00104 } 00105 } 00106 return result; 00107 } 00108 00109 bool Do() 00110 { 00111 if(IsLastFrame()) 00112 { 00113 printf("TransChain::Do() is last frame\n"); 00114 return false; 00115 } 00116 NextFrame(); 00117 return DoChildren(); 00118 } 00119 00120 bool ConcreteStart() 00121 { 00122 void InitSegmentArray(); 00123 00124 Segment* pCurrentData; 00125 pCurrentData=new Segment(*mpChainInput); 00126 mpTmpDataArray.AddElem(pCurrentData); 00127 00128 // set up connections: inSegment<--trans-->outSegment 00129 00130 iterator obj; 00131 for(obj=composite_begin();obj!=composite_end();obj++) 00132 { 00133 //connecting ports for non-supervised mode 00134 Processing & processing = *(*(obj)); 00135 SegmentTransformation&concreteObj = dynamic_cast<SegmentTransformation&>(processing); 00136 00137 concreteObj.AttachIn(*pCurrentData); 00138 if(!(*obj)->CanProcessInplace()) 00139 { 00140 printf("Can't process inplace: setting a temporal segment\n"); 00141 pCurrentData=new Segment(*mpChainInput); 00142 mpTmpDataArray.AddElem(pCurrentData); 00143 } 00144 concreteObj.AttachOut(*pCurrentData); 00145 } 00146 // now we have to restore the inSegment of the first child 00147 obj=composite_begin(); 00148 SegmentTransformation& concreteObj = dynamic_cast<SegmentTransformation&>( *(*(obj)) ); 00149 concreteObj.AttachIn(*mpChainInput); 00150 00151 obj=composite_end(); 00152 obj--; 00153 SegmentTransformation& concreteObj2 = dynamic_cast<SegmentTransformation&>( *(*(obj)) ); 00154 00155 concreteObj2.AttachOut( *mpChainOutput); 00156 00157 InitAllFrameIndex(); 00158 00159 return ProcessingComposite::ConcreteStart(); 00160 00161 } 00162 00163 void InitSegmentArray() 00164 { 00165 for(int i=0;i<mpTmpDataArray.Size();i++) 00166 if(mpTmpDataArray[i]) 00167 delete mpTmpDataArray[i]; 00168 mpTmpDataArray.SetSize(0); 00169 } 00170 00171 void InitAllFrameIndex() 00172 { 00173 for(int i=0;i<mpTmpDataArray.Size();i++) 00174 mpTmpDataArray[i]->mCurrentFrameIndex=0; 00175 mpChainInput->mCurrentFrameIndex=0; 00176 } 00177 00179 void TurnOn(TIndex index) 00180 { 00181 (*mpOnCtrlArray)[index].DoControl(1); 00182 } 00183 00185 void TurnOff(TIndex index) 00186 { 00187 (*mpOnCtrlArray)[index].DoControl(0); 00188 } 00189 00190 const ProcessingConfig& GetConfig() const 00191 { 00192 return *mpConfig; 00193 } 00194 00195 bool ConcreteConfigure(const ProcessingConfig& c) 00196 { 00197 mpConfig=new SMSTransformationChainConfig(dynamic_cast<const SMSTransformationChainConfig&>(c)); 00198 bool result=true; 00199 iterator obj; 00200 00202 obj=composite_begin(); 00203 while(obj!=composite_end()) 00204 { 00205 Remove(*(*obj)); 00206 obj=composite_begin(); 00207 } 00208 00209 SMSTransformationChainConfig::iterator cfg; 00210 for(cfg=mpConfig->ConfigList_begin();cfg!=mpConfig->ConfigList_end();cfg++) 00211 { 00212 AddChainee((*cfg).GetConcreteClassName()); 00213 obj=composite_end(); 00214 obj--; 00215 result&=(*obj)->Configure((*cfg).GetConcreteConfig()); 00216 } 00217 CLAM_ASSERT(mpConfig->GetConfigurations().size()==composite_size(),"Number of configurations should be the same as number of children"); 00218 00219 //TODO: right now there is no way to add or remove controls than to instantiate control array again 00220 CLAM_ASSERT(mpConfig->GetOnArray().Size()==(int)composite_size(),"SMSTransformationChain::ConcreteConfigure: On array does not have same size as number of configurations"); 00221 TSize nControls=composite_size(); 00222 if(mpOnCtrlArray) delete mpOnCtrlArray; 00223 mpOnCtrlArray= new InControlTmplArray<SMSTransformationChain>(nControls,"OnControlArray",this,NULL); 00224 00225 for(int i=0;i<nControls;i++) 00226 { 00227 (*mpOnCtrlArray)[i].DoControl(mpConfig->GetOnArray()[i]); 00228 } 00229 return result; 00230 } 00231 00235 SegmentTransformation* GetTransformation(const std::string& name) 00236 { 00237 for(iterator obj=composite_begin(); obj!=composite_end(); obj++) 00238 { 00239 if(name == (*obj)->GetClassName()) return dynamic_cast<SegmentTransformation*>((*obj));; 00240 } 00241 return NULL; 00242 } 00243 00244 00245 private: 00246 00247 void AddChainee(const std::string& classname) 00248 { 00249 //TODO: Instead of connecting controls, use the publishing mechanism 00250 //TODO2: If all amount controls were named the same I might be able to get rid of the string comparison 00251 ProcessingFactory & theFactory = ProcessingFactory::GetInstance(); 00252 00253 if ( classname=="SMSFreqShift") 00254 { 00255 SegmentTransformation* wrapper = new SegmentTransformation; 00256 Processing * proc = theFactory.Create(classname); 00257 FrameTransformation* freqshift = dynamic_cast<FrameTransformation*>(proc); 00258 wrapper->WrapFrameTransformation(freqshift); 00259 wrapper->mAmountCtrl.PublishInControl(freqshift->GetInControls().Get("Shift Steps")); 00260 // ConnectControls(*wrapper,"Out Control", *freqshift, "Shift Amount"); 00261 Insert( *wrapper ); 00262 return; 00263 } 00264 00265 if ( classname=="SMSSinusoidalGain") 00266 { 00267 SegmentTransformation* wrapper = new SegmentTransformation; 00268 Processing * proc = theFactory.Create(classname); 00269 FrameTransformation* singain = dynamic_cast<FrameTransformation*>(proc); 00270 wrapper->WrapFrameTransformation(singain); 00271 wrapper->mAmountCtrl.PublishInControl(singain->GetInControls().Get("Gain")); 00272 // ConnectControls(*wrapper,"Out Control", *singain, "Gain Amount"); 00273 Insert( *wrapper ); 00274 return; 00275 } 00276 00277 if ( classname=="SMSResidualGain") 00278 { 00279 SegmentTransformation* wrapper = new SegmentTransformation; 00280 Processing * proc = theFactory.Create(classname); 00281 FrameTransformation* resgain = dynamic_cast<FrameTransformation*>(proc); 00282 wrapper->WrapFrameTransformation(resgain); 00283 wrapper->mAmountCtrl.PublishInControl(resgain->GetInControls().Get("Gain")); 00284 // ConnectControls(*wrapper,"Out Control", *resgain, "Gain Amount"); 00285 Insert( *wrapper ); 00286 return; 00287 } 00288 00289 if ( classname=="SMSPitchShift") 00290 { 00291 SegmentTransformation* wrapper = new SegmentTransformation; 00292 Processing * proc = theFactory.Create(classname); 00293 FrameTransformation* pitchshift = dynamic_cast<FrameTransformation*>(proc); 00294 wrapper->WrapFrameTransformation(pitchshift); 00295 wrapper->mAmountCtrl.PublishInControl(pitchshift->GetInControls().Get("PitchSteps")); 00296 // ConnectControls(*wrapper,"Out Control", *pitchshift, "Shift Amount"); 00297 Insert( *wrapper ); 00298 return; 00299 } 00300 00301 if ( classname=="SMSOddEvenHarmonicRatio") 00302 { 00303 SegmentTransformation* wrapper = new SegmentTransformation; 00304 Processing * proc = theFactory.Create(classname); 00305 FrameTransformation* oddEvenHarmRatio = dynamic_cast<FrameTransformation*>(proc); 00306 wrapper->WrapFrameTransformation(oddEvenHarmRatio); 00307 wrapper->mAmountCtrl.PublishInControl(oddEvenHarmRatio->GetInControls().Get("Odd Factor")); 00308 // ConnectControls(*wrapper,"Out Control", *oddEvenHarmRatio, "Odd Harmonics Factor"); 00309 Insert( *wrapper ); 00310 return; 00311 } 00312 00313 if ( classname=="SMSSpectralShapeShift") 00314 { 00315 SegmentTransformation* wrapper = new SegmentTransformation; 00316 Processing * proc = theFactory.Create(classname); 00317 FrameTransformation* spectralShapeShift = dynamic_cast<FrameTransformation*>(proc); 00318 wrapper->WrapFrameTransformation(spectralShapeShift); 00319 wrapper->mAmountCtrl.PublishInControl(spectralShapeShift->GetInControls().Get("Shift Steps")); 00320 // ConnectControls(*wrapper,"Out Control", *spectralShapeShift, "Shift Amount"); 00321 Insert( *wrapper ); 00322 return; 00323 } 00324 00325 if ( classname=="SMSPitchDiscretization") 00326 { 00327 SegmentTransformation* wrapper = new SegmentTransformation; 00328 Processing * proc = theFactory.Create(classname); 00329 FrameTransformation* pitchDiscretization = dynamic_cast<FrameTransformation*>(proc); 00330 wrapper->WrapFrameTransformation(pitchDiscretization); 00331 Insert( *wrapper ); 00332 return; 00333 } 00334 00335 if ( classname=="SMSGenderChange") 00336 { 00337 SegmentTransformation* wrapper = new SegmentTransformation; 00338 Processing * proc = theFactory.Create(classname); 00339 FrameTransformation* genderChange = dynamic_cast<FrameTransformation*>(proc); 00340 wrapper->WrapFrameTransformation(genderChange); 00341 wrapper->mAmountCtrl.PublishInControl(genderChange->GetInControls().Get("Amount")); 00342 // ConnectControls(*wrapper,"Out Control", *genderChange, "Gender Factor"); 00343 Insert( *wrapper ); 00344 return; 00345 } 00346 00347 if ( classname=="SMSSineFilter") 00348 { 00349 SegmentTransformation* wrapper = new SegmentTransformation; 00350 Processing * proc = theFactory.Create(classname); 00351 FrameTransformation* sineFilter = dynamic_cast<FrameTransformation*>(proc); 00352 wrapper->WrapFrameTransformation(sineFilter); 00353 Insert( *wrapper ); 00354 return; 00355 } 00356 Insert( *( theFactory.Create( classname ) ) ); 00357 } 00359 void NextFrame() 00360 { 00361 mpChainInput->mCurrentFrameIndex++; 00362 } 00366 bool IsLastFrame() 00367 { 00368 for(iterator obj=composite_begin(); obj!=composite_end(); obj++) 00369 { 00370 SegmentTransformation* transf =dynamic_cast<SegmentTransformation*>((*obj)); 00371 if(!transf->IsLastFrame()) return false; 00372 } 00373 return true; 00374 00375 } 00376 00377 00378 }; 00379 00380 00381 } // namespace CLAM 00382 00383 #endif // _SMSTransformationChain_ 00384