aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2020-05-13 23:10:31 +0200
committerHarald Welte <laforge@osmocom.org>2020-05-14 14:51:22 +0200
commit5785a4a8fc3c0c685e02b969ad07c1751502f0d5 (patch)
tree12b092b74d2dbe0b1f40a6ef18bf5a469bcb9434 /src
parentddb7586e9d9f4ca4dec3fedae44ecf0ec8231e96 (diff)
codec: Add functions for AMR s->d bits and d->s bits
These functions implement re-ordering of bits as per TS 06.90 / 26.101 based on the already existing tables we've had in libosmocoding. Change-Id: Ia4ac2aea2e96f9185f082a07ca64dfc5276efb46
Diffstat (limited to 'src')
-rw-r--r--src/codec/Makefile.am2
-rw-r--r--src/codec/gsm690.c110
2 files changed, 111 insertions, 1 deletions
diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am
index ac33aa01..778eb2ad 100644
--- a/src/codec/Makefile.am
+++ b/src/codec/Makefile.am
@@ -3,7 +3,7 @@
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
LIBVERSION=2:0:2
-AM_CPPFLAGS = -I$(top_srcdir)/include $(TALLOC_CFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include $(TALLOC_CFLAGS)
AM_CFLAGS = -Wall
if ENABLE_PSEUDOTALLOC
diff --git a/src/codec/gsm690.c b/src/codec/gsm690.c
index 8ab1df12..cc6cdf0c 100644
--- a/src/codec/gsm690.c
+++ b/src/codec/gsm690.c
@@ -2,6 +2,7 @@
* GSM 06.90 - GSM AMR Codec. */
/*
* (C) 2010 Sylvain Munaut <tnt@246tNt.com>
+ * (C) 2020 Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -29,6 +30,7 @@
#include <stdlib.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
#include <osmocom/codec/codec.h>
/*
* These table map between the raw encoder parameter output and
@@ -216,6 +218,114 @@ const uint16_t gsm690_4_75_bitorder[95] = {
92, 31, 52, 65, 86,
};
+/*! These constants refer to the length of one "AMR core frame" as per
+ * TS 26.101 Section 4.2.2 / Table 2. */
+const uint8_t gsm690_bitlength[AMR_NO_DATA+1] = {
+ [AMR_4_75] = 95,
+ [AMR_5_15] = 103,
+ [AMR_5_90] = 118,
+ [AMR_6_70] = 134,
+ [AMR_7_40] = 148,
+ [AMR_7_95] = 159,
+ [AMR_10_2] = 204,
+ [AMR_12_2] = 244,
+ [AMR_SID] = 39,
+};
+
+struct ts26101_reorder_table {
+ /*! Table as per TS 26.101 Annex B to compute d-bits from s-bits */
+ const uint16_t *s_to_d;
+ /*! size of table */
+ uint8_t len;
+};
+
+static const struct ts26101_reorder_table ts26101_reorder_tables[8] = {
+ [AMR_4_75] = {
+ .s_to_d = gsm690_4_75_bitorder,
+ .len = ARRAY_SIZE(gsm690_4_75_bitorder),
+ },
+ [AMR_5_15] = {
+ .s_to_d = gsm690_5_15_bitorder,
+ .len = ARRAY_SIZE(gsm690_5_15_bitorder),
+ },
+ [AMR_5_90] = {
+ .s_to_d = gsm690_5_9_bitorder,
+ .len = ARRAY_SIZE(gsm690_5_9_bitorder),
+ },
+ [AMR_6_70] = {
+ .s_to_d = gsm690_6_7_bitorder,
+ .len = ARRAY_SIZE(gsm690_6_7_bitorder),
+ },
+ [AMR_7_40] = {
+ .s_to_d = gsm690_7_4_bitorder,
+ .len = ARRAY_SIZE(gsm690_7_4_bitorder),
+ },
+ [AMR_7_95] = {
+ .s_to_d = gsm690_7_95_bitorder,
+ .len = ARRAY_SIZE(gsm690_7_95_bitorder),
+ },
+ [AMR_10_2] = {
+ .s_to_d = gsm690_10_2_bitorder,
+ .len = ARRAY_SIZE(gsm690_10_2_bitorder),
+ },
+ [AMR_12_2] = {
+ .s_to_d = gsm690_12_2_bitorder,
+ .len = ARRAY_SIZE(gsm690_12_2_bitorder),
+ },
+};
+
+/*! Convert from S-bits (codec output) to d-bits.
+ * \param[out] out user-provided output buffer for generated unpacked d-bits
+ * \param[in] in input buffer for unpacked s-bits
+ * \param[in] n_bits number of bits (in both in and out)
+ * \param[in] AMR mode (0..7) */
+int osmo_amr_s_to_d(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode)
+{
+ const struct ts26101_reorder_table *tbl;
+ int i;
+
+ if (amr_mode >= ARRAY_SIZE(ts26101_reorder_tables))
+ return -ENODEV;
+
+ tbl = &ts26101_reorder_tables[amr_mode];
+
+ if (n_bits > tbl->len)
+ return -EINVAL;
+
+ for (i = 0; i < n_bits; i++) {
+ uint16_t n = tbl->s_to_d[i];
+ out[i] = in[n];
+ }
+
+ return n_bits;
+}
+
+/*! Convert from d-bits to s-bits (codec input).
+ * \param[out] out user-provided output buffer for generated unpacked s-bits
+ * \param[in] in input buffer for unpacked d-bits
+ * \param[in] n_bits number of bits (in both in and out)
+ * \param[in] AMR mode (0..7) */
+int osmo_amr_d_to_s(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode)
+{
+ const struct ts26101_reorder_table *tbl;
+ int i;
+
+ if (amr_mode >= ARRAY_SIZE(ts26101_reorder_tables))
+ return -ENODEV;
+
+ tbl = &ts26101_reorder_tables[amr_mode];
+
+ if (n_bits > tbl->len)
+ return -EINVAL;
+
+ for (i = 0; i < n_bits; i++) {
+ uint16_t n = tbl->s_to_d[i];
+ out[n] = in[i];
+ }
+
+ return n_bits;
+}
+
/* See also RFC 4867 ยง3.6, Table 1, Column "Total speech bits" */
static const uint8_t amr_len_by_ft[16] = {
12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0