FreeCalypso > hg > gsm-codec-lib
view libtwamr/int_lpc.c @ 581:e2d5cad04cbf
libgsmhr1 RxFE: store CN R0+LPC separately from speech
In the original GSM 06.06 code the ECU for speech mode is entirely
separate from the CN generator, maintaining separate state. (The
main intertie between them is the speech vs CN state variable,
distinguishing between speech and CN BFIs, in addition to the
CN-specific function of distinguishing between initial and update
SIDs.)
In the present RxFE implementation I initially thought that we could
use the same saved_frame buffer for both ECU and CN, overwriting
just the first 4 params (R0 and LPC) when a valid SID comes in.
However, I now realize it was a bad idea: the original code has a
corner case (long sequence of speech-mode BFIs to put the ECU in
state 6, then SID and CN-mode BFIs, then a good speech frame) that
would be broken by that buffer reuse approach. We could eliminate
this corner case by resetting the ECU state when passing through
a CN insertion period, but doing so would needlessly increase
the behavioral diffs between GSM 06.06 and our version.
Solution: use a separate CN-specific buffer for CN R0+LPC parameters,
and match the behavior of GSM 06.06 code in this regard.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Feb 2025 10:02:45 +0000 |
parents | 32bc48faec4b |
children |
line wrap: on
line source
/* ******************************************************************************** * * GSM AMR-NB speech codec R98 Version 7.6.0 December 12, 2001 * R99 Version 3.3.0 * REL-4 Version 4.1.0 * ******************************************************************************** * * File : int_lpc.c * ******************************************************************************** */ /* ******************************************************************************** * MODULE INCLUDE FILE AND VERSION ID ******************************************************************************** */ #include "namespace.h" #include "int_lpc.h" /* ******************************************************************************** * INCLUDE FILES ******************************************************************************** */ #include "typedef.h" #include "basic_op.h" #include "no_count.h" #include "cnst.h" #include "lsp_az.h" /* ******************************************************************************** * LOCAL VARIABLES AND TABLES ******************************************************************************** */ /* *--------------------------------------* * Constants (defined in cnst.h) * *--------------------------------------* * M : LPC order * * MP1 : LPC order + 1 * *--------------------------------------* */ /* ******************************************************************************** * PUBLIC PROGRAM CODE ******************************************************************************** */ /* ************************************************************************** * * Function : Int_lpc_1and3 * Purpose : Interpolates the LSPs and converts to LPC parameters * to get a different LP filter in each subframe. * Description : The 20 ms speech frame is divided into 4 subframes. * The LSPs are quantized and transmitted at the 2nd and * 4th subframes (twice per frame) and interpolated at the * 1st and 3rd subframe. * * |------|------|------|------| * sf1 sf2 sf3 sf4 * F0 Fm F1 * * sf1: 1/2 Fm + 1/2 F0 sf3: 1/2 F1 + 1/2 Fm * sf2: Fm sf4: F1 * Returns : void * ************************************************************************** */ void Int_lpc_1and3 ( Word16 lsp_old[], /* i : LSP vector at the 4th subfr. of past frame (M) */ Word16 lsp_mid[], /* i : LSP vector at the 2nd subfr. of present frame (M) */ Word16 lsp_new[], /* i : LSP vector at the 4th subfr. of present frame (M) */ Word16 Az[] /* o : interpolated LP parameters in all subfr. (AZ_SIZE) */ ) { Word16 i; Word16 lsp[M]; /* lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */ for (i = 0; i < M; i++) { lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_old[i], 1)); move16 (); } Lsp_Az (lsp, Az); /* Subframe 1 */ Az += MP1; move16 (); Lsp_Az (lsp_mid, Az); /* Subframe 2 */ Az += MP1; move16 (); for (i = 0; i < M; i++) { lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_new[i], 1)); move16 (); } Lsp_Az (lsp, Az); /* Subframe 3 */ Az += MP1; move16 (); Lsp_Az (lsp_new, Az); /* Subframe 4 */ return; } /* ************************************************************************** * * Function : Int_lpc_1and3_2 * Purpose : Interpolation of the LPC parameters. Same as the Int_lpc * function but we do not recompute Az() for subframe 2 and * 4 because it is already available. * Returns : void * ************************************************************************** */ void Int_lpc_1and3_2 ( Word16 lsp_old[], /* i : LSP vector at the 4th subfr. of past frame (M) */ Word16 lsp_mid[], /* i : LSP vector at the 2nd subframe of present frame (M) */ Word16 lsp_new[], /* i : LSP vector at the 4th subframe of present frame (M) */ Word16 Az[] /* o :interpolated LP parameters in subframes 1 and 3 (AZ_SIZE) */ ) { Word16 i; Word16 lsp[M]; /* lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */ for (i = 0; i < M; i++) { lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_old[i], 1)); move16 (); } Lsp_Az (lsp, Az); /* Subframe 1 */ Az += MP1 * 2; move16 (); for (i = 0; i < M; i++) { lsp[i] = add (shr (lsp_mid[i], 1), shr (lsp_new[i], 1)); move16 (); } Lsp_Az (lsp, Az); /* Subframe 3 */ return; } /************************************************************************* * * FUNCTION: Int_lpc_1to3() * * PURPOSE: Interpolates the LSPs and convert to LP parameters to get * a different LP filter in each subframe. * * DESCRIPTION: * The 20 ms speech frame is divided into 4 subframes. * The LSPs are quantized and transmitted at the 4th subframe * (once per frame) and interpolated at the 1st, 2nd and 3rd subframe. * * |------|------|------|------| * sf1 sf2 sf3 sf4 * F0 F1 * * sf1: 3/4 F0 + 1/4 F1 sf3: 1/4 F0 + 3/4 F1 * sf2: 1/2 F0 + 1/2 F1 sf4: F1 * *************************************************************************/ void Int_lpc_1to3( Word16 lsp_old[], /* input : LSP vector at the 4th SF of past frame */ Word16 lsp_new[], /* input : LSP vector at the 4th SF of present frame */ Word16 Az[] /* output: interpolated LP parameters in all SFs */ ) { Word16 i; Word16 lsp[M]; for (i = 0; i < M; i++) { lsp[i] = add(shr(lsp_new[i], 2), sub(lsp_old[i], shr(lsp_old[i], 2))); move16 (); } Lsp_Az(lsp, Az); /* Subframe 1 */ Az += MP1; move16 (); for (i = 0; i < M; i++) { lsp[i] = add(shr(lsp_old[i], 1), shr(lsp_new[i], 1)); move16 (); } Lsp_Az(lsp, Az); /* Subframe 2 */ Az += MP1; move16 (); for (i = 0; i < M; i++) { lsp[i] = add(shr(lsp_old[i], 2), sub(lsp_new[i], shr(lsp_new[i], 2))); move16 (); } Lsp_Az(lsp, Az); /* Subframe 3 */ Az += MP1; move16 (); Lsp_Az(lsp_new, Az); /* Subframe 4 */ return; } /************************************************************************* * Function Int_lpc_1to3_2() * Interpolation of the LPC parameters. * Same as the previous function but we do not recompute Az() for * subframe 4 because it is already available. *************************************************************************/ void Int_lpc_1to3_2( Word16 lsp_old[], /* input : LSP vector at the 4th SF of past frame */ Word16 lsp_new[], /* input : LSP vector at the 4th SF of present frame */ Word16 Az[] /* output: interpolated LP parameters in SFs 1,2,3 */ ) { Word16 i; Word16 lsp[M]; for (i = 0; i < M; i++) { lsp[i] = add(shr(lsp_new[i], 2), sub(lsp_old[i], shr(lsp_old[i], 2))); move16 (); } Lsp_Az(lsp, Az); /* Subframe 1 */ Az += MP1; move16 (); for (i = 0; i < M; i++) { lsp[i] = add(shr(lsp_old[i], 1), shr(lsp_new[i], 1)); move16 (); } Lsp_Az(lsp, Az); /* Subframe 2 */ Az += MP1; move16 (); for (i = 0; i < M; i++) { lsp[i] = add(shr(lsp_old[i], 2), sub(lsp_new[i], shr(lsp_new[i], 2))); move16 (); } Lsp_Az(lsp, Az); /* Subframe 3 */ return; }