FreeCalypso > hg > gsm-codec-lib
view libgsmefr/dec_12k2.c @ 467:ad032051166a
doc: AMR-EFR-hybrid-emu new article
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 12 May 2024 23:54:43 +0000 |
parents | 7dd6336e15b2 |
children |
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++; } else if (st->bf_state == 6) { st->bf_state = 5; } else { st->bf_state = 0; } if (st->bf_state > 6) { 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 (pit_sharp > 16384) { 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 (pit_sharp > 16384) { 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; }