www.pudn.com > aacenc.rar > transfo.c



#define d2PI  6.283185307179586

#define SWAP(a,b) tempr=a;a=b;b=tempr   

#include "all.h"
#include "transfo.h"
#include "util.h"
#include 
#ifndef PI
#define PI 3.141592653589795
#endif


/*****************************
  Fast MDCT Code
*****************************/

void MDCT (double *data, int N) {

    static Float *FFTarray = 0;    /* 为FFT定义一个数组 */ 
	static int init = 1;
    Float tempr, tempi, c, s, cold, cfreq, sfreq; /* 为前后交叠定义临时变量*/
    Float freq = 2. * PI / N;
    Float fac;
    int i, n; 
	int isign = 1; 
	int b = N >> 1;
    int a = N - b;

    /* Choosing to allocate 2/N factor to Inverse Xform! */
    fac = 2.; /* 2 from MDCT inverse  to forward */
 
	if (init) { 
		init = 0; 
		FFTarray = NewFloat (1024); 
	}

/* 下面为预交叠准备进行迭代 */ 
    cfreq = cos (freq);
    sfreq = sin (freq);
    c = cos (freq * 0.125);
    s = sin (freq * 0.125);
 
    for (i = 0; i < N / 4; i++) { 
			/* 计算g(n) 或G(p) 的实部和虚部*/ 
		 
		n = N / 2 - 1 - 2 * i; 
		if (i < b / 4) { 
			tempr = data [a / 2 + n] + data [N + a / 2 - 1 - n]; /* 在n = N / 2 - 1 - 2i 时采用e(n) 第二种形式*/ 
		} else { 
			tempr = data [a / 2 + n] - data [a / 2 - 1 - n]; /* 使用e(n) 的第一种形式n = N / 2 - 1 - 2i */ 
		} 
		n = 2 * i; 
		if (i < a / 4) { 
			tempi = data [a / 2 + n] - data [a / 2 - 1 - n]; /* 在n=2i 时采用e(n) 的第一种形式 */ 
		} else { 
			tempi = data [a / 2 + n] + data [N + a / 2 - 1 - n]; /* 采用e(n) 的第二种形式*/ 
		} 
 
	/* 计算预交叠FFT的输入 */ 
		FFTarray [2 * i] = tempr * c + tempi * s; 
		FFTarray [2 * i + 1] = tempi * c - tempr * s; 
		 
		/* 使用迭代来为下一个i的值计算cosine和sine的值 */ 
		cold = c; 
		c = c * cfreq - s * sfreq; 
		s = s * cfreq + cold * sfreq; 
    } 
    
     /* 进行实时的FFT,长度为N/4 */
    CompFFT (FFTarray, N / 4, -1);

    c = cos (freq * 0.125); 
    s = sin (freq * 0.125); 
     
    for (i = 0; i < N / 4; i++) { 
		 
		tempr = fac * (FFTarray [2 * i] * c + FFTarray [2 * i + 1] * s); 
		tempi = fac * (FFTarray [2 * i + 1] * c - FFTarray [2 * i] * s); 
				 
		/* 计算输出值 */ 
		data [2 * i] = -tempr;   /* 第一部分的偶数部分*/ 
		data [N / 2 - 1 - 2 * i] = tempi;  /* 第一部分的奇数部分 */ 
		data [N / 2 + 2 * i] = -tempi;  /* 第二部分的偶数部分*/ 
		data [N - 1 - 2 * i] = tempr;  /* 第二部分的奇数部分 */ 
 
		 
		/* 接着使用迭代计算cosine和sine的值 */ 
		cold = c; 
		c = c * cfreq - s * sfreq; 
		s = s * cfreq + cold * sfreq; 
    } 
} 


