diff libtwamr/qua_gain.c @ 377:b02e043dcba0

libtwamr: integrate qua_gain.c
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 06 May 2024 04:24:17 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libtwamr/qua_gain.c	Mon May 06 04:24:17 2024 +0000
@@ -0,0 +1,236 @@
+/*
+********************************************************************************
+*
+*      GSM AMR-NB speech codec   R98   Version 7.6.0   December 12, 2001
+*                                R99   Version 3.3.0                
+*                                REL-4 Version 4.1.0                
+*
+********************************************************************************
+*
+*      File             : qua_gain.c
+*      Purpose          : Quantization of pitch and codebook gains.
+*
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+*                         MODULE INCLUDE FILE AND VERSION ID
+********************************************************************************
+*/
+#include "namespace.h"
+#include "qua_gain.h"
+
+/*
+********************************************************************************
+*                         INCLUDE FILES
+********************************************************************************
+*/
+#include "tw_amr.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "no_count.h"
+#include "cnst.h"
+#include "pow2.h"
+#include "gc_pred.h"
+#include "qua_gain_tab.h"
+
+/*
+********************************************************************************
+*                         PUBLIC PROGRAM CODE
+********************************************************************************
+*/
+
+/*************************************************************************
+ *
+ * FUNCTION:  Qua_gain()
+ *
+ * PURPOSE: Quantization of pitch and codebook gains.
+ *          (using predicted codebook gain)
+ *
+ *************************************************************************/
+Word16
+Qua_gain(                   /* o  : index of quantization.                 */   
+    enum Mode mode,         /* i  : AMR mode                               */
+    Word16 exp_gcode0,      /* i  : predicted CB gain (exponent),      Q0  */
+    Word16 frac_gcode0,     /* i  : predicted CB gain (fraction),      Q15 */
+    Word16 frac_coeff[],    /* i  : energy coeff. (5), fraction part,  Q15 */
+    Word16 exp_coeff[],     /* i  : energy coeff. (5), exponent part,  Q0  */
+                            /*      (frac_coeff and exp_coeff computed in  */
+                            /*       calc_filt_energies())                 */
+    Word16 gp_limit,        /* i  : pitch gain limit                       */
+    Word16 *gain_pit,       /* o  : Pitch gain,                        Q14 */
+    Word16 *gain_cod,       /* o  : Code gain,                         Q1  */
+    Word16 *qua_ener_MR122, /* o  : quantized energy error,            Q10 */
+                            /*      (for MR122 MA predictor update)        */
+    Word16 *qua_ener        /* o  : quantized energy error,            Q10 */
+                            /*      (for other MA predictor update)        */
+)
+{
+    const Word16 *p;
+    Word16 i, j, index = 0;
+    Word16 gcode0, e_max, exp_code;
+    Word16 g_pitch, g2_pitch, g_code, g2_code, g_pit_cod;
+    Word16 coeff[5], coeff_lo[5];
+    Word16 exp_max[5];
+    Word32 L_tmp, dist_min;
+    const Word16 *table_gain;
+    Word16 table_len;
+    
+    test();  test(); test();
+    if ( sub (mode, MR102) == 0 || sub (mode, MR74) == 0 || sub (mode, MR67) == 0)
+    {
+       table_len = VQ_SIZE_HIGHRATES;            move16 ();
+       table_gain = table_gain_highrates;        move16 ();
+    }
+    else
+    {
+       table_len = VQ_SIZE_LOWRATES;             move16 ();
+       table_gain = table_gain_lowrates;         move16 ();
+    }
+    
+    /*-------------------------------------------------------------------*
+     *  predicted codebook gain                                          *
+     *  ~~~~~~~~~~~~~~~~~~~~~~~                                          *
+     *  gc0     = 2^exp_gcode0 + 2^frac_gcode0                           *
+     *                                                                   *
+     *  gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0)      *
+     *-------------------------------------------------------------------*/
+
+    gcode0 = extract_l(Pow2(14, frac_gcode0));
+
+    /*-------------------------------------------------------------------*
+     *  Scaling considerations:                                          *
+     *  ~~~~~~~~~~~~~~~~~~~~~~~                                          *
+     *-------------------------------------------------------------------*/
+
+    /*
+     * The error energy (sum) to be minimized consists of five terms, t[0..4].
+     *
+     *                      t[0] =    gp^2  * <y1 y1>
+     *                      t[1] = -2*gp    * <xn y1>
+     *                      t[2] =    gc^2  * <y2 y2>
+     *                      t[3] = -2*gc    * <xn y2>
+     *                      t[4] =  2*gp*gc * <y1 y2>
+     *
+     */
+
+    /* determine the scaling exponent for g_code: ec = ec0 - 11 */
+    exp_code = sub(exp_gcode0, 11);
+
+    /* calculate exp_max[i] = s[i]-1 */
+    exp_max[0] = sub(exp_coeff[0], 13);                        move16 ();
+    exp_max[1] = sub(exp_coeff[1], 14);                        move16 ();
+    exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1))); move16 ();
+    exp_max[3] = add(exp_coeff[3], exp_code);                  move16 ();
+    exp_max[4] = add(exp_coeff[4], add(1, exp_code));          move16 ();
+
+
+    /*-------------------------------------------------------------------*
+     *  Find maximum exponent:                                           *
+     *  ~~~~~~~~~~~~~~~~~~~~~~                                           *
+     *                                                                   *
+     *  For the sum operation, all terms must have the same scaling;     *
+     *  that scaling should be low enough to prevent overflow. There-    *
+     *  fore, the maximum scale is determined and all coefficients are   *
+     *  re-scaled:                                                       *
+     *                                                                   *
+     *    e_max = max(exp_max[i]) + 1;                                   *
+     *    e = exp_max[i]-e_max;         e <= 0!                          *
+     *    c[i] = c[i]*2^e                                                *
+     *-------------------------------------------------------------------*/
+
+    e_max = exp_max[0];                                        move16 ();
+    for (i = 1; i < 5; i++)
+    {
+        move16(); test();
+        if (sub(exp_max[i], e_max) > 0)
+        {
+            e_max = exp_max[i];                                move16 ();
+        }
+    }
+
+    e_max = add(e_max, 1);      /* To avoid overflow */
+
+    for (i = 0; i < 5; i++) {
+        j = sub(e_max, exp_max[i]);
+        L_tmp = L_deposit_h(frac_coeff[i]);
+        L_tmp = L_shr(L_tmp, j);
+        L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
+    }
+
+
+    /*-------------------------------------------------------------------*
+     *  Codebook search:                                                 *
+     *  ~~~~~~~~~~~~~~~~                                                 *
+     *                                                                   *
+     *  For each pair (g_pitch, g_fac) in the table calculate the        *
+     *  terms t[0..4] and sum them up; the result is the mean squared    *
+     *  error for the quantized gains from the table. The index for the  *
+     *  minimum MSE is stored and finally used to retrieve the quantized *
+     *  gains                                                            *
+     *-------------------------------------------------------------------*/
+
+    /* start with "infinite" MSE */
+    dist_min = MAX_32;        move32();
+
+    p = &table_gain[0];       move16 ();
+
+    for (i = 0; i < table_len; i++)
+    {
+        g_pitch = *p++;       move16 ();
+        g_code = *p++;        move16 (); /* this is g_fac        */
+        p++;                             /* skip log2(g_fac)     */
+        p++;                             /* skip 20*log10(g_fac) */
+            
+        test ();
+        if (sub(g_pitch, gp_limit) <= 0)
+        {
+            g_code = mult(g_code, gcode0);
+            g2_pitch = mult(g_pitch, g_pitch);
+            g2_code = mult(g_code, g_code);
+            g_pit_cod = mult(g_code, g_pitch);
+
+            L_tmp = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch);
+            L_tmp = L_add(L_tmp, Mpy_32_16(coeff[1], coeff_lo[1], g_pitch));
+            L_tmp = L_add(L_tmp, Mpy_32_16(coeff[2], coeff_lo[2], g2_code));
+            L_tmp = L_add(L_tmp, Mpy_32_16(coeff[3], coeff_lo[3], g_code));
+            L_tmp = L_add(L_tmp, Mpy_32_16(coeff[4], coeff_lo[4], g_pit_cod));
+
+            /* store table index if MSE for this index is lower
+               than the minimum MSE seen so far */
+            test ();
+            if (L_sub(L_tmp, dist_min) < (Word32) 0)
+            {
+                dist_min = L_tmp; move32 ();
+                index = i;        move16 ();
+            }
+        }
+    }
+
+    /*------------------------------------------------------------------*
+     *  read quantized gains and new values for MA predictor memories   *
+     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   *
+     *------------------------------------------------------------------*/
+
+    /* Read the quantized gains */
+    p = &table_gain[shl (index, 2)]; move16 ();
+    *gain_pit = *p++;         move16();
+    g_code = *p++;            move16();
+    *qua_ener_MR122 = *p++;   move16();
+    *qua_ener = *p;           move16();
+
+    /*------------------------------------------------------------------*
+     *  calculate final fixed codebook gain:                            *
+     *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
+     *                                                                  *
+     *   gc = gc0 * g                                                   *
+     *------------------------------------------------------------------*/
+
+    L_tmp = L_mult(g_code, gcode0);
+    L_tmp = L_shr(L_tmp, sub(10, exp_gcode0));
+    *gain_cod = extract_h(L_tmp);
+
+    return index;
+}