view libgsmefr/dec_12k2.c @ 183:452c1d5a6268

libgsmefr BFI w/o data: emit zero output after decoder reset In real-life usage, each EFR decoder session will most likely begin with lots of BFI frames before the first real frame arrives. However, because the spec-defined home state of the decoder is speech rather than CN, our regular logic for BFI w/o data would have to feed pseudorandom noise to the decoder (in the "fixed codebook excitation pulses" part), which is silly to do at the beginning of the decoder session right out of reset. Therefore, let's check reset_flag_old, and if we are still in the reset state, simply emit zero output.
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 03 Jan 2023 00:12:18 +0000
parents d80e9f12a1d1
children 7dd6336e15b2
line wrap: on
line source

/***************************************************************************
 *
 *  FILE NAME:    dec_12k2.c
 *
 *  FUNCTIONS DEFINED IN THIS FILE:
 *                   Init_Decoder_12k2   and  Decoder_12k2
 *
 *
 *  Init_Decoder_12k2():
 *      Initialization of variables for the decoder section.
 *
 *  Decoder_12k2():
 *      Speech decoder routine operating on a frame basis.
 *
 ***************************************************************************/

#include "gsm_efr.h"
#include "typedef.h"
#include "namespace.h"
#include "basic_op.h"
#include "sig_proc.h"
#include "memops.h"
#include "no_count.h"
#include "codec.h"
#include "cnst.h"
#include "dec_state.h"

#include "dtx.h"

/*---------------------------------------------------------------*
 *   Decoder constant parameters (defined in "cnst.h")           *
 *---------------------------------------------------------------*
 *   L_FRAME     : Frame size.                                   *
 *   L_FRAME_BY2 : Half the frame size.                          *
 *   L_SUBFR     : Sub-frame size.                               *
 *   M           : LPC order.                                    *
 *   MP1         : LPC order+1                                   *
 *   PIT_MIN     : Minimum pitch lag.                            *
 *   PIT_MAX     : Maximum pitch lag.                            *
 *   L_INTERPOL  : Length of filter for interpolation            *
 *   PRM_SIZE    : size of vector containing analysis parameters *
 *---------------------------------------------------------------*/

/*--------------------------------------------------------*
 *         Static memory allocation.                      *
 *--------------------------------------------------------*/

/***************************************************************************
 *
 *   FUNCTION:  Init_Decoder_12k2
 *
 *   PURPOSE: Initialization of variables for the decoder section.
 *
 ***************************************************************************/

void Init_Decoder_12k2 (struct EFR_decoder_state *st)
{
    /* Static vectors to zero */

    Set_zero (st->old_exc, PIT_MAX + L_INTERPOL);
    Set_zero (st->mem_syn, M);

    /* Initialize lsp_old [] */

    st->lsp_old[0] = 30000;
    st->lsp_old[1] = 26000;
    st->lsp_old[2] = 21000;
    st->lsp_old[3] = 15000;
    st->lsp_old[4] = 8000;
    st->lsp_old[5] = 0;
    st->lsp_old[6] = -8000;
    st->lsp_old[7] = -15000;
    st->lsp_old[8] = -21000;
    st->lsp_old[9] = -26000;

    /* Initialize memories of bad frame handling */

    st->prev_bf = 0;
    st->bf_state = 0;

    return;
}

/***************************************************************************
 *
 *   FUNCTION:  Decoder_12k2
 *
 *   PURPOSE:   Speech decoder routine.
 *
 ***************************************************************************/

void Decoder_12k2 (
    struct EFR_decoder_state *st,
    Word16 bfi,          /* input : Bad Frame Indication              */
    const Word16 parm[], /* input : vector of synthesis parameters    */
    Word16 synth[],      /* output: synthesis speech                  */
    Word16 A_t[],        /* output: decoded LP filter in 4 subframes  */
    Word16 TAF,
    Word16 SID_flag
)
{
    Word16 *exc = st->old_exc + PIT_MAX + L_INTERPOL;

    /* LPC coefficients */

    Word16 *Az;                 /* Pointer on A_t */

    /* LSPs */

    Word16 lsp_new[M];
    Word16 lsp_mid[M];

    /* Algebraic codevector */

    Word16 code[L_SUBFR];

    /* excitation */

    Word16 excp[L_SUBFR];

    /* Scalars */

    Word16 i, i_subfr;
    Word16 T0, T0_frac, index;
    Word16 gain_pit, gain_code, pit_sharp;
    Word16 temp;
    Word32 L_temp;

    /* Set state machine */

    if (bfi != 0)
    {
        st->bf_state = add (st->bf_state, 1);
    }
    else if (sub (st->bf_state, 6) == 0)
    {
        st->bf_state = 5;
    }
    else
    {
        st->bf_state = 0;
    }

    if (sub (st->bf_state, 6) > 0)
    {
        st->bf_state = 6;
    }
    rx_dtx (st, TAF, bfi, SID_flag);

    /* If this frame is the first speech frame after CNI period,     */
    /* set the BFH state machine to an appropriate state depending   */
    /* on whether there was DTX muting before start of speech or not */
    /* If there was DTX muting, the first speech frame is muted.     */
    /* If there was no DTX muting, the first speech frame is not     */
    /* muted. The BFH state machine starts from state 5, however, to */
    /* keep the audible noise resulting from a SID frame which is    */
    /* erroneously interpreted as a good speech frame as small as    */
    /* possible (the decoder output in this case is quickly muted)   */
    if ((st->rxdtx_ctrl & RX_FIRST_SP_FLAG) != 0)
    {
        if ((st->rxdtx_ctrl & RX_PREV_DTX_MUTING) != 0)
        {
            st->bf_state = 5;
            st->prev_bf = 1;
        }
        else
        {
            st->bf_state = 5;
            st->prev_bf = 0;
        }
    }

    D_plsf_5 (st, parm, lsp_mid, lsp_new, bfi, st->rxdtx_ctrl,
              st->rx_dtx_state);

    /* Advance synthesis parameters pointer */
    parm += 5;                  move16 (); 

    if ((st->rxdtx_ctrl & RX_SP_FLAG) != 0)
    {
        /* Interpolation of LPC for the 4 subframes */

        Int_lpc (st->lsp_old, lsp_mid, lsp_new, A_t);
    }
    else
    {
        /* Comfort noise: use the same parameters in each subframe */
        Lsp_Az (lsp_new, A_t);

        for (i = 0; i < MP1; i++)
        {
            A_t[i + MP1] = A_t[i];      move16 (); 
            A_t[i + 2 * MP1] = A_t[i];  move16 (); 
            A_t[i + 3 * MP1] = A_t[i];  move16 (); 
        }
    }

    /* update the LSPs for the next frame */
    for (i = 0; i < M; i++)
    {
        st->lsp_old[i] = lsp_new[i];
    }

    /*---------------------------------------------------------------------*
     *       Loop for every subframe in the analysis frame                 *
     *---------------------------------------------------------------------*
     * The subframe size is L_SUBFR and the loop is repeated               *
     * L_FRAME/L_SUBFR times                                               *
     *     - decode the pitch delay                                        *
     *     - decode algebraic code                                         *
     *     - decode pitch and codebook gains                               *
     *     - find the excitation and compute synthesis speech              *
     *---------------------------------------------------------------------*/

    /* pointer to interpolated LPC parameters */
    Az = A_t;                           move16 (); 

    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
    {
        Word16 T0_min, T0_max;	/* previously static inside Dec_lag6() */

        index = *parm++;                move16 (); /* pitch index */

        if ((st->rxdtx_ctrl & RX_SP_FLAG) != 0)
        {
            T0 = Dec_lag6 (st, index, PIT_MIN, PIT_MAX, i_subfr, L_FRAME_BY2,
                           &T0_frac, bfi, &T0_min, &T0_max);

            /*-------------------------------------------------*
             * - Find the adaptive codebook vector.            *
             *-------------------------------------------------*/

            Pred_lt_6 (&exc[i_subfr], T0, T0_frac, L_SUBFR);
        }
        else
        {
            T0 = L_SUBFR;               move16 (); 
        }

        /*-------------------------------------------------------*
         * - Decode pitch gain.                                  *
         *-------------------------------------------------------*/

        index = *parm++;                move16 (); 

        gain_pit = d_gain_pitch (st, index, bfi, st->bf_state, st->prev_bf,
                                 st->rxdtx_ctrl);

        /*-------------------------------------------------------*
         * - Decode innovative codebook.                         *
         *-------------------------------------------------------*/

        if ((st->rxdtx_ctrl & RX_SP_FLAG) != 0)
        {
            dec_10i40_35bits (parm, code);
        }
        else
        {   /* Use pseudo noise for excitation when SP_flag == 0 */
            build_CN_code (code, &st->L_pn_seed_rx);
        }

        parm += 10;                     move16 (); 

        /*-------------------------------------------------------*
         * - Add the pitch contribution to code[].               *
         *-------------------------------------------------------*/

        /* pit_sharp = gain_pit;                   */
        /* if (pit_sharp > 1.0) pit_sharp = 1.0;   */

        pit_sharp = shl (gain_pit, 3);

        /* This loop is not entered when SP_FLAG is 0 */
        for (i = T0; i < L_SUBFR; i++)
        {
            temp = mult (code[i - T0], pit_sharp);
            code[i] = add (code[i], temp);
                                        move16 (); 
        }

        /* post processing of excitation elements */

        test (); /* This test is not passed when SP_FLAG is 0 */
        if (sub (pit_sharp, 16384) > 0)
        {
            for (i = 0; i < L_SUBFR; i++)
            {
                temp = mult (exc[i + i_subfr], pit_sharp);
                L_temp = L_mult (temp, gain_pit);
                L_temp = L_shl (L_temp, 1);
                excp[i] = round (L_temp);
                                        move16 (); 
            }
        }
        /*-------------------------------------------------*
         * - Decode codebook gain.                         *
         *-------------------------------------------------*/

        index = *parm++;                move16 (); /* index of energy VQ */

        d_gain_code (st, index, code, L_SUBFR, &gain_code, bfi, st->bf_state,
                     st->prev_bf, st->rxdtx_ctrl, i_subfr, st->rx_dtx_state);

        /*-------------------------------------------------------*
         * - Find the total excitation.                          *
         * - Find synthesis speech corresponding to exc[].       *
         *-------------------------------------------------------*/
        for (i = 0; i < L_SUBFR; i++)
        {
            /* exc[i] = gain_pit*exc[i] + gain_code*code[i]; */

            L_temp = L_mult (exc[i + i_subfr], gain_pit);
            L_temp = L_mac (L_temp, code[i], gain_code);
            L_temp = L_shl (L_temp, 3);

            exc[i + i_subfr] = round (L_temp);
                                        move16 (); 
        }

        if (sub (pit_sharp, 16384) > 0)
        {
            for (i = 0; i < L_SUBFR; i++)
            {
                excp[i] = add (excp[i], exc[i + i_subfr]);
            }
            agc2 (&exc[i_subfr], excp, L_SUBFR);
            Syn_filt (Az, excp, &synth[i_subfr], L_SUBFR, st->mem_syn, 1);
        }
        else
        {
            Syn_filt (Az, &exc[i_subfr], &synth[i_subfr], L_SUBFR,
                      st->mem_syn, 1);
        }

        /* interpolated LPC parameters for next subframe */
        Az += MP1;                      move16 (); 
    }

    /*--------------------------------------------------*
     * Update signal for next frame.                    *
     * -> shift to the left by L_FRAME  exc[]           *
     *--------------------------------------------------*/

    Copy (&st->old_exc[L_FRAME], &st->old_exc[0], PIT_MAX + L_INTERPOL);
    st->prev_bf = bfi;

    return;
}