void CompFFT (Float *data, int nn, int isign) {

    static int i, j, k, kk;
    static int p1, q1;
    static int m, n, logq1;
    static Float **intermed = 0;
    static Float ar, ai;
    static Float d2pn;
    static Float ca, sa, curcos, cursin, oldcos, oldsin;
    static Float ca1, sa1, curcos1, cursin1, oldcos1, oldsin1;


/*将n分解n = p1*q1,q1是2的幂. 
    n = 1152, p1 = 9, q1 = 128.		*/ 

    n = nn;
    logq1 = 0;

    for (;;) {
		m = n >> 1;   /* 右移一位*/
		if ((m << 1) == n) {
		    logq1++;
		    n = m;
			} 
		else {
			break;
			}
		}

    p1 = n;
    q1 = 1;
    q1 <<= logq1;

    d2pn = d2PI / nn;

{static int oldp1 = 0, oldq1 = 0;

	if ((oldp1 < p1) || (oldq1 < q1)) {
		if (intermed) {
			free (intermed);
			intermed = 0;
			}
		if (oldp1 < p1) oldp1 = p1;
		if (oldq1 < q1) oldq1 = q1;;
		}
		
	if (!intermed)
		intermed = NewFloatMatrix (oldp1, 2 * oldq1);
}


    for	(i = 0; i < p1; i++) {
		for (j = 0; j < q1; j++){
		    intermed [i] [2 * j] = data [2 * (p1 * j + i)];
			intermed [i] [2 * j + 1] = data [2 * (p1 * j + i) + 1];
			}
		}


    for (i = 0; i < p1; i++) {
/* 前向FFT */ 
		FFT (intermed [i], q1, isign);
		}

/* 将FFT 结果组合进长度为N的序列 */ 

    ca1 = cos (d2pn);
    sa1 = sin (d2pn);
    curcos1 = 1.;
    cursin1 = 0.;

    for (k = 0; k < nn; k++) {
		data [2 * k] = 0.;
		data [2 * k + 1] = 0.;
		kk = k % q1;

		ca = curcos1;
		sa = cursin1;
		curcos = 1.;
		cursin = 0.;

		for (j = 0; j < p1; j++) {
			ar = curcos;
			ai = isign * cursin;
			data [2 * k] += intermed [j] [2 * kk] * ar - intermed [j] [2 * kk + 1] * ai;
			data [2 * k + 1] += intermed [j] [2 * kk] * ai + intermed [j] [2 * kk + 1] * ar;

		    oldcos = curcos;
		    oldsin = cursin;
			curcos = oldcos * ca - oldsin * sa;
			cursin = oldcos * sa + oldsin * ca;
			}
		oldcos1 = curcos1;
		oldsin1 = cursin1;
		curcos1 = oldcos1 * ca1 - oldsin1 * sa1;
		cursin1 = oldcos1 * sa1 + oldsin1 * ca1;
		}

}

/* 下面的程序是FFT(快速傅立叶变换),它读取数组中的nn个隔行扫描的 
   复数数据,经变换后仍存储在原数组中。如果标示ising为1则存入数组 
   的为FFT计算的结果,如果isign为-1则存入数组的为输入数据的IFFT的 
   nn倍。需要注意的是当作反变换时,不需要乘以1/N。 
 */
void FFT (Float *data, int nn, int isign)  {



    static int n, mmax, m, j, i;
    static Float wtemp, wr, wpr, wpi, wi, theta, wpin;
    static Float tempr, tempi, datar, datai;
    static Float data1r, data1i;

    n = nn * 2;

/* bit reversal */

    j = 0;
    for (i = 0; i < n; i += 2) {
		if (j > i) {  /* could use j>i+1 to help compiler analysis */
			SWAP (data [j], data [i]);
			SWAP (data [j + 1], data [i + 1]);
			}
		m = nn;
		while (m >= 2 && j >= m) {
			j -= m;
			m >>= 1;
			}
		j += m;
		}

    theta = 3.141592653589795 * .5;
    if (isign < 0)
		theta = -theta;
    wpin = 0;   /* sin(+-PI) */
    for (mmax = 2; n > mmax; mmax *= 2) {
		wpi = wpin;
		wpin = sin (theta);
		wpr = 1 - wpin * wpin - wpin * wpin; /* cos(theta*2) */
		theta *= .5;
		wr = 1;
		wi = 0;
		for (m = 0; m < mmax; m += 2) {
			j = m + mmax;
			tempr = (Float) wr * (data1r = data [j]);
			tempi = (Float) wi * (data1i = data [j + 1]);
			for (i = m; i < n - mmax * 2; i += mmax * 2) {
				tempr -= tempi;
				tempi = (Float) wr *data1i + (Float) wi *data1r;
				data1r = data [j + mmax * 2];
				data1i = data [j + mmax * 2 + 1];
				data [i] = (datar = data [i]) + tempr;
				data [i + 1] = (datai = data [i + 1]) + tempi;
				data [j] = datar - tempr;
				data [j + 1] = datai - tempi;
				tempr = (Float) wr *data1r;
				tempi = (Float) wi *data1i;
				j += mmax * 2;
				}
			tempr -= tempi;
			tempi = (Float) wr * data1i + (Float) wi *data1r;
			data [i] = (datar = data [i]) + tempr;
			data [i + 1] = (datai = data [i + 1]) + tempi;
			data [j] = datar - tempr;
			data [j + 1] = datai - tempi;
			wr = (wtemp = wr) * wpr - wi * wpi;
			wi = wtemp * wpi + wi * wpr;
			}
		}
}