FreeCalypso > hg > gsm-codec-lib
comparison libgsmhr1/rxfe.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 | d4979cdbc081 |
children |
comparison
equal
deleted
inserted
replaced
580:d4979cdbc081 | 581:e2d5cad04cbf |
---|---|
220 | 220 |
221 static void cn_output(struct gsmhr_rxfe_state *st, Shortword *prm_out) | 221 static void cn_output(struct gsmhr_rxfe_state *st, Shortword *prm_out) |
222 { | 222 { |
223 int i; | 223 int i; |
224 | 224 |
225 memcpy(prm_out, st->saved_frame, sizeof(Shortword) * 4); | 225 memcpy(prm_out, st->cn_r0_lpc, sizeof(Shortword) * 4); |
226 prm_out[4] = 1; /* soft interpolation */ | 226 prm_out[4] = 1; /* soft interpolation */ |
227 prm_out[5] = 0; /* unvoiced mode */ | 227 prm_out[5] = 0; /* unvoiced mode */ |
228 for (i = 0; i < N_SUB; i++) { | 228 for (i = 0; i < N_SUB; i++) { |
229 prm_out[6 + i * 3] = getPnBits(7, &st->cn_prng); | 229 prm_out[6 + i * 3] = getPnBits(7, &st->cn_prng); |
230 prm_out[7 + i * 3] = getPnBits(7, &st->cn_prng); | 230 prm_out[7 + i * 3] = getPnBits(7, &st->cn_prng); |
274 break; | 274 break; |
275 case CNIFIRSTSID: | 275 case CNIFIRSTSID: |
276 if (dtxd_sp) | 276 if (dtxd_sp) |
277 *dtxd_sp = 0; | 277 *dtxd_sp = 0; |
278 if (frame_class == VALIDSID) | 278 if (frame_class == VALIDSID) |
279 memcpy(st->saved_frame, prm_in, sizeof(Shortword) * 4); | 279 memcpy(st->cn_r0_lpc, prm_in, sizeof(Shortword) * 4); |
280 else | |
281 memcpy(st->cn_r0_lpc, st->saved_frame, | |
282 sizeof(Shortword) * 4); | |
280 init_cn_gen(st); | 283 init_cn_gen(st); |
281 cn_output(st, prm_out); | 284 cn_output(st, prm_out); |
282 break; | 285 break; |
283 case CNICONT: | 286 case CNICONT: |
284 if (dtxd_sp) | 287 if (dtxd_sp) |
285 *dtxd_sp = 0; | 288 *dtxd_sp = 0; |
286 if (frame_class == VALIDSID) | 289 if (frame_class == VALIDSID) |
287 memcpy(st->saved_frame, prm_in, sizeof(Shortword) * 4); | 290 memcpy(st->cn_r0_lpc, prm_in, sizeof(Shortword) * 4); |
288 else | 291 else |
289 deco_mode = CNIBFI; /* for interpolation */ | 292 deco_mode = CNIBFI; /* for interpolation */ |
290 st->dtx_bfi_count = 0; | 293 st->dtx_bfi_count = 0; |
291 st->dtx_muting = 0; | 294 st->dtx_muting = 0; |
292 cn_output(st, prm_out); | 295 cn_output(st, prm_out); |
294 case CNIBFI: | 297 case CNIBFI: |
295 if (dtxd_sp) | 298 if (dtxd_sp) |
296 *dtxd_sp = 0; | 299 *dtxd_sp = 0; |
297 if (st->dtx_muting) { | 300 if (st->dtx_muting) { |
298 if (fast_cn_muting) | 301 if (fast_cn_muting) |
299 st->saved_frame[0] = 0; | 302 st->cn_r0_lpc[0] = 0; |
300 else { | 303 else { |
301 st->saved_frame[0] -= 2; | 304 st->cn_r0_lpc[0] -= 2; |
302 if (st->saved_frame[0] < 0) | 305 if (st->cn_r0_lpc[0] < 0) |
303 st->saved_frame[0] = 0; | 306 st->cn_r0_lpc[0] = 0; |
304 } | 307 } |
305 } | 308 } |
306 st->dtx_bfi_count++; | 309 st->dtx_bfi_count++; |
307 if (st->dtx_bfi_count >= (prm_in[21] ? 25 : 36)) | 310 if (st->dtx_bfi_count >= (prm_in[21] ? 25 : 36)) |
308 st->dtx_muting = 1; | 311 st->dtx_muting = 1; |