📄 sp_dec.c
字号:
* REFERENCES: Sub_Clause 4.2.2 and 4.2.4 of GSM Recomendation 06.20
*
* KEYWORDS: postfilter, agc, automaticgaincontrol, leveladjust
*
*************************************************************************/
static Shortword agcGain(Shortword pswStateCurr[],
struct NormSw snsInSigEnergy, Shortword swEngyRShft)
{
/*_________________________________________________________________________
| |
| Automatic Variables |
|_________________________________________________________________________|
*/
Longword L_OutEnergy,
L_AgcGain;
struct NormSw snsOutEnergy,
snsAgc;
Shortword swAgcOut,
swAgcShftCnt;
/*_________________________________________________________________________
| |
| Executable Code |
|_________________________________________________________________________|
*/
/* Calculate the energy in the output vector divided by 2 */
/*--------------------------------------------------------*/
snsOutEnergy.sh = g_corr1s(pswStateCurr, swEngyRShft, &L_OutEnergy);
/* reduce energy by a factor of 2 */
snsOutEnergy.sh = add(snsOutEnergy.sh, 1);
/* if waveform has nonzero energy, find AGC gain */
/*-----------------------------------------------*/
if (L_OutEnergy == 0)
{
swAgcOut = 0;
}
else
{
snsOutEnergy.man = round(L_OutEnergy);
/* divide input energy by 2 */
snsInSigEnergy.man = shr(snsInSigEnergy.man, 1);
/* Calculate AGC gain squared */
/*----------------------------*/
snsAgc.man = divide_s(snsInSigEnergy.man, snsOutEnergy.man);
swAgcShftCnt = norm_s(snsAgc.man);
snsAgc.man = shl(snsAgc.man, swAgcShftCnt);
/* find shift count for G^2 */
/*--------------------------*/
snsAgc.sh = add(sub(snsInSigEnergy.sh, snsOutEnergy.sh),
swAgcShftCnt);
L_AgcGain = L_deposit_h(snsAgc.man);
/* Calculate AGC gain */
/*--------------------*/
snsAgc.man = sqroot(L_AgcGain);
/* check if 1/2 sqrt(G^2) >= 1.0 */
/* This is equivalent to checking if shiftCnt/2+1 < 0 */
/*----------------------------------------------------*/
if (add(snsAgc.sh, 2) < 0)
{
swAgcOut = SW_MAX;
}
else
{
if (0x1 & snsAgc.sh)
{
snsAgc.man = mult(snsAgc.man, SQRT_ONEHALF);
}
snsAgc.sh = shr(snsAgc.sh, 1); /* shiftCnt/2 */
snsAgc.sh = add(snsAgc.sh, 1); /* shiftCnt/2 + 1 */
if (snsAgc.sh > 0)
{
snsAgc.man = shr(snsAgc.man, snsAgc.sh);
}
swAgcOut = snsAgc.man;
}
}
return (swAgcOut);
}
/***************************************************************************
*
* FUNCTION NAME: b_con
*
* PURPOSE:
* Expands codeword into an one dimensional array. The 0/1 input is
* changed to an element with magnitude +/- 0.5.
*
* input output
*
* 0 -0.5
* 1 +0.5
*
* INPUT:
*
* swCodeWord
* Input codeword, information in the LSB's
*
* siNumBits
* number of bits in the input codeword and number
* of elements in output vector
*
* pswVectOut[0:siNumBits]
*
* pointer to bit array
*
* OUTPUT:
*
* pswVectOut[0:siNumBits]
*
* signed bit array
*
* RETURN:
*
* none
*
* REFERENCES: Sub_Clause 4.1.10 and 4.2.1 of GSM Recomendation 06.20
*
* KEYWORDS: b_con, codeword, expansion
*
*************************************************************************/
void b_con(Shortword swCodeWord, short siNumBits,
Shortword pswVectOut[])
{
/*_________________________________________________________________________
| |
| Automatic Variables |
|_________________________________________________________________________|
*/
short int siLoopCnt;
/*_________________________________________________________________________
| |
| Executable Code |
|_________________________________________________________________________|
*/
for (siLoopCnt = 0; siLoopCnt < siNumBits; siLoopCnt++)
{
if (swCodeWord & 1) /* temp accumulator get 0.5 */
pswVectOut[siLoopCnt] = (Shortword) 0x4000;
else /* temp accumulator gets -0.5 */
pswVectOut[siLoopCnt] = (Shortword) 0xc000;
swCodeWord = shr(swCodeWord, 1);
}
}
/***************************************************************************
*
* FUNCTION NAME: fp_ex
*
* PURPOSE:
*
* Looks up a vector in the adaptive excitation codebook (long-term
* predictor).
*
* INPUTS:
*
* swOrigLagIn
*
* Extended resolution lag (lag * oversampling factor)
*
* pswLTPState[-147:39]
*
* Adaptive codebook (with space at end for looked up
* vector). Indicies [-147:-1] are the history, [0:39]
* are for the looked up vector.
*
* psrPitchIntrpFirBase[0:59]
* ppsrPVecIntFilt[0:9][0:5] ([tap][phase])
*
* Interpolating FIR filter coefficients.
*
* OUTPUTS:
*
* pswLTPState[0:39]
*
* Array containing the contructed output vector
*
* RETURN VALUE:
* none
*
* DESCRIPTION:
*
* The adaptive codebook consists of the history of the excitation.
* The vector is looked up by going back into this history
* by the amount of the input lag. If the input lag is fractional,
* then the samples to be looked up are interpolated from the existing
* samples in the history.
*
* If the lag is less than the length of the vector to be generated
* (i.e. less than the subframe length), then the lag is doubled
* after the first n samples have been looked up (n = input lag).
* In this way, the samples being generated are not part of the
* codebook. This is described in section 4.1.8.
*
* REFERENCES: Sub_Clause 4.1.8.5 and 4.2.1 of GSM Recomendation 06.20
*
* Keywords: pitch, excitation vector, long term filter, history,
* Keywords: fractional lag, get_ipjj
*
*************************************************************************/
void fp_ex(Shortword swOrigLagIn,
Shortword pswLTPState[])
{
/*_________________________________________________________________________
| |
| Automatic Variables |
|_________________________________________________________________________|
*/
Longword L_Temp;
Shortword swIntLag,
swRemain,
swRunningLag;
short int siSampsSoFar,
siSampsThisPass,
i,
j;
/*_________________________________________________________________________
| |
| Executable Code |
|_________________________________________________________________________|
*/
/* Loop: execute until all samples in the vector have been looked up */
/*-------------------------------------------------------------------*/
swRunningLag = swOrigLagIn;
siSampsSoFar = 0;
while (siSampsSoFar < S_LEN)
{
/* Get integer lag and remainder. These are used in addressing */
/* the LTP state and the interpolating filter, respectively */
/*--------------------------------------------------------------*/
get_ipjj(swRunningLag, &swIntLag, &swRemain);
/* Get the number of samples to look up in this pass */
/*---------------------------------------------------*/
if (sub(swIntLag, S_LEN) < 0)
siSampsThisPass = swIntLag - siSampsSoFar;
else
siSampsThisPass = S_LEN - siSampsSoFar;
/* Look up samples by interpolating (fractional lag), or copying */
/* (integer lag). */
/*---------------------------------------------------------------*/
if (swRemain == 0)
{
/* Integer lag: copy samples from history */
/*----------------------------------------*/
for (i = siSampsSoFar; i < siSampsSoFar + siSampsThisPass; i++)
pswLTPState[i] = pswLTPState[i - swIntLag];
}
else
{
/* Fractional lag: interpolate to get samples */
/*--------------------------------------------*/
for (i = siSampsSoFar; i < siSampsSoFar + siSampsThisPass; i++)
{
/* first tap with rounding offset */
/*--------------------------------*/
L_Temp = L_mac((long) 32768,
pswLTPState[i - swIntLag - P_INT_MACS / 2],
ppsrPVecIntFilt[0][swRemain]);
for (j = 1; j < P_INT_MACS - 1; j++)
{
L_Temp = L_mac(L_Temp,
pswLTPState[i - swIntLag - P_INT_MACS / 2 + j],
ppsrPVecIntFilt[j][swRemain]);
}
pswLTPState[i] = extract_h(L_mac(L_Temp,
pswLTPState[i - swIntLag + P_INT_MACS / 2 - 1],
ppsrPVecIntFilt[P_INT_MACS - 1][swRemain]));
}
}
/* Done with this pass: update loop controls */
/*-------------------------------------------*/
siSampsSoFar += siSampsThisPass;
swRunningLag = add(swRunningLag, swOrigLagIn);
}
}
/***************************************************************************
*
* FUNCTION NAME: g_corr1 (no scaling)
*
* PURPOSE:
*
* Calculates energy in subframe vector. Differs from g_corr1s,
* in that there the estimate of the maximum possible
* energy is < 1.0
*
*
* INPUT:
*
* pswIn[0:39]
* A subframe vector.
*
*
* OUTPUT:
*
* *pL_out
* A Longword containing the normalized energy
* in the input vector.
*
* RETURN:
*
* swOut
* Number of right shifts which the accumulator was
* shifted to normalize it. Negative number implies
* a left shift, and therefore an energy larger than
* 1.0.
*
* REFERENCES: Sub_Clause 4.1.10.2 and 4.2.1 of GSM Recomendation 06.20
*
* KEYWORDS: energy, autocorrelation, correlation, g_corr1
*
*
*************************************************************************/
Shortword g_corr1(Shortword *pswIn, Longword *pL_out)
{
/*_________________________________________________________________________
| |
| Automatic Variables |
|_________________________________________________________________________|
*/
Longword L_sum;
Shortword swEngyLShft;
int i;
/*_________________________________________________________________________
| |
| Executable Code |
|_________________________________________________________________________|
*/
/* Calculate energy in subframe vector (40 samples) */
/*--------------------------------------------------*/
L_sum = L_mult(pswIn[0], pswIn[0]);
for (i = 1; i < S_LEN; i++)
{
L_sum = L_mac(L_sum, pswIn[i], pswIn[i]);
}
if (L_sum != 0)
{
/* Normalize the energy in the output Longword */
/*---------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -