⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sp_sfrm.c

📁 GSM中半速率语音编解码源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************
 *
 *   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 + -