comparison doc/FR1-library-API @ 297:6b479cfb06a4

beginning of libgsmfr2 documentation
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 15 Apr 2024 07:12:31 +0000
parents
children a45f806cada9
comparison
equal deleted inserted replaced
296:e0d42e87da96 297:6b479cfb06a4
1 Libgsmfr2 general usage
2 =======================
3
4 The external public interface to Themyscira libgsmfr2 consists of a single
5 header file <tw_gsmfr.h>; it should be installed in some system include
6 directory.
7
8 The dialect of C used by all Themyscira GSM codec libraries is ANSI C (function
9 prototypes), const qualifier is used where appropriate, and the interface is
10 defined in terms of <stdint.h> types; <tw_gsmfr.h> includes <stdint.h>. The
11 use of old libgsm defined types (gsm_byte, gsm_frame and gsm_signal) has been
12 abolished in the migration from libgsm+libgsmfrp to libgsmfr2.
13
14 GSM 06.10 encoder and decoder
15 =============================
16
17 Both the encoder and the decoder are stateful; each running instance of either
18 element needs its own state structure. However, this GSM 06.10 component of
19 libgsmfr2 shares a peculiar property with old libgsm from which it was derived:
20 the same state structure (struct gsmfr_0610_state) is used by both entities.
21 Needless to say, each given instance of struct gsmfr_0610_state must be used
22 for only one purpose, either for the encoder or for the decoder; mixing calls
23 to encoder and decoder functions with the same state structure is an invalid
24 operation with undefined results.
25
26 State structures for the basic encoder or decoder are allocated with this
27 function:
28
29 struct gsmfr_0610_state *gsmfr_0610_create(void);
30
31 This function allocates dynamic memory for the state structure with malloc()
32 (the size of the struct is internal to the library and not exposed) and returns
33 a pointer to the allocated and initialized struct if successful, or NULL if
34 malloc() fails. The state structure is malloc'ed as a single chunk, hence when
35 you are done with it, simply free() it.
36
37 The initialization or reset portion of gsmfr_0610_create() operation can always
38 be repeated with this function:
39
40 void gsmfr_0610_reset(struct gsmfr_0610_state *state);
41
42 Immediately after gsmfr_0610_create() or gsmfr_0610_reset(), the "virgin" state
43 structure can be used either for the encoder or for the decoder; however, once
44 that state struct has been passed to functions of either group, it can only be
45 used for that functional group.
46
47 Encoder specifics
48 -----------------
49
50 The most elementary single-frame processing function of libgsmfr2 GSM 06.10
51 encoder is:
52
53 void gsmfr_0610_encode_params(struct gsmfr_0610_state *st, const int16_t *pcm,
54 struct gsmfr_param_frame *param);
55
56 The input is an array of 160 linear PCM samples (left-justified in int16_t),
57 and the output is this structure:
58
59 struct gsmfr_param_frame {
60 int16_t LARc[8];
61 int16_t Nc[4];
62 int16_t bc[4];
63 int16_t Mc[4];
64 int16_t xmaxc[4];
65 int16_t xMc[4][13];
66 };
67
68 Most of the time the following wrapper function is more useful:
69
70 void gsmfr_0610_encode_frame(struct gsmfr_0610_state *st, const int16_t *pcm,
71 uint8_t *frame);
72
73 The output is a 33-byte buffer, filled with the encoded GSM-FR speech frame in
74 the RTP format specified in ETSI TS 101 318 and IETF RFC 3551.
75
76 If the optional encoder homing feature is desired, call this function right
77 after the call to gsmfr_0610_encode_frame() or gsmfr_0610_encode_params():
78
79 void gsmfr_0610_encoder_homing(struct gsmfr_0610_state *st, const int16_t *pcm);
80
81 This function checks to see if the PCM frame (160 linear PCM samples) is an EHF;
82 if the input frame is indeed EHF, the function calls gsmfr_0610_reset().
83
84 Decoder specifics
85 -----------------
86
87 The internal native form of the 06.10 decoder once again uses
88 struct gsmfr_param_frame:
89
90 void gsmfr_0610_decode_params(struct gsmfr_0610_state *st,
91 const struct gsmfr_param_frame *param,
92 int16_t *pcm);
93
94 The more commonly used RTP-format version is:
95
96 void gsmfr_0610_decode_frame(struct gsmfr_0610_state *st, const uint8_t *frame,
97 int16_t *pcm);
98
99 Please note:
100
101 1) The basic GSM 06.10 decoder is just that: there is no SID recognition or DTX
102 handling, every possible input bit pattern will be interpreted and decoded
103 as a GSM 06.10 speech frame.
104
105 2) There is no decoder homing function at this layer, and no check for DHF.
106
107 3) The RTP signature nibble 0xD is ignored (not checked) by
108 gsmfr_0610_decode_frame().
109
110 Rx DTX preprocessor block
111 =========================
112
113 The Rx DTX preprocessor is its own stateful element, independent from the 06.10
114 decoder to which it is usually coupled. Libgsmfr2 provides a "fulldec" wrapper
115 that incorporates both elements, but the ability to use the Rx DTX preprocessor
116 by itself still remains, unchanged from our previous libgsmfrp offering. One
117 potential application for this preprocessor by itself, without immediately
118 following it with the GSM 06.10 decode step, is the possibility of implementing
119 the TFO/TrFO transform of 3GPP TS 28.062 section C.3.2.1.1 for GSM-FR: our Rx
120 DTX preprocessor does exactly what that section calls for, specifically in
121 "case 1" where the input UL frame stream may contain SIDs and BFI frame gaps,
122 but the output must be 100% valid frames and SID-free.
123
124 The state structure for this block is struct gsmfr_preproc_state, and it is
125 allocated with this function:
126
127 struct gsmfr_preproc_state *gsmfr_preproc_create(void);
128
129 Like other state structures in Themyscira GSM codec libraries, this opaque
130 state is malloc'ed as a single chunk and can be simply freed afterward. A
131 reset function is also provided:
132
133 void gsmfr_preproc_reset(struct gsmfr_preproc_state *state);
134
135 Preprocessing good frames
136 -------------------------
137
138 For every good traffic frame (BFI=0) you receive from the radio subsystem, you
139 need to call this preprocessor function:
140
141 void gsmfr_preproc_good_frame(struct gsmfr_preproc_state *state,
142 uint8_t *frame);
143
144 The second argument is both input and output, i.e., the frame is modified in
145 place. If the received frame is not SID (specifically, if the SID field
146 deviates from the SID codeword by 16 or more bits, per GSM 06.31 section 6.1.1),
147 then the frame (considered a good speech frame) will be left unmodified (i.e.,
148 it is to be passed unchanged to the GSM 06.10 decoder), but preprocessor state
149 will be updated. OTOH, if the received frame is classified as either valid or
150 invalid SID per GSM 06.31, then the output frame will contain comfort noise
151 generated by the preprocessor using a PRNG, or a silence frame in one particular
152 corner case.
153
154 GSM-FR RTP (originally libgsm) 0xD magic: the upper nibble of the first byte
155 can be anything on input to gsmfr_preproc_good_frame(), but the output frame
156 will always have the correct magic in it.
157
158 Handling BFI conditions
159 -----------------------
160
161 If you received a lost/missing frame indication instead of a good traffic frame,
162 call this preprocessor function:
163
164 void gsmfr_preproc_bfi(struct gsmfr_preproc_state *state, int taf,
165 uint8_t *frame_out);
166
167 TAF is a flag defined in GSM 06.31 section 6.1.1; if you don't have this flag,
168 pass 0 - you will lose the function of comfort noise muting in the event of
169 prolonged SID loss, but all other Rx DTX functions will still work the same.
170
171 With this function the 33-byte frame buffer is only an output, i.e., prior
172 buffer content is a don't-care and there is no provision for making any use of
173 erroneous frames like in EFR. The frame generated by the preprocessor may be
174 substitution/muting, comfort noise or silence depending on the state.
175
176 GSM-FR full decoder
177 ===================
178
179 The full decoder is a high-level feature of libgsmfr2, incorporating both the
180 Rx DTX preprocessor block and the GSM 06.10 decoder block. The state structure
181 for the full decoder (struct gsmfr_fulldec_state) internally incorporates both
182 struct gsmfr_0610_state and gsmfr_preproc_state, but because it is implemented
183 inside libgsmfr2, it is still malloc'ed as a single chunk and can thus be
184 released with a single free() call. The functions for allocating and
185 initializing this state follow the established pattern:
186
187 struct gsmfr_fulldec_state *gsmfr_fulldec_create(void);
188
189 void gsmfr_fulldec_reset(struct gsmfr_fulldec_state *state);
190
191 The reset function internally calls gsmfr_0610_reset() and
192 gsmfr_preproc_reset(), initializing both processing blocks.
193
194 Frame processing functions are also straightforward:
195
196 void gsmfr_fulldec_good_frame(struct gsmfr_fulldec_state *state,
197 const uint8_t *frame, int16_t *pcm);
198
199 void gsmfr_fulldec_bfi(struct gsmfr_fulldec_state *state, int taf,
200 int16_t *pcm);
201
202 These functions follow the same pattern as gsmfr_preproc_good_frame() and
203 gsmfr_preproc_bfi(), but the output is a 160-sample linear PCM buffer. Also
204 note that the frame input to gsmfr_fulldec_good_frame() is const, unlike the
205 situation with gsmfr_preproc_good_frame() - the copying into a scratchpad
206 buffer (on the stack) happens inside this "fulldec" wrapper.
207
208 The "fulldec" layer also adds the decoder homing feature:
209 gsmfr_fulldec_good_frame() detects decoder homing frames and invokes
210 gsmfr_fulldec_reset() when required, and also implements EHF output per the
211 spec.