www.pudn.com > AVS_M_ver10.rar > fft9.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2007  Audio Video Coding Standard, Part ¢ú 
* 
* This software module was developed by AVS Audio sub-group 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
/*_____________________________________________________________________ 
 |                                                                     | 
 |                        File Inclusions                              | 
 |_____________________________________________________________________| 
*/ 
#include  
#include  
#include  
#include "../include/amr_plus.h" 
/*_____________________________________________________________________ 
 |                                                                     | 
 |                       Constant Definitions                          | 
 |_____________________________________________________________________| 
*/ 
#define  ORDER_MAX     7 
/*_____________________________________________________________________ 
 |                                                                     | 
 |  FUNCTION NAME fft9                                                 | 
 |      Radix-9 FFT for real-valued sequences of length 576 or 1152. 
 |      The  input  sequence  is  first decimated by nine,  and  the 
 |      split-radix  algorithm described in [1]  are applied to  the 
 |      decimated sequences.  The resulting nine separate transforms 
 |      are then combined. 
 | 
 |      The function requires sine and cosine tables t_sin and t_cos, 
 |      and constants N_MAX = 1152 and ORDER_MAX = log2(N_MAX/9). The 
 |      table entries are  defined as sin(2*pi*i) and cos(2*pi*i) for 
 |      i = 0, 1, ..., N_MAX. 
 | 
 |  INPUT 
 |      X[0:n-1]  Input sequence. 
 |      n         Number of samples in the sequence, must be 288, 
 |                576, or 1152. 
 | 
 |  OUTPUT 
 |      Y[0:n-1]  Transform coeffients in the order re[0], re[n/2],  
 |                re[1], im[1], re[2], im[2], ... re[n/2-1], im[n/2-1]. 
 |_____________________________________________________________________| 
*/ 
void fft9(float X[], float Y[], short n) 
{ 
    float   Z[N_MAX]; 
    float  *Z0, *Z1, *Z2, *Z3, *Z4, *Z5, *Z6, *Z7, *Z8; 
    float  *z0, *z1, *z2, *z3, *z4, *z5, *z6, *z7, *z8; 
    float  *x; 
    float  *yre, *yim, *zre, *zim, *wre, *wim; 
    short   m, step, sign, order; 
    short   i, j, k; 
    short   Ind[9]; 
    short  *ind; 
    short   temp; 
    /* Determine the order of the transform, the length of decimated  */ 
    /* transforms m, and the step for the sine and cosine tables.     */ 
    switch(n) { 
    case 72: 
        order = 3; 
        m     = 8; 
        step  = 16; 
        break; 
    case 144: 
        order = 4; 
        m     = 16; 
        step  = 8; 
        break; 
    case 288: 
        order = 5; 
        m     = 32; 
        step  = 4;    
        break; 
    case 576: 
        order = 6; 
        m     = 64; 
        step  = 2; 
        break; 
    case 1152: 
        order = 7; 
        m     = 128; 
        step  = 1; 
        break; 
    default: 
        printf(" invalid fft9 size!\n"); 
        exit(0);  
    } 
    /* Compose decimated sequences X[9i], X[9i+1], ..., X[9i+4] and   */ 
    /* compute their FFT of length m.                                 */ 
    Z0 = &Z[0];   z0 = &Z0[0]; 
    Z1 = &Z0[m];  z1 = &Z1[0];   /* Z1 = &Z[ m];     */ 
    Z2 = &Z1[m];  z2 = &Z2[0];   /* Z2 = &Z[2m];     */ 
    Z3 = &Z2[m];  z3 = &Z3[0];   /* Z3 = &Z[3m];     */ 
    Z4 = &Z3[m];  z4 = &Z4[0];   /* Z4 = &Z[4m];     */ 
    Z5 = &Z4[m];  z5 = &Z5[0];   /* Z5 = &Z[5m];     */ 
    Z6 = &Z5[m];  z6 = &Z6[0];   /* Z6 = &Z[6m];     */ 
    Z7 = &Z6[m];  z7 = &Z7[0];   /* Z7 = &Z[7m];     */ 
    Z8 = &Z7[m];  z8 = &Z8[0];   /* Z8 = &Z[8m];     */ 
    x  =  &X[0]; 
    for (i = 0; i < n/9; i++) 
    { 
        *z0++ = *x++;            /* Z0[i] = X[9i];   */ 
        *z1++ = *x++;            /* Z1[i] = X[9i+1]; */ 
        *z2++ = *x++;            /* Z2[i] = X[9i+2]; */ 
        *z3++ = *x++;            /* Z3[i] = X[9i+3]; */ 
        *z4++ = *x++;            /* Z4[i] = X[9i+4]; */ 
        *z5++ = *x++;            /* Z5[i] = X[9i+5]; */ 
        *z6++ = *x++;            /* Z6[i] = X[9i+6]; */ 
        *z7++ = *x++;            /* Z7[i] = X[9i+7]; */ 
        *z8++ = *x++;            /* Z8[i] = X[9i+8]; */ 
    } 
    fft_rel(&Z0[0], m, order); 
    fft_rel(&Z1[0], m, order); 
    fft_rel(&Z2[0], m, order); 
    fft_rel(&Z3[0], m, order); 
    fft_rel(&Z4[0], m, order); 
    fft_rel(&Z5[0], m, order); 
    fft_rel(&Z6[0], m, order); 
    fft_rel(&Z7[0], m, order); 
    fft_rel(&Z8[0], m, order); 
    /* Compute the DC coefficient and store it into Y[0]. Note that   */ 
    /* the variables Z0, ..., Z8, z0, ..., z8 are not needed after    */ 
    /* this.                                                          */ 
    *Y = *Z0 + *Z1 + *Z2 + *Z3 + *Z4 + *Z5 + *Z6 + *Z7 + *Z8; 
    /* Initialize the index table, which points to the sine and       */ 
    /* cosine tables.                                                 */ 
    ind = &Ind[0]; 
    for (k = 1; k < 9; k++) { 
        *ind++ = (short) (k*step); 
    } 
    /* Butterflies of order 9. */ 
    /* EXAMPLE RADIX5:                                                */ 
    /* ~~~~~~~~~~~~~~~                                                */ 
    /* Transform coefficients in Y are computed so that the pointer   */ 
    /* yre goes over Y[1:n/2] = Y[1:5m],  and the pointer yim  over   */ 
    /* Y[n/2+1:n-1] = Y[5m+1:10m-1].  The pointers  zre and zim run   */ 
    /* over the butterflies in Z according to the following table.    */ 
    /*                                                                */ 
    /* ===================================================            */ 
    /*   i     yre           yim       zre         zim                */ 
    /* ===================================================            */ 
    /*   0   Y[   1: m]  Y[10m-1:9m]  Z[1:m]    Z[2m-1:m]             */ 
    /*   1   Y[ m+1:2m]  Y[ 9m-1:8m]  Z[m-1:0]  Z[m+1:2m]             */ 
    /*   2   Y[2m+1:3m]  Y[ 8m-1:7m]  Z[1:m]    Z[2m-1:m]             */ 
    /*   3   Y[3m+1:4m]  Y[ 7m-1:6m]  Z[m-1:0]  Z[m+1:2m]             */ 
    /*   4   Y[4m+1:5m]  Y[ 6m-1:5m]  Z[1:m]    Z[2m-1:m]             */ 
    /* ===================================================            */ 
    sign = 1; 
    zre = &Z[1];   zim = &Z[m-1]; 
    yre = &Y[1];   yim = &Y[n/2+1]; 
    for (i = 0; i < 9; i++) { 
        for (j = 1; j < m/2; j++) { 
            wre = &zre[0]; 
            wim = &zim[0]; 
            ind = &Ind[0]; 
            *yre =       *wre; 
            *yim = sign*(*wim); 
            for (k = 1; k < 9; k++) { 
                wre  += m; 
                wim  += m; 
                temp = *ind; 
                *yre +=  (*wre)*t_cos[temp] + sign*(*wim)*t_sin[temp]; 
                *yim += -(*wre)*t_sin[temp] + sign*(*wim)*t_cos[temp]; 
		temp = (short) (temp + k*step); 
                if (temp >= N_MAX) { 
			temp -= N_MAX; 
		} 
                *ind = temp; 
                ind++; 
            } 
            yre++;   zre += sign; 
            yim++;   zim -= sign; 
        } 
        wre  = &zre[0]; 
        ind  = &Ind[0]; 
        *yre = *wre; 
/*        *yim = 0.0; */ 
        if (i<8) { 
		*yim = 0.0; 
	} 
        for (k = 1; k < 9; k++) { 
            wre  += m; 
            *yre +=  (*wre)*t_cos[*ind]; 
/*            *yim += -(*wre)*t_sin[*ind]; */ 
            if (i<8) { 
		*yim += -(*wre)*t_sin[*ind]; 
	    } 
            *ind = (short) (*ind+k*step); 
            if (*ind >= N_MAX) { 
		*ind -= N_MAX; 
	    } 
            ind++; 
        } 
        sign = (short) -sign; 
        yre++;   zre += sign; 
        yim++;   zim -= sign; 
    } 
  /* reordering : re[0], re[1], ... re[n/2],  im[1], im[2], ... im[n/2-1] */ 
  /* to           re[0], re[n/2], re[1], im[1], ..., re[n/2-1], im[n/2-1] */ 
  for (i=0; i>1); 
/* k<=j comparison */ 
        } 
        j = (short)(j+k); 
    } 
    /* Length two butterflies. */ 
    x0 = &x[0]; 
    x1 = &x[1]; 
    for (i = 0; i < n/2; i++) { 
        xt  = *x0;                   /* xt      = x[2i]        */ 
        *x0 = xt + *x1;              /* x[2i]   = xt - x[2i+1] */ 
        *x1 = xt - *x1;              /* x[2i+1] = xt - x[2i+1] */ 
        x0++; x0++; 
        x1++; x1++; 
    } 
    /* Other butterflies. */ 
    /* The implementation described in [1] has been changed by using  */ 
    /* table lookup for evaluating sine and cosine functions.  The    */ 
    /* variable ind and its increment step are needed to access table */ 
    /* entries.  Note that this implementation assumes n4 to be so    */ 
    /* small that ind will never exceed the table.  Thus the input    */ 
    /* argument n and the constant N_MAX must be set properly.        */ 
    n2 = 1; 
    for (k = 2; k <= m; k++) { 
        n4 = n2; 
        n2 = (short)(n4<<1); 
        n1 = (short)(n2<<1); 
        step = (short)(N_MAX/n1); 
        for (i = 0; i < n; i = (short)(i+n1)) { 
            xt         = x[i]; 
            x[i]       = xt + x[i+n2]; 
            x[i+n2]    = xt - x[i+n2]; 
            x[i+n2+n4] = -x[i+n2+n4]; 
            ind = step; 
            for (j = 1; j < n4; j++) { 
		short temp; 
                i1 = (short)(i + j); 
		temp = (short)(i - j); 
                i2 = (short)(temp + n2); 
                i3 = (short)(i1 + n2); 
                i4 = (short)(temp + n1); 
                t1 = x[i3]*t_cos[ind] + x[i4]*t_sin[ind]; 
                t2 = x[i3]*t_sin[ind] - x[i4]*t_cos[ind]; 
                x[i4] =  x[i2] - t2; 
                x[i3] = -x[i2] - t2; 
                x[i2] =  x[i1] - t1; 
                x[i1] =  x[i1] + t1; 
                ind = (short)(ind+step); 
            } 
        } 
    } 
} 
/*_____________________________________________________________________ 
 |                                                                     | 
 |  FUNCTION NAME ifft9                                                | 
 |      Inverse Radix-9 FFT for real-valued sequences of length 288,   | 
 |      576 or 1152. The function computes first inverse butterflies   | 
 |      for obtaining transform coefficients of sequencies decimated 
 |      by 9.  The inverse split-radix FFT [1] is applied separately 
 |      to these nine coefficient blocks and the outcomes are 
 |      combined. 
 | 
 |      The function requires sine and cosine tables t_sin and t_cos, 
 |      and constants N_MAX = 1152 and ORDER_MAX = log2(N_MAX/9). The 
 |      table entries are  defined as sin(2*pi*i) and cos(2*pi*i) for 
 |      i = 0, 1, ..., N_MAX-1. 
 | 
 |  INPUT 
 |      Y[0:n-1]  Transform coeffients in the order re[0], re[n/2],  
 |                re[1], im[1], re[2], im[2], ... re[n/2-1], im[n/2-1]. 
 |      n         Number of transform coefficients, must be 288, 576, 
 |                or 1152. 
 | 
 |  OUTPUT 
 |      X[0:n-1]  Output sequence. 
 |_____________________________________________________________________| 
*/ 
void ifft9(float Y[], float X[], short n) 
{ 
    short  i, j, k, m, step, order; 
    short  Ind[9]; 
    short  *ind; 
    float  Z[N_MAX]; 
    float  *z, *zre, *zim; 
    float  *z0, *z1, *z2, *z3, *z4, *z5, *z6, *z7, *z8; 
    float  *yr0,  *yr1,  *yr2, *yr3, *yr4;   
    float  *yi0,  *yi1,  *yi2, *yi3, *yi4; 
    float  *yr0f, *yr1f, *yr2f, *yr3f, *yr4f;  
    float  *yi0f, *yi1f, *yi2f, *yi3f, *yi4f; 
    float  *yr0b, *yr1b, *yr2b, *yr3b;  
    float  *yi0b, *yi1b, *yi2b, *yi3b; 
    float  scale; 
    /* Determine the order of the transform, the length of decimated  */ 
    /* transforms m, and the step for the sine and cosine tables.     */ 
    switch(n) { 
    case 72: 
        order = 3; 
        m     = 8; 
        step  = 16; 
        break; 
    case 144: 
        order = 4; 
        m     = 16; 
        step  = 8; 
        break; 
    case 288: 
        order = 5; 
        m     = 32; 
        step  = 4; 
        break; 
    case 576: 
        order = 6; 
        m     = 64; 
        step  = 2; 
        break; 
    case 1152: 
        order = 7; 
        m     = 128; 
        step  = 1; 
        break; 
    default: 
        printf(" invalid ifft9 size!\n"); 
        exit(0);  
    } 
    /* reordering : re[0], re[n/2], re[1], im[1], ..., re[n/2-1], im[n/2-1] */ 
    /* to           re[0], re[1], ... re[n/2],  im[1], im[2], ... im[n/2-1] */ 
    for (i=0; i                            */ 
    /*     1    re[1]                                                 */ 
    /*     2    re[2]                                                 */ 
    /*     3    re[3]               <-yr0b                            */ 
    /*     4    re[4]    &yr1[0]    yr1f->                            */ 
    /*     5    re[5]                                                 */ 
    /*     6    re[6]                                                 */ 
    /*     7    re[7]               <-yr1b                            */ 
    /*     8    re[8]    &yr2[0]    yr2f->                            */ 
    /*     9    re[9]                                                 */ 
    /*     10   re[10]                                                */ 
    /*     11   im[1]    &yi0[0]    yi0f->                            */ 
    /*     12   im[2]                                                 */ 
    /*     13   im[3]               <-yi0b                            */ 
    /*     14   im[4]    &yi1[0]                                      */ 
    /*     15   im[5]               yi1f->                            */ 
    /*     16   im[6]                                                 */ 
    /*     17   im[7]               <-yi1b                            */ 
    /*     18   im[8]    &yi2[0]                                      */ 
    /*     19   im[9]               yi2f->                            */ 
    /*   ==================================                           */ 
    /* Initialize the fixed and the floating pointers. */ 
    yr0 = &Y[0]; 
    yr1 = &yr0[m];       /* = &Y[  m];     */ 
    yr2 = &yr1[m];       /* = &Y[2*m];     */ 
    yr3 = &yr2[m]; 
    yr4 = &yr3[m]; 
    yi0 = &Y[n/2+1]; 
    yi1 = &Y[n/2+m]; 
    yi2 = &Y[n/2+2*m]; 
    yi3 = &Y[n/2+3*m]; 
    yi4 = &Y[n/2+4*m]; 
    zre  = &Z[  0]; 
    zim  = &Z[m-1]; 
    yr0f = &yr0[0];   yr0b = &yr1[-1]; 
    yr1f = &yr1[0];   yr1b = &yr2[-1]; 
    yr2f = &yr2[0];   yr2b = &yr3[-1]; 
    yr3f = &yr3[0];   yr3b = &yr4[-1]; 
    yr4f = &yr4[0]; 
    yi0f = &yi0[0];   yi0b = &yi1[-1]; 
    yi1f = &yi0f[m];  yi1b = &yi2[-1]; 
    yi2f = &yi1f[m];  yi2b = &yi3[-1]; 
    yi3f = &yi2f[m];  yi3b = &yi4[-1]; 
    yi4f = &yi3f[m]; 
    /* Compute the inverse butterflies. */ 
    *zre++ = *yr0f++ + 2*(*yr1f++) + 2*(*yr2f++) + 2*(*yr3f++) + 2*(*yr4f++) ; 
    for (i = 1; i < m/2; i++) { 
        *zre++ = *yr0f++ + *yr1f++ + *yr2f++ + *yr3f++ + *yr4f++ + *yr0b-- + *yr1b-- + *yr2b-- + *yr3b--; 
        *zim-- = *yi0f++ + *yi1f++ + *yi2f++ + *yi3f++ + *yi4f++ - *yi0b-- - *yi1b-- - *yi2b-- - *yi3b--; 
    } 
    *zre = 2*(*yr0f) + 2*(*yr1f) + 2*(*yr2f) + 2*(*yr3f) + *yr4f; 
    for (k = 1; k < 9; k++) { 
        ind = &Ind[0]; 
        *ind++ = 0; 
        for (j = 1; j < 9; j++) { 
            *ind = (short)(ind[-1] + m*step); 
            if (*ind >= N_MAX) { 
		*ind -= N_MAX; 
	    } 
            ind++; 
        } 
         z  = &Z[k*m]; 
        *z  = *yr0;                                 ind = &Ind[1]; 
        *z += *yr1*t_cos[*ind] - *yi1*t_sin[*ind];  ind++; 
        *z += *yr2*t_cos[*ind] - *yi2*t_sin[*ind];  ind++; 
        *z += *yr3*t_cos[*ind] - *yi3*t_sin[*ind];  ind++; 
        *z += *yr4*t_cos[*ind] - *yi4*t_sin[*ind];  ind++; 
        *z += *yr4*t_cos[*ind] + *yi4*t_sin[*ind];  ind++; 
        *z += *yr3*t_cos[*ind] + *yi3*t_sin[*ind];  ind++; 
        *z += *yr2*t_cos[*ind] + *yi2*t_sin[*ind];  ind++; 
        *z += *yr1*t_cos[*ind] + *yi1*t_sin[*ind]; 
        zre  = &z[1];     zim  = &z[m-1]; 
        yr0f = &yr0[ 1];  yi0f = &yi0[0]; 
        yr1f = &yr1[ 1];  yi1f = &yi0f[m]; 
        yr2f = &yr2[ 1];  yi2f = &yi1f[m]; 
        yr3f = &yr3[ 1];  yi3f = &yi2f[m]; 
        yr4f = &yr4[ 1];  yi4f = &yi3f[m]; 
        yr3b = &yr4[-1];  yi3b = &yi4[-1]; 
        yr2b = &yr3[-1];  yi2b = &yi3[-1]; 
        yr1b = &yr2[-1];  yi1b = &yi2[-1]; 
        yr0b = &yr1[-1];  yi0b = &yi1[-1]; 
        for (i = 1; i < m/2; i++) { 
            ind = &Ind[0]; 
            for (j = 0; j < 9; j++) { 
                *ind = (short)(*ind+step); 
                if (*ind >= N_MAX) { 
		    *ind -= N_MAX; 
		} 
                ind++; 
            } 
            ind = &Ind[0]; 
            *zre  = *yr0f*t_cos[*ind] - *yi0f*t_sin[*ind]; 
            *zim  = *yr0f*t_sin[*ind] + *yi0f*t_cos[*ind];  ind++; 
            *zre += *yr1f*t_cos[*ind] - *yi1f*t_sin[*ind]; 
            *zim += *yr1f*t_sin[*ind] + *yi1f*t_cos[*ind];  ind++; 
            *zre += *yr2f*t_cos[*ind] - *yi2f*t_sin[*ind]; 
            *zim += *yr2f*t_sin[*ind] + *yi2f*t_cos[*ind];  ind++; 
            *zre += *yr3f*t_cos[*ind] - *yi3f*t_sin[*ind]; 
            *zim += *yr3f*t_sin[*ind] + *yi3f*t_cos[*ind];  ind++; 
            *zre += *yr4f*t_cos[*ind] - *yi4f*t_sin[*ind]; 
            *zim += *yr4f*t_sin[*ind] + *yi4f*t_cos[*ind];  ind++; 
            yr0f++;  yi0f++; 
            yr1f++;  yi1f++; 
            yr2f++;  yi2f++; 
            yr3f++;  yi3f++; 
            yr4f++;  yi4f++; 
            *zre += *yr3b*t_cos[*ind] + *yi3b*t_sin[*ind]; 
            *zim += *yr3b*t_sin[*ind] - *yi3b*t_cos[*ind];  ind++; 
            *zre += *yr2b*t_cos[*ind] + *yi2b*t_sin[*ind]; 
            *zim += *yr2b*t_sin[*ind] - *yi2b*t_cos[*ind];  ind++; 
            *zre += *yr1b*t_cos[*ind] + *yi1b*t_sin[*ind]; 
            *zim += *yr1b*t_sin[*ind] - *yi1b*t_cos[*ind];  ind++; 
            *zre += *yr0b*t_cos[*ind] + *yi0b*t_sin[*ind]; 
            *zim += *yr0b*t_sin[*ind] - *yi0b*t_cos[*ind]; 
            yr0b--;  yi0b--; 
            yr1b--;  yi1b--; 
            yr2b--;  yi2b--; 
            yr3b--;  yi3b--; 
            zre++;   zim--; 
        } 
        ind = &Ind[0]; 
        for (j = 0; j < 9; j++) { 
            *ind = (short)(*ind+step); 
            if (*ind >= N_MAX) { 
		*ind -= N_MAX; 
	    } 
            ind++; 
        } 
        ind = &Ind[0]; 
        *zre  = *yr0f*t_cos[*ind] - *yi0f*t_sin[*ind];   ind++; 
        *zre += *yr1f*t_cos[*ind] - *yi1f*t_sin[*ind];   ind++; 
        *zre += *yr2f*t_cos[*ind] - *yi2f*t_sin[*ind];   ind++; 
        *zre += *yr3f*t_cos[*ind] - *yi3f*t_sin[*ind];   ind++; 
        *zre += *yr4f*(t_cos[*ind] - t_sin[*ind]);       ind++; 
        *zre += *yr3b*t_cos[*ind] + *yi3b*t_sin[*ind];   ind++; 
        *zre += *yr2b*t_cos[*ind] + *yi2b*t_sin[*ind];   ind++; 
        *zre += *yr1b*t_cos[*ind] + *yi1b*t_sin[*ind];   ind++; 
        *zre += *yr0b*t_cos[*ind] + *yi0b*t_sin[*ind]; 
        /* Update the table step. */ 
        step = (short)(step+(1<<(ORDER_MAX-order))); 
    } 
    /* Compute the inverse FFT for all nine blocks. */ 
    z0 = &Z[0]; 
    z1 = &z0[m];   /* z1 = &Z[ m];     */ 
    z2 = &z1[m];   /* z2 = &Z[2m];     */ 
    z3 = &z2[m];   /* z3 = &Z[3m];     */ 
    z4 = &z3[m];   /* z4 = &Z[4m];     */ 
    z5 = &z4[m];   /* z5 = &Z[5m];     */ 
    z6 = &z5[m];   /* z6 = &Z[6m];     */ 
    z7 = &z6[m];   /* z7 = &Z[7m];     */ 
    z8 = &z7[m];   /* z8 = &Z[8m];     */ 
    ifft_rel(&z0[0], m, order); 
    ifft_rel(&z1[0], m, order); 
    ifft_rel(&z2[0], m, order); 
    ifft_rel(&z3[0], m, order); 
    ifft_rel(&z4[0], m, order); 
    ifft_rel(&z5[0], m, order); 
    ifft_rel(&z6[0], m, order); 
    ifft_rel(&z7[0], m, order); 
    ifft_rel(&z8[0], m, order); 
    /* Decimation and scaling, scale = 1/9m. */ 
    scale =((float)1/9)/((float)m); 
    for (i = 0; i < n/9; i++) { 
        *X++ = (*z0++)*scale; 
        *X++ = (*z1++)*scale; 
        *X++ = (*z2++)*scale; 
        *X++ = (*z3++)*scale; 
        *X++ = (*z4++)*scale; 
        *X++ = (*z5++)*scale; 
        *X++ = (*z6++)*scale; 
        *X++ = (*z7++)*scale; 
        *X++ = (*z8++)*scale; 
    } 
} 
/*_____________________________________________________________________ 
 |                                                                     | 
 |  FUNCTION NAME ifft_rel                                             | 
 |      Computes the inverse split-radix FFT in place for the real- 
 |      valued signal x of length n.  The algorithm has been ported 
 |      from the Fortran code presented in [1]. 
 | 
 |      The function  needs sine and cosine tables t_sin and t_cos, 
 |      and the constant N_MAX.  The table  entries  are defined as 
 |      sin(2*pi*i) and cos(2*pi*i) for i = 0, 1, ..., N_MAX-1. The 
 |      implementation  assumes  that any entry  will not be needed 
 |      outside the tables. Therefore, N_MAX and n must be properly 
 |      set.  The function has been  tested with the values n = 16, 
 |      32, 64, 128, 256, and N_MAX = 1280. 
 | 
 |      References 
 |      [1] H.V. Sorensen,  D.L. Jones, M.T. Heideman, C.S. Burrus, 
 |          "Real-valued fast  Fourier transform  algorithm,"  IEEE 
 |          Trans. on Signal Processing,  Vol.35, No.6, pp 849-863, 
 |          1987. 
 | 
 |  INPUT 
 |      x[0:n-1]  Transform coeffients in the order re[0], re[1], 
 |                ..., re[n/2], im[n/2-1], ..., im[1]. 
 |      n         Number of transform coefficients. 
 |      m         m = log2(n). 
 | 
 |  OUTPUT 
 |      x[0:n-1]  Output sequence. 
 |_____________________________________________________________________| 
*/ 
#define SQRT2 1.414213562373095048801688724209698078569671f 
void ifft_rel(float x[], short n, short m) 
{ 
    short  i, j, k; 
    short  i0, i1, i2, i3, i4, i5, i6, i7, i8; 
    short  n1, n2, n4, n8; 
    short  is, id; 
    short  step, ind; 
    float *x0; 
    float  xt; 
    float  r1; 
    float  t1, t2, t3, t4, t5; 
    float  cc1, cc3, ss1, ss3; 
    /* This patch is needed for converting the Fortran indexing to    */ 
    /* the C indexing.                                                */ 
    x = &x[-1]; 
    /* L-shaped butterflies.   */ 
    n2 = (short)(2*n); 
    for (k = 1; k < m; k++) { 
        is = 0; 
        id = n2; 
        n2 = (short)(n2 >> 1); 
        n4 = (short)(n2 >> 2); 
        n8 = (short)(n4 >> 1); 
        while (is < n-1) { 
            for (i = is; i < n; i=(short)(i+id)) { 
                i1    = (short)(i  + 1); 
                i2    = (short)(i1 + n4); 
                i3    = (short)(i2 + n4); 
                i4    = (short)(i3 + n4); 
                t1    = x[i1] - x[i3]; 
                x[i1] = x[i1] + x[i3]; 
                x[i2] = 2.0f*x[i2]; 
                x[i3] = t1 - 2.0f*x[i4]; 
                x[i4] = t1 + 2.0f*x[i4]; 
                if (n4 != 1) { 
                    i1    = (short)(i1 + n8); 
                    i2    = (short)(i2 + n8); 
                    i3    = (short)(i3 + n8); 
                    i4    = (short)(i4 + n8); 
                    t1    = x[i2] - x[i1]; 
                    t2    = x[i4] + x[i3]; 
                    x[i1] = x[i1] + x[i2]; 
                    x[i2] = x[i4] - x[i3]; 
                    x[i3] = SQRT2*(-t2 - t1); 
                    x[i4] = SQRT2*(-t2 + t1); 
                } 
            } 
            is = (short)(2*id - n2); 
            id = (short)(4*id); 
        } 
        step = (short)(N_MAX/n2); 
        ind  = step; 
        for (j = 2; j <= n8; j++) { 
            cc1  = t_cos[ind]; 
            ss1  = t_sin[ind]; 
            cc3  = t_cos[3*ind]; 
            ss3  = t_sin[3*ind]; 
            ind = (short)(ind+step); 
            is  = 0; 
            id  = (short)(2*n2); 
            while (is < n-1) { 
                for (i = is; i < n; i=(short)(i+id)) { 
                    i1    = (short)(i  + j); 
                    i2    = (short)(i1 + n4); 
                    i3    = (short)(i2 + n4); 
                    i4    = (short)(i3 + n4); 
                    i5    = (short)(i  + n4  - j + 2); 
                    i6    = (short)(i5 + n4); 
                    i7    = (short)(i6 + n4); 
                    i8    = (short)(i7 + n4); 
                    t1    = x[i1] - x[i6]; 
                    x[i1] = x[i1] + x[i6]; 
                    t2    = x[i5] - x[i2]; 
                    x[i5] = x[i2] + x[i5]; 
                    t3    = x[i8] + x[i3]; 
                    x[i6] = x[i8] - x[i3]; 
                    t4    = x[i4] + x[i7]; 
                    x[i2] = x[i4] - x[i7]; 
                    t5    = t1 - t4; 
                    t1    = t1 + t4; 
                    t4    = t2 - t3; 
                    t2    = t2 + t3; 
                    x[i3] =  t5*cc1 + t4*ss1; 
                    x[i7] = -t4*cc1 + t5*ss1; 
                    x[i4] =  t1*cc3 - t2*ss3; 
                    x[i8] =  t2*cc3 + t1*ss3; 
                } 
                is = (short)(2*id - n2); 
                id = (short)(4*id); 
            } 
        } 
    } 
    /* Length two butterflies. */ 
    is = 1; 
    id = 4; 
    while (is < n) { 
        for (i0 = is; i0 <= n; i0=(short)(i0+id)) { 
            i1 = (short)(i0 + 1);					 
            r1 = x[i0]; 
            x[i0] = r1 + x[i1]; 
            x[i1] = r1 - x[i1]; 
	/* two ptrs: x[i0] and x[i1], incrment by id, not 1 */ 
        } 
        is = (short)(2*id - 1); 
        id = (short)(4*id); 
    } 
    /* Digit reverse counter. */ 
    j  = 1; 
    n1 = (short)(n - 1); 
    x0 = &x[1]; 
    for (i = 1; i < n; i++) { 
        if (i < j) { 
            xt = x[j];               /* xt   = x[j] */ 
            x[j] = *x0;              /* x[j] = x[i] */ 
            *x0  = xt;               /* x[i] = xt   */ 
        } 
        x0++; 
        k = (short)(n >> 1); 
        while (k < j) { 
            j = (short)(j - k); 
            k = (short)(k >> 1); 
        } 
        j = (short)(j + k); 
    } 
}