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