blob: b14933005be93ead8341823b35add96466615bee [file] [log] [blame]
Philipp Maier898c9c62020-02-06 14:25:01 +01001/*
2 * (C) 2020 by sysmocom - s.f.m.c. GmbH, Author: Philipp Maier
3 * All Rights Reserved
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <stdio.h>
23#include <stdint.h>
24#include <string.h>
25#include <stdlib.h>
26#include <errno.h>
27
28#include <osmocom/core/bits.h>
29#include <osmocom/core/conv.h>
30#include <osmocom/core/utils.h>
31#include <osmocom/coding/gsm0503_amr_dtx.h>
32#include <osmocom/coding/gsm0503_parity.h>
33#include <osmocom/gsm/gsm0503.h>
34
35/* See also: 3GPP TS 05.03, chapter 3.10.1.3, 3.10.5.2 Identification marker */
36static const ubit_t id_marker_1[] = { 1, 0, 1, 1, 0, 0, 0, 0, 1 };
37
38/* See also: 3GPP TS 05.03, chapter 3.9.1.3, 3.10.2.2, 3.10.2.2 Identification marker */
39static const ubit_t id_marker_0[] = { 0, 1, 0, 0, 1, 1, 1, 1, 0 };
40
41/* See also: 3GPP TS 05.03, chapter 3.9 Adaptive multi rate speech channel at full rate (TCH/AFS) */
42static const ubit_t codec_mode_1_sid[] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0 };
43static const ubit_t codec_mode_2_sid[] = { 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0 };
44static const ubit_t codec_mode_3_sid[] = { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1 };
45static const ubit_t codec_mode_4_sid[] = { 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1 };
46
47const struct value_string gsm0503_amr_dtx_frame_names[] = {
Philipp Maier3c0a87c2020-04-23 10:46:30 +020048 { AMR_OTHER, "AMR_OTHER (audio)" },
Philipp Maier898c9c62020-02-06 14:25:01 +010049 { AFS_SID_FIRST, "AFS_SID_FIRST" },
Philipp Maier3c0a87c2020-04-23 10:46:30 +020050 { AFS_SID_UPDATE, "AFS_SID_UPDATE (marker)" },
51 { AFS_SID_UPDATE_CN, "AFS_SID_UPDATE_CN (audio)" },
Philipp Maier898c9c62020-02-06 14:25:01 +010052 { AFS_ONSET, "AFS_ONSET" },
Philipp Maier3c0a87c2020-04-23 10:46:30 +020053 { AHS_SID_UPDATE, "AHS_SID_UPDATE (marker)" },
54 { AHS_SID_UPDATE_CN, "AHS_SID_UPDATE_CN (audio)" },
Philipp Maier898c9c62020-02-06 14:25:01 +010055 { AHS_SID_FIRST_P1, "AHS_SID_FIRST_P1" },
56 { AHS_SID_FIRST_P2, "AHS_SID_FIRST_P2" },
57 { AHS_ONSET, "AHS_ONSET" },
58 { AHS_SID_FIRST_INH, "AHS_SID_FIRST_INH" },
59 { AHS_SID_UPDATE_INH, "AHS_SID_UPDATE_INH" },
Philipp Maier898c9c62020-02-06 14:25:01 +010060 { 0, NULL }
61};
62
63static bool detect_afs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, uint8_t offset, uint8_t count,
64 const ubit_t * id_marker, uint8_t id_marker_len)
65{
66 unsigned int i, k;
67 unsigned int id_bit_nr = 0;
68 int errors = 0;
69 int bits = 0;
70
71 /* Override coded in-band data */
72 ubits += offset;
73
74 /* Check for identification marker bits */
75 for (i = 0; i < count; i++) {
76 for (k = 0; k < 4; k++) {
77 if (id_marker[id_bit_nr % id_marker_len] != *ubits)
78 errors++;
79 id_bit_nr++;
80 ubits++;
81 bits++;
82 }
83
84 /* Jump to the next block of 4 bits */
85 ubits += 4;
86 }
87
88 *n_errors = errors;
89 *n_bits_total = bits;
90
91 /* Tolerate up to 1/8 errornous bits */
92 return *n_errors < *n_bits_total / 8;
93}
94
95static bool detect_ahs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, const ubit_t * id_marker)
96{
97 unsigned int i, k;
98 int errors = 0;
99 int bits = 0;
100
101 /* Override coded in-band data */
102 ubits += 16;
103
104 /* Check first identification marker bits (23*9 bits) */
105 for (i = 0; i < 23; i++) {
106 for (k = 0; k < 9; k++) {
107 if (id_marker[k] != *ubits)
108 errors++;
109 ubits++;
110 bits++;
111 }
112 }
113
114 /* Check remaining identification marker bits (5 bits) */
115 for (k = 0; k < 5; k++) {
116 if (id_marker[k] != *ubits)
117 errors++;
118 ubits++;
119 bits++;
120 }
121
122 *n_errors = errors;
123 *n_bits_total = bits;
124
125 /* Tolerate up to 1/8 errornous bits */
126 return *n_errors < *n_bits_total / 8;
127}
128
129static bool detect_interleaved_ahs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, uint8_t offset,
130 uint8_t n_bits, const ubit_t * id_marker, uint8_t id_marker_len)
131{
132 unsigned int i, k;
133 int errors = 0;
134 int bits = 0;
135 uint8_t full_rounds = n_bits / id_marker_len;
136 uint8_t remainder = n_bits % id_marker_len;
137
138 /* Override coded in-band data */
139 ubits += offset;
140
141 /* Check first identification marker bits (23*9 bits) */
142 for (i = 0; i < full_rounds; i++) {
143 for (k = 0; k < id_marker_len; k++) {
144 if (id_marker[k] != *ubits)
145 errors++;
146 ubits += 2;
147 bits++;
148 }
149 }
150
151 /* Check remaining identification marker bits (5 bits) */
152 for (k = 0; k < remainder; k++) {
153 if (id_marker[k] != *ubits)
154 errors++;
155 ubits += 2;
156 bits++;
157 }
158
159 *n_errors = errors;
160 *n_bits_total = bits;
161
162 /* Tolerate up to 1/8 errornous bits */
163 return *n_errors < *n_bits_total / 8;
164}
165
Vadim Yanitskiyf6fd0bb2022-04-23 03:34:33 +0300166/* Detect an FR AMR SID_FIRST frame by its identifcation marker */
Philipp Maier898c9c62020-02-06 14:25:01 +0100167static bool detect_afs_sid_first(int *n_errors, int *n_bits_total, const ubit_t * ubits)
168{
169 return detect_afs_id_marker(n_errors, n_bits_total, ubits, 32, 53, id_marker_0, 9);
170}
171
Vadim Yanitskiyf6fd0bb2022-04-23 03:34:33 +0300172/* Detect an FR AMR SID_UPDATE frame by its identification marker */
Philipp Maier898c9c62020-02-06 14:25:01 +0100173static bool detect_afs_sid_update(int *n_errors, int *n_bits_total, const ubit_t * ubits)
174{
175 return detect_afs_id_marker(n_errors, n_bits_total, ubits, 36, 53, id_marker_0, 9);
176}
177
Vadim Yanitskiyf6fd0bb2022-04-23 03:34:33 +0300178/* Detect an FR AMR ONSET frame by its repeating coded inband data */
Philipp Maier898c9c62020-02-06 14:25:01 +0100179static bool detect_afs_onset(int *n_errors, int *n_bits_total, const ubit_t * ubits)
180{
181 bool rc;
182
183 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_1_sid, 16);
184 if (rc)
185 return true;
186
187 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_2_sid, 16);
188 if (rc)
189 return true;
190
191 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_3_sid, 16);
192 if (rc)
193 return true;
194
195 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_4_sid, 16);
196 if (rc)
197 return true;
198
199 return false;
200}
201
202/* Detect an HR AMR SID UPDATE frame by its identification marker */
203static bool detect_ahs_sid_update(int *n_errors, int *n_bits_total, const ubit_t * ubits)
204{
205 return detect_ahs_id_marker(n_errors, n_bits_total, ubits, id_marker_1);
206}
207
208/* Detect an HR AMR SID FIRST (part 1) frame by its identification marker */
209static bool detect_ahs_sid_first_p1(int *n_errors, int *n_bits_total, const ubit_t * ubits)
210{
211 return detect_ahs_id_marker(n_errors, n_bits_total, ubits, id_marker_0);
212}
213
214/* Detect an HR AMR SID FIRST (part 2) frame by its repeating coded inband data */
215static bool detect_ahs_sid_first_p2(int *n_errors, int *n_bits_total, const ubit_t * ubits)
216{
217 bool rc;
218
219 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_1_sid, 16);
220 if (rc)
221 return true;
222
223 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_2_sid, 16);
224 if (rc)
225 return true;
226
227 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_3_sid, 16);
228 if (rc)
229 return true;
230
231 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_4_sid, 16);
232 if (rc)
233 return true;
234
235 return false;
236}
237
238/* Detect an HR AMR ONSET frame by its repeating coded inband data */
239static bool detect_ahs_onset(int *n_errors, int *n_bits_total, const ubit_t * ubits)
240{
241 bool rc;
242
243 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_1_sid, 16);
244 if (rc)
245 return true;
246
247 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_2_sid, 16);
248 if (rc)
249 return true;
250
251 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_3_sid, 16);
252 if (rc)
253 return true;
254
255 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_4_sid, 16);
256 if (rc)
257 return true;
258
259 return false;
260}
261
262/* Detect an HR AMR SID FIRST INHIBIT frame by its identification marker */
263static bool detect_ahs_sid_first_inh(int *n_errors, int *n_bits_total, const ubit_t * ubits)
264{
265 return detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 33, 212, id_marker_1, 9);
266}
267
268/* Detect an HR AMR SID UPDATE INHIBIT frame by its identification marker */
269static bool detect_ahs_sid_update_inh(int *n_errors, int *n_bits_total, const ubit_t * ubits)
270{
271 return detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 33, 212, id_marker_0, 9);
272}
273
274/*! Detect FR AMR DTX frame in unmapped, deinterleaved frame bits.
275 * \param[in] ubits input bits (456 bit).
276 * \param[out] n_errors number of errornous bits.
277 * \param[out] n_bits_total number of checked bits.
278 * \returns dtx frame type. */
279enum gsm0503_amr_dtx_frames gsm0503_detect_afs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t * ubits)
280{
281 if (detect_afs_sid_first(n_errors, n_bits_total, ubits))
282 return AFS_SID_FIRST;
283 if (detect_afs_sid_update(n_errors, n_bits_total, ubits))
284 return AFS_SID_UPDATE;
285 if (detect_afs_onset(n_errors, n_bits_total, ubits))
286 return AFS_ONSET;
287
288 *n_errors = 0;
289 *n_bits_total = 0;
290 return AMR_OTHER;
291}
292
293/*! Detect HR AMR DTX frame in unmapped, deinterleaved frame bits.
294 * \param[in] ubits input bits (456 bit).
295 * \param[out] n_errors number of errornous bits.
296 * \param[out] n_bits_total number of checked bits.
297 * \returns dtx frame type, */
298enum gsm0503_amr_dtx_frames gsm0503_detect_ahs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t * ubits)
299{
300 if (detect_ahs_sid_update(n_errors, n_bits_total, ubits))
301 return AHS_SID_UPDATE;
302 if (detect_ahs_sid_first_inh(n_errors, n_bits_total, ubits))
303 return AHS_SID_FIRST_INH;
304 if (detect_ahs_sid_update_inh(n_errors, n_bits_total, ubits))
305 return AHS_SID_UPDATE_INH;
306 if (detect_ahs_sid_first_p1(n_errors, n_bits_total, ubits))
307 return AHS_SID_FIRST_P1;
308 if (detect_ahs_sid_first_p2(n_errors, n_bits_total, ubits))
309 return AHS_SID_FIRST_P2;
310 if (detect_ahs_onset(n_errors, n_bits_total, ubits))
311 return AHS_ONSET;
312
313 *n_errors = 0;
314 *n_bits_total = 0;
315 return AMR_OTHER;
316}