transform.h

00001 /******** Digital signal processing library v0.01 ********
00002                 
00003                 Header file Transform.h
00004         Contains interfaces for abstract class ITransform, 
00005         Template classes: WFastHT, WFastFT, WFastWT
00006                                      WIFastHT
00007                                     
00008                 Template class WFastHT - implements algorighm of 
00009         Fast Haara's Transformation (by Anatoly Beletsky). Template has to type parameters:
00010                 T_in            - type of input values (input signal)
00011                 T_out   - type of output values (spectrum).     
00012         Input signal has any type(int,double, complex<T> ).
00013         Spectrum is double or complex.
00014         
00015                 Template class WIFastHT - implements algorithm of
00016         Inverse Fast Haara's Transformation.
00017         
00018                 Template class WFastFT - implements algorithm of
00019         Fast Fourier Transformation (Tim Kientzle "A Programmers Guide To Sound"
00020         Copyright (c) 1998 Tim Kientzle)
00021         
00022                 Template class WFastWT - implements algorihtm of
00023         Fast Walsh's Transformation in different basises.
00024                 HADOMARD - Walshs-Hadomars basis
00025                 PELEY      - Peleys basis
00026                 WALSH      - "classical" basis
00027                 COLEY      - Coleys basis (discovered by Anatoly Belestky in 1999)
00028 
00029 Alexander Beletsky
00030 e-mail:  albel@pochtamt.ru
00031 
00032 À.À. Beletsky 2002(c)
00033 *********************************************************/
00034 
00035 #ifndef Transform_H
00036 #define Transform_H
00037 
00038 #include <cmath>
00039 #include <complex>
00040 using namespace std;
00041 
00042 
00043 #include "transerr.h"
00044 
00045 const double PI = 3.14159265358979323846264338;
00046 //Basises of Fast Walshs Transformation
00047 enum WBasis {
00048         HADOMARD,       
00049         PELEY,          
00050         WALSH,          
00051         COOLEY
00052 };
00053 
00054 //--------------------------------------------------------------
00055 
00056 template < class T_in, class T_out >
00057 class ITransform {
00058 public:
00059         virtual void setData( T_in *dat ) = 0;
00060         virtual void doTransform() = 0;
00061 };
00062 
00063 //--------------------------------------------------------------
00064 
00065 // Template class WFastHT
00066 template< class T_in, class T_out >
00067 class WFastHT : public ITransform< T_in, T_out > {
00068 public:
00069         WFastHT( uint N_par = 8 );
00070         void setData( T_in *dat );
00071         void doTransform();
00072         T_out *getSpectrum();
00073         virtual ~WFastHT();
00074 private:
00075         void regroupe();
00076         void multiply();
00077         uint binInv( uint index );
00078         T_out *spectrum;
00079         T_out *aux;
00080         uint N, m;
00081         bool noData;
00082 };
00083 
00084 template< class T_in, class T_out >
00085 WFastHT< T_in, T_out >::WFastHT( uint N_par ) : N( N_par ), noData( true )
00086 {
00087         //is N binary rational?
00088         if( ((~N + 1)&N) != N ) {
00089                 throw TransError::badNValue();
00090         }
00091         //Log(n) - computation
00092         int count = 0;
00093         for(int check = N_par; (check&1) == 0 ; count++, check >>= 1 );
00094         m = count;
00095 
00096         spectrum = new T_out[N];
00097         aux = new T_out[N];
00098 }
00099 
00100 template< class T_in, class T_out >
00101 WFastHT< T_in, T_out >::~WFastHT()
00102 {
00103         delete [] spectrum;
00104         delete [] aux;
00105 }
00106 
00107 template< class T_in, class T_out >
00108 void WFastHT< T_in, T_out >::setData( T_in *dat )
00109 {
00110         if( dat != 0 ) {
00111                 for(int i = 0; i < N; i++ ) aux[i] = static_cast< T_out >( dat[i] );
00112                 noData = false;
00113         }
00114         else throw TransError::noData();
00115 }
00116 
00117 template< class T_in, class T_out >
00118 void WFastHT< T_in, T_out >::doTransform()
00119 {
00120         if( noData )
00121                 throw TransError::noData();
00122         else {
00123         //Spectrum computation
00124         for( int stage = 0, make = N/2, turn = 1; stage < m; stage++, make /= 2, turn *= 2 ) {
00125                 for( int step = 0; step < make; step++ ) {
00126                         //"butterfly" operation
00127                         T_out A = aux[2*turn*step] - aux[2*turn*step + turn];           
00128                         aux[2*turn*step] += aux[2*turn*step + turn];
00129                         aux[2*turn*step + turn] = A;
00130                 }
00131         }
00132         //Regrouping of harmonics
00133         regroupe();
00134         //Multiplication with nessesary coeffisients
00135         multiply();
00136         }
00137 }
00138 
00139 template< class T_in, class T_out >
00140 T_out *WFastHT< T_in, T_out>::getSpectrum()
00141 {
00142         return spectrum;
00143 }
00144 
00145 template< class T_in, class T_out >
00146 void WFastHT< T_in, T_out >::regroupe() 
00147 {
00148         //Regroping of harmonics
00149 
00150         for( uint i = 0, k = 0; i < N; i++ ) {
00151                 if( i < N/2 ) {
00152                         spectrum[i] = aux[ binInv( i ) ];
00153                 }
00154                 else {
00155                         spectrum[i] = aux[2*k + 1];
00156                         k++;
00157                 }
00158         }
00159 }
00160 
00161 template< class T_in, class T_out >
00162 void WFastHT< T_in, T_out >::multiply()
00163 {
00164         spectrum[0] /= N;
00165         spectrum[1] /= N;
00166         
00167         double S = sqrt(2.0), coeff = 1;
00168         for(int i = 1, l_1 = 2, l_2 = l_1*2; i < m; i++, l_1 *= 2, l_2 = l_1*2 ) {
00169                 coeff *= S;
00170                 for(int j = l_1; j < l_2; j++) {
00171                         spectrum[j] *= coeff;
00172                         spectrum[j] /= N;
00173                 }
00174         }
00175 }
00176 
00177 //Binary inversion operation
00178 template< class T_in, class T_out >
00179 uint WFastHT< T_in, T_out >::binInv( uint index )
00180 {
00181         uint LMASK = 1, RMASK = N >> 1, inverse = index;
00182         bool nextIter = true;
00183         
00184         while( nextIter ) {
00185                 if( LMASK == RMASK ) nextIter = false;
00186                 if( ( (index & LMASK) == 0 ) && ( (index & RMASK) == 0) ||
00187                         ( (index & LMASK) != 0 ) && ( (index & RMASK) != 0) ) {
00188                 //return inverse;
00189                 }
00190                 else {
00191                         if( (index & LMASK) == LMASK ) {
00192                                 inverse |= RMASK;
00193                                 inverse &= ~LMASK;
00194                         }
00195                         else {
00196                                 if( (index & RMASK) == RMASK ) {
00197                                         inverse |= LMASK;
00198                                         inverse &= ~RMASK;
00199                                 }
00200                         }
00201                 }
00202                 LMASK <<= 1;
00203                 RMASK >>= 1;
00204         }
00205         return inverse;
00206 }
00207 
00208 //--------------------------------------------------------------
00209 
00210 //Template class WIFastFT
00211 template< class T_in >
00212 class WFastFT : public ITransform< T_in, complex< double > > {
00213 public:
00214         WFastFT( uint N_par = 8 );
00215         void setData( T_in *dat );
00216         void doTransform();
00217         complex< double > *getSpectrum();
00218         virtual ~WFastFT();
00219 private:
00220         void regroupe();
00221         uint binInv( uint index ); 
00222         T_in *inputData;
00223         complex< double > *spectrum;
00224         uint N;
00225         bool noData;
00226 };
00227 
00228 template< class T_in >
00229 WFastFT< T_in >::WFastFT( uint N_par ) : N( N_par ), noData( true )
00230 {
00231         if( ((~N + 1)&N) != N ) {
00232                 throw TransError::badNValue();
00233         }
00234 
00235         spectrum = new complex< double >[N];
00236 }
00237 
00238 template< class T_in >
00239 WFastFT< T_in >::~WFastFT()
00240 {
00241         delete [] spectrum;
00242 }
00243 
00244 template< class T_in >
00245 void WFastFT< T_in >::setData( T_in *dat )
00246 {
00247         if( dat != 0 ) {
00248                 inputData = dat;
00249 
00250                 regroupe();
00251                 noData = false;
00252         }
00253         else throw TransError::noData();
00254 }
00255 
00256 template< class T_in >
00257 void WFastFT< T_in >::doTransform()
00258 {
00259         if( noData )
00260                 throw TransError::noData();
00261         else {
00262                 for( uint halfSize = 1; halfSize < N; halfSize *= 2) {
00263                         complex< double > phaseShiftStep = polar( 1.0 , -PI/halfSize );
00264                         complex< double > currentPhaseShift = polar( 1.0 );
00265                         for( uint fftStep = 0; fftStep < halfSize; fftStep++ ) {
00266                                 for( uint i = fftStep; i < N; i += 2*halfSize ) {
00267                                         complex< double > A = currentPhaseShift * spectrum[i + halfSize];
00268                                         spectrum[i + halfSize] = spectrum[i] - A;
00269                                         spectrum[i] += A;
00270                                 }
00271                                 currentPhaseShift *= phaseShiftStep;
00272                         }
00273                 }
00274         }
00275 }
00276 
00277 template< class T_in >
00278 complex< double > *WFastFT< T_in >::getSpectrum()
00279 {
00280         return spectrum;
00281 }
00282 
00283 template< class T_in >
00284 void WFastFT< T_in >::regroupe()
00285 {
00286         for( uint i = 0; i < N; i++ ) {
00287                 spectrum[i] = static_cast< complex< double > >( inputData[ binInv( i ) ] );
00288         }
00289 }
00290 
00291 template< class T_in >
00292 uint WFastFT< T_in >::binInv( uint index  )
00293 {
00294         uint LMASK = 1, RMASK = N >> 1, inverse = index;
00295         bool nextIter = true;
00296         
00297         while( nextIter ) {
00298                 if( LMASK == RMASK ) nextIter = false;
00299                 if( ( (index & LMASK) == 0 ) && ( (index & RMASK) == 0) ||
00300                         ( (index & LMASK) != 0 ) && ( (index & RMASK) != 0) ) {
00301                 //return inverse;
00302                 }
00303                 else {
00304                         if( (index & LMASK) == LMASK ) {
00305                                 inverse |= RMASK;
00306                                 inverse &= ~LMASK;
00307                         }
00308                         else {
00309                                 if( (index & RMASK) == RMASK ) {
00310                                         inverse |= LMASK;
00311                                         inverse &= ~RMASK;
00312                                 }
00313                         }
00314                 }
00315                 LMASK <<= 1;
00316                 RMASK >>= 1;
00317         }
00318         return inverse;
00319 }
00320 
00321 //--------------------------------------------------------------
00322 
00323 //Template class WFastWT
00324 template < class T_in, class T_out >
00325 class WFastWT : ITransform< T_in, T_out > {
00326 public:
00327         WFastWT( uint N_par = 8, WBasis bas = HADOMARD );
00328         void setData( T_in *dat );
00329         void doTransform();
00330         T_out *getSpectrum();
00331         virtual ~WFastWT();
00332 private:
00333         void regroupe();
00334         uint binInv( uint index );
00335         uint binInvGCL( uint index );
00336         uint binInvGCR( uint index );
00337         T_in *inputData;
00338         T_out *spectrum;
00339         uint N;
00340         WBasis basis;
00341         bool noData;
00342 };
00343 
00344 template< class T_in, class T_out >
00345 WFastWT< T_in, T_out>::WFastWT( uint N_par, WBasis bas ) : N( N_par ), basis( bas ),
00346                                                                                                                         noData( true )
00347 {
00348         if( ((~N + 1)&N) != N ) {
00349                 throw TransError::badNValue();
00350         }
00351 
00352         spectrum = new T_out[N];
00353 }
00354 
00355 template< class T_in, class T_out >
00356 WFastWT< T_in, T_out >::~WFastWT()
00357 {
00358         delete [] spectrum;
00359 }
00360 
00361 template< class T_in, class T_out >
00362 void WFastWT< T_in, T_out >::setData( T_in *dat )
00363 {
00364         if( dat != 0 ) {
00365                 inputData = dat;
00366 
00367                 regroupe();
00368                 noData = false;
00369         }
00370         else throw TransError::noData();
00371 }
00372 
00373 template< class T_in, class T_out >
00374 void WFastWT< T_in, T_out >::doTransform()
00375 {
00376         if( noData ) {
00377                 throw TransError::noData();
00378         }
00379         else {
00380                 for( int halfSize = 1; halfSize < N; halfSize *= 2) {
00381                         for( int fwtStep = 0; fwtStep < halfSize; fwtStep++ ) {
00382                                 for( int i = fwtStep; i < N; i += 2*halfSize ) {
00383                                         T_out A = spectrum[i + halfSize];
00384                                         spectrum[i + halfSize] = spectrum[i] - A;
00385                                         spectrum[i] += A;
00386                                 }
00387                         }
00388                 }
00389         }
00390 }
00391 
00392 template< class T_in, class T_out >
00393 T_out *WFastWT< T_in, T_out >::getSpectrum()
00394 {
00395         return spectrum;
00396 }
00397 
00398 template< class T_in, class T_out >
00399 void WFastWT< T_in, T_out >::regroupe()
00400 {
00401         int i;
00402         switch( basis ) {
00403         case HADOMARD:
00404                 for( i = 0; i < N; i++ ) {
00405                         spectrum[i] = static_cast< T_out >( inputData[i] );
00406                 }
00407                 break;
00408         case PELEY:
00409                 for( i = 0; i < N; i++ ) {
00410                         spectrum[i] = static_cast< T_out >( inputData[ binInv( i ) ] );
00411                 }
00412                 break;
00413         case WALSH:
00414                 for( i = 0; i < N; i++ ) {
00415                         int newI = binInv( i );
00416                         spectrum[i] = static_cast< T_out >( inputData[ binInvGCL( newI ) ] );
00417                 }
00418                 break;
00419         case COOLEY:
00420                 for( i = 0; i < N; i++ ) {
00421                         int newI = binInv( i );
00422                         spectrum[i] = static_cast< T_out >( inputData[ binInvGCR( newI ) ] );
00423                 }
00424                 break;
00425         default:
00426                 throw TransError::noSuchBasis();
00427         }
00428 }
00429 
00430 template< class T_in, class T_out >
00431 uint WFastWT< T_in, T_out >::binInv( uint index  )
00432 {
00433         //base >>= 1;
00434         uint LMASK = 1, RMASK = N >> 1, inverse = index;
00435         bool nextIter = true;
00436         
00437         while( nextIter ) {
00438                 if( LMASK == RMASK ) nextIter = false;
00439                 if( ( (index & LMASK) == 0 ) && ( (index & RMASK) == 0) ||
00440                         ( (index & LMASK) != 0 ) && ( (index & RMASK) != 0) ) {
00441                 //return inverse;
00442                 }
00443                 else {
00444                         if( (index & LMASK) == LMASK ) {
00445                                 inverse |= RMASK;
00446                                 inverse &= ~LMASK;
00447                         }
00448                         else {
00449                                 if( (index & RMASK) == RMASK ) {
00450                                         inverse |= LMASK;
00451                                         inverse &= ~RMASK;
00452                                 }
00453                         }
00454                 }
00455                 LMASK <<= 1;
00456                 RMASK >>= 1;
00457         }
00458         return inverse;
00459 }
00460 
00461 //Binary operation of Greys lefthanded transposition (classical coding)
00462 template< class T_in, class T_out >
00463 uint WFastWT< T_in, T_out >::binInvGCL( uint index  )
00464 {
00465         unsigned int LMASK = N >> 1, RMASK = LMASK >> 1, greyCL = 0;
00466 
00467         if( ( index & LMASK ) != 0 )
00468                  greyCL |= LMASK;
00469 
00470         while( RMASK ) {
00471                 if( ( ( greyCL & LMASK ) != 0 ) && ( ( index & RMASK ) == 0 ) ||
00472                         ( ( greyCL & LMASK ) == 0 ) && ( ( index & RMASK ) != 0 ) ) {
00473                         greyCL |= RMASK;
00474                 }
00475                 LMASK >>= 1;
00476                 RMASK >>= 1;
00477         }
00478         return greyCL;
00479 }
00480 
00481 //Binary operation of Greys righthanded transposition (discovered by Anatoly Beletsky)
00482 template< class T_in, class T_out >
00483 uint WFastWT< T_in, T_out >::binInvGCR( uint index  )
00484 {
00485         unsigned int base = N >> 1;
00486         unsigned int LMASK = 1, RMASK = LMASK << 1, greyCR = 0;
00487 
00488         if( ( index & LMASK ) != 0 )
00489                 greyCR |= LMASK;
00490 
00491         while( LMASK != base ) {
00492                 if( ( ( greyCR & LMASK ) != 0 ) && ( ( index & RMASK ) == 0 ) ||
00493                     ( ( greyCR & LMASK ) == 0 ) && ( ( index & RMASK ) != 0 ) ) {
00494                         greyCR |= RMASK;
00495                 }
00496                 LMASK <<= 1;
00497                 RMASK <<= 1;
00498         }
00499         return greyCR;
00500 }
00501 
00502 //-------------------------------------------------------------------
00503 
00504 template < class T_in, class T_out >
00505 class WIFastHT : public ITransform< T_in, T_out > {
00506 public:
00507         WIFastHT( uint N_par = 8 );
00508         void doTransform();
00509         void setData( T_in *dat );
00510         T_out *getSpectrum();
00511         virtual void regroupe();
00512         virtual ~WIFastHT();
00513 private:
00514         uint N, m;
00515         void multiply();
00516         T_out *spectrum;
00517         T_out *aux1;
00518         T_out *aux2;
00519         bool noData;
00520 };
00521 
00522 template< class T_in, class T_out >
00523 WIFastHT< T_in, T_out>::WIFastHT( uint N_par ) : N( N_par ), noData( true )
00524 {
00525 
00526         if( ((~N + 1)&N) != N ) {
00527                 throw TransError::badNValue();
00528         }
00529 
00530         int count = 0;
00531         for(int check = N_par; (check&1) == 0 ; count++, check >>= 1 );
00532         m = count;
00533 
00534         spectrum = new T_out[ N ];
00535         aux1 = new T_out[ N ];
00536         aux2 = new T_out[ N ];
00537 }
00538 
00539 template< class T_in, class T_out >
00540 WIFastHT< T_in, T_out >::~WIFastHT()
00541 {
00542         delete [] spectrum;
00543         delete [] aux1;
00544         delete [] aux2;
00545 }
00546 
00547 template< class T_in, class T_out >
00548 void WIFastHT< T_in, T_out >::doTransform()
00549 {
00550         if( noData )
00551                 throw TransError::noData();
00552         else {
00553                 spectrum[ 0 ] = aux1[ 0 ] + aux1[ 1 ];
00554                 spectrum[ 1 ] = aux1[ 0 ] - aux1[ 1 ];
00555                 for( int halfSize = 2; halfSize < N; halfSize *= 2) {
00556                         for( int i = 0; i < halfSize; i++ ) aux2[ i ] = spectrum[ i ]; 
00557                         uint count = halfSize;
00558                         for( int ifhtStep = 0; ifhtStep < halfSize; ifhtStep++ ) {
00559                                 spectrum[ 2*ifhtStep ] = aux2[ ifhtStep ] + aux1[ count ];
00560                                 spectrum[ 2*ifhtStep + 1 ] = aux2[ ifhtStep ] - aux1[ count ];
00561                                 count++;
00562                         }
00563                 }
00564         }
00565 }
00566 
00567 template< class T_in, class T_out >
00568 void WIFastHT< T_in, T_out >::setData( T_in *dat )
00569 {
00570         for( int i = 0; i < N; i++ ) {
00571                 aux1[i] = static_cast< T_out >( dat[i] );
00572         }
00573         multiply();
00574         noData = false;
00575 }
00576 
00577 template< class T_in, class T_out >
00578 void WIFastHT< T_in, T_out >::multiply()
00579 {
00580         double S = sqrt(2.0), coeff = 1;
00581         for(int i = 1, l_1 = 2, l_2 = l_1*2; i < m; i++, l_1 *= 2, l_2 = l_1*2 ) {
00582                 coeff *= S;
00583                 for(int j = l_1; j < l_2; j++) {
00584                         aux1[j] *= coeff;
00585                 }
00586         }
00587 }
00588 
00589 template< class T_in, class T_out >
00590 T_out *WIFastHT< T_in, T_out >::getSpectrum()
00591 {
00592         return spectrum;
00593 }
00594 
00595 template< class T_in, class T_out >
00596 void WIFastHT< T_in, T_out >::regroupe()
00597 {
00598 
00599 }
00600 
00601 #endif
00602 

Generated on Mon Jun 5 10:20:48 2006 for Intelligence.kdevelop by  doxygen 1.4.6