FreeCalypso > hg > gsm-codec-lib
comparison doc/EFR-library-API @ 123:92fdb499b5c3
doc/EFR-library-API article written
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sat, 10 Dec 2022 22:01:14 +0000 |
| parents | |
| children | 1c529bb31219 |
comparison
equal
deleted
inserted
replaced
| 122:b33f2168fdec | 123:92fdb499b5c3 |
|---|---|
| 1 The external public interface to Themyscira libgsmefr consists of a single | |
| 2 header file <gsm_efr.h>; it should be installed in the same system include | |
| 3 directory as <gsm.h> from classic libgsm (1990s free software product) for the | |
| 4 original FR codec, and the API of libgsmefr is modeled after that of libgsm. | |
| 5 | |
| 6 The dialect of C we chose for libgsmefr is ANSI C (function prototypes), const | |
| 7 qualifier is used where appropriate, and the interface is defined in terms of | |
| 8 <stdint.h> types; <gsm_efr.h> includes <stdint.h>. | |
| 9 | |
| 10 State allocation and freeing | |
| 11 ============================ | |
| 12 | |
| 13 In order to use the EFR encoder, you will need to allocate an encoder state | |
| 14 structure, and to use the EFR decoder, you will need to allocate a decoder state | |
| 15 structure. The necessary state allocation functions are: | |
| 16 | |
| 17 extern struct EFR_encoder_state *EFR_encoder_create(int dtx); | |
| 18 extern struct EFR_decoder_state *EFR_decoder_create(void); | |
| 19 | |
| 20 struct EFR_encoder_state and struct EFR_decoder_state are opaque structures to | |
| 21 library users: you only get pointers which you remember and pass around, but | |
| 22 <gsm_efr.h> does not give you full definitions of these structs. As a library | |
| 23 user, you don't even get to know the size of these structs, hence the necessary | |
| 24 malloc() operation happens inside EFR_encoder_create() and EFR_decoder_create(). | |
| 25 However, each structure is malloc'ed as a single chunk, hence when you are done | |
| 26 with it, simply call free() to relinquish each encoder or decoder state | |
| 27 instance. | |
| 28 | |
| 29 EFR_encoder_create() and EFR_decoder_create() functions can fail if the malloc() | |
| 30 call inside fails, in which case the two libgsmefr functions in question return | |
| 31 NULL. | |
| 32 | |
| 33 The dtx argument to EFR_encoder_create() is a Boolean flag represented as an | |
| 34 int; it tells the EFR encoder whether it should operate with DTX enabled (run | |
| 35 GSM 06.82 VAD and emit SID frames instead of speech frames per GSM 06.81) or DTX | |
| 36 disabled (skip VAD and always emit speech frames). | |
| 37 | |
| 38 Using the EFR encoder | |
| 39 ===================== | |
| 40 | |
| 41 To encode one 20 ms audio frame per EFR, call EFR_encode_frame(): | |
| 42 | |
| 43 extern void EFR_encode_frame(struct EFR_encoder_state *st, const int16_t *pcm, | |
| 44 uint8_t *frame, int *sp, int *vad); | |
| 45 | |
| 46 You need to provide an encoder state structure allocated earlier with | |
| 47 EFR_encoder_create(), a block of 160 linear PCM samples, and an output buffer of | |
| 48 31 bytes (EFR_RTP_FRAME_LEN constant also defined in <gsm_efr.h>) into which the | |
| 49 encoded EFR frame will be written; the frame format is that defined in ETSI TS | |
| 50 101 318 for EFR in RTP, including the 0xC signature in the upper nibble of the | |
| 51 first byte. | |
| 52 | |
| 53 The last two arguments of type (int *) are optional pointers to extra output | |
| 54 flags SP and VAD, defined in GSM 06.81 section 5.1.1; either pointer or both of | |
| 55 them can be NULL if these extra output flags aren't needed. Both of these flags | |
| 56 are needed in order to test our libgsmefr encoder implementation against | |
| 57 official ETSI test sequences (GSM 06.54), but they typically aren't needed | |
| 58 otherwise. | |
| 59 | |
| 60 Using the EFR decoder | |
| 61 ===================== | |
| 62 | |
| 63 The main interface to our EFR decoder is this function: | |
| 64 | |
| 65 extern void EFR_decode_frame(struct EFR_decoder_state *st, const uint8_t *frame, | |
| 66 int bfi, int taf, int16_t *pcm); | |
| 67 | |
| 68 The inputs consist of 244 bits of frame payload (the 4 upper bits of the first | |
| 69 byte are ignored - there is NO enforcement of 0xC signature in our frame | |
| 70 decoder) and BFI and TAF flags defined in GSM 06.81 section 6.1.1. Note the | |
| 71 absence of a SID flag argument: EFR_decode_frame() calls our own utility | |
| 72 function EFR_sid_classify() to determine SID from the frame itself per the rules | |
| 73 of GSM 06.81 section 6.1.1. | |
| 74 | |
| 75 Many EFR decoder applications will also be faced with a situation where they | |
| 76 receive a frame gap (no data at all), and they need to run the EFR decoder with | |
| 77 BFI=1, but don't have any frame-bits input. If you find yourself in this | |
| 78 situation, call the following function: | |
| 79 | |
| 80 extern void EFR_decode_bfi_nodata(struct EFR_decoder_state *st, int taf, | |
| 81 int16_t *pcm); | |
| 82 | |
| 83 EFR_decode_bfi_nodata() is equivalent to calling EFR_decode_frame() with a frame | |
| 84 buffer of 31 zero bytes (or 0xC signature followed by 244 zero bits) and BFI=1, | |
| 85 but is slightly more efficient in that the internal steps of EFR_frame2params() | |
| 86 and EFR_sid_classify() are skipped, and the made-up "frame" of 244 zero bits is | |
| 87 passed to the decoder core at the params array level. | |
| 88 | |
| 89 Note that the official EFR decoder from ETSI, which we've replicated in our | |
| 90 librified form in libgsmefr, does make use of some presumed-invalid frame data | |
| 91 bits under BFI=1 conditions: see the description in GSM 06.61 section 6.1, where | |
| 92 the last sentence reads "The received fixed codebook excitation pulses from the | |
| 93 erroneous frame are always used as such." With our current implementation, the | |
| 94 "erroneous frame" in the case of completely lost or missing frames is a made-up | |
| 95 frame of 244 zero bits; the question of whether this approach is good enough or | |
| 96 if we need to do something more complex remains for further study. | |
| 97 | |
| 98 Stateless utility functions | |
| 99 =========================== | |
| 100 | |
| 101 All functions in this section are stateless (no encoder state or decoder state | |
| 102 structure is needed); they merely manipulate bit fields. | |
| 103 | |
| 104 extern void EFR_frame2params(const uint8_t *frame, int16_t *params); | |
| 105 | |
| 106 This function unpacks an EFR codec frame in ETSI TS 101 318 RTP encoding (the | |
| 107 upper nibble of the first byte is NOT checked, i.e., there is NO enforcement of | |
| 108 0xC signature) into an array of 57 (EFR_NUM_PARAMS) parameter words for the | |
| 109 codec. int16_t signed type is used for the params array (even though all | |
| 110 parameters are actually unsigned) in order to match the guts of ETSI-based EFR | |
| 111 codec, and EFR_frame2params() is called internally by EFR_decode_frame(). | |
| 112 | |
| 113 extern void EFR_params2frame(const int16_t *params, uint8_t *frame); | |
| 114 | |
| 115 This function takes an array of 57 (EFR_NUM_PARAMS) EFR codec parameter words | |
| 116 and packs them into a 31-byte (EFR_RTP_FRAME_LEN) frame in ETSI TS 101 318 | |
| 117 format. The 0xC signature is generated by this function, and every byte of the | |
| 118 output buffer is fully written without regard to any previous content. This | |
| 119 function is called internally by EFR_encode_frame(). | |
| 120 | |
| 121 extern int EFR_sid_classify(const uint8_t *frame); | |
| 122 | |
| 123 This function analyzes an RTP-encoded EFR frame (the upper nibble of the first | |
| 124 byte is NOT checked for 0xC signature) for the SID codeword of GSM 06.62 and | |
| 125 classifies the frame as SID=0, SID=1 or SID=2 per the rules of GSM 06.81 | |
| 126 section 6.1.1. | |
| 127 | |
| 128 extern void EFR_insert_sid_codeword(uint8_t *frame); | |
| 129 | |
| 130 This function inserts the SID codeword of GSM 06.62 into the frame in the | |
| 131 pointed-to buffer; specifically, the 95 bits that make up the SID field are all | |
| 132 set to 1s, but all other bits remain unchanged. This function is arguably least | |
| 133 useful to external users of libgsmefr, but it exists because of how the original | |
| 134 code from ETSI generates SID frames produced by the encoder in DTX mode. | |
| 135 | |
| 136 Parameter-based encoder and decoder functions | |
| 137 ============================================= | |
| 138 | |
| 139 The EFR_encode_frame() and EFR_decode_frame() functions described earlier in | |
| 140 this document constitute the most practically useful (intended for actual use) | |
| 141 interfaces to our EFR encoder and decoder, but they are actually wrappers around | |
| 142 these parameter-based functions: | |
| 143 | |
| 144 extern void EFR_encode_params(struct EFR_encoder_state *st, const int16_t *pcm, | |
| 145 int16_t *params, int *sp, int *vad); | |
| 146 | |
| 147 This function is similar to EFR_encode_frame(), but the output is an array of | |
| 148 57 (EFR_NUM_PARAMS) codec parameter words rather than a finished frame. The two | |
| 149 extra output flags are optional (pointers may be NULL) just like with | |
| 150 EFR_encode_frame(), but there is a catch: if the output frame is a SID (which | |
| 151 can only happen if DTX is enabled), the bits inside parameter words that would | |
| 152 correspond to SID codeword bits are NOT set, instead one MUST call | |
| 153 EFR_insert_sid_codeword() after packing the frame with EFR_params2frame(). The | |
| 154 wrapper in EFR_encode_frame() does exactly as described, and the overall logic | |
| 155 follows the original code structure from ETSI. | |
| 156 | |
| 157 extern void EFR_decode_params(struct EFR_decoder_state *st, | |
| 158 const int16_t *params, int bfi, int sid, int taf, | |
| 159 int16_t *pcm); | |
| 160 | |
| 161 This function is similar to EFR_decode_frame() with the frame input replaced | |
| 162 with params array input, but the SID classification per the rules of GSM 06.81 | |
| 163 section 6.1.1 needs to be provided by the caller. The wrapper in | |
| 164 EFR_decode_frame() calls both EFR_frame2params() and EFR_sid_classify() before | |
| 165 passing the work to EFR_decode_params(). | |
| 166 | |
| 167 State reset functions | |
| 168 ===================== | |
| 169 | |
| 170 extern void EFR_encoder_reset(struct EFR_encoder_state *st, int dtx); | |
| 171 extern void EFR_decoder_reset(struct EFR_decoder_state *st); | |
| 172 | |
| 173 These functions reset the state of the encoder or the decoder, respectively; | |
| 174 the entire state structure is fully initialized to the respective home state | |
| 175 defined in GSM 06.60 section 8.5 for the encoder or section 8.6 for the decoder. | |
| 176 | |
| 177 EFR_encoder_reset() is called internally by EFR_encoder_create() and by the | |
| 178 encoder itself when it encounters the ETSI-prescribed encoder homing frame; | |
| 179 EFR_decoder_reset() is called internally by EFR_decoder_create() and by the | |
| 180 decoder itself when it encounters the ETSI-prescribed decoder homing frame. | |
| 181 Therefore, there is generally no need for libgsmefr users to call these | |
| 182 functions directly - but they are made public for the sake of completeness. |
