view libgsmhr1/dtx_dec.c @ 598:5809165fb140

libgsmhr1: integrate DTX functions for speech decoder
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 04 Dec 2025 09:51:11 +0000
parents
children c7c03231002d
line wrap: on
line source

/***************************************************************************
 *
 *   File Name: dtx_dec.c
 *
 *   Derivation: this module is the subset of GSM 06.06 dtx.c
 *   reduced to decoder functions that aren't in dtx_rxfe.c, i.e.,
 *   apply only to the full decoder and not the TFO transform.
 *
 **************************************************************************/

/*________________________________________________________________________
 |                                                                        |
 |                         Include Files                                  |
 |________________________________________________________________________|
*/

#include <string.h>
#include "typedefs.h"
#include "namespace.h"
#include "mathhalf.h"
#include "mathdp31.h"
#include "dec_func.h"
#include "dec_state.h"
#include "dtx_const.h"
#include "dtx_dec.h"

/*________________________________________________________________________
 |                                                                        |
 |                            Defines                                     |
 |________________________________________________________________________|
*/

#define ASHIFT 4
#define ASCALE 0x0800


/*________________________________________________________________________
 |                                                                        |
 |                         DTX Rom Tables                                 |
 |________________________________________________________________________|
*/

/* interpolation curve for comfort noise (i*1/12) i=1..12 */
static const Shortword psrCNNewFactor[12] = {
	0x0aaa, 0x1554, 0x1ffe, 0x2aa8, 0x3552,
	0x3ffc, 0x4aa6, 0x5550, 0x5ffa, 0x6aa4,
	0x754e, 0x7fff
};


/*
 * This function is a fragment from original rxInterpR0Lpc():
 * init or update CN interpolation endpoints on CNIFIRSTSID
 * or CNICONT.
 */
void Init_CN_interpolation(struct gsmhr_decoder_state *st, Shortword deco_mode,
			   Shortword new_R0, const Shortword *pswNewKs)
{
	st->swR0OldCN = st->swOldR0Dec;
	st->swR0NewCN = new_R0;
	if (deco_mode == CNIFIRSTSID) {
		rcToCorrDpL(ASHIFT, ASCALE, st->pswOldFrmKsDec,
			    st->pL_OldCorrSeq);
	} else {
		memcpy(st->pL_OldCorrSeq, st->pL_CorrSeq,
			sizeof(st->pL_CorrSeq));
	}
	rcToCorrDpL(ASHIFT, ASCALE, pswNewKs, st->pL_NewCorrSeq);
}

/*
 * This function is a fragment from original rxInterpR0Lpc():
 * interpolate R0 for CN output.
 */
Shortword CN_Interpolate_R0(struct gsmhr_decoder_state *st)
{
	return linInterpSidShort(st->swR0NewCN, st->swR0OldCN,
				 st->swRxDTXState);
}

/*
 * This function is a fragment from original rxInterpR0Lpc():
 * interpolate LPC for CN output.
 */
void CN_Interpolate_LPC(struct gsmhr_decoder_state *st, Shortword *pswNewKs)
{
    int i;

    /* linearly interpolate between the two sets of correlation coefs */
    /* -------------------------------------------------------------- */

    for (i = 0; i < NP + 1; i++)
    {
      st->pL_CorrSeq[i] = linInterpSid(st->pL_NewCorrSeq[i],
					st->pL_OldCorrSeq[i],
					st->swRxDTXState);
    }

    /* Generate this frames K's (overwrite input) */
    /* ------------------------------------------ */

    aFlatRcDp(st->pL_CorrSeq, pswNewKs);
}


/*************************************************************************
 *
 *   FUNCTION NAME: linInterpSid
 *
 *   PURPOSE:
 *
 *     Linearly interpolate between two input numbers based on what the
 *     current DtxState is.
 *
 *   INPUTS:
 *
 *     L_New - longword more current value
 *
 *     L_Old - longword oldest value
 *
 *     swDtxState - state is 0 at the transmitted SID Frame.
 *
 *
 *   OUTPUTS:
 *
 *     none
 *
 *   RETURN VALUE:
 *
 *     A value between old and new inputs with dtxState+1/12 of the new
 *     (dtxState+1)-12/12 of the old
 *
 *
 *************************************************************************/

Longword linInterpSid(Longword L_New, Longword L_Old, Shortword swDtxState)
{

/*_________________________________________________________________________
 |                                                                         |
 |                            Automatic Variables                          |
 |_________________________________________________________________________|
*/

  Shortword swOldFactor;


/*_________________________________________________________________________
 |                                                                         |
 |                              Executable Code                            |
 |_________________________________________________________________________|
*/

  /* old factor = (1.0 - newFactor) */
  /* ------------------------------ */

  swOldFactor = sub(0x7fff, psrCNNewFactor[swDtxState]);
  swOldFactor = add(0x1, swOldFactor);


  /* contributions from new and old */
  /* ------------------------------ */

  L_New = L_mpy_ls(L_New, psrCNNewFactor[swDtxState]);
  L_Old = L_mpy_ls(L_Old, swOldFactor);

  return (L_add(L_New, L_Old));

}


/*************************************************************************
 *
 *   FUNCTION NAME: linInterpSidShort
 *
 *   PURPOSE:
 *
 *     Linearly interpolate between two input numbers based on what
 *     the current DtxState is.
 *
 *   INPUTS:
 *
 *     swNew - 16 bit,  more current value
 *
 *     swOld - 16 bit, oldest value
 *
 *     swDtxState - state is 0 at the transmitted SID Frame.
 *
 *
 *   OUTPUTS:
 *
 *     none
 *
 *   RETURN VALUE:
 *
 *     A value between old and new inputs with dtxState+1/12 of the new
 *     (dtxState+1)-12/12 of the old
 *
 *************************************************************************/

Shortword linInterpSidShort(Shortword swNew, Shortword swOld,
                                   Shortword swDtxState)
{

/*_________________________________________________________________________
 |                                                                         |
 |                            Automatic Variables                          |
 |_________________________________________________________________________|
*/

  Shortword swOldFactor;
  Longword L_New,
         L_Old;


/*_________________________________________________________________________
 |                                                                         |
 |                              Executable Code                            |
 |_________________________________________________________________________|
*/

  /* old factor = (1.0 - newFactor) */
  /* ------------------------------ */

  swOldFactor = sub(0x7fff, psrCNNewFactor[swDtxState]);
  swOldFactor = add(0x1, swOldFactor);


  /* contributions from new and old */
  /* ------------------------------ */

  L_New = L_mult(swNew, psrCNNewFactor[swDtxState]);
  L_Old = L_mult(swOld, swOldFactor);


  return (round(L_add(L_New, L_Old)));

}