view libgsmefr/q_gains.c @ 282:9ee8ad3d4d30

frtest: rm gsmfr-hand-test and gsmfr-max-out utils These hack programs were never properly documented and were written only as part of a debug chase, in pursuit of a bug that ultimately turned out to be in our then-hacky patch to osmo-bts-sysmo, before beginning of proper patches in Osmocom. These hack programs need to be dropped from the present sw package because they depend on old libgsm, and we are eliminating that dependency.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 14 Apr 2024 05:44:47 +0000
parents 33487966077e
children
line wrap: on
line source

/*--------------------------------------------------------------------------*
 * 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 "gsm_efr.h"
#include "typedef.h"
#include "namespace.h"
#include "basic_op.h"
#include "oper_32b.h"
#include "no_count.h"
#include "sig_proc.h"
#include "codec.h"

#include "gains_tb.h"

#include "cnst.h"
#include "dtx.h"
#include "enc_state.h"

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 (err < err_min)
        {
            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                  */
    struct EFR_encoder_state *st,
    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;

    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, st->past_qua_en[i], st->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 (err < err_min)
            {
                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--)
        {
            st->past_qua_en[i] = st->past_qua_en[i - 1];
        }
        Log2 (L_deposit_l (qua_gain_code[index]), &exp, &frac);

        st->past_qua_en[0] = shr (frac, 5);
        st->past_qua_en[0] = add (st->past_qua_en[0], shl (sub (exp, 11), 10));

        update_gain_code_history_tx (st, *gain);
    }
    else
    {
        if ((txdtx_ctrl & TX_PREV_HANGOVER_ACTIVE) != 0 && (i_subfr == 0))
        {
            st->gcode0_CN = update_gcode0_CN (st->gain_code_old_tx);
            st->gcode0_CN = shl (st->gcode0_CN, 4);
        }
        *gain = st->CN_excitation_gain;

        if ((txdtx_ctrl & TX_SID_UPDATE) != 0)
        {
            aver_gain = aver_gain_code_history (st->CN_excitation_gain,
                                                st->gain_code_old_tx);

            /*---------------------------------------------------------------*
             *                   Search for best quantizer                    *
             *---------------------------------------------------------------*/

            err_min = abs_s (sub (aver_gain, 
                                  mult (st->gcode0_CN, qua_gain_code[0])));
            index = 0;

            for (i = 1; i < NB_QUA_CODE; i++)
            {
                err = abs_s (sub (aver_gain, 
                                  mult (st->gcode0_CN, qua_gain_code[i])));

                if (err < err_min)
                {
                    err_min = err;              move16 (); 
                    index = i;                  move16 (); 
                }
            }
        }
        update_gain_code_history_tx (st, *gain);

        /*-------------------------------------------------------------------*
         *  reset table of past quantized energies                            *
         *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            *
         *-------------------------------------------------------------------*/

        for (i = 0; i < 4; i++)
        {
            st->past_qua_en[i] = -2381;
        }
    }

    return index;
}