diff libgsmhr1/err_conc.c @ 600:5a7d04bf26f5

libgsmhr1: integrate signal-level err_conc code
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 04 Dec 2025 10:24:06 +0000
parents 762cf36e2487
children
line wrap: on
line diff
--- a/libgsmhr1/err_conc.c	Thu Dec 04 10:02:09 2025 +0000
+++ b/libgsmhr1/err_conc.c	Thu Dec 04 10:24:06 2025 +0000
@@ -27,8 +27,12 @@
  |_________________________________________________________________________|
 */
 
+#include "typedefs.h"
+#include "tw_gsmhr.h"
+#include "namespace.h"
 #include "mathhalf.h"
-#include "sp_dec.h"
+#include "dec_func.h"
+#include "dec_state.h"
 #include "err_conc.h"
 
 /*_________________________________________________________________________
@@ -38,282 +42,6 @@
 */
 #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];
-
-}
-
 
 /****************************************************************************
  *
@@ -333,9 +61,44 @@
  *
  ***************************************************************************/
 
-void   level_estimator(Shortword update, Shortword *pswLevelMean,
-                              Shortword *pswLevelMax,
-                              Shortword pswDecodedSpeechFrame[])
+void level_estimator_det(struct gsmhr_decoder_state *st,
+			 Shortword *pswLevelMean, Shortword *pswLevelMax)
+{
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                            Automatic Variables                          |
+ |_________________________________________________________________________|
+*/
+  Shortword i;
+  Longword L_sum;
+
+/*_________________________________________________________________________
+ |                                                                         |
+ |                              Executable Code                            |
+ |_________________________________________________________________________|
+*/
+
+    /* Determine mean level of the last 4 sub-frames: */
+    /* ---------------------------------------------- */
+    for (i = 0, L_sum = 0; i < 4; ++i)
+    {
+      L_sum = L_add(L_sum, st->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(st->swLevelMem[i], *pswLevelMax) > 0)
+        *pswLevelMax = st->swLevelMem[i];
+    }
+}
+
+void level_estimator_upd(struct gsmhr_decoder_state *st,
+			 Shortword pswDecodedSpeechFrame[])
 {
 
 /*_________________________________________________________________________
@@ -354,29 +117,6 @@
  |_________________________________________________________________________|
 */
 
-  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)
@@ -389,13 +129,12 @@
     /* Update memories of level estimator: */
     /* ----------------------------------- */
     for (i = 0; i < 3; ++i)
-      plSubfrEnergyMem[i] = plSubfrEnergyMem[i + 1];
-    plSubfrEnergyMem[3] = L_sum;
+      st->plSubfrEnergyMem[i] = st->plSubfrEnergyMem[i + 1];
+    st->plSubfrEnergyMem[3] = L_sum;
 
     for (i = 0; i < 3; ++i)
-      swLevelMem[i] = swLevelMem[i + 1];
-    swLevelMem[3] = swLevelSub;
-  }
+      st->swLevelMem[i] = st->swLevelMem[i + 1];
+    st->swLevelMem[3] = swLevelSub;
 }