diff options
Diffstat (limited to 'third_party/g7221/decode/dct4_s.c')
-rw-r--r-- | third_party/g7221/decode/dct4_s.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/third_party/g7221/decode/dct4_s.c b/third_party/g7221/decode/dct4_s.c new file mode 100644 index 00000000..84514824 --- /dev/null +++ b/third_party/g7221/decode/dct4_s.c @@ -0,0 +1,480 @@ +/******************************************************************************** +** +** ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C +** > Software Release 2.1 (2008-06) +** (Simple repackaging; no change from 2005-05 Release 2.0 code) +** +** © 2004 Polycom, Inc. +** +** All rights reserved. +** +********************************************************************************/ + +/******************************************************************************** +* Filename: dct_type_iv_s.c +* +* Purpose: Discrete Cosine Transform, Type IV used for inverse 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_s.h" + +/*************************************************************************** + External variable declarations +***************************************************************************/ +extern Word16 syn_bias_7khz[DCT_LENGTH]; +extern Word16 dither[DCT_LENGTH]; +extern Word16 max_dither[MAX_DCT_LENGTH]; + +extern Word16 dct_core_s[DCT_LENGTH_DIV_32][DCT_LENGTH_DIV_32]; +extern cos_msin_t s_cos_msin_2[DCT_LENGTH_DIV_32]; +extern cos_msin_t s_cos_msin_4[DCT_LENGTH_DIV_16]; +extern cos_msin_t s_cos_msin_8[DCT_LENGTH_DIV_8]; +extern cos_msin_t s_cos_msin_16[DCT_LENGTH_DIV_4]; +extern cos_msin_t s_cos_msin_32[DCT_LENGTH_DIV_2]; +extern cos_msin_t s_cos_msin_64[DCT_LENGTH]; +extern cos_msin_t *s_cos_msin_table[]; + +/******************************************************************************** + Function: dct_type_iv_s + + Syntax: void dct_type_iv_s (Word16 *input,Word16 *output,Word16 dct_length) + + + Description: Discrete Cosine Transform, Type IV used for inverse MLT + + Design Notes: + + WMOPS: 7kHz | 24kbit | 32kbit + -------|--------------|---------------- + AVG | 1.74 | 1.74 + -------|--------------|---------------- + MAX | 1.74 | 1.74 + -------|--------------|---------------- + + 14kHz | 24kbit | 32kbit | 48kbit + -------|--------------|----------------|---------------- + AVG | 3.62 | 3.62 | 3.62 + -------|--------------|----------------|---------------- + MAX | 3.62 | 3.62 | 3.62 + -------|--------------|----------------|---------------- + +********************************************************************************/ + +void dct_type_iv_s (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 set_span, set_count, set_count_log, pairs_left, sets_left; + Word16 i,k; + Word16 index; + Word16 dummy; + Word32 sum; + cos_msin_t **table_ptr_ptr, *cos_msin_ptr; + + Word32 acca; + Word16 temp; + + Word16 dct_length_log; + Word16 *dither_ptr; + + /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* Do the sum/difference butterflies, the first part of */ + /* converting one N-point transform into 32 - 10 point transforms */ + /* transforms, where N = 1 << DCT_LENGTH_LOG. */ + /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + test(); + if (dct_length==DCT_LENGTH) + { + dct_length_log = DCT_LENGTH_LOG; + move16(); + dither_ptr = dither; + move16(); + } + else + { + dct_length_log = MAX_DCT_LENGTH_LOG; + move16(); + dither_ptr = max_dither; + move16(); + } + + in_buffer = input; + move16(); + out_buffer = buffer_a; + move16(); + + index=0; + move16(); + + i=0; + move16(); + + 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 = 1 << (DCT_LENGTH_LOG - set_count_log); */ + set_span = shr(dct_length,set_count_log); + + set_count = shl(1,set_count_log); + in_ptr = in_buffer; + move16(); + next_out_base = out_buffer; + move16(); + + /*=====================================*/ + /* Loop over all the sets of this size */ + /*=====================================*/ + temp = sub(index,1); + test(); + if(temp < 0) + { + for (sets_left = set_count;sets_left > 0;sets_left--) + { + + /*||||||||||||||||||||||||||||||||||||||||||||*/ + /* Set up output pointers for the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||*/ + /* pointer arithmetic */ + out_ptr_low = next_out_base; + move16(); + next_out_base += set_span; + move16(); + out_ptr_high = next_out_base; + move16(); + + /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ + /* Loop over all the butterflies in the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ + + do + { + in_val_low = *in_ptr++; + move16(); + in_val_high = *in_ptr++; + move16(); + + /* BEST METHOD OF GETTING RID OF BIAS, BUT COMPUTATIONALLY UNPLEASANT */ + /* ALTERNATIVE METHOD, SMEARS BIAS OVER THE ENTIRE FRAME, COMPUTATIONALLY SIMPLEST. */ + /* IF THIS WORKS, IT'S PREFERABLE */ + + dummy = add(in_val_low,dither_ptr[i++]); + acca = L_add(dummy,in_val_high); + out_val_low = extract_l(L_shr(acca,1)); + + dummy = add(in_val_low,dither_ptr[i++]); + acca = L_add(dummy,-in_val_high); + out_val_high = extract_l(L_shr(acca,1)); + + *out_ptr_low++ = out_val_low; + move16(); + *--out_ptr_high = out_val_high; + move16(); + + test(); + + /* this involves comparison of pointers */ + /* pointer arithmetic */ + + } while (out_ptr_low < out_ptr_high); + + } /* End of loop over sets of the current size */ + } + else + { + for (sets_left = set_count; sets_left > 0; sets_left--) + { + /*||||||||||||||||||||||||||||||||||||||||||||*/ + /* Set up output pointers for the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||*/ + + out_ptr_low = next_out_base; + move16(); + next_out_base += set_span; + move16(); + out_ptr_high = next_out_base; + move16(); + + /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ + /* Loop over all the butterflies in the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||||||||*/ + + do + { + in_val_low = *in_ptr++; + move16(); + in_val_high = *in_ptr++; + move16(); + + out_val_low = add(in_val_low,in_val_high); + out_val_high = add(in_val_low,negate(in_val_high)); + + *out_ptr_low++ = out_val_low; + move16(); + *--out_ptr_high = out_val_high; + move16(); + + 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(); + + test(); + if (out_buffer == buffer_a) + { + out_buffer = buffer_b; + move16(); + } + else + { + out_buffer = buffer_a; + move16(); + } + + index = add(index,1); + } /* End of loop over set sizes */ + + + /*++++++++++++++++++++++++++++++++*/ + /* Do 32 - 10 point transforms */ + /*++++++++++++++++++++++++++++++++*/ + + pair_ptr = in_buffer; + move16(); + buffer_swap = buffer_c; + move16(); + + for (pairs_left = 1 << (dct_length_log - 1); pairs_left > 0; pairs_left--) + { + for ( k=0; k<CORE_SIZE; k++ ) + { + sum=0L; + move32(); + + for ( i=0; i<CORE_SIZE; i++ ) + { + sum = L_mac(sum, pair_ptr[i],dct_core_s[i][k]); + } + buffer_swap[k] = round(sum); + } + + pair_ptr += CORE_SIZE; + move16(); + buffer_swap += CORE_SIZE; + move16(); + } + + for (i=0;i<dct_length;i++) + { + in_buffer[i] = buffer_c[i]; + move16(); + } + + table_ptr_ptr = s_cos_msin_table; + move16(); + + /*++++++++++++++++++++++++++++++*/ + /* Perform rotation butterflies */ + /*++++++++++++++++++++++++++++++*/ + index=0; + move16(); + + for (set_count_log = dct_length_log - 2 ; set_count_log >= 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; + move16(); + } + else + { + next_out_base = out_buffer; + move16(); + } + + /*=====================================*/ + /* 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); + in_ptr_high = in_ptr_low + temp; + move16(); + + next_in_base += set_span; + move16(); + + out_ptr_low = next_out_base; + move16(); + + next_out_base += set_span; + move16(); + out_ptr_high = next_out_base; + move16(); + + cos_msin_ptr = *table_ptr_ptr; + move16(); + + /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ + /* Loop over all the butterfly pairs in the current set */ + /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ + + do + { + in_low_even = *in_ptr_low++; + move16(); + in_low_odd = *in_ptr_low++; + move16(); + in_high_even = *in_ptr_high++; + move16(); + in_high_odd = *in_ptr_high++; + move16(); + 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; + move32(); + + sum = L_mac(sum,cos_even,in_low_even); + sum = L_mac(sum,negate(msin_even),in_high_even); + out_low_even = round(L_shl(sum,1)); + + sum = 0L; + move32(); + sum = L_mac(sum,msin_even,in_low_even); + sum = L_mac(sum,cos_even,in_high_even); + out_high_even = round(L_shl(sum,1)); + + sum = 0L; + move32(); + sum = L_mac(sum,cos_odd,in_low_odd); + sum = L_mac(sum,msin_odd,in_high_odd); + out_low_odd = round(L_shl(sum,1)); + + sum = 0L; + move32(); + sum = L_mac(sum,msin_odd,in_low_odd); + sum = L_mac(sum,negate(cos_odd),in_high_odd); + out_high_odd = round(L_shl(sum,1)); + + *out_ptr_low++ = out_low_even; + move16(); + *--out_ptr_high = out_high_even; + move16(); + *out_ptr_low++ = out_low_odd; + move16(); + *--out_ptr_high = out_high_odd; + move16(); + + 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; + move16(); + in_buffer = out_buffer; + move16(); + out_buffer = buffer_swap; + move16(); + + index = add(index,1); + table_ptr_ptr++; + } + /*------------------------------------ + + ADD IN BIAS FOR OUTPUT + + -----------------------------------*/ + if (dct_length==DCT_LENGTH) + { + for(i=0;i<320;i++) + { + sum = L_add(output[i],syn_bias_7khz[i]); + acca = L_sub(sum,32767); + test(); + if (acca > 0) + { + sum = 32767L; + move32(); + } + acca = L_add(sum,32768L); + test(); + if (acca < 0) + { + sum = -32768L; + move32(); + } + output[i] = extract_l(sum); + } + } +} + |