123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- /********************************************************************************
- **
- ** 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_nocheck(dct_length,set_count_log);
-
- set_count = shl_nocheck(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++]);
- // blp: addition of two 16bits vars, there's no way
- // they'll overflow a 32bit var
- //acca = L_add(dummy,in_val_high);
- acca = dummy + in_val_high;
- out_val_low = extract_l(L_shr_nocheck(acca,1));
-
- dummy = add(in_val_low,dither_ptr[i++]);
- // blp: addition of two 16bits vars, there's no way
- // they'll overflow a 32bit var
- //acca = L_add(dummy,-in_val_high);
- acca = dummy - in_val_high;
- out_val_high = extract_l(L_shr_nocheck(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++ )
- {
- #if PJ_HAS_INT64
- /* blp: danger danger! not really compatible but faster */
- pj_int64_t sum64=0;
- move32();
-
- for ( i=0; i<CORE_SIZE; i++ )
- {
- sum64 += L_mult(pair_ptr[i], dct_core_s[i][k]);
- }
- sum = L_saturate(sum64);
- #else
- sum=0L;
- move32();
-
- for ( i=0; i<CORE_SIZE; i++ )
- {
- sum = L_mac(sum, pair_ptr[i],dct_core_s[i][k]);
- }
- #endif
- buffer_swap[k] = itu_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_nocheck(dct_length,set_count_log);
-
- set_count = shl_nocheck(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_nocheck(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 = itu_round(L_shl_nocheck(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 = itu_round(L_shl_nocheck(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 = itu_round(L_shl_nocheck(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 = itu_round(L_shl_nocheck(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++)
- {
- // blp: addition of two 16bits vars, there's no way
- // they'll overflow a 32bit var
- //sum = L_add(output[i],syn_bias_7khz[i]);
- sum = output[i] + syn_bias_7khz[i];
- acca = L_sub(sum,32767);
- test();
- if (acca > 0)
- {
- sum = 32767L;
- move32();
- }
- // blp: addition of two 16bits vars, there's no way
- // they'll overflow 32bit var
- //acca = L_add(sum,32768L);
- acca = sum + 32768;
- test();
- if (acca < 0)
- {
- sum = -32768L;
- move32();
- }
- output[i] = extract_l(sum);
- }
- }
- }
|