/*************************************************************************** ** ** 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: decoder.c Purpose: Contains files used to implement the G.722.1 Annex C decoder Design Notes: ***************************************************************************/ /*************************************************************************** Include files ***************************************************************************/ #include "defs.h" #include "tables.h" #include "huff_def.h" #include "count.h" /*************************************************************************** Function: decoder Syntax: void decoder(Bit_Obj *bitobj, Rand_Obj *randobj, Word16 number_of_regions, Word16 *decoder_mlt_coefs, Word16 *p_mag_shift, Word16 *p_old_mag_shift, Word16 *old_decoder_mlt_coefs, Word16 frame_error_flag) inputs: Bit_Obj *bitobj Rand_Obj *randobj Word16 number_of_regions Word16 *p_old_mag_shift Word16 *old_decoder_mlt_coefs Word16 frame_error_flag outputs: Word16 *decoder_mlt_coefs, Word16 *p_mag_shift, Description: Decodes the out_words into mlt coefs using G.722.1 Annex C Design Notes: WMOPS: 7kHz | 24kbit | 32kbit -------|-------------|---------------- AVG | 0.84 | 0.94 -------|-------------|---------------- MAX | 0.90 | 1.00 -------|-------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|-------------|----------------|---------------- AVG | 1.31 | 1.56 | 1.88 -------|-------------|----------------|---------------- MAX | 1.59 | 1.80 | 1.98 -------|-------------|----------------|---------------- ***************************************************************************/ void decoder(Bit_Obj *bitobj, Rand_Obj *randobj, Word16 number_of_regions, Word16 *decoder_mlt_coefs, Word16 *p_mag_shift, Word16 *p_old_mag_shift, Word16 *old_decoder_mlt_coefs, Word16 frame_error_flag) { Word16 absolute_region_power_index[MAX_NUMBER_OF_REGIONS]; Word16 decoder_power_categories[MAX_NUMBER_OF_REGIONS]; Word16 decoder_category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1]; UWord16 categorization_control; Word16 decoder_region_standard_deviation[MAX_NUMBER_OF_REGIONS]; Word16 i; Word16 num_categorization_control_bits; Word16 num_categorization_control_possibilities; Word16 number_of_coefs; Word16 number_of_valid_coefs; 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(); number_of_coefs = DCT_LENGTH; move16(); number_of_valid_coefs = NUMBER_OF_VALID_COEFS; move16(); } else { num_categorization_control_bits = MAX_NUM_CATEGORIZATION_CONTROL_BITS; move16(); num_categorization_control_possibilities = MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES; move16(); number_of_coefs = MAX_DCT_LENGTH; move16(); number_of_valid_coefs = MAX_NUMBER_OF_VALID_COEFS; move16(); } test(); if (frame_error_flag == 0) { /* convert the bits to absolute region power index and decoder_region_standard_deviation */ decode_envelope(bitobj, number_of_regions, decoder_region_standard_deviation, absolute_region_power_index, p_mag_shift); /* fill the categorization_control with NUM_CATEGORIZATION_CONTROL_BITS */ categorization_control = 0; for (i=0; inext_bit); } bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,num_categorization_control_bits); /* obtain decoder power categories and category balances */ /* based on the absolute region power index */ categorize(bitobj->number_of_bits_left, number_of_regions, num_categorization_control_possibilities, absolute_region_power_index, decoder_power_categories, decoder_category_balances); /* perform adjustmaents to the power categories and category balances based on the cat control */ rate_adjust_categories(categorization_control, decoder_power_categories, decoder_category_balances); /* decode the quantized bits into mlt coefs */ decode_vector_quantized_mlt_indices(bitobj, randobj, number_of_regions, decoder_region_standard_deviation, decoder_power_categories, decoder_mlt_coefs); /* test for frame errors */ test_4_frame_errors(bitobj, number_of_regions, num_categorization_control_possibilities, &frame_error_flag, categorization_control, absolute_region_power_index); } /* perform error handling operations */ error_handling(number_of_coefs, number_of_valid_coefs, &frame_error_flag, decoder_mlt_coefs, old_decoder_mlt_coefs, p_mag_shift, p_old_mag_shift); } /*************************************************************************** Function: decode_envelope Syntax: void decode_envelope(Bit_Obj *bitobj, Word16 number_of_regions, Word16 *decoder_region_standard_deviation, Word16 *absolute_region_power_index, Word16 *p_mag_shift) inputs: Bit_Obj *bitobj Word16 number_of_regions outputs: Word16 *decoder_region_standard_deviation Word16 *absolute_region_power_index Word16 *p_mag_shift Description: Recover differential_region_power_index from code bits Design Notes: WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.04 | 0.04 -------|--------------|---------------- MAX | 0.05 | 0.05 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.08 | 0.08 | 0.08 -------|--------------|----------------|---------------- MAX | 0.10 | 0.10 | 0.10 -------|--------------|----------------|---------------- ***************************************************************************/ void decode_envelope(Bit_Obj *bitobj, Word16 number_of_regions, Word16 *decoder_region_standard_deviation, Word16 *absolute_region_power_index, Word16 *p_mag_shift) { Word16 region; Word16 i; Word16 index; Word16 differential_region_power_index[MAX_NUMBER_OF_REGIONS]; Word16 max_index; Word16 temp; Word16 temp1; Word16 temp2; Word32 acca; index = 0; move16(); /* get 5 bits from the current code word */ for (i=0; i<5; i++) { get_next_bit(bitobj); index = shl_nocheck(index,1); index = add(index,bitobj->next_bit); } bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,5); /* ESF_ADJUSTMENT_TO_RMS_INDEX compensates for the current (9/30/96) IMLT being scaled to high by the ninth power of sqrt(2). */ differential_region_power_index[0] = sub(index,ESF_ADJUSTMENT_TO_RMS_INDEX); move16(); /* obtain differential_region_power_index */ for (region=1; regionnext_bit == 0) { index = differential_region_power_decoder_tree[region][index][0]; move16(); } else { index = differential_region_power_decoder_tree[region][index][1]; move16(); } bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,1); test(); } while (index > 0); differential_region_power_index[region] = negate(index); move16(); } /* Reconstruct absolute_region_power_index[] from differential_region_power_index[]. */ absolute_region_power_index[0] = differential_region_power_index[0]; move16(); for (region=1; region 0) { max_index = i; move16(); } temp = add(temp,int_region_standard_deviation_table[i]); } i = 9; move16(); temp1 = sub(temp,8); temp2 = sub(max_index,28); test(); test(); logic16(); test(); logic16(); while ((i >= 0) && ((temp1 >= 0) || (temp2 > 0))) { i = sub(i,1); temp = shr_nocheck(temp,1); max_index = sub(max_index,2); temp1 = sub(temp,8); temp2 = sub(max_index,28); test(); test(); logic16(); test(); logic16(); } *p_mag_shift = i; move16(); /* pointer arithmetic */ temp = (Word16 )(REGION_POWER_TABLE_NUM_NEGATIVES + (*p_mag_shift * 2)); for (region=0; region 0) { region = decoder_category_balances[i++]; move16(); decoder_power_categories[region] = add(decoder_power_categories[region],1); move16(); categorization_control = sub(categorization_control,1); } } /*************************************************************************** Function: decode_vector_quantized_mlt_indices Syntax: void decode_vector_quantized_mlt_indices(Bit_Obj *bitobj, Rand_Obj *randobj, Word16 number_of_regions, Word16 *decoder_region_standard_deviation, Word16 *decoder_power_categories, Word16 *decoder_mlt_coefs) inputs: Bit_Obj *bitobj Rand_Obj *randobj Word16 number_of_regions Word16 *decoder_region_standard_deviation Word16 *decoder_power_categories outputs: Word16 *decoder_mlt_coefs Description: Decode MLT coefficients Design Notes: WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.60 | 0.72 -------|--------------|---------------- MAX | 0.67 | 0.76 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.77 | 0.98 | 1.28 -------|--------------|----------------|---------------- MAX | 1.05 | 1.18 | 1.36 -------|--------------|----------------|---------------- ***************************************************************************/ void decode_vector_quantized_mlt_indices(Bit_Obj *bitobj, Rand_Obj *randobj, Word16 number_of_regions, Word16 *decoder_region_standard_deviation, Word16 *decoder_power_categories, Word16 *decoder_mlt_coefs) { Word16 standard_deviation; Word16 *decoder_mlt_ptr; Word16 decoder_mlt_value; Word16 noifillpos; Word16 noifillneg; Word16 noise_fill_factor[3] = {5793,8192,23170}; Word16 region; Word16 category; Word16 j,n; Word16 k[MAX_VECTOR_DIMENSION]; Word16 vec_dim; Word16 num_vecs; Word16 index; Word16 bit=0; Word16 signs_index=0; Word16 num_sign_bits; Word16 ran_out_of_bits_flag; Word16 *decoder_table_ptr; Word16 random_word; Word16 temp1; Word16 temp; Word32 acca; ran_out_of_bits_flag = 0; move16(); for (region=0; regionnumber_of_bits_left <= 0) { ran_out_of_bits_flag = 1; move16(); break; } get_next_bit(bitobj); test(); if (bitobj->next_bit == 0) { temp = shl_nocheck(index,1); index = (Word16)*(decoder_table_ptr + temp); move16(); } else { temp = shl_nocheck(index,1); index = (Word16)*(decoder_table_ptr + temp + 1); move16(); } bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,1); test(); } while (index > 0); test(); if (ran_out_of_bits_flag != 0) break; index = negate(index); /* convert index into array used to access the centroid table */ /* get the number of sign bits in the index */ num_sign_bits = index_to_array(index,k,category); temp = sub(bitobj->number_of_bits_left,num_sign_bits); test(); if (temp >= 0) { test(); if (num_sign_bits != 0) { signs_index = 0; move16(); for (j=0; jnext_bit); bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,1); } temp = sub(num_sign_bits,1); bit = shl_nocheck(1,(temp)); } for (j=0; jnumber_of_bits_left = sub(bitobj->number_of_bits_left,1); } /**************************************************************************************** Function: index_to_array Syntax: number_of_non_zero = index_to_array(Word16 index, Word16 array[MAX_VECTOR_DIMENSION], Word16 category) inputs: Word16 index Word16 category outputs: Word16 array[MAX_VECTOR_DIMENSION] - used in decoder to access mlt_quant_centroid table Word16 number_of_non_zero - number of non zero elements in the array Description: Computes an array of sign bits with the length of the category vector Returns the number of sign bits and the array WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.00 | 0.00 -------|--------------|---------------- MAX | 0.00 | 0.00 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.00 | 0.00 | 0.00 -------|--------------|----------------|---------------- MAX | 0.00 | 0.00 | 0.00 -------|--------------|----------------|---------------- ****************************************************************************************/ Word16 index_to_array(Word16 index,Word16 *array,Word16 category) { Word16 j,q,p; Word16 number_of_non_zero; Word16 max_bin_plus_one; Word16 inverse_of_max_bin_plus_one; Word16 temp; number_of_non_zero = 0; move16(); p = index; move16(); max_bin_plus_one = add(max_bin[category],1); inverse_of_max_bin_plus_one = max_bin_plus_one_inverse[category]; move16(); temp = sub(vector_dimension[category],1); for (j=temp; j>=0; j--) { q = mult(p,inverse_of_max_bin_plus_one); temp = extract_l(L_mult0(q,max_bin_plus_one)); array[j] = sub(p,temp); move16(); p = q; move16(); temp = array[j]; move16(); test(); if (temp != 0) number_of_non_zero = add(number_of_non_zero,1); } return(number_of_non_zero); } /*************************************************************************** Function: test_4_frame_errors Syntax: void test_4_frame_errors(Bit_Obj *bitobj, Word16 number_of_regions, Word16 num_categorization_control_possibilities, Word16 *frame_error_flag, Word16 categorization_control, Word16 *absolute_region_power_index) inputs: bit_obj number_of_regions num_categorization_control_possibilities frame_error_flag categorization_control absolute_region_power_index outputs: frame_error_flag Description: Tests for error conditions and sets the frame_error_flag accordingly Design Notes: WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.01 | 0.01 -------|--------------|---------------- MAX | 0.04 | 0.08 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.01 | 0.01 | 0.01 -------|--------------|----------------|---------------- MAX | 0.02 | 0.06 | 0.08 -------|--------------|----------------|---------------- ***************************************************************************/ void test_4_frame_errors(Bit_Obj *bitobj, Word16 number_of_regions, Word16 num_categorization_control_possibilities, Word16 *frame_error_flag, Word16 categorization_control, Word16 *absolute_region_power_index) { Word16 region; Word16 i; Word16 temp; Word32 acca; Word32 accb; /* Test for bit stream errors. */ test(); if (bitobj->number_of_bits_left > 0) { for (i=0; inumber_of_bits_left; i++) { get_next_bit(bitobj); test(); if (bitobj->next_bit == 0) { *frame_error_flag = 1; move16(); } } } else { temp = sub(categorization_control,sub(num_categorization_control_possibilities,1)); test(); if (temp < 0) { test(); if (bitobj->number_of_bits_left < 0) { *frame_error_flag |= 2; logic16(); } } } /* checks to ensure that abs_region_power_index is within range */ /* the error flag is set if it is out of range */ for (region=0; region 31) || (absolute_region_power_index[region] < -8) */ acca = L_add(absolute_region_power_index[region],ESF_ADJUSTMENT_TO_RMS_INDEX); accb = L_sub(acca,31); acca = L_add(acca,8); test(); /* the next line was modifed in release 1.2 to * correct miss typed code and error checking. */ if ((accb > 0) || (acca < 0)) { *frame_error_flag |= 4; logic16(); } } } /*************************************************************************** Function: error_handling Syntax: void error_handling(Word16 number_of_coefs, Word16 number_of_valid_coefs, Word16 *frame_error_flag, Word16 *decoder_mlt_coefs, Word16 *old_decoder_mlt_coefs, Word16 *p_mag_shift, Word16 *p_old_mag_shift) inputs: number_of_coefs number_of_valid_coefs frame_error_flag old_decoder_mlt_coefs p_old_mag_shift outputs: decoder_mlt_coefs old_decoder_mlt_coefs p_mag_shift p_old_mag_shift Description: If both the current and previous frames are errored, set the mlt coefficients to 0. If only the current frame is errored, then repeat the previous frame's mlt coefficients. Design Notes: WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.02 | 0.02 -------|--------------|---------------- MAX | 0.03 | 0.03 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.03 | 0.03 | 0.03 -------|--------------|----------------|---------------- MAX | 0.03 | 0.03 | 0.06 -------|--------------|----------------|---------------- ***************************************************************************/ void error_handling(Word16 number_of_coefs, Word16 number_of_valid_coefs, Word16 *frame_error_flag, Word16 *decoder_mlt_coefs, Word16 *old_decoder_mlt_coefs, Word16 *p_mag_shift, Word16 *p_old_mag_shift) { Word16 i; test(); if (*frame_error_flag != 0) { for (i = 0; i < number_of_valid_coefs; i++) { decoder_mlt_coefs[i] = old_decoder_mlt_coefs[i]; move16(); } for (i = 0; i < number_of_valid_coefs; i++) { old_decoder_mlt_coefs[i] = 0; move16(); } *p_mag_shift = *p_old_mag_shift; move16(); *p_old_mag_shift = 0; move16(); } else { /* Store in case next frame is errored. */ for (i = 0; i < number_of_valid_coefs; i++) { old_decoder_mlt_coefs[i] = decoder_mlt_coefs[i]; move16(); } *p_old_mag_shift = *p_mag_shift; move16(); } /* Zero out the upper 1/8 of the spectrum. */ for (i = number_of_valid_coefs; i < number_of_coefs; i++) { decoder_mlt_coefs[i] = 0; move16(); } } /**************************************************************************************** Function: get_next_bit Syntax: void get_next_bit(Bit_Obj *bitobj) Description: Returns the next bit in the current word inside the bit object WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.00 | 0.00 -------|--------------|---------------- MAX | 0.00 | 0.00 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.00 | 0.00 | 0.00 -------|--------------|----------------|---------------- MAX | 0.00 | 0.00 | 0.00 -------|--------------|----------------|---------------- ****************************************************************************************/ void get_next_bit(Bit_Obj *bitobj) { Word16 temp; test(); if (bitobj->code_bit_count == 0) { bitobj->current_word = *bitobj->code_word_ptr++; move16(); bitobj->code_bit_count = 16; move16(); } bitobj->code_bit_count = sub(bitobj->code_bit_count,1); temp = shr_nocheck(bitobj->current_word,bitobj->code_bit_count); logic16(); bitobj->next_bit = (Word16 )(temp & 1); } /**************************************************************************************** Function: get_rand Syntax: Word16 get_rand(Rand_Obj *randobj) Description: Returns a random Word16 based on the seeds inside the rand object WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.00 | 0.00 -------|--------------|---------------- MAX | 0.00 | 0.00 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.00 | 0.00 | 0.00 -------|--------------|----------------|---------------- MAX | 0.00 | 0.00 | 0.00 -------|--------------|----------------|---------------- ****************************************************************************************/ Word16 get_rand(Rand_Obj *randobj) { Word16 random_word; Word32 acca; acca = L_add(randobj->seed0,randobj->seed3); random_word = extract_l(acca); logic16(); test(); if ((random_word & 32768L) != 0) random_word = add(random_word,1); randobj->seed3 = randobj->seed2; move16(); randobj->seed2 = randobj->seed1; move16(); randobj->seed1 = randobj->seed0; move16(); randobj->seed0 = random_word; move16(); return(random_word); }