FreeCalypso > hg > gsm-codec-lib
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmhr1/dtx_dec.c Thu Dec 04 09:51:11 2025 +0000 @@ -0,0 +1,238 @@ +/*************************************************************************** + * + * 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))); + +}
