Neels Hofmeyr | 17518fe | 2017-06-20 04:35:06 +0200 | [diff] [blame] | 1 | /*! \file gsm660.c |
| 2 | * GSM 06.60 - GSM EFR Codec. */ |
Sylvain Munaut | 1a4ea5b | 2010-10-08 15:09:16 +0200 | [diff] [blame] | 3 | /* |
| 4 | * (C) 2010 Sylvain Munaut <tnt@246tNt.com> |
| 5 | * |
| 6 | * All Rights Reserved |
| 7 | * |
Harald Welte | e08da97 | 2017-11-13 01:00:26 +0900 | [diff] [blame] | 8 | * SPDX-License-Identifier: GPL-2.0+ |
| 9 | * |
Sylvain Munaut | 1a4ea5b | 2010-10-08 15:09:16 +0200 | [diff] [blame] | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of the GNU General Public License as published by |
| 12 | * the Free Software Foundation; either version 2 of the License, or |
| 13 | * (at your option) any later version. |
| 14 | * |
| 15 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. |
| 19 | * |
Sylvain Munaut | 1a4ea5b | 2010-10-08 15:09:16 +0200 | [diff] [blame] | 20 | */ |
| 21 | |
| 22 | #include <stdint.h> |
Mychaela N. Falconia | 7f91880 | 2023-03-24 00:46:12 +0000 | [diff] [blame] | 23 | #include <stdbool.h> |
| 24 | |
| 25 | #include <osmocom/core/bitvec.h> |
| 26 | #include <osmocom/core/utils.h> |
Harald Welte | dee7172 | 2017-05-31 02:48:48 +0200 | [diff] [blame] | 27 | #include <osmocom/codec/codec.h> |
Sylvain Munaut | 1a4ea5b | 2010-10-08 15:09:16 +0200 | [diff] [blame] | 28 | |
| 29 | /* GSM EFR - subjective importance bit ordering */ |
| 30 | /* This array encodes GSM 05.03 Table 6. |
| 31 | * |
| 32 | * It converts between serial parameter output (as described in |
| 33 | * GSM 06.60 Table 6 and GSM 05.03 Table 5) and the order needed |
| 34 | * before channel encoding. CRC poly and bit repetition must be |
| 35 | * applied prior to this table, as in GSM 05.03 3.1.1, to get 260 |
| 36 | * bits from a 244 bits raw EFR frame. |
| 37 | */ |
Diego Elio Pettenò | 23431c7 | 2012-06-29 13:01:27 -0700 | [diff] [blame] | 38 | const uint16_t gsm660_bitorder[260] = { |
Sylvain Munaut | 1a4ea5b | 2010-10-08 15:09:16 +0200 | [diff] [blame] | 39 | 38, 39, 40, 41, 42, 43, /* 0 -> LTP-LAG 1: b8..b3 */ |
| 40 | 145, 146, 147, 148, 149, 150, /* 6 -> LTP-LAG 3: b8..b3 */ |
| 41 | 93, 94, /* 12 -> LTP-LAG 2: b5..b4 */ |
| 42 | 200, 201, /* 14 -> LTP-LAG 4: b5..b4 */ |
| 43 | 47, /* 16 -> LTP-GAIN 1: b3 */ |
| 44 | 88, /* 17 -> FCB-GAIN 1: b4 */ |
| 45 | 99, /* 18 -> LTP-GAIN 2: b3 */ |
| 46 | 140, /* 19 -> FCB-GAIN 2: b4 */ |
| 47 | 44, /* 20 -> LTP-LAG 1: b2 */ |
| 48 | 151, /* 21 -> LTP-LAG 3: b2 */ |
| 49 | 95, /* 22 -> LTP-LAG 2: b3 */ |
| 50 | 202, /* 23 -> LTP-LAG 4: b3 */ |
| 51 | 1, 2, /* 24 -> LPC 1: b5..b4 */ |
| 52 | 7, /* 26 -> LPC 2: b7 */ |
| 53 | 9, /* 27 -> LPC 2: b5 */ |
| 54 | 17, 18, /* 28 -> LPC 3: b6..b5 */ |
| 55 | 23, /* 30 -> LPC 3: b0 */ |
| 56 | 45, 46, /* 31 -> LTP-LAG 1: b1..b0 */ |
| 57 | 152, 153, /* 33 -> LTP-LAG 3: b1..b0 */ |
| 58 | 96, /* 35 -> LTP-LAG 2: b2 */ |
| 59 | 203, /* 36 -> LTP-LAG 4: b2 */ |
| 60 | 3, 4, /* 37 -> LPC 1: b3..b2 */ |
| 61 | 10, 11, /* 39 -> LPC 2: b4..b3 */ |
| 62 | 15, /* 41 -> LPC 3: b8 */ |
| 63 | 8, /* 42 -> LPC 2: b6 */ |
| 64 | 5, 6, /* 43 -> LPC 1: b1..b0 */ |
| 65 | 12, /* 45 -> LPC 2: b2 */ |
| 66 | 16, /* 46 -> LPC 3: b7 */ |
| 67 | 19, /* 47 -> LPC 3: b4 */ |
| 68 | 97, /* 48 -> LTP-LAG 2: b1 */ |
| 69 | 204, /* 49 -> LTP-LAG 4: b1 */ |
| 70 | 0, /* 50 -> LPC 1: b6 */ |
| 71 | 13, 14, /* 51 -> LPC 2: b1..b0 */ |
| 72 | 20, /* 53 -> LPC 3: b3 */ |
| 73 | 24, 25, /* 54 -> LPC 4: b7..b6 */ |
| 74 | 27, /* 56 -> LPC 4: b4 */ |
| 75 | 154, /* 57 -> LTP-GAIN 3: b3 */ |
| 76 | 206, /* 58 -> LTP-GAIN 4: b3 */ |
| 77 | 195, /* 59 -> FCB-GAIN 3: b4 */ |
| 78 | 247, /* 60 -> FCB-GAIN 4: b4 */ |
| 79 | 89, /* 61 -> FCB-GAIN 1: b3 */ |
| 80 | 141, /* 62 -> FCB-GAIN 2: b3 */ |
| 81 | 196, /* 63 -> FCB-GAIN 3: b3 */ |
| 82 | 248, /* 64 -> FCB-GAIN 4: b3 */ |
| 83 | 252, 253, 254, 255, 256, 257, 258, 259, /* 65 -> CRC-POLY: b7..b0 */ |
| 84 | 48, /* 73 -> LTP-GAIN 1: b2 */ |
| 85 | 100, /* 74 -> LTP-GAIN 2: b2 */ |
| 86 | 155, /* 75 -> LTP-GAIN 3: b2 */ |
| 87 | 207, /* 76 -> LTP-GAIN 4: b2 */ |
| 88 | 21, 22, /* 77 -> LPC 3: b2..b1 */ |
| 89 | 26, /* 79 -> LPC 4: b5 */ |
| 90 | 28, /* 80 -> LPC 4: b3 */ |
| 91 | 51, /* 81 -> PULSE 1_1: b3 */ |
| 92 | 55, /* 82 -> PULSE 1_2: b3 */ |
| 93 | 59, /* 83 -> PULSE 1_3: b3 */ |
| 94 | 63, /* 84 -> PULSE 1_4: b3 */ |
| 95 | 67, /* 85 -> PULSE 1_5: b3 */ |
| 96 | 103, /* 86 -> PULSE 2_1: b3 */ |
| 97 | 107, /* 87 -> PULSE 2_2: b3 */ |
| 98 | 111, /* 88 -> PULSE 2_3: b3 */ |
| 99 | 115, /* 89 -> PULSE 2_4: b3 */ |
| 100 | 119, /* 90 -> PULSE 2_5: b3 */ |
| 101 | 158, /* 91 -> PULSE 3_1: b3 */ |
| 102 | 162, /* 92 -> PULSE 3_2: b3 */ |
| 103 | 166, /* 93 -> PULSE 3_3: b3 */ |
| 104 | 170, /* 94 -> PULSE 3_4: b3 */ |
| 105 | 174, /* 95 -> PULSE 3_5: b3 */ |
| 106 | 210, /* 96 -> PULSE 4_1: b3 */ |
| 107 | 214, /* 97 -> PULSE 4_2: b3 */ |
| 108 | 218, /* 98 -> PULSE 4_3: b3 */ |
| 109 | 222, /* 99 -> PULSE 4_4: b3 */ |
| 110 | 226, /* 100 -> PULSE 4_5: b3 */ |
| 111 | 90, /* 101 -> FCB-GAIN 1: b2 */ |
| 112 | 142, /* 102 -> FCB-GAIN 2: b2 */ |
| 113 | 197, /* 103 -> FCB-GAIN 3: b2 */ |
| 114 | 249, /* 104 -> FCB-GAIN 4: b2 */ |
| 115 | 49, /* 105 -> LTP-GAIN 1: b1 */ |
| 116 | 101, /* 106 -> LTP-GAIN 2: b1 */ |
| 117 | 156, /* 107 -> LTP-GAIN 3: b1 */ |
| 118 | 208, /* 108 -> LTP-GAIN 4: b1 */ |
| 119 | 29, 30, 31, /* 109 -> LPC 4: b2..b0 */ |
| 120 | 32, 33, 34, 35, /* 112 -> LPC 5: b5..b2 */ |
| 121 | 98, /* 116 -> LTP-LAG 2: b0 */ |
| 122 | 205, /* 117 -> LTP-LAG 4: b0 */ |
| 123 | 52, /* 118 -> PULSE 1_1: b2 */ |
| 124 | 56, /* 119 -> PULSE 1_2: b2 */ |
| 125 | 60, /* 120 -> PULSE 1_3: b2 */ |
| 126 | 64, /* 121 -> PULSE 1_4: b2 */ |
| 127 | 68, /* 122 -> PULSE 1_5: b2 */ |
| 128 | 104, /* 123 -> PULSE 2_1: b2 */ |
| 129 | 108, /* 124 -> PULSE 2_2: b2 */ |
| 130 | 112, /* 125 -> PULSE 2_3: b2 */ |
| 131 | 116, /* 126 -> PULSE 2_4: b2 */ |
| 132 | 120, /* 127 -> PULSE 2_5: b2 */ |
| 133 | 159, /* 128 -> PULSE 3_1: b2 */ |
| 134 | 163, /* 129 -> PULSE 3_2: b2 */ |
| 135 | 167, /* 130 -> PULSE 3_3: b2 */ |
| 136 | 171, /* 131 -> PULSE 3_4: b2 */ |
| 137 | 175, /* 132 -> PULSE 3_5: b2 */ |
| 138 | 211, /* 133 -> PULSE 4_1: b2 */ |
| 139 | 215, /* 134 -> PULSE 4_2: b2 */ |
| 140 | 219, /* 135 -> PULSE 4_3: b2 */ |
| 141 | 223, /* 136 -> PULSE 4_4: b2 */ |
| 142 | 227, /* 137 -> PULSE 4_5: b2 */ |
| 143 | 53, /* 138 -> PULSE 1_1: b1 */ |
| 144 | 57, /* 139 -> PULSE 1_2: b1 */ |
| 145 | 61, /* 140 -> PULSE 1_3: b1 */ |
| 146 | 65, /* 141 -> PULSE 1_4: b1 */ |
| 147 | 105, /* 142 -> PULSE 2_1: b1 */ |
| 148 | 109, /* 143 -> PULSE 2_2: b1 */ |
| 149 | 113, /* 144 -> PULSE 2_3: b1 */ |
| 150 | 117, /* 145 -> PULSE 2_4: b1 */ |
| 151 | 160, /* 146 -> PULSE 3_1: b1 */ |
| 152 | 164, /* 147 -> PULSE 3_2: b1 */ |
| 153 | 168, /* 148 -> PULSE 3_3: b1 */ |
| 154 | 172, /* 149 -> PULSE 3_4: b1 */ |
| 155 | 212, /* 150 -> PULSE 4_1: b1 */ |
| 156 | 220, /* 151 -> PULSE 4_3: b1 */ |
| 157 | 224, /* 152 -> PULSE 4_4: b1 */ |
| 158 | 91, /* 153 -> FCB-GAIN 1: b1 */ |
| 159 | 143, /* 154 -> FCB-GAIN 2: b1 */ |
| 160 | 198, /* 155 -> FCB-GAIN 3: b1 */ |
| 161 | 250, /* 156 -> FCB-GAIN 4: b1 */ |
| 162 | 50, /* 157 -> LTP-GAIN 1: b0 */ |
| 163 | 102, /* 158 -> LTP-GAIN 2: b0 */ |
| 164 | 157, /* 159 -> LTP-GAIN 3: b0 */ |
| 165 | 209, /* 160 -> LTP-GAIN 4: b0 */ |
| 166 | 92, /* 161 -> FCB-GAIN 1: b0 */ |
| 167 | 144, /* 162 -> FCB-GAIN 2: b0 */ |
| 168 | 199, /* 163 -> FCB-GAIN 3: b0 */ |
| 169 | 251, /* 164 -> FCB-GAIN 4: b0 */ |
| 170 | 54, /* 165 -> PULSE 1_1: b0 */ |
| 171 | 58, /* 166 -> PULSE 1_2: b0 */ |
| 172 | 62, /* 167 -> PULSE 1_3: b0 */ |
| 173 | 66, /* 168 -> PULSE 1_4: b0 */ |
| 174 | 106, /* 169 -> PULSE 2_1: b0 */ |
| 175 | 110, /* 170 -> PULSE 2_2: b0 */ |
| 176 | 114, /* 171 -> PULSE 2_3: b0 */ |
| 177 | 118, /* 172 -> PULSE 2_4: b0 */ |
| 178 | 161, /* 173 -> PULSE 3_1: b0 */ |
| 179 | 165, /* 174 -> PULSE 3_2: b0 */ |
| 180 | 169, /* 175 -> PULSE 3_3: b0 */ |
| 181 | 173, /* 176 -> PULSE 3_4: b0 */ |
| 182 | 213, /* 177 -> PULSE 4_1: b0 */ |
| 183 | 221, /* 178 -> PULSE 4_3: b0 */ |
| 184 | 225, /* 179 -> PULSE 4_4: b0 */ |
| 185 | 36, 37, /* 180 -> LPC 5: b1..b0 */ |
| 186 | 69, /* 182 -> PULSE 1_5: b1 */ |
| 187 | 71, 72, /* 183 -> PULSE 1_5: b1..b1 */ |
| 188 | 121, /* 185 -> PULSE 2_5: b1 */ |
| 189 | 123, 124, /* 186 -> PULSE 2_5: b1..b1 */ |
| 190 | 176, /* 188 -> PULSE 3_5: b1 */ |
| 191 | 178, 179, /* 189 -> PULSE 3_5: b1..b1 */ |
| 192 | 228, /* 191 -> PULSE 4_5: b1 */ |
| 193 | 230, 231, /* 192 -> PULSE 4_5: b1..b1 */ |
| 194 | 216, 217, /* 194 -> PULSE 4_2: b1..b0 */ |
| 195 | 70, /* 196 -> PULSE 1_5: b0 */ |
| 196 | 122, /* 197 -> PULSE 2_5: b0 */ |
| 197 | 177, /* 198 -> PULSE 3_5: b0 */ |
| 198 | 229, /* 199 -> PULSE 4_5: b0 */ |
| 199 | 73, /* 200 -> PULSE 1_6: b2 */ |
| 200 | 76, /* 201 -> PULSE 1_7: b2 */ |
| 201 | 79, /* 202 -> PULSE 1_8: b2 */ |
| 202 | 82, /* 203 -> PULSE 1_9: b2 */ |
| 203 | 85, /* 204 -> PULSE 1_10: b2 */ |
| 204 | 125, /* 205 -> PULSE 2_6: b2 */ |
| 205 | 128, /* 206 -> PULSE 2_7: b2 */ |
| 206 | 131, /* 207 -> PULSE 2_8: b2 */ |
| 207 | 134, /* 208 -> PULSE 2_9: b2 */ |
| 208 | 137, /* 209 -> PULSE 2_10: b2 */ |
| 209 | 180, /* 210 -> PULSE 3_6: b2 */ |
| 210 | 183, /* 211 -> PULSE 3_7: b2 */ |
| 211 | 186, /* 212 -> PULSE 3_8: b2 */ |
| 212 | 189, /* 213 -> PULSE 3_9: b2 */ |
| 213 | 192, /* 214 -> PULSE 3_10: b2 */ |
| 214 | 232, /* 215 -> PULSE 4_6: b2 */ |
| 215 | 235, /* 216 -> PULSE 4_7: b2 */ |
| 216 | 238, /* 217 -> PULSE 4_8: b2 */ |
| 217 | 241, /* 218 -> PULSE 4_9: b2 */ |
| 218 | 244, /* 219 -> PULSE 4_10: b2 */ |
| 219 | 74, /* 220 -> PULSE 1_6: b1 */ |
| 220 | 77, /* 221 -> PULSE 1_7: b1 */ |
| 221 | 80, /* 222 -> PULSE 1_8: b1 */ |
| 222 | 83, /* 223 -> PULSE 1_9: b1 */ |
| 223 | 86, /* 224 -> PULSE 1_10: b1 */ |
| 224 | 126, /* 225 -> PULSE 2_6: b1 */ |
| 225 | 129, /* 226 -> PULSE 2_7: b1 */ |
| 226 | 132, /* 227 -> PULSE 2_8: b1 */ |
| 227 | 135, /* 228 -> PULSE 2_9: b1 */ |
| 228 | 138, /* 229 -> PULSE 2_10: b1 */ |
| 229 | 181, /* 230 -> PULSE 3_6: b1 */ |
| 230 | 184, /* 231 -> PULSE 3_7: b1 */ |
| 231 | 187, /* 232 -> PULSE 3_8: b1 */ |
| 232 | 190, /* 233 -> PULSE 3_9: b1 */ |
| 233 | 193, /* 234 -> PULSE 3_10: b1 */ |
| 234 | 233, /* 235 -> PULSE 4_6: b1 */ |
| 235 | 236, /* 236 -> PULSE 4_7: b1 */ |
| 236 | 239, /* 237 -> PULSE 4_8: b1 */ |
| 237 | 242, /* 238 -> PULSE 4_9: b1 */ |
| 238 | 245, /* 239 -> PULSE 4_10: b1 */ |
| 239 | 75, /* 240 -> PULSE 1_6: b0 */ |
| 240 | 78, /* 241 -> PULSE 1_7: b0 */ |
| 241 | 81, /* 242 -> PULSE 1_8: b0 */ |
| 242 | 84, /* 243 -> PULSE 1_9: b0 */ |
| 243 | 87, /* 244 -> PULSE 1_10: b0 */ |
| 244 | 127, /* 245 -> PULSE 2_6: b0 */ |
| 245 | 130, /* 246 -> PULSE 2_7: b0 */ |
| 246 | 133, /* 247 -> PULSE 2_8: b0 */ |
| 247 | 136, /* 248 -> PULSE 2_9: b0 */ |
| 248 | 139, /* 249 -> PULSE 2_10: b0 */ |
| 249 | 182, /* 250 -> PULSE 3_6: b0 */ |
| 250 | 185, /* 251 -> PULSE 3_7: b0 */ |
| 251 | 188, /* 252 -> PULSE 3_8: b0 */ |
| 252 | 191, /* 253 -> PULSE 3_9: b0 */ |
| 253 | 194, /* 254 -> PULSE 3_10: b0 */ |
| 254 | 234, /* 255 -> PULSE 4_6: b0 */ |
| 255 | 237, /* 256 -> PULSE 4_7: b0 */ |
| 256 | 240, /* 257 -> PULSE 4_8: b0 */ |
| 257 | 243, /* 258 -> PULSE 4_9: b0 */ |
| 258 | 246, /* 259 -> PULSE 4_10: b0 */ |
| 259 | }; |
Mychaela N. Falconia | 7f91880 | 2023-03-24 00:46:12 +0000 | [diff] [blame] | 260 | |
Mychaela N. Falconia | ec65085 | 2023-04-16 01:34:35 +0000 | [diff] [blame] | 261 | static const uint8_t sid_code_word_bits[95] = { |
| 262 | /* bit numbers are relative to "pure" EFR frame beginning, |
| 263 | * not counting the signature bits. */ |
| 264 | 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, |
| 265 | 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, |
| 266 | 66, 67, 68, 94, 95, 96, 98, 99, 100, 101, |
| 267 | 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, |
| 268 | 112, 113, 114, 115, 116, 117, 118, 148, 149, 150, |
| 269 | 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, |
| 270 | 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, |
| 271 | 171, 196, 197, 198, 199, 200, 201, 202, 203, 204, |
| 272 | 205, 206, 207, 208, 209, 212, 213, 214, 215, 216, |
| 273 | 217, 218, 219, 220, 221 |
| 274 | }; |
| 275 | |
Mychaela N. Falconia | 7f91880 | 2023-03-24 00:46:12 +0000 | [diff] [blame] | 276 | /*! Check whether RTP frame contains EFR SID code word according to |
| 277 | * TS 101 318 §5.3.2 |
| 278 | * \param[in] rtp_payload Buffer with RTP payload |
| 279 | * \param[in] payload_len Length of payload |
| 280 | * \returns true if code word is found, false otherwise |
| 281 | */ |
| 282 | bool osmo_efr_check_sid(const uint8_t *rtp_payload, size_t payload_len) |
| 283 | { |
| 284 | struct bitvec bv; |
| 285 | uint16_t i; |
Mychaela N. Falconia | 7f91880 | 2023-03-24 00:46:12 +0000 | [diff] [blame] | 286 | |
| 287 | /* signature does not match Enhanced Full Rate SID */ |
| 288 | if ((rtp_payload[0] >> 4) != 0xC) |
| 289 | return false; |
| 290 | |
| 291 | bv.data = (uint8_t *) rtp_payload; |
| 292 | bv.data_len = payload_len; |
| 293 | |
| 294 | /* code word is all 1 at given bits */ |
| 295 | for (i = 0; i < ARRAY_SIZE(sid_code_word_bits); i++) { |
| 296 | if (bitvec_get_bit_pos(&bv, sid_code_word_bits[i]+4) != ONE) |
| 297 | return false; |
| 298 | } |
| 299 | |
| 300 | return true; |
| 301 | } |
Mychaela N. Falconia | ec65085 | 2023-04-16 01:34:35 +0000 | [diff] [blame] | 302 | |
| 303 | /*! Classify potentially-SID EFR codec frame in RTP format according |
| 304 | * to the rules of GSM 06.81 §6.1.1 |
| 305 | * \param[in] rtp_payload Buffer with RTP payload |
| 306 | * \returns enum osmo_gsm631_sid_class, with symbolic values |
| 307 | * OSMO_GSM631_SID_CLASS_SPEECH, OSMO_GSM631_SID_CLASS_INVALID or |
| 308 | * OSMO_GSM631_SID_CLASS_VALID corresponding to the 3 possible bit-counting |
| 309 | * classifications prescribed by the spec. |
| 310 | * |
| 311 | * Differences between the more familiar osmo_efr_check_sid() and the present |
| 312 | * function are: |
| 313 | * |
| 314 | * 1. osmo_efr_check_sid() returns true only if the SID frame is absolutely |
| 315 | * perfect, with all 95 bits of the SID code word set. However, the |
| 316 | * rules of GSM 06.81 §6.1.1 allow up to one bit to be in error, |
| 317 | * and the frame is still accepted as valid SID. |
| 318 | * |
| 319 | * 2. The third possible state of invalid SID is not handled at all by the |
| 320 | * simpler osmo_efr_check_sid() function. |
| 321 | * |
| 322 | * 3. osmo_efr_check_sid() includes a check for 0xC RTP signature, and returns |
| 323 | * false if that signature nibble is wrong. That check is not included |
| 324 | * in the present version because there is no place for it in the |
| 325 | * ETSI-prescribed classification, it is neither speech nor SID. The |
| 326 | * assumption is that this function is used to classify the bit content |
| 327 | * of received codec frames, not their RTP encoding - the latter needs |
| 328 | * to be validated beforehand. |
| 329 | * |
| 330 | * Which function should one use? The answer depends on the specific |
| 331 | * circumstances, and needs to be addressed on a case-by-case basis. |
| 332 | */ |
| 333 | enum osmo_gsm631_sid_class osmo_efr_sid_classify(const uint8_t *rtp_payload) |
| 334 | { |
| 335 | struct bitvec bv; |
| 336 | uint16_t i, n; |
| 337 | |
| 338 | bv.data = (uint8_t *) rtp_payload; |
| 339 | bv.data_len = GSM_EFR_BYTES; |
| 340 | |
| 341 | /* count not-SID-matching bits per the spec */ |
| 342 | n = 0; |
| 343 | for (i = 0; i < ARRAY_SIZE(sid_code_word_bits); i++) { |
| 344 | if (bitvec_get_bit_pos(&bv, sid_code_word_bits[i]+4) != ONE) |
| 345 | n++; |
| 346 | if (n >= 16) |
| 347 | return OSMO_GSM631_SID_CLASS_SPEECH; |
| 348 | } |
| 349 | if (n >= 2) |
| 350 | return OSMO_GSM631_SID_CLASS_INVALID; |
| 351 | else |
| 352 | return OSMO_GSM631_SID_CLASS_VALID; |
| 353 | } |
Mychaela N. Falconia | 295636b | 2023-04-16 17:19:50 +0000 | [diff] [blame] | 354 | |
Mychaela N. Falconia | 2974a23 | 2023-05-26 20:38:02 +0000 | [diff] [blame] | 355 | /*! Reset the SID field of a potentially corrupted, but still valid GSM-EFR |
| 356 | * SID frame in RTP encoding to its pristine state (full SID code word). |
| 357 | * \param[in] rtp_payload Buffer with RTP payload - must be writable! |
| 358 | * |
| 359 | * Per GSM 06.62 section 5.3, a freshly minted SID frame consists of 58 bits |
| 360 | * of comfort noise parameters (LSF and 4 times fixed codebook gain), 95 bits |
| 361 | * of SID code word (all 1s) and 91 unused bits (all 0s). Network elements |
| 362 | * that receive SID frames from call leg A uplink and need to retransmit them |
| 363 | * on leg B downlink should "rejuvenate" received SID frames prior to |
| 364 | * retransmission by resetting the SID field to its pristine state of all 1s; |
| 365 | * this function does the job. |
| 366 | * |
| 367 | * Potential TODO: it would be nice to also zero out the remaining 91 bits |
| 368 | * which the spec leaves as reserved, clearing out leg A radio bit errors - |
| 369 | * but do we really need to? |
| 370 | */ |
| 371 | void osmo_efr_sid_reset(uint8_t *rtp_payload) |
| 372 | { |
| 373 | /* set all 95 SID code word bits to 1 */ |
| 374 | rtp_payload[6] |= 0x6F; |
| 375 | rtp_payload[7] = 0xFF; |
| 376 | rtp_payload[8] = 0xFF; |
| 377 | rtp_payload[9] |= 0x80; |
| 378 | rtp_payload[12] |= 0x3B; |
| 379 | rtp_payload[13] = 0xFF; |
| 380 | rtp_payload[14] = 0xFF; |
| 381 | rtp_payload[15] |= 0xE0; |
| 382 | rtp_payload[19] = 0xFF; |
| 383 | rtp_payload[20] = 0xFF; |
| 384 | rtp_payload[21] = 0xFF; |
| 385 | rtp_payload[25] = 0xFF; |
| 386 | rtp_payload[26] |= 0xFC; |
| 387 | rtp_payload[27] = 0xFF; |
| 388 | rtp_payload[28] |= 0xC0; |
| 389 | } |
| 390 | |
Mychaela N. Falconia | 295636b | 2023-04-16 17:19:50 +0000 | [diff] [blame] | 391 | /*! Preen potentially-SID EFR codec frame in RTP format, ensuring that it is |
| 392 | * either a speech frame or a valid SID, and if the latter, making it a |
| 393 | * perfect, error-free SID frame. |
| 394 | * \param[in] rtp_payload Buffer with RTP payload - must be writable! |
| 395 | * \returns true if the frame is good, false otherwise |
| 396 | */ |
| 397 | bool osmo_efr_sid_preen(uint8_t *rtp_payload) |
| 398 | { |
| 399 | enum osmo_gsm631_sid_class sidc; |
| 400 | |
| 401 | sidc = osmo_efr_sid_classify(rtp_payload); |
| 402 | switch (sidc) { |
| 403 | case OSMO_GSM631_SID_CLASS_SPEECH: |
| 404 | return true; |
| 405 | case OSMO_GSM631_SID_CLASS_INVALID: |
| 406 | return false; |
| 407 | case OSMO_GSM631_SID_CLASS_VALID: |
Mychaela N. Falconia | 2974a23 | 2023-05-26 20:38:02 +0000 | [diff] [blame] | 408 | /* "Rejuvenate" this SID frame, correcting any errors */ |
| 409 | osmo_efr_sid_reset(rtp_payload); |
Mychaela N. Falconia | 295636b | 2023-04-16 17:19:50 +0000 | [diff] [blame] | 410 | return true; |
| 411 | default: |
| 412 | /* There are only 3 possible SID classifications per GSM 06.81 |
| 413 | * section 6.1.1, thus any other return value is a grave error |
| 414 | * in the code. */ |
| 415 | OSMO_ASSERT(0); |
| 416 | } |
| 417 | } |