📄 sp_sfrm.c
字号:
/***************************************************************************
*
* File Name: sp_sfrm.c
*
* Purpose: Contains all functions for subframe based processing in the
* speech encoder. Subframe based processing determines the synthetic
* LPC excitation signal, which is composed of the adaptive codebook
* (long-term predictor) vector (in voiced modes), the vector-sum
* codebook vector (two of these in unvoiced mode), and the vector-
* quantized gains applied to these vectors.
*
* Below is a listing of all the functions appearing in the file.
* The functions are arranged according to their purpose. Under
* each heading, the ordering is hierarchical.
*
* sfrmAnalysis
* decorr
* closedLoopLagSearch
* hnwFilt
* g_quant_vl
* g_corr2
* gainTweak
* v_srch
*
*
***************************************************************************/
/*_________________________________________________________________________
| |
| Include Files |
|_________________________________________________________________________|
*/
#include <stdio.h>
#include "mathhalf.h"
#include "sp_rom.h"
#include "sp_dec.h"
#include "sp_frm.h"
#include "sp_sfrm.h"
/*_________________________________________________________________________
| |
| Local Defines |
|_________________________________________________________________________|
*/
#define CG_INT_MACS 6
#define C_BITS_UV 7
#define C_BITS_UV_1 C_BITS_UV-1
#define C_BITS_V 9
#define C_BITS_V_1 C_BITS_V-1
#define DELTA_LEVELS 16
#define GSP0_NUM 32
#define GSP0_VECTOR_SIZE 5
#define GTWEAKMAX 0x5A82 /* sqrt(2)/2 */
#define LMAX 142
#define LSMAX (LMAX + CG_INT_MACS/2)
#define HNW_BUFF_LEN LSMAX
#define LSP_MASK 0xffff
#define LTP_LEN 147 /* maximum ltp lag */
#define MAX_CANDIDATE 6 /* maximum number of lag candidates */
/*_________________________________________________________________________
| |
| State variables (globals) |
|_________________________________________________________________________|
*/
Shortword pswLtpStateBase[LTP_LEN + S_LEN];
Shortword pswHState[NP];
Shortword pswHNWState[HNW_BUFF_LEN];
/***************************************************************************
*
* FUNCTION NAME: closedLoopLagSearch
*
* PURPOSE:
*
* Performs the closed loop search of a list of candidate lags to
* determine the best fractional lag.
*
* INPUTS:
*
* pswLagList[0:iNumLags] - list of candidate lags
* iNumLags - number of candidate lags in LagList
* pswLtpState[0:5] - array of past excitations (LTP state)
* pswHCoefs[0:9] - coefficient array of spectral weighting filter
* pswPVect[0:39] - speech sub frame data
*
* OUTPUTS:
*
* pswLag - pointer to put best lag from list of candidates
* *pswLtpShift - Number of shifts applied to weighted LTP vector.
*
* RETURN VALUE:
*
* siLagCode - code corresponding to the best lag
*
* IMPLEMENTATION:
*
* Generate excitation vectors for all candidate lags. Find the candidate
* lag that maximizes C**2/G using the calculated excitation.
*
* DESCRIPTION:
*
* The function closedLoopLagSearch() searches a very small subset of the
* available LTP lags. The lags to be searched are defined by the open
* loop lag search. This information is passed in as a list of
* oversampled lag values. These values are translated into LTP
* vectors extracted from the LTP history.
*
* GSM document 06.20's b sub L prime variable is called
* ppswTVect[L][n] in the C code. The document's variable p(n) is
* named pswPVect[] in the C code.
*
* The function performs a simple maximization of the cross correlation
* of the weighted LTP vector and the weighted speech vector divided
* by the autocorrelation of the weighted LTP vector. The function is
* encumbered slightly by the necessity of scaling.
*
* REFERENCE: Sub-clause 4.1.8.5 of GSM Recommendation 06.20
*
* KEYWORDS: closed loop, LTP lag search, adaptive codebook search
*
**************************************************************************/
int closedLoopLagSearch(Shortword pswLagList[], int iNumLags,
Shortword pswLtpState[], Shortword pswHCoefs[],
Shortword pswPVect[],
Shortword *pswLag, Shortword *pswLtpShift)
{
/*_________________________________________________________________________
| |
| Automatic Variables |
|_________________________________________________________________________|
*/
Longword L_Energy,
L_ccNorm,
L_cgNorm,
L_CrossCorr;
Longword pL_CCBuf[MAX_CANDIDATE],
pL_CGBuf[MAX_CANDIDATE];
Shortword swCCMax,
swCCShiftCnt,
swCGShiftCnt,
swGMax,
swLTPEnergy,
swSampleA,
pswCCBuf[MAX_CANDIDATE],
pswCGBuf[MAX_CANDIDATE],
ppswTVect[N_SUB][S_LEN];
Shortword i,
j,
siLagOffset,
siLagCode;
/*_________________________________________________________________________
| |
| Executable Code |
|_________________________________________________________________________|
*/
*pswLtpShift = 0; /* Energy in weighted ltp vector =
* [0..0x7ff] */
for (i = 0; i < iNumLags; i++)
{
/* Construct the excitation vector for lag i */
/* ----------------------------------------- */
fp_ex(pswLagList[i], &pswLtpState[LTP_LEN]);
/* Perform all pole filtering */
/* -------------------------- */
lpcZsIir(&pswLtpState[LTP_LEN], pswHCoefs, ppswTVect[i]);
}
/* scale the pitch vector s.t. its energy is strictly */
/* less than 1.0 */
/*----------------------------------------------------*/
swSampleA = shr(ppswTVect[0][0], 2);
L_Energy = L_mac(0x001dff4cL, swSampleA, swSampleA);
for (j = 1; j < S_LEN; j++)
{
swSampleA = shr(ppswTVect[0][j], 2);
L_Energy = L_mac(L_Energy, swSampleA, swSampleA);
}
/* add in the energy of the first sample of the subsequent lags */
/*--------------------------------------------------------------*/
for (i = 1; i < iNumLags; i++)
{
swSampleA = shr(ppswTVect[i][0], 2);
L_Energy = L_mac(L_Energy, swSampleA, swSampleA);
}
/* An upper bound on the weighted pitch vectors energy */
/*-----------------------------------------------------*/
swLTPEnergy = round(L_Energy);
if (sub(swLTPEnergy, 0x07ff) > 0)
{ /* E = (0x7ff.. 0x7fff] */
if (sub(swLTPEnergy, 0x1fff) > 0)
{
*pswLtpShift = 2; /* E = (0x1fff..0x7fff] */
}
else
{
*pswLtpShift = 1; /* E = (0x7ff.. 0x1fff] */
}
}
for (i = 0; i < iNumLags; i++)
{
/* shift all vectors down s.t. the largest is has energy < 1.0 */
/*-------------------------------------------------------------*/
for (j = 0; j < S_LEN; j++)
ppswTVect[i][j] = shr(ppswTVect[i][j], *pswLtpShift);
/* Calculate the energy of the subframe */
/* ------------------------------------ */
L_Energy = L_mult(ppswTVect[i][0], ppswTVect[i][0]);
for (j = 1; j < S_LEN; j++)
L_Energy = L_mac(L_Energy, ppswTVect[i][j], ppswTVect[i][j]);
pL_CGBuf[i] = L_Energy;
/* Cross correlate the normalized speech frame and the filtered
* subframe */
/* ---------------------------------------------------------------------
* */
L_CrossCorr = L_mult(ppswTVect[i][0], pswPVect[0]);
for (j = 1; j < S_LEN; j++)
L_CrossCorr = L_mac(L_CrossCorr, ppswTVect[i][j], pswPVect[j]);
pL_CCBuf[i] = L_CrossCorr;
}
/* find the shift count associated with the largest CC and G */
/* ---------------------------------------------------------- */
L_ccNorm = L_abs(pL_CCBuf[0]);
L_cgNorm = pL_CGBuf[0];
for (i = 1; i < iNumLags; i++)
{
L_ccNorm |= L_abs(pL_CCBuf[i]);
L_cgNorm |= pL_CGBuf[i];
}
swCCShiftCnt = norm_l(L_ccNorm);
swCGShiftCnt = norm_l(L_cgNorm);
for (i = 0; i < iNumLags; i++)
{
pswCCBuf[i] = round(L_shl(pL_CCBuf[i], swCCShiftCnt));
pswCGBuf[i] = round(L_shl(pL_CGBuf[i], swCGShiftCnt));
}
/* Maximize C**2/G */
/* --------------- */
siLagOffset = maxCCOverGWithSign(pswCCBuf, pswCGBuf,
&swCCMax, &swGMax,
iNumLags);
/* Determine the offset of the max value into CC buffer */
/* ---------------------------------------------------- */
*pswLag = pswLagList[siLagOffset];
/* Store Lag Code for best lag result */
/* ---------------------------------- */
quantLag(*pswLag, &siLagCode);
return (siLagCode);
}
/*****************************************************************************
*
* FUNCTION NAME: decorr
*
* PURPOSE: Decorrelates(orthogonalizes) a set of vectors from a given
* vector.
*
*
* INPUTS: iNumVects - number of vectors to decorrelate
* pswGivenVect[0..39] - array of given vectors
* pswVects[0..359] (voice) [0..279] (unvoiced) - array of
* contiguous vectors to be decorrelated
* OUTPUTS: pswVects[0..359] (voice) [0..279] (unvoiced) - output vectors
* are written back over input vectors
*
* RETURN VALUE: none
*
* IMPLEMENTATION:
*
* REFERENCE: Sub-clause 4.1.10.1 of GSM Recommendation 06.20
*
* KEYWORDS: decorrelate, codewords, codevectors, orthogonalize, encoder
*
****************************************************************************/
void decorr(int iNumVects, Shortword pswGivenVect[],
Shortword pswVects[])
{
/*___________________________________________________________________________
| |
| Automatic Variables |
|___________________________________________________________________________|
*/
int i,
iLoopCnt;
Shortword swNorm_energy,
swTemp;
Shortword swEShift,
swCShift,
swShiftSum,
swQShift;
Longword L_Energy,
L_Temp1,
L_Temp2,
L_Accum;
/*___________________________________________________________________________
| |
| Executable Code |
|___________________________________________________________________________|
*/
/* Compute normalized energy in given vector */
/*-------------------------------------------*/
swEShift = g_corr1(pswGivenVect, &L_Energy);
swNorm_energy = extract_h(L_Energy);
if (swNorm_energy == 0)
{
return;
}
/* Decorrelate vectors */
/*---------------------*/
for (iLoopCnt = 0; iLoopCnt < iNumVects; iLoopCnt++)
{
swCShift = g_corr2(pswGivenVect, &pswVects[iLoopCnt * S_LEN],
&L_Temp1);
L_Temp2 = L_Temp1;
L_Temp1 = L_abs(L_Temp1);
swCShift = sub(swCShift, 1);
swShiftSum = sub(swCShift, swEShift);
L_Temp1 = L_shr(L_Temp1, 1);
swTemp = divide_s(round(L_Temp1), swNorm_energy);
if (L_Temp2 > 0)
swTemp = negate(swTemp);
swQShift = norm_s(swTemp);
swTemp = shl(swTemp, swQShift);
swQShift = add(swShiftSum, swQShift);
if (swQShift > 0)
{
swTemp = shift_r(swTemp, negate(swQShift));
swQShift = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -