aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2022-12-19 14:36:49 +0100
committerPau Espin Pedrol <pespin@sysmocom.de>2022-12-19 19:44:16 +0100
commit678c7fc8fe4fd11e09ccd642ad60c10c365bd19a (patch)
treeb893797cd9ac3df517723a4b14e00d282d4ba1de
parentc2228b7674a94a0d8a8f3d688f84c6adc95108f1 (diff)
amr: Support all SID and NO_DATA amr formats
-rw-r--r--include/osmocom/netif/amr.h53
-rw-r--r--src/amr.c67
-rw-r--r--tests/amr/amr_test.c3
-rw-r--r--tests/amr/amr_test.ok28
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 <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.
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