CLAM-Development  1.4.0
TokenDelay.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 // TokenDelay.hxx
23 
24 #ifndef _TokenDelay_
25 #define _TokenDelay_
26 
27 #include "Processing.hxx"
28 #include "InControl.hxx"
29 #include "InPort.hxx"
30 #include "OutPort.hxx"
31 #include "Component.hxx"
32 #include "Enum.hxx"
33 #include <string>
34 #include <deque>
35 
36 #include "Array.hxx"
37 
38 namespace CLAM
39 {
40 
41 
47 {
48 public:
50  DYN_ATTRIBUTE (0, public, unsigned, Delay);
51  DYN_ATTRIBUTE (1, public, unsigned, MaxDelay );
52 protected:
53  void DefaultInit(void)
54  {
55  AddDelay();
56  AddMaxDelay();
57  UpdateData();
58  SetDelay(0);
59  SetMaxDelay(1);
60  }
61 
62 };
63 
76 template <class T> class TokenDelay : public Processing
77 {
78 
79 private:
81  TokenDelayConfig mConfig;
82  // Ports and control
83  InPort<T> mInput;
84  OutPort<T> mOutput;
85  FloatInControl mDelayControl;
86 
87 public:
89  mInput ("In", this),
90  mOutput ("Out", this),
91  mDelayControl("Delay Control", this),
92  mCapacity(0)
93  {
94  Configure(cfg);
95  }
96  virtual ~TokenDelay<T>() {};
97 
103  bool ConcreteConfigure(const ProcessingConfig& c);
104 
108  virtual const ProcessingConfig &GetConfig() const { return mConfig;}
113  virtual bool Do(void);
114 
124  virtual bool Do(const T & in, T& out);
125 
126 
127 
130  void Debug() const;
134  void FulfillsInvariant() const;
135 
136  const char *GetClassName() const {return "TokenDelay";}
137 
141  TSize RealDelay() const {
142  return mTokenQueue.size();
143  }
144 
145  unsigned MaxDelay() const {
146  return mCapacity;
147  }
148 
149  unsigned GivenDelay() {
150 
151  return CastDelayControlValue(mDelayControl.GetLastValue());
152  }
153 
154 private:
160  virtual void Discard(T* toDiscard);
161 
165  unsigned CastDelayControlValue(TControlData readControlValue);
170  void UpdateBuffersToDelay();
171  void WriteNewSample(const T& in);
172  void ReadCurrentSample(T& out);
173 
174 // Implementation Details:
175 
176  std::vector<T> mTokenQueue;
177  unsigned mReadPointer;
178  unsigned mWritePointer;
180  unsigned mCapacity;
182  unsigned mGivenDelay;
184  unsigned mLastDelay;
185 
186 };
187 
188 
189 
191 // Class implementation
192 
193 
194 #include "Err.hxx"
195 
196 template <class T>
197 void TokenDelay<T>::Discard(T* toDiscard) {
198  CLAM_ASSERT(toDiscard, "TokenDelay: Discarding a null pointer");
199  delete toDiscard;
200 }
201 
202 template <class T>
204 {
205  CopyAsConcreteConfig(mConfig, c);
206  // TODO: Put some sanity checks on the configuration here
207  mCapacity = mConfig.GetMaxDelay();
208  mDelayControl.DoControl(TControlData(mConfig.GetDelay()));
209  mGivenDelay = CastDelayControlValue(mDelayControl.GetLastValue());
210  mTokenQueue.resize(mCapacity);
211  mWritePointer = 0;
212  mReadPointer = -mGivenDelay;
213  return true;
214 }
215 
216 
217 template <class T>
219 {
220  Do(mInput.GetData(), mOutput.GetData());
221  mInput.Consume();
222  mOutput.Produce();
223  return false;
224 }
225 
226 template <class T>
227 unsigned TokenDelay<T>::CastDelayControlValue(TControlData readControlValue) {
228  if (readControlValue > mCapacity) return mCapacity;
229  if (readControlValue < 0) return 0;
230  return unsigned(readControlValue);
231 }
232 
233 template <class T>
234 bool TokenDelay<T>::Do(const T& in, T& out)
235 // implementation using the supervised-mode Do
236 {
237  // @todo debug
238  mLastDelay = mGivenDelay;
239  mGivenDelay = CastDelayControlValue(mDelayControl.GetLastValue());
240  // If the value is different make the difference efective
241  if (mLastDelay != mGivenDelay)
242  UpdateBuffersToDelay();
243  WriteNewSample(in);
244  ReadCurrentSample(out);
245  return true;
246 }
247 
248 template <class T>
249 void TokenDelay<T>::WriteNewSample(const T& in)
250 {
251  mTokenQueue[mWritePointer++] = in;
252  if(mWritePointer==mCapacity) mWritePointer=0;
253 
254 }
255 
256 
257 template <class T>
258 void TokenDelay<T>::ReadCurrentSample(T& out)
259 {
260  CLAM_DEBUG_ASSERT(mReadPointer>=0, "Trying to read outside buffer");
261  out = mTokenQueue[mReadPointer++];
262  if(mReadPointer==mCapacity) mReadPointer=0;
263 }
264 
265 
266 
267 // Delay change
268 template <class T>
269 void TokenDelay<T>::UpdateBuffersToDelay()
270 {
271  mWritePointer = mReadPointer + CastDelayControlValue(mGivenDelay);
272  if(mWritePointer>=mCapacity) mWritePointer-=mCapacity;
273  return;
274 }
275 
276 
277 template <class T>
279 {
280  /*
281  unsigned real = RealDelay();
282  unsigned size = mVector.size();
283  unsigned cap = mVector.capacity();
284 
285  std::cout << "\n-- " << mConfig.GetClassName() << "\n-- (first,last)=(" << mFirst <<","<< mLast <<")\n-- "\
286  << "(given,real delay)=("<< mGivenDelay <<"," << real << ")\n-- (vector size,capacity;mCapacity)=("\
287  << size <<","<< cap <<";"<< mCapacity <<")\n-- (mInstantToken,mVector[mFirst])=("<< mInstantToken\
288  <<","<< mVector[mFirst] <<")\n";
289  */
290 
291 }
292 
293 template <class T>
295 {/*
296  unsigned real = RealDelay();
297 
298  if (mVector.capacity() < mCapacity) throw Err("TokenDelay : invariant not fullfilled!: vector capacity < req. capacity");
299  if (real && mFirst==mLast) throw Err("TokenDelay : invariant not fullfilled!: there is a 'real' delay and mFirst==mLast");
300  if (real > mCapacity) throw Err("TokenDelay : invariant not fullfilled!: real delay > mCapacity");
301  if (mGivenDelay > mCapacity) throw Err("TokenDelay : invariant not fullfilled!: given (by control) delay > mCapacity");
302  if (mFirst <0 || mLast<0 || mCapacity <= 0) throw Err("TokenDelay : invariant not fullfilled!: some very bad thing...");
303 */
304 }
305 
306 }; //namespace CLAM
307 
308 
309 
310 #endif //_TokenDelay_