www.pudn.com > T-REC-G.722.1-200505-I!!SOFT-ZST-E.zip > dct4.c
/***************************************************************** ****************************************************************** ** ** ITU-T Wideband Coder Candidate (G.WB) Source Code ** ** File Name : dct4.c ** ** © 2000 PictureTel Coporation ** Andover, MA, USA ** ** All rights reserved. ** ****************************************************************** *****************************************************************/ /********************************************************************************* * DCT_TYPE_IV Discrete Cosine Transform, Type IV * * 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#include #include "defs.h" static float dct_core_a[100]; typedef struct { float cosine; float minus_sine; } cos_msin_t; static cos_msin_t cos_msin_5[5]; /* Not used since core_size = 10 */ static cos_msin_t cos_msin_10[10]; static cos_msin_t cos_msin_20[20]; static cos_msin_t cos_msin_40[40]; static cos_msin_t cos_msin_80[80]; static cos_msin_t cos_msin_160[160]; static cos_msin_t cos_msin_320[320]; static cos_msin_t cos_msin_640[640]; /* Used only for 640 point dct */ static cos_msin_t *cos_msin_table[] = {cos_msin_5, cos_msin_10, cos_msin_20, cos_msin_40, cos_msin_80, cos_msin_160, cos_msin_320, cos_msin_640}; /********************************************************************************* Procedure/Function: set_up_one_table Syntax: static void set_up_one_table (table, length) cos_msin_t table[]; long length; Description: SET_UP_ONE_TABLE Set Up One Table of Cosine and Minus Sine Values *********************************************************************************/ static void set_up_one_table (table, length) cos_msin_t table[]; long length; { double angle, scale; int index; scale = PI / (double)(4 * length); for (index = 0; index < length; index++) { angle = scale * ((double)index + 0.5); table[index].cosine = (float) cos(angle); table[index].minus_sine = (float) -sin(angle); } } /********************************************************************************* Procedure/Function: set_up_table s Syntax: static void set_up_tables (long dct_size) Description: Set Up Tables of Cosine and Minus Sine Values *********************************************************************************/ static void set_up_tables(long dct_size) { int length_log; int i,k; double scale; scale = sqrt(2.0/dct_size); if ( dct_size <= 0 ) printf("wrong dct size"), exit(1); length_log=0; while ( (dct_size&1) == 0) { length_log++; dct_size >>= 1; } for(k=0;k<10;++k) { for(i=0;i<10;++i) dct_core_a[10*k+i] = (float)( cos(PI*(k+0.5)*(i+0.5)/10.) * scale); } for (i = 0; i<= length_log ; i++) set_up_one_table (cos_msin_table[i], dct_size<>= 1; } core_size <<= 1; 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. */ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ in_buffer = input; out_buffer = buffer_a; for (set_count_log = 0; set_count_log <= dct_length_log - 2; set_count_log++) { /*===========================================================*/ /* Initialization for the loop over sets at the current size */ /*===========================================================*/ set_span = dct_length>>set_count_log; set_count = 1 << set_count_log; in_ptr = in_buffer; 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 output pointers for the current set */ /*||||||||||||||||||||||||||||||||||||||||||||*/ out_ptr_low = 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++; *out_ptr_low++ = in_val_low + in_val_high; *--out_ptr_high = in_val_low - in_val_high; } 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; if (out_buffer == buffer_a) out_buffer = buffer_b; else out_buffer = buffer_a; } /* End of loop over set sizes */ /*+++++++++++++++++++++++++++++++++++++*/ /* Do dct_size/10 ten-point transforms */ /*+++++++++++++++++++++++++++++++++++++*/ fptr0 = in_buffer; buffer_swap = buffer_c; for (pairs_left = 1 << (dct_length_log - 1); pairs_left > 0; pairs_left--) { fptr2 = dct_core_a; for ( k=0; k = 0; set_count_log--) { /*===========================================================*/ /* Initialization for the loop over sets at the current size */ /*===========================================================*/ set_span = dct_length >> set_count_log; set_count = 1 << set_count_log; next_in_base = in_buffer; if (set_count_log == 0) next_out_base = output; else next_out_base = out_buffer; ++table_ptr_ptr; /*=====================================*/ /* 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; in_ptr_high = in_ptr_low + (set_span >> 1); 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 { cos_even = (*cos_msin_ptr).cosine; msin_even = (*cos_msin_ptr++).minus_sine; *out_ptr_low++ = cos_even * *in_ptr_low - msin_even * *in_ptr_high; *--out_ptr_high = msin_even * *in_ptr_low++ + cos_even * *in_ptr_high++; cos_odd = (*cos_msin_ptr).cosine; msin_odd = (*cos_msin_ptr++).minus_sine; *out_ptr_low++ = cos_odd * *in_ptr_low + msin_odd * *in_ptr_high; *--out_ptr_high = msin_odd * *in_ptr_low++ - cos_odd * *in_ptr_high++; } 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; } }