/*************************************************************************/ /* */ /* Centre for Speech Technology Research */ /* University of Edinburgh, UK */ /* Copyright (c) 1994,1995,1996 */ /* All Rights Reserved. */ /* */ /* Permission is hereby granted, free of charge, to use and distribute */ /* this software and its documentation without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of this work, and to */ /* permit persons to whom this work is furnished to do so, subject to */ /* the following conditions: */ /* 1. The code must retain the above copyright notice, this list of */ /* conditions and the following disclaimer. */ /* 2. Any modifications must be clearly marked as such. */ /* 3. Original authors' names are not deleted. */ /* 4. The authors' names are not used to endorse or promote products */ /* derived from this software without specific prior written */ /* permission. */ /* */ /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */ /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */ /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ /* THIS SOFTWARE. */ /* */ /*************************************************************************/ /* Author : Simon King (taken from Tony Robinson) */ /* Date : July 1994 */ /*-----------------------------------------------------------------------*/ /* FFT functions */ /* */ /*=======================================================================*/ #include //#include //#include #include "sigpr/EST_fft.h" #include "EST_math.h" #include "EST_error.h" #define PI8 0.392699081698724 /* PI / 8.0 */ #define RT2 1.4142135623731 /* sqrt(2.0) */ #define IRT2 0.707106781186548 /* 1.0/sqrt(2.0) */ static void FR2TR(int, float*, float*); static void FR4TR(int, int, float*, float*, float*, float*); static void FORD1(int, float*); static void FORD2(int, float*); /* ** FAST(b,n) ** This routine replaces the float vector b ** of length n with its finite discrete fourier transform. ** DC term is returned in b[0]; ** n/2th harmonic float part in b[1]. ** jth harmonic is returned as complex number stored as ** b[2*j] + i b[2*j + 1] ** (i.e., remaining coefficients are as a DPCOMPLEX vector). ** */ static int slowFFTsub(EST_FVector &real, EST_FVector &imag, float f) { // f = -1 for FFT, 1 for IFFT // would be nicer if we used a complex number class, // but we don't, so it isn't // taken from the FORTRAN old chestnut // in various sig proc books // FORTRAN uses 1..n arrays, so subtract 1 all over the place float u_real,u_imag; float w_real,w_imag; float t_real,t_imag; float tmp_real,tmp_imag; int M,N; int i,j,k,l; M = fastlog2(real.n()); N = (int)pow(float(2.0),(float)M); if (N != real.n()) { EST_warning("Illegal FFT order %d", real.n()); return -1; } for(l=1;l<=M;l++){ int le = (int)pow(float(2.0),(float)(M+1-l)); int le1=le/2; u_real = 1.0; u_imag = 0.0; w_real=cos(PI/le1); w_imag=f * sin(PI/le1); for (j=1;j<=le1;j++) { for (i=j;i<=N-le1;i+=le) { int ip=i+le1; t_real = real.a_no_check(i-1) + real.a_no_check(ip-1); t_imag = imag.a_no_check(i-1) + imag.a_no_check(ip-1); tmp_real = real.a_no_check(i-1) - real.a_no_check(ip-1); tmp_imag = imag.a_no_check(i-1) - imag.a_no_check(ip-1); real.a_no_check(ip-1) = tmp_real*u_real - tmp_imag*u_imag; imag.a_no_check(ip-1) = tmp_real*u_imag + tmp_imag*u_real; real.a_no_check(i-1) = t_real; imag.a_no_check(i-1) = t_imag; } tmp_real = u_real*w_real - u_imag*w_imag; tmp_imag = u_real*w_imag + u_imag*w_real; u_real=tmp_real; u_imag=tmp_imag; } } int NV2=N/2; int NM1=N-1; j=1; for (i=1; i<=NM1;i++) { if (i < j) { t_real=real(j-1); t_imag=imag(j-1); real[j-1] = real(i-1); imag[j-1] = imag(i-1); real[i-1] = t_real; imag[i-1] = t_imag; } k=NV2; while(k < j) { j=j-k; k=k/2; } j=j+k; } return 0; } int slowFFT(EST_FVector &real, EST_FVector &imag) { return slowFFTsub(real,imag,-1.0); } int slowIFFT(EST_FVector &real, EST_FVector &imag) { int N=real.n(); if (N <=0 ) return -1; if (slowFFTsub(real,imag,1.0) != 0) return -1; for(int i=1;i<=N;i++){ real[i-1] /= (float)N; imag[i-1] /= (float)N; } return 0; } int energy_spectrum(EST_FVector &real, EST_FVector &imag) { if (slowFFT(real, imag) != 0) return -1; int i; for(i=0;i0) { k0 = in*4 + 1; kl = k0 + in - 1; for (k=k0;k<=kl;k++) { kk = k-1; pr = IRT2 * (b1[kk]-b3[kk]); pi = IRT2 * (b1[kk]+b3[kk]); b3[kk] = b2[kk] + pi; b1[kk] = pi - b2[kk]; b2[kk] = b0[kk] - pr; b0[kk] = b0[kk] + pr; } } } else { arg = th2*piovn; c1 = cos(arg); s1 = sin(arg); c2 = c1*c1 - s1*s1; s2 = c1*s1 + c1*s1; c3 = c1*c2 - s1*s2; s3 = c2*s1 + s2*c1; int4 = in*4; j0=jr*int4 + 1; k0=ji*int4 + 1; jlast = j0+in-1; for(j=j0;j<=jlast;j++) { k = k0 + j - j0; kk = k-1; jj = j-1; r1 = b1[jj]*c1 - b5[kk]*s1; r5 = b1[jj]*s1 + b5[kk]*c1; t2 = b2[jj]*c2 - b6[kk]*s2; t6 = b2[jj]*s2 + b6[kk]*c2; t3 = b3[jj]*c3 - b7[kk]*s3; t7 = b3[jj]*s3 + b7[kk]*c3; t0 = b0[jj] + t2; t4 = b4[kk] + t6; t2 = b0[jj] - t2; t6 = b4[kk] - t6; t1 = r1 + t3; t5 = r5 + t7; t3 = r1 - t3; t7 = r5 - t7; b0[jj] = t0 + t1; b7[kk] = t4 + t5; b6[kk] = t0 - t1; b1[jj] = t5 - t4; b2[jj] = t2 - t7; b5[kk] = t6 + t3; b4[kk] = t2 + t7; b3[jj] = t3 - t6; } jr += 2; ji -= 2; if(ji-jl <= 0) { ji = 2*jr - 1; jl = jr; } } } } /* an inplace reordering subroutine */ void FORD1(int m, float *b) { int j, k = 4, kl = 2, n = 0x1 << m; float t; for(j = 4; j <= n; j += 2) { if (k - j>0) { t = b[j-1]; b[j - 1] = b[k - 1]; b[k - 1] = t; } k -= 2; if (k - kl <= 0) { k = 2*j; kl = j; } } } /* the other inplace reordering subroutine */ void FORD2(int m, float *b) { float t; int n = 0x1<>= 1; power += 1; if (n & 0x01) { if (n > 1) return(0); else return(power); } } return(0); }