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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">codec: Add functions for AMR s->d bits and d->s bits<br><br>These functions implement re-ordering of bits as per TS 06.90 / 26.101<br>based on the already existing tables we've had in libosmocoding.<br><br>Change-Id: Ia4ac2aea2e96f9185f082a07ca64dfc5276efb46<br>---<br>M include/osmocom/codec/codec.h<br>M src/codec/Makefile.am<br>M src/codec/gsm690.c<br>M tests/codec/codec_test.c<br>M tests/codec/codec_test.ok<br>5 files changed, 165 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h</span><br><span>index 6a1bf9f..cbdad75 100644</span><br><span>--- a/include/osmocom/codec/codec.h</span><br><span>+++ b/include/osmocom/codec/codec.h</span><br><span>@@ -6,6 +6,7 @@</span><br><span> #include <stdbool.h></span><br><span> </span><br><span> #include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span> </span><br><span> /* TS 101318 Chapter 5.1: 260 bits + 4bit sig */</span><br><span> #define GSM_FR_BYTES        33</span><br><span>@@ -51,6 +52,11 @@</span><br><span>        AMR_GOOD = 1</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+extern const uint8_t gsm690_bitlength[AMR_NO_DATA+1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_amr_s_to_d(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_amr_d_to_s(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Check if given AMR Frame Type is a speech frame</span><br><span>  *  \param[in] ft AMR Frame Type</span><br><span>  *  \returns true if AMR with given Frame Type contains voice, false otherwise</span><br><span>diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am</span><br><span>index ac33aa0..778eb2a 100644</span><br><span>--- a/src/codec/Makefile.am</span><br><span>+++ b/src/codec/Makefile.am</span><br><span>@@ -3,7 +3,7 @@</span><br><span> # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html</span><br><span> LIBVERSION=2:0:2</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-AM_CPPFLAGS = -I$(top_srcdir)/include $(TALLOC_CFLAGS)</span><br><span style="color: hsl(120, 100%, 40%);">+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include $(TALLOC_CFLAGS)</span><br><span> AM_CFLAGS = -Wall</span><br><span> </span><br><span> if ENABLE_PSEUDOTALLOC</span><br><span>diff --git a/src/codec/gsm690.c b/src/codec/gsm690.c</span><br><span>index 8ab1df1..cc6cdf0 100644</span><br><span>--- a/src/codec/gsm690.c</span><br><span>+++ b/src/codec/gsm690.c</span><br><span>@@ -2,6 +2,7 @@</span><br><span>  * GSM 06.90 - GSM AMR Codec. */</span><br><span> /*</span><br><span>  * (C) 2010 Sylvain Munaut <tnt@246tNt.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 Harald Welte <laforge@gnumonks.org></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>  *</span><br><span>@@ -29,6 +30,7 @@</span><br><span> #include <stdlib.h></span><br><span> </span><br><span> #include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/bits.h></span><br><span> #include <osmocom/codec/codec.h></span><br><span> /*</span><br><span>  * These table map between the raw encoder parameter output and</span><br><span>@@ -216,6 +218,114 @@</span><br><span>    92,  31,  52,  65,  86,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! These constants refer to the length of one "AMR core frame" as per</span><br><span style="color: hsl(120, 100%, 40%);">+ *  TS 26.101 Section 4.2.2 / Table 2. */</span><br><span style="color: hsl(120, 100%, 40%);">+const uint8_t gsm690_bitlength[AMR_NO_DATA+1] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_4_75] = 95,</span><br><span style="color: hsl(120, 100%, 40%);">+      [AMR_5_15] = 103,</span><br><span style="color: hsl(120, 100%, 40%);">+     [AMR_5_90] = 118,</span><br><span style="color: hsl(120, 100%, 40%);">+     [AMR_6_70] = 134,</span><br><span style="color: hsl(120, 100%, 40%);">+     [AMR_7_40] = 148,</span><br><span style="color: hsl(120, 100%, 40%);">+     [AMR_7_95] = 159,</span><br><span style="color: hsl(120, 100%, 40%);">+     [AMR_10_2] = 204,</span><br><span style="color: hsl(120, 100%, 40%);">+     [AMR_12_2] = 244,</span><br><span style="color: hsl(120, 100%, 40%);">+     [AMR_SID] = 39,</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%);">+struct ts26101_reorder_table {</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Table as per TS 26.101 Annex B to compute d-bits from s-bits */</span><br><span style="color: hsl(120, 100%, 40%);">+   const uint16_t *s_to_d;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! size of table */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t 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%);">+static const struct ts26101_reorder_table ts26101_reorder_tables[8] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   [AMR_4_75] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_4_75_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+               .len = ARRAY_SIZE(gsm690_4_75_bitorder),</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_5_15] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_5_15_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+               .len = ARRAY_SIZE(gsm690_5_15_bitorder),</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_5_90] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_5_9_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+                .len = ARRAY_SIZE(gsm690_5_9_bitorder),</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_6_70] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_6_7_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+                .len = ARRAY_SIZE(gsm690_6_7_bitorder),</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_7_40] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_7_4_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+                .len = ARRAY_SIZE(gsm690_7_4_bitorder),</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_7_95] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_7_95_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+               .len = ARRAY_SIZE(gsm690_7_95_bitorder),</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_10_2] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_10_2_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+               .len = ARRAY_SIZE(gsm690_10_2_bitorder),</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    [AMR_12_2] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .s_to_d = gsm690_12_2_bitorder,</span><br><span style="color: hsl(120, 100%, 40%);">+               .len = ARRAY_SIZE(gsm690_12_2_bitorder),</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%);">+/*! Convert from S-bits (codec output) to d-bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] out user-provided output buffer for generated unpacked d-bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] in input buffer for unpacked s-bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] n_bits number of bits (in both in and out)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] AMR mode (0..7) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_amr_s_to_d(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct ts26101_reorder_table *tbl;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (amr_mode >= ARRAY_SIZE(ts26101_reorder_tables))</span><br><span style="color: hsl(120, 100%, 40%);">+                return -ENODEV;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     tbl = &ts26101_reorder_tables[amr_mode];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (n_bits > tbl->len)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < n_bits; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             uint16_t n = tbl->s_to_d[i];</span><br><span style="color: hsl(120, 100%, 40%);">+               out[i] = in[n];</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 n_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%);">+/*! Convert from d-bits to s-bits (codec input).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] out user-provided output buffer for generated unpacked s-bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] in input buffer for unpacked d-bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] n_bits number of bits (in both in and out)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] AMR mode (0..7) */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_amr_d_to_s(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct ts26101_reorder_table *tbl;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (amr_mode >= ARRAY_SIZE(ts26101_reorder_tables))</span><br><span style="color: hsl(120, 100%, 40%);">+                return -ENODEV;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     tbl = &ts26101_reorder_tables[amr_mode];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (n_bits > tbl->len)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < n_bits; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             uint16_t n = tbl->s_to_d[i];</span><br><span style="color: hsl(120, 100%, 40%);">+               out[n] = in[i];</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 n_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* See also RFC 4867 ยง3.6, Table 1, Column "Total speech bits" */</span><br><span> static const uint8_t amr_len_by_ft[16] = {</span><br><span>    12, 13, 15, 17, 19, 20, 26, 31, 5,  0,  0,  0,  0,  0,  0,  0</span><br><span>diff --git a/tests/codec/codec_test.c b/tests/codec/codec_test.c</span><br><span>index 7a10fc5..5579e99 100644</span><br><span>--- a/tests/codec/codec_test.c</span><br><span>+++ b/tests/codec/codec_test.c</span><br><span>@@ -190,6 +190,42 @@</span><br><span>    }</span><br><span> }</span><br><span> </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 void test_amr_s_d(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     ubit_t in[244];</span><br><span style="color: hsl(120, 100%, 40%);">+       ubit_t mid[244];</span><br><span style="color: hsl(120, 100%, 40%);">+      ubit_t out[244];</span><br><span style="color: hsl(120, 100%, 40%);">+      int i, j;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (j = AMR_4_75; j <= AMR_12_2; j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           unsigned int n_bits = gsm690_bitlength[j];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          printf("=> AMR Mode %d (%d bits)\n", j, n_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+         /* set a single bit in the input buffer */</span><br><span style="color: hsl(120, 100%, 40%);">+            for (i = 0; i < n_bits; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   memset(in, 0, sizeof(in));</span><br><span style="color: hsl(120, 100%, 40%);">+                    in[i] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* re-order from s to d */</span><br><span style="color: hsl(120, 100%, 40%);">+                    osmo_amr_s_to_d(mid, in, n_bits, j);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* and back to d */</span><br><span style="color: hsl(120, 100%, 40%);">+                   osmo_amr_d_to_s(out, mid, n_bits, j);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (memcmp(in, out, n_bits)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                printf("Error in bit %d of mode %d!\n", i, j);</span><br><span style="color: hsl(120, 100%, 40%);">+                              printf("inp s-bits: %s\n", osmo_ubit_dump(in, n_bits));</span><br><span style="color: hsl(120, 100%, 40%);">+                             printf("mid d-bits: %s\n", osmo_ubit_dump(mid, n_bits));</span><br><span style="color: hsl(120, 100%, 40%);">+                            printf("out s-bits: %s\n", osmo_ubit_dump(out, n_bits));</span><br><span style="color: hsl(120, 100%, 40%);">+                            //OSMO_ASSERT(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%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span>       printf("AMR RTP payload decoder test:\n");</span><br><span>@@ -213,6 +249,9 @@</span><br><span>   printf("FR RTP payload SID test:\n");</span><br><span>      test_sid_fr();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    printf("AMR s/d bit re-ordering test:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  test_amr_s_d();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span>diff --git a/tests/codec/codec_test.ok b/tests/codec/codec_test.ok</span><br><span>index b8cba19..7d8609b 100644</span><br><span>--- a/tests/codec/codec_test.ok</span><br><span>+++ b/tests/codec/codec_test.ok</span><br><span>@@ -30,3 +30,12 @@</span><br><span> FR SID d8 62 a2 61 60 00 00 10 00 00 92 00 00 00 00 40 00 00 08 00 00 00 01 00 00 01 00 00 80 00 40 02 40 : 1</span><br><span> FR SID d9 e4 c3 6d 12 00 00 80 00 20 00 40 00 00 00 00 00 10 00 00 00 10 48 00 10 48 00 00 00 00 2d 04 00 : 1</span><br><span> FR SID d9 a4 c3 29 59 00 00 10 00 00 12 00 00 00 00 41 00 00 01 00 00 00 01 00 80 00 00 00 00 42 00 12 02 : 1</span><br><span style="color: hsl(120, 100%, 40%);">+AMR s/d bit re-ordering test:</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 0 (95 bits)</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 1 (103 bits)</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 2 (118 bits)</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 3 (134 bits)</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 4 (148 bits)</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 5 (159 bits)</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 6 (204 bits)</span><br><span style="color: hsl(120, 100%, 40%);">+=> AMR Mode 7 (244 bits)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/18246">change 18246</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/+/18246"/><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: Ia4ac2aea2e96f9185f082a07ca64dfc5276efb46 </div>
<div style="display:none"> Gerrit-Change-Number: 18246 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: tnt <tnt@246tNt.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>