📄 sp_sfrm.c
字号:
* pswInSample points to the "oldest" sample of the
* current subframe to be hnw filtered, S_LEN samples
* will be stored in this array, this data is not
* explicitly modified.
*
* pswState[0:183] - array of state of samples, the most
* recent sample is the tail of the state buffer,
* used only for full- state filtering, this data is
* not modified
* pswInCoef[0:5] - array of unmodified filter coefficients
* iStateOffset - address offset from a sample in the subframe back
* to the oldest element of the state used in the interpolating
* filter for that sample. Although the subframe samples and
* state information can come from different buffers, this
* offset represents the case in which the state and sample
* information are in the same buffer
* swZeroState - indicate if the interpolating filter should be
* "zero-state" filtering or "full-state" filtering:
* 0 ==> zero-state filtering
* !0 ==> full-state filtering
* iNumSamples - the number of samples that are to be filtered,
* required to be less than or equal to S_LEN in order to
* correctly match speech samples with sample states for the
* filtering procedure
*
* OUTPUTS:
* pswOutSample[0:39] - array of output filtered speech signal,
* pswOutSample points to the "oldest" sample location, S_LEN
* filtered samples will be stored at the buffer associated with
* this array, can implicitly overwrite input samples with
* with filtered samples by setting pswOutSample = pswInSample
*
* RETURN VALUE:
* none
*
* IMPLEMENTATION:
* The harmonic noise weighting filter is implemented in reverse
* temporal order, from most recent input sample backwards through
* the input sample array. The procedure follows the equation:
* x(n) = x(n) - PW_COEF*x(n - lag)
* where the PW_COEF is the pitch weighting for the current
* subframe and lag is the full-resolution lag for the current
* subframe. x(n - lag) is found by implementing a CG_INT_MACS-
* order FIR interpolating filter
*
* Harmonic noise weighting is discussed in secion 5.5.
*
* REFERENCE: Sub-clause 4.1.9 of GSM Recommendation 06.20
*
* KEYWORDS: T_SUB, LAG, HNW_FILT, PW_COEF, CG_INT_MACS, S_LEN, LSMAX
*
**************************************************************************/
void hnwFilt(Shortword pswInSample[],
Shortword pswOutSample[],
Shortword pswState[],
Shortword pswInCoef[],
int iStateOffset,
Shortword swZeroState,
int iNumSamples)
{
/*_________________________________________________________________________
| |
| Automatic Variables |
|_________________________________________________________________________|
*/
Longword L_temp;
int i,
j;
int iStatIndx = S_LEN - 1 + iStateOffset;
int iStatIndx1 = S_LEN + iStateOffset;
/*_________________________________________________________________________
| |
| Executable Code |
|_________________________________________________________________________|
*/
if (swZeroState == 0)
{
/* zero state response assumes input and output arrays are the same */
/*------------------------------------------------------------------*/
for (i = 0; i < iNumSamples; i++)
{
/* get input with rounding */
/*-------------------------*/
L_temp = L_mac((long) 16384, pswInSample[S_LEN - i - 1], 0x4000);
for (j = 5; (j >= 0) && (iStatIndx - i + j >= 0); j--)
/* evaluate taps 1 - 6 that point to input */
/*-----------------------------------------*/
L_temp = L_mac(L_temp, pswInSample[iStatIndx - i + j], pswInCoef[j]);
pswOutSample[S_LEN - 1 - i] = extract_h(L_shl(L_temp, 1));
}
}
else
{
for (i = 0; i < iNumSamples; i++)
{
/* get input with rounding */
/*-------------------------*/
L_temp = L_mac((long) 16384, pswInSample[S_LEN - i - 1], 0x4000);
for (j = 5; (j >= 0) && (iStatIndx - i + j >= 0); j--)
/* evaluate taps 1 - 6 that point to input */
/*-----------------------------------------*/
L_temp = L_mac(L_temp, pswInSample[iStatIndx - i + j], pswInCoef[j]);
for (; (j >= 0); j--)
/* evaluate taps 1 - 6 that point to state */
/*----------------------------------------*/
L_temp = L_mac(L_temp, pswState[iStatIndx1 - i + j], pswInCoef[j]);
pswOutSample[S_LEN - 1 - i] = extract_h(L_shl(L_temp, 1));
}
}
}
/***************************************************************************
*
* FUNCTION NAME: sfrmAnalysis
*
* PURPOSE:
*
* Determines the synthetic excitation for a subframe.
*
* INPUTS:
*
* pswWSpeech
* Input weighted speech vector to be matched.
*
* swVoicingMode
*
* Voicing mode 0,1,2 or 3. 0 is unvoiced. A
* frame parameter.
*
* snsSqrtRs
*
* Normalized estimate of the excitation energy
*
* pswHCoefs
*
* Coefficientss used in weighted synthesis filter,
* H(z), (a negated version is used). pswHCoefs[0]
* is t=-1 tap, pswHCoefs[9] is t=-10 tap.
*
* pswLagList
*
* List of lags to be searched in the long-term
* predictor, determined by the open-loop lag search.
*
* siNumLags
*
* Number of lags in pswLagList.
*
* swPitch
*
* Fundamental pitch value to be used in harmonic-
* noise-weighting, actualPitch*OS_FCTR.
*
* swHNWCoef
* Coefficient of the harmonic-noise-weighting filter.
*
* ppsrCGIntFilt[0:5][0:5]
*
* polyphase interpolation filter,
* ppsrCGIntFilt[iTap][iPhase], OS_FCTR phases,
* CG_INT_MACS taps per phase. Used to construct
* sequences delayed by fractional lags for Harmonic-
* Noise-Weighting.
*
* pppsrUvCodeVec[0:1][0:6][0:39]
*
* unvoiced codebooks:
* pppsrUvCodeVec[codeBook][vectorNumber][time]
*
* pppsrVcdCodeVec[0][0:8][0:39]
*
* voiced codebook:
* pppsrVcdCodeVect[codebook(=0)][vectorNumber][time]
*
* swSP
* speech flag (DTX mode)
*
* OUTPUTS:
*
* psiLagCode
*
* Lag code: frame- or delta-, or zero if unvoiced.
*
* psiVSCode1
*
* First vector-sum codebook code.
*
* psiVSCode2
*
* Second vector-sum codebook code, or zero if voiced.
*
* psiGsp0Code
*
* Gain quantizer code.
*
* DESCRIPTION:
*
* sfrmAnalysis() is the calling function for the subframe analysis
* functions. All subframe based processing is done by it and its
* daughter functions. All functions in this file are called by
* sfrmAnalysis() or one of its daughter functions. As can be seen
* above, this routine will select the LTP lag, the VSELP
* codevector(s) and the GSP0 codeword. It is called by
* speechEncoder().
*
* The subframe processing can follow one of two paths depending on
* whether the frame is voiced or unvoiced. These two paths are now
* described.
*
* First the zero input response of H(z) is calculated (lpcZiIir());
* then subtracted from the weighted speech (W(z)). The outcome, p(n)
* or pswWSVec[], will be the vector matched by the first excitation
* vector (either adaptive or first VSELP codevector). The p(n)
* vector is scaled to prevent overflow.
*
* If the frame is voiced, the closed loop lag search (closedLoop())
* is performed. An adaptive codevector lag is selected. Using the
* open loop "pitch" value, the harmonic noise weighting
* coefficients are obtained. The adaptive codevector is
* reconstructed (fp_ex()), and weighted through the (zero state)
* spectral (lpcZsIir()) and harmonic noise weighting filters
* (hnwFilt()).
*
* The basis vectors are also filtered through the weighting
* filters. If the frame is unvoiced, there is no spectral noise
* weighting.
*
* If voiced the VSELP basis vectors are decorrelated (decorr())
* from the selected adaptive (LTP) codevector, and the VSELP
* codevector search is initiated (v_srch()).
*
* If unvoiced, the first VSELP codevector search is performed
* (without any decorrelation). After a vector from the first VSELP
* codebook has been selected, the second set of basis vectors are
* decorrelated from the selected vector.
*
* Once all the excitation vectors have been selected, the gain
* quantizer is called, g_quant_vl().
*
* Finally, once all subframe parameters have been found, the
* selected excitation is scaled according to GSP0 (scaleExcite()),
* and the composite excitation is entered into the long term
* predictor history. The final excitation is also used to update
* H(z) and C(z).
*
* REFERENCE: Sub-clauses 4.1.8.5, 4.1.9 - 4.1.12 of GSM
* Recommendation 06.20
*
* Keywords: codewords, lag, codevectors, gsp0, decoding, analysis, t_sub
*
**************************************************************************/
void sfrmAnalysis(Shortword *pswWSpeech,
Shortword swVoicingMode,
struct NormSw snsSqrtRs,
Shortword *pswHCoefs,
Shortword *pswLagList,
short siNumLags,
Shortword swPitch,
Shortword swHNWCoef,
short *psiLagCode,
short *psiVSCode1,
short *psiVSCode2,
short *psiGsp0Code,
Shortword swSP)
{
/*_________________________________________________________________________
| |
| Static Variables |
|_________________________________________________________________________|
*/
static short siPrevLagCode;
/*_________________________________________________________________________
| |
| Automatic Variables |
|_________________________________________________________________________|
*/
short i,
j,
siCode,
siIntPitch,
siRemainder;
short siHnwOffset,
siHnwNum,
siNumBasisVecs;
Shortword swLag,
swPnEnergy,
swPnShift,
swSampleA;
Shortword swLtpShift;
Longword L_PnEnergy;
struct NormSw snsRs00,
snsRs11,
snsRs22;
Shortword pswWSVec[S_LEN],
pswTempVec[S_LEN];
Shortword pswPVec[S_LEN],
pswWPVec[S_LEN];
Shortword ppswVselpEx[2][S_LEN],
ppswWVselpEx[2][S_LEN];
Shortword pswWBasisVecs[9 * S_LEN],
pswBitArray[9];
Shortword pswHNWCoefs[CG_INT_MACS];
Shortword *pswLtpStateOut;
/*_________________________________________________________________________
| |
| Executable Code |
|_________________________________________________________________________|
*/
pswLtpStateOut = pswLtpStateBase + LTP_LEN;
if (swSP == 1) /* DTX mode */
{ /* DTX mode */
/* if not in CNI mode */
/*--------------------*/
/* Get the zero-input response of H(z) */
/*-------------------------------------*/
lpcZiIir(pswHCoefs, pswHState, pswTempVec);
/* Subtract the zero-input response of H(z) from W(z)-weighted speech. */
/* The result is the vector to match for the adaptive codebook (long- */
/* term-predictor) search in voiced modes, or the vector to match for */
/* all synthetic excitation searches in unvoiced mode. */
/*---------------------------------------------------------------------*/
for (i = 0; i < S_LEN; i++)
{
pswWSVec[i] = sub(pswWSpeech[i], pswTempVec[i]);
}
/* scale the weighted speech vector (p[n]) s.t. its energy is strictly */
/* less than 1.0 */
/*---------------------------------------------------------------------*/
swSampleA = shr(pswWSVec[0], 2);
L_PnEnergy = L_mac(0x001dff4cL, swSampleA, swSampleA);
for (i = 1; i < S_LEN; i++)
{
swSampleA = shr(pswWSVec[i], 2); /* reduces energy by 16 */
L_PnEnergy = L_mac(L_PnEnergy, swSampleA, swSampleA);
}
swPnEnergy = round(L_PnEnergy);
if (sub(swPnEnergy, 0x7ff) <= 0)
{ /* E = [0..0x7ff] */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -