amr: Support all SID and NO_DATA amr formats

Related: SYS#6161
Change-Id: I0e766b3231f03ea87d89fad6ecdce3bd14769054
This commit is contained in:
Pau Espin 2022-12-19 14:36:49 +01:00
parent c2228b7674
commit 678c7fc8fe
4 changed files with 93 additions and 58 deletions

View File

@ -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);

View File

@ -18,7 +18,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/netif/amr.h>
/* 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.

View File

@ -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",
};

View File

@ -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