|
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 // TokenDelay.hxx 00023 00024 #ifndef _TokenDelay_ 00025 #define _TokenDelay_ 00026 00027 #include "Processing.hxx" 00028 #include "InControl.hxx" 00029 #include "InPort.hxx" 00030 #include "OutPort.hxx" 00031 #include "Component.hxx" 00032 #include "Enum.hxx" 00033 #include <string> 00034 #include <deque> 00035 00036 #include "Array.hxx" 00037 00038 namespace CLAM 00039 { 00040 00041 00046 class TokenDelayConfig : public ProcessingConfig 00047 { 00048 public: 00049 DYNAMIC_TYPE_USING_INTERFACE (TokenDelayConfig, 2, ProcessingConfig); 00050 DYN_ATTRIBUTE (0, public, unsigned, Delay); 00051 DYN_ATTRIBUTE (1, public, unsigned, MaxDelay ); 00052 protected: 00053 void DefaultInit(void) 00054 { 00055 AddDelay(); 00056 AddMaxDelay(); 00057 UpdateData(); 00058 SetDelay(0); 00059 SetMaxDelay(1); 00060 } 00061 00062 }; 00063 00076 template <class T> class TokenDelay : public Processing 00077 { 00078 00079 private: 00081 TokenDelayConfig mConfig; 00082 // Ports and control 00083 InPort<T> mInput; 00084 OutPort<T> mOutput; 00085 FloatInControl mDelayControl; 00086 00087 public: 00088 TokenDelay(const TokenDelayConfig& cfg = TokenDelayConfig() ) : 00089 mInput ("In", this), 00090 mOutput ("Out", this), 00091 mDelayControl("Delay Control", this), 00092 mCapacity(0) 00093 { 00094 Configure(cfg); 00095 } 00096 virtual ~TokenDelay<T>() {}; 00097 00103 bool ConcreteConfigure(const ProcessingConfig& c); 00104 00108 virtual const ProcessingConfig &GetConfig() const { return mConfig;} 00113 virtual bool Do(void); 00114 00124 virtual bool Do(const T & in, T& out); 00125 00126 00127 00130 void Debug() const; 00134 void FulfillsInvariant() const; 00135 00136 const char *GetClassName() const {return "TokenDelay";} 00137 00141 TSize RealDelay() const { 00142 return mTokenQueue.size(); 00143 } 00144 00145 unsigned MaxDelay() const { 00146 return mCapacity; 00147 } 00148 00149 unsigned GivenDelay() { 00150 00151 return CastDelayControlValue(mDelayControl.GetLastValue()); 00152 } 00153 00154 private: 00160 virtual void Discard(T* toDiscard); 00161 00165 unsigned CastDelayControlValue(TControlData readControlValue); 00170 void UpdateBuffersToDelay(); 00171 void WriteNewSample(const T& in); 00172 void ReadCurrentSample(T& out); 00173 00174 // Implementation Details: 00175 00176 std::vector<T> mTokenQueue; 00177 unsigned mReadPointer; 00178 unsigned mWritePointer; 00180 unsigned mCapacity; 00182 unsigned mGivenDelay; 00184 unsigned mLastDelay; 00185 00186 }; 00187 00188 00189 00191 // Class implementation 00192 00193 00194 #include "Err.hxx" 00195 00196 template <class T> 00197 void TokenDelay<T>::Discard(T* toDiscard) { 00198 CLAM_ASSERT(toDiscard, "TokenDelay: Discarding a null pointer"); 00199 delete toDiscard; 00200 } 00201 00202 template <class T> 00203 bool TokenDelay<T>::ConcreteConfigure(const ProcessingConfig& c) 00204 { 00205 CopyAsConcreteConfig(mConfig, c); 00206 // TODO: Put some sanity checks on the configuration here 00207 mCapacity = mConfig.GetMaxDelay(); 00208 mDelayControl.DoControl(TControlData(mConfig.GetDelay())); 00209 mGivenDelay = CastDelayControlValue(mDelayControl.GetLastValue()); 00210 mTokenQueue.resize(mCapacity); 00211 mWritePointer = 0; 00212 mReadPointer = -mGivenDelay; 00213 return true; 00214 } 00215 00216 00217 template <class T> 00218 bool TokenDelay<T>::Do(void) 00219 { 00220 Do(mInput.GetData(), mOutput.GetData()); 00221 mInput.Consume(); 00222 mOutput.Produce(); 00223 return false; 00224 } 00225 00226 template <class T> 00227 unsigned TokenDelay<T>::CastDelayControlValue(TControlData readControlValue) { 00228 if (readControlValue > mCapacity) return mCapacity; 00229 if (readControlValue < 0) return 0; 00230 return unsigned(readControlValue); 00231 } 00232 00233 template <class T> 00234 bool TokenDelay<T>::Do(const T& in, T& out) 00235 // implementation using the supervised-mode Do 00236 { 00237 // @todo debug 00238 mLastDelay = mGivenDelay; 00239 mGivenDelay = CastDelayControlValue(mDelayControl.GetLastValue()); 00240 // If the value is different make the difference efective 00241 if (mLastDelay != mGivenDelay) 00242 UpdateBuffersToDelay(); 00243 WriteNewSample(in); 00244 ReadCurrentSample(out); 00245 return true; 00246 } 00247 00248 template <class T> 00249 void TokenDelay<T>::WriteNewSample(const T& in) 00250 { 00251 mTokenQueue[mWritePointer++] = in; 00252 if(mWritePointer==mCapacity) mWritePointer=0; 00253 00254 } 00255 00256 00257 template <class T> 00258 void TokenDelay<T>::ReadCurrentSample(T& out) 00259 { 00260 CLAM_DEBUG_ASSERT(mReadPointer>=0, "Trying to read outside buffer"); 00261 out = mTokenQueue[mReadPointer++]; 00262 if(mReadPointer==mCapacity) mReadPointer=0; 00263 } 00264 00265 00266 00267 // Delay change 00268 template <class T> 00269 void TokenDelay<T>::UpdateBuffersToDelay() 00270 { 00271 mWritePointer = mReadPointer + CastDelayControlValue(mGivenDelay); 00272 if(mWritePointer>=mCapacity) mWritePointer-=mCapacity; 00273 return; 00274 } 00275 00276 00277 template <class T> 00278 void TokenDelay<T>::Debug() const 00279 { 00280 /* 00281 unsigned real = RealDelay(); 00282 unsigned size = mVector.size(); 00283 unsigned cap = mVector.capacity(); 00284 00285 std::cout << "\n-- " << mConfig.GetClassName() << "\n-- (first,last)=(" << mFirst <<","<< mLast <<")\n-- "\ 00286 << "(given,real delay)=("<< mGivenDelay <<"," << real << ")\n-- (vector size,capacity;mCapacity)=("\ 00287 << size <<","<< cap <<";"<< mCapacity <<")\n-- (mInstantToken,mVector[mFirst])=("<< mInstantToken\ 00288 <<","<< mVector[mFirst] <<")\n"; 00289 */ 00290 00291 } 00292 00293 template <class T> 00294 void TokenDelay<T>::FulfillsInvariant() const 00295 {/* 00296 unsigned real = RealDelay(); 00297 00298 if (mVector.capacity() < mCapacity) throw Err("TokenDelay : invariant not fullfilled!: vector capacity < req. capacity"); 00299 if (real && mFirst==mLast) throw Err("TokenDelay : invariant not fullfilled!: there is a 'real' delay and mFirst==mLast"); 00300 if (real > mCapacity) throw Err("TokenDelay : invariant not fullfilled!: real delay > mCapacity"); 00301 if (mGivenDelay > mCapacity) throw Err("TokenDelay : invariant not fullfilled!: given (by control) delay > mCapacity"); 00302 if (mFirst <0 || mLast<0 || mCapacity <= 0) throw Err("TokenDelay : invariant not fullfilled!: some very bad thing..."); 00303 */ 00304 } 00305 00306 }; //namespace CLAM 00307 00308 00309 00310 #endif //_TokenDelay_
1.7.6.1