FreeCalypso > hg > gsmhr-codec-ref
diff sp_enc.c @ 0:9008dbc8ca74
import original C code from GSM 06.06
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 14 Jun 2024 23:27:16 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sp_enc.c Fri Jun 14 23:27:16 2024 +0000 @@ -0,0 +1,406 @@ +/*************************************************************************** + * + * File Name: sp_enc.c + * + * Purpose: Contains speech encoder function. Calls are made to the + * frame-based encoding functions (see sp_frm.c), and the subframe- + * based encoding function (see sp_sfrm.c) + * + * Functions in this file (only 1) + * speechEncoder() + * + **************************************************************************/ +/*_________________________________________________________________________ + | | + | Include Files | + |_________________________________________________________________________| +*/ + +#include "mathhalf.h" +#include "mathdp31.h" +#include "sp_rom.h" +#include "sp_dec.h" +#include "sp_frm.h" +#include "sp_sfrm.h" +#include "sp_enc.h" +#include "host.h" +#include "vad.h" + +/*_________________________________________________________________________ + | | + | Local Defines | + |_________________________________________________________________________| +*/ + +#define CG_INT_MACS 6 /* Number of Multiply-Accumulates in */ + /* one interpolation */ +#define ASCALE 0x0800 +#define LMAX 142 /* largest lag (integer sense) */ +#define LSMAX (LMAX+ CG_INT_MACS/2) /* Lag Search Array Length */ +#define NUM_CLOSED 3 /* Maximum number of lags searched */ + /* in closed loop. */ + +#define LPCSTARTINDEX 25 /* Where the LPC analysis window + * starts */ +#define INBUFFSZ LPCSTARTINDEX + A_LEN /* Input buffer size */ +#define NUMSTARTUPSMP INBUFFSZ - F_LEN /* Number of samples needed */ + /* at start up */ +#define NUMSTARTUPSMP_P1 INBUFFSZ - F_LEN + 1 +#define HPFSHIFT 1 /* no right shifts high pass shifts + * speech */ + +/*_________________________________________________________________________ + | | + | State variables (globals) | + |_________________________________________________________________________| +*/ + +Shortword swOldR0; +Shortword swOldR0Index; + +struct NormSw psnsWSfrmEngSpace[2 * N_SUB]; + +Shortword pswHPFXState[4]; +Shortword pswHPFYState[8]; +Shortword pswOldFrmKs[NP]; +Shortword pswOldFrmAs[NP]; +Shortword pswOldFrmSNWCoefs[NP]; +Shortword pswWgtSpeechSpace[F_LEN + LMAX + CG_INT_MACS / 2]; + +Shortword pswSpeech[INBUFFSZ]; /* input speech */ + +Shortword swPtch = 1; + +/*_________________________________________________________________________ + | | + | Global DTX variables | + |_________________________________________________________________________| +*/ + +Shortword swTxGsHistPtr = 0; + +Shortword pswCNVSCode1[N_SUB], + pswCNVSCode2[N_SUB], + pswCNGsp0Code[N_SUB], + pswCNLpc[3], + swCNR0; + + +extern Longword pL_GsHist[]; +extern LongwordRom ppLr_gsTable[4][32]; + +/*************************************************************************** + * + * FUNCTION NAME: speechEncoder + * + * PURPOSE: + * + * Performs GSM half-rate speech encoding on frame basis (160 samples). + * + * INPUTS: + * + * pswSpeechIn[0:159] - input speech samples, 160 new samples per frame + * + * OUTPUTS: + * + * pswFrmCodes[0:19] - output parameters, 18 speech parameters plus + * VAD and SP flags + * + * RETURN VALUE: + * + * None + * + * IMPLEMENTATION: + * + * n/a + * + * REFERENCES: Sub-clause 4.1 of GSM Recomendation 06.20 + * + * KEYWORDS: speechcoder, analysis + * + *************************************************************************/ + +void speechEncoder(Shortword pswSpeechIn[], Shortword pswFrmCodes[]) +{ + +/*_________________________________________________________________________ + | | + | Static Variables | + |_________________________________________________________________________| +*/ + + /* 1st point in analysis window */ + static Shortword *pswLpcStart = &pswSpeech[LPCSTARTINDEX]; + + /* 1st point of new frame other than 1st */ + static Shortword *pswNewSpeech = &pswSpeech[NUMSTARTUPSMP]; + + /* sample 0 of weighted speech */ + static Shortword *pswWgtSpeech = &pswWgtSpeechSpace[LSMAX]; + + static struct NormSw *psnsWSfrmEng = &psnsWSfrmEngSpace[N_SUB]; + +/*_________________________________________________________________________ + | | + | Automatic Variables | + |_________________________________________________________________________| +*/ + + int iVoicing, /* bitAlloc */ + iR0, /* bitAlloc and aflat */ + piVq[3], /* bitAlloc */ + iSi, /* bitAlloc */ + piLagCode[N_SUB], /* bitAlloc */ + piVSCode1[N_SUB], /* bitAlloc */ + piVSCode2[N_SUB], /* bitAlloc */ + piGsp0Code[N_SUB]; /* bitAlloc */ + + short int siUVCode, + siSi, + i, + j; + + Shortword swR0, + pswLagCode[N_SUB], + pswVSCode1[N_SUB], + pswVSCode2[N_SUB], + pswGsp0Code[N_SUB], + *pswLagListPtr, + pswFrmKs[NP], + pswFrmAs[NP], + pswFrmSNWCoefs[NP], + pswLagList[N_SUB * NUM_CLOSED], + pswNumLagList[N_SUB], + pswPitchBuf[N_SUB], + pswHNWCoefBuf[N_SUB], + ppswSNWCoefAs[N_SUB][NP], + ppswSynthAs[N_SUB][NP]; + + Shortword swSP, + pswVadLags[4], /* VAD Parameters */ + swVadFlag; /* flag indicating voice activity + * detector state. 1 = speech or + * speech/signal present */ + struct NormSw + psnsSqrtRs[N_SUB]; + +/*_________________________________________________________________________ + | | + | Executable Code | + |_________________________________________________________________________| +*/ + + /* Speech frame processing */ + /* High pass filter the speech */ + /* ---------------------------- */ + + filt4_2nd(psrHPFCoefs, pswSpeechIn, + pswHPFXState, pswHPFYState, F_LEN, HPFSHIFT); + + /* copy high passed filtered speech into encoder's speech buff */ + /*-------------------------------------------------------------*/ + + for (i = 0; i < F_LEN; i++) + pswNewSpeech[i] = pswSpeechIn[i]; + + + + + /* Calculate and quantize LPC coefficients */ + /* --------------------------------------- */ + + aflat(pswLpcStart, &iR0, pswFrmKs, piVq, + swPtch, &swVadFlag, &swSP); + + + /* Lookup frame energy r0 */ + /* ---------------------- */ + + swR0 = psrR0DecTbl[iR0 * 2]; /* lookupR0 */ + + /* Generate the direct form coefs */ + /* ------------------------------ */ + + if (!rcToADp(ASCALE, pswFrmKs, pswFrmAs)) + { + + getNWCoefs(pswFrmAs, pswFrmSNWCoefs); + } + else + { + + for (i = 0; i < NP; i++) + { + pswFrmKs[i] = pswOldFrmKs[i]; + pswFrmAs[i] = pswOldFrmAs[i]; + pswFrmSNWCoefs[i] = pswOldFrmSNWCoefs[i]; + } + } + + /* Interpolate, or otherwise get sfrm reflection coefs */ + /* --------------------------------------------------- */ + + getSfrmLpcTx(swOldR0, swR0, + pswOldFrmKs, pswOldFrmAs, + pswOldFrmSNWCoefs, + pswFrmKs, pswFrmAs, + pswFrmSNWCoefs, + pswSpeech, + &siSi, + psnsSqrtRs, + ppswSynthAs, ppswSNWCoefAs); + + /* loose once bitAlloc done */ + iSi = siSi; + + /* Weight the entire speech frame */ + /* ------------------------------ */ + + weightSpeechFrame(pswSpeech, ppswSynthAs[0], ppswSNWCoefAs[0], + pswWgtSpeechSpace); + + /* Perform open-loop lag search, get harmonic-noise-weighting parameters */ + /* --------------------------------------------------------------------- */ + + openLoopLagSearch(&pswWgtSpeechSpace[LSMAX], + swOldR0Index, + (Shortword) iR0, + &siUVCode, + pswLagList, + pswNumLagList, + pswPitchBuf, + pswHNWCoefBuf, + &psnsWSfrmEng[0], + pswVadLags, + swSP); + + iVoicing = siUVCode; + + + /* Using open loop LTP data to calculate swPtch */ /* DTX mode */ + /* parameter */ /* DTX mode */ + /* -------------------------------------------- */ /* DTX mode */ + + periodicity_update(pswVadLags, &swPtch); /* DTX mode */ + + + /* Subframe processing loop */ + /* ------------------------ */ + + pswLagListPtr = pswLagList; + + for (giSfrmCnt = 0; giSfrmCnt < N_SUB; giSfrmCnt++) + { + + if (swSP == 0) /* DTX mode */ + { /* DTX mode */ + pswVSCode1[giSfrmCnt] = pswCNVSCode1[giSfrmCnt]; /* DTX mode */ + pswVSCode2[giSfrmCnt] = pswCNVSCode2[giSfrmCnt]; /* DTX mode */ + pswGsp0Code[giSfrmCnt] = pswCNGsp0Code[giSfrmCnt]; /* DTX mode */ + } /* DTX mode */ + + sfrmAnalysis(&pswWgtSpeech[giSfrmCnt * S_LEN], + siUVCode, + psnsSqrtRs[giSfrmCnt], + ppswSNWCoefAs[giSfrmCnt], + pswLagListPtr, + pswNumLagList[giSfrmCnt], + pswPitchBuf[giSfrmCnt], + pswHNWCoefBuf[giSfrmCnt], + &pswLagCode[giSfrmCnt], &pswVSCode1[giSfrmCnt], + &pswVSCode2[giSfrmCnt], &pswGsp0Code[giSfrmCnt], + swSP); + + pswLagListPtr = &pswLagListPtr[pswNumLagList[giSfrmCnt]]; + + } + + + /* copy comfort noise parameters, */ /* DTX mode */ + /* update GS history */ /* DTX mode */ + /* ------------------------------ */ /* DTX mode */ + + if (swSP == 0) /* DTX mode */ + { /* DTX mode */ + + /* copy comfort noise frame parameter */ /* DTX mode */ + /* ---------------------------------- */ /* DTX mode */ + + iR0 = swCNR0; /* quantized R0 index */ /* DTX mode */ + for (i=0; i < 3; i++) /* DTX mode */ + piVq[i] = pswCNLpc[i]; /* DTX mode */ + + } /* DTX mode */ + else /* DTX mode */ + { /* DTX mode */ + + /* if swSP != 0, then update the GS history */ /* DTX mode */ + /* -----------------------------------------*/ /* DTX mode */ + + for (i=0; i < N_SUB; i++){ /* DTX mode */ + pL_GsHist[swTxGsHistPtr] = /* DTX mode */ + ppLr_gsTable[siUVCode][pswGsp0Code[i]]; /* DTX mode */ + swTxGsHistPtr++; /* DTX mode */ + if (swTxGsHistPtr > ((OVERHANG-1)*N_SUB)-1) /* DTX mode */ + swTxGsHistPtr=0; /* DTX mode */ + } /* DTX mode */ + + } /* DTX mode */ + + + /* End of frame processing, update frame based parameters */ + /* ------------------------------------------------------ */ + + for (i = 0; i < N_SUB; i++) + { + piLagCode[i] = pswLagCode[i]; + piVSCode1[i] = pswVSCode1[i]; + piVSCode2[i] = pswVSCode2[i]; + piGsp0Code[i] = pswGsp0Code[i]; + } + + swOldR0Index = (Shortword) iR0; + swOldR0 = swR0; + + for (i = 0; i < NP; i++) + { + pswOldFrmKs[i] = pswFrmKs[i]; + pswOldFrmAs[i] = pswFrmAs[i]; + pswOldFrmSNWCoefs[i] = pswFrmSNWCoefs[i]; + } + + /* Insert SID Codeword */ /* DTX mode */ + /* ------------------- */ /* DTX mode */ + + if (swSP == 0) /* DTX mode */ + { /* DTX mode */ + iVoicing = 0x0003; /* 2 bits */ /* DTX mode */ + iSi = 0x0001; /* 1 bit */ /* DTX mode */ + for (i=0; i < N_SUB; i++) /* DTX mode */ + { /* DTX mode */ + piVSCode1[i] = 0x01ff; /* 9 bits */ /* DTX mode */ + piGsp0Code[i] = 0x001f; /* 5 bits */ /* DTX mode */ + } + piLagCode[0] = 0x00ff; /* 8 bits */ /* DTX mode */ + piLagCode[1] = 0x000f; /* 4 bits */ /* DTX mode */ + piLagCode[2] = 0x000f; /* 4 bits */ /* DTX mode */ + piLagCode[3] = 0x000f; /* 4 bits */ /* DTX mode */ + } /* DTX mode */ + + + /* Generate encoded parameter array */ + /* -------------------------------- */ + + fillBitAlloc(iVoicing, iR0, piVq, iSi, piLagCode, + piVSCode1, piVSCode2, + piGsp0Code, swVadFlag, swSP, pswFrmCodes); + + + /* delay the input speech by 1 frame */ + /*-----------------------------------*/ + + for (i = 0, j = F_LEN; j < INBUFFSZ; i++, j++) + { + pswSpeech[i] = pswSpeech[j]; + } +}