annotate libgsmefr/dec_main.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 18866c0354ef
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
94
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
1 /*
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
2 * This module contains our GSM EFR decoder main function, EFR_decode_params(),
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
3 * that stands at the boundary between our public interface and the guts of
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
4 * ETSI-based codec.
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
5 */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
6
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
7 #include "gsm_efr.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
8 #include "typedef.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
9 #include "namespace.h"
98
18866c0354ef libgsmefr/dec_main.c: need to use official shl() function
Mychaela Falconia <falcon@freecalypso.org>
parents: 94
diff changeset
10 #include "basic_op.h"
94
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
11 #include "cnst.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
12 #include "codec.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
13 #include "sig_proc.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
14 #include "memops.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
15 #include "dec_state.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
16 #include "d_homing.h"
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
17
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
18 /* These constants define the number of consecutive parameters
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
19 that function decoder_homing_frame_test() checks */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
20
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
21 #define WHOLE_FRAME 57
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
22 #define TO_FIRST_SUBFRAME 18
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
23
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
24 void EFR_decode_params(struct EFR_decoder_state *st, const int16_t *params,
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
25 int bfi, int SID_flag, int TAF, int16_t *pcm_out)
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
26 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
27 Word16 *synth = st->synth_buf + M;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
28 Word16 Az_dec[AZ_SIZE];
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
29 Word16 i, temp;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
30 Word16 reset_flag;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
31
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
32 if (!bfi) /* BFI == 0, perform DHF check */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
33 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
34 if (st->reset_flag_old) /* Check for second and further
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
35 successive DHF (to first subfr.) */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
36 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
37 reset_flag = decoder_homing_frame_test (params,
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
38 TO_FIRST_SUBFRAME);
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
39 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
40 else
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
41 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
42 reset_flag = 0;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
43 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
44 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
45 else /* BFI==1, bypass DHF check (frame
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
46 is taken as not being a DHF) */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
47 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
48 reset_flag = 0;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
49 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
50
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
51 if (reset_flag && st->reset_flag_old)
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
52 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
53 /* Force the output to be the encoder homing frame pattern */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
54
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
55 for (i = 0; i < L_FRAME; i++)
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
56 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
57 synth[i] = EHF_MASK;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
58 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
59 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
60 else
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
61 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
62 /* Synthesis */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
63 Decoder_12k2 (st, bfi, params, synth, Az_dec, TAF, SID_flag);
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
64
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
65 Post_Filter (st, synth, Az_dec); /* Post-filter */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
66
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
67 for (i = 0; i < L_FRAME; i++)
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
68 /* Upscale the 15 bit linear PCM to 16 bits,
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
69 then truncate to 13 bits */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
70 {
98
18866c0354ef libgsmefr/dec_main.c: need to use official shl() function
Mychaela Falconia <falcon@freecalypso.org>
parents: 94
diff changeset
71 temp = shl (synth[i], 1);
94
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
72 synth[i] = temp & 0xfff8;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
73 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
74 } /* else */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
75
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
76 Copy (synth, pcm_out, L_FRAME);
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
77
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
78 /* BFI == 0, perform check for first DHF (whole frame) */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
79 if (!bfi && !st->reset_flag_old)
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
80 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
81 reset_flag = decoder_homing_frame_test (params, WHOLE_FRAME);
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
82 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
83
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
84 if (reset_flag)
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
85 {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
86 /* Bring the decoder and receive DTX to the home state */
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
87 EFR_decoder_reset(st);
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
88 } else {
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
89 st->reset_flag_old = 0;
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
90 }
d80e9f12a1d1 libgsmefr: decoder main function put together
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
91 }