/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include #include #include "options.h" #include "cnst.h" #include "prot.h" #include "rom_com.h" /*-----------------------------------------------------------------* * Local functions *-----------------------------------------------------------------*/ static void cdftForw( short n, float *a, const short *ip, const float *w ); static void bitrv2_SR( short n, const short *ip, float *a ); static void cftfsub( short n, float *a, const float *w ); static void cft1st(short n, float *a, const float *w); static void cftmdl(short n, short l, float *a, const float *w); static void fft16( float *x, float *y, const short *Idx ); static void fft5_shift1( int n1, float *zRe, float *zIm, const short *Idx ); static void fft8( float *x, float *y, const short *Idx ); static void fft15_shift2( int n1, float *zRe, float *zIm, const short *Idx ); static void fft15_shift8( int n1, float *zRe, float *zIm, const short *Idx ); static void fft5_shift4( int n1, float *zRe, float *zIm, const short *Idx ); static void fft5_32( float *zRe, float *zIm, const short *Idx ); static void fft64( float *x, float *y, const short *Idx ); static void fft32_15( float *x, float *y, const short *Idx ); static void fft32_5( float *x, float *y, const short *Idx ); static void fft8_5( float *x, float *y, const short *Idx ); static void fft5_8( int n1, float *zRe, float *zIm, const short *Idx ); static void fft4_5( float *x, float *y, const short *Idx ); static void fft5_4( int n1, float *zRe, float *zIm, const short *Idx ); static float fmac(float a, float b, float c) { return (((a) * (b)) + (c)); } static float fnms(float a, float b, float c) { return ((c) - ((a) * (b))); } /*-----------------------------------------------------------------* * fft15_shift2() * 15-point FFT with 2-point circular shift *-----------------------------------------------------------------*/ static void fft15_shift2( int n1, /* i : length of data */ float *zRe, /* i/o : real part of input and output data */ float *zIm, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { float T5, T2l, Tx, TV, T1C, T20, Tl, Tq, Tr, TN, TS, TT, T2c, T2d, T2n; float T1O, T1P, T22, T1l, T1q, T1w, TZ, T10, T11, Ta, Tf, Tg, TC, TH, TI; float T2f, T2g, T2m, T1R, T1S, T21, T1a, T1f, T1v, TW, TX, TY; short i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14; float T1, T1z, T4, T1y, Tw, T1A, Tt, T1B; float T2, T3, Tu, Tv; float Th, Tk, TJ, T1h, T1i, T1j, TM, T1k, Tm, Tp, TO, T1m, T1n, T1o, TR; float T1p; float Ti, Tj, TK, TL; float Tn, To, TP, TQ; float T6, T9, Ty, T16, T17, T18, TB, T19, Tb, Te, TD, T1b, T1c, T1d, TG; float T1e; float T7, T8, Tz, TA; float T2a, Ts, T29, T2i, T2k, T2e, T2h, T2j, T2b; float T2q, T2o, T2p, T2u, T2w, T2s, T2t, T2v, T2r; float Tc, Td, TE, TF; float T1M, TU, T1L, T1U, T1W, T1Q, T1T, T1V, T1N; float T25, T23, T24, T1Z, T28, T1X, T1Y, T27, T26; float T1x, T1D, T1E, T1I, T1J, T1G, T1H, T1K, T1F; float T13, T12, T14, T1s, T1u, T1g, T1r, T1t, T15; i0 = Idx[0]; i1 = Idx[n1]; i2 = Idx[n1*2]; i3 = Idx[n1*3]; i4 = Idx[n1*4]; i5 = Idx[n1*5]; i6 = Idx[n1*6]; i7 = Idx[n1*7]; i8 = Idx[n1*8]; i9 = Idx[n1*9]; i10 = Idx[n1*10]; i11 = Idx[n1*11]; i12 = Idx[n1*12]; i13 = Idx[n1*13]; i14 = Idx[n1*14]; T1 = zRe[i0]; T1z = zIm[i0]; T2 = zRe[i5]; T3 = zRe[i10]; T4 = T2 + T3; T1y = KP866025403 * (T3 - T2); Tu = zIm[i5]; Tv = zIm[i10]; Tw = KP866025403 * (Tu - Tv); T1A = Tu + Tv; T5 = T1 + T4; T2l = T1z + T1A; Tt = fnms(0.5, T4, T1); Tx = Tt - Tw; TV = Tt + Tw; T1B = fnms(0.5, T1A, T1z); T1C = T1y + T1B; T20 = T1B - T1y; Th = zRe[i6]; Ti = zRe[i11]; Tj = zRe[i1]; Tk = Ti + Tj; TJ = fnms(0.5, Tk, Th); T1h = KP866025403 * (Tj - Ti); T1i = zIm[i6]; TK = zIm[i11]; TL = zIm[i1]; T1j = TK + TL; TM = KP866025403 * (TK - TL); T1k = fnms(0.5, T1j, T1i); Tm = zRe[i9]; Tn = zRe[i14]; To = zRe[i4]; Tp = Tn + To; TO = fnms(0.5, Tp, Tm); T1m = KP866025403 * (To - Tn); T1n = zIm[i9]; TP = zIm[i14]; TQ = zIm[i4]; T1o = TP + TQ; TR = KP866025403 * (TP - TQ); T1p = fnms(0.5, T1o, T1n); Tl = Th + Tk; Tq = Tm + Tp; Tr = Tl + Tq; TN = TJ - TM; TS = TO - TR; TT = TN + TS; T2c = T1i + T1j; T2d = T1n + T1o; T2n = T2c + T2d; T1O = T1k - T1h; T1P = T1p - T1m; T22 = T1O + T1P; T1l = T1h + T1k; T1q = T1m + T1p; T1w = T1l + T1q; TZ = TJ + TM; T10 = TO + TR; T11 = TZ + T10; T6 = zRe[i3]; T7 = zRe[i8]; T8 = zRe[i13]; T9 = T7 + T8; Ty = fnms(0.5, T9, T6); T16 = KP866025403 * (T8 - T7); T17 = zIm[i3]; Tz = zIm[i8]; TA = zIm[i13]; T18 = Tz + TA; TB = KP866025403 * (Tz - TA); T19 = fnms(0.5, T18, T17); Tb = zRe[i12]; Tc = zRe[i2]; Td = zRe[i7]; Te = Tc + Td; TD = fnms(0.5, Te, Tb); T1b = KP866025403 * (Td - Tc); T1c = zIm[i12]; TE = zIm[i2]; TF = zIm[i7]; T1d = TE + TF; TG = KP866025403 * (TE - TF); T1e = fnms(0.5, T1d, T1c); Ta = T6 + T9; Tf = Tb + Te; Tg = Ta + Tf; TC = Ty - TB; TH = TD - TG; TI = TC + TH; T2f = T17 + T18; T2g = T1c + T1d; T2m = T2f + T2g; T1R = T19 - T16; T1S = T1e - T1b; T21 = T1R + T1S; T1a = T16 + T19; T1f = T1b + T1e; T1v = T1a + T1f; TW = Ty + TB; TX = TD + TG; TY = TW + TX; T2a = KP559016994 * (Tg - Tr); Ts = Tg + Tr; T29 = fnms(KP250000000, Ts, T5); T2e = T2c - T2d; T2h = T2f - T2g; T2i = fnms(KP587785252, T2h, KP951056516 * T2e); T2k = fmac(KP951056516, T2h, KP587785252 * T2e); zRe[i0] = T5 + Ts; T2j = T2a + T29; zRe[i12] = T2j - T2k; zRe[i3] = T2j + T2k; T2b = T29 - T2a; zRe[i6] = T2b - T2i; zRe[i9] = T2b + T2i; T2q = KP559016994 * (T2m - T2n); T2o = T2m + T2n; T2p = fnms(KP250000000, T2o, T2l); T2s = Tl - Tq; T2t = Ta - Tf; T2u = fnms(KP587785252, T2t, KP951056516 * T2s); T2w = fmac(KP951056516, T2t, KP587785252 * T2s); zIm[i0] = T2l + T2o; T2v = T2q + T2p; zIm[i3] = T2v - T2w; zIm[i12] = T2w + T2v; T2r = T2p - T2q; zIm[i9] = T2r - T2u; zIm[i6] = T2u + T2r; T1M = KP559016994 * (TI - TT); TU = TI + TT; T1L = fnms(KP250000000, TU, Tx); T1Q = T1O - T1P; T1T = T1R - T1S; T1U = fnms(KP587785252, T1T, KP951056516 * T1Q); T1W = fmac(KP951056516, T1T, KP587785252 * T1Q); zRe[i10] = Tx + TU; T1V = T1M + T1L; zRe[i7] = T1V - T1W; zRe[i13] = T1V + T1W; T1N = T1L - T1M; zRe[i1] = T1N - T1U; zRe[i4] = T1N + T1U; T25 = KP559016994 * (T21 - T22); T23 = T21 + T22; T24 = fnms(KP250000000, T23, T20); T1X = TN - TS; T1Y = TC - TH; T1Z = fnms(KP587785252, T1Y, KP951056516 * T1X); T28 = fmac(KP951056516, T1Y, KP587785252 * T1X); zIm[i10] = T20 + T23; T27 = T25 + T24; zIm[i13] = T27 - T28; zIm[i7] = T28 + T27; T26 = T24 - T25; zIm[i1] = T1Z + T26; zIm[i4] = T26 - T1Z; T1x = KP559016994 * (T1v - T1w); T1D = T1v + T1w; T1E = fnms(KP250000000, T1D, T1C); T1G = TW - TX; T1H = TZ - T10; T1I = fmac(KP951056516, T1G, KP587785252 * T1H); T1J = fnms(KP587785252, T1G, KP951056516 * T1H); zIm[i5] = T1C + T1D; T1K = T1E - T1x; zIm[i11] = T1J + T1K; zIm[i14] = T1K - T1J; T1F = T1x + T1E; zIm[i8] = T1F - T1I; zIm[i2] = T1I + T1F; T13 = KP559016994 * (TY - T11); T12 = TY + T11; T14 = fnms(KP250000000, T12, TV); T1g = T1a - T1f; T1r = T1l - T1q; T1s = fmac(KP951056516, T1g, KP587785252 * T1r); T1u = fnms(KP587785252, T1g, KP951056516 * T1r); zRe[i5] = TV + T12; T1t = T14 - T13; zRe[i11] = T1t - T1u; zRe[i14] = T1t + T1u; T15 = T13 + T14; zRe[i2] = T15 - T1s; zRe[i8] = T15 + T1s; return; } /*-----------------------------------------------------------------* * fft15_shift8() * 15-point FFT with 8-point circular shift *-----------------------------------------------------------------*/ static void fft15_shift8( int n1, /* i : length of data */ float *zRe, /* i/o : real part of input and output data */ float *zIm, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { float T5, T2l, Tx, TV, T1C, T20, Tl, Tq, Tr, TN, TS, TT, T2c, T2d, T2n; float T1O, T1P, T22, T1l, T1q, T1w, TZ, T10, T11, Ta, Tf, Tg, TC, TH, TI; float T2f, T2g, T2m, T1R, T1S, T21, T1a, T1f, T1v, TW, TX, TY; short i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14; float T1, T1z, T4, T1y, Tw, T1A, Tt, T1B; float T2, T3, Tu, Tv; float Th, Tk, TJ, T1h, T1i, T1j, TM, T1k, Tm, Tp, TO, T1m, T1n, T1o, TR; float T1p; float Ti, Tj, TK, TL; float Tn, To, TP, TQ; float T6, T9, Ty, T16, T17, T18, TB, T19, Tb, Te, TD, T1b, T1c, T1d, TG; float T1e; float T7, T8, Tz, TA; float Tc, Td, TE, TF; float T2a, Ts, T29, T2i, T2k, T2e, T2h, T2j, T2b; float T2q, T2o, T2p, T2u, T2w, T2s, T2t, T2v, T2r; float T1M, TU, T1L, T1U, T1W, T1Q, T1T, T1V, T1N; float T25, T23, T24, T1Z, T28, T1X, T1Y, T27, T26; float T1x, T1D, T1E, T1I, T1J, T1G, T1H, T1K, T1F; float T13, T12, T14, T1s, T1u, T1g, T1r, T1t, T15; i0 = Idx[0] ; i1 = Idx[n1]; i2 = Idx[n1*2]; i3 = Idx[n1*3]; i4 = Idx[n1*4]; i5 = Idx[n1*5]; i6 = Idx[n1*6]; i7 = Idx[n1*7]; i8 = Idx[n1*8]; i9 = Idx[n1*9]; i10 = Idx[n1*10]; i11 = Idx[n1*11]; i12 = Idx[n1*12]; i13 = Idx[n1*13]; i14 = Idx[n1*14]; T1 = zRe[i0]; T1z = zIm[i0]; T2 = zRe[i5]; T3 = zRe[i10]; T4 = T2 + T3; T1y = KP866025403 * (T3 - T2); Tu = zIm[i5]; Tv = zIm[i10]; Tw = KP866025403 * (Tu - Tv); T1A = Tu + Tv; T5 = T1 + T4; T2l = T1z + T1A; Tt = fnms(0.5, T4, T1); Tx = Tt - Tw; TV = Tt + Tw; T1B = fnms(0.5, T1A, T1z); T1C = T1y + T1B; T20 = T1B - T1y; Th = zRe[i6]; Ti = zRe[i11]; Tj = zRe[i1]; Tk = Ti + Tj; TJ = fnms(0.5, Tk, Th); T1h = KP866025403 * (Tj - Ti); T1i = zIm[i6]; TK = zIm[i11]; TL = zIm[i1]; T1j = TK + TL; TM = KP866025403 * (TK - TL); T1k = fnms(0.5, T1j, T1i); Tm = zRe[i9]; Tn = zRe[i14]; To = zRe[i4]; Tp = Tn + To; TO = fnms(0.5, Tp, Tm); T1m = KP866025403 * (To - Tn); T1n = zIm[i9]; TP = zIm[i14]; TQ = zIm[i4]; T1o = TP + TQ; TR = KP866025403 * (TP - TQ); T1p = fnms(0.5, T1o, T1n); Tl = Th + Tk; Tq = Tm + Tp; Tr = Tl + Tq; TN = TJ - TM; TS = TO - TR; TT = TN + TS; T2c = T1i + T1j; T2d = T1n + T1o; T2n = T2c + T2d; T1O = T1k - T1h; T1P = T1p - T1m; T22 = T1O + T1P; T1l = T1h + T1k; T1q = T1m + T1p; T1w = T1l + T1q; TZ = TJ + TM; T10 = TO + TR; T11 = TZ + T10; T6 = zRe[i3]; T7 = zRe[i8]; T8 = zRe[i13]; T9 = T7 + T8; Ty = fnms(0.5, T9, T6); T16 = KP866025403 * (T8 - T7); T17 = zIm[i3]; Tz = zIm[i8]; TA = zIm[i13]; T18 = Tz + TA; TB = KP866025403 * (Tz - TA); T19 = fnms(0.5, T18, T17); Tb = zRe[i12]; Tc = zRe[i2]; Td = zRe[i7]; Te = Tc + Td; TD = fnms(0.5, Te, Tb); T1b = KP866025403 * (Td - Tc); T1c = zIm[i12]; TE = zIm[i2]; TF = zIm[i7]; T1d = TE + TF; TG = KP866025403 * (TE - TF); T1e = fnms(0.5, T1d, T1c); Ta = T6 + T9; Tf = Tb + Te; Tg = Ta + Tf; TC = Ty - TB; TH = TD - TG; TI = TC + TH; T2f = T17 + T18; T2g = T1c + T1d; T2m = T2f + T2g; T1R = T19 - T16; T1S = T1e - T1b; T21 = T1R + T1S; T1a = T16 + T19; T1f = T1b + T1e; T1v = T1a + T1f; TW = Ty + TB; TX = TD + TG; TY = TW + TX; T2a = KP559016994 * (Tg - Tr); Ts = Tg + Tr; T29 = fnms(KP250000000, Ts, T5); T2e = T2c - T2d; T2h = T2f - T2g; T2i = fnms(KP587785252, T2h, KP951056516 * T2e); T2k = fmac(KP951056516, T2h, KP587785252 * T2e); zRe[i0] = T5 + Ts; T2j = T2a + T29; zRe[i3] = T2j - T2k; zRe[i12] = T2j + T2k; T2b = T29 - T2a; zRe[i9] = T2b - T2i; zRe[i6] = T2b + T2i; T2q = KP559016994 * (T2m - T2n); T2o = T2m + T2n; T2p = fnms(KP250000000, T2o, T2l); T2s = Tl - Tq; T2t = Ta - Tf; T2u = fnms(KP587785252, T2t, KP951056516 * T2s); T2w = fmac(KP951056516, T2t, KP587785252 * T2s); zIm[i0] = T2l + T2o; T2v = T2q + T2p; zIm[i12] = T2v - T2w; zIm[i3] = T2w + T2v; T2r = T2p - T2q; zIm[i6] = T2r - T2u; zIm[i9] = T2u + T2r; T1M = KP559016994 * (TI - TT); TU = TI + TT; T1L = fnms(KP250000000, TU, Tx); T1Q = T1O - T1P; T1T = T1R - T1S; T1U = fnms(KP587785252, T1T, KP951056516 * T1Q); T1W = fmac(KP951056516, T1T, KP587785252 * T1Q); zRe[i10] = Tx + TU; T1V = T1M + T1L; zRe[i13] = T1V - T1W; zRe[i7] = T1V + T1W; T1N = T1L - T1M; zRe[i4] = T1N - T1U; zRe[i1] = T1N + T1U; T25 = KP559016994 * (T21 - T22); T23 = T21 + T22; T24 = fnms(KP250000000, T23, T20); T1X = TN - TS; T1Y = TC - TH; T1Z = fnms(KP587785252, T1Y, KP951056516 * T1X); T28 = fmac(KP951056516, T1Y, KP587785252 * T1X); zIm[i10] = T20 + T23; T27 = T25 + T24; zIm[i7] = T27 - T28; zIm[i13] = T28 + T27; T26 = T24 - T25; zIm[i4] = T1Z + T26; zIm[i1] = T26 - T1Z; T1x = KP559016994 * (T1v - T1w); T1D = T1v + T1w; T1E = fnms(KP250000000, T1D, T1C); T1G = TW - TX; T1H = TZ - T10; T1I = fmac(KP951056516, T1G, KP587785252 * T1H); T1J = fnms(KP587785252, T1G, KP951056516 * T1H); zIm[i5] = T1C + T1D; T1K = T1E - T1x; zIm[i14] = T1J + T1K; zIm[i11] = T1K - T1J; T1F = T1x + T1E; zIm[i2] = T1F - T1I; zIm[i8] = T1I + T1F; T13 = KP559016994 * (TY - T11); T12 = TY + T11; T14 = fnms(KP250000000, T12, TV); T1g = T1a - T1f; T1r = T1l - T1q; T1s = fmac(KP951056516, T1g, KP587785252 * T1r); T1u = fnms(KP587785252, T1g, KP951056516 * T1r); zRe[i5] = TV + T12; T1t = T14 - T13; zRe[i14] = T1t - T1u; zRe[i11] = T1t + T1u; T15 = T13 + T14; zRe[i8] = T15 - T1s; zRe[i2] = T15 + T1s; return; } /*-----------------------------------------------------------------* * fft5_shift1() * 5-point FFT with 1-point circular shift *-----------------------------------------------------------------*/ static void fft5_shift1( int n1, /* i : length of data */ float *zRe, /* i/o : real part of input and output data */ float *zIm, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { float T1, To, T8, Tt, T9, Ts, Te, Tp, Th, Tn,T2, T3, T4, T5, T6, T7; short i0,i1,i2,i3,i4; i0 = Idx[0]; i1 = Idx[n1]; i2 = Idx[n1*2]; i3 = Idx[n1*3]; i4 = Idx[n1*4]; T1 = zRe[i0]; To = zIm[i0]; T2 = zRe[i1]; T3 = zRe[i4]; T4 = T2 + T3; T5 = zRe[i2]; T6 = zRe[i3]; T7 = T5 + T6; T8 = T4 + T7; Tt = T5 - T6; T9 = KP559016994 * (T4 - T7); Ts = T2 - T3; T2 = zIm[i1]; T3 = zIm[i4]; T4 = T2 + T3; T5 = zIm[i2]; T6 = zIm[i3]; T7 = T5 + T6; Te = T2 - T3; Tp = T4 + T7; Th = T5 - T6; Tn = KP559016994 * (T4 - T7); zRe[i0] = T1 + T8; zIm[i0] = To + Tp; T2 = KP951056516*Te + KP587785252*Th; T3 = KP951056516*Th - KP587785252*Te; T6 = T1-T8/4; T4 = T9 + T6; T5 = T6 - T9; zRe[i4] = T4 - T2; zRe[i3] = T5 + T3; zRe[i1] = T4 + T2; zRe[i2] = T5 - T3; T2 = KP951056516 * Ts + KP587785252 * Tt; T3 = KP951056516 * Tt - KP587785252 * Ts; T6 = To-Tp/4; T4 = Tn + T6; T5 = T6 - Tn; zIm[i1] = T4 - T2; zIm[i3] = T5 - T3; zIm[i4] = T2 + T4; zIm[i2] = T3 + T5; return; } /*-----------------------------------------------------------------* * fft5_shift4() * 5-point FFT with 4-point circular shift *-----------------------------------------------------------------*/ static void fft5_shift4( int n1, /* i : length of data */ float *zRe, /* i/o : real part of input and output data */ float *zIm, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { float T1, To, T8, Tt, T9, Ts, Te, Tp, Th, Tn,T2, T3, T4, T5, T6, T7; short i0,i1,i2,i3,i4; i0 = Idx[0]; i1 = Idx[n1]; i2 = Idx[n1*2]; i3 = Idx[n1*3]; i4 = Idx[n1*4]; T1 = zRe[i0]; To = zIm[i0]; T2 = zRe[i1]; T3 = zRe[i4]; T4 = T2 + T3; T5 = zRe[i2]; T6 = zRe[i3]; T7 = T5 + T6; T8 = T4 + T7; Tt = T5 - T6; T9 = KP559016994 * (T4 - T7); Ts = T2 - T3; T2 = zIm[i1]; T3 = zIm[i4]; T4 = T2 + T3; T5 = zIm[i2]; T6 = zIm[i3]; T7 = T5 + T6; Te = T2 - T3; Tp = T4 + T7; Th = T5 - T6; Tn = KP559016994 * (T4 - T7); zRe[i0] = T1 + T8; zIm[i0] = To + Tp; T2 = KP951056516*Te + KP587785252*Th; T3 = KP951056516*Th - KP587785252*Te; T6 = T1-T8/4; T4 = T9 + T6; T5 = T6 - T9; zRe[i1] = T4 - T2; zRe[i2] = T5 + T3; zRe[i4] = T4 + T2; zRe[i3] = T5 - T3; T2 = KP951056516 * Ts + KP587785252 * Tt; T3 = KP951056516 * Tt - KP587785252 * Ts; T6 = To-Tp/4; T4 = Tn + T6; T5 = T6 - Tn; zIm[i4] = T4 - T2; zIm[i2] = T5 - T3; zIm[i1] = T2 + T4; zIm[i3] = T3 + T5; return; } /*-----------------------------------------------------------------* * fft5_32() * 5-point FFT called for 32 times *-----------------------------------------------------------------*/ static void fft5_32( float *zRe, /* i/o : real part of input and output data */ float *zIm, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { float T1, To, T8, Tt, T9, Ts, Te, Tp, Th, Tn,T2, T3, T4, T5, T6, T7; short i0,i1,i2,i3,i4; i0 = Idx[0]; i1 = Idx[32]; i2 = Idx[64]; i3 = Idx[96]; i4 = Idx[128]; T1 = zRe[i0]; To = zIm[i0]; T2 = zRe[i1]; T3 = zRe[i4]; T4 = T2 + T3; T5 = zRe[i2]; T6 = zRe[i3]; T7 = T5 + T6; T8 = T4 + T7; Tt = T5 - T6; T9 = KP559016994 * (T4 - T7); Ts = T2 - T3; T2 = zIm[i1]; T3 = zIm[i4]; T4 = T2 + T3; T5 = zIm[i2]; T6 = zIm[i3]; T7 = T5 + T6; Te = T2 - T3; Tp = T4 + T7; Th = T5 - T6; Tn = KP559016994 * (T4 - T7); zRe[i0] = T1 + T8; zIm[i0] = To + Tp; T2 = KP951056516*Te + KP587785252*Th; T3 = KP951056516*Th - KP587785252*Te; T6 = T1-T8/4; T4 = T9 + T6; T5 = T6 - T9; zRe[i3] = T4 - T2; zRe[i1] = T5 + T3; zRe[i2] = T4 + T2; zRe[i4] = T5 - T3; T2 = KP951056516 * Ts + KP587785252 * Tt; T3 = KP951056516 * Tt - KP587785252 * Ts; T6 = To-Tp/4; T4 = Tn + T6; T5 = T6 - Tn; zIm[i2] = T4 - T2; zIm[i1] = T5 - T3; zIm[i3] = T2 + T4; zIm[i4] = T3 + T5; return; } /*-----------------------------------------------------------------* * fft64() * 64-point FFT *-----------------------------------------------------------------*/ static void fft64( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { short i,id,jd; float z[128]; for ( i=0; i<64; i++ ) { id = Idx[i]; z[2*i] = x[id]; z[2*i+1] = y[id]; } cdftForw(128,z,Ip_fft64,w_fft64); for( i=0; i<64 ; i++) { jd = Odx_fft64[i]; id = Idx[jd]; x[id]=z[2*i]; y[id]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * fft32_15() * 32-point FFT called for 15 times *-----------------------------------------------------------------*/ static void fft32_15( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { short i,id,jd; float z[64]; for( i=0; i<32; i++ ) { id = Idx[i]; z[2*i] = x[id]; z[2*i+1] = y[id]; } cdftForw(64,z,Ip_fft32,w_fft32); for( i=0; i<32; i++ ) { jd = Odx_fft32_15[i]; id = Idx[jd]; x[id]=z[2*i]; y[id]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * fft32_5() * 32-point FFT called for 5 times *-----------------------------------------------------------------*/ static void fft32_5( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { short i,id,jd; float z[64]; for( i=0; i<32; i++ ) { id = Idx[i]; z[2*i] = x[id]; z[2*i+1] = y[id]; } cdftForw(64,z,Ip_fft32,w_fft32); for( i=0; i<32; i++ ) { jd = Odx_fft32_5[i]; id = Idx[jd]; x[id]=z[2*i]; y[id]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * fft16() * 16-point FFT *-----------------------------------------------------------------*/ static void fft16( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { short i,id,jd; float z[32]; for(i=0; i<16 ; i++) { id = Idx[i]; z[2*i] = x[id]; z[2*i+1] = y[id]; } cdftForw(32,z,Ip_fft16,w_fft16); for(i=0; i<16; i++) { jd = Odx_fft16[i]; id = Idx[jd]; x[id]=z[2*i]; y[id]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * fft8() * 8-point FFT *-----------------------------------------------------------------*/ static void fft8( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { short i,id; float z[16]; for(i=0; i<8; i++) { id = Idx[i]; z[2*i] = x[id]; z[2*i+1] = y[id]; } cdftForw(16,z,Ip_fft8,w_fft8); for(i=0; i<8; i++) { id = Idx[i]; x[id]=z[2*i]; y[id]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * fft8_5() * 8-point FFT with shift 5 *-----------------------------------------------------------------*/ static void fft8_5( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { short i,id,jd; float z[16]; for(i=0; i<8; i++) { id = Idx[i]; z[2*i] = x[id]; z[2*i+1] = y[id]; } cdftForw(16,z,Ip_fft8,w_fft8); for(i=0; i<8; i++) { jd = Odx_fft8_5[i]; id = Idx[jd]; x[id]=z[2*i]; y[id]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * fft5_8() * 5-point FFT with shift 2 *-----------------------------------------------------------------*/ static void fft5_8( int n1, /* i : length of data */ float *zRe, /* i/o : real part of input and output data */ float *zIm, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { float T1, To, T8, Tt, T9, Ts, Te, Tp, Th, Tn,T2, T3, T4, T5, T6, T7; short i0,i1,i2,i3,i4; i0 = Idx[0]; i1 = Idx[n1]; i2 = Idx[n1*2]; i3 = Idx[n1*3]; i4 = Idx[n1*4]; T1 = zRe[i0]; To = zIm[i0]; T2 = zRe[i1]; T3 = zRe[i4]; T4 = T2 + T3; T5 = zRe[i2]; T6 = zRe[i3]; T7 = T5 + T6; T8 = T4 + T7; Tt = T5 - T6; T9 = KP559016994 * (T4 - T7); Ts = T2 - T3; T2 = zIm[i1]; T3 = zIm[i4]; T4 = T2 + T3; T5 = zIm[i2]; T6 = zIm[i3]; T7 = T5 + T6; Te = T2 - T3; Tp = T4 + T7; Th = T5 - T6; Tn = KP559016994 * (T4 - T7); zRe[i0] = T1 + T8; zIm[i0] = To + Tp; T2 = KP951056516*Te + KP587785252*Th; T3 = KP951056516*Th - KP587785252*Te; T6 = T1-T8/4; T4 = T9 + T6; T5 = T6 - T9; zRe[i2] = T4 - T2; zRe[i4] = T5 + T3; zRe[i3] = T4 + T2; zRe[i1] = T5 - T3; T2 = KP951056516 * Ts + KP587785252 * Tt; T3 = KP951056516 * Tt - KP587785252 * Ts; T6 = To-Tp/4; T4 = Tn + T6; T5 = T6 - Tn; zIm[i3] = T4 - T2; zIm[i4] = T5 - T3; zIm[i2] = T2 + T4; zIm[i1] = T3 + T5; return; } /*-----------------------------------------------------------------* * fft4_5() * 8-point FFT with shift 1 *-----------------------------------------------------------------*/ static void fft4_5( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short *Idx /* i : pointer of the address table */ ) { short i,id,jd; float z[8]; for(i=0; i<4; i++) { id = Idx[i]; z[2*i] = x[id]; z[2*i+1] = y[id]; } cdftForw(8,z,Ip_fft4,w_fft4); for(i=0; i<4; i++) { jd = Odx_fft4_5[i]; id = Idx[jd]; x[id]=z[2*i]; y[id]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * fft5_4() * 5-point FFT with shift 4 *-----------------------------------------------------------------*/ static void fft5_4( int n1, float *zRe, float *zIm, const short *Idx ) { float T1, To, T8, Tt, T9, Ts, Te, Tp, Th, Tn,T2, T3, T4, T5, T6, T7; short i0,i1,i2,i3,i4; i0 = Idx[0]; i1 = Idx[n1]; i2 = Idx[n1*2]; i3 = Idx[n1*3]; i4 = Idx[n1*4]; T1 = zRe[i0]; To = zIm[i0]; T2 = zRe[i1]; T3 = zRe[i4]; T4 = T2 + T3; T5 = zRe[i2]; T6 = zRe[i3]; T7 = T5 + T6; T8 = T4 + T7; Tt = T5 - T6; T9 = KP559016994 * (T4 - T7); Ts = T2 - T3; T2 = zIm[i1]; T3 = zIm[i4]; T4 = T2 + T3; T5 = zIm[i2]; T6 = zIm[i3]; T7 = T5 + T6; Te = T2 - T3; Tp = T4 + T7; Th = T5 - T6; Tn = KP559016994 * (T4 - T7); zRe[i0] = T1 + T8; zIm[i0] = To + Tp; T2 = KP951056516*Te + KP587785252*Th; T3 = KP951056516*Th - KP587785252*Te; T6 = T1-T8/4; T4 = T9 + T6; T5 = T6 - T9; zRe[i1] = T4 - T2; zRe[i2] = T5 + T3; zRe[i4] = T4 + T2; zRe[i3] = T5 - T3; T2 = KP951056516 * Ts + KP587785252 * Tt; T3 = KP951056516 * Tt - KP587785252 * Ts; T6 = To-Tp/4; T4 = Tn + T6; T5 = T6 - Tn; zIm[i4] = T4 - T2; zIm[i2] = T5 - T3; zIm[i1] = T2 + T4; zIm[i3] = T3 + T5; return; } /*-----------------------------------------------------------------* * DoRTFT80() * a low complexity 2-dimensional DFT of 80 points *-----------------------------------------------------------------*/ void DoRTFT80( float *x, /* i/o : real part of input and output data */ float *y /* i/o : imaginary part of input and output data */ ) { short j; /* Applying 16-point FFT for 5 times based on the address table Idx_dortft80 */ for(j=0; j<5; j++) { fft16(x,y,Idx_dortft80+16*j); } /* Applying 5-point FFT for 16 times based on the address table Idx_dortft80 */ for(j=0; j<16; j++) { fft5_shift1(16,x,y,Idx_dortft80+j); } return; } /*-----------------------------------------------------------------* * DoRTFT120() * a low complexity 2-dimensional DFT of 120 points *-----------------------------------------------------------------*/ void DoRTFT120( float *x, /* i/o : real part of input and output data */ float *y /* i/o : imaginary part of input and output data */ ) { short j; /* Applying 8-point FFT for 15 times based on the address table Idx_dortft120 */ for(j=0; j<15; j++) { fft8(x,y,Idx_dortft120+8*j); } /* Applying 15-point FFT for 8 times based on the address table Idx_dortft120 */ for(j=0; j<8; j++) { fft15_shift2(8,x,y,Idx_dortft120+j); } return; } /*-----------------------------------------------------------------* * DoRTFT160() * a low complexity 2-dimensional DFT of 160 points *-----------------------------------------------------------------*/ void DoRTFT160( float x[], /* i/o : real part of input and output data */ float y[] /* i/o : imaginary part of input and output data */ ) { short j; /* Applying 32-point FFT for 5 times based on the address table Idx_dortft160 */ for(j=0; j<5; j++) { fft32_5(x,y,Idx_dortft160+32*j); } /* Applying 5-point FFT for 32 times based on the address table Idx_dortft160 */ for(j=0; j<32; j++) { fft5_32(x,y,Idx_dortft160+j); } return; } /*-----------------------------------------------------------------* * DoRTFT320() * a low complexity 2-dimensional DFT of 320 points *-----------------------------------------------------------------*/ void DoRTFT320( float *x, /* i/o : real part of input and output data */ float *y /* i/o : imaginary part of input and output data */ ) { short j; /* Applying 64-point FFT for 5 times based on the address table Idx_dortft160 */ for(j=0; j<5; j++) { fft64(x,y,Idx_dortft320+64*j); } /* Applying 5-point FFT for 64 times based on the address table Idx_dortft160 */ for(j=0; j<64; j++) { fft5_shift4(64,x,y,Idx_dortft320+j); } return; } /*-----------------------------------------------------------------* * DoRTFT480() * a low complexity 2-dimensional DFT of 480 points *-----------------------------------------------------------------*/ void DoRTFT480( float *x, /* i/o : real part of input and output data */ float *y /* i/o : imaginary part of input and output data */ ) { short j; /* Applying 32-point FFT for 15 times based on the address table Idx_dortft160 */ for(j=0; j<15; j++) { fft32_15(x,y,Idx_dortft480+32*j); } /* Applying 5-point FFT for 32 times based on the address table Idx_dortft160 */ for(j=0; j<32; j++) { fft15_shift8(32,x,y,Idx_dortft480+j); } return; } /*-----------------------------------------------------------------* * DoRTFT40() * a low complexity 2-dimensional DFT of 40 points *-----------------------------------------------------------------*/ void DoRTFT40( float *x, /* i/o : real part of input and output data */ float *y /* i/o : imaginary part of input and output data */ ) { short j; /* Applying 8-point FFT for 5 times based on the address table Idx_dortft40 */ for(j=0; j<5; j++) { fft8_5(x,y,Idx_dortft40+8*j); } /* Applying 5-point FFT for 8 times based on the address table Idx_dortft40 */ for(j=0; j<8; j++) { fft5_8(8,x,y,Idx_dortft40+j); } return; } /*-----------------------------------------------------------------* * DoRTFT20() * a low complexity 2-dimensional DFT of 20 points *-----------------------------------------------------------------*/ void DoRTFT20( float *x, /* i/o : real part of input and output data */ float *y /* i/o : imaginary part of input and output data */ ) { short j; /* Applying 4-point FFT for 5 times based on the address table Idx_dortft20 */ for(j=0; j<5; j++) { fft4_5(x,y,Idx_dortft20+4*j); } /* Applying 5-point FFT for 4 times based on the address table Idx_dortft20 */ for(j=0; j<4; j++) { fft5_4(4,x,y,Idx_dortft20+j); } return; } /*-----------------------------------------------------------------* * DoRTFT128() * FFT with 128 points *-----------------------------------------------------------------*/ void DoRTFT128( float *x, /* i/o : real part of input and output data */ float *y /* i/o : imaginary part of input and output data */ ) { int i; float z[256]; for ( i=0; i<128; i++ ) { z[2*i] = x[i]; z[2*i+1] = y[i]; } cdftForw(256,z,Ip_fft128,w_fft128); x[0]=z[0]; y[0]=z[1]; for( i=1; i<128 ; i++) { x[128-i]=z[2*i]; y[128-i]=z[2*i+1]; } return; } /*-----------------------------------------------------------------* * cdftForw() * Main fuction of Complex Discrete Fourier Transform *-----------------------------------------------------------------*/ static void cdftForw( short n, /* i : data length of real and imag */ float *a, /* i/o : input/output data */ const short *ip, /* i : work area for bit reversal */ const float *w /* i : cos/sin table */ ) { /* bit reversal */ bitrv2_SR(n, ip + 2, a); /* Do FFT */ cftfsub(n, a, w); } /*-----------------------------------------------------------------* * bitrv2_SR() * Bit reversal *-----------------------------------------------------------------*/ static void bitrv2_SR( short n, /* i : data length of real and imag */ const short *ip, /* i/o : work area for bit reversal */ float *a /* i/o : input/output data */ ) { short j, j1, k, k1, m, m2; short l; float xr, xi, yr, yi; if (n == 64) { m = 4; l = -1; } else if (n == 256) { m = 8; l = -1; } else if (n == 16) { m = 2; l = -1; } else { l = n; m = 1; while ((m << 3) < l) { l >>= 1; m <<= 1; } l -= m * 8; } m2 = 2 * m; if (l == 0) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 -= m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += 2 * m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } j1 = 2 * k + m2 + ip[k]; k1 = j1 + m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } else { for (k = 1; k < m; k++) { for (j = 0; j < k; j++) { j1 = 2 * j + ip[k]; k1 = 2 * k + ip[j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += m2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } } return; } /*-----------------------------------------------------------------* * cftfsub() * Complex Discrete Fourier Transform *-----------------------------------------------------------------*/ static void cftfsub( short n, /* i : data length of real and imag */ float *a, /* i/o : input/output data */ const float *w /* i : cos/sin table */ ) { short j, j1, j2, j3, l; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; l = 2; if (n > 8) { cft1st(n, a, w); l = 8; while ((l << 2) < n) { cftmdl(n, l, a, w); l <<= 2; } } if ((l << 2) == n) { for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } } else { for (j = 0; j < l; j += 2) { j1 = j + l; x0r = a[j] - a[j1]; x0i = a[j + 1] - a[j1 + 1]; a[j] += a[j1]; a[j + 1] += a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } } return; } /*-----------------------------------------------------------------* * cft1st() * Subfunction of Complex Discrete Fourier Transform *-----------------------------------------------------------------*/ static void cft1st( short n, /* i : data length of real and imag */ float *a, /* i/o : input/output data */ const float *w /* i : cos/sin table */ ) { short j, k1, k2; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[2]; x0i = a[1] + a[3]; x1r = a[0] - a[2]; x1i = a[1] - a[3]; x2r = a[4] + a[6]; x2i = a[5] + a[7]; x3r = a[4] - a[6]; x3i = a[5] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[4] = x0r - x2r; a[5] = x0i - x2i; a[2] = x1r - x3i; a[3] = x1i + x3r; a[6] = x1r + x3i; a[7] = x1i - x3r; wk1r = w[2]; x0r = a[8] + a[10]; x0i = a[9] + a[11]; x1r = a[8] - a[10]; x1i = a[9] - a[11]; x2r = a[12] + a[14]; x2i = a[13] + a[15]; x3r = a[12] - a[14]; x3i = a[13] - a[15]; a[8] = x0r + x2r; a[9] = x0i + x2i; a[12] = x2i - x0i; a[13] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[10] = wk1r * (x0r - x0i); a[11] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[14] = wk1r * (x0i - x0r); a[15] = wk1r * (x0i + x0r); k1 = 0; for (j = 16; j < n; j += 16) { k1 += 2; k2 = 2 * k1; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[k2]; wk1i = w[k2 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; x0r = a[j] + a[j + 2]; x0i = a[j + 1] + a[j + 3]; x1r = a[j] - a[j + 2]; x1i = a[j + 1] - a[j + 3]; x2r = a[j + 4] + a[j + 6]; x2i = a[j + 5] + a[j + 7]; x3r = a[j + 4] - a[j + 6]; x3i = a[j + 5] - a[j + 7]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 4] = wk2r * x0r - wk2i * x0i; a[j + 5] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 2] = wk1r * x0r - wk1i * x0i; a[j + 3] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 6] = wk3r * x0r - wk3i * x0i; a[j + 7] = wk3r * x0i + wk3i * x0r; wk1r = w[k2 + 2]; wk1i = w[k2 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; x0r = a[j + 8] + a[j + 10]; x0i = a[j + 9] + a[j + 11]; x1r = a[j + 8] - a[j + 10]; x1i = a[j + 9] - a[j + 11]; x2r = a[j + 12] + a[j + 14]; x2i = a[j + 13] + a[j + 15]; x3r = a[j + 12] - a[j + 14]; x3i = a[j + 13] - a[j + 15]; a[j + 8] = x0r + x2r; a[j + 9] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j + 12] = -wk2i * x0r - wk2r * x0i; a[j + 13] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j + 10] = wk1r * x0r - wk1i * x0i; a[j + 11] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j + 14] = wk3r * x0r - wk3i * x0i; a[j + 15] = wk3r * x0i + wk3i * x0r; } return; } /*-----------------------------------------------------------------* * cftmdl() * Subfunction of Complex Discrete Fourier Transform *-----------------------------------------------------------------*/ static void cftmdl( short n, /* i : data length of real and imag */ short l, /* i : initial shift for processing */ float *a, /* i/o : input/output data */ const float *w /* i : cos/sin table */ ) { short j, j1, j2, j3, k, k1, k2, m, m2; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; m = l << 2; for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } wk1r = w[2]; for (j = m; j < l + m; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x2i - x0i; a[j2 + 1] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * (x0r - x0i); a[j1 + 1] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[j3] = wk1r * (x0i - x0r); a[j3 + 1] = wk1r * (x0i + x0r); } k1 = 0; m2 = 2 * m; for (k = m2; k < n; k += m2) { k1 += 2; k2 = 2 * k1; wk2r = w[k1]; wk2i = w[k1 + 1]; wk1r = w[k2]; wk1i = w[k2 + 1]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; for (j = k; j < l + k; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = wk2r * x0r - wk2i * x0i; a[j2 + 1] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } wk1r = w[k2 + 2]; wk1i = w[k2 + 3]; wk3r = wk1r - 2 * wk2r * wk1i; wk3i = 2 * wk2r * wk1r - wk1i; for (j = k + m; j < l + (k + m); j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = -wk2i * x0r - wk2r * x0i; a[j2 + 1] = -wk2i * x0i + wk2r * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } } return; } static void cftbsub( short n, float *a, const float *w /* i : cos/sin table */ ) { short j, j1, j2, j3, l; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; l = 2; if (n > 8) { cft1st(n, a, w); l = 8; while ((l << 2) < n) { cftmdl(n, l, a, w); l <<= 2; } } if ((l << 2) == n) { for (j = 0; j < l; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = -a[j + 1] - a[j1 + 1]; x1r = a[j] - a[j1]; x1i = -a[j + 1] + a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i - x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i + x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i - x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i + x3r; } } else { for (j = 0; j < l; j += 2) { j1 = j + l; x0r = a[j] - a[j1]; x0i = -a[j + 1] + a[j1 + 1]; a[j] += a[j1]; a[j + 1] = -a[j + 1] - a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } } } static void rftfsub( short n, float *a, short nc, const float *c ) { short j, k, kk, ks, m; float wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5f - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } static void rftbsub( short n, float *a, short nc, const float *c ) { short j, k, kk, ks, m; float wkr, wki, xr, xi, yr, yi; a[1] = -a[1]; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5f - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr + wki * xi; yi = wkr * xi - wki * xr; a[j] -= yr; a[j + 1] = yi - a[j + 1]; a[k] += yr; a[k + 1] = yi - a[k + 1]; } a[m + 1] = -a[m + 1]; } static void dctsub( short n, float *a, short nc, const float *c ) { short j, k, kk, ks, m; float wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[j] - wkr * a[k]; a[j] = wkr * a[j] + wki * a[k]; a[k] = xr; } a[m] *= c[0]; } /*-----------------------------------------------------------------* * edct2() * * Transformation of the signal to DCT domain * OR Inverse EDCT-II for short frames *-----------------------------------------------------------------*/ void edct2( short n, short isgn, float *in, float *a, const short *ip, const float *w ) { short j, nw, nc; float xr; mvr2r(in, a, n); nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; } nc = ip[1]; if (n > nc) { nc = n; } if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = a[j] - a[j - 1]; a[j] += a[j - 1]; } a[1] = a[0] - xr; a[0] += xr; if (n > 4) { rftbsub(n, a, nc, w + nw); bitrv2_SR(n, ip + 2, a); cftbsub(n, a, w); } else if (n == 4) { cftfsub(n, a, w); } } if (isgn >= 0) { a[0] *= 0.5f; } dctsub(n, a, nc, w + nw); if (isgn >= 0) { if (n > 4) { bitrv2_SR(n, ip + 2, a); cftfsub(n, a, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, w); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = a[j] - a[j + 1]; a[j] += a[j + 1]; } a[n - 1] = xr; for (j = 0; j < n; j ++) { a[j] /= 32.0f; } } } void DoRTFTn( float *x, /* i/o : real part of input and output data */ float *y, /* i/o : imaginary part of input and output data */ const short n /* i : size of the FFT up to 1024 */ ) { int i; float z[2048]; for ( i=0; i 0); if (len == 640) { float x[320], y[320]; int i; if (sign != -1) { rfft_pre(sine_table, data, len); } for (i = 0; i < 320; i++) { x[i] = data[2*i]; y[i] = data[2*i+1]; } DoRTFT320(x, y); for (i = 0; i < 320; i++) { data[2*i] = x[i]; data[2*i+1] = y[i]; } if (sign == -1) { rfft_post(sine_table, data, len); } } else { if (len == 512) { int i; int const log2 = 9; float reordered_data[512]; if (sign == -1) { fft_rel(data, len, log2); reordered_data[0] = data[0]; reordered_data[1] = data[len/2]; for (i = 1; i < len/2; i++) { reordered_data[2*i] = data[i]; reordered_data[2*i+1] = data[len-i]; } } else { reordered_data[0] = data[0]; reordered_data[len/2] = data[1]; for (i = 1; i < len/2; i++) { reordered_data[i] = data[2*i]; reordered_data[len-i] = data[2*i+1]; } ifft_rel(reordered_data, len, log2); } mvr2r(reordered_data, data, len); } else { assert(!"Not supported FFT length!"); } } return 0; } static void butterfly(const float a, const float b, float *aPlusb, float *aMinusb) { *aPlusb = a + b; *aMinusb = a - b; } static void fft2(float *pInOut) { /* FFT MATRIX: 1.0000 1.0000 1.0000 -1.0000 */ float re1, im1; float re2, im2; re1 = pInOut[0]; im1 = pInOut[1]; re2 = pInOut[2]; im2 = pInOut[3]; pInOut[0] = re1 + re2; pInOut[1] = im1 + im2; pInOut[2] = re1 - re2; pInOut[3] = im1 - im2; } static const float C31 = 0.5f; /* cos(PI/3); sin(2*PI/3) */ static const float C32 = 0.866025403784439f; /* cos(PI/3); sin(2*PI/3) */ static void fft3_2(float *pInOut) { float re1, im1; float re2, im2; float re3, im3; float tmp1, tmp2; float tmp3, tmp4; re1 = pInOut[0]; im1 = pInOut[1]; re2 = pInOut[2]; im2 = pInOut[3]; re3 = pInOut[4]; im3 = pInOut[5]; /* FFT MATRIX: 1.0000 1.0000 1.0000 C31 C32 1.0000 -0.5000 - 0.8660i -0.5000 + 0.8660i 1.0000 -0.5000 + 0.8660i -0.5000 - 0.8660i */ tmp1 = re2 + re3; tmp3 = im2 + im3; tmp2 = re2 - re3; tmp4 = im2 - im3; pInOut[0] = re1 + tmp1; pInOut[1] = im1 + tmp3; pInOut[2] = re1 - C31 * tmp1 + C32 * tmp4; pInOut[4] = re1 - C31 * tmp1 - C32 * tmp4; pInOut[3] = im1 - C32 * tmp2 - C31 * tmp3; pInOut[5] = im1 + C32 * tmp2 - C31 * tmp3; } static void fft4(float *pInOut) { float re1, im1; float re2, im2; float re3, im3; float re4, im4; float tmp1, tmp2; float tmp3, tmp4; float tmp5, tmp6; float tmp7, tmp8; re1 = pInOut[0]; im1 = pInOut[1]; re2 = pInOut[2]; im2 = pInOut[3]; re3 = pInOut[4]; im3 = pInOut[5]; re4 = pInOut[6]; im4 = pInOut[7]; /* 1.0000 1.0000 1.0000 1.0000 1.0000 -1.0000i -1.0000 1.0000i 1.0000 -1.0000 1.0000 -1.0000 1.0000 1.0000i -1.0000 -1.0000i */ tmp1 = re1 + re3; tmp3 = re2 + re4; tmp5 = im1 + im3; tmp7 = im2 + im4; pInOut[0] = tmp1 + tmp3; pInOut[4] = tmp1 - tmp3; pInOut[1] = tmp5 + tmp7; pInOut[5] = tmp5 - tmp7; tmp2 = re1 - re3; tmp4 = re2 - re4; tmp6 = im1 - im3; tmp8 = im2 - im4; pInOut[2] = tmp2 + tmp8; pInOut[6] = tmp2 - tmp8; pInOut[3] = -tmp4 + tmp6; pInOut[7] = tmp4 + tmp6; } static const float C51 = 0.309016994374947f; /* cos(2*PI/5); */ static const float C52 = 0.951056516295154f; /* sin(2*PI/5); */ static const float C53 = 0.809016994374947f; /* cos( PI/5); */ static const float C54 = 0.587785252292473f; /* sin( PI/5); */ static void fft5(float *pInOut) { float re1, im1; float re2, im2; float re3, im3; float re4, im4; float re5, im5; float tmp1, tmp2; float tmp3, tmp4; float tmp5, tmp6; float tmp7, tmp8; re1 = pInOut[0]; im1 = pInOut[1]; re2 = pInOut[2]; im2 = pInOut[3]; re3 = pInOut[4]; im3 = pInOut[5]; re4 = pInOut[6]; im4 = pInOut[7]; re5 = pInOut[8]; im5 = pInOut[9]; /* 1.0000 1.0000 1.0000 1.0000 1.0000 C51 C52 C53 C54 1.0000 0.3090 - 0.9511i -0.8090 - 0.5878i -0.8090 + 0.5878i 0.3090 + 0.9511i 1.0000 -0.8090 - 0.5878i 0.3090 + 0.9511i 0.3090 - 0.9511i -0.8090 + 0.5878i 1.0000 -0.8090 + 0.5878i 0.3090 - 0.9511i 0.3090 + 0.9511i -0.8090 - 0.5878i 1.0000 0.3090 + 0.9511i -0.8090 + 0.5878i -0.8090 - 0.5878i 0.3090 - 0.9511i */ tmp1 = re2 + re5; tmp2 = re2 - re5; tmp3 = im2 + im5; tmp4 = im2 - im5; tmp5 = re3 + re4; tmp6 = re3 - re4; tmp7 = im3 + im4; tmp8 = im3 - im4; pInOut[0] = re1 + tmp1 + tmp5; pInOut[1] = im1 + tmp3 + tmp7; pInOut[2] = re1 + C51 * tmp1 - C53 * tmp5 + C52 * tmp4 + C54 * tmp8; pInOut[8] = re1 + C51 * tmp1 - C53 * tmp5 - C52 * tmp4 - C54 * tmp8; pInOut[3] = im1 - C52 * tmp2 - C54 * tmp6 + C51 * tmp3 - C53 * tmp7; pInOut[9] = im1 + C52 * tmp2 + C54 * tmp6 + C51 * tmp3 - C53 * tmp7; pInOut[4] = re1 - C53 * tmp1 + C51 * tmp5 + C54 * tmp4 - C52 * tmp8; pInOut[6] = re1 - C53 * tmp1 + C51 * tmp5 - C54 * tmp4 + C52 * tmp8; pInOut[5] = im1 - C54 * tmp2 + C52 * tmp6 - C53 * tmp3 + C51 * tmp7; pInOut[7] = im1 + C54 * tmp2 - C52 * tmp6 - C53 * tmp3 + C51 * tmp7; } static const float C81 = 0.707106781186548f; /* cos(PI/4); */ static void fft8_2(float *pInOut) { float re0, im0, re4, im4; float re1_7p, re1_7m; float im1_7p, im1_7m; float re2_6p, re2_6m; float im2_6p, im2_6m; float re3_5p, re3_5m; float im3_5p, im3_5m; re0 = pInOut[0]; im0 = pInOut[1]; re4 = pInOut[8]; im4 = pInOut[9]; butterfly(pInOut[1*2 ], pInOut[7*2 ],&re1_7p, &re1_7m); butterfly(pInOut[1*2+1], pInOut[7*2+1],&im1_7p, &im1_7m); butterfly(pInOut[2*2 ], pInOut[6*2 ],&re2_6p, &re2_6m); butterfly(pInOut[2*2+1], pInOut[6*2+1],&im2_6p, &im2_6m); butterfly(pInOut[3*2 ], pInOut[5*2 ],&re3_5p, &re3_5m); butterfly(pInOut[3*2+1], pInOut[5*2+1],&im3_5p, &im3_5m); /* 0: 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1: 1 + 0i C81 - C81i 0 - 1i -C81 - C81i -1 - 0i -C81 + C81i - 0 + 1i C81 + C81i 2: 1 + 0i 0 - 1i -1 - 0i - 0 + 1i 1 + 0i 0 - 1i - 1 - 0i - 0 + 1i 3: 1 + 0i -C81 - C81i -0 + 1i C81 - C81i -1 - 0i C81 + C81i 0 - 1i -C81 + C81i 4: 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i 1 + 0i - 1 - 0i 5: 1 + 0i -C81 + C81i 0 - 1i C81 + C81i -1 - 0i C81 - C81i - 0 + 1i -C81 - C81i 6: 1 + 0i - 0 + 1i -1 - 0i 0 - 1i 1 + 0i - 0 + 1i - 1 - 0i - 0 - 1i 7: 1 + 0i C81 + C81i -0 + 1i -C81 + C81i -1 - 0i -C81 - C81i - 0 - 1i C81 - C81i */ pInOut[ 0] = re0 + re4 + re1_7p + re2_6p + re3_5p; pInOut[ 1] = im0 + im4 + im1_7p + im2_6p + im3_5p; pInOut[ 2] = re0 + C81*(re1_7p - re3_5p) - re4 + C81*( im1_7m + im3_5m) + im2_6m; pInOut[ 3] = im0 + C81*(im1_7p - im3_5p) - im4 - C81* (re1_7m + re3_5m) - re2_6m; pInOut[ 4] = re0 - re2_6p + re4 + im1_7m - im3_5m; pInOut[ 5] = im0 - im2_6p + im4 - re1_7m + re3_5m; pInOut[ 6] = re0 + C81*(-re1_7p + re3_5p) - re4 + C81*( im1_7m + im3_5m) - im2_6m; pInOut[ 7] = im0 + C81*(-im1_7p + im3_5p) - im4 - C81* (re1_7m + re3_5m) + re2_6m; pInOut[ 8] = re0 - re1_7p + re2_6p - re3_5p + re4; pInOut[ 9] = im0 - im1_7p + im2_6p - im3_5p + im4; pInOut[10] = re0 + C81*(-re1_7p + re3_5p) - re4 - C81*( im1_7m + im3_5m) + im2_6m; pInOut[11] = im0 + C81*(-im1_7p + im3_5p) - im4 + C81* (re1_7m + re3_5m) - re2_6m; pInOut[12] = re0 - re2_6p + re4 - im1_7m + im3_5m; pInOut[13] = im0 - im2_6p + im4 + re1_7m - re3_5m; pInOut[14] = re0 + C81*(re1_7p - re3_5p) - re4 - C81*( im1_7m + im3_5m) - im2_6m; pInOut[15] = im0 + C81*(im1_7p - im3_5p) - im4 + C81* (re1_7m + re3_5m) + re2_6m; } static void nextFFT(float *x, int length) { switch(length) { case 2: fft2(x); break; case 3: fft3_2(x); break; case 4: fft4(x); break; case 5: fft5(x); break; case 8: fft8_2(x); break; default: assert(!"length not supported"); break; } } static const int CTFFTfactors[] = {9,8,7,5,4,3,2,0}; static __inline int findFactor(const int length) { int i = 0; int factor = 0; while(CTFFTfactors[i]!=0) { if(0==(length%CTFFTfactors[i])) { factor = CTFFTfactors[i]; break; } i++; } return factor; } static __inline void twiddle(float *x, const int length, const int n1, const int n2) { int i, ii; double pi = 4. * atan(1.); float sinValOrg, cosValOrg; float sinVal=0.f, cosVal=1.f; float twReal=0.f, twImag=1.f; cosValOrg = (float) cos(-2*pi*1./(double)length); sinValOrg = (float) sin(-2*pi*1./(double)length); for(i=1; i0&&(length/factor>1)) { n1 = factor; n2 = length/factor; /* DATA Resorting for stage1 */ dest = scratch; for (i=0; i<2*n1; i+=2) { src = x+i; for(ii=0; ii1) { float *tmp = scratch1; int n1_inv=1, n2_inv=1; int n2 = factor[0/*idx*/]; int n1 = length/n2; int idx, incr; while(((n1_inv*n1)%n2)!=1) { n1_inv++; } while(((n2_inv*n2)%n1)!=1) { n2_inv++; } idx = 0; incr = n1*n1_inv; cnt = 0; for(i=0; ilength) { idx -= length; } } tmp[cnt++] = x[2*idx ]; tmp[cnt++] = x[2*idx+1]; idx++; } for(cnt=0; cntlength) { idx -= length; } } } for(cnt=0; cnt