CLAM-Development  1.4.0
SMSTransformationChain.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #ifndef _SMSTransformationChain_
23 #define _SMSTransformationChain_
24 
25 
28 #include "ProcessingComposite.hxx"
29 #include "ProcessingData.hxx"
30 #include "InPort.hxx"
31 #include "OutPort.hxx"
32 #include "InControlArray.hxx"
33 #include "ProcessingFactory.hxx"
34 #include "Array.hxx"
35 
36 #include "FrameTransformation.hxx"
37 
38 namespace CLAM {
39 
45  {
46 
47  InControlArray mOnCtrlArray;
48 
50  Array<Segment*> mpTmpDataArray;
53  Segment* mpChainInput;
54  Segment* mpChainOutput;
55 
56 
57  public:
58 
59  void AttachIn(Segment& data) { mpChainInput = &data; }
60  void AttachOut(Segment& data) { mpChainOutput = &data; }
61 
63  mpChainInput(0),
64  mpChainOutput(0)
65  {
66  mpConfig=NULL;
67  }
72 
73  for(int i=0;i<mpTmpDataArray.Size();i++)
74  if(mpTmpDataArray[i]) delete mpTmpDataArray[i];
75  if (mpConfig) delete mpConfig;
76 
77  for(iterator obj=composite_begin();obj!=composite_end();obj++)
78  {
79  delete (*obj);
80  }
81  }
82 
83  virtual bool DoChildren()
84  {
86  "SMSTransformationChain: Do(): Not in execution mode");
87 
88  bool result=true;
89  int i=0;
90  //We iterate through all chainees and call their Do()
91  for (iterator obj=composite_begin(); obj!=composite_end(); obj++,i++)
92  {
93  Processing & proc = *(*obj);
94  SegmentTransformation& trans = dynamic_cast<SegmentTransformation&>(proc);
95  //TODO have a list instead of being a composite
96 
97  if(mOnCtrlArray[i].GetLastValue()||i==0||i==int(composite_size())-1)
98  //Note: First and last chainee's will always be active regartheless the value
99  //of their On control.
100  {
101  CLAM_DEBUG_ASSERT(proc.IsRunning(), "child is not running" );
102  result &= trans.DoWithSegments();
103  }
104  }
105  return result;
106  }
107 
108  bool Do()
109  {
110  if(IsLastFrame())
111  {
112  printf("TransChain::Do() is last frame\n");
113  return false;
114  }
115  NextFrame();
116  return DoChildren();
117  }
118 
120  {
121  void InitSegmentArray();
122 
123  Segment* pCurrentData;
124  pCurrentData=new Segment(*mpChainInput);
125  mpTmpDataArray.AddElem(pCurrentData);
126 
127  // set up connections: inSegment<--trans-->outSegment
128 
129  iterator obj;
130  for(obj=composite_begin();obj!=composite_end();obj++)
131  {
132  //connecting ports for non-supervised mode
133  Processing & processing = *(*(obj));
134  SegmentTransformation&concreteObj = dynamic_cast<SegmentTransformation&>(processing);
135 
136  concreteObj.AttachIn(*pCurrentData);
137  if(!(*obj)->CanProcessInplace())
138  {
139  printf("Can't process inplace: setting a temporal segment\n");
140  pCurrentData=new Segment(*mpChainInput);
141  mpTmpDataArray.AddElem(pCurrentData);
142  }
143  concreteObj.AttachOut(*pCurrentData);
144  }
145  // now we have to restore the inSegment of the first child
146  obj=composite_begin();
147  SegmentTransformation& concreteObj = dynamic_cast<SegmentTransformation&>( *(*(obj)) );
148  concreteObj.AttachIn(*mpChainInput);
149 
150  obj=composite_end();
151  obj--;
152  SegmentTransformation& concreteObj2 = dynamic_cast<SegmentTransformation&>( *(*(obj)) );
153 
154  concreteObj2.AttachOut( *mpChainOutput);
155 
157 
159 
160  }
161 
163  {
164  for(int i=0;i<mpTmpDataArray.Size();i++)
165  if(mpTmpDataArray[i])
166  delete mpTmpDataArray[i];
167  mpTmpDataArray.SetSize(0);
168  }
169 
171  {
172  for(int i=0;i<mpTmpDataArray.Size();i++)
173  mpTmpDataArray[i]->mCurrentFrameIndex=0;
174  mpChainInput->mCurrentFrameIndex=0;
175  }
176 
178  void TurnOn(TIndex index)
179  {
180  mOnCtrlArray[index].DoControl(1);
181  }
182 
184  void TurnOff(TIndex index)
185  {
186  mOnCtrlArray[index].DoControl(0);
187  }
188 
190  {
191  return *mpConfig;
192  }
193 
195  {
196  mpConfig=new SMSTransformationChainConfig(dynamic_cast<const SMSTransformationChainConfig&>(c));
197  bool result=true;
198  iterator obj;
199 
201  obj=composite_begin();
202  while(obj!=composite_end())
203  {
204  Remove(*(*obj));
205  obj=composite_begin();
206  }
207 
209  for(cfg=mpConfig->ConfigList_begin();cfg!=mpConfig->ConfigList_end();cfg++)
210  {
211  AddChainee((*cfg).GetConcreteClassName());
212  obj=composite_end();
213  obj--;
214  result&=(*obj)->Configure((*cfg).GetConcreteConfig());
215  }
216  CLAM_ASSERT(mpConfig->GetConfigurations().size()==composite_size(),"Number of configurations should be the same as number of children");
217 
218  //TODO: right now there is no way to add or remove controls than to instantiate control array again
219  CLAM_ASSERT(mpConfig->GetOnArray().Size()==(int)composite_size(),"SMSTransformationChain::ConcreteConfigure: On array does not have same size as number of configurations");
220  TSize nControls=composite_size();
221  mOnCtrlArray.Resize(nControls,"OnControlArray",this);
222 
223  for(int i=0;i<nControls;i++)
224  {
225  mOnCtrlArray[i].DoControl(mpConfig->GetOnArray()[i]);
226  }
227  return result;
228  }
229 
233  SegmentTransformation* GetTransformation(const std::string& name)
234  {
235  for(iterator obj=composite_begin(); obj!=composite_end(); obj++)
236  {
237  if(name == (*obj)->GetClassName()) return dynamic_cast<SegmentTransformation*>((*obj));;
238  }
239  return NULL;
240  }
241 
242 
243  private:
244 
245  void AddChainee(const std::string& classname)
246  {
247  //TODO: Instead of connecting controls, use the publishing mechanism
248  //TODO2: If all amount controls were named the same I might be able to get rid of the string comparison
250 
252  Processing * proc = theFactory.Create(classname);
253  struct Supported
254  {
255  const char * name;
256  const char * control;
257  } supported[] = {
258  {"SMSFreqShift", "Shift Steps"},
259  {"SMSSinusoidalGain", "Gain"},
260  {"SMSResidualGain", "Gain"},
261  {"SMSPitchShift", "PitchSteps"},
262  {"SMSOddEvenHarmonicRatio", "Odd Factor"},
263  {"SMSSpectralShapeShift", "Shift Steps"},
264  {"SMSPitchDiscretization", 0},
265  {"SMSGenderChange", "Amount"},
266  {"SMSSineFilter", 0},
267  {0,0}
268  };
269  for (Supported * processing = supported; processing->name; processing ++)
270  {
271  if (classname != processing->name) continue;
272  FrameTransformation * transformation = dynamic_cast<FrameTransformation*> (proc);
273  wrapper->WrapFrameTransformation(transformation);
274  if (processing->control)
275  wrapper->mAmountCtrl.PublishInControl((FloatInControl&)proc->GetInControl(processing->control));
276  Insert( *wrapper );
277  return;
278  }
279 
280  delete wrapper;
281  Insert( *proc );
282  }
284  void NextFrame()
285  {
286  mpChainInput->mCurrentFrameIndex++;
287  }
291  bool IsLastFrame()
292  {
293  for(iterator obj=composite_begin(); obj!=composite_end(); obj++)
294  {
295  SegmentTransformation* transf =dynamic_cast<SegmentTransformation*>((*obj));
296  if(!transf->IsLastFrame()) return false;
297  }
298  return true;
299 
300  }
301 
302 
303  };
304 
305 
306 } // namespace CLAM
307 
308 #endif // _SMSTransformationChain_
309