|
CLAM-Development
1.3
|
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 "InControlArray.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 InControlArray mOnCtrlArray; 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 } 00071 virtual ~SMSTransformationChain(){ 00072 00073 for(int i=0;i<mpTmpDataArray.Size();i++) 00074 if(mpTmpDataArray[i]) delete mpTmpDataArray[i]; 00075 if (mpConfig) delete mpConfig; 00076 00077 for(iterator obj=composite_begin();obj!=composite_end();obj++) 00078 { 00079 delete (*obj); 00080 } 00081 } 00082 00083 virtual bool DoChildren() 00084 { 00085 CLAM_DEBUG_ASSERT(IsRunning(), 00086 "SMSTransformationChain: Do(): Not in execution mode"); 00087 00088 bool result=true; 00089 int i=0; 00090 //We iterate through all chainees and call their Do() 00091 for (iterator obj=composite_begin(); obj!=composite_end(); obj++,i++) 00092 { 00093 Processing & proc = *(*obj); 00094 SegmentTransformation& trans = dynamic_cast<SegmentTransformation&>(proc); 00095 //TODO have a list instead of being a composite 00096 00097 if(mOnCtrlArray[i].GetLastValue()||i==0||i==int(composite_size())-1) 00098 //Note: First and last chainee's will always be active regartheless the value 00099 //of their On control. 00100 { 00101 CLAM_DEBUG_ASSERT(proc.IsRunning(), "child is not running" ); 00102 result &= trans.DoWithSegments(); 00103 } 00104 } 00105 return result; 00106 } 00107 00108 bool Do() 00109 { 00110 if(IsLastFrame()) 00111 { 00112 printf("TransChain::Do() is last frame\n"); 00113 return false; 00114 } 00115 NextFrame(); 00116 return DoChildren(); 00117 } 00118 00119 bool ConcreteStart() 00120 { 00121 void InitSegmentArray(); 00122 00123 Segment* pCurrentData; 00124 pCurrentData=new Segment(*mpChainInput); 00125 mpTmpDataArray.AddElem(pCurrentData); 00126 00127 // set up connections: inSegment<--trans-->outSegment 00128 00129 iterator obj; 00130 for(obj=composite_begin();obj!=composite_end();obj++) 00131 { 00132 //connecting ports for non-supervised mode 00133 Processing & processing = *(*(obj)); 00134 SegmentTransformation&concreteObj = dynamic_cast<SegmentTransformation&>(processing); 00135 00136 concreteObj.AttachIn(*pCurrentData); 00137 if(!(*obj)->CanProcessInplace()) 00138 { 00139 printf("Can't process inplace: setting a temporal segment\n"); 00140 pCurrentData=new Segment(*mpChainInput); 00141 mpTmpDataArray.AddElem(pCurrentData); 00142 } 00143 concreteObj.AttachOut(*pCurrentData); 00144 } 00145 // now we have to restore the inSegment of the first child 00146 obj=composite_begin(); 00147 SegmentTransformation& concreteObj = dynamic_cast<SegmentTransformation&>( *(*(obj)) ); 00148 concreteObj.AttachIn(*mpChainInput); 00149 00150 obj=composite_end(); 00151 obj--; 00152 SegmentTransformation& concreteObj2 = dynamic_cast<SegmentTransformation&>( *(*(obj)) ); 00153 00154 concreteObj2.AttachOut( *mpChainOutput); 00155 00156 InitAllFrameIndex(); 00157 00158 return ProcessingComposite::ConcreteStart(); 00159 00160 } 00161 00162 void InitSegmentArray() 00163 { 00164 for(int i=0;i<mpTmpDataArray.Size();i++) 00165 if(mpTmpDataArray[i]) 00166 delete mpTmpDataArray[i]; 00167 mpTmpDataArray.SetSize(0); 00168 } 00169 00170 void InitAllFrameIndex() 00171 { 00172 for(int i=0;i<mpTmpDataArray.Size();i++) 00173 mpTmpDataArray[i]->mCurrentFrameIndex=0; 00174 mpChainInput->mCurrentFrameIndex=0; 00175 } 00176 00178 void TurnOn(TIndex index) 00179 { 00180 mOnCtrlArray[index].DoControl(1); 00181 } 00182 00184 void TurnOff(TIndex index) 00185 { 00186 mOnCtrlArray[index].DoControl(0); 00187 } 00188 00189 const ProcessingConfig& GetConfig() const 00190 { 00191 return *mpConfig; 00192 } 00193 00194 bool ConcreteConfigure(const ProcessingConfig& c) 00195 { 00196 mpConfig=new SMSTransformationChainConfig(dynamic_cast<const SMSTransformationChainConfig&>(c)); 00197 bool result=true; 00198 iterator obj; 00199 00201 obj=composite_begin(); 00202 while(obj!=composite_end()) 00203 { 00204 Remove(*(*obj)); 00205 obj=composite_begin(); 00206 } 00207 00208 SMSTransformationChainConfig::iterator cfg; 00209 for(cfg=mpConfig->ConfigList_begin();cfg!=mpConfig->ConfigList_end();cfg++) 00210 { 00211 AddChainee((*cfg).GetConcreteClassName()); 00212 obj=composite_end(); 00213 obj--; 00214 result&=(*obj)->Configure((*cfg).GetConcreteConfig()); 00215 } 00216 CLAM_ASSERT(mpConfig->GetConfigurations().size()==composite_size(),"Number of configurations should be the same as number of children"); 00217 00218 //TODO: right now there is no way to add or remove controls than to instantiate control array again 00219 CLAM_ASSERT(mpConfig->GetOnArray().Size()==(int)composite_size(),"SMSTransformationChain::ConcreteConfigure: On array does not have same size as number of configurations"); 00220 TSize nControls=composite_size(); 00221 mOnCtrlArray.Resize(nControls,"OnControlArray",this); 00222 00223 for(int i=0;i<nControls;i++) 00224 { 00225 mOnCtrlArray[i].DoControl(mpConfig->GetOnArray()[i]); 00226 } 00227 return result; 00228 } 00229 00233 SegmentTransformation* GetTransformation(const std::string& name) 00234 { 00235 for(iterator obj=composite_begin(); obj!=composite_end(); obj++) 00236 { 00237 if(name == (*obj)->GetClassName()) return dynamic_cast<SegmentTransformation*>((*obj));; 00238 } 00239 return NULL; 00240 } 00241 00242 00243 private: 00244 00245 void AddChainee(const std::string& classname) 00246 { 00247 //TODO: Instead of connecting controls, use the publishing mechanism 00248 //TODO2: If all amount controls were named the same I might be able to get rid of the string comparison 00249 ProcessingFactory & theFactory = ProcessingFactory::GetInstance(); 00250 00251 SegmentTransformation* wrapper = new SegmentTransformation; 00252 Processing * proc = theFactory.Create(classname); 00253 struct Supported 00254 { 00255 const char * name; 00256 const char * control; 00257 } supported[] = { 00258 {"SMSFreqShift", "Shift Steps"}, 00259 {"SMSSinusoidalGain", "Gain"}, 00260 {"SMSResidualGain", "Gain"}, 00261 {"SMSPitchShift", "PitchSteps"}, 00262 {"SMSOddEvenHarmonicRatio", "Odd Factor"}, 00263 {"SMSSpectralShapeShift", "Shift Steps"}, 00264 {"SMSPitchDiscretization", 0}, 00265 {"SMSGenderChange", "Amount"}, 00266 {"SMSSineFilter", 0}, 00267 {0,0} 00268 }; 00269 for (Supported * processing = supported; processing->name; processing ++) 00270 { 00271 if (classname != processing->name) continue; 00272 FrameTransformation * transformation = dynamic_cast<FrameTransformation*> (proc); 00273 wrapper->WrapFrameTransformation(transformation); 00274 if (processing->control) 00275 wrapper->mAmountCtrl.PublishInControl((FloatInControl&)proc->GetInControl(processing->control)); 00276 Insert( *wrapper ); 00277 return; 00278 } 00279 00280 delete wrapper; 00281 Insert( *proc ); 00282 } 00284 void NextFrame() 00285 { 00286 mpChainInput->mCurrentFrameIndex++; 00287 } 00291 bool IsLastFrame() 00292 { 00293 for(iterator obj=composite_begin(); obj!=composite_end(); obj++) 00294 { 00295 SegmentTransformation* transf =dynamic_cast<SegmentTransformation*>((*obj)); 00296 if(!transf->IsLastFrame()) return false; 00297 } 00298 return true; 00299 00300 } 00301 00302 00303 }; 00304 00305 00306 } // namespace CLAM 00307 00308 #endif // _SMSTransformationChain_ 00309
1.7.6.1