/***************************************************************************
**
**   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; i<num_categorization_control_bits; i++) 
        {
        	get_next_bit(bitobj);
        	categorization_control = shl_nocheck(categorization_control,1);
        	categorization_control = add(categorization_control,bitobj->next_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; region<number_of_regions; region++) 
    {
        index = 0;
        move16();
        do 
        {
            get_next_bit(bitobj);
            test();
            if (bitobj->next_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<number_of_regions; region++) 
    {
        acca = L_add(absolute_region_power_index[region-1],differential_region_power_index[region]);
        acca = L_add(acca,DRP_DIFF_MIN);
        absolute_region_power_index[region] = extract_l(acca);        
    }

    /* Reconstruct decoder_region_standard_deviation[] from absolute_region_power_index[]. */
    /* DEBUG!!!! - This integer method jointly computes the mag_shift
       and the standard deviations already mag_shift compensated. It
       relies on REGION_POWER_STEPSIZE_DB being exactly 3.010299957 db
       or a square root of 2 chnage in standard deviation. If
       REGION_POWER_STEPSIZE_DB changes, this software must be
       reworked. */

    temp = 0;
    move16();
    max_index = 0;
    move16();
    for (region=0; region<number_of_regions; region++) 
    {
        acca = L_add(absolute_region_power_index[region],REGION_POWER_TABLE_NUM_NEGATIVES);
        i = extract_l(acca);
        
        temp1 = sub(i,max_index);
        test();
        if (temp1 > 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<number_of_regions; region++) 
    {
        acca = L_add(absolute_region_power_index[region],temp);
        i = extract_l(acca);
        decoder_region_standard_deviation[region] = int_region_standard_deviation_table[i];
        move16();
    }

}

