www.pudn.com > T-REC-G.722.1-200505-I!!SOFT-ZST-E.zip > dct4_a.c


/********************************************************************************* 
** 
**   ITU-T 7/14kHz Audio Candidate (G.722.1 Annex C) Source Code 
** 
**   © 2004 Polycom, Inc. 
** 
**	 All rights reserved. 
** 
*********************************************************************************/ 
 
/********************************************************************************* 
* Filename: dct_type_iv_a.c 
* 
* Purpose:  Discrete Cosine Transform, Type IV used for MLT 
* 
* The basis functions are 
* 
*	 cos(PI*(t+0.5)*(k+0.5)/block_length) 
* 
* for time t and basis function number k.  Due to the symmetry of the expression 
* in t and k, it is clear that the forward and inverse transforms are the same. 
* 
*********************************************************************************/ 
 
/********************************************************************************* 
 Include files                                                            
*********************************************************************************/ 
#include "defs.h" 
#include "count.h" 
#include "dct4_a.h" 
 
/********************************************************************************* 
 External variable declarations                                           
*********************************************************************************/ 
extern Word16       anal_bias[DCT_LENGTH]; 
extern Word16       dct_core_a[DCT_LENGTH_DIV_32][DCT_LENGTH_DIV_32]; 
extern cos_msin_t   a_cos_msin_2 [DCT_LENGTH_DIV_32]; 
extern cos_msin_t   a_cos_msin_4 [DCT_LENGTH_DIV_16]; 
extern cos_msin_t   a_cos_msin_8 [DCT_LENGTH_DIV_8]; 
extern cos_msin_t   a_cos_msin_16[DCT_LENGTH_DIV_4]; 
extern cos_msin_t   a_cos_msin_32[DCT_LENGTH_DIV_2]; 
extern cos_msin_t   a_cos_msin_64[DCT_LENGTH]; 
extern cos_msin_t   *a_cos_msin_table[]; 
 
/********************************************************************************* 
 Function:    dct_type_iv_a 
 
 Syntax:      void dct_type_iv_a (input, output, dct_length)  
                        Word16   input[], output[], dct_length;               
 
 Description: Discrete Cosine Transform, Type IV used for MLT 
 
 Design Notes: 
                 
 WMOPS:          |    24kbit    |     32kbit 
          -------|--------------|---------------- 
            AVG  |    1.14      |     1.14 
          -------|--------------|----------------   
            MAX  |    1.14      |     1.14 
          -------|--------------|----------------  
                 
           14kHz |    24kbit    |     32kbit     |     48kbit 
          -------|--------------|----------------|---------------- 
            AVG  |    2.57      |     2.57       |     2.57 
          -------|--------------|----------------|---------------- 
            MAX  |    2.57      |     2.57       |     2.57 
          -------|--------------|----------------|---------------- 
 
*********************************************************************************/ 
 
