view libtwamr/d_plsf_5.c @ 350:9b05bbc23b8a

libgsmefr inline: make shift count guards 100% robust
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 23 Apr 2024 05:34:54 +0000
parents 29769a9b89d3
children
line wrap: on
line source

/*
*****************************************************************************
*
*      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             : d_plsf_5.c
*
*****************************************************************************
*/
 
/*
*****************************************************************************
*                         MODULE INCLUDE FILE AND VERSION ID
*****************************************************************************
*/
#include "namespace.h"
#include "d_plsf.h"
 
/*
*****************************************************************************
*                         INCLUDE FILES
*****************************************************************************
*/
#include "typedef.h"
#include "basic_op.h"
#include "no_count.h"
#include "lsp_lsf.h"
#include "reorder.h"
#include "cnst.h"
#include "memops.h"
#include "q_plsf5_tab.h"

/*
*****************************************************************************
*                         LOCAL VARIABLES AND TABLES
*****************************************************************************
*/

/* ALPHA    ->  0.95       */
/* ONE_ALPHA-> (1.0-ALPHA) */
#define ALPHA     31128
#define ONE_ALPHA 1639

/*
*--------------------------------------------------*
* Constants (defined in cnst.h)                    *
*--------------------------------------------------*
*  M                    : LPC order
*--------------------------------------------------*
*/
 
/*
*****************************************************************************
*                         PUBLIC PROGRAM CODE
*****************************************************************************
*/
/*
**************************************************************************
*
*  Function    : D_plsf_5
*  Purpose     : Decodes the 2 sets of LSP parameters in a frame 
*                using the received quantization indices.
*
**************************************************************************
*/
int D_plsf_5 (
    D_plsfState *st,    /* i/o: State variables                            */
    Word16 bfi,         /* i  : bad frame indicator (set to 1 if a bad    
                                frame is received)                         */  
    Word16 *indice,     /* i  : quantization indices of 5 submatrices, Q0  */
    Word16 *lsp1_q,     /* o  : quantized 1st LSP vector (M),          Q15 */
    Word16 *lsp2_q      /* o  : quantized 2nd LSP vector (M),          Q15 */
)
{
    Word16 i;
    const Word16 *p_dico;
    Word16 temp, sign;
    Word16 lsf1_r[M], lsf2_r[M];
    Word16 lsf1_q[M], lsf2_q[M];

    test (); 
    if (bfi != 0)                               /* if bad frame */
    {
        /* use the past LSFs slightly shifted towards their mean */

        for (i = 0; i < M; i++)
        {
            /* lsfi_q[i] = ALPHA*st->past_lsf_q[i] + ONE_ALPHA*mean_lsf[i]; */

            lsf1_q[i] = add (mult (st->past_lsf_q[i], ALPHA),
                             mult (mean_lsf[i], ONE_ALPHA));
                                                move16 (); 

            lsf2_q[i] = lsf1_q[i];              move16 (); 
        }

        /* estimate past quantized residual to be used in next frame */

        for (i = 0; i < M; i++)
        {
            /* temp  = mean_lsf[i] +  st->past_r_q[i] * LSP_PRED_FAC_MR122; */

            temp = add (mean_lsf[i], mult (st->past_r_q[i],
                                           LSP_PRED_FAC_MR122));

            st->past_r_q[i] = sub (lsf2_q[i], temp);
                                                move16 (); 
        }
    }
    else
        /* if good LSFs received */
    {
        /* decode prediction residuals from 5 received indices */

        p_dico = &dico1_lsf[shl (indice[0], 2)];move16 ();
        lsf1_r[0] = *p_dico++;                  move16 (); 
        lsf1_r[1] = *p_dico++;                  move16 (); 
        lsf2_r[0] = *p_dico++;                  move16 (); 
        lsf2_r[1] = *p_dico++;                  move16 (); 

        p_dico = &dico2_lsf[shl (indice[1], 2)];move16 ();
        lsf1_r[2] = *p_dico++;                  move16 (); 
        lsf1_r[3] = *p_dico++;                  move16 (); 
        lsf2_r[2] = *p_dico++;                  move16 (); 
        lsf2_r[3] = *p_dico++;                  move16 (); 

        sign = indice[2] & 1;                   logic16 (); 
        i = shr (indice[2], 1);
        p_dico = &dico3_lsf[shl (i, 2)];        move16 (); 

        test (); 
        if (sign == 0)
        {
            lsf1_r[4] = *p_dico++;              move16 (); 
            lsf1_r[5] = *p_dico++;              move16 (); 
            lsf2_r[4] = *p_dico++;              move16 (); 
            lsf2_r[5] = *p_dico++;              move16 (); 
        }
        else
        {
            lsf1_r[4] = negate (*p_dico++);     move16 (); 
            lsf1_r[5] = negate (*p_dico++);     move16 (); 
            lsf2_r[4] = negate (*p_dico++);     move16 (); 
            lsf2_r[5] = negate (*p_dico++);     move16 (); 
        }

        p_dico = &dico4_lsf[shl (indice[3], 2)];move16 (); 
        lsf1_r[6] = *p_dico++;                  move16 (); 
        lsf1_r[7] = *p_dico++;                  move16 (); 
        lsf2_r[6] = *p_dico++;                  move16 (); 
        lsf2_r[7] = *p_dico++;                  move16 (); 

        p_dico = &dico5_lsf[shl (indice[4], 2)];move16 (); 
        lsf1_r[8] = *p_dico++;                  move16 (); 
        lsf1_r[9] = *p_dico++;                  move16 (); 
        lsf2_r[8] = *p_dico++;                  move16 (); 
        lsf2_r[9] = *p_dico++;                  move16 (); 

        /* Compute quantized LSFs and update the past quantized residual */
        for (i = 0; i < M; i++)
        {
            temp = add (mean_lsf[i], mult (st->past_r_q[i],
                                           LSP_PRED_FAC_MR122));
            lsf1_q[i] = add (lsf1_r[i], temp);
                                                move16 (); 
            lsf2_q[i] = add (lsf2_r[i], temp);
                                                move16 (); 
            st->past_r_q[i] = lsf2_r[i];        move16 (); 
        }
    }

    /* verification that LSFs have minimum distance of LSF_GAP Hz */

    Reorder_lsf (lsf1_q, LSF_GAP, M);
    Reorder_lsf (lsf2_q, LSF_GAP, M);

    Copy (lsf2_q, st->past_lsf_q, M);

    /*  convert LSFs to the cosine domain */

    Lsf_lsp (lsf1_q, lsp1_q, M);
    Lsf_lsp (lsf2_q, lsp2_q, M);

    return 0;
}