FreeCalypso > hg > gsm-codec-lib
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; }