void dct_type_iv_a (Word16 *input,Word16 *output,Word16 dct_length) 
{ 
    Word16   buffer_a[MAX_DCT_LENGTH], buffer_b[MAX_DCT_LENGTH], buffer_c[MAX_DCT_LENGTH]; 
    Word16   *in_ptr, *in_ptr_low, *in_ptr_high, *next_in_base; 
    Word16   *out_ptr_low, *out_ptr_high, *next_out_base; 
    Word16   *out_buffer, *in_buffer, *buffer_swap; 
    Word16   in_val_low, in_val_high; 
    Word16   out_val_low, out_val_high; 
    Word16   in_low_even, in_low_odd; 
    Word16   in_high_even, in_high_odd; 
    Word16   out_low_even, out_low_odd; 
    Word16   out_high_even, out_high_odd; 
    Word16   *pair_ptr; 
    Word16   cos_even, cos_odd, msin_even, msin_odd; 
    Word16   neg_cos_odd; 
    Word16   neg_msin_even; 
    Word32   sum; 
    Word16   set_span, set_count, set_count_log, pairs_left, sets_left; 
    Word16   i,k; 
    Word16   index; 
    cos_msin_t  **table_ptr_ptr, *cos_msin_ptr; 
     
    Word16   temp; 
    Word32   acca; 
 
    Word16   dct_length_log; 
 
 
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
    /* Do the sum/difference butterflies, the first part of */ 
    /* converting one N-point transform into N/2 two-point  */ 
    /* transforms, where N = 1 << DCT_LENGTH_LOG. = 64/128  */ 
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
    test(); 
    if (dct_length==DCT_LENGTH) 
    { 
        dct_length_log = DCT_LENGTH_LOG; 
 
        /* Add bias offsets */ 
        for (i=0;i0;sets_left--) 
        { 
 
            /*||||||||||||||||||||||||||||||||||||||||||||*/ 
            /* Set up output pointers for the current set */ 
            /*||||||||||||||||||||||||||||||||||||||||||||*/ 
 
            out_ptr_low    = next_out_base; 
            next_out_base  = next_out_base + set_span; 
            out_ptr_high   = next_out_base; 
 
            /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ 
            /* Loop over all the butterflies in the current set */ 
            /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ 
 
            do  
            { 
                in_val_low      = *in_ptr++; 
                in_val_high     = *in_ptr++; 
                acca            = L_add(in_val_low,in_val_high); 
                acca            = L_shr(acca,1); 
                out_val_low     = extract_l(acca); 
 
                acca            = L_sub(in_val_low,in_val_high); 
                acca            = L_shr(acca,1); 
                out_val_high    = extract_l(acca); 
 
                *out_ptr_low++  = out_val_low; 
                *--out_ptr_high = out_val_high; 
 
                test(); 
            } while (out_ptr_low < out_ptr_high); 
 
        } /* End of loop over sets of the current size */ 
 
        /*============================================================*/ 
        /* Decide which buffers to use as input and output next time. */ 
        /* Except for the first time (when the input buffer is the    */ 
        /* subroutine input) we just alternate the local buffers.     */ 
        /*============================================================*/ 
 
        in_buffer = out_buffer; 
        move16(); 
        if (out_buffer == buffer_a) 
            out_buffer = buffer_b; 
        else 
            out_buffer = buffer_a; 
        index = add(index,1); 
 
    } /* End of loop over set sizes */ 
 
 
    /*++++++++++++++++++++++++++++++++*/ 
    /* Do N/2 two-point transforms,   */ 
    /* where N =  1 << DCT_LENGTH_LOG */ 
    /*++++++++++++++++++++++++++++++++*/ 
 
    pair_ptr = in_buffer; 
    move16(); 
 
    buffer_swap = buffer_c; 
    move16(); 
 
    temp = sub(dct_length_log,1); 
    temp = shl(1,temp); 
 
    for (pairs_left=temp; pairs_left > 0; pairs_left--) 
    { 
        for ( k=0; k= 0;    set_count_log--) 
    { 
        /*===========================================================*/ 
        /* Initialization for the loop over sets at the current size */ 
        /*===========================================================*/ 
        /*    set_span      = 1 << (DCT_LENGTH_LOG - set_count_log); */ 
        set_span = shr(dct_length,set_count_log); 
 
        set_count     = shl(1,set_count_log); 
        next_in_base  = in_buffer; 
        move16(); 
 
        test(); 
        if (set_count_log == 0) 
        { 
            next_out_base = output; 
        } 
        else 
        { 
            next_out_base = out_buffer; 
        } 
 
 
        /*=====================================*/ 
        /* Loop over all the sets of this size */ 
        /*=====================================*/ 
        for (sets_left = set_count; sets_left > 0;sets_left--) 
        { 
            /*|||||||||||||||||||||||||||||||||||||||||*/ 
            /* Set up the pointers for the current set */ 
            /*|||||||||||||||||||||||||||||||||||||||||*/ 
            in_ptr_low     = next_in_base; 
            move16(); 
            temp           = shr(set_span,1); 
 
            /* address arithmetic */ 
            in_ptr_high    = in_ptr_low + temp; 
            next_in_base  += set_span; 
            out_ptr_low    = next_out_base; 
            next_out_base += set_span; 
            out_ptr_high   = next_out_base; 
            cos_msin_ptr   = *table_ptr_ptr; 
 
            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ 
            /* Loop over all the butterfly pairs in the current set */ 
            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ 
 
            do  
            { 
                /* address arithmetic */ 
                in_low_even     = *in_ptr_low++; 
                in_low_odd      = *in_ptr_low++; 
                in_high_even    = *in_ptr_high++; 
                in_high_odd     = *in_ptr_high++; 
                cos_even        = cos_msin_ptr[0].cosine; 
                move16(); 
                msin_even       = cos_msin_ptr[0].minus_sine; 
                move16(); 
                cos_odd         = cos_msin_ptr[1].cosine; 
                move16(); 
                msin_odd        = cos_msin_ptr[1].minus_sine; 
                move16(); 
                cos_msin_ptr   += 2; 
 
                sum = 0L; 
                sum=L_mac(sum,cos_even,in_low_even); 
                neg_msin_even = negate(msin_even); 
                sum=L_mac(sum,neg_msin_even,in_high_even); 
                out_low_even = round(sum); 
 
                sum = 0L; 
                sum=L_mac(sum,msin_even,in_low_even); 
                sum=L_mac(sum,cos_even,in_high_even); 
                out_high_even= round(sum); 
 
                sum = 0L; 
                sum=L_mac(sum,cos_odd,in_low_odd); 
                sum=L_mac(sum,msin_odd,in_high_odd); 
                out_low_odd= round(sum); 
 
                sum = 0L; 
                sum=L_mac(sum,msin_odd,in_low_odd); 
                neg_cos_odd = negate(cos_odd); 
                sum=L_mac(sum,neg_cos_odd,in_high_odd); 
                out_high_odd= round(sum); 
 
                *out_ptr_low++  = out_low_even; 
                *--out_ptr_high = out_high_even; 
                *out_ptr_low++  = out_low_odd; 
                *--out_ptr_high = out_high_odd; 
                test(); 
            } while (out_ptr_low < out_ptr_high); 
 
        } /* End of loop over sets of the current size */ 
 
        /*=============================================*/ 
        /* Swap input and output buffers for next time */ 
        /*=============================================*/ 
 
        buffer_swap = in_buffer; 
        in_buffer   = out_buffer; 
        out_buffer  = buffer_swap; 
        table_ptr_ptr++; 
    } 
}