diff err_conc.c @ 0:9008dbc8ca74

import original C code from GSM 06.06
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 14 Jun 2024 23:27:16 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/err_conc.c	Fri Jun 14 23:27:16 2024 +0000
@@ -0,0 +1,655 @@
+/***************************************************************************
+ *
+ *   File Name:  err_conc.c
+ *
+ *   Purpose:
+ *      Contains all functions for error concealment.
+ *      Relevant specification: GSM 06.21
+ *
+ *     Below is a listing of all the functions appearing in the file.
+ *     All functions are called within speechDecoder().
+ *
+ *     Error concealment on parameter level:
+ *        para_conceal_speech_decoder()
+ *
+ *     Error concealment on signal level:
+ *        signal_conceal_sub()
+ *
+ *     Additional functions to support concealment:
+ *        level_estimator()
+ *        level_calc()
+ *
+ **************************************************************************/
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                              Include Files                              |
+ |_________________________________________________________________________|
+*/
+
+#include "mathhalf.h"
+#include "sp_dec.h"
+#include "err_conc.h"
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                              Local Defines                              |
+ |_________________________________________________________________________|
+*/
+#define  MIN_MUTE_LEVEL -45
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                         State variables (globals)                       |
+ |_________________________________________________________________________|
+*/
+
+Longword plSubfrEnergyMem[4];
+Shortword swLevelMem[4],
+       lastR0,
+       pswLastGood[18],
+       swState,
+       swLastFlag;
+
+
+/*****************************************************************************
+ *
+ *   FUNCTION NAME: para_conceal_speech_decoder
+ *
+ *     This subroutine performs concealment on parameter level. If the
+ *     badframe flag (swErrorFlag[0]) has been set in the channel decoder
+ *     parameter repetition is performed.
+ *     If the average frame energy R0 shows an abnormal increase between two
+ *     subsequent frames the badframe flag is also set and parameter
+ *     repetition is performed.
+ *     If R0 shows an important increase muting is permitted in the signal
+ *     concealment unit. There the level of the synthesized speech signal is
+ *     controlled and corrected if necessary.
+ *
+ *     In table "psrR0RepeatThreshold[]" the maximum allowed
+ *     increase of R0 for badframe setting is stored. The table
+ *     is controlled by the value of R0 of the last frame.
+ *     If e.g. the previous R0 is 10 the allowed maximum increase
+ *     is 9 (psrR0RepeatThreshold[10]).
+ *     The figures in psrR0RepeatThreshold[] have been determined
+ *     by measuring the R0 statistics of an error free speech
+ *     signal. In approximately 95 % of the frames the increase of
+ *     R0 is less than the defined figures for error free speech.
+ *     If the level increase is higher than the determined limit
+ *     then the badframe flag is set.
+ *
+ *     In table "psrR0MuteThreshold[]" the maximum allowed
+ *     increase of R0 for muting is stored.
+ *     The table is controlled by the value of R0 of the last frame
+ *     If e.g. the previous R0 is 10 the allowed maximum increase
+ *     is 7 (psrR0MuteThreshold[10]).
+ *     The figures in psrR0MuteThreshold[] have been determined
+ *     by measuring the R0 statistics of an error free speech
+ *     signal. In approximately 85 % of the frames the increase of
+ *     R0 is less than the defined figures for error free speech.
+ *     If the level increase is higher than the determined limit
+ *     then muting is allowed.
+ *
+ *     Input:     pswErrorFlag[0]   badframe flag from channel decoder
+ *                pswErrorFlag[1]   unreliable frame flag from channel decoder
+ *                pswSpeechPara[]   unconcealed speech parameters
+ *     Output:    pswSpeechPara[]   concealed speech parameters
+ *                swMutePermit      flag, indicating whether muting is
+ *                                  permitted
+ *
+ *     Constants: psrR0RepeatThreshold[32]  maximum allowed R0 difference
+ *                                          before frame is repeated
+ *                psrR0MuteThreshold[32]    maximum allowed R0 difference
+ *                                          before muting is permitted
+ *
+ *
+ ****************************************************************************/
+
+void   para_conceal_speech_decoder(Shortword pswErrorFlag[],
+                        Shortword pswSpeechPara[], Shortword *pswMutePermit)
+{
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                           Local Static Variables                        |
+ |_________________________________________________________________________|
+*/
+  static const Shortword psrR0RepeatThreshold[32] =
+  {15, 15, 15, 12, 12, 12, 12, 11,
+    10, 10, 9, 9, 9, 9, 8, 8,
+    7, 6, 5, 5, 5, 4, 4, 3,
+  2, 2, 2, 2, 2, 2, 10, 10};
+  static const Shortword psrR0MuteThreshold[32] =
+  {14, 12, 11, 9, 9, 9, 9, 7,
+    7, 7, 7, 7, 6, 6, 6, 5,
+    5, 4, 3, 3, 3, 3, 3, 2,
+  1, 1, 1, 1, 1, 1, 10, 10};
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                            Automatic Variables                          |
+ |_________________________________________________________________________|
+*/
+  Shortword swLastLag,
+         swR0,
+         swLag,
+         r0_diff,
+         i;
+
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                              Executable Code                            |
+ |_________________________________________________________________________|
+*/
+
+  /* Initialise mute permission flag */
+  /* ------------------------------- */
+  *pswMutePermit = 0;
+
+  /* Determine R0-difference to last frame */
+  /* ------------------------------------- */
+  r0_diff = sub(pswSpeechPara[0], lastR0);
+
+  /* If no badframe has been declared, but the frame is unreliable then */
+  /* check whether there is an abnormal increase of R0                  */
+  /* ------------------------------------------------------------------ */
+  if ((pswErrorFlag[0] == 0) && (pswErrorFlag[1] > 0))
+  {
+
+    /* Check if difference exceeds the maximum allowed threshold. */
+    /* If yes, set badframe flag                                  */
+    /* ---------------------------------------------------------- */
+    if (sub(r0_diff, psrR0RepeatThreshold[lastR0]) >= 0)
+    {
+      pswErrorFlag[0] = 1;
+    }
+    else
+    {
+      /* Allow muting if R0 >= 30 */
+      /* ------------------------ */
+      if (sub(pswSpeechPara[0], 30) >= 0)
+        *pswMutePermit = 1;
+    }
+  }
+
+  /* If no badframe has been declared, but the frame is unreliable then */
+  /* check whether there is an important increase of R0                 */
+  /* ------------------------------------------------------------------ */
+  if ((pswErrorFlag[1] > 0) && (pswErrorFlag[0] == 0))
+  {
+
+    /* Check if difference exceeds a threshold.                   */
+    /* If yes, allow muting in the signal concealment unit        */
+    /* ---------------------------------------------------------- */
+    if (sub(r0_diff, psrR0MuteThreshold[lastR0]) >= 0)
+    {
+      *pswMutePermit = 1;
+    }
+  }
+
+
+  /* Perform parameter repetition, if necessary (badframe handling) */
+  /* -------------------------------------------------------------- */
+
+  if (pswErrorFlag[0] > 0)
+  {
+    swState = add(swState, 1);         /* update the bad frame
+                                        * masking state */
+    if (sub(swState, 6) > 0)
+      swState = 6;
+  }
+  else
+  {
+    if (sub(swState, 6) < 0)
+      swState = 0;
+    else if (swLastFlag == 0)
+      swState = 0;
+  }
+
+  swLastFlag = pswErrorFlag[0];
+
+  /* if the decoded frame is good, save it */
+  /* ------------------------------------- */
+  if (swState == 0)
+  {
+    for (i = 0; i < 18; i++)
+      pswLastGood[i] = pswSpeechPara[i];
+  }
+
+  /* if the frame is bad, attenuate and repeat last good frame */
+  /* --------------------------------------------------------- */
+  else
+  {
+    if ((sub(swState, 3) >= 0) && (sub(swState, 5) <= 0))
+    {
+      swR0 = sub(pswLastGood[0], 2);   /* attenuate by 4 dB */
+      if (swR0 < 0)
+        swR0 = 0;
+      pswLastGood[0] = swR0;
+    }
+
+    if (sub(swState, 6) >= 0)          /* mute */
+      pswLastGood[0] = 0;
+
+    /* If the last good frame is unvoiced, use its energy, voicing mode, lpc
+     * coefficients, and soft interpolation.   For gsp0, use only the gsp0
+     * value from the last good subframe.  If the current bad frame is
+     * unvoiced, use the current codewords.  If not, use the codewords from
+     * the last good frame.               */
+    /* -------------------------------------------------------------- */
+    if (pswLastGood[5] == 0)
+    {                                  /* unvoiced good frame */
+      if (pswSpeechPara[5] == 0)
+      {                                /* unvoiced bad frame */
+        for (i = 0; i < 5; i++)
+          pswSpeechPara[i] = pswLastGood[i];
+        for (i = 0; i < 4; i++)
+          pswSpeechPara[3 * i + 8] = pswLastGood[17];
+      }
+      else
+      {                                /* voiced bad frame */
+        for (i = 0; i < 18; i++)
+          pswSpeechPara[i] = pswLastGood[i];
+        for (i = 0; i < 3; i++)
+          pswSpeechPara[3 * i + 8] = pswLastGood[17];
+      }
+    }
+
+    /* If the last good frame is voiced, the long term predictor lag at the
+     * last subframe is used for all subsequent subframes. Use the last good
+     * frame's energy, voicing mode, lpc coefficients, and soft
+     * interpolation.  For gsp0 in all subframes, use the gsp0 value from the
+     * last good subframe.  If the current bad frame is voiced, use the
+     * current codewords.  If not, use the codewords from the last good
+     * frame.                              */
+    /* ---------------------------------------------------------------- */
+    else
+    {                                  /* voiced good frame */
+      swLastLag = pswLastGood[6];      /* frame lag */
+      for (i = 0; i < 3; i++)
+      {                                /* each delta lag */
+        swLag = sub(pswLastGood[3 * i + 9], 0x8);       /* biased around 0 */
+        swLag = add(swLag, swLastLag); /* reconstruct pitch */
+        if (sub(swLag, 0x00ff) > 0)
+        {                              /* limit, as needed */
+          swLastLag = 0x00ff;
+        }
+        else if (swLag < 0)
+        {
+          swLastLag = 0;
+        }
+        else
+          swLastLag = swLag;
+      }
+      pswLastGood[6] = swLastLag;      /* saved frame lag */
+      pswLastGood[9] = 0x8;            /* saved delta lags */
+      pswLastGood[12] = 0x8;
+      pswLastGood[15] = 0x8;
+
+      if (pswSpeechPara[5] != 0)
+      {                                /* voiced bad frame */
+        for (i = 0; i < 6; i++)
+          pswSpeechPara[i] = pswLastGood[i];
+        for (i = 0; i < 4; i++)
+          pswSpeechPara[3 * i + 6] = pswLastGood[3 * i + 6];
+        for (i = 0; i < 4; i++)
+          pswSpeechPara[3 * i + 8] = pswLastGood[17];
+      }
+      else
+      {                                /* unvoiced bad frame */
+        for (i = 0; i < 18; i++)
+          pswSpeechPara[i] = pswLastGood[i];
+        for (i = 0; i < 3; i++)
+          pswSpeechPara[3 * i + 8] = pswLastGood[17];
+      }
+    }
+
+  }                                    /* end of bad frame */
+
+
+  /* Update last value of R0 */
+  /* ----------------------- */
+  lastR0 = pswSpeechPara[0];
+
+}
+
+
+/****************************************************************************
+ *
+ *   FUNCTION NAME: level_estimator
+ *
+ *     This subroutine determines the mean level and the maximum level
+ *     of the last four speech sub-frames. These parameters are the basis
+ *     for the level estimation in signal_conceal_sub().
+ *
+ *     Input:     swUpdate      = 0: the levels are determined
+ *                              = 1: the memory of the level estimator
+ *                                   is updated
+ *                pswDecodedSpeechFrame[]  synthesized speech signal
+ *
+ *     Output:    swLevelMean   mean level of the last 4 sub-frames
+ *                swLevelMax    maximum level of the last 4 sub-frames
+ *
+ ***************************************************************************/
+
+void   level_estimator(Shortword update, Shortword *pswLevelMean,
+                              Shortword *pswLevelMax,
+                              Shortword pswDecodedSpeechFrame[])
+{
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                            Automatic Variables                          |
+ |_________________________________________________________________________|
+*/
+  Shortword i,
+         tmp,
+         swLevelSub;
+  Longword L_sum;
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                              Executable Code                            |
+ |_________________________________________________________________________|
+*/
+
+  if (update == 0)
+  {
+
+    /* Determine mean level of the last 4 sub-frames: */
+    /* ---------------------------------------------- */
+    for (i = 0, L_sum = 0; i < 4; ++i)
+    {
+      L_sum = L_add(L_sum, plSubfrEnergyMem[i]);
+    }
+    *pswLevelMean = level_calc(1, &L_sum);
+
+    /* Determine maximum level of the last 4 sub-frames: */
+    /* ------------------------------------------------- */
+    *pswLevelMax = -72;
+    for (i = 0; i < 4; ++i)
+    {
+      if (sub(swLevelMem[i], *pswLevelMax) > 0)
+        *pswLevelMax = swLevelMem[i];
+    }
+
+  }
+  else
+  {
+    /* Determine the energy of the synthesized speech signal: */
+    /* ------------------------------------------------------ */
+    for (i = 0, L_sum = 0; i < S_LEN; ++i)
+    {
+      tmp = shr(pswDecodedSpeechFrame[i], 3);
+      L_sum = L_mac(L_sum, tmp, tmp);
+    }
+    swLevelSub = level_calc(0, &L_sum);
+
+    /* Update memories of level estimator: */
+    /* ----------------------------------- */
+    for (i = 0; i < 3; ++i)
+      plSubfrEnergyMem[i] = plSubfrEnergyMem[i + 1];
+    plSubfrEnergyMem[3] = L_sum;
+
+    for (i = 0; i < 3; ++i)
+      swLevelMem[i] = swLevelMem[i + 1];
+    swLevelMem[3] = swLevelSub;
+  }
+}
+
+
+/*****************************************************************************
+ *
+ *   FUNCTION NAME: signal_conceal_sub
+ *
+ *     This subroutine performs concealment on subframe signal level.
+ *     A test synthesis is performed and the level of the synthesized speech
+ *     signal is compared to the estimated level. Depending on the control
+ *     flag "swMutePermit" a muting factor is determined.
+ *     If muting is permitted (swMutePermit=1) and the actual sub-frame level
+ *     exceeds the maximum level of the last four sub-frames "swLevelMax" plus
+ *     an allowed increase "psrLevelMaxIncrease[]" then the synthesized speech
+ *     signal together with the signal memories is muted.
+ *     In table "psrLevelMaxIncrease[]" the maximum allowed increase
+ *     of the maximum sub-frame level is stored. The table is controled by the
+ *     mean level "swMeanLevel".
+ *     If e.g. the level is in the range between -30 and -35 db
+ *     the allowed maximum increase is 4 db (psrLevelMaxIncrease[6]).
+ *     The figures in psrLevelMaxIncrease[] have been determined
+ *     by measuring the level statistics of error free synthesized speech.
+ *
+ *     Input:     pswPPFExcit[]            excitation signal
+ *                pswSynthFiltState[]      state of LPC synthesis filter
+ *                ppswSynthAs[]            LPC coefficients
+ *                pswLtpStateOut[]         state of long term predictor
+ *                pswPPreState[]           state of pitch prefilter
+ *                swLevelMean              mean level
+ *                swLevelMax               maximum level
+ *                swUFI                    unreliable frame flag
+ *                swMuteFlagOld            last muting flag
+ *                pswMuteFlag              actual muting flag
+ *                swMutePermit             mute permission
+ *
+ *     Output:    pswPPFExcit[]            muted excitation signal
+ *                pswSynthFiltState[]      muted state of LPC synthesis filter
+ *                pswLtpStateOut[]         muted state of long term predictor
+ *                pswPPreState[]           muted state of pitch prefilter
+ *
+ *     Constants: psrConceal[0:15]         muting factors
+ *                psrLevelMaxIncrease[0:7] maximum allowed level increase
+ *
+ *
+ ****************************************************************************/
+
+void   signal_conceal_sub(Shortword pswPPFExcit[],
+                     Shortword ppswSynthAs[], Shortword pswSynthFiltState[],
+                       Shortword pswLtpStateOut[], Shortword pswPPreState[],
+                                 Shortword swLevelMean, Shortword swLevelMax,
+                                 Shortword swUFI, Shortword swMuteFlagOld,
+                             Shortword *pswMuteFlag, Shortword swMutePermit)
+{
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                           Local Static Variables                        |
+ |_________________________________________________________________________|
+*/
+  static const Shortword psrConceal[15] = {29205, 27571, 24573, 21900,
+  19519, 17396, 15504, 13818, 12315, 10976, 9783, 8719, 7771, 6925, 6172};
+  static const Shortword psrLevelMaxIncrease[16] =
+  {0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16};
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                            Automatic Variables                          |
+ |_________________________________________________________________________|
+*/
+  Shortword swMute,
+         swLevelSub,
+         i,
+         swIndex;
+  Shortword swTmp,
+         pswStateTmp[10],
+         swOutTmp[40],
+         swPermitMuteSub;
+  Longword L_sum;
+
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                              Executable Code                            |
+ |_________________________________________________________________________|
+*/
+
+  /* Test synthesis filter: */
+  /* ---------------------- */
+  for (i = 0; i < 10; ++i)
+    pswStateTmp[i] = pswSynthFiltState[i];
+
+  lpcIir(pswPPFExcit, ppswSynthAs, pswStateTmp, swOutTmp);
+
+
+  /* Determine level in db of synthesized signal: */
+  /* -------------------------------------------- */
+  L_sum = 0;
+  for (i = 0; i < S_LEN; ++i)
+  {
+    swTmp = shr(swOutTmp[i], 2);
+    L_sum = L_mac(L_sum, swTmp, swTmp);
+  }
+  swLevelSub = level_calc(0, &L_sum);
+
+
+  /* Determine index to table, specifying the allowed level increase: */
+  /* level [ 0 ..  -5] --> swIndex = 0       */
+  /* level [-5 .. -10] --> swIndex = 1  etc. */
+  /*---------------------------------------------*/
+  swIndex = mult(negate(swLevelMean), 1638);
+  if (sub(swIndex, 15) > 0)
+    swIndex = 15;
+
+  /* Muting is permitted, if it is signalled from the parameter concealment */
+  /* unit or if muting has been performed in the last frame                */
+  /*-----------------------------------------------------------------------*/
+  swPermitMuteSub = swMutePermit;
+  if (swMuteFlagOld > 0)
+    swPermitMuteSub = 1;
+
+  if (swPermitMuteSub > 0)
+  {
+    /* Muting is not permitted if the sub-frame level is less than */
+    /* MIN_MUTE_LEVEL                                              */
+    /* ------------------------------------------------------------ */
+    if (sub(swLevelSub, MIN_MUTE_LEVEL) <= 0)
+      swPermitMuteSub = 0;
+
+    /* Muting is not permitted if the sub-frame level is less than */
+    /* the maximum level of the last 4 sub-frames plus the allowed */
+    /* increase                                                    */
+    /* ------------------------------------------------------------ */
+    swMute = sub(swLevelSub, add(swLevelMax, psrLevelMaxIncrease[swIndex]));
+    if (swMute <= 0)
+      swPermitMuteSub = 0;
+  }
+
+
+  /* Perform muting, if allowed */
+  /* -------------------------- */
+  if (swPermitMuteSub > 0)
+  {
+
+    if (sub(swMute, (Shortword) 15) > 0)
+      swMute = 15;
+
+    /* Keep information that muting occured for next frame */
+    /* --------------------------------------------------- */
+    if (swUFI > 0)
+      *pswMuteFlag = 1;
+
+
+    /* Mute excitation signal: */
+    /* ----------------------- */
+    for (i = 0; i < 10; ++i)
+      pswSynthFiltState[i] =
+              mult_r(pswSynthFiltState[i], psrConceal[swMute - 1]);
+    for (i = 0; i < S_LEN; ++i)
+      pswPPFExcit[i] = mult_r(pswPPFExcit[i], psrConceal[swMute - 1]);
+
+    /* Mute pitch memory: */
+    /* ------------------ */
+    for (i = 0; i < S_LEN; ++i)
+      pswLtpStateOut[i] =
+              mult_r(pswLtpStateOut[i], psrConceal[swMute - 1]);
+
+
+    /* Mute pitch prefilter memory: */
+    /* ---------------------------- */
+    for (i = 0; i < S_LEN; ++i)
+      pswPPreState[i] = mult_r(pswPPreState[i], psrConceal[swMute - 1]);
+  }
+}
+
+
+/****************************************************************************
+ *
+ *   FUNCTION NAME: level_calc
+ *
+ *     This subroutine calculates the level (db) from the energy
+ *     of a speech sub-frame (swInd=0) or a speech frame (swInd=1):
+ *     The level of a speech subframe is:
+ *       swLevel =  10 * lg(EN/(40.*4096*4096))
+ *               =   3 * ld(EN) - 88.27
+ *               = (3*4*ld(EN) - 353)/4
+ *               = (3*(4*POS(MSB(EN)) + 2*BIT(MSB-1) + BIT(MSB-2)) - 353)/4
+ *
+ *     Input:     pl_en      energy of the speech subframe or frame
+ *                           The energy is multiplied by 2 because of the
+ *                           MAC routines !!
+ *                swInd      = 0: EN is the energy of one subframe
+ *                           = 1: EN is the energy of one frame
+ *
+ *     Output:    swLevel    level in db
+ *
+ *
+ ***************************************************************************/
+
+Shortword level_calc(Shortword swInd, Longword *pl_en)
+{
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                            Automatic Variables                          |
+ |_________________________________________________________________________|
+*/
+  Shortword swPos,
+         swLevel;
+  Longword L_tmp;
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                              Executable Code                            |
+ |_________________________________________________________________________|
+*/
+
+  if (*pl_en != 0)
+    swPos = sub((Shortword) 29, norm_l(*pl_en));
+  else
+    swPos = 0;
+
+  /* Determine the term: 4*POS(MSB(EN)): */
+  /* ----------------------------------- */
+  swLevel = shl(swPos, 2);
+
+  /* Determine the term: 2*BIT(MSB-1): */
+  /* --------------------------------- */
+  if (swPos >= 0)
+  {
+    L_tmp = L_shl((Longword) 1, swPos);
+    if ((*pl_en & L_tmp) != 0)
+      swLevel += 2;
+  }
+
+  /* Determine the term: BIT(MSB-2): */
+  /* ------------------------------- */
+  if (--swPos >= 0)
+  {
+    L_tmp = L_shl((Longword) 1, swPos);
+    if ((*pl_en & L_tmp) != 0)
+      ++swLevel;
+  }
+
+  /* Multiply by 3: */
+  /* -------------- */
+  swLevel += shl(swLevel, 1);
+  swLevel -= (swInd == 0) ? 353 : 377;
+  swLevel = mult_r(swLevel, 0X2000);   /* >> 2 */
+
+  if (sub(swLevel, -72) < 0)
+  {
+    swLevel = -72;
+    *pl_en = (swInd == 0) ? 80 : 320;
+  }
+
+  return (swLevel);
+}