SMSTransformationChain.hxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3