00001 #ifndef GAMMA_DFT_H_INC
00002 #define GAMMA_DFT_H_INC
00003
00004
00005
00006
00007 #include <math.h>
00008 #include "Gamma/mem.h"
00009 #include "Gamma/scl.h"
00010 #include "Gamma/tbl.h"
00011 #include "Gamma/Sync.h"
00012 #include "Gamma/Constants.h"
00013 #include "Gamma/Containers.h"
00014 #include "Gamma/FFT.h"
00015 #include "Gamma/Types.h"
00016
00017
00018 namespace gam{
00019
00020
00022 enum SpectralType{
00023 COMPLEX,
00024 MAG_PHASE,
00025 MAG_FREQ
00026 };
00027
00028
00029
00031 template <class T=gam::real>
00032 class SlidingWindow{
00033 public:
00034 SlidingWindow(uint32_t winSize, uint32_t hopSize);
00035 ~SlidingWindow();
00036
00037 void resize(uint32_t winSize, uint32_t hopSize);
00038 void sizeHop(uint32_t size);
00039 void sizeWin(uint32_t size);
00040
00041 uint32_t sizeHop() const;
00042 uint32_t sizeWin() const;
00043
00045
00048 const T * window();
00049 const T * operator()();
00050
00052 bool operator()(T input);
00053
00055
00058 bool operator()(T * dst, T input);
00059
00060 protected:
00061 void slide();
00062
00063
00064
00065 protected:
00066 T * mBuf;
00067 uint32_t mSizeWin, mSizeHop;
00068 uint32_t mTapW;
00069 uint32_t mHopCnt;
00070
00071 private:
00072 uint32_t hopStart() const;
00073 };
00074
00075
00076
00078 template <class T=gam::real>
00079 class DFTBase : public Synced{
00080 public:
00081 DFTBase();
00082 virtual ~DFTBase();
00083
00085 T * aux(uint32_t num);
00086
00088 Complex<T> * bins() const { return mBins; }
00089
00091 Complex<T>& bin(uint32_t k){ return mBins[k]; }
00092
00094 const Complex<T>& bin(uint32_t k) const { return mBins[k]; }
00095
00096 double binFreq() const;
00097 uint32_t numBins() const;
00098 uint32_t sizeDFT() const;
00099 Sync& syncFreq();
00100
00101 void numAux(uint32_t num);
00102
00103 virtual void onResync(double r);
00104
00105 protected:
00106 uint32_t mSizeDFT, mNumAux;
00107 union{
00108 T * mBuf;
00109 Complex<T> * mBins;
00110 };
00111 T * mAux;
00112 Sync mSyncFreq;
00113
00114 T normForward() const;
00115 T * bufPos(){ return mBuf+1; }
00116 T * bufFrq(){ return mBuf; }
00117 };
00118
00119
00120
00122 class DFT : public DFTBase<float>{
00123 public:
00125
00130 DFT(
00131 uint32_t winSize=1024, uint32_t padSize=0,
00132 SpectralType specType=COMPLEX,
00133 uint32_t numAux=0
00134 );
00135
00136 virtual ~DFT();
00137
00138
00140 DFT& spectrumType(SpectralType v);
00141
00143 DFT& precise(bool whether);
00144
00146 void resize(uint32_t windowSize, uint32_t padSize);
00147
00148 float freqRes() const;
00149 float overlap() const;
00150 bool overlapping() const;
00151 uint32_t sizeHop() const;
00152 uint32_t sizePad() const;
00153 uint32_t sizeWin() const;
00154
00155 Sync& syncHop();
00156
00158
00161 bool operator()(float input);
00162
00164
00167 float operator()();
00168
00170
00173 void forward(const float * src);
00174
00176
00181 virtual void inverse(float * dst);
00182
00184
00187 bool inverseOnNext();
00188
00189 void spctToRect();
00190 void spctToPolar();
00191 void zero();
00192 void zeroEnds();
00193
00194 virtual void onResync(double r);
00195 virtual void print(FILE * fp=stdout, const char * append="\n");
00196
00197 protected:
00198 uint32_t mSizeWin;
00199 uint32_t mSizeHop;
00200 SpectralType mSpctFormat;
00201 RFFT<float> mFFT;
00202 Sync mSyncHop;
00203
00204
00205 float * mPadOA;
00206 float * mBufInv;
00207 uint32_t mTapW, mTapR;
00208 bool mPrecise;
00209 };
00210
00211
00212
00213
00215
00220 class STFT : public DFT {
00221 public:
00222
00229 STFT(uint32_t winSize=1024, uint32_t hopSize=256, uint32_t padSize=0,
00230 WindowType winType = RECTANGLE,
00231 SpectralType specType = COMPLEX,
00232 uint32_t numAux=0
00233 );
00234
00235 virtual ~STFT();
00236
00237
00238 using DFT::operator();
00239 using DFT::sizeHop;
00240
00241
00243
00246 bool operator()(float input);
00247
00249 void forward(const float * src);
00250
00252 virtual void inverse(float * dst);
00253
00254
00256 void resize(uint32_t winSize, uint32_t padSize);
00257
00259 STFT& inverseWindowing(bool v){
00260 mWindowInverse=v; computeInvWinMul(); return *this; }
00261
00263 STFT& rotateForward(bool v){ mRotateForward=v; return *this; }
00264
00266 STFT& sizeHop(uint32_t size);
00267
00269 STFT& windowType(WindowType type);
00270
00271
00272 float unitsHop();
00273
00275 float * phases();
00276
00277 virtual void print(FILE * fp=stdout, const char * append="\n");
00278
00279 protected:
00280 void computeInvWinMul();
00281
00282 SlidingWindow<float> mSlide;
00283 float * mFwdWin;
00284 float * mPhases;
00285 WindowType mWinType;
00286 float mFwdWinMul, mInvWinMul;
00287 bool mWindowInverse;
00288 bool mRotateForward;
00289 };
00290
00291
00292
00293
00295
00299 template <class T>
00300 class SDFT : public DFTBase<T> {
00301 public:
00302
00306 SDFT(uint32_t sizeDFT, uint32_t binLo, uint32_t binHi);
00307
00309 void forward(T input);
00310
00312 SDFT& interval(uint32_t binLo, uint32_t binHi);
00313
00315 void resize(uint32_t sizeDFT, uint32_t binLo, uint32_t binHi);
00316
00317 protected:
00318 uint32_t mBinLo, mBinHi;
00319 DelayN<T> mDelay;
00320
00321 Complex<T> mF1;
00322 Complex<T> mFL;
00323
00324
00325 T mNorm;
00326 };
00327
00328
00329
00330
00331
00332
00333 #define TEM template<class T>
00334 TEM SlidingWindow<T>::SlidingWindow(uint32_t winSize, uint32_t hopSize)
00335 : mBuf(0), mSizeWin(0), mSizeHop(0), mHopCnt(0)
00336 {
00337 resize(winSize, hopSize);
00338 mem::deepZero(mBuf, sizeWin());
00339 }
00340
00341 TEM SlidingWindow<T>::~SlidingWindow(){
00342 if(mBuf){ free(mBuf); mBuf = 0; }
00343 }
00344
00345 TEM void SlidingWindow<T>::resize(uint32_t winSize, uint32_t hopSize){
00346 sizeWin(winSize);
00347 sizeHop(hopSize);
00348
00349 mTapW = 0;
00350 }
00351
00352 TEM void SlidingWindow<T>::sizeWin(uint32_t size){
00353 if(mem::resize(mBuf, sizeWin(), size)) mSizeWin = size;
00354 }
00355
00356 TEM void SlidingWindow<T>::sizeHop(uint32_t size){
00357 mSizeHop = scl::clip(size, sizeWin(), (uint32_t)1);
00358 }
00359
00360 TEM inline uint32_t SlidingWindow<T>::sizeHop() const { return mSizeHop; }
00361 TEM inline uint32_t SlidingWindow<T>::sizeWin() const { return mSizeWin; }
00362 TEM inline const T * SlidingWindow<T>::window(){ return mBuf; }
00363 TEM inline const T * SlidingWindow<T>::operator()(){ return mBuf; }
00364
00365 TEM inline bool SlidingWindow<T>::operator()(T input){
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 mBuf[mTapW] = input;
00377
00378 if(++mTapW >= sizeHop()){
00379 mTapW = 0;
00380 mem::rotateLeft(sizeHop(), mBuf, sizeWin());
00381 return true;
00382 }
00383 return false;
00384 }
00385
00386 TEM inline bool SlidingWindow<T>::operator()(T * output, T input){
00387 mBuf[mTapW] = input;
00388 if(++mTapW == sizeWin()) mTapW = 0;
00389
00390 if(++mHopCnt == sizeHop()){
00391 mem::copyAllFromRing(mBuf, sizeWin(), mTapW, output);
00392 mHopCnt = 0;
00393 return true;
00394 }
00395 return false;
00396 }
00397
00398 TEM inline void SlidingWindow<T>::slide(){
00399 mem::deepMove(mBuf, mBuf + sizeHop(), hopStart());
00400 }
00401
00402 TEM inline uint32_t SlidingWindow<T>::hopStart() const { return sizeWin() - sizeHop(); }
00403
00404
00405
00406
00407
00408 TEM DFTBase<T>::DFTBase() : mSizeDFT(0), mNumAux(0), mBuf(0), mAux(0){ initSynced(); }
00409
00410 TEM DFTBase<T>::~DFTBase(){
00411 mem::free(mBuf);
00412 mem::free(mAux);
00413 }
00414
00415 TEM inline T * DFTBase<T>::aux(uint32_t num){ return mAux + numBins() * num; }
00416 TEM inline double DFTBase<T>::binFreq() const { return spu() / (double)sizeDFT(); }
00417 TEM inline uint32_t DFTBase<T>::numBins() const { return (sizeDFT() + 2)>>1; }
00418 TEM inline uint32_t DFTBase<T>::sizeDFT() const { return mSizeDFT; }
00419 TEM inline Sync& DFTBase<T>::syncFreq(){ return mSyncFreq; }
00420 TEM inline T DFTBase<T>::normForward() const { return (T)2 / (T)sizeDFT(); }
00421
00422 TEM void DFTBase<T>::numAux(uint32_t num){
00423 if(mem::resize(mAux, mNumAux * numBins(), num * numBins())) mNumAux = num;
00424 }
00425
00426 TEM void DFTBase<T>::onResync(double r){
00427 mSyncFreq.ups(binFreq());
00428 }
00429
00430
00431
00432
00433
00434 inline DFT& DFT::spectrumType(SpectralType v){ mSpctFormat=v; return *this; }
00435 inline DFT& DFT::precise(bool w){ mPrecise=w; return *this; }
00436
00437 inline float DFT::freqRes() const { return spu() / sizeWin(); }
00438 inline float DFT::overlap() const { return float(sizeWin()) / sizeHop(); }
00439 inline bool DFT::overlapping() const { return sizeHop() < sizeWin(); }
00440 inline uint32_t DFT::sizeHop() const { return mSizeHop; }
00441 inline uint32_t DFT::sizePad() const { return mSizeDFT - mSizeWin; }
00442 inline uint32_t DFT::sizeWin() const { return mSizeWin; }
00443 inline Sync& DFT::syncHop(){ return mSyncHop; }
00444
00445 inline bool DFT::operator()(float input){
00446 bufPos()[mTapW] = input;
00447
00448 if(++mTapW >= sizeHop()){
00449 forward(bufPos());
00450 mTapW = 0;
00451 return true;
00452 }
00453 return false;
00454 }
00455
00456 inline float DFT::operator()(){
00457 if(++mTapR >= sizeHop()){
00458 inverse(0);
00459 mTapR = 0;
00460 }
00461 return mBufInv[mTapR];
00462 }
00463
00464 inline bool DFT::inverseOnNext(){ return mTapR == (sizeHop() - 1); }
00465 inline void DFT::zero(){ mem::deepZero(mBuf, sizeDFT() + 2); }
00466 inline void DFT::zeroEnds(){
00467
00468
00469 bins()[0](0,0);
00470 bins()[numBins()-1](0,0);
00471 }
00472
00473
00474
00475
00476 inline bool STFT::operator()(float input){
00477 if(mSlide(bufPos(), input)){
00478 forward(bufPos());
00479 return true;
00480 }
00481 return false;
00482 }
00483
00484 inline float STFT::unitsHop(){ return (float)DFT::sizeHop() * ups(); }
00485 inline float * STFT::phases(){ return mPhases; }
00486
00487
00488
00489
00490
00491 TEM SDFT<T>::SDFT(uint32_t sizeDFT, uint32_t binLo, uint32_t binHi)
00492 : DFTBase<T>(), mBinLo(0), mBinHi(0), mDelay(0)
00493 {
00494 resize(sizeDFT, binLo, binHi);
00495 }
00496
00497 TEM void SDFT<T>::resize(uint32_t sizeDFT, uint32_t binLo, uint32_t binHi){
00498
00499 mem::resize(this->mBuf, this->mSizeDFT + 2, sizeDFT + 2);
00500 mem::deepZero(this->mBuf, sizeDFT + 2);
00501
00502 mDelay.resize(sizeDFT);
00503 mDelay.assign(T(0));
00504
00505 this->mSizeDFT = sizeDFT;
00506
00507 interval(binLo, binHi);
00508
00509
00510 }
00511
00512 TEM SDFT<T>& SDFT<T>::interval(uint32_t binLo, uint32_t binHi){
00513 mBinLo = binLo;
00514 mBinHi = binHi;
00515
00516 double theta = M_2PI / this->sizeDFT();
00517
00518 mF1.fromPhase(theta);
00519 mFL.fromPhase(theta*mBinLo);
00520 mNorm = T(2) / T(this->sizeDFT());
00521 return *this;
00522 }
00523
00524
00525 TEM inline void SDFT<T>::forward(T input){
00526 T dif = (input - mDelay(input)) * mNorm;
00527
00528 Complex<T> c = mFL;
00529
00530
00531
00532
00533
00534 for(uint32_t k=mBinLo; k<mBinHi; ++k){
00535 Complex<T>& b = this->bins(k);
00536 b = b*c + dif;
00537 c *= mF1;
00538 }
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 #undef TEM
00566
00567 }
00568
00569 #endif
00570