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

📄 sp_dec.c

📁 GSM中半速率语音编解码源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *     extended resolution lag is divided by the oversampling factor
 *
 *   INPUTS:
 *
 *     swLagIn
 *                     extended resolution lag as an integer, i.e.
 *                     fractional lag x oversampling factor
 *
 *   OUTPUTS:
 *
 *     *pswIp
 *                     fractional lag rounded down to nearest integer, IP
 *
 *     *pswJj
 *                     the remainder JJ
 *
 *   RETURN VALUE:
 *
 *     none
 *
 *   DESCRIPTION:
 *
 *     ip = integer[lag/OS_FCTR]
 *     jj = integer_round[((lag/OS_FCTR)-ip)*(OS_FCTR)]
 *          if the rounding caused an 'overflow'
 *            set remainder jj to 0 and add 'carry' to ip
 *
 *     This routine is involved in the mechanics of fractional and
 *     integer LTP searchs.  The LTP is described in section 5.
 *
 *   REFERENCES: Sub-clause 4.1.8 and 4.2.2 of GSM Recomendation 06.20
 *
 *   KEYWORDS: lag, fractional, remainder, ip, jj, get_ipjj
 *
 *************************************************************************/

void   get_ipjj(Shortword swLagIn,
                       Shortword *pswIp, Shortword *pswJj)
{

/*_________________________________________________________________________
 |                                                                         |
 |                              Local Constants                            |
 |_________________________________________________________________________|
*/

#define  OS_FCTR_INV  (Shortword)0x1555/* SW_MAX/OS_FCTR */

/*_________________________________________________________________________
 |                                                                         |
 |                            Automatic Variables                          |
 |_________________________________________________________________________|
*/

  Longword L_Temp;

  Shortword swTemp,
         swTempIp,
         swTempJj;

/*_________________________________________________________________________
 |                                                                         |
 |                              Executable Code                            |
 |_________________________________________________________________________|
*/

  /* calculate ip */
  /* ------------ */

  L_Temp = L_mult(OS_FCTR_INV, swLagIn);        /* lag/OS_FCTR */
  swTempIp = extract_h(L_Temp);

  /* calculate jj */
  /* ------------ */

  swTemp = extract_l(L_Temp);          /* loose ip */
  swTemp = shr(swTemp, 1);             /* isolate jj fraction */
  swTemp = swTemp & SW_MAX;
  L_Temp = L_mult(swTemp, OS_FCTR);    /* ((lag/OS_FCTR)-ip))*(OS_FCTR) */
  swTemp = round(L_Temp);              /* round and pick-off jj */
  if (sub(swTemp, OS_FCTR) == 0)
  {                                    /* if 'overflow ' */
    swTempJj = 0;                      /* set remainder,jj to 0 */
    swTempIp = add(swTempIp, 1);       /* 'carry' overflow into ip */
  }
  else
  {
    swTempJj = swTemp;                 /* read-off remainder,jj */
  }

  /* return ip and jj */
  /* ---------------- */

  *pswIp = swTempIp;
  *pswJj = swTempJj;
}

/***************************************************************************
 *
 *   FUNCTION NAME: interpolateCheck
 *
 *   PURPOSE:
 *
 *     Interpolates between direct form coefficient sets.
 *     Before releasing the interpolated coefficients, they are checked.
 *     If unstable, the "old" parameters are used.
 *
 *   INPUTS:
 *
 *     pswRefKs[0:9]
 *                     decoded version of the rc's tx'd last frame
 *
 *     pswRefCoefsA[0:9]
 *                     above K's converted to direct form coefficients
 *
 *     pswOldCoefsA[0:9]
 *                     array of old Coefseters
 *
 *     pswNewCoefsA[0:9]
 *                     array of new Coefseters
 *
 *     swOldPer
 *                     amount old coefs supply to the output
 *
 *     swNewPer
 *                     amount new coefs supply to the output
 *
 *     ASHIFT
 *                     shift for reflection coef. conversion
 *
 *     swRq
 *                     quantized energy to use for subframe
 * *
 *   OUTPUTS:
 *
 *     psnsSqrtRsOut
 *                     output pointer to sqrt(RS) normalized
 *
 *     pswCoefOutA[0:9]
 *                     output coefficients
 *
 *   RETURN VALUE:
 *
 *     siInterp_flg
 *                     temporary subframe interpolation flag
 *                     0 - coef. interpolated, 1 -coef. not interpolated
 *
 *   DESCRIPTION:
 *
 *     For interpolated subframes, the direct form coefficients
 *     are converted to reflection coefficients to check for
 *     filter stability. If unstable, the uninterpolated coef.
 *     are used for that subframe.  Section 4.1.6 describes
 *     interpolation.
 *
 *   REFERENCES: Sub-clause 4.1.6 and 4.2.3 of GSM Recomendation 06.20
 *
 *   KEYWORDS: soft interpolation, int_lpc, interpolate, atorc,res_eng,i_mov
 *
 *************************************************************************/

