FreeCalypso > hg > gsm-codec-lib
changeset 613:7ce83c70ec5f
libgsmhr1: integrate encoder DTX functions, first round
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Thu, 05 Mar 2026 07:53:49 +0000 |
| parents | a5879e04ad47 |
| children | cf74197b9d4f |
| files | libgsmhr1/Makefile libgsmhr1/dtx_enc.c libgsmhr1/dtx_enc.h |
| diffstat | 3 files changed, 689 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/libgsmhr1/Makefile Thu Mar 05 07:35:43 2026 +0000 +++ b/libgsmhr1/Makefile Thu Mar 05 07:53:49 2026 +0000 @@ -1,12 +1,12 @@ -OBJS= dec_func.o dec_state.o dhf_packed.o dhf_params.o dtx_dec.o dtx_rxfe.o \ - enc_out_order.o enc_state.o err_conc.o mathdp31.o mathhalf.o \ +OBJS= dec_func.o dec_state.o dhf_packed.o dhf_params.o dtx_dec.o dtx_enc.o \ + dtx_rxfe.o enc_out_order.o enc_state.o err_conc.o mathdp31.o mathhalf.o\ pack_frame.o paramval_cod.o paramval_common.o paramval_dec.o rtp_in.o \ rtp_in_direct.o rxfe.o rxfe_create.o sid_cw_params.o sid_detect.o \ sid_reset.o sp_dec.o sp_rom.o tfo.o twts002_in.o twts002_out.o \ unpack_frame.o -HDRS= dec_func.h dec_state.h dtx_const.h dtx_dec.h dtx_rxfe.h enc_out_order.h\ - enc_state.h err_conc.h mathdp31.h mathhalf.h namespace.h rxfe.h \ - sp_rom.h tw_gsmhr.h typedefs.h +HDRS= dec_func.h dec_state.h dtx_const.h dtx_dec.h dtx_enc.h dtx_rxfe.h \ + enc_out_order.h enc_state.h err_conc.h mathdp31.h mathhalf.h \ + namespace.h rxfe.h sp_rom.h tw_gsmhr.h typedefs.h LIB= libgsmhr1.a include ../config.defs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmhr1/dtx_enc.c Thu Mar 05 07:53:49 2026 +0000 @@ -0,0 +1,656 @@ +/*************************************************************************** + * + * File Name: dtx_enc.c + * + * Derivation: this module is the subset of GSM 06.06 dtx.c + * reduced to those functions that are used only by the speech + * encoder. + * + **************************************************************************/ + +/*________________________________________________________________________ + | | + | Include Files | + |________________________________________________________________________| +*/ + +#include "typedefs.h" +#include "namespace.h" +#include "mathhalf.h" +#include "mathdp31.h" +#include "enc_state.h" +#include "dtx_const.h" +#include "dtx_enc.h" +#include "dtx_rxfe.h" + +/*________________________________________________________________________ + | | + | Defines | + |________________________________________________________________________| +*/ + +#define OH_SHIFT 3 /* shift corresponding to OVERHANG */ + +#define NP_AFLAT 4 +#define LPC_VQ_SEG 3 + + +/************************************************************************* + * + * FUNCTION NAME: swComfortNoise + * + * PURPOSE: + * + * This routine perform the following tasks: + * - generation of the speech flag (swSP) + * - averaging and encoding of the comfort noise parameters + * - randomization of the codebook indices + * + * + * INPUTS: + * + * swVadFrmCnt (global) - swVadFlag=0 frame counter. + * If swVadFlag=1 then this counter is 0, the first frame with + * swVadFlag=0 will set this counter to 1, with each additional + * swVadFlag=0 frame the counter is incremented. + * + * swVadFlag - voise activity flag. swVadFlag=0 frame with + * no voice activity, swVadFlag=0 frame with voice activity + * + * L_UnqntzdR0 - unquantized R(0), 32 bit value, output of + * FLAT. + * + * pL_UnqntzdCorr[NP+1] - unquantized correlation sequence, + * also an output of FLAT. + * + * + * OUTPUTS: + * + * swCNR0 - global variable, the output quantized R0 index + * + * pswCNLpc[3] - global variable, the output quantized LPC to the + * transmitted in the SID frame + * + * pswCNGsp0Code[N_SUB] - global variable, the output quantized GSP0 indices + * + * pswCNVSCode1[N_SUB] - global variable, the output quantized codevector 1 + * indices. + * + * pswCNVSCode2[N_SUB] - global variable, the output quantized codevector 2 + * indices. + * + * + * RETURN VALUE: + * + * swSP - speech flag, swSP=1 speech frames are generated, swSP=0 + * SID frames are generated. + * + *************************************************************************/ + +Shortword swComfortNoise(struct gsmhr_encoder_state *st, Shortword swVadFlag, + Longword L_UnqntzdR0, Longword *pL_UnqntzdCorr) +{ + +/*_________________________________________________________________________ + | | + | Automatic Variables | + |_________________________________________________________________________| +*/ + + struct cn_state *cn_st = &st->cn_state; + Shortword swSP; + Shortword pswFinalRc[NP]; + + /* unquantized reference parameters */ + Longword L_RefR0; + Longword pL_RefCorr[NP + 1]; + Longword L_RefGs; + + int i; + + +/*_________________________________________________________________________ + | | + | Executable Code | + |_________________________________________________________________________| +*/ + + swSP = 1; + + /* VadFrmCnt will indicate the number of sequential frames where */ + /* swVadFlag == 0 */ + /* ------------------------------------------------------------- */ + + if (swVadFlag) + st->swVadFrmCnt = 0; /* Voice acitvity present */ + else + st->swVadFrmCnt = add(st->swVadFrmCnt, 1); /* no voice activity */ + + + /* swNElapsed will indicate the number of frames that have elapsed */ + /* since the last SID frame with updated comfort noise parameters */ + /* was generated */ + /* --------------------------------------------------------------- */ + + st->swNElapsed = add(st->swNElapsed, 1); + + + /* If no voice activity was detected. */ + /* ----------------------------------- */ + + if (st->swVadFrmCnt) + { + + /* Short speech burst ? */ + /* -------------------- */ + + if (st->swVadFrmCnt == 1) + { + if (sub(st->swNElapsed, 24) < 0) + cn_st->swShortBurst = 1; /* short speech burst detected */ + else + cn_st->swShortBurst = 0; /* long speech burst detected */ + } + + + /* Update history, with this frames data */ + /* ------------------------------------- */ + + updateCNHist(st, L_UnqntzdR0, pL_UnqntzdCorr, + cn_st->pL_R0Hist, cn_st->ppL_CorrHist); + + + /* first SID frame */ + /* --------------- */ + + if (((cn_st->swShortBurst == 0) && (st->swVadFrmCnt == OVERHANG)) || + ((cn_st->swShortBurst == 1) && (st->swVadFrmCnt == 1))) + { + + /* init. random generator */ + /* ---------------------- */ + cn_st->L_TxPNSeed = PN_INIT_SEED; + + + /* average GS */ + /* ---------- */ + avgGsHistQntz(st->pL_GsHist, &L_RefGs); + + + /* GS quantization */ + /* --------------- */ + cn_st->swRefGsIndex = gsQuant(L_RefGs, 0); + + } + + + /* No Overhang in case of short speech bursts, */ + /* generate SID frames with repeated comfort noise parameters */ + /* ---------------------------------------------------------- */ + + if ((cn_st->swShortBurst == 1) && (st->swVadFrmCnt < OVERHANG)) + { + + /* generate a SID frame with repeated parameters */ + /* --------------------------------------------- */ + + swSP = 0; + + + /* repeat data: r0, LPC, GS */ + /* ------------------------ */ + + st->swCNR0 = cn_st->swQntRefR0; + + for (i = 0; i < 3; i++) + st->pswCNLpc[i] = cn_st->piRefVqCodewds[i]; + + for (i = 0; i < N_SUB; i++) + st->pswCNGsp0Code[i] = cn_st->swRefGsIndex; + + } + + + /* generate SID frames with updated comfort noise parameters */ + /* --------------------------------------------------------- */ + + if (st->swVadFrmCnt >= OVERHANG) + { + + /* A SID frame with updated parameters */ + /* ----------------------------------- */ + + swSP = 0; + st->swNElapsed = 0; + + + /* average R0 and correlation values */ + /* --------------------------------- */ + + avgCNHist(cn_st->pL_R0Hist, cn_st->ppL_CorrHist, &L_RefR0, + pL_RefCorr); + + + /* now quantize the averaged R(0) */ + /* ------------------------------ */ + + cn_st->swQntRefR0 = r0Quant(L_RefR0); + + + /* Quantize the averaged correlation */ + /* --------------------------------- */ + + lpcCorrQntz(pL_RefCorr, + pswFinalRc, + cn_st->piRefVqCodewds); + + + /* update frame data: r0, LPC */ + /* -------------------------- */ + + st->swCNR0 = cn_st->swQntRefR0; + for (i = 0; i < 3; i++) + st->pswCNLpc[i] = cn_st->piRefVqCodewds[i]; + + + /* update subframe data (unvoiced mode): GSP0 */ + /* ------------------------------------------ */ + + for (i = 0; i < N_SUB; i++) + st->pswCNGsp0Code[i] = cn_st->swRefGsIndex; + + } + + + /* random codevectors */ + /* ------------------ */ + + if (swSP == 0) + { + for (i = 0; i < N_SUB; i++) + { + st->pswCNVSCode1[i] = getPnBits(7, &cn_st->L_TxPNSeed); + st->pswCNVSCode2[i] = getPnBits(7, &cn_st->L_TxPNSeed); + } + } + + + } + + return (swSP); +} + + +/************************************************************************* + * + * FUNCTION NAME: updateCNHist + * + * PURPOSE: + * + * Add current frame's unquantized R(0) and LPC information to the + * comfort noise history, so that it will be available for + * averaging. + * + * INPUTS: + * + * Unquantized values from the coder: + * + * + * L_UnqntzdR0 - unquantized frame energy R(0), an output of FLAT + * + * pL_UnqntzdCorr[NP+1] - unquantized correlation coefficient + * array. Also an output of FLAT. + * + * siUpdPointer (global) - A modulo counter which counts up from + * 0 to OVERHANG-1. + * + * OUTPUTS: + * + * pL_R0History[OVERHANG] - history of the OVERHANG frames worth of + * R(0). + * + * ppL_CorrHistory[OVERHANG][NP+1] - - history of the OVERHANG + * frames worth of pL_UnqntzdCorr[]. + * + * RETURN VALUE: + * + * none + * + *************************************************************************/ + +void updateCNHist(struct gsmhr_encoder_state *st, Longword L_UnqntzdR0, + Longword *pL_UnqntzdCorr, Longword pL_R0Hist[], + Longword ppL_CorrHist[OVERHANG][NP + 1]) +{ + +/*_________________________________________________________________________ + | | + | Automatic Variables | + |_________________________________________________________________________| +*/ + + int i; + + +/*_________________________________________________________________________ + | | + | Executable Code | + |_________________________________________________________________________| +*/ + + /* update */ + pL_R0Hist[st->siUpdPointer] = L_UnqntzdR0; + + for (i = 0; i < NP + 1; i++) + ppL_CorrHist[st->siUpdPointer][i] = pL_UnqntzdCorr[i]; + + st->siUpdPointer = (st->siUpdPointer + 1) % OVERHANG; +} + + +/************************************************************************* + * + * FUNCTION NAME: avgCNHist + * + * PURPOSE: + * + * Average the unquantized R0 and LPC data stored at the encoder + * to arrive at an average R0 and LPC frame for use in a SID + * frame. + * + * INPUTS: + * + * pL_R0History[OVERHANG] - contains unquantized R(0) data from the + * most recent OVERHANG frame (including this one). + * + * ppL_CorrHistory[OVERHANG][NP+1] - Unquantized correlation + * coefficients from the most recent OVERHANG frame (including this + * one). The data stored here is an output of FLAT. + * + * OUTPUTS: + * + * *pL_AvgdR0 - the average of pL_R0History[] + * + * pL_AvgdCorrSeq[NP+1] - the average of ppL_CorrHistory[][]. + * + * + * RETURN VALUE: + * + * none + * + *************************************************************************/ + +void avgCNHist(Longword pL_R0History[], + Longword ppL_CorrHistory[OVERHANG][NP + 1], + Longword *pL_AvgdR0, Longword pL_AvgdCorrSeq[]) +{ + +/*_________________________________________________________________________ + | | + | Automatic Variables | + |_________________________________________________________________________| +*/ + + int i, + j; + Longword L_avg; + +/*_________________________________________________________________________ + | | + | Executable Code | + |_________________________________________________________________________| +*/ + + /* R0 Averaging */ + /* ------------ */ + + for (L_avg = 0, i = 0; i < OVERHANG; i++) + L_avg = L_add(L_shr(pL_R0History[i], OH_SHIFT), L_avg); + + *pL_AvgdR0 = L_avg; + + + /* LPC: average the last OVERHANG frames */ + /* ------------------------------------- */ + + for (j = 0; j < NP + 1; j++) + { + for (L_avg = 0, i = 0; i < OVERHANG; i++) + { + L_avg = L_add(L_shift_r(ppL_CorrHistory[i][j], -OH_SHIFT), L_avg); + } + + pL_AvgdCorrSeq[j] = L_avg; + } + +} + + +/*************************************************************************** + * + * FUNCTION NAME: lpcCorrQntz + * + * PURPOSE: Quantize a correlation sequence + * + * + * INPUT: + * + * pL_CorrelSeq[NP+1] + * Correlation sequence to quantize. + * + * OUTPUTS: + * + * pswFinalRc[0:NP-1] + * A quantized set of NP reflection coefficients. + * + * piVQCodewds[0:2] + * An array containing the indices of the 3 reflection + * coefficient vectors selected from the three segment + * Rc-VQ. + * + * RETURN: + * None. + * + * KEYWORDS: AFLAT,aflat,flat,vectorquantization, reflectioncoefficients + * + *************************************************************************/ + +#if 0 +void lpcCorrQntz(Longword pL_CorrelSeq[], + Shortword pswFinalRc[], + int piVQCodewds[]) +{ + +/*_________________________________________________________________________ + | | + | Automatic Variables | + |_________________________________________________________________________| +*/ + + Shortword pswPOldSpace[NP_AFLAT], + pswPNewSpace[NP_AFLAT], + pswVOldSpace[2 * NP_AFLAT - 1], + pswVNewSpace[2 * NP_AFLAT - 1], + *ppswPAddrs[2], + *ppswVAddrs[2], + *pswVBar, + pswPBar[NP_AFLAT], + pswVBarSpace[2 * NP_AFLAT - 1], + pswFlatsRc[NP], /* Unquantized Rc's computed by FLAT */ + pswRc[NP + 1]; /* Temp list for the converted RC's */ + Longword *pL_VBarFull, + pL_PBarFull[NP], + pL_VBarFullSpace[2 * NP - 1]; + + int i, + iVec, + iSeg, + iCnt; /* Loop counter */ + struct QuantList quantList, /* A list of vectors */ + bestPql[4]; /* The four best vectors from + * the PreQ */ + struct QuantList bestQl[LPC_VQ_SEG + 1]; /* Best vectors for each of + * the three segments */ + +/*_________________________________________________________________________ + | | + | Executable Code | + |_________________________________________________________________________| +*/ + + /* Setup pointers temporary space */ + /*--------------------------------*/ + + pswVBar = pswVBarSpace + NP_AFLAT - 1; + pL_VBarFull = pL_VBarFullSpace + NP - 1; + ppswPAddrs[0] = pswPOldSpace; + ppswPAddrs[1] = pswPNewSpace; + ppswVAddrs[0] = pswVOldSpace + NP_AFLAT - 1; + ppswVAddrs[1] = pswVNewSpace + NP_AFLAT - 1; + + + /* Set up pL_PBarFull and pL_VBarFull initial conditions, using the */ + /* autocorrelation sequence derived from the optimal reflection */ + /* coefficients computed by FLAT. The initial conditions are shifted */ + /* right by RSHIFT bits. These initial conditions, stored as */ + /* Longwords, are used to initialize PBar and VBar arrays for the */ + /* next VQ segment. */ + /*--------------------------------------------------------------------*/ + + initPBarFullVBarFullL(pL_CorrelSeq, pL_PBarFull, pL_VBarFull); + + /* Set up initial PBar and VBar initial conditions, using pL_PBarFull */ + /* and pL_VBarFull arrays initialized above. These are the initial */ + /* PBar and VBar conditions to be used by the AFLAT recursion at the */ + /* 1-st Rc-VQ segment. */ + /*--------------------------------------------------------------------*/ + + initPBarVBarL(pL_PBarFull, pswPBar, pswVBar); + + for (iSeg = 1; iSeg <= LPC_VQ_SEG; iSeg++) + { + /* initialize candidate list */ + /*---------------------------*/ + + quantList.iNum = psrPreQSz[iSeg - 1]; + quantList.iRCIndex = 0; + + /* do aflat for all vectors in the list */ + /*--------------------------------------*/ + + setupPreQ(iSeg, quantList.iRCIndex); /* set up vector ptrs */ + + for (iCnt = 0; iCnt < quantList.iNum; iCnt++) + { + /* get a vector */ + /*--------------*/ + + getNextVec(pswRc); + + /* clear the limiter flag */ + /*------------------------*/ + + iLimit = 0; + + /* find the error values for each vector */ + /*---------------------------------------*/ + + quantList.pswPredErr[iCnt] = + aflatRecursion(&pswRc[psvqIndex[iSeg - 1].l], + pswPBar, pswVBar, + ppswPAddrs, ppswVAddrs, + psvqIndex[iSeg - 1].len); + + /* check the limiter flag */ + /*------------------------*/ + + if (iLimit) + quantList.pswPredErr[iCnt] = 0x7fff; /* set error to bad value */ + + } /* done list loop */ + + /* find 4 best prequantizer levels */ + /*---------------------------------*/ + + findBestInQuantList(quantList, 4, bestPql); + + for (iVec = 0; iVec < 4; iVec++) + { + + /* initialize quantizer list */ + /*---------------------------*/ + + quantList.iNum = psrQuantSz[iSeg - 1]; + quantList.iRCIndex = bestPql[iVec].iRCIndex * psrQuantSz[iSeg - 1]; + + setupQuant(iSeg, quantList.iRCIndex); /* set up vector ptrs */ + + /* do aflat recursion on each element of list */ + /*--------------------------------------------*/ + + for (iCnt = 0; iCnt < quantList.iNum; iCnt++) + { + /* get a vector */ + /*--------------*/ + + getNextVec(pswRc); + + /* clear the limiter flag */ + /*------------------------*/ + + iLimit = 0; + + /* find the error values for each vector */ + /*---------------------------------------*/ + + quantList.pswPredErr[iCnt] = + aflatRecursion(&pswRc[psvqIndex[iSeg - 1].l], + pswPBar, pswVBar, + ppswPAddrs, ppswVAddrs, + psvqIndex[iSeg - 1].len); + + /* check the limiter flag */ + /*------------------------*/ + + if (iLimit) + quantList.pswPredErr[iCnt] = 0x7fff; /* set error to the worst + * value */ + + } /* done list loop */ + + /* find best quantizer vector for this segment, and save it */ + /*----------------------------------------------------------*/ + + findBestInQuantList(quantList, 1, bestQl); + if (iVec == 0) + bestQl[iSeg] = bestQl[0]; + else if (sub(bestQl[iSeg].pswPredErr[0], bestQl[0].pswPredErr[0]) > 0) + bestQl[iSeg] = bestQl[0]; + + } + + /* find the quantized reflection coefficients */ + /*--------------------------------------------*/ + + setupQuant(iSeg, bestQl[iSeg].iRCIndex); /* set up vector ptrs */ + getNextVec((Shortword *) (pswFinalRc - 1)); + + + /* Update pBarFull and vBarFull for the next Rc-VQ segment, and */ + /* update the pswPBar and pswVBar for the next Rc-VQ segment */ + /*--------------------------------------------------------------*/ + + if (iSeg < LPC_VQ_SEG) + aflatNewBarRecursionL(&pswFinalRc[psvqIndex[iSeg - 1].l - 1], iSeg, + pL_PBarFull, pL_VBarFull, pswPBar, pswVBar); + + } + + /* find the quantizer index (the values to be output in the symbol file) */ + /*-----------------------------------------------------------------*/ + + for (iSeg = 1; iSeg <= LPC_VQ_SEG; iSeg++) + piVQCodewds[iSeg - 1] = bestQl[iSeg].iRCIndex; + +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgsmhr1/dtx_enc.h Thu Mar 05 07:53:49 2026 +0000 @@ -0,0 +1,28 @@ +#ifndef __DTX_ENC +#define __DTX_ENC + +#include "typedefs.h" +#include "tw_gsmhr.h" + +/*________________________________________________________________________ + | | + | Function Prototypes | + |________________________________________________________________________| +*/ + +void avgCNHist(Longword pL_R0History[], + Longword ppL_CorrHistory[OVERHANG][NP + 1], + Longword *pL_AvgdR0, Longword pL_AvgdCorrSeq[]); + +Shortword swComfortNoise(struct gsmhr_encoder_state *st, Shortword swVadFlag, + Longword L_UnqntzdR0, Longword *pL_UnqntzdCorr); + +void updateCNHist(struct gsmhr_encoder_state *st, Longword L_UnqntzdR0, + Longword *pL_UnqntzdCorr, Longword pL_R0Hist[], + Longword ppL_CorrHist[OVERHANG][NP + 1]); + +void lpcCorrQntz(Longword pL_CorrelSeq[], + Shortword pswFinalRc[], + int piVQCodewds[]); + +#endif
