FreeCalypso > hg > gsm-codec-lib
view libgsmhr1/dtx_enc.c @ 622:3ae5508f9a54 default tip
libgsmhr1/sp_sfrm.c: constify "ROM" static data
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Thu, 05 Mar 2026 21:56:18 +0000 |
| parents | e6e9d5104503 |
| children |
line wrap: on
line source
/*************************************************************************** * * 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" #include "sp_frm.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(st, 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 * *************************************************************************/ void lpcCorrQntz(struct gsmhr_encoder_state *st, 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(st, iSeg, quantList.iRCIndex); /* set up vector ptrs */ for (iCnt = 0; iCnt < quantList.iNum; iCnt++) { /* get a vector */ /*--------------*/ getNextVec(st, pswRc); /* clear the limiter flag */ /*------------------------*/ st->iLimit = 0; /* find the error values for each vector */ /*---------------------------------------*/ quantList.pswPredErr[iCnt] = aflatRecursion(st, &pswRc[psvqIndex[iSeg - 1].l], pswPBar, pswVBar, ppswPAddrs, ppswVAddrs, psvqIndex[iSeg - 1].len); /* check the limiter flag */ /*------------------------*/ if (st->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(st, 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(st, pswRc); /* clear the limiter flag */ /*------------------------*/ st->iLimit = 0; /* find the error values for each vector */ /*---------------------------------------*/ quantList.pswPredErr[iCnt] = aflatRecursion(st, &pswRc[psvqIndex[iSeg - 1].l], pswPBar, pswVBar, ppswPAddrs, ppswVAddrs, psvqIndex[iSeg - 1].len); /* check the limiter flag */ /*------------------------*/ if (st->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(st, iSeg, bestQl[iSeg].iRCIndex); /* set up vector ptrs */ getNextVec(st, (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; }