short int interpolateCheck(Shortword pswRefKs[],
                                  Shortword pswRefCoefsA[],
                         Shortword pswOldCoefsA[], Shortword pswNewCoefsA[],
                                  Shortword swOldPer, Shortword swNewPer,
                                  Shortword swRq,
                                  struct NormSw *psnsSqrtRsOut,
                                  Shortword pswCoefOutA[])
{

/*_________________________________________________________________________
 |                                                                         |
 |                            Automatic Variables                          |
 |_________________________________________________________________________|
*/

  Shortword pswRcTemp[NP];

  Longword L_Temp;

  short int siInterp_flg,
         i;

/*_________________________________________________________________________
 |                                                                         |
 |                              Executable Code                            |
 |_________________________________________________________________________|
*/

  /* Interpolation loop, NP is order of LPC filter */
  /* --------------------------------------------- */

  for (i = 0; i < NP; i++)
  {
    L_Temp = L_mult(pswNewCoefsA[i], swNewPer);
    pswCoefOutA[i] = mac_r(L_Temp, pswOldCoefsA[i], swOldPer);
  }

  /* Convert to reflection coefficients and check stability */
  /* ------------------------------------------------------ */

  if (aToRc(ASHIFT, pswCoefOutA, pswRcTemp) != 0)
  {

    /* Unstable, use uninterpolated parameters and compute RS update the
     * state with the frame data closest to this subfrm */
    /* --------------------------------------------------------- */

    res_eng(pswRefKs, swRq, psnsSqrtRsOut);

    for (i = 0; i < NP; i++)
    {
      pswCoefOutA[i] = pswRefCoefsA[i];
    }
    siInterp_flg = 0;
  }
  else
  {

    /* Stable, compute RS */
    /* ------------------ */
    res_eng(pswRcTemp, swRq, psnsSqrtRsOut);

    /* Set temporary subframe interpolation flag */
    /* ----------------------------------------- */
    siInterp_flg = 1;
  }

  /* Return subframe interpolation flag */
  /* ---------------------------------- */
  return (siInterp_flg);
}

/***************************************************************************
 *
 *   FUNCTION NAME: lagDecode
 *
 *   PURPOSE:
 *
 *     The purpose of this function is to decode the lag received from the
 *     speech encoder into a full resolution lag for the speech decoder
 *
 *   INPUTS:
 *
 *     swDeltaLag
 *
 *                     lag received from channel decoder
 *
 *     giSfrmCnt
 *
 *                     current sub-frame count
 *
 *     swLastLag
 *
 *                     previous lag to un-delta this sub-frame's lag
 *
 *     psrLagTbl[0:255]
 *
 *                     table used to look up full resolution lag
 *
 *   OUTPUTS:
 *
 *     swLastLag
 *
 *                     new previous lag for next sub-frame
 *
 *   RETURN VALUE:
 *
 *     swLag
 *
 *                     decoded full resolution lag
 *
 *   DESCRIPTION:
 *
 *     If first subframe, use lag as index to look up table directly.
 *
 *     If it is one of the other subframes, the codeword represents a
 *     delta offset.  The previously decoded lag is used as a starting
 *     point for decoding the current lag.
 *
 *   REFERENCES: Sub-clause 4.2.1 of GSM Recomendation 06.20
 *
 *   KEYWORDS: deltalags, lookup lag
 *
 *************************************************************************/

static Shortword lagDecode(Shortword swDeltaLag)
{

/*_________________________________________________________________________
 |                                                                         |
 |                              Local Constants                            |
 |_________________________________________________________________________|
*/

#define  DELTA_LEVELS_D2  DELTA_LEVELS/2
#define  MAX_LAG          0x00ff
#define  MIN_LAG          0x0000

/*_________________________________________________________________________
 |                                                                         |
 |                           Local Static Variables                        |
 |_________________________________________________________________________|
*/

  static Shortword swLastLag;

/*_________________________________________________________________________
 |                                                                         |
 |                            Automatic Variables                          |
 |_________________________________________________________________________|
*/

  Shortword swLag;

/*_________________________________________________________________________
 |                                                                         |
 |                              Executable Code                            |
 |_________________________________________________________________________|
*/

  /* first sub-frame */
  /* --------------- */

  if (giSfrmCnt == 0)
  {
    swLastLag = swDeltaLag;
  }

  /* remaining sub-frames */
  /* -------------------- */

  else
  {

    /* get lag biased around 0 */
    /* ----------------------- */

    swLag = sub(swDeltaLag, DELTA_LEVELS_D2);

    /* get real lag relative to last */
    /* ----------------------------- */

    swLag = add(swLag, swLastLag);

    /* clip to max or min */
    /* ------------------ */

    if (sub(swLag, MAX_LAG) > 0)
    {
      swLastLag = MAX_LAG;
    }
    else if (sub(swLag, MIN_LAG) < 0)
    {
      swLastLag = MIN_LAG;
    }
    else
    {
      swLastLag = swLag;
    }
  }

  /* return lag after look up */
  /* ------------------------ */

  swLag = psrLagTbl[swLastLag];
  return (swLag);
}

/***************************************************************************
 *
 *   FUNCTION NAME: lookupVq
 *
 *   PURPOSE:
 *
 *     The purpose of this function is to recover the reflection coeffs from
 *     the received LPC codewords.
 *
 *   INPUTS:
 *
 *     pswVqCodeWds[0:2]
 *
 *                         the codewords for each of the segments
 *
 *   OUTPUTS:
 *
 *     pswRCOut[0:NP-1]
 *
 *                        the decoded reflection coefficients
 *
 *   RETURN VALUE:
 *
 *     none.
 *
 *   DESCRIPTION:
 *
 *     For each segment do the following:
 *       setup the retrieval pointers to the correct vector
 *       get that vector
 *
 *   REFERENCES: Sub-clause 4.2.3 of GSM Recomendation 06.20
 *
 *   KEYWORDS: vq, vectorquantizer, lpc
 *
 *************************************************************************/

static void lookupVq(Shortword pswVqCodeWds[], Shortword pswRCOut[])
{
/*_________________________________________________________________________
 |                                                                         |
 |                              Local Constants           

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -