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

📄 sp_dec.c

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