libosmocore/src/codec/gsm660.c

418 lines
16 KiB
C

/*! \file gsm660.c
* GSM 06.60 - GSM EFR Codec. */
/*
* (C) 2010 Sylvain Munaut <tnt@246tNt.com>
*
* All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <stdint.h>
#include <stdbool.h>
#include <osmocom/core/bitvec.h>
#include <osmocom/core/utils.h>
#include <osmocom/codec/codec.h>
/* GSM EFR - subjective importance bit ordering */
/* This array encodes GSM 05.03 Table 6.
*
* It converts between serial parameter output (as described in
* GSM 06.60 Table 6 and GSM 05.03 Table 5) and the order needed
* before channel encoding. CRC poly and bit repetition must be
* applied prior to this table, as in GSM 05.03 3.1.1, to get 260
* bits from a 244 bits raw EFR frame.
*/
const uint16_t gsm660_bitorder[260] = {
38, 39, 40, 41, 42, 43, /* 0 -> LTP-LAG 1: b8..b3 */
145, 146, 147, 148, 149, 150, /* 6 -> LTP-LAG 3: b8..b3 */
93, 94, /* 12 -> LTP-LAG 2: b5..b4 */
200, 201, /* 14 -> LTP-LAG 4: b5..b4 */
47, /* 16 -> LTP-GAIN 1: b3 */
88, /* 17 -> FCB-GAIN 1: b4 */
99, /* 18 -> LTP-GAIN 2: b3 */
140, /* 19 -> FCB-GAIN 2: b4 */
44, /* 20 -> LTP-LAG 1: b2 */
151, /* 21 -> LTP-LAG 3: b2 */
95, /* 22 -> LTP-LAG 2: b3 */
202, /* 23 -> LTP-LAG 4: b3 */
1, 2, /* 24 -> LPC 1: b5..b4 */
7, /* 26 -> LPC 2: b7 */
9, /* 27 -> LPC 2: b5 */
17, 18, /* 28 -> LPC 3: b6..b5 */
23, /* 30 -> LPC 3: b0 */
45, 46, /* 31 -> LTP-LAG 1: b1..b0 */
152, 153, /* 33 -> LTP-LAG 3: b1..b0 */
96, /* 35 -> LTP-LAG 2: b2 */
203, /* 36 -> LTP-LAG 4: b2 */
3, 4, /* 37 -> LPC 1: b3..b2 */
10, 11, /* 39 -> LPC 2: b4..b3 */
15, /* 41 -> LPC 3: b8 */
8, /* 42 -> LPC 2: b6 */
5, 6, /* 43 -> LPC 1: b1..b0 */
12, /* 45 -> LPC 2: b2 */
16, /* 46 -> LPC 3: b7 */
19, /* 47 -> LPC 3: b4 */
97, /* 48 -> LTP-LAG 2: b1 */
204, /* 49 -> LTP-LAG 4: b1 */
0, /* 50 -> LPC 1: b6 */
13, 14, /* 51 -> LPC 2: b1..b0 */
20, /* 53 -> LPC 3: b3 */
24, 25, /* 54 -> LPC 4: b7..b6 */
27, /* 56 -> LPC 4: b4 */
154, /* 57 -> LTP-GAIN 3: b3 */
206, /* 58 -> LTP-GAIN 4: b3 */
195, /* 59 -> FCB-GAIN 3: b4 */
247, /* 60 -> FCB-GAIN 4: b4 */
89, /* 61 -> FCB-GAIN 1: b3 */
141, /* 62 -> FCB-GAIN 2: b3 */
196, /* 63 -> FCB-GAIN 3: b3 */
248, /* 64 -> FCB-GAIN 4: b3 */
252, 253, 254, 255, 256, 257, 258, 259, /* 65 -> CRC-POLY: b7..b0 */
48, /* 73 -> LTP-GAIN 1: b2 */
100, /* 74 -> LTP-GAIN 2: b2 */
155, /* 75 -> LTP-GAIN 3: b2 */
207, /* 76 -> LTP-GAIN 4: b2 */
21, 22, /* 77 -> LPC 3: b2..b1 */
26, /* 79 -> LPC 4: b5 */
28, /* 80 -> LPC 4: b3 */
51, /* 81 -> PULSE 1_1: b3 */
55, /* 82 -> PULSE 1_2: b3 */
59, /* 83 -> PULSE 1_3: b3 */
63, /* 84 -> PULSE 1_4: b3 */
67, /* 85 -> PULSE 1_5: b3 */
103, /* 86 -> PULSE 2_1: b3 */
107, /* 87 -> PULSE 2_2: b3 */
111, /* 88 -> PULSE 2_3: b3 */
115, /* 89 -> PULSE 2_4: b3 */
119, /* 90 -> PULSE 2_5: b3 */
158, /* 91 -> PULSE 3_1: b3 */
162, /* 92 -> PULSE 3_2: b3 */
166, /* 93 -> PULSE 3_3: b3 */
170, /* 94 -> PULSE 3_4: b3 */
174, /* 95 -> PULSE 3_5: b3 */
210, /* 96 -> PULSE 4_1: b3 */
214, /* 97 -> PULSE 4_2: b3 */
218, /* 98 -> PULSE 4_3: b3 */
222, /* 99 -> PULSE 4_4: b3 */
226, /* 100 -> PULSE 4_5: b3 */
90, /* 101 -> FCB-GAIN 1: b2 */
142, /* 102 -> FCB-GAIN 2: b2 */
197, /* 103 -> FCB-GAIN 3: b2 */
249, /* 104 -> FCB-GAIN 4: b2 */
49, /* 105 -> LTP-GAIN 1: b1 */
101, /* 106 -> LTP-GAIN 2: b1 */
156, /* 107 -> LTP-GAIN 3: b1 */
208, /* 108 -> LTP-GAIN 4: b1 */
29, 30, 31, /* 109 -> LPC 4: b2..b0 */
32, 33, 34, 35, /* 112 -> LPC 5: b5..b2 */
98, /* 116 -> LTP-LAG 2: b0 */
205, /* 117 -> LTP-LAG 4: b0 */
52, /* 118 -> PULSE 1_1: b2 */
56, /* 119 -> PULSE 1_2: b2 */
60, /* 120 -> PULSE 1_3: b2 */
64, /* 121 -> PULSE 1_4: b2 */
68, /* 122 -> PULSE 1_5: b2 */
104, /* 123 -> PULSE 2_1: b2 */
108, /* 124 -> PULSE 2_2: b2 */
112, /* 125 -> PULSE 2_3: b2 */
116, /* 126 -> PULSE 2_4: b2 */
120, /* 127 -> PULSE 2_5: b2 */
159, /* 128 -> PULSE 3_1: b2 */
163, /* 129 -> PULSE 3_2: b2 */
167, /* 130 -> PULSE 3_3: b2 */
171, /* 131 -> PULSE 3_4: b2 */
175, /* 132 -> PULSE 3_5: b2 */
211, /* 133 -> PULSE 4_1: b2 */
215, /* 134 -> PULSE 4_2: b2 */
219, /* 135 -> PULSE 4_3: b2 */
223, /* 136 -> PULSE 4_4: b2 */
227, /* 137 -> PULSE 4_5: b2 */
53, /* 138 -> PULSE 1_1: b1 */
57, /* 139 -> PULSE 1_2: b1 */
61, /* 140 -> PULSE 1_3: b1 */
65, /* 141 -> PULSE 1_4: b1 */
105, /* 142 -> PULSE 2_1: b1 */
109, /* 143 -> PULSE 2_2: b1 */
113, /* 144 -> PULSE 2_3: b1 */
117, /* 145 -> PULSE 2_4: b1 */
160, /* 146 -> PULSE 3_1: b1 */
164, /* 147 -> PULSE 3_2: b1 */
168, /* 148 -> PULSE 3_3: b1 */
172, /* 149 -> PULSE 3_4: b1 */
212, /* 150 -> PULSE 4_1: b1 */
220, /* 151 -> PULSE 4_3: b1 */
224, /* 152 -> PULSE 4_4: b1 */
91, /* 153 -> FCB-GAIN 1: b1 */
143, /* 154 -> FCB-GAIN 2: b1 */
198, /* 155 -> FCB-GAIN 3: b1 */
250, /* 156 -> FCB-GAIN 4: b1 */
50, /* 157 -> LTP-GAIN 1: b0 */
102, /* 158 -> LTP-GAIN 2: b0 */
157, /* 159 -> LTP-GAIN 3: b0 */
209, /* 160 -> LTP-GAIN 4: b0 */
92, /* 161 -> FCB-GAIN 1: b0 */
144, /* 162 -> FCB-GAIN 2: b0 */
199, /* 163 -> FCB-GAIN 3: b0 */
251, /* 164 -> FCB-GAIN 4: b0 */
54, /* 165 -> PULSE 1_1: b0 */
58, /* 166 -> PULSE 1_2: b0 */
62, /* 167 -> PULSE 1_3: b0 */
66, /* 168 -> PULSE 1_4: b0 */
106, /* 169 -> PULSE 2_1: b0 */
110, /* 170 -> PULSE 2_2: b0 */
114, /* 171 -> PULSE 2_3: b0 */
118, /* 172 -> PULSE 2_4: b0 */
161, /* 173 -> PULSE 3_1: b0 */
165, /* 174 -> PULSE 3_2: b0 */
169, /* 175 -> PULSE 3_3: b0 */
173, /* 176 -> PULSE 3_4: b0 */
213, /* 177 -> PULSE 4_1: b0 */
221, /* 178 -> PULSE 4_3: b0 */
225, /* 179 -> PULSE 4_4: b0 */
36, 37, /* 180 -> LPC 5: b1..b0 */
69, /* 182 -> PULSE 1_5: b1 */
71, 72, /* 183 -> PULSE 1_5: b1..b1 */
121, /* 185 -> PULSE 2_5: b1 */
123, 124, /* 186 -> PULSE 2_5: b1..b1 */
176, /* 188 -> PULSE 3_5: b1 */
178, 179, /* 189 -> PULSE 3_5: b1..b1 */
228, /* 191 -> PULSE 4_5: b1 */
230, 231, /* 192 -> PULSE 4_5: b1..b1 */
216, 217, /* 194 -> PULSE 4_2: b1..b0 */
70, /* 196 -> PULSE 1_5: b0 */
122, /* 197 -> PULSE 2_5: b0 */
177, /* 198 -> PULSE 3_5: b0 */
229, /* 199 -> PULSE 4_5: b0 */
73, /* 200 -> PULSE 1_6: b2 */
76, /* 201 -> PULSE 1_7: b2 */
79, /* 202 -> PULSE 1_8: b2 */
82, /* 203 -> PULSE 1_9: b2 */
85, /* 204 -> PULSE 1_10: b2 */
125, /* 205 -> PULSE 2_6: b2 */
128, /* 206 -> PULSE 2_7: b2 */
131, /* 207 -> PULSE 2_8: b2 */
134, /* 208 -> PULSE 2_9: b2 */
137, /* 209 -> PULSE 2_10: b2 */
180, /* 210 -> PULSE 3_6: b2 */
183, /* 211 -> PULSE 3_7: b2 */
186, /* 212 -> PULSE 3_8: b2 */
189, /* 213 -> PULSE 3_9: b2 */
192, /* 214 -> PULSE 3_10: b2 */
232, /* 215 -> PULSE 4_6: b2 */
235, /* 216 -> PULSE 4_7: b2 */
238, /* 217 -> PULSE 4_8: b2 */
241, /* 218 -> PULSE 4_9: b2 */
244, /* 219 -> PULSE 4_10: b2 */
74, /* 220 -> PULSE 1_6: b1 */
77, /* 221 -> PULSE 1_7: b1 */
80, /* 222 -> PULSE 1_8: b1 */
83, /* 223 -> PULSE 1_9: b1 */
86, /* 224 -> PULSE 1_10: b1 */
126, /* 225 -> PULSE 2_6: b1 */
129, /* 226 -> PULSE 2_7: b1 */
132, /* 227 -> PULSE 2_8: b1 */
135, /* 228 -> PULSE 2_9: b1 */
138, /* 229 -> PULSE 2_10: b1 */
181, /* 230 -> PULSE 3_6: b1 */
184, /* 231 -> PULSE 3_7: b1 */
187, /* 232 -> PULSE 3_8: b1 */
190, /* 233 -> PULSE 3_9: b1 */
193, /* 234 -> PULSE 3_10: b1 */
233, /* 235 -> PULSE 4_6: b1 */
236, /* 236 -> PULSE 4_7: b1 */
239, /* 237 -> PULSE 4_8: b1 */
242, /* 238 -> PULSE 4_9: b1 */
245, /* 239 -> PULSE 4_10: b1 */
75, /* 240 -> PULSE 1_6: b0 */
78, /* 241 -> PULSE 1_7: b0 */
81, /* 242 -> PULSE 1_8: b0 */
84, /* 243 -> PULSE 1_9: b0 */
87, /* 244 -> PULSE 1_10: b0 */
127, /* 245 -> PULSE 2_6: b0 */
130, /* 246 -> PULSE 2_7: b0 */
133, /* 247 -> PULSE 2_8: b0 */
136, /* 248 -> PULSE 2_9: b0 */
139, /* 249 -> PULSE 2_10: b0 */
182, /* 250 -> PULSE 3_6: b0 */
185, /* 251 -> PULSE 3_7: b0 */
188, /* 252 -> PULSE 3_8: b0 */
191, /* 253 -> PULSE 3_9: b0 */
194, /* 254 -> PULSE 3_10: b0 */
234, /* 255 -> PULSE 4_6: b0 */
237, /* 256 -> PULSE 4_7: b0 */
240, /* 257 -> PULSE 4_8: b0 */
243, /* 258 -> PULSE 4_9: b0 */
246, /* 259 -> PULSE 4_10: b0 */
};
static const uint8_t sid_code_word_bits[95] = {
/* bit numbers are relative to "pure" EFR frame beginning,
* not counting the signature bits. */
45, 46, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 94, 95, 96, 98, 99, 100, 101,
102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 148, 149, 150,
151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
161, 162, 163, 164, 165, 166, 167, 168, 169, 170,
171, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 212, 213, 214, 215, 216,
217, 218, 219, 220, 221
};
/*! Check whether RTP frame contains EFR SID code word according to
* TS 101 318 §5.3.2
* \param[in] rtp_payload Buffer with RTP payload
* \param[in] payload_len Length of payload
* \returns true if code word is found, false otherwise
*/
bool osmo_efr_check_sid(const uint8_t *rtp_payload, size_t payload_len)
{
struct bitvec bv;
uint16_t i;
/* signature does not match Enhanced Full Rate SID */
if ((rtp_payload[0] >> 4) != 0xC)
return false;
bv.data = (uint8_t *) rtp_payload;
bv.data_len = payload_len;
/* code word is all 1 at given bits */
for (i = 0; i < ARRAY_SIZE(sid_code_word_bits); i++) {
if (bitvec_get_bit_pos(&bv, sid_code_word_bits[i]+4) != ONE)
return false;
}
return true;
}
/*! Classify potentially-SID EFR codec frame in RTP format according
* to the rules of GSM 06.81 §6.1.1
* \param[in] rtp_payload Buffer with RTP payload
* \returns enum osmo_gsm631_sid_class, with symbolic values
* OSMO_GSM631_SID_CLASS_SPEECH, OSMO_GSM631_SID_CLASS_INVALID or
* OSMO_GSM631_SID_CLASS_VALID corresponding to the 3 possible bit-counting
* classifications prescribed by the spec.
*
* Differences between the more familiar osmo_efr_check_sid() and the present
* function are:
*
* 1. osmo_efr_check_sid() returns true only if the SID frame is absolutely
* perfect, with all 95 bits of the SID code word set. However, the
* rules of GSM 06.81 §6.1.1 allow up to one bit to be in error,
* and the frame is still accepted as valid SID.
*
* 2. The third possible state of invalid SID is not handled at all by the
* simpler osmo_efr_check_sid() function.
*
* 3. osmo_efr_check_sid() includes a check for 0xC RTP signature, and returns
* false if that signature nibble is wrong. That check is not included
* in the present version because there is no place for it in the
* ETSI-prescribed classification, it is neither speech nor SID. The
* assumption is that this function is used to classify the bit content
* of received codec frames, not their RTP encoding - the latter needs
* to be validated beforehand.
*
* Which function should one use? The answer depends on the specific
* circumstances, and needs to be addressed on a case-by-case basis.
*/
enum osmo_gsm631_sid_class osmo_efr_sid_classify(const uint8_t *rtp_payload)
{
struct bitvec bv;
uint16_t i, n;
bv.data = (uint8_t *) rtp_payload;
bv.data_len = GSM_EFR_BYTES;
/* count not-SID-matching bits per the spec */
n = 0;
for (i = 0; i < ARRAY_SIZE(sid_code_word_bits); i++) {
if (bitvec_get_bit_pos(&bv, sid_code_word_bits[i]+4) != ONE)
n++;
if (n >= 16)
return OSMO_GSM631_SID_CLASS_SPEECH;
}
if (n >= 2)
return OSMO_GSM631_SID_CLASS_INVALID;
else
return OSMO_GSM631_SID_CLASS_VALID;
}
/*! Reset the SID field of a potentially corrupted, but still valid GSM-EFR
* SID frame in RTP encoding to its pristine state (full SID code word).
* \param[in] rtp_payload Buffer with RTP payload - must be writable!
*
* Per GSM 06.62 section 5.3, a freshly minted SID frame consists of 58 bits
* of comfort noise parameters (LSF and 4 times fixed codebook gain), 95 bits
* of SID code word (all 1s) and 91 unused bits (all 0s). Network elements
* that receive SID frames from call leg A uplink and need to retransmit them
* on leg B downlink should "rejuvenate" received SID frames prior to
* retransmission by resetting the SID field to its pristine state of all 1s;
* this function does the job.
*
* Potential TODO: it would be nice to also zero out the remaining 91 bits
* which the spec leaves as reserved, clearing out leg A radio bit errors -
* but do we really need to?
*/
void osmo_efr_sid_reset(uint8_t *rtp_payload)
{
/* set all 95 SID code word bits to 1 */
rtp_payload[6] |= 0x6F;
rtp_payload[7] = 0xFF;
rtp_payload[8] = 0xFF;
rtp_payload[9] |= 0x80;
rtp_payload[12] |= 0x3B;
rtp_payload[13] = 0xFF;
rtp_payload[14] = 0xFF;
rtp_payload[15] |= 0xE0;
rtp_payload[19] = 0xFF;
rtp_payload[20] = 0xFF;
rtp_payload[21] = 0xFF;
rtp_payload[25] = 0xFF;
rtp_payload[26] |= 0xFC;
rtp_payload[27] = 0xFF;
rtp_payload[28] |= 0xC0;
}
/*! Preen potentially-SID EFR codec frame in RTP format, ensuring that it is
* either a speech frame or a valid SID, and if the latter, making it a
* perfect, error-free SID frame.
* \param[in] rtp_payload Buffer with RTP payload - must be writable!
* \returns true if the frame is good, false otherwise
*/
bool osmo_efr_sid_preen(uint8_t *rtp_payload)
{
enum osmo_gsm631_sid_class sidc;
sidc = osmo_efr_sid_classify(rtp_payload);
switch (sidc) {
case OSMO_GSM631_SID_CLASS_SPEECH:
return true;
case OSMO_GSM631_SID_CLASS_INVALID:
return false;
case OSMO_GSM631_SID_CLASS_VALID:
/* "Rejuvenate" this SID frame, correcting any errors */
osmo_efr_sid_reset(rtp_payload);
return true;
default:
/* There are only 3 possible SID classifications per GSM 06.81
* section 6.1.1, thus any other return value is a grave error
* in the code. */
OSMO_ASSERT(0);
}
}