/***************************************************************************
 Function:     rate_adjust_categories

 Syntax:       void rate_adjust_categories(Word16 categorization_control,            
                                           Word16 *decoder_power_categories,         
                                           Word16 *decoder_category_balances)        
               
               inputs:    Word16 categorization_control,   
                          Word16 *decoder_power_categories,
                          Word16 *decoder_category_balances
                          
               outputs:   Word16 categorization_control,   
                          Word16 *decoder_power_categories,
 
 Description:  Adjust the power categories based on the categorization control

 Design Notes:
 
 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.01      |    0.01        |     0.01   
          -------|--------------|----------------|----------------
				
***************************************************************************/
void rate_adjust_categories(Word16 categorization_control,
			                Word16 *decoder_power_categories,
			                Word16 *decoder_category_balances)
{
    Word16 i;
    Word16 region;
    
    i = 0;
    move16();

    test();
    while (categorization_control > 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; region<number_of_regions; region++) 
    {
        category = (Word16)decoder_power_categories[region];
        move16();
        acca = L_mult0(region,REGION_SIZE);
        index = extract_l(acca);
        decoder_mlt_ptr = &decoder_mlt_coefs[index];
        move16();
        standard_deviation = decoder_region_standard_deviation[region];
        move16();
        
        temp = sub(category,7);
        test();
        if (temp < 0)
        {
            /* Get the proper table of decoder tables, vec_dim, and num_vecs for the cat */
            decoder_table_ptr = (Word16 *) table_of_decoder_tables[category];
            move16();
            vec_dim = vector_dimension[category];
            move16();
            num_vecs = number_of_vectors[category];
            move16();
            
            for (n=0; n<num_vecs; n++) 
            {
                index = 0;
                move16();
                
                /* get index */
                do 
                {
                    test();
                    if (bitobj->number_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; j<num_sign_bits; j++) 
                        {
		                    get_next_bit(bitobj);
       		                signs_index = shl_nocheck(signs_index,1);
		                    signs_index = add(signs_index,bitobj->next_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; j<vec_dim; j++) 
                    {
	                    acca = L_mult0(standard_deviation,mlt_quant_centroid[category][k[j]]);
                        acca = L_shr_nocheck(acca,12);
                        decoder_mlt_value = extract_l(acca);
	                    
                        test();
                        if (decoder_mlt_value != 0) 
                        {
		                    test();
                            if ((signs_index & bit) == 0)
		                        decoder_mlt_value = negate(decoder_mlt_value);
		                    bit = shr_nocheck(bit,1);
	                    }
                        *decoder_mlt_ptr++ = decoder_mlt_value;
                        move16();
	                }
	            }
	            else 
                {
	                ran_out_of_bits_flag = 1;
                    move16();
	                break;
	            }
	        }
            /* If ran out of bits during decoding do noise fill for remaining regions. */
            /* DEBUG!! - For now also redo all of last region with all noise fill. */
        	test();
            if (ran_out_of_bits_flag != 0) 
            {
        	    temp = add(region,1);
                for (j=temp; j<number_of_regions; j++)
                {
                    decoder_power_categories[j] = 7;
                    move16();
                }
        	    category = 7;
                move16();
        	    decoder_mlt_ptr = &decoder_mlt_coefs[region*REGION_SIZE];
                move16();
        	}
        }

        temp = sub(category,5);
        temp1 = sub(category,6);
        test();
        test();
        logic16();
        if ((temp == 0) || (temp1 == 0))
        {
 
	        decoder_mlt_ptr = &decoder_mlt_coefs[region*REGION_SIZE];
	        move16();
            noifillpos = mult(standard_deviation,noise_fill_factor[category - 5]);
            noifillneg = negate(noifillpos);

	        random_word = get_rand(randobj);

	        for (j=0; j<10; j++) 
            {
	            test();
                if (*decoder_mlt_ptr == 0) 
                {
	                logic16();
                    test();
                    if ((random_word & 1) == 0) 
                    {
                        temp1 = noifillneg;
                        move16();
                    }
	                else
                    {
                        temp1 = noifillpos;
                        move16();
                    }
	                *decoder_mlt_ptr = temp1;
                    move16();
	                random_word = shr_nocheck(random_word,1);
	            }
	            /* pointer arithmetic */
                decoder_mlt_ptr++;
	        }
	        random_word = get_rand(randobj);
	        for (j=0; j<10; j++) 
            {
	            test();
                if (*decoder_mlt_ptr == 0) 
                {
	                logic16();
                    test();
                    if ((random_word & 1) == 0) 
                    {
                        temp1 = noifillneg;
                        move16();
                    }
	                else
                    {
                        temp1 = noifillpos;
                        move16();
                    }
	                *decoder_mlt_ptr = temp1;
                    move16();
	                random_word  = shr_nocheck(random_word,1);
	            }
	            /* pointer arithmetic */
                decoder_mlt_ptr++;
	        }
        }

        /* if (category == 7) */
        temp1 = sub(category,7);
        test();
        if (temp1 == 0)
        {
	        index = sub(category,5);
            noifillpos = mult(standard_deviation,noise_fill_factor[index]);
	        noifillneg = negate(noifillpos);

            random_word = get_rand(randobj);
            for (j=0; j<10; j++) 
            {
                logic16();
                test();
                if ((random_word & 1) == 0) 
                {
                    temp1 = noifillneg;
                    move16();
                }
                else
                {
                    temp1 = noifillpos;
                    move16();
                }
                *decoder_mlt_ptr++ = temp1;
                move16();
                random_word = shr_nocheck(random_word,1);
            }
            random_word = get_rand(randobj);
            for (j=0; j<10; j++) 
            {
                logic16();
                test();
                if ((random_word & 1) == 0) 
                {
                    temp1 = noifillneg;
                    move16();
                }
                else
                {
                    temp1 = noifillpos;
                    move16();
                }
                
                *decoder_mlt_ptr++ = temp1;
                move16();
                random_word = shr_nocheck(random_word,1);
            }
        }
    }

    test();
    if (ran_out_of_bits_flag)
        bitobj->number_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; i<bitobj->number_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<number_of_regions; region++) 
    {
        /*  the next two lines of comments were modified in release 1.2
	   *  to correct the description of the range of 
	   *  absolute_region_power_index[] to be tested in the next
	   *  9 lines of code.
	   */
	  /*  if ((absolute_region_power_index[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);
}
