From 678c7fc8fe4fd11e09ccd642ad60c10c365bd19a Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 19 Dec 2022 14:36:49 +0100 Subject: [PATCH] amr: Support all SID and NO_DATA amr formats Related: SYS#6161 Change-Id: I0e766b3231f03ea87d89fad6ecdce3bd14769054 --- include/osmocom/netif/amr.h | 53 ++++++++++++++++++----------- src/amr.c | 67 +++++++++++++++++++++---------------- tests/amr/amr_test.c | 3 +- tests/amr/amr_test.ok | 28 ++++++++++------ 4 files changed, 93 insertions(+), 58 deletions(-) diff --git a/include/osmocom/netif/amr.h b/include/osmocom/netif/amr.h index c7ca5bb..0eb26e2 100644 --- a/include/osmocom/netif/amr.h +++ b/include/osmocom/netif/amr.h @@ -99,31 +99,41 @@ static inline void *osmo_amr_get_payload(struct amr_hdr *amrh) /* AMR voice frame type identifiers * See also 3GPP TS 26.101, Table 1a: Interpretation of Frame Type, Mode * Indication and Mode Request fields */ -#define AMR_FT_0 0 /* 4.75 */ -#define AMR_FT_1 1 /* 5.15 */ -#define AMR_FT_2 2 /* 5.90 */ -#define AMR_FT_3 3 /* 6.70 */ -#define AMR_FT_4 4 /* 7.40 */ -#define AMR_FT_5 5 /* 7.95 */ -#define AMR_FT_6 6 /* 10.2 */ -#define AMR_FT_7 7 /* 12.2 */ -#define AMR_FT_SID 8 /* SID */ -#define AMR_FT_MAX 9 +#define AMR_FT_0 0 /* 4.75 */ +#define AMR_FT_1 1 /* 5.15 */ +#define AMR_FT_2 2 /* 5.90 */ +#define AMR_FT_3 3 /* 6.70 */ +#define AMR_FT_4 4 /* 7.40 */ +#define AMR_FT_5 5 /* 7.95 */ +#define AMR_FT_6 6 /* 10.2 */ +#define AMR_FT_7 7 /* 12.2 */ +#define AMR_FT_SID 8 /* AMR SID */ +#define AMR_FT_GSM_EFR_SID 9 /* GSM-EFR SID */ +#define AMR_FT_TDMA_EFR_SID 10 /* TDMA-EFR SID */ +#define AMR_FT_PDC_EFR_SID 11 /* PDC-EFR SID */ +/* version 16.0.0 Release 16: 12-14 for future use */ +#define AMR_FT_NO_DATA 15 /* NO_DATA */ +#define AMR_FT_MAX 16 /* INTERNAL, NO NOT USE OUTSIDE libosmo-netif */ /* AMR voice frame length (in bits). * See also RFC 3267, chapter 3.6. * * NOTE: These constants refer to the length of one AMR speech frame-block, * not counting CMR, TOC. */ -#define AMR_FT_0_LEN_BITS 95 /* 4.75 */ -#define AMR_FT_1_LEN_BITS 103 /* 5.15 */ -#define AMR_FT_2_LEN_BITS 118 /* 5.90 */ -#define AMR_FT_3_LEN_BITS 134 /* 6.70 */ -#define AMR_FT_4_LEN_BITS 148 /* 7.40 */ -#define AMR_FT_5_LEN_BITS 159 /* 7.95 */ -#define AMR_FT_6_LEN_BITS 204 /* 10.2 */ -#define AMR_FT_7_LEN_BITS 244 /* 12.2 */ -#define AMR_FT_SID_LEN_BITS 39 /* SID */ +#define AMR_FT_0_LEN_BITS 95 /* 4.75 */ +#define AMR_FT_1_LEN_BITS 103 /* 5.15 */ +#define AMR_FT_2_LEN_BITS 118 /* 5.90 */ +#define AMR_FT_3_LEN_BITS 134 /* 6.70 */ +#define AMR_FT_4_LEN_BITS 148 /* 7.40 */ +#define AMR_FT_5_LEN_BITS 159 /* 7.95 */ +#define AMR_FT_6_LEN_BITS 204 /* 10.2 */ +#define AMR_FT_7_LEN_BITS 244 /* 12.2 */ +#define AMR_FT_SID_LEN_BITS 39 /* SID */ +#define AMR_FT_GSM_EFR_SID_LEN_BITS 43 /* GSM-EFR SID */ +#define AMR_FT_TDMA_EFR_SID_LEN_BITS 38 /* TDMA-EFR SID */ +#define AMR_FT_PDC_EFR_SID_LEN_BITS 37 /* PDC-EFR SID */ +/* version 16.0.0 Release 16: 12-14 for future use */ +#define AMR_FT_NO_DATA_LEN_BITS 0 /* NO_DATA */ /* AMR voice frame length (in bytes, rounded). * @@ -138,6 +148,11 @@ static inline void *osmo_amr_get_payload(struct amr_hdr *amrh) #define AMR_FT_6_LEN ((AMR_FT_6_LEN_BITS+7)/8) /* 10.2 */ #define AMR_FT_7_LEN ((AMR_FT_7_LEN_BITS+7)/8) /* 12.2 */ #define AMR_FT_SID_LEN ((AMR_FT_SID_LEN_BITS+7)/8) /* SID */ +#define AMR_FT_GSM_EFR_SID_LEN 43 /* GSM-EFR SID */ +#define AMR_FT_TDMA_EFR_SID_LEN 38 /* TDMA-EFR SID */ +#define AMR_FT_PDC_EFR_SID_LEN 37 /* PDC-EFR SID */ +/* version 16.0.0 Release 16: 12-14 for future use */ +#define AMR_FT_NO_DATA_LEN 0 /* NO_DATA */ int osmo_amr_ft_valid(uint8_t amr_ft); size_t osmo_amr_bytes(uint8_t amr_cmr); diff --git a/src/amr.c b/src/amr.c index a40e496..66f41c6 100644 --- a/src/amr.c +++ b/src/amr.c @@ -18,7 +18,7 @@ #include #include -/* According to TS 26.101: +/* According to TS 26.101 Table A.1b: * * Frame type AMR code bits bytes * 0 4.75 95 12 @@ -29,19 +29,33 @@ * 5 7.95 159 20 * 6 10.20 204 26 * 7 12.20 244 31 - * 8 SID 39 5 + * 8 AMR SID 39 5 + * 9 GSM-EFR SID 43 5 + * 10 TDMA-EFR SID 38 5 + * 11 PDC-EFR SID 37 5 + * 12 NOT USED + * 13 NOT USED + * 14 NOT USED + * 15 NO DATA 0 0 */ -static size_t amr_ft_to_bits[AMR_FT_MAX] = { - [AMR_FT_0] = AMR_FT_0_LEN_BITS, - [AMR_FT_1] = AMR_FT_1_LEN_BITS, - [AMR_FT_2] = AMR_FT_2_LEN_BITS, - [AMR_FT_3] = AMR_FT_3_LEN_BITS, - [AMR_FT_4] = AMR_FT_4_LEN_BITS, - [AMR_FT_5] = AMR_FT_5_LEN_BITS, - [AMR_FT_6] = AMR_FT_6_LEN_BITS, - [AMR_FT_7] = AMR_FT_7_LEN_BITS, - [AMR_FT_SID] = AMR_FT_SID_LEN_BITS, +static int amr_ft_to_bits[AMR_FT_MAX] = { + [AMR_FT_0] = AMR_FT_0_LEN_BITS, + [AMR_FT_1] = AMR_FT_1_LEN_BITS, + [AMR_FT_2] = AMR_FT_2_LEN_BITS, + [AMR_FT_3] = AMR_FT_3_LEN_BITS, + [AMR_FT_4] = AMR_FT_4_LEN_BITS, + [AMR_FT_5] = AMR_FT_5_LEN_BITS, + [AMR_FT_6] = AMR_FT_6_LEN_BITS, + [AMR_FT_7] = AMR_FT_7_LEN_BITS, + [AMR_FT_SID] = AMR_FT_SID_LEN_BITS, + [AMR_FT_GSM_EFR_SID] = AMR_FT_GSM_EFR_SID_LEN_BITS, + [AMR_FT_TDMA_EFR_SID] = AMR_FT_TDMA_EFR_SID_LEN_BITS, + [AMR_FT_PDC_EFR_SID] = AMR_FT_PDC_EFR_SID_LEN_BITS, + [12] = 0, /* for future use */ + [13] = 0, /* for future use */ + [14] = 0, /* for future use */ + [AMR_FT_NO_DATA] = AMR_FT_NO_DATA_LEN_BITS, }; static size_t amr_ft_to_bytes[AMR_FT_MAX] = { @@ -54,6 +68,13 @@ static size_t amr_ft_to_bytes[AMR_FT_MAX] = { [AMR_FT_6] = AMR_FT_6_LEN, [AMR_FT_7] = AMR_FT_7_LEN, [AMR_FT_SID] = AMR_FT_SID_LEN, + [AMR_FT_GSM_EFR_SID] = AMR_FT_GSM_EFR_SID_LEN, + [AMR_FT_TDMA_EFR_SID] = AMR_FT_TDMA_EFR_SID_LEN, + [AMR_FT_PDC_EFR_SID] = AMR_FT_PDC_EFR_SID_LEN, + [12] = 0, /* for future use */ + [13] = 0, /* for future use */ + [14] = 0, /* for future use */ + [AMR_FT_NO_DATA] = AMR_FT_NO_DATA_LEN, }; size_t osmo_amr_bits(uint8_t amr_ft) @@ -72,30 +93,20 @@ int osmo_amr_bytes_to_ft(size_t bytes) { int ft; - for (ft = 0; ft < AMR_FT_MAX; ft++) { + for (ft = 0; ft < AMR_FT_PDC_EFR_SID; ft++) { if (amr_ft_to_bytes[ft] == bytes) return ft; } + /* 12-14 not used, jump to 15 (AMR_FT_NO_DATA): */ + if (amr_ft_to_bytes[AMR_FT_NO_DATA] == bytes) + return AMR_FT_NO_DATA; + return -1; } int osmo_amr_ft_valid(uint8_t amr_ft) { - /* - * Extracted from RFC3267: - * - * "... with a FT value in the range 9-14 for AMR ... the whole packet - * SHOULD be discarded." - * - * "... packets containing only NO_DATA frames (FT=15) SHOULD NOT be - * transmitted." - * - * So, let's discard frames with a AMR FT >= 9. - */ - if (amr_ft >= AMR_FT_MAX) - return 0; - - return 1; + return amr_ft <= AMR_FT_PDC_EFR_SID || amr_ft == AMR_FT_NO_DATA; } /*! Check if an AMR frame is octet aligned by looking at the padding bits. diff --git a/tests/amr/amr_test.c b/tests/amr/amr_test.c index 593723c..bc18554 100644 --- a/tests/amr/amr_test.c +++ b/tests/amr/amr_test.c @@ -49,7 +49,7 @@ char *oa_amr_samples[] = { "0004633cc7f0630439ffe0000000", "0004eb81fc0758973b9edc782550", "a070ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00fc", /* sample with invalid FT=14, will be detected as bandwith-efficient */ - "a078ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00fc", /* sample with invalid FT=15, will be detected as bandwith-efficient */ + "a078", /* sample with FT=15 NO_DATA */ "END", }; @@ -72,6 +72,7 @@ char *bwe_amr_samples[] = { "f3c381bc7061c9f8507f6029de6115c16e5fa470c243b21b6e35dbb48bd84c00", "73c901b7a2004be7f85284b6ab7142acfe6872b1ae1c107d0588b551de7be650", "a7bfc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03f", /* sample with invalid FT */ + "4780", /* FT=15 NO_DATA */ "END", }; diff --git a/tests/amr/amr_test.ok b/tests/amr/amr_test.ok index 8aee2d3..24cbd6a 100644 --- a/tests/amr/amr_test.ok +++ b/tests/amr/amr_test.ok @@ -164,11 +164,11 @@ Sample No.: 22 rc: -1 Sample No.: 23 - octet aligned: a078ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00fc - 101000000111100011111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111100 - bw-efficient: - (no data) - rc: -1 + octet aligned: a078 + 1010000001111000 + bw-efficient: a780 + 1010011110000000 + rc: 2 Testing conversion from bw-efficient to octet-aligned: @@ -288,9 +288,16 @@ Sample No.: 15 Sample No.: 16 bw-efficient: a7bfc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03fc03f 1010011110111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000111111110000000011111111000000001111111100000000111111 - octet aligned: - (no data) - rc: -1 + octet aligned: a078 + 1010000001111000 + rc: 2 + +Sample No.: 17 + bw-efficient: 4780 + 0100011110000000 + octet aligned: 4078 + 0100000001111000 + rc: 2 Testing conversion from octet-aligned to bw-efficient and inverse: @@ -317,7 +324,7 @@ Sample No.: 19... AMR mode: 0, OA: 14 bytes, BE: 14 bytes, OA: 14 bytes Sample No.: 20... AMR mode: 0, OA: 14 bytes, BE: 14 bytes, OA: 14 bytes Sample No.: 21... AMR mode: 0, OA: 14 bytes, BE: 14 bytes, OA: 14 bytes Sample No.: 22... skipping a sample with a wrong FT -Sample No.: 23... skipping a sample with a wrong FT +Sample No.: 23... AMR mode: 15, OA: 2 bytes, BE: 2 bytes, OA: 2 bytes Testing conversion from IuUP to bw-efficient and inverse: @@ -350,7 +357,7 @@ Sample No.: 19 ==>octet aligned Sample No.: 20 ==>octet aligned Sample No.: 21 ==>octet aligned Sample No.: 22 ==>bandwith efficient -Sample No.: 23 ==>bandwith efficient +Sample No.: 23 ==>octet aligned Sample No.: 0 ==>bandwith efficient Sample No.: 1 ==>bandwith efficient Sample No.: 2 ==>bandwith efficient @@ -368,4 +375,5 @@ Sample No.: 13 ==>bandwith efficient Sample No.: 14 ==>bandwith efficient Sample No.: 15 ==>bandwith efficient Sample No.: 16 ==>bandwith efficient +Sample No.: 17 ==>bandwith efficient OK: Test passed