00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "spli.h"
00042
00043
00044
00045
00046
00047 #define FFT_FAST
00048
00049
00050
00051
00052
00053
00054
00055 #ifndef M_SQRT1_2
00056
00057 #define M_SQRT1_2 M_SQRT_2
00058
00059 #endif
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 PUBLIC SPL_INT XAPI fft_n_bits ( SPL_INT np )
00073
00074 {
00075 SPL_INT i, n, on;
00076
00077 i = on = 0;
00078 n = 1;
00079
00080 while (n>on) {
00081 if ( n >= np )
00082 return i;
00083 i++;
00084 on = n;
00085 n <<= 1;
00086 }
00087
00088 assert(1==0);
00089 return 0;
00090 }
00091
00092
00093
00094
00095
00096 PUBLIC SPL_BOOL XAPI fft_test_2pow( SPL_INT n )
00097
00098 {
00099 return ( ((SPL_INT)1 << fft_n_bits(n)) == n );
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 PUBLIC SPL_VOID XAPI fft_fill_half_tsin( SPL_pFLOAT vhts, SPL_INT tp )
00116
00117 {
00118 SPL_INT i;
00119 assert(tp>0);
00120
00121 vhts[0] = 0.0;
00122 for (i=1; i<tp; i++)
00123 vhts[i] = sin(((-M_PI_2)*i)/tp);
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 PUBLIC SPL_VOID XAPI fft_fill_tsin_tcos( SPL_pFLOAT vts,
00138 SPL_pFLOAT vtc, SPL_INT tp )
00139
00140 {
00141 SPL_INT i;
00142 SPL_INT np;
00143 assert(tp>0);
00144
00145 np = tp >> 1;
00146 vtc[np] = vts[0] = 0.0;
00147 vts[np] = -1.0;
00148 vtc[0] = 1.0;
00149
00150 for (i=1; i<np; i++)
00151 vtc[np+i] = vts[tp-i] = vts[i] = -( vtc[np-i] =
00152 sin((M_PI*i)/tp) );
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 PUBLIC SPL_VOID XAPI fft_htsin_fill_tsin_tcos( SPL_pFLOAT vts,
00172 SPL_pFLOAT vtc, SPL_pFLOAT vhts, SPL_INT tp )
00173
00174 {
00175 SPL_INT i;
00176 SPL_INT np;
00177 assert(tp>0);
00178
00179 np = tp >> 1;
00180 vtc[np] = vts[0] = 0.0;
00181 vts[np] = -1.0;
00182 vtc[0] = 1.0;
00183
00184 for (i=1; i<np; i++)
00185 vtc[np-i] = - ( vtc[np+i] = vts[tp-i] = vts[i] =
00186 vhts[i << 1] );
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196 PUBLIC SPL_VOID XAPI fft_fill_tinv( SPL_pINT vti, SPL_INT tp )
00197
00198 {
00199 SPL_INT i,m,j;
00200
00201 for (j=i=0; i<tp; i++) {
00202 vti[j] = i;
00203 vti[i] = j;
00204 j ^= (m = tp >> 1);
00205 while (m>j)
00206 j ^= (m >>= 1);
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215 PUBLIC SPL_VOID XAPI fft_inverse_vecs( SPL_pFLOAT vre,
00216 SPL_pFLOAT vim, SPL_INT np )
00217
00218 {
00219 SPL_INT i,m,j;
00220 SPL_FLOAT temp;
00221
00222 for (j=i=0; i<np; i++) {
00223 if (j>i) {
00224 __swap(vre[i],vre[j],temp);
00225 __swap(vim[i],vim[j],temp);
00226 };
00227 j ^= (m = np >> 1);
00228 while (m>j)
00229 j ^= (m >>= 1);
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 PUBLIC SPL_VOID XAPI fft_scramble_re_in( SPL_pFLOAT vre,
00248 SPL_pFLOAT vim, SPL_INT np )
00249
00250 {
00251 SPL_INT i,j;
00252 assert((np&1)==0);
00253
00254 np >>= 1;
00255 for (i=j=0; i<np; i++) {
00256 vre[i] = vre[j++];
00257 vim[i] = vre[j++];
00258 };
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 PUBLIC SPL_VOID XAPI fft_unscramble_cx_out( SPL_pFLOAT vre, SPL_pFLOAT vim,
00279 SPL_INT np, SPL_pFLOAT vhts, SPL_BOOL inv )
00280
00281 {
00282 SPL_INT i;
00283 SPL_FLOAT RSum,ISum, RDif,IDif, S;
00284 SPL_INT NPmi;
00285 SPL_INT NPd2;
00286 assert(np>0);
00287
00288 NPmi = np;
00289 NPd2 = np >> 1;
00290
00291 vre[0] += vim[0];
00292 vim[0] = vre[0] - 2.0*vim[0];
00293
00294 if (inv)
00295 S = -1.0;
00296 else {
00297 S = 1.0;
00298 if (NPd2)
00299 vim[NPd2] = -vim[NPd2];
00300 };
00301 for (i=1; i<NPd2; i++) {
00302 NPmi--;
00303 RSum = vre[i]+vre[NPmi];
00304 ISum = vim[i]+vim[NPmi];
00305 RDif = vre[i]-vre[NPmi];
00306 IDif = vim[i]-vim[NPmi];
00307 vre[i] = 0.5*( RSum - ISum*vhts[NPd2-i] + S*RDif*vhts[i] );
00308 vim[i] = 0.5*( IDif + RDif*vhts[NPd2-i] + S*ISum*vhts[i] );
00309 vre[NPmi] = RSum-vre[i];
00310 vim[NPmi] = vim[i]-IDif;
00311 };
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 PUBLIC SPL_VOID XAPI fft_expand_cx_out( SPL_pFLOAT vre,
00326 SPL_pFLOAT vim, SPL_INT np )
00327
00328 {
00329 SPL_INT i;
00330 SPL_INT npd2;
00331 assert(np>0);
00332 assert((np&1)==0);
00333
00334 npd2 = np >> 1;
00335 for (i=1; i<npd2; i++) {
00336 vre[np-i] = vre[i];
00337 vim[np-i] = -vim[i];
00338 };
00339 vre[npd2] = vim[0];
00340 vim[0] = vim[npd2] = 0.0;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 #ifdef FFT_FAST
00380
00381
00382
00383
00384
00385
00386
00387 PUBLIC SPL_VOID XAPI fft_fft( SPL_INT nb, SPL_BOOL inv, SPL_pFLOAT vre,
00388 SPL_pFLOAT vim, SPL_pFLOAT vts,
00389 SPL_pFLOAT vtc, SPL_FLOAT ufac )
00390
00391 {
00392 SPL_INT Term;
00393 SPL_INT CellSeparation;
00394 SPL_INT NumberOfCells;
00395 SPL_INT NumElemenvtsCell;
00396 SPL_INT NumElInCellLess1;
00397 SPL_INT NumElInCell_d2;
00398 SPL_INT NumElInCellDiv4;
00399 SPL_FLOAT RealRootOfUnity, ImagRootOfUnity;
00400 SPL_INT Element;
00401 SPL_INT CellElements;
00402 SPL_INT ElementInNextCell;
00403 SPL_INT ind;
00404 SPL_FLOAT RealDummy, ImagDummy;
00405 SPL_INT Tmp;
00406 SPL_INT np = (SPL_INT)1 << nb;
00407
00408 if (inv)
00409 for (Element=0; Element<np; Element++)
00410 vim[Element] = -vim[Element];
00411
00412 NumberOfCells = np;
00413 for (CellSeparation=Term=1; Term<=nb; Term++) {
00414
00415 NumberOfCells >>= 1;
00416
00417 NumElInCellDiv4 = ( NumElInCell_d2 = (
00418 NumElemenvtsCell = CellSeparation ) >> 1 ) >> 1;
00419
00420 CellSeparation <<= 1;
00421 NumElInCellLess1 = NumElemenvtsCell-1;
00422
00423
00424 Element = 0;
00425 while (Element < np) {
00426
00427
00428 ElementInNextCell = Element + NumElemenvtsCell;
00429 RealDummy = vre[ElementInNextCell];
00430 ImagDummy = vim[ElementInNextCell];
00431 vre[ElementInNextCell] = vre[Element] - RealDummy;
00432 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00433 vre[Element] += RealDummy;
00434 vim[Element] += ImagDummy;
00435 Element += CellSeparation;
00436 }
00437
00438 for (CellElements=1; CellElements<(NumElInCellDiv4); CellElements++) {
00439 ind = CellElements * NumberOfCells;
00440 RealRootOfUnity = vtc[ind];
00441 ImagRootOfUnity = vts[ind];
00442 Element = CellElements;
00443
00444 while (Element < np) {
00445
00446
00447 ElementInNextCell = Element + NumElemenvtsCell;
00448 RealDummy = vre[ElementInNextCell] * RealRootOfUnity -
00449 vim[ElementInNextCell] * ImagRootOfUnity;
00450 ImagDummy = vre[ElementInNextCell] * ImagRootOfUnity +
00451 vim[ElementInNextCell] * RealRootOfUnity;
00452 vre[ElementInNextCell] = vre[Element] - RealDummy;
00453 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00454 vre[Element] += RealDummy;
00455 vim[Element] += ImagDummy;
00456 Element += CellSeparation;
00457 }
00458 }
00459
00460
00461 if (Term>2) {
00462 Element = NumElInCellDiv4;
00463 while (Element < np) {
00464
00465
00466 ElementInNextCell = Element + NumElemenvtsCell;
00467 RealDummy = M_SQRT1_2 * (vre[ElementInNextCell] +
00468 vim[ElementInNextCell]);
00469 ImagDummy = M_SQRT1_2 * (vim[ElementInNextCell] -
00470 vre[ElementInNextCell]);
00471 vre[ElementInNextCell] = vre[Element] - RealDummy;
00472 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00473 vre[Element] += RealDummy;
00474 vim[Element] += ImagDummy;
00475 Element += CellSeparation;
00476 }
00477 }
00478
00479 for ( CellElements=NumElInCellDiv4+1; CellElements<(NumElInCell_d2);
00480 CellElements++) {
00481 ind = CellElements * NumberOfCells;
00482 RealRootOfUnity = vtc[ind];
00483 ImagRootOfUnity = vts[ind];
00484 Element = CellElements;
00485 while (Element < np) {
00486
00487
00488 ElementInNextCell = Element + NumElemenvtsCell;
00489 RealDummy = vre[ElementInNextCell] * RealRootOfUnity -
00490 vim[ElementInNextCell] * ImagRootOfUnity;
00491 ImagDummy = vre[ElementInNextCell] * ImagRootOfUnity +
00492 vim[ElementInNextCell] * RealRootOfUnity;
00493 vre[ElementInNextCell] = vre[Element] - RealDummy;
00494 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00495 vre[Element] += RealDummy;
00496 vim[Element] += ImagDummy;
00497 Element += CellSeparation;
00498 }
00499 }
00500
00501
00502 if (Term > 1) {
00503 Element = NumElInCell_d2;
00504 while (Element < np) {
00505
00506
00507 ElementInNextCell = Element + NumElemenvtsCell;
00508 RealDummy = vim[ElementInNextCell];
00509 ImagDummy = -vre[ElementInNextCell];
00510 vre[ElementInNextCell] = vre[Element] - RealDummy;
00511 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00512 vre[Element] += RealDummy;
00513 vim[Element] += ImagDummy;
00514 Element += CellSeparation;
00515 };
00516 };
00517
00518 Tmp = NumElemenvtsCell - NumElInCellDiv4;
00519 for (CellElements=NumElInCell_d2+1;CellElements<Tmp;CellElements++) {
00520 ind = CellElements * NumberOfCells;
00521 RealRootOfUnity = vtc[ind];
00522 ImagRootOfUnity = vts[ind];
00523 Element = CellElements;
00524 while (Element < np) {
00525
00526
00527 ElementInNextCell = Element + NumElemenvtsCell;
00528 RealDummy = vre[ElementInNextCell] * RealRootOfUnity -
00529 vim[ElementInNextCell] * ImagRootOfUnity;
00530 ImagDummy = vre[ElementInNextCell] * ImagRootOfUnity +
00531 vim[ElementInNextCell] * RealRootOfUnity;
00532 vre[ElementInNextCell] = vre[Element] - RealDummy;
00533 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00534 vre[Element] += RealDummy;
00535 vim[Element] += ImagDummy;
00536 Element += CellSeparation;
00537 };
00538 };
00539
00540
00541 if (Term > 2) {
00542 Element = NumElemenvtsCell - NumElInCellDiv4;
00543 while (Element < np) {
00544
00545
00546 ElementInNextCell = Element + NumElemenvtsCell;
00547 RealDummy = -M_SQRT1_2 * (vre[ElementInNextCell] -
00548 vim[ElementInNextCell]);
00549 ImagDummy = -M_SQRT1_2 * (vre[ElementInNextCell] +
00550 vim[ElementInNextCell]);
00551 vre[ElementInNextCell] = vre[Element] - RealDummy;
00552 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00553 vre[Element] += RealDummy;
00554 vim[Element] += ImagDummy;
00555 Element += CellSeparation;
00556 };
00557 };
00558
00559 for ( CellElements=NumElemenvtsCell-NumElInCellDiv4+1;
00560 CellElements<=NumElInCellLess1;CellElements++) {
00561 ind = CellElements * NumberOfCells;
00562 RealRootOfUnity = vtc[ind];
00563 ImagRootOfUnity = vts[ind];
00564 Element = CellElements;
00565 while (Element < np) {
00566
00567
00568 ElementInNextCell = Element + NumElemenvtsCell;
00569 RealDummy = vre[ElementInNextCell] * RealRootOfUnity -
00570 vim[ElementInNextCell] * ImagRootOfUnity;
00571 ImagDummy = vre[ElementInNextCell] * ImagRootOfUnity +
00572 vim[ElementInNextCell] * RealRootOfUnity;
00573 vre[ElementInNextCell] = vre[Element] - RealDummy;
00574 vim[ElementInNextCell] = vim[Element] - ImagDummy;
00575 vre[Element] += RealDummy;
00576 vim[Element] += ImagDummy;
00577 Element += CellSeparation;
00578 }
00579 }
00580 }
00581
00582 if (inv)
00583 ImagDummy = - (RealDummy = 1/(ufac*FFT_FACTOR*np));
00584 else
00585 ImagDummy = RealDummy = (ufac*FFT_FACTOR);
00586
00587 for (Element=0; Element<np; Element++ ) {
00588 vre[Element] *= RealDummy;
00589 vim[Element] *= ImagDummy;
00590 };
00591 }
00592
00593 #else
00594
00595 PUBLIC SPL_VOID XAPI fft_fft( SPL_INT nb, SPL_BOOL inv, SPL_pFLOAT vre,
00596 SPL_pFLOAT vim, SPL_pFLOAT vts,
00597 SPL_pFLOAT vtc, SPL_FLOAT ufac )
00598 {
00599 SPL_INT i,j,k,t;
00600 SPL_INT vl,vm;
00601 SPL_FLOAT Tempr,Tempi;
00602 SPL_pFLOAT re1,im1,re2,im2, ts, tc;
00603 SPL_INT np = (SPL_INT)1 << nb;
00604
00605 if (inv)
00606 for (i=0; i<np; i++)
00607 vim[i] = -vim[i];
00608
00609 vl = 1;
00610 for (k=1; k<=nb; k++) {
00611 vm = vl;
00612 t = np/(vl<<=1);
00613 re2=(re1=vre)+vm;
00614 im2=(im1=vim)+vm;
00615 for (j=0; j<t; j++) {
00616 ts = vts;
00617 tc = vtc;
00618 for (i=0; i<vm; i++) {
00619 Tempr = (*re2)*(*tc)-(*im2)*(*ts);
00620 Tempi = (*re2)*(*ts)+(*im2)*(*tc);
00621 *(re2++) = (*re1)-Tempr;
00622 *(im2++) = (*im1)-Tempi;
00623 *(re1++) += Tempr;
00624 *(im1++) += Tempi;
00625 ts += t;
00626 tc += t;
00627 };
00628 re1+=vm;
00629 re2+=vm;
00630 im1+=vm;
00631 im2+=vm;
00632 };
00633 };
00634
00635 if (inv)
00636 Tempi = - (Tempr = 1/(ufac*FFT_FACTOR*np));
00637 else
00638 Tempi = Tempr = (ufac*FFT_FACTOR);
00639
00640 for (i=0; i<np; i++) {
00641 vre[i] *= Tempr;
00642 vim[i] *= Tempi;
00643 };
00644 }
00645
00646 #endif
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 PUBLIC SPL_VOID XAPI fft_cxfft( SPL_pFLOAT vre, SPL_pFLOAT vim, SPL_INT np,
00662 SPL_BOOL inv, SPL_FLOAT ufac,
00663 SPL_pFLOAT vtmp )
00664
00665 {
00666 SPL_pFLOAT vts, vtc;
00667 SPL_INT np_d2;
00668 assert(fft_test_2pow(np));
00669
00670 np_d2 = np >> 1;
00671 if (np_d2) {
00672 vts = vtmp;
00673 vtc = vtmp+np_d2;
00674 fft_fill_tsin_tcos(vts,vtc,np_d2);
00675 }
00676 else
00677 vts = vtc = NULL;
00678
00679 fft_inverse_vecs(vre,vim,np);
00680
00681 fft_fft(fft_n_bits(np),inv,vre,vim,vts,vtc,ufac);
00682 }
00683
00684
00685
00686
00687
00688
00689
00690 PUBLIC SPL_INT XAPI tnel_fft_cxfft( SPL_INT np )
00691
00692 {
00693 return np;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 PUBLIC SPL_VOID XAPI fft_refft( SPL_pFLOAT vre, SPL_pFLOAT vim, SPL_INT np,
00712 SPL_BOOL inv, SPL_FLOAT ufac,
00713 SPL_pFLOAT vtmp )
00714
00715 {
00716 SPL_pFLOAT vhts,vts,vtc;
00717 SPL_INT np_d2, npdiv4;
00718 assert(fft_test_2pow(np));
00719 assert(np>=2);
00720
00721 npdiv4 = (np_d2 = np >> 1) >> 1;
00722 if (npdiv4) {
00723 vhts = vtmp;
00724 vts = vhts+npdiv4;
00725 vtc = vts+npdiv4;
00726
00727 fft_fill_half_tsin(vhts,npdiv4);
00728 fft_htsin_fill_tsin_tcos(vts,vtc,vhts,npdiv4);
00729 }
00730 else
00731 vhts = vts = vtc = NULL;
00732
00733
00734 fft_scramble_re_in(vre,vim,np);
00735
00736 fft_inverse_vecs(vre,vim,np_d2);
00737 if (inv)
00738 ufac *= 2.0;
00739 fft_fft(fft_n_bits(np_d2),inv,vre,vim,vts,vtc,ufac);
00740
00741
00742 fft_unscramble_cx_out(vre,vim,np_d2,vhts,inv);
00743
00744
00745
00746 fft_expand_cx_out(vre,vim,np);
00747 }
00748
00749
00750
00751
00752
00753
00754
00755 PUBLIC SPL_INT XAPI tnel_fft_refft( SPL_INT np )
00756
00757 {
00758 return (np >> 2)*3;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768 PUBLIC SPL_FLOAT XAPI fft_zcx_norm( SPL_FLOAT re, SPL_FLOAT im )
00769
00770 {
00771 SPL_FLOAT d;
00772
00773 d = re*re+im*im;
00774 if (d<(FFT_ZERO*FFT_ZERO))
00775 return 0.0;
00776 else
00777 return d;
00778 }
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 PUBLIC SPL_FLOAT XAPI fft_zcx_arg( SPL_FLOAT re, SPL_FLOAT im )
00789
00790 {
00791 if (!((re>FFT_ZERO)||(re<-FFT_ZERO))) {
00792 if (im<-FFT_ZERO)
00793 return -M_PI_2;
00794 else if (im>FFT_ZERO)
00795 return M_PI_2;
00796 else
00797 return 0.0;
00798 }
00799
00800 if (!((im>FFT_ZERO)||(im<-FFT_ZERO))) {
00801 if (re<-FFT_ZERO)
00802 return M_PI;
00803 else
00804 return 0.0;
00805 }
00806 else
00807 return atan2(im,re);
00808 }
00809
00810
00811
00812
00813
00814
00815 PUBLIC SPL_FLOAT XAPI fft_cx_norm( SPL_FLOAT re, SPL_FLOAT im )
00816
00817 {
00818 return __fft_cx_norm(re,im);
00819 }
00820
00821
00822