summaryrefslogtreecommitdiff
path: root/third_party/g7221/encode/encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/g7221/encode/encoder.c')
-rw-r--r--third_party/g7221/encode/encoder.c1125
1 files changed, 1125 insertions, 0 deletions
diff --git a/third_party/g7221/encode/encoder.c b/third_party/g7221/encode/encoder.c
new file mode 100644
index 00000000..0ec8cf85
--- /dev/null
+++ b/third_party/g7221/encode/encoder.c
@@ -0,0 +1,1125 @@
+/***************************************************************************
+**
+** 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: encoder.c
+
+ Purpose: Contains files used to implement the G.722.1 Annex C encoder
+
+ Design Notes:
+
+***************************************************************************/
+
+/***************************************************************************
+ Include files
+***************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "defs.h"
+#include "huff_def.h"
+#include "tables.h"
+#include "count.h"
+
+/***************************************************************************
+ Function: encoder
+
+ Syntax: void encoder(Word16 number_of_available_bits,
+ Word16 number_of_regions,
+ Word16 mlt_coefs,
+ Word16 mag_shift,
+ Word16 out_words)
+
+ inputs: number_of_available_bits
+ number_of_regions
+ mag_shift
+ mlt_coefs[DCT_LENGTH]
+
+ outputs: out_words[MAX_BITS_PER_FRAME/16]
+
+
+ Description: Encodes the mlt coefs into out_words using G.722.1 Annex C
+
+
+ WMOPS: 7kHz | 24kbit | 32kbit
+ -------|--------------|----------------
+ AVG | 0.93 | 1.04
+ -------|--------------|----------------
+ MAX | 1.20 | 1.28
+ -------|--------------|----------------
+
+ 14kHz | 24kbit | 32kbit | 48kbit
+ -------|--------------|----------------|----------------
+ AVG | 1.39 | 1.71 | 2.01
+ -------|--------------|----------------|----------------
+ MAX | 2.00 | 2.30 | 2.52
+ -------|--------------|----------------|----------------
+
+***************************************************************************/
+
+void encoder(Word16 number_of_available_bits,
+ Word16 number_of_regions,
+ Word16 *mlt_coefs,
+ Word16 mag_shift,
+ Word16 *out_words)
+{
+
+ Word16 num_categorization_control_bits;
+ Word16 num_categorization_control_possibilities;
+ Word16 number_of_bits_per_frame;
+ Word16 number_of_envelope_bits;
+ Word16 categorization_control;
+ Word16 region;
+ Word16 absolute_region_power_index[MAX_NUMBER_OF_REGIONS];
+ Word16 power_categories[MAX_NUMBER_OF_REGIONS];
+ Word16 category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1];
+ Word16 drp_num_bits[MAX_NUMBER_OF_REGIONS+1];
+ UWord16 drp_code_bits[MAX_NUMBER_OF_REGIONS+1];
+ Word16 region_mlt_bit_counts[MAX_NUMBER_OF_REGIONS];
+ UWord32 region_mlt_bits[4*MAX_NUMBER_OF_REGIONS];
+ Word16 mag_shift_offset;
+
+ Word16 temp;
+
+ /* initialize variables */
+ test();
+ if (number_of_regions == NUMBER_OF_REGIONS)
+ {
+ num_categorization_control_bits = NUM_CATEGORIZATION_CONTROL_BITS;
+ move16();
+ num_categorization_control_possibilities = NUM_CATEGORIZATION_CONTROL_POSSIBILITIES;
+ move16();
+ }
+ else
+ {
+ num_categorization_control_bits = MAX_NUM_CATEGORIZATION_CONTROL_BITS;
+ move16();
+ num_categorization_control_possibilities = MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES;
+ move16();
+ }
+
+ number_of_bits_per_frame = number_of_available_bits;
+ move16();
+
+ for (region=0; region<number_of_regions; region++)
+ {
+ region_mlt_bit_counts[region] = 0;
+ move16();
+ }
+
+ /* Estimate power envelope. */
+ number_of_envelope_bits = compute_region_powers(mlt_coefs,
+ mag_shift,
+ drp_num_bits,
+ drp_code_bits,
+ absolute_region_power_index,
+ number_of_regions);
+
+ /* Adjust number of available bits based on power envelope estimate */
+ temp = sub(number_of_available_bits,number_of_envelope_bits);
+ number_of_available_bits = sub(temp,num_categorization_control_bits);
+
+ /* get categorizations */
+ categorize(number_of_available_bits,
+ number_of_regions,
+ num_categorization_control_possibilities,
+ absolute_region_power_index,
+ power_categories,
+ category_balances);
+
+ /* Adjust absolute_region_category_index[] for mag_shift.
+ This assumes that REGION_POWER_STEPSIZE_DB is defined
+ to be exactly 3.010299957 or 20.0 times log base 10
+ of square root of 2. */
+ temp = shl(mag_shift,1);
+ mag_shift_offset = add(temp,REGION_POWER_TABLE_NUM_NEGATIVES);
+
+ for (region=0; region<number_of_regions; region++)
+ {
+ absolute_region_power_index[region] = add(absolute_region_power_index[region],mag_shift_offset);
+ move16();
+ }
+
+ /* adjust the absolute power region index based on the mlt coefs */
+ adjust_abs_region_power_index(absolute_region_power_index,mlt_coefs,number_of_regions);
+
+
+ /* quantize and code the mlt coefficients based on categorizations */
+ vector_quantize_mlts(number_of_available_bits,
+ number_of_regions,
+ num_categorization_control_possibilities,
+ mlt_coefs,
+ absolute_region_power_index,
+ power_categories,
+ category_balances,
+ &categorization_control,
+ region_mlt_bit_counts,
+ region_mlt_bits);
+
+ /* stuff bits into words */
+ bits_to_words(region_mlt_bits,
+ region_mlt_bit_counts,
+ drp_num_bits,
+ drp_code_bits,
+ out_words,
+ categorization_control,
+ number_of_regions,
+ num_categorization_control_bits,
+ number_of_bits_per_frame);
+
+}
+
+/***************************************************************************
+ Function: bits_to_words
+
+ Syntax: bits_to_words(UWord32 *region_mlt_bits,
+ Word16 *region_mlt_bit_counts,
+ Word16 *drp_num_bits,
+ UWord16 *drp_code_bits,
+ Word16 *out_words,
+ Word16 categorization_control,
+ Word16 number_of_regions,
+ Word16 num_categorization_control_bits,
+ Word16 number_of_bits_per_frame)
+
+
+ Description: Stuffs the bits into words for output
+
+ WMOPS: 7kHz | 24kbit | 32kbit
+ -------|--------------|----------------
+ AVG | 0.09 | 0.12
+ -------|--------------|----------------
+ MAX | 0.10 | 0.13
+ -------|--------------|----------------
+
+ 14kHz | 24kbit | 32kbit | 48kbit
+ -------|--------------|----------------|----------------
+ AVG | 0.12 | 0.15 | 0.19
+ -------|--------------|----------------|----------------
+ MAX | 0.14 | 0.17 | 0.21
+ -------|--------------|----------------|----------------
+
+***************************************************************************/
+void bits_to_words(UWord32 *region_mlt_bits,
+ Word16 *region_mlt_bit_counts,
+ Word16 *drp_num_bits,
+ UWord16 *drp_code_bits,
+ Word16 *out_words,
+ Word16 categorization_control,
+ Word16 number_of_regions,
+ Word16 num_categorization_control_bits,
+ Word16 number_of_bits_per_frame)
+{
+ Word16 out_word_index = 0;
+ Word16 j;
+ Word16 region;
+ Word16 out_word;
+ Word16 region_bit_count;
+ Word16 current_word_bits_left;
+ UWord16 slice;
+ Word16 out_word_bits_free = 16;
+ UWord32 *in_word_ptr;
+ UWord32 current_word;
+
+ Word32 acca;
+ Word32 accb;
+ Word16 temp;
+
+ /* First set up the categorization control bits to look like one more set of region power bits. */
+ out_word = 0;
+ move16();
+
+ drp_num_bits[number_of_regions] = num_categorization_control_bits;
+ move16();
+
+ drp_code_bits[number_of_regions] = (UWord16)categorization_control;
+ move16();
+
+ /* These code bits are right justified. */
+ for (region=0; region <= number_of_regions; region++)
+ {
+ current_word_bits_left = drp_num_bits[region];
+ move16();
+
+ current_word = (UWord32)drp_code_bits[region];
+ move16();
+
+ j = sub(current_word_bits_left,out_word_bits_free);
+
+ test();
+ if (j >= 0)
+ {
+ temp = extract_l(L_shr(current_word,j));
+ out_word = add(out_word,temp);
+
+ out_words[out_word_index++] = out_word;
+ move16();
+
+ out_word_bits_free = 16;
+ move16();
+
+ out_word_bits_free = sub(out_word_bits_free,j);
+
+ acca = (current_word << out_word_bits_free);
+ out_word = extract_l(acca);
+ }
+ else
+ {
+ j = negate(j);
+
+ acca = (current_word << j);
+ accb = L_deposit_l(out_word);
+ acca = L_add(accb,acca);
+ out_word = extract_l(acca);
+
+ out_word_bits_free = sub(out_word_bits_free,current_word_bits_left);
+ }
+ }
+
+ /* These code bits are left justified. */
+
+ for (region=0;region<number_of_regions; region++)
+ {
+ accb = L_deposit_l(out_word_index);
+ accb = L_shl(accb,4);
+ accb = L_sub(accb,number_of_bits_per_frame);
+ test();
+ if(accb < 0)
+ {
+ temp = shl(region,2);
+ in_word_ptr = &region_mlt_bits[temp];
+ region_bit_count = region_mlt_bit_counts[region];
+ move16();
+
+ temp = sub(32,region_bit_count);
+ test();
+ if(temp > 0)
+ current_word_bits_left = region_bit_count;
+ else
+ current_word_bits_left = 32;
+
+ current_word = *in_word_ptr++;
+
+ acca = L_deposit_l(out_word_index);
+ acca = L_shl(acca,4);
+ acca = L_sub(acca,number_of_bits_per_frame);
+
+ /* from while loop */
+ test();
+ test();
+ logic16();
+ while ((region_bit_count > 0) && (acca < 0))
+ {
+ /* from while loop */
+ test();
+ test();
+ logic16();
+
+ temp = sub(current_word_bits_left,out_word_bits_free);
+ test();
+ if (temp >= 0)
+ {
+ temp = sub(32,out_word_bits_free);
+ accb = LU_shr(current_word,temp);
+ slice = (UWord16)extract_l(accb);
+
+ out_word = add(out_word,slice);
+
+ test();
+ current_word <<= out_word_bits_free;
+
+ current_word_bits_left = sub(current_word_bits_left,out_word_bits_free);
+ out_words[out_word_index++] = extract_l(out_word);
+ move16();
+
+ out_word = 0;
+ move16();
+
+ out_word_bits_free = 16;
+ move16();
+ }
+ else
+ {
+ temp = sub(32,current_word_bits_left);
+ accb = LU_shr(current_word,temp);
+ slice = (UWord16)extract_l(accb);
+
+ temp = sub(out_word_bits_free,current_word_bits_left);
+ test();
+ accb = slice << temp;
+ acca = L_deposit_l(out_word);
+ acca = L_add(acca,accb);
+ out_word = extract_l(acca);
+ out_word_bits_free = sub(out_word_bits_free,current_word_bits_left);
+
+ current_word_bits_left = 0;
+ move16();
+ }
+
+ test();
+ if (current_word_bits_left == 0)
+ {
+ current_word = *in_word_ptr++;
+ region_bit_count = sub(region_bit_count,32);
+
+ /* current_word_bits_left = MIN(32,region_bit_count); */
+ temp = sub(32,region_bit_count);
+ test();
+ if(temp > 0)
+ current_word_bits_left = region_bit_count;
+ else
+ current_word_bits_left = 32;
+
+ }
+ acca = L_deposit_l(out_word_index);
+ acca = L_shl(acca,4);
+ acca = L_sub(acca,number_of_bits_per_frame);
+ }
+ accb = L_deposit_l(out_word_index);
+ accb = L_shl(accb,4);
+ accb = L_sub(accb,number_of_bits_per_frame);
+ }
+ }
+
+ /* Fill out with 1's. */
+
+ test();
+ while (acca < 0)
+ {
+ test();
+ current_word = 0x0000ffff;
+ move32();
+
+ temp = sub(16,out_word_bits_free);
+ acca = LU_shr(current_word,temp);
+ slice = (UWord16)extract_l(acca);
+
+ out_word = add(out_word,slice);
+ out_words[out_word_index++] = out_word;
+ move16();
+
+ out_word = 0;
+ move16();
+
+ out_word_bits_free = 16;
+ move16();
+
+ acca = L_deposit_l(out_word_index);
+ acca = L_shl(acca,4);
+ acca = L_sub(acca,number_of_bits_per_frame);
+ }
+}
+/***************************************************************************
+ Function: adjust_abs_region_power_index
+
+ Syntax: adjust_abs_region_power_index(Word16 *absolute_region_power_index,
+ Word16 *mlt_coefs,
+ Word16 number_of_regions)
+
+ inputs: *mlt_coefs
+ *absolute_region_power_index
+ number_of_regions
+
+ outputs: *absolute_region_power_index
+
+ Description: Adjusts the absolute power index
+
+
+ WMOPS: 7kHz | 24kbit | 32kbit
+ -------|--------------|----------------
+ AVG | 0.03 | 0.03
+ -------|--------------|----------------
+ MAX | 0.12 | 0.12
+ -------|--------------|----------------
+
+ 14kHz | 24kbit | 32kbit | 48kbit
+ -------|--------------|----------------|----------------
+ AVG | 0.03 | 0.03 | 0.03
+ -------|--------------|----------------|----------------
+ MAX | 0.14 | 0.14 | 0.14
+ -------|--------------|----------------|----------------
+
+***************************************************************************/
+void adjust_abs_region_power_index(Word16 *absolute_region_power_index,Word16 *mlt_coefs,Word16 number_of_regions)
+{
+ Word16 n,i;
+ Word16 region;
+ Word16 *raw_mlt_ptr;
+
+ Word32 acca;
+ Word16 temp;
+
+ for (region=0; region<number_of_regions; region++)
+ {
+ n = sub(absolute_region_power_index[region],39);
+ n = shr(n,1);
+
+ test();
+ if (n > 0)
+ {
+ temp = extract_l(L_mult0(region,REGION_SIZE));
+
+ raw_mlt_ptr = &mlt_coefs[temp];
+
+ for (i=0; i<REGION_SIZE; i++)
+ {
+ acca = L_shl(*raw_mlt_ptr,16);
+ acca = L_add(acca,32768L);
+ acca = L_shr(acca,n);
+ acca = L_shr(acca,16);
+ *raw_mlt_ptr++ = extract_l(acca);
+ }
+
+ temp = shl(n,1);
+ temp = sub(absolute_region_power_index[region],temp);
+ absolute_region_power_index[region] = temp;
+ move16();
+ }
+ }
+}
+
+/***************************************************************************
+ Function: compute_region_powers
+
+ Syntax: Word16 compute_region_powers(Word16 *mlt_coefs,
+ Word16 mag_shift,
+ Word16 *drp_num_bits,
+ UWord16 *drp_code_bits,
+ Word16 *absolute_region_power_index,
+ Word16 number_of_regions)
+ mlt_coefs[DCT_LENGTH];
+ mag_shift;
+ drp_num_bits[MAX_NUMBER_OF_REGIONS];
+ drp_code_bits[MAX_NUMBER_OF_REGIONS];
+ absolute_region_power_index[MAX_NUMBER_OF_REGIONS];
+ number_of_regions;
+
+ Description: Computes the power for each of the regions
+
+
+ WMOPS: 7kHz | 24kbit | 32kbit
+ -------|--------------|----------------
+ AVG | 0.09 | 0.09
+ -------|--------------|----------------
+ MAX | 0.13 | 0.13
+ -------|--------------|----------------
+
+ 14kHz | 24kbit | 32kbit | 48kbit
+ -------|--------------|----------------|----------------
+ AVG | 0.20 | 0.20 | 0.20
+ -------|--------------|----------------|----------------
+ MAX | 0.29 | 0.29 | 0.29
+ -------|--------------|----------------|----------------
+
+***************************************************************************/
+
+Word16 compute_region_powers(Word16 *mlt_coefs,
+ Word16 mag_shift,
+ Word16 *drp_num_bits,
+ UWord16 *drp_code_bits,
+ Word16 *absolute_region_power_index,
+ Word16 number_of_regions)
+{
+
+ Word16 *input_ptr;
+ Word32 long_accumulator;
+ Word16 itemp1;
+ Word16 power_shift;
+ Word16 region;
+ Word16 j;
+ Word16 differential_region_power_index[MAX_NUMBER_OF_REGIONS];
+ Word16 number_of_bits;
+
+ Word32 acca;
+ Word16 temp;
+ Word16 temp1;
+ Word16 temp2;
+
+
+ input_ptr = mlt_coefs;
+ for (region=0; region<number_of_regions; region++)
+ {
+ long_accumulator = L_deposit_l(0);
+
+ for (j=0; j<REGION_SIZE; j++)
+ {
+ itemp1 = *input_ptr++;
+ move16();
+ long_accumulator = L_mac0(long_accumulator,itemp1,itemp1);
+ }
+
+ power_shift = 0;
+ move16();
+
+ acca = (long_accumulator & 0x7fff0000L);
+ logic32();
+
+ test();
+ while (acca > 0)
+ {
+ test();
+ long_accumulator = L_shr(long_accumulator,1);
+
+ acca = (long_accumulator & 0x7fff0000L);
+ logic32();
+
+ power_shift = add(power_shift,1);
+ }
+
+ acca = L_sub(long_accumulator,32767);
+
+ temp = add(power_shift,15);
+ test();
+ test();
+ logic16();
+ while ((acca <= 0) && (temp >= 0))
+ {
+ test();
+ test();
+ logic16();
+
+ long_accumulator = L_shl(long_accumulator,1);
+ acca = L_sub(long_accumulator,32767);
+ power_shift--;
+ temp = add(power_shift,15);
+ }
+ long_accumulator = L_shr(long_accumulator,1);
+ /* 28963 corresponds to square root of 2 times REGION_SIZE(20). */
+ acca = L_sub(long_accumulator,28963);
+
+ test();
+ if (acca >= 0)
+ power_shift = add(power_shift,1);
+
+ acca = L_deposit_l(mag_shift);
+ acca = L_shl(acca,1);
+ acca = L_sub(power_shift,acca);
+ acca = L_add(35,acca);
+ acca = L_sub(acca,REGION_POWER_TABLE_NUM_NEGATIVES);
+ absolute_region_power_index[region] = extract_l(acca);
+ }
+
+
+ /* Before we differentially encode the quantized region powers, adjust upward the
+ valleys to make sure all the peaks can be accurately represented. */
+ temp = sub(number_of_regions,2);
+
+ for (region = temp; region >= 0; region--)
+ {
+ temp1 = sub(absolute_region_power_index[region+1],DRP_DIFF_MAX);
+ temp2 = sub(absolute_region_power_index[region],temp1);
+ test();
+ if (temp2 < 0)
+ {
+ absolute_region_power_index[region] = temp1;
+ move16();
+ }
+ }
+
+ /* The MLT is currently scaled too low by the factor
+ ENCODER_SCALE_FACTOR(=18318)/32768 * (1./sqrt(160).
+ This is the ninth power of 1 over the square root of 2.
+ So later we will add ESF_ADJUSTMENT_TO_RMS_INDEX (now 9)
+ to drp_code_bits[0]. */
+
+ /* drp_code_bits[0] can range from 1 to 31. 0 will be used only as an escape sequence. */
+ temp1 = sub(1,ESF_ADJUSTMENT_TO_RMS_INDEX);
+ temp2 = sub(absolute_region_power_index[0],temp1);
+ test();
+ if (temp2 < 0)
+ {
+ absolute_region_power_index[0] = temp1;
+ move16();
+ }
+
+ temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX);
+
+ /*
+ * The next line was corrected in Release 1.2
+ */
+
+ temp2 = sub(absolute_region_power_index[0], temp1);
+ test();
+ if (temp2 > 0)
+ {
+ absolute_region_power_index[0] = temp1;
+ move16();
+ }
+
+ differential_region_power_index[0] = absolute_region_power_index[0];
+ move16();
+
+ number_of_bits = 5;
+ move16();
+
+ drp_num_bits[0] = 5;
+ move16();
+
+ drp_code_bits[0] = (UWord16)add(absolute_region_power_index[0],ESF_ADJUSTMENT_TO_RMS_INDEX);
+ move16();
+
+ /* Lower limit the absolute region power indices to -8 and upper limit them to 31. Such extremes
+ may be mathematically impossible anyway.*/
+ for (region=1; region<number_of_regions; region++)
+ {
+ temp1 = sub(-8,ESF_ADJUSTMENT_TO_RMS_INDEX);
+ temp2 = sub(absolute_region_power_index[region],temp1);
+ test();
+ if (temp2 < 0)
+ {
+ absolute_region_power_index[region] = temp1;
+ move16();
+ }
+
+ temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX);
+ temp2 = sub(absolute_region_power_index[region],temp1);
+ test();
+ if (temp2 > 0)
+ {
+ absolute_region_power_index[region] = temp1;
+ move16();
+ }
+ }
+
+ for (region=1; region<number_of_regions; region++)
+ {
+ j = sub(absolute_region_power_index[region],absolute_region_power_index[region-1]);
+ temp = sub(j,DRP_DIFF_MIN);
+ test();
+ if (temp < 0)
+ {
+ j = DRP_DIFF_MIN;
+ }
+ j = sub(j,DRP_DIFF_MIN);
+ move16();
+ differential_region_power_index[region] = j;
+ move16();
+
+ temp = add(absolute_region_power_index[region-1],differential_region_power_index[region]);
+ temp = add(temp,DRP_DIFF_MIN);
+ absolute_region_power_index[region] = temp;
+ move16();
+
+ number_of_bits = add(number_of_bits,differential_region_power_bits[region][j]);
+ drp_num_bits[region] = differential_region_power_bits[region][j];
+ move16();
+ drp_code_bits[region] = differential_region_power_codes[region][j];
+ move16();
+ }
+
+ return (number_of_bits);
+}
+
+/***************************************************************************
+ Function: vector_quantize_mlts
+
+ Syntax: void vector_quantize_mlts(number_of_available_bits,
+ number_of_regions,
+ num_categorization_control_possibilities,
+ mlt_coefs,
+ absolute_region_power_index,
+ power_categories,
+ category_balances,
+ p_categorization_control,
+ region_mlt_bit_counts,
+ region_mlt_bits)
+
+ Word16 number_of_available_bits;
+ Word16 number_of_regions;
+ Word16 num_categorization_control_possibilities;
+ Word16 mlt_coefs[DCT_LENGTH];
+ Word16 absolute_region_power_index[MAX_NUMBER_OF_REGIONS];
+ Word16 power_categories[MAX_NUMBER_OF_REGIONS];
+ Word16 category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1];
+ Word16 *p_categorization_control;
+ Word16 region_mlt_bit_counts[MAX_NUMBER_OF_REGIONS];
+ Word32 region_mlt_bits[4*MAX_NUMBER_OF_REGIONS];
+
+ Description: Scalar quantized vector Huffman coding (SQVH)
+
+
+ WMOPS: 7kHz | 24kbit | 32kbit
+ -------|--------------|----------------
+ AVG | 0.57 | 0.65
+ -------|--------------|----------------
+ MAX | 0.78 | 0.83
+ -------|--------------|----------------
+
+ 14kHz | 24kbit | 32kbit | 48kbit
+ -------|--------------|----------------|----------------
+ AVG | 0.62 | 0.90 | 1.11
+ -------|--------------|----------------|----------------
+ MAX | 1.16 | 1.39 | 1.54
+ -------|--------------|----------------|----------------
+
+***************************************************************************/
+
+void vector_quantize_mlts(Word16 number_of_available_bits,
+ Word16 number_of_regions,
+ Word16 num_categorization_control_possibilities,
+ Word16 *mlt_coefs,
+ Word16 *absolute_region_power_index,
+ Word16 *power_categories,
+ Word16 *category_balances,
+ Word16 *p_categorization_control,
+ Word16 *region_mlt_bit_counts,
+ UWord32 *region_mlt_bits)
+{
+
+ Word16 *raw_mlt_ptr;
+ Word16 region;
+ Word16 category;
+ Word16 total_mlt_bits = 0;
+
+ Word16 temp;
+ Word16 temp1;
+ Word16 temp2;
+
+ /* Start in the middle of the categorization control range. */
+ temp = shr(num_categorization_control_possibilities,1);
+ temp = sub(temp,1);
+ for (*p_categorization_control = 0; *p_categorization_control < temp; (*p_categorization_control)++)
+ {
+ region = category_balances[*p_categorization_control];
+ move16();
+ power_categories[region] = add(power_categories[region],1);
+ move16();
+ }
+
+ for (region=0; region<number_of_regions; region++)
+ {
+ category = power_categories[region];
+ move16();
+ temp = extract_l(L_mult0(region,REGION_SIZE));
+ raw_mlt_ptr = &mlt_coefs[temp];
+ move16();
+ temp = sub(category,(NUM_CATEGORIES-1));
+ test();
+ if (temp < 0)
+ {
+ region_mlt_bit_counts[region] =
+ vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr,
+ &region_mlt_bits[shl(region,2)]);
+ }
+ else
+ {
+ region_mlt_bit_counts[region] = 0;
+ move16();
+ }
+ total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]);
+ }
+
+
+ /* If too few bits... */
+ temp = sub(total_mlt_bits,number_of_available_bits);
+ test();
+ test();
+ logic16();
+ while ((temp < 0) && (*p_categorization_control > 0))
+ {
+ test();
+ test();
+ logic16();
+ (*p_categorization_control)--;
+ region = category_balances[*p_categorization_control];
+ move16();
+
+ power_categories[region] = sub(power_categories[region],1);
+ move16();
+
+ total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]);
+ category = power_categories[region];
+ move16();
+
+ raw_mlt_ptr = &mlt_coefs[region*REGION_SIZE];
+ move16();
+
+ temp = sub(category,(NUM_CATEGORIES-1));
+ test();
+ if (temp < 0)
+ {
+ region_mlt_bit_counts[region] =
+ vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr,
+ &region_mlt_bits[shl(region,2)]);
+ }
+ else
+ {
+ region_mlt_bit_counts[region] = 0;
+ move16();
+ }
+ total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]);
+ temp = sub(total_mlt_bits,number_of_available_bits);
+ }
+
+ /* If too many bits... */
+ /* Set up for while loop test */
+ temp1 = sub(total_mlt_bits,number_of_available_bits);
+ temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1));
+ test();
+ test();
+ logic16();
+
+ while ((temp1 > 0) && (temp2 < 0))
+ {
+ /* operations for while contitions */
+ test();
+ test();
+ logic16();
+
+ region = category_balances[*p_categorization_control];
+ move16();
+
+ power_categories[region] = add(power_categories[region],1);
+ move16();
+
+ total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]);
+ category = power_categories[region];
+ move16();
+
+ temp = extract_l(L_mult0(region,REGION_SIZE));
+ raw_mlt_ptr = &mlt_coefs[temp];
+ move16();
+
+ temp = sub(category,(NUM_CATEGORIES-1));
+ test();
+ if (temp < 0)
+ {
+ region_mlt_bit_counts[region] =
+ vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr,
+ &region_mlt_bits[shl(region,2)]);
+ }
+ else
+ {
+ region_mlt_bit_counts[region] = 0;
+ move16();
+ }
+ total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]);
+ (*p_categorization_control)++;
+
+ temp1 = sub(total_mlt_bits,number_of_available_bits);
+ temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1));
+ }
+}
+
+/***************************************************************************
+ Function: vector_huffman
+
+ Syntax: Word16 vector_huffman(Word16 category,
+ Word16 power_index,
+ Word16 *raw_mlt_ptr,
+ UWord32 *word_ptr)
+
+ inputs: Word16 category
+ Word16 power_index
+ Word16 *raw_mlt_ptr
+
+ outputs: number_of_region_bits
+ *word_ptr
+
+
+ Description: Huffman encoding for each region based on category and power_index
+
+ WMOPS: 7kHz | 24kbit | 32kbit
+ -------|--------------|----------------
+ AVG | 0.03 | 0.03
+ -------|--------------|----------------
+ MAX | 0.04 | 0.04
+ -------|--------------|----------------
+
+ 14kHz | 24kbit | 32kbit | 48kbit
+ -------|--------------|----------------|----------------
+ AVG | 0.03 | 0.03 | 0.03
+ -------|--------------|----------------|----------------
+ MAX | 0.04 | 0.04 | 0.04
+ -------|--------------|----------------|----------------
+
+***************************************************************************/
+Word16 vector_huffman(Word16 category,
+ Word16 power_index,
+ Word16 *raw_mlt_ptr,
+ UWord32 *word_ptr)
+{
+
+
+ Word16 inv_of_step_size_times_std_dev;
+ Word16 j,n;
+ Word16 k;
+ Word16 number_of_region_bits;
+ Word16 number_of_non_zero;
+ Word16 vec_dim;
+ Word16 num_vecs;
+ Word16 kmax, kmax_plus_one;
+ Word16 index,signs_index;
+ Word16 *bitcount_table_ptr;
+ UWord16 *code_table_ptr;
+ Word32 code_bits;
+ Word16 number_of_code_bits;
+ UWord32 current_word;
+ Word16 current_word_bits_free;
+
+ Word32 acca;
+ Word32 accb;
+ Word16 temp;
+
+ Word16 mytemp; /* new variable in Release 1.2 */
+ Word16 myacca; /* new variable in Release 1.2 */
+
+
+ /* initialize variables */
+ vec_dim = vector_dimension[category];
+ move16();
+
+ num_vecs = number_of_vectors[category];
+ move16();
+
+ kmax = max_bin[category];
+ move16();
+
+ kmax_plus_one = add(kmax,1);
+ move16();
+
+ current_word = 0L;
+ move16();
+
+ current_word_bits_free = 32;
+ move16();
+
+ number_of_region_bits = 0;
+ move16();
+
+ /* set up table pointers */
+ bitcount_table_ptr = (Word16 *)table_of_bitcount_tables[category];
+ code_table_ptr = (UWord16 *) table_of_code_tables[category];
+
+ /* compute inverse of step size * standard deviation */
+ acca = L_mult(step_size_inverse_table[category],standard_deviation_inverse_table[power_index]);
+ acca = L_shr(acca,1);
+ acca = L_add(acca,4096);
+ acca = L_shr(acca,13);
+
+ /*
+ * The next two lines are new to Release 1.2
+ */
+
+ mytemp = acca & 0x3;
+ acca = L_shr(acca,2);
+
+ inv_of_step_size_times_std_dev = extract_l(acca);
+
+
+ for (n=0; n<num_vecs; n++)
+ {
+ index = 0;
+ move16();
+
+ signs_index = 0;
+ move16();
+
+ number_of_non_zero = 0;
+ move16();
+
+ for (j=0; j<vec_dim; j++)
+ {
+ k = abs_s(*raw_mlt_ptr);
+
+ acca = L_mult(k,inv_of_step_size_times_std_dev);
+ acca = L_shr(acca,1);
+
+ /*
+ * The next four lines are new to Release 1.2
+ */
+
+ myacca = (Word16)L_mult(k,mytemp);
+ myacca = (Word16)L_shr(myacca,1);
+ myacca = (Word16)L_add(myacca,int_dead_zone_low_bits[category]);
+ myacca = (Word16)L_shr(myacca,2);
+
+ acca = L_add(acca,int_dead_zone[category]);
+
+ /*
+ * The next two lines are new to Release 1.2
+ */
+
+ acca = L_add(acca,myacca);
+ acca = L_shr(acca,13);
+
+ k = extract_l(acca);
+
+ test();
+ if (k != 0)
+ {
+ number_of_non_zero = add(number_of_non_zero,1);
+ signs_index = shl(signs_index,1);
+
+ test();
+ if (*raw_mlt_ptr > 0)
+ {
+ signs_index = add(signs_index,1);
+ }
+
+ temp = sub(k,kmax);
+ test();
+ if (temp > 0)
+ {
+ k = kmax;
+ move16();
+ }
+ }
+ acca = L_shr(L_mult(index,(kmax_plus_one)),1);
+ index = extract_l(acca);
+ index = add(index,k);
+ raw_mlt_ptr++;
+ }
+
+ code_bits = *(code_table_ptr+index);
+ number_of_code_bits = add((*(bitcount_table_ptr+index)),number_of_non_zero);
+ number_of_region_bits = add(number_of_region_bits,number_of_code_bits);
+
+ acca = code_bits << number_of_non_zero;
+ accb = L_deposit_l(signs_index);
+ acca = L_add(acca,accb);
+ code_bits = acca;
+ move32();
+
+ /* msb of codebits is transmitted first. */
+ j = sub(current_word_bits_free,number_of_code_bits);
+ test();
+ if (j >= 0)
+ {
+ test();
+ acca = code_bits << j;
+ current_word = L_add(current_word,acca);
+ current_word_bits_free = j;
+ move16();
+ }
+ else
+ {
+ j = negate(j);
+ acca = L_shr(code_bits,j);
+ current_word = L_add(current_word,acca);
+
+ *word_ptr++ = current_word;
+ move16();
+
+ current_word_bits_free = sub(32,j);
+ test();
+ current_word = code_bits << current_word_bits_free;
+ }
+ }
+
+ *word_ptr++ = current_word;
+ move16();
+
+ return (number_of_region_bits);
+}
+
+