diff libgsmefr/q_gains.c @ 53:49dd1ac8e75b

libgsmefr: import most *.c files from ETSI source
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 25 Nov 2022 16:18:21 +0000
parents
children 03599300d2db
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmefr/q_gains.c	Fri Nov 25 16:18:21 2022 +0000
@@ -0,0 +1,218 @@
+/*--------------------------------------------------------------------------*
+ * Function q_gain_pitch(), q_gain_code()                                  *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                  *
+ * Scalar quantization of the pitch gain and the innovative codebook gain.  *
+ *                                                                          *
+ * MA prediction is performed on the innovation energy                      *
+ * (in dB/(20*log10(2))) with mean removed.                                 *
+ *-------------------------------------------------------------------------*/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "count.h"
+#include "sig_proc.h"
+
+#include "gains_tb.h"
+
+#include "cnst.h"
+#include "dtx.h"
+
+/* past quantized energies.                               */
+/* initialized to -14.0/constant, constant = 20*Log10(2)   */
+Word16 past_qua_en[4];
+
+/* MA prediction coeff */
+Word16 pred[4];
+
+extern Word16 CN_excitation_gain, gain_code_old_tx[4 * DTX_HANGOVER];
+
+Word16 q_gain_pitch (   /* Return index of quantization */
+    Word16 *gain        /* (i)  :  Pitch gain to quantize  */
+)
+{
+    Word16 i, index, gain_q14, err, err_min;
+
+    gain_q14 = shl (*gain, 2);
+
+    err_min = abs_s (sub (gain_q14, qua_gain_pitch[0]));
+    index = 0;                                  move16 (); 
+
+    for (i = 1; i < NB_QUA_PITCH; i++)
+    {
+        err = abs_s (sub (gain_q14, qua_gain_pitch[i]));
+
+        test (); 
+        if (sub (err, err_min) < 0)
+        {
+            err_min = err;                      move16 (); 
+            index = i;                          move16 (); 
+        }
+    }
+
+    *gain = shr (qua_gain_pitch[index], 2);     move16 (); 
+
+    return index;
+}
+
+/* average innovation energy.                             */
+/* MEAN_ENER  = 36.0/constant, constant = 20*Log10(2)     */
+
+#define MEAN_ENER  783741L      /* 36/(20*log10(2))       */
+
+Word16 q_gain_code (    /* Return quantization index                  */
+    Word16 code[],      /* (i)      : fixed codebook excitation       */
+    Word16 lcode,       /* (i)      : codevector size                 */
+    Word16 *gain,       /* (i/o)    : quantized fixed codebook gain   */
+    Word16 txdtx_ctrl,
+    Word16 i_subfr
+)
+{
+    Word16 i, index;
+    Word16 gcode0, err, err_min, exp, frac;
+    Word32 ener, ener_code;
+    Word16 aver_gain;
+    static Word16 gcode0_CN;
+
+    logic16 (); test (); 
+    if ((txdtx_ctrl & TX_SP_FLAG) != 0)
+    {
+
+        /*-------------------------------------------------------------------*
+         *  energy of code:                                                   *
+         *  ~~~~~~~~~~~~~~~                                                   *
+         *  ener_code(Q17) = 10 * Log10(energy/lcode) / constant              *
+         *                 = 1/2 * Log2(energy/lcode)                         *
+         *                                           constant = 20*Log10(2)   *
+         *-------------------------------------------------------------------*/
+
+        /* ener_code = log10(ener_code/lcode) / (20*log10(2))       */
+        ener_code = 0;                          move32 (); 
+        for (i = 0; i < lcode; i++)
+        {
+            ener_code = L_mac (ener_code, code[i], code[i]);
+        }
+        /* ener_code = ener_code / lcode */
+        ener_code = L_mult (round (ener_code), 26214);
+
+        /* ener_code = 1/2 * Log2(ener_code) */
+        Log2 (ener_code, &exp, &frac);
+        ener_code = L_Comp (sub (exp, 30), frac);
+
+        /* predicted energy */
+
+        ener = MEAN_ENER;                       move32 (); 
+        for (i = 0; i < 4; i++)
+        {
+            ener = L_mac (ener, past_qua_en[i], pred[i]);
+        }
+
+        /*-------------------------------------------------------------------*
+         *  predicted codebook gain                                           *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~                                           *
+         *  gcode0(Qx) = Pow10( (ener*constant - ener_code*constant) / 20 )   *
+         *             = Pow2(ener-ener_code)                                 *
+         *                                           constant = 20*Log10(2)   *
+         *-------------------------------------------------------------------*/
+
+        ener = L_shr (L_sub (ener, ener_code), 1);
+        L_Extract (ener, &exp, &frac);
+
+        gcode0 = extract_l (Pow2 (exp, frac));  /* predicted gain */
+
+        gcode0 = shl (gcode0, 4);
+
+        /*-------------------------------------------------------------------*
+         *                   Search for best quantizer                        *
+         *-------------------------------------------------------------------*/
+
+        err_min = abs_s (sub (*gain, mult (gcode0, qua_gain_code[0])));
+        index = 0;              move16 (); 
+
+        for (i = 1; i < NB_QUA_CODE; i++)
+        {
+            err = abs_s (sub (*gain, mult (gcode0, qua_gain_code[i])));
+
+            test (); 
+            if (sub (err, err_min) < 0)
+            {
+                err_min = err;                  move16 (); 
+                index = i;                      move16 (); 
+            }
+        }
+
+        *gain = mult (gcode0, qua_gain_code[index]);
+                                                move16 (); 
+
+        /*------------------------------------------------------------------*
+         *  update table of past quantized energies                         *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         *
+         *  past_qua_en(Q12) = 20 * Log10(qua_gain_code) / constant         *
+         *                   = Log2(qua_gain_code)                          *
+         *                                           constant = 20*Log10(2) *
+         *------------------------------------------------------------------*/
+
+        for (i = 3; i > 0; i--)
+        {
+            past_qua_en[i] = past_qua_en[i - 1];move16 (); 
+        }
+        Log2 (L_deposit_l (qua_gain_code[index]), &exp, &frac);
+
+        past_qua_en[0] = shr (frac, 5);         move16 (); 
+        past_qua_en[0] = add (past_qua_en[0], shl (sub (exp, 11), 10));
+                                                move16 (); 
+
+        update_gain_code_history_tx (*gain, gain_code_old_tx);
+    }
+    else
+    {
+        logic16 (); test (); test (); 
+        if ((txdtx_ctrl & TX_PREV_HANGOVER_ACTIVE) != 0 && (i_subfr == 0))
+        {
+            gcode0_CN = update_gcode0_CN (gain_code_old_tx);
+            gcode0_CN = shl (gcode0_CN, 4);
+        }
+        *gain = CN_excitation_gain;             move16 (); 
+
+        logic16 (); test (); test (); 
+        if ((txdtx_ctrl & TX_SID_UPDATE) != 0)
+        {
+            aver_gain = aver_gain_code_history (CN_excitation_gain,
+                                                gain_code_old_tx);
+
+            /*---------------------------------------------------------------*
+             *                   Search for best quantizer                    *
+             *---------------------------------------------------------------*/
+
+            err_min = abs_s (sub (aver_gain, 
+                                  mult (gcode0_CN, qua_gain_code[0])));
+            index = 0;                          move16 (); 
+
+            for (i = 1; i < NB_QUA_CODE; i++)
+            {
+                err = abs_s (sub (aver_gain, 
+                                  mult (gcode0_CN, qua_gain_code[i])));
+
+                test (); 
+                if (sub (err, err_min) < 0)
+                {
+                    err_min = err;              move16 (); 
+                    index = i;                  move16 (); 
+                }
+            }
+        }
+        update_gain_code_history_tx (*gain, gain_code_old_tx);
+
+        /*-------------------------------------------------------------------*
+         *  reset table of past quantized energies                            *
+         *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
+         *-------------------------------------------------------------------*/
+
+        for (i = 0; i < 4; i++)
+        {
+            past_qua_en[i] = -2381;             move16 (); 
+        }
+    }
+
+    return index;
+}