diff options
author | Harald Welte <laforge@osmocom.org> | 2020-05-13 23:10:31 +0200 |
---|---|---|
committer | Harald Welte <laforge@osmocom.org> | 2020-05-14 14:51:22 +0200 |
commit | 5785a4a8fc3c0c685e02b969ad07c1751502f0d5 (patch) | |
tree | 12b092b74d2dbe0b1f40a6ef18bf5a469bcb9434 /src | |
parent | ddb7586e9d9f4ca4dec3fedae44ecf0ec8231e96 (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.am | 2 | ||||
-rw-r--r-- | src/codec/gsm690.c | 110 |
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 |