Ticket #774:
 - Initial source of G.722.1/Annex C integration.
 - Disabled some "odd" modes of L16 codec (11kHz & 22kHz mono & stereo) while releasing some payload types.



git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@2563 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/third_party/g7221/decode/coef2sam.c b/third_party/g7221/decode/coef2sam.c
new file mode 100644
index 0000000..18a88ac
--- /dev/null
+++ b/third_party/g7221/decode/coef2sam.c
@@ -0,0 +1,180 @@
+/*****************************************************************************
+**
+**   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: rmlt_coefs_to_samples.c
+*
+* Purpose:  Convert Reversed MLT (Modulated Lapped Transform) 
+*           Coefficients to Samples
+*
+*     The "Reversed MLT" is an overlapped block transform which uses
+*     even symmetry * on the left, odd symmetry on the right and a
+*     Type IV DCT as the block transform.  * It is thus similar to a
+*     MLT which uses odd symmetry on the left, even symmetry * on the
+*     right and a Type IV DST as the block transform.  In fact, it is
+*     equivalent * to reversing the order of the samples, performing
+*     an MLT and then negating all * the even-numbered coefficients.
+*
+*****************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include "defs.h"
+#include "tables.h"
+#include "count.h"
+
+/***************************************************************************
+ Function:     rmlt_coefs_to_samples 
+
+ Syntax:       void rmlt_coefs_to_samples(Word16 *coefs,       
+                                          Word16 *old_samples, 
+                                          Word16 *out_samples, 
+                                          Word16 dct_length,
+                                          Word16 mag_shift)    
+            
+               inputs:    Word16 *coefs
+                          Word16 *old_samples
+                          Word16 dct_length
+                          Word16 mag_shift
+                          
+                          
+               outputs:   Word16 *out_samples
+               
+ Description:  Converts the mlt_coefs to samples
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |     1.91     |    1.91
+          -------|--------------|----------------  
+            MAX  |     1.91     |    1.91
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |     3.97     |    3.97        |     3.97   
+          -------|--------------|----------------|----------------
+            MAX  |     3.97     |    3.97        |     3.97   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+
+void rmlt_coefs_to_samples(Word16 *coefs,     
+                           Word16 *old_samples,
+                           Word16 *out_samples,           
+                           Word16 dct_length,
+                           Word16 mag_shift)             
+{
+
+    
+    Word16	index, vals_left;
+    Word16	new_samples[MAX_DCT_LENGTH];
+    Word16	*new_ptr, *old_ptr;
+    Word16	*win_new, *win_old;
+    Word16	*out_ptr;
+    Word16  half_dct_size;
+    Word32  sum;
+
+    
+
+    half_dct_size = shr(dct_length,1);
+    
+    /* Perform a Type IV (inverse) DCT on the coefficients */
+    dct_type_iv_s(coefs, new_samples, dct_length);
+    
+    test();
+    if (mag_shift > 0) 
+    {
+        for(index=0;index<dct_length;index++)
+        {
+            new_samples[index] = shr(new_samples[index],mag_shift);
+            move16();
+        }
+    }
+    else 
+    {
+        test();
+        if (mag_shift < 0) 
+        {
+            mag_shift = negate(mag_shift);
+            for(index=0;index<dct_length;index++)
+            {
+                new_samples[index] = shl(new_samples[index],mag_shift);
+                move16();
+            }
+        }
+
+    }
+
+    /* Get the first half of the windowed samples */
+    
+    out_ptr = out_samples;
+    move16();
+    test();
+    if (dct_length==DCT_LENGTH)
+    {
+        win_new = rmlt_to_samples_window;
+        move16();
+        win_old = rmlt_to_samples_window + dct_length;
+        move16();
+    }
+    else
+    {
+        win_new = max_rmlt_to_samples_window;
+        move16();
+        win_old = max_rmlt_to_samples_window + dct_length;
+        move16();
+    }
+    old_ptr = old_samples;
+    move16();
+    new_ptr = new_samples + half_dct_size;
+    move16();
+    
+    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
+    {
+        sum = 0L;
+        move32();
+        sum = L_mac(sum,*win_new++, *--new_ptr);
+        sum = L_mac(sum,*--win_old, *old_ptr++);
+        *out_ptr++ = round(L_shl(sum,2));
+        move16();
+
+    }
+    
+    /* Get the second half of the windowed samples */
+    
+    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
+    {
+        sum = 0L;
+        move32();
+        sum = L_mac(sum,*win_new++, *new_ptr++);
+        sum = L_mac(sum,negate(*--win_old), *--old_ptr);
+        *out_ptr++ = round(L_shl(sum,2));
+        move16();
+    }
+        
+    /* Save the second half of the new samples for   */
+    /* next time, when they will be the old samples. */
+    
+    /* pointer arithmetic */
+    new_ptr = new_samples + half_dct_size;
+    move16();
+    old_ptr = old_samples;
+    move16();
+    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
+    {
+        *old_ptr++ = *new_ptr++;
+        move16();
+    }
+}
diff --git a/third_party/g7221/decode/dct4_s.c b/third_party/g7221/decode/dct4_s.c
new file mode 100644
index 0000000..8451482
--- /dev/null
+++ b/third_party/g7221/decode/dct4_s.c
@@ -0,0 +1,480 @@
+/********************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   © 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+********************************************************************************/
+
+/********************************************************************************
+* Filename: dct_type_iv_s.c
+*
+* Purpose:  Discrete Cosine Transform, Type IV used for inverse MLT
+*
+* The basis functions are
+*
+*	 cos(PI*(t+0.5)*(k+0.5)/block_length)
+*
+* for time t and basis function number k.  Due to the symmetry of the expression
+* in t and k, it is clear that the forward and inverse transforms are the same.
+*
+*********************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include "defs.h"
+#include "count.h"
+#include "dct4_s.h"
+
+/***************************************************************************
+ External variable declarations                                          
+***************************************************************************/
+extern Word16    syn_bias_7khz[DCT_LENGTH];
+extern Word16    dither[DCT_LENGTH];
+extern Word16    max_dither[MAX_DCT_LENGTH];
+
+extern Word16       dct_core_s[DCT_LENGTH_DIV_32][DCT_LENGTH_DIV_32];
+extern cos_msin_t	s_cos_msin_2[DCT_LENGTH_DIV_32];
+extern cos_msin_t	s_cos_msin_4[DCT_LENGTH_DIV_16];
+extern cos_msin_t	s_cos_msin_8[DCT_LENGTH_DIV_8];
+extern cos_msin_t	s_cos_msin_16[DCT_LENGTH_DIV_4];
+extern cos_msin_t	s_cos_msin_32[DCT_LENGTH_DIV_2];
+extern cos_msin_t	s_cos_msin_64[DCT_LENGTH];
+extern cos_msin_t	*s_cos_msin_table[];
+
+/********************************************************************************
+ Function:    dct_type_iv_s
+
+ Syntax:      void dct_type_iv_s (Word16 *input,Word16 *output,Word16 dct_length)
+              
+
+ Description: Discrete Cosine Transform, Type IV used for inverse MLT
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |     1.74     |     1.74
+          -------|--------------|----------------  
+            MAX  |     1.74     |     1.74
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |     3.62     |     3.62       |      3.62   
+          -------|--------------|----------------|----------------
+            MAX  |     3.62     |     3.62       |      3.62   
+          -------|--------------|----------------|----------------
+
+********************************************************************************/
+
+void dct_type_iv_s (Word16 *input,Word16 *output,Word16 dct_length)
+{
+    Word16   buffer_a[MAX_DCT_LENGTH], buffer_b[MAX_DCT_LENGTH], buffer_c[MAX_DCT_LENGTH];
+    Word16   *in_ptr, *in_ptr_low, *in_ptr_high, *next_in_base;
+    Word16   *out_ptr_low, *out_ptr_high, *next_out_base;
+    Word16   *out_buffer, *in_buffer, *buffer_swap;
+    Word16   in_val_low, in_val_high;
+    Word16   out_val_low, out_val_high;
+    Word16   in_low_even, in_low_odd;
+    Word16   in_high_even, in_high_odd;
+    Word16   out_low_even, out_low_odd;
+    Word16   out_high_even, out_high_odd;
+    Word16   *pair_ptr;
+    Word16   cos_even, cos_odd, msin_even, msin_odd;
+    Word16   set_span, set_count, set_count_log, pairs_left, sets_left;
+    Word16   i,k;
+    Word16   index;
+    Word16   dummy;
+    Word32 	 sum;
+    cos_msin_t	**table_ptr_ptr, *cos_msin_ptr;
+
+    Word32 acca;
+    Word16 temp;
+
+    Word16   dct_length_log;
+    Word16   *dither_ptr;
+    
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Do the sum/difference butterflies, the first part of */
+    /* converting one N-point transform into 32 - 10 point transforms  */
+    /* transforms, where N = 1 << DCT_LENGTH_LOG.           */
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    test();
+    if (dct_length==DCT_LENGTH)
+    {
+        dct_length_log = DCT_LENGTH_LOG;
+        move16();
+        dither_ptr = dither;
+        move16();
+    }
+    else
+    {
+        dct_length_log = MAX_DCT_LENGTH_LOG;
+        move16();
+        dither_ptr = max_dither;
+        move16();
+    }
+    
+    in_buffer  = input;
+    move16();
+    out_buffer = buffer_a;
+    move16();
+    
+    index=0;
+    move16();
+    
+    i=0;
+    move16();
+
+    for (set_count_log = 0;    set_count_log <= dct_length_log - 2;    set_count_log++) 
+    {
+
+        /*===========================================================*/
+        /* Initialization for the loop over sets at the current size */
+        /*===========================================================*/
+        
+        /*    set_span      = 1 << (DCT_LENGTH_LOG - set_count_log); */
+        set_span = shr(dct_length,set_count_log);
+           
+        set_count     = shl(1,set_count_log);
+        in_ptr        = in_buffer;
+        move16();
+        next_out_base = out_buffer;
+        move16();
+        
+        /*=====================================*/
+        /* Loop over all the sets of this size */
+        /*=====================================*/
+        temp = sub(index,1);
+        test();
+        if(temp < 0)
+        {
+            for (sets_left = set_count;sets_left > 0;sets_left--) 
+            {
+    
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                /* Set up output pointers for the current set */
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                /* pointer arithmetic */
+                out_ptr_low    = next_out_base;
+                move16();
+                next_out_base += set_span;
+                move16();
+                out_ptr_high   = next_out_base;
+                move16();
+
+                /*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+                /* Loop over all the butterflies in the current set */
+                /*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+                    
+                do 
+                {
+                    in_val_low      = *in_ptr++;
+                    move16();
+                    in_val_high     = *in_ptr++;
+                    move16();
+
+                    /* BEST METHOD OF GETTING RID OF BIAS, BUT COMPUTATIONALLY UNPLEASANT */
+                    /* ALTERNATIVE METHOD, SMEARS BIAS OVER THE ENTIRE FRAME, COMPUTATIONALLY SIMPLEST. */
+                    /* IF THIS WORKS, IT'S PREFERABLE */
+                        
+                    dummy = add(in_val_low,dither_ptr[i++]);
+                    acca = L_add(dummy,in_val_high);
+                    out_val_low = extract_l(L_shr(acca,1));
+                    
+                    dummy = add(in_val_low,dither_ptr[i++]);
+                    acca = L_add(dummy,-in_val_high);
+                    out_val_high = extract_l(L_shr(acca,1));
+                    
+                    *out_ptr_low++  = out_val_low;
+                    move16();
+                    *--out_ptr_high = out_val_high;
+                    move16();
+
+                    test();
+                    
+                    /* this involves comparison of pointers */
+                    /* pointer arithmetic */
+
+                } while (out_ptr_low < out_ptr_high);
+    
+            } /* End of loop over sets of the current size */
+        }
+        else
+        {
+            for (sets_left = set_count;    sets_left > 0;    sets_left--) 
+            {
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                /* Set up output pointers for the current set */
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                
+                out_ptr_low    = next_out_base;
+                move16();
+                next_out_base += set_span;
+                move16();
+                out_ptr_high   = next_out_base;
+                move16();
+
+            	/*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+            	/* Loop over all the butterflies in the current set */
+            	/*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+                
+                do 
+                {
+                    in_val_low      = *in_ptr++;
+                    move16();
+                    in_val_high     = *in_ptr++;
+                    move16();
+
+                    out_val_low     = add(in_val_low,in_val_high);
+                    out_val_high    = add(in_val_low,negate(in_val_high));
+                    
+                    *out_ptr_low++  = out_val_low;
+                    move16();
+                    *--out_ptr_high = out_val_high;
+                    move16();
+
+                    test();
+                } while (out_ptr_low < out_ptr_high);
+    
+            } /* End of loop over sets of the current size */
+        }
+
+        /*============================================================*/
+        /* Decide which buffers to use as input and output next time. */
+        /* Except for the first time (when the input buffer is the    */
+        /* subroutine input) we just alternate the local buffers.     */
+        /*============================================================*/
+        
+        in_buffer = out_buffer;
+        move16();
+        
+        test();
+        if (out_buffer == buffer_a)
+        {
+            out_buffer = buffer_b;
+            move16();
+        }
+        else
+        {
+            out_buffer = buffer_a;
+            move16();
+        }
+        
+        index = add(index,1);
+    } /* End of loop over set sizes */
+
+
+    /*++++++++++++++++++++++++++++++++*/
+    /* Do 32 - 10 point transforms */
+    /*++++++++++++++++++++++++++++++++*/
+    
+    pair_ptr = in_buffer;
+    move16();
+    buffer_swap = buffer_c;
+    move16();
+
+    for (pairs_left = 1 << (dct_length_log - 1);    pairs_left > 0;    pairs_left--) 
+    {
+        for ( k=0; k<CORE_SIZE; k++ )
+        {
+            sum=0L;
+            move32();
+            
+            for ( i=0; i<CORE_SIZE; i++ )
+            {
+                sum = L_mac(sum, pair_ptr[i],dct_core_s[i][k]);
+            }
+            buffer_swap[k] = round(sum);
+        }
+        
+        pair_ptr   += CORE_SIZE;
+        move16();
+        buffer_swap += CORE_SIZE;
+        move16();
+    }
+    
+    for (i=0;i<dct_length;i++)
+    {
+        in_buffer[i] = buffer_c[i];
+        move16();
+    }
+
+    table_ptr_ptr = s_cos_msin_table;
+    move16();
+
+    /*++++++++++++++++++++++++++++++*/
+    /* Perform rotation butterflies */
+    /*++++++++++++++++++++++++++++++*/
+    index=0;
+    move16();
+    
+    for (set_count_log = dct_length_log - 2 ;    set_count_log >= 0;    set_count_log--) 
+    {
+
+        /*===========================================================*/
+        /* Initialization for the loop over sets at the current size */
+        /*===========================================================*/
+        
+        /*    set_span      = 1 << (DCT_LENGTH_LOG - set_count_log); */
+        set_span = shr(dct_length,set_count_log);
+        
+        set_count     = shl(1,set_count_log);
+        next_in_base  = in_buffer;
+        move16();
+        test();
+        if (set_count_log == 0)
+        {
+            next_out_base = output;
+            move16();
+        }
+        else
+        {
+            next_out_base = out_buffer;
+            move16();
+        }
+        
+        /*=====================================*/
+        /* Loop over all the sets of this size */
+        /*=====================================*/
+
+        for (sets_left = set_count;    sets_left > 0;    sets_left--) 
+        {
+
+            /*|||||||||||||||||||||||||||||||||||||||||*/
+            /* Set up the pointers for the current set */
+            /*|||||||||||||||||||||||||||||||||||||||||*/
+            
+            in_ptr_low     = next_in_base;
+            move16();
+            
+            temp = shr(set_span,1);
+            in_ptr_high    = in_ptr_low + temp;
+            move16();
+            
+            next_in_base  += set_span;
+            move16();
+            
+            out_ptr_low    = next_out_base;
+            move16();
+            
+            next_out_base += set_span;
+            move16();
+            out_ptr_high   = next_out_base;
+            move16();
+            
+            cos_msin_ptr   = *table_ptr_ptr;
+            move16();
+
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
+            /* Loop over all the butterfly pairs in the current set */
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
+
+	        do 
+            {
+                in_low_even     = *in_ptr_low++;
+                move16();
+                in_low_odd      = *in_ptr_low++;
+                move16();
+                in_high_even    = *in_ptr_high++;
+                move16();
+                in_high_odd     = *in_ptr_high++;
+                move16();
+                cos_even        = cos_msin_ptr[0].cosine;
+                move16();
+                msin_even       = cos_msin_ptr[0].minus_sine;
+                move16();
+                cos_odd         = cos_msin_ptr[1].cosine;
+                move16();
+                msin_odd        = cos_msin_ptr[1].minus_sine;
+                move16();
+                cos_msin_ptr   += 2;
+                
+                sum = 0L;
+                move32();
+                
+                sum = L_mac(sum,cos_even,in_low_even);
+                sum = L_mac(sum,negate(msin_even),in_high_even);
+                out_low_even = round(L_shl(sum,1));
+                
+                sum = 0L;
+                move32();
+                sum = L_mac(sum,msin_even,in_low_even);
+                sum = L_mac(sum,cos_even,in_high_even);
+                out_high_even = round(L_shl(sum,1));
+                
+                sum = 0L;
+                move32();
+                sum = L_mac(sum,cos_odd,in_low_odd);
+                sum = L_mac(sum,msin_odd,in_high_odd);
+                out_low_odd = round(L_shl(sum,1));
+                
+                sum = 0L;
+                move32();
+                sum = L_mac(sum,msin_odd,in_low_odd);
+                sum = L_mac(sum,negate(cos_odd),in_high_odd);
+                out_high_odd = round(L_shl(sum,1));
+                
+                *out_ptr_low++  = out_low_even;
+                move16();
+                *--out_ptr_high = out_high_even;
+                move16();
+                *out_ptr_low++  = out_low_odd;
+                move16();
+                *--out_ptr_high = out_high_odd;
+                move16();
+            
+                test();
+            } while (out_ptr_low < out_ptr_high);
+
+	    } /* End of loop over sets of the current size */
+
+        /*=============================================*/
+        /* Swap input and output buffers for next time */
+        /*=============================================*/
+        
+        buffer_swap = in_buffer;
+        move16();
+        in_buffer   = out_buffer;
+        move16();
+        out_buffer  = buffer_swap;
+        move16();
+        
+        index = add(index,1);
+        table_ptr_ptr++;
+    }
+    /*------------------------------------
+    
+         ADD IN BIAS FOR OUTPUT
+         
+    -----------------------------------*/
+    if (dct_length==DCT_LENGTH)
+    {
+        for(i=0;i<320;i++) 
+        {
+           sum = L_add(output[i],syn_bias_7khz[i]);
+           acca = L_sub(sum,32767);
+           test();
+           if (acca > 0) 
+           {
+               sum = 32767L;
+               move32();
+           }
+           acca = L_add(sum,32768L);
+           test();
+           if (acca < 0) 
+           {
+               sum = -32768L;
+               move32();
+           }
+           output[i] = extract_l(sum);
+        }
+    }
+}
+
diff --git a/third_party/g7221/decode/dct4_s.h b/third_party/g7221/decode/dct4_s.h
new file mode 100644
index 0000000..010e52d
--- /dev/null
+++ b/third_party/g7221/decode/dct4_s.h
@@ -0,0 +1,856 @@
+/***********************************************************************
+**
+**   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:    dct4_s.h    
+
+  Purpose:     Contains tables used by dct4_s.c
+		
+  Design Notes:
+
+***********************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+
+typedef struct 
+{
+    Word16 cosine;
+    Word16 minus_sine;
+} cos_msin_t;
+
+/***************************************************************************
+  The dct_core_s table was generated by the following code
+
+      for(i=0;i<10;++i)
+      {
+          for(k=0;k<10;++k)
+          {
+              dct_core_s[i][k]=(short) (FTOI(((.9*32768.)*cos(3.1415926*(k+0.5)*(i+0.5)/10.))));
+          }
+      }
+***************************************************************************/
+Word16 dct_core_s[10][10] = {
+{ 29400,   28676,   27246,   25145,   22425,   19153,   15409,   11286,    6885,  2314 },
+{ 28676,   22425,   11286,   -2314,  -15409,  -25145,  -29400,  -27246,  -19153,  -6885 },
+{ 27246,   11286,  -11286,  -27246,  -27246,  -11286,   11286,   27246,   27246,  11286 },
+{ 25145,   -2314,  -27246,  -22425,    6885,   28676,   19153,  -11286,  -29400,  -15409 },
+{ 22425,  -15409,  -27246,    6885,   29400,    2314,  -28676,  -11286,   25145,  19153 },
+{ 19153,  -25145,  -11286,   28676,    2314,  -29400,    6885,   27246,  -15409,  -22425 },
+{ 15409,  -29400,   11286,   19153,  -28676,    6885,   22425,  -27246,    2314,  25145 },
+{ 11286,  -27246,   27246,  -11286,  -11286,   27246,  -27246,   11286,   11286,  -27246 },
+{  6885,  -19153,   27246,  -29400,   25145,  -15409,    2314,   11286,  -22425,  28676 },
+{  2314,   -6885,   11286,  -15409,   19153,  -22425,   25145,  -27246,   28676,  -29400 }
+};    
+
+Word16 syn_bias_7khz[DCT_LENGTH] = {
+ -4,  4, -5, -2,  0, -4,  6,  2, -2, -4,
+ -3,  3,  0,  0, -2,  4,  0,  0,  3, -6,
+  8,  5,  4,  5, -8,  0, -2,  0,  0, -3,
+  3,  0,  0,  0,  1, -1, -2,  0,  0,  2,
+ -2, -5, -2,  3,  2, -1, -1, -6,  3,  1,
+ -7,  4,  4,  0,  1,  4,  1,  0,  1, -5,
+ -1,  1, -6,  0, -1, -1,  3,  0, -2,  1,
+  2, -4,  0,  9,  0, -3,  1,  1,  1,  0,
+ -3, -2, -1, -4, -2,  0,  5,  2, -3,  5,
+  0, -2,  4,  4,  0, -6, -4,  2,  0,  0,
+  0, -1, -1, -2,  0,  6,  1,  0,  0, -1,
+  0, -4, -1,  0, -4,  1, -1, -5,  0,  1,
+  2,  4,  0, -8, -4,  0, -2, -2,  2,  5,
+ -3, -1,  1, -4,  0,  0,  0, -1, -3,  0,
+ -5, -4,  0, -2,  0,  7,  1,  0,  5, -2,
+ -1,  2,  2, -2,  3,  7, -3,  4,  1, -4,
+  0,  0,  3, -7, -5,  0,  0,  4,  0, -2,
+ -1,  0, -5,  0,  2,  0, 11,  5, -1,  0,
+  2,  2, -2, -2,  5,  4, -3,  1,  0, -2,
+  1,  3,  2,  0,  1,  0,  0,  0,  5,  6,
+ -2, -1,  0,  2,  3,  2,  0, -3,  4,  5,
+  0, -1,  0,  3,  1, -2, -3, -2, -1,  2,
+ -1, -1, -2, -7,  4,  6, -5, -6, -3, -4,
+  0,  2, -5, -2,  3,  0,  0,  0,  2, -2,
+ -4,  3,  3,  1,  0,  0,  4, -1,  8, 13,
+  1,  2,  0,  2,  0, -1,  4, -3,  1,  0,
+ -1,  3,  0,  0, -5,  0,  6,  2,  4,  5,
+  2, -1, -1,  3,  6,  1,  1,  2, -4,  0,
+ -1, -6, -2, -2,  2,  1,  2,  6,  2,  0,
+ -2, -2,  0, -1,  2,  0,  0,  3, -2,  1,
+  3,  1,  2, -1, -2,  2,  2, -4,  0,  0,
+ -3,  0, -4, -3,  6,  7,  2,  2,  0, -3};
+
+Word16 dither[DCT_LENGTH]= {
+  1,  0,  0,  0,  1,  0,  0,  1,  1,  1,
+  1,  0,  0,  0,  1,  1,  1,  1,  1,  0,
+  0,  1,  1,  1,  0,  1,  1,  0,  0,  0,
+  1,  0,  0,  1,  0,  1,  0,  0,  1,  0,
+  1,  0,  0,  0,  1,  0,  1,  0,  0,  0,
+  1,  1,  1,  1,  1,  0,  0,  1,  0,  0,
+  0,  0,  1,  0,  0,  0,  1,  0,  0,  1,
+  1,  1,  1,  1,  1,  0,  1,  0,  0,  1,
+  1,  0,  0,  1,  0,  0,  0,  1,  0,  1,
+  0,  0,  1,  1,  0,  1,  0,  1,  1,  1,
+  1,  0,  0,  0,  0,  1,  1,  1,  1,  1,
+  0,  0,  0,  1,  0,  1,  0,  0,  0,  1,
+  1,  1,  0,  0,  1,  1,  1,  1,  1,  0,
+  0,  1,  1,  1,  1,  0,  1,  1,  1,  0,
+  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
+  1,  0,  1,  1,  1,  1,  0,  0,  0,  0,
+  1,  1,  0,  1,  0,  0,  1,  0,  0,  1,
+  0,  0,  0,  1,  1,  0,  0,  1,  1,  1,
+  1,  0,  0,  0,  0,  0,  1,  1,  1,  1,
+  1,  0,  0,  1,  1,  0,  1,  1,  0,  0,
+  1,  1,  1,  0,  1,  1,  0,  1,  0,  1,
+  0,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  0,  1,  1,  1,  1,  0,  1,  1,  1,  0,
+  1,  1,  1,  0,  1,  1,  1,  0,  1,  0,
+  1,  1,  0,  0,  1,  0,  0,  1,  0,  1,
+  0,  1,  1,  0,  1,  0,  1,  0,  1,  1,
+  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,
+  0,  1,  0,  0,  0,  1,  0,  0,  0,  1,
+  1,  0,  0,  0,  1,  0,  0,  1,  0,  1,
+  1,  0,  1,  1,  0,  0,  1,  1,  0,  1,
+  1,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  1,  1,  1,  0,  1,  0,  0,  0,  1,  0};
+
+Word16 max_dither[MAX_DCT_LENGTH]= {
+  1,  0,  1,  0,  1,  1,  0,  1,  0,  1,
+  1,  1,  0,  0,  0,  0,  0,  1,  1,  1,
+  1,  1,  1,  0,  1,  1,  0,  0,  0,  1,
+  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
+  1,  1,  1,  0,  1,  0,  1,  1,  1,  1,
+  0,  1,  0,  1,  1,  1,  1,  1,  1,  0,
+  1,  0,  1,  1,  0,  1,  0,  0,  0,  1,
+  0,  1,  1,  1,  1,  1,  0,  1,  1,  0,
+  0,  0,  1,  1,  0,  0,  0,  1,  1,  1,
+  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,
+  1,  0,  1,  0,  1,  0,  0,  0,  1,  1,
+  0,  1,  1,  1,  1,  1,  1,  0,  1,  0,
+  0,  0,  1,  0,  1,  0,  0,  0,  1,  0,
+  0,  1,  0,  1,  0,  0,  0,  0,  1,  0,
+  1,  0,  0,  1,  0,  1,  0,  0,  0,  1,
+  0,  1,  0,  0,  1,  1,  1,  1,  0,  1,
+  1,  0,  0,  0,  1,  1,  0,  1,  0,  1,
+  0,  1,  0,  1,  0,  1,  1,  1,  0,  1,
+  1,  0,  0,  1,  1,  1,  1,  0,  1,  1,
+  1,  1,  1,  0,  1,  1,  0,  0,  0,  0,
+  1,  0,  1,  0,  0,  0,  0,  1,  1,  0,
+  1,  1,  0,  0,  0,  0,  1,  0,  0,  1,
+  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,
+  0,  0,  1,  1,  1,  0,  1,  1,  1,  0,
+  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,
+  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,
+  0,  0,  1,  1,  0,  1,  0,  1,  0,  1,
+  0,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  0,  1,  1,  1,  0,  1,  0,  1,  0,  0,
+  0,  1,  0,  1,  1,  0,  0,  0,  1,  0,
+  1,  1,  0,  0,  1,  1,  1,  1,  0,  0,
+  0,  0,  1,  1,  1,  1,  0,  0,  1,  1,
+  1,  1,  1,  0,  1,  0,  0,  0,  1,  0,
+  0,  1,  1,  1,  0,  1,  0,  1,  0,  0,
+  1,  1,  0,  1,  0,  1,  1,  0,  0,  0,
+  0,  1,  1,  0,  1,  1,  1,  0,  1,  1,
+  0,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  1,  1,  0,  0,  0,  1,  1,  1,  1,  0,
+  0,  1,  0,  1,  0,  1,  1,  0,  1,  0,
+  1,  1,  1,  0,  0,  1,  1,  0,  0,  1,
+  0,  1,  0,  0,  0,  1,  1,  0,  0,  1,
+  0,  0,  1,  1,  0,  1,  0,  1,  0,  1,
+  1,  1,  0,  1,  0,  0,  1,  1,  0,  0,
+  1,  0,  1,  0,  1,  0,  0,  1,  0,  0,
+  0,  1,  0,  1,  1,  1,  1,  1,  1,  0,
+  0,  1,  1,  0,  0,  0,  1,  1,  1,  0,
+  1,  1,  1,  0,  1,  1,  1,  0,  0,  0,
+  0,  0,  1,  0,  0,  1,  0,  0,  0,  1,
+  0,  0,  0,  1,  1,  0,  0,  1,  0,  1,
+  1,  1,  1,  1,  0,  0,  1,  0,  1,  0,
+  0,  1,  0,  1,  1,  1,  1,  1,  1,  0,
+  0,  0,  1,  0,  1,  0,  0,  1,  0,  1,
+  1,  0,  1,  0,  1,  1,  0,  0,  1,  1,
+  1,  1,  1,  0,  1,  0,  0,  1,  1,  1,
+  0,  1,  0,  1,  0,  1,  0,  0,  0,  1,
+  1,  0,  0,  1,  0,  0,  1,  1,  0,  1,
+  1,  0,  1,  0,  1,  1,  0,  0,  1,  1,
+  0,  0,  0,  1,  0,  1,  1,  1,  0,  0,
+  1,  0,  1,  0,  1,  1,  0,  0,  0,  1,
+  1,  0,  1,  0,  0,  1,  1,  1,  0,  1,
+  0,  0,  1,  1,  1,  1,  1,  0,  0,  0,
+  0,  1,  0,  1,  0,  0,  1,  0,  1,  0,
+  0,  1,  1,  1,  1,  0,  0,  0,  1,  0,
+  0,  1,  0,  1,  0,  1,  0,  0,  0,  0
+};
+
+
+/********************************************************************************
+  The s_cos_min tables were generated by the following code:
+      double		angle, scale;
+      int		    index;
+
+      for (index = 0;index < length;index++) 
+      {
+          angle = scale * ((double)index + 0.5);
+          table[index].cosine     = (short) (FTOI((18427)* cos(angle)));
+          table[index].minus_sine = (short) (FTOI((18427)*(-sin(angle))));
+      }
+
+
+********************************************************************************/
+
+cos_msin_t	s_cos_msin_2[DCT_LENGTH_DIV_32] = {
+    {  18413   ,   -723   } , 
+    {  18299   ,   -2166   } , 
+    {  18073   ,   -3595   } , 
+    {  17735   ,   -5002   } , 
+    {  17288   ,   -6378   } , 
+    {  16734   ,   -7715   } , 
+    {  16077   ,   -9004   } , 
+    {  15321   ,   -10237   } , 
+    {  14471   ,   -11408   } , 
+    {  13531   ,   -12508   } 
+    };
+cos_msin_t	s_cos_msin_4[DCT_LENGTH_DIV_16] = {
+    {  18423   ,   -362   } , 
+    {  18395   ,   -1085   } , 
+    {  18338   ,   -1806   } , 
+    {  18253   ,   -2525   } , 
+    {  18140   ,   -3239   } , 
+    {  17999   ,   -3949   } , 
+    {  17830   ,   -4653   } , 
+    {  17634   ,   -5349   } , 
+    {  17410   ,   -6037   } , 
+    {  17159   ,   -6716   } , 
+    {  16883   ,   -7385   } , 
+    {  16580   ,   -8042   } , 
+    {  16251   ,   -8686   } , 
+    {  15898   ,   -9318   } , 
+    {  15520   ,   -9935   } , 
+    {  15118   ,   -10536   } , 
+    {  14692   ,   -11122   } , 
+    {  14244   ,   -11690   } , 
+    {  13774   ,   -12240   } , 
+    {  13283   ,   -12772   } 
+    };
+cos_msin_t	s_cos_msin_8[DCT_LENGTH_DIV_8] = {
+    {  18426   ,   -181   } , 
+    {  18419   ,   -543   } , 
+    {  18405   ,   -904   } , 
+    {  18384   ,   -1265   } , 
+    {  18355   ,   -1626   } , 
+    {  18320   ,   -1986   } , 
+    {  18277   ,   -2345   } , 
+    {  18228   ,   -2704   } , 
+    {  18171   ,   -3061   } , 
+    {  18107   ,   -3417   } , 
+    {  18037   ,   -3772   } , 
+    {  17959   ,   -4126   } , 
+    {  17875   ,   -4477   } , 
+    {  17783   ,   -4827   } , 
+    {  17685   ,   -5176   } , 
+    {  17580   ,   -5522   } , 
+    {  17468   ,   -5866   } , 
+    {  17350   ,   -6208   } , 
+    {  17225   ,   -6547   } , 
+    {  17093   ,   -6884   } , 
+    {  16954   ,   -7219   } , 
+    {  16809   ,   -7550   } , 
+    {  16658   ,   -7879   } , 
+    {  16500   ,   -8204   } , 
+    {  16336   ,   -8526   } , 
+    {  16165   ,   -8846   } , 
+    {  15988   ,   -9161   } , 
+    {  15805   ,   -9473   } , 
+    {  15616   ,   -9782   } , 
+    {  15421   ,   -10087   } , 
+    {  15220   ,   -10387   } , 
+    {  15013   ,   -10684   } , 
+    {  14801   ,   -10977   } , 
+    {  14582   ,   -11265   } , 
+    {  14358   ,   -11550   } , 
+    {  14129   ,   -11829   } , 
+    {  13894   ,   -12104   } , 
+    {  13654   ,   -12375   } , 
+    {  13408   ,   -12641   } , 
+    {  13157   ,   -12901   } 
+    };
+cos_msin_t	s_cos_msin_16[DCT_LENGTH_DIV_4] = {
+    {  18427   ,   -90   } , 
+    {  18425   ,   -271   } , 
+    {  18421   ,   -452   } , 
+    {  18416   ,   -633   } , 
+    {  18409   ,   -814   } , 
+    {  18400   ,   -995   } , 
+    {  18389   ,   -1175   } , 
+    {  18377   ,   -1356   } , 
+    {  18363   ,   -1536   } , 
+    {  18347   ,   -1716   } , 
+    {  18329   ,   -1896   } , 
+    {  18310   ,   -2076   } , 
+    {  18288   ,   -2256   } , 
+    {  18265   ,   -2435   } , 
+    {  18241   ,   -2614   } , 
+    {  18214   ,   -2793   } , 
+    {  18186   ,   -2972   } , 
+    {  18156   ,   -3150   } , 
+    {  18124   ,   -3328   } , 
+    {  18090   ,   -3506   } , 
+    {  18055   ,   -3684   } , 
+    {  18018   ,   -3861   } , 
+    {  17979   ,   -4037   } , 
+    {  17939   ,   -4214   } , 
+    {  17897   ,   -4390   } , 
+    {  17853   ,   -4565   } , 
+    {  17807   ,   -4740   } , 
+    {  17760   ,   -4915   } , 
+    {  17710   ,   -5089   } , 
+    {  17660   ,   -5262   } , 
+    {  17607   ,   -5436   } , 
+    {  17553   ,   -5608   } , 
+    {  17497   ,   -5780   } , 
+    {  17439   ,   -5952   } , 
+    {  17380   ,   -6123   } , 
+    {  17319   ,   -6293   } , 
+    {  17257   ,   -6463   } , 
+    {  17192   ,   -6632   } , 
+    {  17126   ,   -6800   } , 
+    {  17059   ,   -6968   } , 
+    {  16990   ,   -7135   } , 
+    {  16919   ,   -7302   } , 
+    {  16846   ,   -7467   } , 
+    {  16772   ,   -7632   } , 
+    {  16696   ,   -7797   } , 
+    {  16619   ,   -7960   } , 
+    {  16540   ,   -8123   } , 
+    {  16459   ,   -8285   } , 
+    {  16377   ,   -8446   } , 
+    {  16294   ,   -8607   } , 
+    {  16208   ,   -8766   } , 
+    {  16121   ,   -8925   } , 
+    {  16033   ,   -9083   } , 
+    {  15943   ,   -9240   } , 
+    {  15852   ,   -9396   } , 
+    {  15759   ,   -9551   } , 
+    {  15664   ,   -9705   } , 
+    {  15568   ,   -9858   } , 
+    {  15471   ,   -10011   } , 
+    {  15372   ,   -10162   } , 
+    {  15271   ,   -10313   } , 
+    {  15169   ,   -10462   } , 
+    {  15066   ,   -10610   } , 
+    {  14961   ,   -10758   } , 
+    {  14854   ,   -10904   } , 
+    {  14747   ,   -11049   } , 
+    {  14637   ,   -11194   } , 
+    {  14527   ,   -11337   } , 
+    {  14415   ,   -11479   } , 
+    {  14301   ,   -11620   } , 
+    {  14187   ,   -11760   } , 
+    {  14071   ,   -11898   } , 
+    {  13953   ,   -12036   } , 
+    {  13834   ,   -12172   } , 
+    {  13714   ,   -12308   } , 
+    {  13593   ,   -12442   } , 
+    {  13470   ,   -12575   } , 
+    {  13346   ,   -12706   } , 
+    {  13220   ,   -12837   } , 
+    {  13094   ,   -12966   } 
+    };
+cos_msin_t	s_cos_msin_32[DCT_LENGTH_DIV_2] = {
+    {  18427   ,   -45   } , 
+    {  18427   ,   -136   } , 
+    {  18426   ,   -226   } , 
+    {  18424   ,   -317   } , 
+    {  18423   ,   -407   } , 
+    {  18420   ,   -497   } , 
+    {  18418   ,   -588   } , 
+    {  18415   ,   -678   } , 
+    {  18411   ,   -769   } , 
+    {  18407   ,   -859   } , 
+    {  18403   ,   -949   } , 
+    {  18398   ,   -1040   } , 
+    {  18392   ,   -1130   } , 
+    {  18387   ,   -1220   } , 
+    {  18380   ,   -1310   } , 
+    {  18374   ,   -1401   } , 
+    {  18367   ,   -1491   } , 
+    {  18359   ,   -1581   } , 
+    {  18351   ,   -1671   } , 
+    {  18343   ,   -1761   } , 
+    {  18334   ,   -1851   } , 
+    {  18324   ,   -1941   } , 
+    {  18315   ,   -2031   } , 
+    {  18305   ,   -2121   } , 
+    {  18294   ,   -2211   } , 
+    {  18283   ,   -2301   } , 
+    {  18271   ,   -2390   } , 
+    {  18259   ,   -2480   } , 
+    {  18247   ,   -2570   } , 
+    {  18234   ,   -2659   } , 
+    {  18221   ,   -2749   } , 
+    {  18207   ,   -2838   } , 
+    {  18193   ,   -2927   } , 
+    {  18178   ,   -3017   } , 
+    {  18163   ,   -3106   } , 
+    {  18148   ,   -3195   } , 
+    {  18132   ,   -3284   } , 
+    {  18116   ,   -3373   } , 
+    {  18099   ,   -3462   } , 
+    {  18082   ,   -3551   } , 
+    {  18064   ,   -3639   } , 
+    {  18046   ,   -3728   } , 
+    {  18027   ,   -3816   } , 
+    {  18009   ,   -3905   } , 
+    {  17989   ,   -3993   } , 
+    {  17969   ,   -4081   } , 
+    {  17949   ,   -4170   } , 
+    {  17928   ,   -4258   } , 
+    {  17907   ,   -4346   } , 
+    {  17886   ,   -4434   } , 
+    {  17864   ,   -4521   } , 
+    {  17841   ,   -4609   } , 
+    {  17818   ,   -4696   } , 
+    {  17795   ,   -4784   } , 
+    {  17772   ,   -4871   } , 
+    {  17747   ,   -4958   } , 
+    {  17723   ,   -5045   } , 
+    {  17698   ,   -5132   } , 
+    {  17672   ,   -5219   } , 
+    {  17647   ,   -5306   } , 
+    {  17620   ,   -5392   } , 
+    {  17594   ,   -5479   } , 
+    {  17567   ,   -5565   } , 
+    {  17539   ,   -5651   } , 
+    {  17511   ,   -5737   } , 
+    {  17483   ,   -5823   } , 
+    {  17454   ,   -5909   } , 
+    {  17425   ,   -5994   } , 
+    {  17395   ,   -6080   } , 
+    {  17365   ,   -6165   } , 
+    {  17335   ,   -6250   } , 
+    {  17304   ,   -6335   } , 
+    {  17272   ,   -6420   } , 
+    {  17241   ,   -6505   } , 
+    {  17208   ,   -6590   } , 
+    {  17176   ,   -6674   } , 
+    {  17143   ,   -6758   } , 
+    {  17110   ,   -6842   } , 
+    {  17076   ,   -6926   } , 
+    {  17042   ,   -7010   } , 
+    {  17007   ,   -7093   } , 
+    {  16972   ,   -7177   } , 
+    {  16937   ,   -7260   } , 
+    {  16901   ,   -7343   } , 
+    {  16864   ,   -7426   } , 
+    {  16828   ,   -7509   } , 
+    {  16791   ,   -7591   } , 
+    {  16753   ,   -7674   } , 
+    {  16715   ,   -7756   } , 
+    {  16677   ,   -7838   } , 
+    {  16638   ,   -7919   } , 
+    {  16599   ,   -8001   } , 
+    {  16560   ,   -8082   } , 
+    {  16520   ,   -8164   } , 
+    {  16480   ,   -8245   } , 
+    {  16439   ,   -8325   } , 
+    {  16398   ,   -8406   } , 
+    {  16357   ,   -8486   } , 
+    {  16315   ,   -8567   } , 
+    {  16272   ,   -8647   } , 
+    {  16230   ,   -8726   } , 
+    {  16187   ,   -8806   } , 
+    {  16143   ,   -8885   } , 
+    {  16100   ,   -8964   } , 
+    {  16055   ,   -9043   } , 
+    {  16011   ,   -9122   } , 
+    {  15966   ,   -9200   } , 
+    {  15920   ,   -9279   } , 
+    {  15875   ,   -9357   } , 
+    {  15829   ,   -9435   } , 
+    {  15782   ,   -9512   } , 
+    {  15735   ,   -9589   } , 
+    {  15688   ,   -9667   } , 
+    {  15640   ,   -9744   } , 
+    {  15592   ,   -9820   } , 
+    {  15544   ,   -9897   } , 
+    {  15495   ,   -9973   } , 
+    {  15446   ,   -10049   } , 
+    {  15396   ,   -10124   } , 
+    {  15347   ,   -10200   } , 
+    {  15296   ,   -10275   } , 
+    {  15246   ,   -10350   } , 
+    {  15195   ,   -10425   } , 
+    {  15143   ,   -10499   } , 
+    {  15092   ,   -10573   } , 
+    {  15040   ,   -10647   } , 
+    {  14987   ,   -10721   } , 
+    {  14934   ,   -10794   } , 
+    {  14881   ,   -10868   } , 
+    {  14828   ,   -10941   } , 
+    {  14774   ,   -11013   } , 
+    {  14719   ,   -11086   } , 
+    {  14665   ,   -11158   } , 
+    {  14610   ,   -11230   } , 
+    {  14555   ,   -11301   } , 
+    {  14499   ,   -11372   } , 
+    {  14443   ,   -11444   } , 
+    {  14387   ,   -11514   } , 
+    {  14330   ,   -11585   } , 
+    {  14273   ,   -11655   } , 
+    {  14216   ,   -11725   } , 
+    {  14158   ,   -11795   } , 
+    {  14100   ,   -11864   } , 
+    {  14041   ,   -11933   } , 
+    {  13983   ,   -12002   } , 
+    {  13924   ,   -12070   } , 
+    {  13864   ,   -12138   } , 
+    {  13804   ,   -12206   } , 
+    {  13744   ,   -12274   } , 
+    {  13684   ,   -12341   } , 
+    {  13623   ,   -12408   } , 
+    {  13562   ,   -12475   } , 
+    {  13501   ,   -12541   } , 
+    {  13439   ,   -12608   } , 
+    {  13377   ,   -12673   } , 
+    {  13314   ,   -12739   } , 
+    {  13252   ,   -12804   } , 
+    {  13189   ,   -12869   } , 
+    {  13125   ,   -12934   } , 
+    {  13062   ,   -12998   } 
+    };
+cos_msin_t	s_cos_msin_64[DCT_LENGTH] = {
+{18426,	-21},
+{18426,	-66},
+{18426,	-110},
+{18426,	-154},
+{18425,	-198},
+{18425,	-242},
+{18424,	-286},
+{18424,	-331},
+{18423,	-374},
+{18421,	-419},
+{18421,	-463},
+{18419,	-507},
+{18418,	-552},
+{18417,	-595},
+{18415,	-639},
+{18414,	-684},
+{18412,	-728},
+{18410,	-772},
+{18408,	-816},
+{18406,	-860},
+{18404,	-904},
+{18402,	-949},
+{18400,	-992},
+{18397,	-1037},
+{18394,	-1081},
+{18392,	-1125},
+{18389,	-1169},
+{18387,	-1213},
+{18384,	-1257},
+{18380,	-1301},
+{18378,	-1345},
+{18374,	-1389},
+{18371,	-1433},
+{18367,	-1477},
+{18364,	-1521},
+{18360,	-1566},
+{18356,	-1609},
+{18352,	-1653},
+{18348,	-1697},
+{18344,	-1742},
+{18339,	-1785},
+{18335,	-1829},
+{18331,	-1873},
+{18326,	-1917},
+{18322,	-1961},
+{18317,	-2005},
+{18312,	-2049},
+{18307,	-2092},
+{18302,	-2137},
+{18297,	-2180},
+{18292,	-2224},
+{18286,	-2268},
+{18281,	-2312},
+{18275,	-2356},
+{18270,	-2399},
+{18264,	-2443},
+{18258,	-2487},
+{18252,	-2531},
+{18246,	-2574},
+{18240,	-2618},
+{18233,	-2662},
+{18227,	-2706},
+{18220,	-2749},
+{18214,	-2793},
+{18207,	-2836},
+{18200,	-2880},
+{18193,	-2924},
+{18186,	-2967},
+{18179,	-3011},
+{18172,	-3055},
+{18164,	-3098},
+{18157,	-3142},
+{18149,	-3185},
+{18141,	-3229},
+{18134,	-3272},
+{18126,	-3316},
+{18118,	-3359},
+{18109,	-3403},
+{18101,	-3446},
+{18094,	-3489},
+{18085,	-3533},
+{18076,	-3576},
+{18068,	-3619},
+{18059,	-3663},
+{18050,	-3706},
+{18041,	-3749},
+{18032,	-3792},
+{18023,	-3836},
+{18014,	-3879},
+{18005,	-3922},
+{17995,	-3965},
+{17986,	-4008},
+{17975,	-4051},
+{17966,	-4094},
+{17956,	-4138},
+{17946,	-4180},
+{17936,	-4224},
+{17926,	-4266},
+{17916,	-4309},
+{17905,	-4353},
+{17895,	-4395},
+{17884,	-4438},
+{17874,	-4481},
+{17863,	-4524},
+{17852,	-4567},
+{17841,	-4609},
+{17830,	-4652},
+{17819,	-4695},
+{17807,	-4738},
+{17796,	-4780},
+{17784,	-4823},
+{17772,	-4865},
+{17761,	-4908},
+{17749,	-4951},
+{17738,	-4993},
+{17725,	-5036},
+{17713,	-5078},
+{17701,	-5121},
+{17689,	-5163},
+{17676,	-5205},
+{17664,	-5248},
+{17651,	-5290},
+{17638,	-5333},
+{17626,	-5375},
+{17613,	-5417},
+{17599,	-5459},
+{17586,	-5501},
+{17573,	-5544},
+{17560,	-5586},
+{17546,	-5627},
+{17533,	-5670},
+{17519,	-5712},
+{17505,	-5753},
+{17492,	-5795},
+{17478,	-5837},
+{17464,	-5879},
+{17450,	-5921},
+{17435,	-5963},
+{17421,	-6005},
+{17406,	-6046},
+{17392,	-6088},
+{17377,	-6130},
+{17363,	-6172},
+{17348,	-6213},
+{17333,	-6254},
+{17318,	-6296},
+{17303,	-6338},
+{17288,	-6379},
+{17272,	-6420},
+{17257,	-6462},
+{17241,	-6503},
+{17225,	-6545},
+{17210,	-6586},
+{17194,	-6627},
+{17178,	-6668},
+{17162,	-6709},
+{17145,	-6750},
+{17130,	-6791},
+{17113,	-6832},
+{17097,	-6874},
+{17080,	-6915},
+{17064,	-6956},
+{17047,	-6996},
+{17030,	-7037},
+{17013,	-7078},
+{16996,	-7119},
+{16979,	-7159},
+{16962,	-7200},
+{16945,	-7241},
+{16927,	-7281},
+{16910,	-7322},
+{16892,	-7362},
+{16874,	-7403},
+{16856,	-7444},
+{16838,	-7484},
+{16821,	-7524},
+{16802,	-7564},
+{16784,	-7605},
+{16766,	-7645},
+{16748,	-7685},
+{16729,	-7725},
+{16711,	-7765},
+{16692,	-7805},
+{16674,	-7845},
+{16654,	-7885},
+{16635,	-7925},
+{16616,	-7964},
+{16597,	-8004},
+{16578,	-8044},
+{16559,	-8084},
+{16539,	-8124},
+{16520,	-8164},
+{16500,	-8203},
+{16480,	-8242},
+{16461,	-8282},
+{16441,	-8322},
+{16421,	-8361},
+{16401,	-8400},
+{16380,	-8440},
+{16360,	-8479},
+{16340,	-8518},
+{16319,	-8557},
+{16299,	-8597},
+{16278,	-8635},
+{16257,	-8674},
+{16237,	-8713},
+{16215,	-8752},
+{16195,	-8791},
+{16173,	-8829},
+{16152,	-8868},
+{16131,	-8907},
+{16110,	-8946},
+{16088,	-8985},
+{16067,	-9023},
+{16045,	-9061},
+{16023,	-9100},
+{16001,	-9138},
+{15979,	-9176},
+{15957,	-9215},
+{15935,	-9253},
+{15913,	-9291},
+{15891,	-9329},
+{15868,	-9367},
+{15846,	-9405},
+{15823,	-9443},
+{15800,	-9481},
+{15778,	-9519},
+{15755,	-9557},
+{15732,	-9595},
+{15709,	-9632},
+{15686,	-9670},
+{15662,	-9708},
+{15639,	-9745},
+{15615,	-9782},
+{15592,	-9820},
+{15569,	-9857},
+{15544,	-9894},
+{15521,	-9932},
+{15497,	-9969},
+{15473,	-10006},
+{15449,	-10043},
+{15425,	-10080},
+{15401,	-10117},
+{15377,	-10154},
+{15352,	-10191},
+{15327,	-10227},
+{15303,	-10264},
+{15278,	-10301},
+{15254,	-10337},
+{15229,	-10374},
+{15204,	-10411},
+{15180,	-10447},
+{15154,	-10483},
+{15129,	-10519},
+{15104,	-10556},
+{15078,	-10592},
+{15053,	-10628},
+{15027,	-10664},
+{15002,	-10700},
+{14976,	-10736},
+{14950,	-10772},
+{14924,	-10808},
+{14898,	-10844},
+{14872,	-10879},
+{14846,	-10915},
+{14820,	-10950},
+{14794,	-10985},
+{14767,	-11021},
+{14741,	-11056},
+{14714,	-11092},
+{14687,	-11127},
+{14661,	-11162},
+{14635,	-11197},
+{14607,	-11232},
+{14581,	-11267},
+{14554,	-11302},
+{14526,	-11337},
+{14499,	-11372},
+{14472,	-11407},
+{14444,	-11441},
+{14417,	-11476},
+{14389,	-11511},
+{14362,	-11545},
+{14334,	-11579},
+{14306,	-11614},
+{14278,	-11648},
+{14251,	-11682},
+{14222,	-11716},
+{14194,	-11750},
+{14166,	-11784},
+{14137,	-11818},
+{14109,	-11852},
+{14081,	-11886},
+{14053,	-11919},
+{14023,	-11953},
+{13995,	-11987},
+{13966,	-12020},
+{13937,	-12054},
+{13909,	-12087},
+{13879,	-12120},
+{13851,	-12153},
+{13821,	-12187},
+{13792,	-12220},
+{13763,	-12253},
+{13733,	-12286},
+{13704,	-12319},
+{13674,	-12351},
+{13645,	-12385},
+{13615,	-12417},
+{13585,	-12450},
+{13555,	-12482},
+{13525,	-12514},
+{13495,	-12546},
+{13465,	-12579},
+{13435,	-12611},
+{13405,	-12644},
+{13374,	-12676},
+{13345,	-12708},
+{13314,	-12739},
+{13283,	-12772}
+};
+
+
+
+cos_msin_t	*s_cos_msin_table[] = {s_cos_msin_2,  s_cos_msin_4,
+                                   s_cos_msin_8,  s_cos_msin_16,
+                                   s_cos_msin_32, s_cos_msin_64
+                                  };
+
diff --git a/third_party/g7221/decode/decoder.c b/third_party/g7221/decode/decoder.c
new file mode 100644
index 0000000..c6b8c06
--- /dev/null
+++ b/third_party/g7221/decode/decoder.c
@@ -0,0 +1,1112 @@
+/***************************************************************************
+**
+**   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(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(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(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 signs_index;
+    Word16 bit;
+    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(index,1);
+                        index = (Word16)*(decoder_table_ptr + temp);
+                        move16();
+                    }
+	                else
+	                {
+                        temp = shl(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(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(1,(temp));
+	                }
+	                
+                    for (j=0; j<vec_dim; j++) 
+                    {
+	                    acca = L_mult0(standard_deviation,mlt_quant_centroid[category][k[j]]);
+                        acca = L_shr(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(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(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(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(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(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(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);
+}