<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/17095">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">dtx: add decoding for AMR-DTX frames<br><br>gsm0503_coding contains AMR decoder functions for HR and FR. Those can<br>only decode AMR payload frames but not amr DTX frames. Lets add<br>functionality to detect DTX frames. Also lets add decoding for SID_UPDATE<br>frames as well as error checking for the SID frame recognition patterns.<br><br>Related: OS#2978<br>Change-Id: I2bbdb39ea20461ca08b2e6f1a33532cb55cd5195<br>---<br>M include/Makefile.am<br>A include/osmocom/coding/gsm0503_amr_dtx.h<br>M include/osmocom/coding/gsm0503_coding.h<br>M src/coding/Makefile.am<br>A src/coding/gsm0503_amr_dtx.c<br>M src/coding/gsm0503_coding.c<br>M src/coding/libosmocoding.map<br>M tests/Makefile.am<br>A tests/dtx/dtx_gsm0503_test.c<br>A tests/dtx/dtx_gsm0503_test.ok<br>M tests/testsuite.at<br>11 files changed, 702 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/Makefile.am b/include/Makefile.am</span><br><span>index b341ee3..572c880 100644</span><br><span>--- a/include/Makefile.am</span><br><span>+++ b/include/Makefile.am</span><br><span>@@ -90,6 +90,7 @@</span><br><span>                        osmocom/coding/gsm0503_mapping.h \</span><br><span>                        osmocom/coding/gsm0503_interleaving.h \</span><br><span>                        osmocom/coding/gsm0503_coding.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmocom/coding/gsm0503_amr_dtx.h \</span><br><span>                        osmocom/gsm/gsm0808.h \</span><br><span>                        osmocom/gsm/gsm29205.h \</span><br><span>                        osmocom/gsm/gsm0808_utils.h \</span><br><span>diff --git a/include/osmocom/coding/gsm0503_amr_dtx.h b/include/osmocom/coding/gsm0503_amr_dtx.h</span><br><span>new file mode 100644</span><br><span>index 0000000..f048a6e</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/coding/gsm0503_amr_dtx.h</span><br><span>@@ -0,0 +1,40 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file gsm0503_amr_dtx.h</span><br><span style="color: hsl(120, 100%, 40%);">+ *  GSM TS 05.03 coding</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/defs.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \addtogroup coding</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @{</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file gsm0503_amr_dtx.h */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum gsm0503_amr_dtx_frames {</span><br><span style="color: hsl(120, 100%, 40%);">+    AMR_OTHER,</span><br><span style="color: hsl(120, 100%, 40%);">+    AFS_SID_FIRST,</span><br><span style="color: hsl(120, 100%, 40%);">+        AFS_SID_UPDATE,</span><br><span style="color: hsl(120, 100%, 40%);">+       AFS_SID_UPDATE_CN,</span><br><span style="color: hsl(120, 100%, 40%);">+    AFS_ONSET,</span><br><span style="color: hsl(120, 100%, 40%);">+    AHS_SID_UPDATE,</span><br><span style="color: hsl(120, 100%, 40%);">+       AHS_SID_UPDATE_CN,</span><br><span style="color: hsl(120, 100%, 40%);">+    AHS_SID_FIRST_P1,</span><br><span style="color: hsl(120, 100%, 40%);">+     AHS_SID_FIRST_P2,</span><br><span style="color: hsl(120, 100%, 40%);">+     AHS_ONSET,</span><br><span style="color: hsl(120, 100%, 40%);">+    AHS_SID_FIRST_INH,</span><br><span style="color: hsl(120, 100%, 40%);">+    AHS_SID_UPDATE_INH,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string gsm0503_amr_dtx_frame_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const char *gsm0503_amr_dtx_frame_name(enum gsm0503_amr_dtx_frames frame)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        return get_value_string(gsm0503_amr_dtx_frame_names, frame);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum gsm0503_amr_dtx_frames gsm0503_detect_afs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t *ubits);</span><br><span style="color: hsl(120, 100%, 40%);">+enum gsm0503_amr_dtx_frames gsm0503_detect_ahs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t *ubits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/include/osmocom/coding/gsm0503_coding.h b/include/osmocom/coding/gsm0503_coding.h</span><br><span>index 98038f8..2afa049 100644</span><br><span>--- a/include/osmocom/coding/gsm0503_coding.h</span><br><span>+++ b/include/osmocom/coding/gsm0503_coding.h</span><br><span>@@ -58,12 +58,18 @@</span><br><span> int gsm0503_tch_afs_decode(uint8_t *tch_data, const sbit_t *bursts,</span><br><span>     int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span>         uint8_t *cmr, int *n_errors, int *n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0503_tch_afs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts,</span><br><span style="color: hsl(120, 100%, 40%);">+     int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx);</span><br><span> </span><br><span> int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,</span><br><span>   int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr);</span><br><span> int gsm0503_tch_ahs_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,</span><br><span>    int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span>         uint8_t *cmr, int *n_errors, int *n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0503_tch_ahs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts, int odd,</span><br><span style="color: hsl(120, 100%, 40%);">+    int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx);</span><br><span> </span><br><span> int gsm0503_rach_ext_encode(ubit_t *burst, uint16_t ra, uint8_t bsic, bool is_11bit);</span><br><span> int gsm0503_rach_encode(ubit_t *burst, const uint8_t *ra, uint8_t bsic) OSMO_DEPRECATED("Use gsm0503_rach_ext_encode() instead");</span><br><span>diff --git a/src/coding/Makefile.am b/src/coding/Makefile.am</span><br><span>index f47fe45..b023668 100644</span><br><span>--- a/src/coding/Makefile.am</span><br><span>+++ b/src/coding/Makefile.am</span><br><span>@@ -20,7 +20,8 @@</span><br><span>  gsm0503_mapping.c \</span><br><span>  gsm0503_tables.c \</span><br><span>   gsm0503_parity.c \</span><br><span style="color: hsl(0, 100%, 40%);">-      gsm0503_coding.c</span><br><span style="color: hsl(120, 100%, 40%);">+      gsm0503_coding.c \</span><br><span style="color: hsl(120, 100%, 40%);">+    gsm0503_amr_dtx.c</span><br><span> libosmocoding_la_LDFLAGS = \</span><br><span>    $(LTLDFLAGS_OSMOCODING) \</span><br><span>    -version-info \</span><br><span>diff --git a/src/coding/gsm0503_amr_dtx.c b/src/coding/gsm0503_amr_dtx.c</span><br><span>new file mode 100644</span><br><span>index 0000000..724cf09</span><br><span>--- /dev/null</span><br><span>+++ b/src/coding/gsm0503_amr_dtx.c</span><br><span>@@ -0,0 +1,314 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom - s.f.m.c. GmbH, Author: Philipp Maier</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/conv.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/coding/gsm0503_amr_dtx.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/coding/gsm0503_parity.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/gsm0503.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* See also: 3GPP TS 05.03, chapter 3.10.1.3, 3.10.5.2 Identification marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t id_marker_1[] = { 1, 0, 1, 1, 0, 0, 0, 0, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* See also: 3GPP TS 05.03, chapter 3.9.1.3, 3.10.2.2, 3.10.2.2 Identification marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t id_marker_0[] = { 0, 1, 0, 0, 1, 1, 1, 1, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* See also: 3GPP TS 05.03, chapter 3.9 Adaptive multi rate speech channel at full rate (TCH/AFS) */</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t codec_mode_1_sid[] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t codec_mode_2_sid[] = { 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t codec_mode_3_sid[] = { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t codec_mode_4_sid[] = { 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string gsm0503_amr_dtx_frame_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { AFS_SID_FIRST,        "AFS_SID_FIRST" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { AFS_SID_UPDATE,       "AFS_SID_UPDATE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { AFS_ONSET,            "AFS_ONSET" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { AHS_SID_UPDATE,       "AHS_SID_UPDATE" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { AHS_SID_FIRST_P1,     "AHS_SID_FIRST_P1" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { AHS_SID_FIRST_P2,     "AHS_SID_FIRST_P2" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { AHS_ONSET,            "AHS_ONSET" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { AHS_SID_FIRST_INH,    "AHS_SID_FIRST_INH" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { AHS_SID_UPDATE_INH,   "AHS_SID_UPDATE_INH" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { AMR_OTHER,            "NON DTX FRAME (OTHER)" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { 0, NULL }</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_afs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, uint8_t offset, uint8_t count,</span><br><span style="color: hsl(120, 100%, 40%);">+                             const ubit_t * id_marker, uint8_t id_marker_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int i, k;</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int id_bit_nr = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   int errors = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       int bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Override coded in-band data */</span><br><span style="color: hsl(120, 100%, 40%);">+     ubits += offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Check for identification marker bits */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < count; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              for (k = 0; k < 4; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (id_marker[id_bit_nr % id_marker_len] != *ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+                           errors++;</span><br><span style="color: hsl(120, 100%, 40%);">+                     id_bit_nr++;</span><br><span style="color: hsl(120, 100%, 40%);">+                  ubits++;</span><br><span style="color: hsl(120, 100%, 40%);">+                      bits++;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Jump to the next block of 4 bits */</span><br><span style="color: hsl(120, 100%, 40%);">+                ubits += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_errors = errors;</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_bits_total = bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Tolerate up to 1/8 errornous bits */</span><br><span style="color: hsl(120, 100%, 40%);">+       return *n_errors < *n_bits_total / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_ahs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, const ubit_t * id_marker)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int i, k;</span><br><span style="color: hsl(120, 100%, 40%);">+    int errors = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       int bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Override coded in-band data */</span><br><span style="color: hsl(120, 100%, 40%);">+     ubits += 16;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Check first identification marker bits (23*9 bits) */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < 23; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         for (k = 0; k < 9; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (id_marker[k] != *ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+                           errors++;</span><br><span style="color: hsl(120, 100%, 40%);">+                     ubits++;</span><br><span style="color: hsl(120, 100%, 40%);">+                      bits++;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Check remaining identification marker bits (5 bits) */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (k = 0; k < 5; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (id_marker[k] != *ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+                   errors++;</span><br><span style="color: hsl(120, 100%, 40%);">+             ubits++;</span><br><span style="color: hsl(120, 100%, 40%);">+              bits++;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_errors = errors;</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_bits_total = bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Tolerate up to 1/8 errornous bits */</span><br><span style="color: hsl(120, 100%, 40%);">+       return *n_errors < *n_bits_total / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_interleaved_ahs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, uint8_t offset,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        uint8_t n_bits, const ubit_t * id_marker, uint8_t id_marker_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int i, k;</span><br><span style="color: hsl(120, 100%, 40%);">+    int errors = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       int bits = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t full_rounds = n_bits / id_marker_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t remainder = n_bits % id_marker_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Override coded in-band data */</span><br><span style="color: hsl(120, 100%, 40%);">+     ubits += offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Check first identification marker bits (23*9 bits) */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < full_rounds; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                for (k = 0; k < id_marker_len; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (id_marker[k] != *ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+                           errors++;</span><br><span style="color: hsl(120, 100%, 40%);">+                     ubits += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                   bits++;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Check remaining identification marker bits (5 bits) */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (k = 0; k < remainder; k++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (id_marker[k] != *ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+                   errors++;</span><br><span style="color: hsl(120, 100%, 40%);">+             ubits += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+           bits++;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_errors = errors;</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_bits_total = bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Tolerate up to 1/8 errornous bits */</span><br><span style="color: hsl(120, 100%, 40%);">+       return *n_errors < *n_bits_total / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect a an FR AMR SID_FIRST frame by its identifcation marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_afs_sid_first(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return detect_afs_id_marker(n_errors, n_bits_total, ubits, 32, 53, id_marker_0, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an FR AMR SID_FIRST frame by its identification marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_afs_sid_update(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return detect_afs_id_marker(n_errors, n_bits_total, ubits, 36, 53, id_marker_0, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an FR AMR SID_FIRST frame by its repeating coded inband data */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_afs_onset(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  bool rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_1_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_2_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_3_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_4_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an HR AMR SID UPDATE frame by its identification marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_ahs_sid_update(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        return detect_ahs_id_marker(n_errors, n_bits_total, ubits, id_marker_1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an HR AMR SID FIRST (part 1) frame by its identification marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_ahs_sid_first_p1(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   return detect_ahs_id_marker(n_errors, n_bits_total, ubits, id_marker_0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an HR AMR SID FIRST (part 2) frame by its repeating coded inband data */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_ahs_sid_first_p2(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     bool rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_1_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_2_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_3_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_4_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an HR AMR ONSET frame by its repeating coded inband data */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_ahs_onset(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    bool rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_1_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_2_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_3_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_4_sid, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return true;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an HR AMR SID FIRST INHIBIT frame by its identification marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_ahs_sid_first_inh(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 33, 212, id_marker_1, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Detect an HR AMR SID UPDATE INHIBIT frame by its identification marker */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool detect_ahs_sid_update_inh(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 33, 212, id_marker_0, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Detect FR AMR DTX frame in unmapped, deinterleaved frame bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ubits input bits (456 bit).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_errors number of errornous bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_bits_total number of checked bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns dtx frame type. */</span><br><span style="color: hsl(120, 100%, 40%);">+enum gsm0503_amr_dtx_frames gsm0503_detect_afs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (detect_afs_sid_first(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+              return AFS_SID_FIRST;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (detect_afs_sid_update(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+             return AFS_SID_UPDATE;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (detect_afs_onset(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+          return AFS_ONSET;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_errors = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        *n_bits_total = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    return AMR_OTHER;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Detect HR AMR DTX frame in unmapped, deinterleaved frame bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ubits input bits (456 bit).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_errors number of errornous bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_bits_total number of checked bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns dtx frame type, */</span><br><span style="color: hsl(120, 100%, 40%);">+enum gsm0503_amr_dtx_frames gsm0503_detect_ahs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t * ubits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (detect_ahs_sid_update(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+             return AHS_SID_UPDATE;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (detect_ahs_sid_first_inh(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+          return AHS_SID_FIRST_INH;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (detect_ahs_sid_update_inh(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+         return AHS_SID_UPDATE_INH;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (detect_ahs_sid_first_p1(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+           return AHS_SID_FIRST_P1;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (detect_ahs_sid_first_p2(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+           return AHS_SID_FIRST_P2;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (detect_ahs_onset(n_errors, n_bits_total, ubits))</span><br><span style="color: hsl(120, 100%, 40%);">+          return AHS_ONSET;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   *n_errors = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        *n_bits_total = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    return AMR_OTHER;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/coding/gsm0503_coding.c b/src/coding/gsm0503_coding.c</span><br><span>index 5592433..1bec56e 100644</span><br><span>--- a/src/coding/gsm0503_coding.c</span><br><span>+++ b/src/coding/gsm0503_coding.c</span><br><span>@@ -47,6 +47,7 @@</span><br><span> #include <osmocom/coding/gsm0503_tables.h></span><br><span> #include <osmocom/coding/gsm0503_coding.h></span><br><span> #include <osmocom/coding/gsm0503_parity.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/coding/gsm0503_amr_dtx.h></span><br><span> </span><br><span> /*! \mainpage libosmocoding Documentation</span><br><span>  *</span><br><span>@@ -1635,6 +1636,39 @@</span><br><span>             d_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Append STI and MI bits to the SID_UPDATE frame, see also</span><br><span style="color: hsl(120, 100%, 40%);">+ * 3GPP TS 26.101, chapter 4.2.3 AMR Core Frame with comfort noise bits */</span><br><span style="color: hsl(120, 100%, 40%);">+static void tch_amr_sid_update_append(ubit_t *sid_update, uint8_t sti, uint8_t mi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Zero out the space that had been used by the CRC14 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memset(sid_update + 35, 0, 14);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Append STI and MI parameters */</span><br><span style="color: hsl(120, 100%, 40%);">+    sid_update[35] = sti & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ sid_update[36] = mi & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  sid_update[37] = mi >> 1 & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       sid_update[38] = mi >> 2 & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Extract a SID UPDATE fram the sbits of an FR AMR frame */</span><br><span style="color: hsl(120, 100%, 40%);">+static void extract_afs_sid_update(sbit_t *sid_update, const sbit_t *sbits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     sbits += 32;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < 53; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         sid_update[0] = sbits[0];</span><br><span style="color: hsl(120, 100%, 40%);">+             sid_update[1] = sbits[1];</span><br><span style="color: hsl(120, 100%, 40%);">+             sid_update[2] = sbits[2];</span><br><span style="color: hsl(120, 100%, 40%);">+             sid_update[3] = sbits[3];</span><br><span style="color: hsl(120, 100%, 40%);">+             sid_update += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+              sbits += 8;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* re-arrange according to TS 05.03 Table 2 (receiver) */</span><br><span> static void tch_fr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)</span><br><span> {</span><br><span>@@ -2101,10 +2135,37 @@</span><br><span>      int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span>         uint8_t *cmr, int *n_errors, int *n_bits_total)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+  return gsm0503_tch_afs_decode_dtx(tch_data, bursts, codec_mode_req,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     codec, codecs, ft, cmr, n_errors,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     n_bits_total, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Perform channel decoding of a TCH/AFS channel according TS 05.03</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] tch_data Codec frame in RTP payload format</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bursts buffer containing the symbols of 8 bursts</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] codec_mode_req is this CMR (1) or CMC (0)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] codec array of active codecs (active codec set)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] codecs number of codecs in \a codec</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param ft Frame Type; Input if \a codec_mode_req = 1, Output *  otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] cmr Output in \a codec_mode_req = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_errors Number of detected bit errors</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_bits_total Total number of bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[inout] dtx DTX frame type output, previous DTX frame type input</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])</span><br><span style="color: hsl(120, 100%, 40%);">+ *        codec out of range; negative on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0503_tch_afs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts,</span><br><span style="color: hsl(120, 100%, 40%);">+      int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span>     sbit_t iB[912], cB[456], h;</span><br><span>  ubit_t d[244], p[6], conv[250];</span><br><span>      int i, j, k, best = 0, rv, len, steal = 0, id = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t cBd[456];</span><br><span>     *n_errors = 0; *n_bits_total = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     static ubit_t sid_first_dummy[64] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+    sbit_t sid_update_enc[256];</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t dtx_prev;</span><br><span> </span><br><span>        for (i=0; i<8; i++) {</span><br><span>             gsm0503_tch_burst_unmap(&iB[i * 114], &bursts[i * 116], &h, i >> 2);</span><br><span>@@ -2123,6 +2184,50 @@</span><br><span>              return GSM_MACBLOCK_LEN;</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Determine the DTX frame type (SID_UPDATE, ONSET etc...) */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dtx) {</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_sbit2ubit(cBd, cB, 456);</span><br><span style="color: hsl(120, 100%, 40%);">+         dtx_prev = *dtx;</span><br><span style="color: hsl(120, 100%, 40%);">+              *dtx = gsm0503_detect_afs_dtx_frame(n_errors, n_bits_total, cBd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (dtx_prev == AFS_SID_UPDATE && *dtx == AMR_OTHER) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* NOTE: The AFS_SID_UPDATE frame is splitted into</span><br><span style="color: hsl(120, 100%, 40%);">+                     * two half rate frames. If the id marker frame</span><br><span style="color: hsl(120, 100%, 40%);">+                        * (AFS_SID_UPDATE) is detected the following frame</span><br><span style="color: hsl(120, 100%, 40%);">+                    * contains the actual comfort noised data part of</span><br><span style="color: hsl(120, 100%, 40%);">+                     * (AFS_SID_UPDATE_CN). */</span><br><span style="color: hsl(120, 100%, 40%);">+                    *dtx = AFS_SID_UPDATE_CN;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   extract_afs_sid_update(sid_update_enc, cB);</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_conv_decode_ber(&gsm0503_tch_axs_sid_update,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      sid_update_enc, conv, n_errors,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+                   rv = osmo_crc16gen_check_bits(&gsm0503_amr_crc14, conv,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 35, conv + 35);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (rv != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                /* Error checking CRC14 for an AMR SID_UPDATE frame */</span><br><span style="color: hsl(120, 100%, 40%);">+                                return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   tch_amr_sid_update_append(conv, 1,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              (codec_mode_req) ? codec[*ft]</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 : codec[id]);</span><br><span style="color: hsl(120, 100%, 40%);">+                       tch_amr_reassemble(tch_data, conv, 39);</span><br><span style="color: hsl(120, 100%, 40%);">+                       len = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto out;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (*dtx == AFS_SID_FIRST) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   tch_amr_sid_update_append(sid_first_dummy, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           (codec_mode_req) ? codec[*ft]</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 : codec[id]);</span><br><span style="color: hsl(120, 100%, 40%);">+                       tch_amr_reassemble(tch_data, conv, 39);</span><br><span style="color: hsl(120, 100%, 40%);">+                       len = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto out;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (*dtx == AFS_ONSET) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto out;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  for (i = 0; i < 4; i++) {</span><br><span>                 for (j = 0, k = 0; j < 8; j++)</span><br><span>                    k += abs(((int)gsm0503_afs_ic_sbit[i][j]) - ((int)cB[j]));</span><br><span>@@ -2283,6 +2388,7 @@</span><br><span>           return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+out:</span><br><span>  /* Change codec request / indication, if frame is valid */</span><br><span>   if (codec_mode_req)</span><br><span>          *cmr = id;</span><br><span>@@ -2480,9 +2586,36 @@</span><br><span>  int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span>         uint8_t *cmr, int *n_errors, int *n_bits_total)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+  return gsm0503_tch_ahs_decode_dtx(tch_data, bursts, odd, codec_mode_req,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        codec, codecs, ft, cmr, n_errors,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     n_bits_total, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Perform channel decoding of a TCH/AFS channel according TS 05.03</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] tch_data Codec frame in RTP payload format</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bursts buffer containing the symbols of 8 bursts</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] odd Is this an odd (1) or even (0) frame number?</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] codec_mode_req is this CMR (1) or CMC (0)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] codec array of active codecs (active codec set)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] codecs number of codecs in \a codec</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param ft Frame Type; Input if \a codec_mode_req = 1, Output *  otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] cmr Output in \a codec_mode_req = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_errors Number of detected bit errors</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] n_bits_total Total number of bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[inout] dtx DTX frame type output, previous DTX frame type input</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])</span><br><span style="color: hsl(120, 100%, 40%);">+ *               codec out of range; negative on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int gsm0503_tch_ahs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts, int odd,</span><br><span style="color: hsl(120, 100%, 40%);">+     int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span>     sbit_t iB[912], cB[456], h;</span><br><span>  ubit_t d[244], p[6], conv[135];</span><br><span>      int i, j, k, best = 0, rv, len, steal = 0, id = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t cBd[456];</span><br><span style="color: hsl(120, 100%, 40%);">+      static ubit_t sid_first_dummy[64] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t dtx_prev;</span><br><span> </span><br><span>        /* only unmap the stealing bits */</span><br><span>   if (!odd) {</span><br><span>@@ -2526,6 +2659,52 @@</span><br><span> </span><br><span>     gsm0503_tch_hr_deinterleave(cB, iB);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      /* Determine the DTX frame type (SID_UPDATE, ONSET etc...) */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dtx) {</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_sbit2ubit(cBd, cB, 456);</span><br><span style="color: hsl(120, 100%, 40%);">+         dtx_prev = *dtx;</span><br><span style="color: hsl(120, 100%, 40%);">+              *dtx = gsm0503_detect_ahs_dtx_frame(n_errors, n_bits_total, cBd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (dtx_prev == AHS_SID_UPDATE && *dtx == AMR_OTHER) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* NOTE: The AHS_SID_UPDATE frame is splitted into</span><br><span style="color: hsl(120, 100%, 40%);">+                     * two half rate frames. If the id marker frame</span><br><span style="color: hsl(120, 100%, 40%);">+                        * (AHS_SID_UPDATE) is detected the following frame</span><br><span style="color: hsl(120, 100%, 40%);">+                    * contains the actual comfort noised data part of</span><br><span style="color: hsl(120, 100%, 40%);">+                     * (AHS_SID_UPDATE_CN). */</span><br><span style="color: hsl(120, 100%, 40%);">+                    *dtx = AHS_SID_UPDATE_CN;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_conv_decode_ber(&gsm0503_tch_axs_sid_update,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      cB + 16, conv, n_errors,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+                   rv = osmo_crc16gen_check_bits(&gsm0503_amr_crc14, conv,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 35, conv + 35);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (rv != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                /* Error checking CRC14 for an AMR SID_UPDATE frame */</span><br><span style="color: hsl(120, 100%, 40%);">+                                return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   tch_amr_sid_update_append(conv, 1,</span><br><span style="color: hsl(120, 100%, 40%);">+                                              (codec_mode_req) ? codec[*ft]</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 : codec[id]);</span><br><span style="color: hsl(120, 100%, 40%);">+                       tch_amr_reassemble(tch_data, conv, 39);</span><br><span style="color: hsl(120, 100%, 40%);">+                       len = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto out;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (*dtx == AHS_SID_FIRST_P2) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        tch_amr_sid_update_append(sid_first_dummy, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           (codec_mode_req) ? codec[*ft]</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 : codec[id]);</span><br><span style="color: hsl(120, 100%, 40%);">+                       tch_amr_reassemble(tch_data, sid_first_dummy, 39);</span><br><span style="color: hsl(120, 100%, 40%);">+                    len = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto out;</span><br><span style="color: hsl(120, 100%, 40%);">+             } else if (*dtx == AHS_SID_UPDATE || *dtx == AHS_ONSET</span><br><span style="color: hsl(120, 100%, 40%);">+                           || *dtx == AHS_SID_FIRST_INH</span><br><span style="color: hsl(120, 100%, 40%);">+                          || *dtx == AHS_SID_UPDATE_INH</span><br><span style="color: hsl(120, 100%, 40%);">+                         || *dtx == AHS_SID_FIRST_P1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     len = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto out;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  for (i = 0; i < 4; i++) {</span><br><span>                 for (j = 0, k = 0; j < 4; j++)</span><br><span>                    k += abs(((int)gsm0503_ahs_ic_sbit[i][j]) - ((int)cB[j]));</span><br><span>@@ -2670,6 +2849,7 @@</span><br><span>           return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+out:</span><br><span>  /* Change codec request / indication, if frame is valid */</span><br><span>   if (codec_mode_req)</span><br><span>          *cmr = id;</span><br><span>diff --git a/src/coding/libosmocoding.map b/src/coding/libosmocoding.map</span><br><span>index 7f88111..325b6d8 100644</span><br><span>--- a/src/coding/libosmocoding.map</span><br><span>+++ b/src/coding/libosmocoding.map</span><br><span>@@ -107,8 +107,10 @@</span><br><span> gsm0503_tch_hr_decode;</span><br><span> gsm0503_tch_afs_encode;</span><br><span> gsm0503_tch_afs_decode;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0503_tch_afs_decode_dtx;</span><br><span> gsm0503_tch_ahs_encode;</span><br><span> gsm0503_tch_ahs_decode;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0503_tch_ahs_decode_dtx;</span><br><span> gsm0503_rach_ext_encode;</span><br><span> gsm0503_rach_ext_decode;</span><br><span> gsm0503_rach_ext_decode_ber;</span><br><span>@@ -117,6 +119,10 @@</span><br><span> gsm0503_rach_decode_ber;</span><br><span> gsm0503_sch_encode;</span><br><span> gsm0503_sch_decode;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0503_amr_dtx_frame_names;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0503_amr_dtx_frame_name;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0503_detect_afs_dtx_frame;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0503_detect_ahs_dtx_frame;</span><br><span> </span><br><span> local: *;</span><br><span> };</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index bf7017b..0d0327a 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -34,6 +34,7 @@</span><br><span>                  use_count/use_count_test                               \</span><br><span>             context/context_test                                   \</span><br><span>                  gsm0502/gsm0502_test                                      \</span><br><span style="color: hsl(120, 100%, 40%);">+                 dtx/dtx_gsm0503_test                                        \</span><br><span>             $(NULL)</span><br><span> </span><br><span> if ENABLE_MSGFILE</span><br><span>@@ -114,6 +115,10 @@</span><br><span> gsm0502_gsm0502_test_SOURCES = gsm0502/gsm0502_test.c</span><br><span> gsm0502_gsm0502_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+dtx_dtx_gsm0503_test_SOURCES = dtx/dtx_gsm0503_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+dtx_dtx_gsm0503_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la \</span><br><span style="color: hsl(120, 100%, 40%);">+                         $(top_builddir)/src/coding/libosmocoding.la</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> conv_conv_gsm0503_test_SOURCES = conv/conv_gsm0503_test.c conv/conv.c conv/gsm0503_test_vectors.c</span><br><span> conv_conv_gsm0503_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libgsmint.la</span><br><span> conv_conv_gsm0503_test_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/conv</span><br><span>@@ -339,6 +344,7 @@</span><br><span>              use_count/use_count_test.ok use_count/use_count_test.err \</span><br><span>           context/context_test.ok \</span><br><span>            gsm0502/gsm0502_test.ok \</span><br><span style="color: hsl(120, 100%, 40%);">+             dtx/dtx_gsm0503_test.ok \</span><br><span>            exec/exec_test.ok exec/exec_test.err \</span><br><span>       $(NULL)</span><br><span> </span><br><span>diff --git a/tests/dtx/dtx_gsm0503_test.c b/tests/dtx/dtx_gsm0503_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..f300313</span><br><span>--- /dev/null</span><br><span>+++ b/tests/dtx/dtx_gsm0503_test.c</span><br><span>@@ -0,0 +1,130 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Philipp Maier <pmaier@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/coding/gsm0503_amr_dtx.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_afs_sid_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"111111110000000011001100101010100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001111011100100010011111111001000100111011110011001001100111100110010011001"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_afs_sid_update_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"111111110000000011001100101010100000010000001111111100101011011110001001000000110111110000001001011111101111010011001111100000101000011111001001111100110111110011111001001111101100010001001111000000100100011100111001100000111000110000111001010011101111010011111111010000101100011100111001111100110111110011111001110011101000010010001111110000100000011111001001011100110011110010111001101111100011010001111111001100100100011111111001000000110000110000001001"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_afs_onset_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"111111110000000011001100101010100000111100000000111111000100101000111111100000000111110010001010001111110100000011111100111110100100111111000000110011001011101001001111011100001011110000001010010011111100000000111100111110101000111110110000111111000000101011111111010000001100110000111010111111111000000010111100000010100100111100110000100011001000101000111111101100001011110000111010011111110011000010111100101110101100111111000000010011001111101000001111"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_ahs_sid_update_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"111100001100101010110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110000110110100011001000011010000000000000001111010010000000000001000000000010110000000011001000000000000000100000101000000000000000001010100000010010000000000010000111110001110110110011001101000000000100100011001000001010000100100000000011"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_ahs_sid_first_p1_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"111100001100101001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001111001001001011010110001101100101001110001111001110100110010000111101110110110000100100011111001001110000011110110001010010101100001010100000111101110110001010000111110001110110110011001101001111000011101001010011100011000111010110000011"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_ahs_sid_first_p2_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"111110100100000010100000110111001110101100000100101001011101100011101010010000001010010010001100101010100100010111110101110011011110101000010100111000001001110111101110010101001110000010001101101011110000000011100100110110011111100011001000001101100101001110001111001110100110010000111101110110110000100100011111001001110000011110110001010010101100001010100000111101110110001010000111110001110110110011001101001111000011101001010011100011000111010110000011"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_ahs_onset_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"111101011000101001010000111001000111011110000000011110001110010011011111100000101101101001101110011111010000000001010010110001101101110100000010011110101100010001011101101010000111100011101100111101011010100011110010110001001111100011001000011010000000000000001010010010000000000001000000000000100000000011001000000000000000100000101000000000000000010010000101010010000000000010101100111110101000110110011001000000000100100011001000001010000100100000001100"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_sid_first_inh_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"xBxBxBxBxBxBxBxBxBxBxBxBxBxBxBxBx1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0x0x0x0x1x1x0x1x1x0"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char sample_sid_update_inh_frame[] =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+"xBxBxBxBxBxBxBxBxBxBxBxBxBxBxBxBx0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1x1x1x1x0x0x1x0x0x1"</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+unsigned int string_to_ubit(ubit_t * ubits, char *string)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int len;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     len = strlen(string);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ubits[i] = string[i] & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return len;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void test_gsm0503_detect_afs_dtx_frame(char *string)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     ubit_t ubits[512];</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t dtx_frame_type;</span><br><span style="color: hsl(120, 100%, 40%);">+       int n_errors;</span><br><span style="color: hsl(120, 100%, 40%);">+ int n_bits_total;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   string_to_ubit(ubits, string);</span><br><span style="color: hsl(120, 100%, 40%);">+        dtx_frame_type = gsm0503_detect_afs_dtx_frame(&n_errors, &n_bits_total, ubits);</span><br><span style="color: hsl(120, 100%, 40%);">+       printf(" ==> %s, n_errors=%i, n_bits_total=%i\n", gsm0503_amr_dtx_frame_name(dtx_frame_type),</span><br><span style="color: hsl(120, 100%, 40%);">+           n_errors, n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void test_gsm0503_detect_ahs_dtx_frame(char *string)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ubit_t ubits[512];</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t dtx_frame_type;</span><br><span style="color: hsl(120, 100%, 40%);">+       int n_errors;</span><br><span style="color: hsl(120, 100%, 40%);">+ int n_bits_total;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   string_to_ubit(ubits, string);</span><br><span style="color: hsl(120, 100%, 40%);">+        dtx_frame_type = gsm0503_detect_ahs_dtx_frame(&n_errors, &n_bits_total, ubits);</span><br><span style="color: hsl(120, 100%, 40%);">+       printf(" ==> %s, n_errors=%i, n_bits_total=%i\n", gsm0503_amr_dtx_frame_name(dtx_frame_type),</span><br><span style="color: hsl(120, 100%, 40%);">+           n_errors, n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int main(int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("FR AMR DTX FRAMES:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+     test_gsm0503_detect_afs_dtx_frame(sample_afs_sid_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+      test_gsm0503_detect_afs_dtx_frame(sample_afs_sid_update_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+       test_gsm0503_detect_afs_dtx_frame(sample_afs_onset_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("HR AMR DTX FRAMES:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+     test_gsm0503_detect_ahs_dtx_frame(sample_ahs_sid_update_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+       test_gsm0503_detect_ahs_dtx_frame(sample_ahs_sid_first_p1_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+     test_gsm0503_detect_ahs_dtx_frame(sample_ahs_sid_first_p2_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+     test_gsm0503_detect_ahs_dtx_frame(sample_ahs_onset_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+    test_gsm0503_detect_ahs_dtx_frame(sample_sid_first_inh_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+        test_gsm0503_detect_ahs_dtx_frame(sample_sid_update_inh_frame);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return EXIT_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/dtx/dtx_gsm0503_test.ok b/tests/dtx/dtx_gsm0503_test.ok</span><br><span>new file mode 100644</span><br><span>index 0000000..a95a18b</span><br><span>--- /dev/null</span><br><span>+++ b/tests/dtx/dtx_gsm0503_test.ok</span><br><span>@@ -0,0 +1,11 @@</span><br><span style="color: hsl(120, 100%, 40%);">+FR AMR DTX FRAMES:</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AFS_SID_FIRST, n_errors=0, n_bits_total=212</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AFS_SID_UPDATE, n_errors=0, n_bits_total=212</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AFS_ONSET, n_errors=0, n_bits_total=228</span><br><span style="color: hsl(120, 100%, 40%);">+HR AMR DTX FRAMES:</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AHS_SID_UPDATE, n_errors=0, n_bits_total=212</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AHS_SID_FIRST_P1, n_errors=0, n_bits_total=212</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AHS_SID_FIRST_P2, n_errors=0, n_bits_total=114</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AHS_ONSET, n_errors=0, n_bits_total=114</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AHS_SID_FIRST_INH, n_errors=0, n_bits_total=212</span><br><span style="color: hsl(120, 100%, 40%);">+ ==> AHS_SID_UPDATE_INH, n_errors=0, n_bits_total=212</span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index cb83ab9..bab5730 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -132,6 +132,12 @@</span><br><span> AT_CHECK([$abs_top_builddir/tests/gsm0502/gsm0502_test], [0], [expout], [ignore])</span><br><span> AT_CLEANUP</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+AT_SETUP([dtx])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([dtx])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/dtx/dtx_gsm0503_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/dtx/dtx_gsm0503_test], [0], [expout], [ignore])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CLEANUP</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> AT_SETUP([gsm0808])</span><br><span> AT_KEYWORDS([gsm0808])</span><br><span> cat $abs_srcdir/gsm0808/gsm0808_test.ok > expout</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/17095">change 17095</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/17095"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I2bbdb39ea20461ca08b2e6f1a33532cb55cd5195 </div>
<div style="display:none"> Gerrit-Change-Number: 17095 </div>
<div style="display:none"> Gerrit-PatchSet: 13 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>