laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/38139?usp=email )
Change subject: tests: add unit tests for trau2rtp conversion, FR & EFR ......................................................................
tests: add unit tests for trau2rtp conversion, FR & EFR
The present set of tests exercises osmo_trau_frame_decode_16k() and osmo_trau2rtp() functions for frame types of FR speech and EFR speech. Both standard (RFC 3551) and TW-TS-001 output modes are tested.
Change-Id: Ie319900125baa8f20595cac83343771d780a5b4e --- M .gitignore M tests/Makefile.am M tests/testsuite.at A tests/trau_conv/trau16_efr.in A tests/trau_conv/trau16_efr_std.ok A tests/trau_conv/trau16_efr_twts001.ok A tests/trau_conv/trau16_fr.in A tests/trau_conv/trau16_fr_std.ok A tests/trau_conv/trau16_fr_twts001.ok A tests/trau_conv/trau16_to_rtp.c 10 files changed, 1,128 insertions(+), 0 deletions(-)
Approvals: Jenkins Builder: Verified fixeria: Looks good to me, but someone else must approve laforge: Looks good to me, approved
diff --git a/.gitignore b/.gitignore index f932b39..2bed942 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ tests/subchan_demux/subchan_demux_test tests/ipa_recv/ipa_recv_test tests/trau_pcu_ericsson/trau_pcu_ericsson_test +tests/trau_conv/trau16_to_rtp tests/trau_sync/trau_sync_test
diff --git a/tests/Makefile.am b/tests/Makefile.am index a01f381..e50a3b7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -7,6 +7,7 @@ ipa_proxy_test \ subchan_demux/subchan_demux_test \ ipa_recv/ipa_recv_test \ + trau_conv/trau16_to_rtp \ trau_sync/trau_sync_test \ trau_pcu_ericsson/trau_pcu_ericsson_test
@@ -41,6 +42,10 @@ rtp_test_rtp_test_LDADD = $(top_builddir)/src/libosmotrau.la \ $(LIBOSMOCORE_LIBS)
+trau_conv_trau16_to_rtp_SOURCES = trau_conv/trau16_to_rtp.c +trau_conv_trau16_to_rtp_LDADD = $(top_builddir)/src/libosmotrau.la \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) + trau_sync_trau_sync_test_SOURCES = trau_sync/trau_sync_test.c trau_sync_trau_sync_test_LDADD = $(top_builddir)/src/libosmotrau.la \ $(LIBOSMOCORE_LIBS) @@ -72,6 +77,10 @@ subchan_demux/subchan_demux_test.ok \ ipa_recv/ipa_recv_test.ok \ rtp_test/rtp_test.ok \ + trau_conv/trau16_efr.in trau_conv/trau16_efr_std.ok \ + trau_conv/trau16_efr_twts001.ok \ + trau_conv/trau16_fr.in trau_conv/trau16_fr_std.ok \ + trau_conv/trau16_fr_twts001.ok \ trau_sync/trau_sync_test.ok trau_sync/trau_sync_test.err \ trau_pcu_ericsson/trau_pcu_ericsson_test.ok
diff --git a/tests/testsuite.at b/tests/testsuite.at index 818e4fa..2528eb8 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -42,3 +42,27 @@ cat $abs_srcdir/trau_pcu_ericsson/trau_pcu_ericsson_test.ok > expout AT_CHECK([$abs_top_builddir/tests/trau_pcu_ericsson/trau_pcu_ericsson_test], [0], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([trau2rtp_fr_std]) +AT_KEYWORDS([trau2rtp_fr_std]) +cat $abs_srcdir/trau_conv/trau16_fr_std.ok > expout +AT_CHECK([$abs_top_builddir/tests/trau_conv/trau16_to_rtp $abs_srcdir/trau_conv/trau16_fr.in ul std], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([trau2rtp_fr_twts001]) +AT_KEYWORDS([trau2rtp_fr_twts001]) +cat $abs_srcdir/trau_conv/trau16_fr_twts001.ok > expout +AT_CHECK([$abs_top_builddir/tests/trau_conv/trau16_to_rtp $abs_srcdir/trau_conv/trau16_fr.in ul tw-ts-001], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([trau2rtp_efr_std]) +AT_KEYWORDS([trau2rtp_efr_std]) +cat $abs_srcdir/trau_conv/trau16_efr_std.ok > expout +AT_CHECK([$abs_top_builddir/tests/trau_conv/trau16_to_rtp $abs_srcdir/trau_conv/trau16_efr.in ul std], [0], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([trau2rtp_efr_twts001]) +AT_KEYWORDS([trau2rtp_efr_twts001]) +cat $abs_srcdir/trau_conv/trau16_efr_twts001.ok > expout +AT_CHECK([$abs_top_builddir/tests/trau_conv/trau16_to_rtp $abs_srcdir/trau_conv/trau16_efr.in ul tw-ts-001], [0], [expout], [ignore]) +AT_CLEANUP diff --git a/tests/trau_conv/trau16_efr.in b/tests/trau_conv/trau16_efr.in new file mode 100644 index 0000000..a0a3fa0 --- /dev/null +++ b/tests/trau_conv/trau16_efr.in @@ -0,0 +1,68 @@ +# This file is an input to trau16_to_rtp unit test program, containing +# TRAU-16k Abis-UL frames for TCH/EFS. +# +# All test frames presented here have been taken from these Abis E1 captures: +# +# https://osmocom.org/projects/retro-gsm/wiki/InSite_UL_captures +# +# The extraction of hex-encoded TRAU frames from E1 timeslot *.bin captures +# was done with trau-parse program (-r option) developed in this repository: +# +# https://www.freecalypso.org/hg/gsm-net-reveng/ + +# A few BFI frames from channel start-up, including one in TAF position + +ID efr-dtx.bin frame 0x8e11 +0000e808c0e1ab5dbb94ef0ee7c6967ce3b5846ec1b19ededdbab7ddd5b48e51acd6bde2aefab2ff +ID efr-dtx.bin frame 0x8eb1 +0000e808f4d7b875e9538027a20597dc8affe571f92ba6fe986af0fe98cd97e3c138cda2fe45daff +ID efr-dtx.bin frame 0x8f51 +0000e809c4b6d46fa0a6c763fa80fb499311b22eb576a68da81b971cd89fe22ebe4190908ee9caff + +# Some good speech frames + +ID efr-dtx.bin frame 0x9311 +0000e8c0ecc6e6d39ae5ac008013b21780ec800080008002aad6800080008036eb00800080008eff +ID efr-dtx.bin frame 0x93b1 +0000e8c0c5959c70daf191608000800081abb8ccf580a07c873fb977a81cc410f1588c7fdd61ceff +ID efr-dtx.bin frame 0x9451 +0000e8c0d01dc9f2f67a885ff583d73fa9daf2cca28a91babde68c43a24efc32aa69ad8af003caff + +# A good speech frame in TAF position + +ID efr-dtx.bin frame 0x9e51 +0000e8c1c9dfd7d1dfbff22fe2dceb339454b771e18ba09ddbccab2ce3dc821386be9b1d9fe9c6ff + +# Entry into DTXu pause + +ID efr-dtx.bin frame 0x3cad1 +0000ebe4ca1b97f3b45086fffffc8000c68efffffe008046c07fffffe0008451fffcffe08004e2ff +ID efr-dtx.bin frame 0x3cb71 +0000ebecca31d987973086fffffc9b0ace8effffff20804ec07fffffe12084d1ffffffe28b0ce2ff +ID efr-dtx.bin frame 0x3cc11 +0000ebe8f23dea94e91ec4229aacfe968207e8d7ba6bb402ec02d8e6b00c83a0fe44dd50ae84eaff + +# SID update in TAF position, with half-blocks before and after + +ID efr-dtx.bin frame 0x430b1 +0000ebeccf36da92c6a086fffffca494d68efffffe4ba056c07ffffff0048551fffcffe0a485a2ff +ID efr-dtx.bin frame 0x43151 +0000ebe5cf36da92c6a086fffffc8000d68efffffe008056c07fffffe0008551fffcffe08005a2ff +ID efr-dtx.bin frame 0x431f1 +0000ebeccf36da92c6a086fffffcc340d68efffffe04d0d6c07fffffe0818551fffdffe0d84da2ff + +# FACCH activity in the middle of DTXu pause, includes a BFI-no-data frame +# in which buffered bit content is still (invalid) SID, but is marked as +# SID=0 in out-of-band flag bits. + +ID efr-dtx-dtmf.bin frame 0x4d471 +0000ebecd090a131e71086fffffca494ce8efffffe4ba04ec07ffffff00484d1fffcffe0a484e2ff +ID efr-dtx-dtmf.bin frame 0x4d511 +0000ebe8c7e5a131e70da61ffffca494cc79fffffe4ba04d9214fffff00484c7fffcffe0a484feff + +# Another similar occurrence, but this time it was SID=1 initially + +ID efr-dtx-dtmf.bin frame 0x53a51 +0000ebead10eba68ada886f7fbfca494ca8cfffffe4ba04ac07ffffff0048491fffcffe0a485c2ff +ID efr-dtx-dtmf.bin frame 0x53af1 +0000ebe8cf05b311adada617fbfca494c87afffffe4ba04ac214fffff00484affffcffe0a485deff diff --git a/tests/trau_conv/trau16_efr_std.ok b/tests/trau_conv/trau16_efr_std.ok new file mode 100644 index 0000000..1f09a0b --- /dev/null +++ b/tests/trau_conv/trau16_efr_std.ok @@ -0,0 +1,110 @@ +ID efr-dtx.bin frame 0x8e11 +0000e808c0e1ab5dbb94ef0ee7c6967ce3b5846ec1b19ededdbab7ddd5b48e51acd6bde2aefab2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx.bin frame 0x8eb1 +0000e808f4d7b875e9538027a20597dc8affe571f92ba6fe986af0fe98cd97e3c138cda2fe45daff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx.bin frame 0x8f51 +0000e809c4b6d46fa0a6c763fa80fb499311b22eb576a68da81b971cd89fe22ebe4190908ee9caff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx.bin frame 0x9311 +0000e8c0ecc6e6d39ae5ac008013b21780ec800080008002aad6800080008036eb00800080008eff + TRAU frame type: EFR + osmo_trau2rtp() result: 31 + EFR frame: + LPC 89 141 310 153 43 + 342 0 0 0 0 1 3 3 1 0 2 7 0 + 54 0 0 0 0 0 0 0 0 0 0 0 0 + 342 11 0 0 0 0 0 0 0 0 0 0 0 + 54 11 0 0 0 0 0 0 0 0 0 0 0 + SID recompute: 0 +ID efr-dtx.bin frame 0x93b1 +0000e8c0c5959c70daf191608000800081abb8ccf580a07c873fb977a81cc410f1588c7fdd61ceff + TRAU frame type: EFR + osmo_trau2rtp() result: 31 + EFR frame: + LPC 11 42 227 133 43 + 72 11 0 0 0 0 0 0 0 0 0 0 0 + 21 11 8 12 12 14 11 0 0 1 0 0 31 + 57 15 11 9 7 7 5 0 0 7 1 0 16 + 7 1 5 8 1 8 15 7 5 6 5 4 6 + SID recompute: 0 +ID efr-dtx.bin frame 0x9451 +0000e8c0d01dc9f2f67a885ff583d73fa9daf2cca28a91babde68c43a24efc32aa69ad8af003caff + TRAU frame type: EFR + osmo_trau2rtp() result: 31 + EFR frame: + LPC 32 59 79 151 25 + 132 2 15 15 5 8 3 5 3 4 7 7 10 + 45 7 2 12 12 4 5 0 5 0 4 3 14 + 495 3 0 12 4 3 4 2 2 3 5 7 16 + 18 10 6 9 5 11 1 2 7 0 0 0 14 + SID recompute: 0 +ID efr-dtx.bin frame 0x9e51 +0000e8c1c9dfd7d1dfbff22fe2dceb339454b771e18ba09ddbccab2ce3dc821386be9b1d9fe9c6ff + TRAU frame type: EFR + osmo_trau2rtp() result: 31 + EFR frame: + LPC 19 191 190 141 62 + 505 1 7 14 2 13 12 6 5 4 6 3 5 + 42 3 7 7 1 12 3 0 5 5 0 1 7 + 222 6 2 11 2 12 12 3 6 7 0 0 8 + 24 6 11 14 3 6 3 5 1 7 7 5 6 + SID recompute: 0 +ID efr-dtx.bin frame 0x3cad1 +0000ebe4ca1b97f3b45086fffffc8000c68efffffe008046c07fffffe0008451fffcffe08004e2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 31 + EFR frame: + LPC 20 54 191 155 17 + 3 7 15 15 15 15 12 0 0 0 0 0 17 + 7 7 15 15 15 15 12 0 0 0 0 0 17 + 3 15 15 15 15 15 12 0 0 0 0 0 17 + 15 15 15 12 15 15 12 0 0 0 0 0 19 + SID recompute: 2 +ID efr-dtx.bin frame 0x3cb71 +0000ebecca31d987973086fffffc9b0ace8effffff20804ec07fffffe12084d1ffffffe28b0ce2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx.bin frame 0x3cc11 +0000ebe8f23dea94e91ec4229aacfe968207e8d7ba6bb402ec02d8e6b00c83a0fe44dd50ae84eaff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx.bin frame 0x430b1 +0000ebeccf36da92c6a086fffffca494d68efffffe4ba056c07ffffff0048551fffcffe0a485a2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx.bin frame 0x43151 +0000ebe5cf36da92c6a086fffffc8000d68efffffe008056c07fffffe0008551fffcffe08005a2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 31 + EFR frame: + LPC 30 109 212 148 26 + 3 7 15 15 15 15 12 0 0 0 0 0 21 + 7 7 15 15 15 15 12 0 0 0 0 0 21 + 3 15 15 15 15 15 12 0 0 0 0 0 21 + 15 15 15 12 15 15 12 0 0 0 0 0 21 + SID recompute: 2 +ID efr-dtx.bin frame 0x431f1 +0000ebeccf36da92c6a086fffffcc340d68efffffe04d0d6c07fffffe0818551fffdffe0d84da2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx-dtmf.bin frame 0x4d471 +0000ebecd090a131e71086fffffca494ce8efffffe4ba04ec07ffffff00484d1fffcffe0a484e2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx-dtmf.bin frame 0x4d511 +0000ebe8c7e5a131e70da61ffffca494cc79fffffe4ba04d9214fffff00484c7fffcffe0a484feff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx-dtmf.bin frame 0x53a51 +0000ebead10eba68ada886f7fbfca494ca8cfffffe4ba04ac07ffffff0048491fffcffe0a485c2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 +ID efr-dtx-dtmf.bin frame 0x53af1 +0000ebe8cf05b311adada617fbfca494c87afffffe4ba04ac214fffff00484affffcffe0a485deff + TRAU frame type: EFR + osmo_trau2rtp() result: 0 diff --git a/tests/trau_conv/trau16_efr_twts001.ok b/tests/trau_conv/trau16_efr_twts001.ok new file mode 100644 index 0000000..14dfe9d --- /dev/null +++ b/tests/trau_conv/trau16_efr_twts001.ok @@ -0,0 +1,204 @@ +ID efr-dtx.bin frame 0x8e11 +0000e808c0e1ab5dbb94ef0ee7c6967ce3b5846ec1b19ededdbab7ddd5b48e51acd6bde2aefab2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 1 194 346 235 46 + 311 8 7 6 7 12 6 1 3 1 7 4 24 + 26 8 4 6 14 8 3 3 0 4 7 5 23 + 237 13 3 7 13 13 10 5 5 5 0 1 25 + 10 12 13 6 7 11 12 2 2 7 3 7 9 + SID recompute: 0 +ID efr-dtx.bin frame 0x8eb1 +0000e808f4d7b875e9538027a20597dc8affe571f92ba6fe986af0fe98cd97e3c138cda2fe45daff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 105 174 451 174 37 + 192 1 3 10 2 0 5 1 3 7 3 4 2 + 63 14 5 7 1 15 2 2 5 5 1 5 31 + 195 5 7 0 15 14 3 0 6 3 2 2 31 + 28 1 3 8 9 11 4 2 7 7 1 0 22 + SID recompute: 0 +ID efr-dtx.bin frame 0x8f51 +0000e809c4b6d46fa0a6c763fa80fb499311b22eb576a68da81b971cd89fe22ebe4190908ee9caff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE3 + EFR frame: + LPC 9 109 163 122 2 + 419 11 1 15 10 8 0 7 5 5 1 1 4 + 8 11 2 2 14 6 10 7 3 1 1 5 3 + 320 13 9 7 1 12 11 0 4 7 7 4 8 + 51 14 4 1 2 1 2 0 0 7 3 5 6 + SID recompute: 0 +ID efr-dtx.bin frame 0x9311 +0000e8c0ecc6e6d39ae5ac008013b21780ec800080008002aad6800080008036eb00800080008eff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE0 + EFR frame: + LPC 89 141 310 153 43 + 342 0 0 0 0 1 3 3 1 0 2 7 0 + 54 0 0 0 0 0 0 0 0 0 0 0 0 + 342 11 0 0 0 0 0 0 0 0 0 0 0 + 54 11 0 0 0 0 0 0 0 0 0 0 0 + SID recompute: 0 +ID efr-dtx.bin frame 0x93b1 +0000e8c0c5959c70daf191608000800081abb8ccf580a07c873fb977a81cc410f1588c7fdd61ceff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE0 + EFR frame: + LPC 11 42 227 133 43 + 72 11 0 0 0 0 0 0 0 0 0 0 0 + 21 11 8 12 12 14 11 0 0 1 0 0 31 + 57 15 11 9 7 7 5 0 0 7 1 0 16 + 7 1 5 8 1 8 15 7 5 6 5 4 6 + SID recompute: 0 +ID efr-dtx.bin frame 0x9451 +0000e8c0d01dc9f2f67a885ff583d73fa9daf2cca28a91babde68c43a24efc32aa69ad8af003caff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE0 + EFR frame: + LPC 32 59 79 151 25 + 132 2 15 15 5 8 3 5 3 4 7 7 10 + 45 7 2 12 12 4 5 0 5 0 4 3 14 + 495 3 0 12 4 3 4 2 2 3 5 7 16 + 18 10 6 9 5 11 1 2 7 0 0 0 14 + SID recompute: 0 +ID efr-dtx.bin frame 0x9e51 +0000e8c1c9dfd7d1dfbff22fe2dceb339454b771e18ba09ddbccab2ce3dc821386be9b1d9fe9c6ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE1 + EFR frame: + LPC 19 191 190 141 62 + 505 1 7 14 2 13 12 6 5 4 6 3 5 + 42 3 7 7 1 12 3 0 5 5 0 1 7 + 222 6 2 11 2 12 12 3 6 7 0 0 8 + 24 6 11 14 3 6 3 5 1 7 7 5 6 + SID recompute: 0 +ID efr-dtx.bin frame 0x3cad1 +0000ebe4ca1b97f3b45086fffffc8000c68efffffe008046c07fffffe0008451fffcffe08004e2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE0 + EFR frame: + LPC 20 54 191 155 17 + 3 7 15 15 15 15 12 0 0 0 0 0 17 + 7 7 15 15 15 15 12 0 0 0 0 0 17 + 3 15 15 15 15 15 12 0 0 0 0 0 17 + 15 15 15 12 15 15 12 0 0 0 0 0 19 + SID recompute: 2 +ID efr-dtx.bin frame 0x3cb71 +0000ebecca31d987973086fffffc9b0ace8effffff20804ec07fffffe12084d1ffffffe28b0ce2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 20 99 204 57 28 + 3 7 15 15 15 15 12 1 5 4 1 2 19 + 7 7 15 15 15 15 14 2 0 0 0 0 19 + 3 15 15 15 15 15 12 1 1 0 0 0 19 + 15 15 15 15 15 15 12 2 0 5 4 1 19 + SID recompute: 2 +ID efr-dtx.bin frame 0x3cc11 +0000ebe8f23dea94e91ec4229aacfe968207e8d7ba6bb402ec02d8e6b00c83a0fe44dd50ae84eaff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 100 123 340 166 36 + 418 1 1 1 10 10 12 7 7 2 2 6 0 + 3 14 8 13 7 7 4 6 5 5 5 0 0 + 352 1 5 8 14 6 6 0 0 3 0 0 14 + 7 14 4 4 11 10 10 0 2 7 2 0 19 + SID recompute: 0 +ID efr-dtx.bin frame 0x430b1 +0000ebeccf36da92c6a086fffffca494d68efffffe4ba056c07ffffff0048551fffcffe0a485a2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 30 109 212 148 26 + 3 7 15 15 15 15 12 2 2 2 2 4 21 + 7 7 15 15 15 15 12 4 5 5 0 0 21 + 3 15 15 15 15 15 14 0 0 1 0 0 21 + 15 15 15 12 15 15 12 0 2 2 2 0 21 + SID recompute: 2 +ID efr-dtx.bin frame 0x43151 +0000ebe5cf36da92c6a086fffffc8000d68efffffe008056c07fffffe0008551fffcffe08005a2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE1 + EFR frame: + LPC 30 109 212 148 26 + 3 7 15 15 15 15 12 0 0 0 0 0 21 + 7 7 15 15 15 15 12 0 0 0 0 0 21 + 3 15 15 15 15 15 12 0 0 0 0 0 21 + 15 15 15 12 15 15 12 0 0 0 0 0 21 + SID recompute: 2 +ID efr-dtx.bin frame 0x431f1 +0000ebeccf36da92c6a086fffffcc340d68efffffe04d0d6c07fffffe0818551fffdffe0d84da2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 30 109 212 148 26 + 3 7 15 15 15 15 12 4 1 5 0 0 21 + 7 7 15 15 15 15 12 0 2 2 4 1 21 + 3 15 15 15 15 15 12 0 4 0 2 0 21 + 15 15 15 13 15 15 12 0 5 4 1 1 21 + SID recompute: 2 +ID efr-dtx-dtmf.bin frame 0x4d471 +0000ebecd090a131e71086fffffca494ce8efffffe4ba04ec07ffffff00484d1fffcffe0a484e2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 33 32 265 142 28 + 3 7 15 15 15 15 12 2 2 2 2 4 19 + 7 7 15 15 15 15 12 4 5 5 0 0 19 + 3 15 15 15 15 15 14 0 0 1 0 0 19 + 15 15 15 12 15 15 12 0 2 2 2 0 19 + SID recompute: 2 +ID efr-dtx-dtmf.bin frame 0x4d511 +0000ebe8c7e5a131e70da61ffffca494cc79fffffe4ba04d9214fffff00484c7fffcffe0a484feff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 15 202 265 142 28 + 339 0 15 15 15 15 12 2 2 2 2 4 19 + 60 15 15 15 15 15 12 4 5 5 0 0 19 + 144 10 7 15 15 15 14 0 0 1 0 0 19 + 63 15 15 12 15 15 12 0 2 2 2 0 19 + SID recompute: 1 +ID efr-dtx-dtmf.bin frame 0x53a51 +0000ebead10eba68ada886f7fbfca494ca8cfffffe4ba04ac07ffffff0048491fffcffe0a485c2ff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 34 28 467 66 54 + 3 7 11 15 11 15 12 2 2 2 2 4 18 + 6 7 15 15 15 15 12 4 5 5 0 0 18 + 3 15 15 15 15 15 14 0 0 1 0 0 18 + 15 15 15 12 15 15 12 0 2 2 2 0 22 + SID recompute: 1 +ID efr-dtx-dtmf.bin frame 0x53af1 +0000ebe8cf05b311adada617fbfca494c87afffffe4ba04ac214fffff00484affffcffe0a485deff + TRAU frame type: EFR + osmo_trau2rtp() result: 32 + TW-TS-001 TEH octet: 0xE2 + EFR frame: + LPC 30 10 408 138 54 + 339 0 11 15 11 15 12 2 2 2 2 4 18 + 61 7 15 15 15 15 12 4 5 5 0 0 18 + 16 10 7 15 15 15 14 0 0 1 0 0 18 + 63 15 15 12 15 15 12 0 2 2 2 0 22 + SID recompute: 1 diff --git a/tests/trau_conv/trau16_fr.in b/tests/trau_conv/trau16_fr.in new file mode 100644 index 0000000..2b3f20a --- /dev/null +++ b/tests/trau_conv/trau16_fr.in @@ -0,0 +1,57 @@ +# This file is an input to trau16_to_rtp unit test program, containing +# TRAU-16k Abis-UL frames for TCH/FS. +# +# All test frames presented here have been taken from these Abis E1 captures: +# +# https://osmocom.org/projects/retro-gsm/wiki/InSite_UL_captures +# +# The extraction of hex-encoded TRAU frames from E1 timeslot *.bin captures +# was done with trau-parse program (-r option) developed in this repository: +# +# https://www.freecalypso.org/hg/gsm-net-reveng/ + +# A few BFI frames from channel start-up + +ID fr1-dtx.bin frame 0x6ed1 +0000880885a5a009e1b8f6aaba318cb4f67fca1ac37fc94df1fba117e9e48c1bf5cff04ad135eeff +ID fr1-dtx.bin frame 0x6f71 +000088088499e0ade1bcf769ba318cb4f64dcc9ac37fc94df4dda117e9e48c18f5d7f04ad135eeff +ID fr1-dtx.bin frame 0x7011 +00008808f493a0ed81d7ef67cda2d099d74f89badd7ac666d9fef3d3fe9b9c758fa591d0d14886ff + +# BFI frame in TAF position + +ID fr1-dtx.bin frame 0x71f1 +00008809c6998721f08e995ac68aeb4db9efd0eece95b7749eeedfaefadea54f9bbbd65ba0a6deff + +# Some good speech frames + +ID fr1-dtx.bin frame 0x7511 +000088b0bd72ba9a94288012a492a492a2808124c924c9248710edb69468b5b5bc12a49ca685c6ff +ID fr1-dtx.bin frame 0x75b1 +000088b08c0fce6ee368831ba4edd833a38f82e4e46b8eb8ec68eba1d3d29c8ec50b86139d8792ff +ID fr1-dtx.bin frame 0x7651 +000088b0cc29bedc9c46a83ce650af55cee8c234e947943caa90ea92e2cecba6ed05e663b1cfb2ff + +# A good example of DTXu: SID frame not in TAF position, followed by one that +# is in TAF position, followed by half-block BFI, followed by regular BFI. + +ID fr1-dtx.bin frame 0x8051 +000088b4b58ee6ee92008000800080008000800080008000800080008000800080008000800082ff +ID fr1-dtx.bin frame 0x80f1 +000088b5b50ae6e6dc008000800080008000800080008000800080008000800080008000800082ff +ID fr1-dtx.bin frame 0x8191 +000088bcf48ae6ee9c0080009240800180028000800280008000c9008024880080008248c02082ff +ID fr1-dtx.bin frame 0x8231 +000088b8ce61b2b2c02d88cdc752c173890ef796f49ac82fd0e0a925e874d8c59751db08b9a1faff + +# A good speech frame in TAF position + +ID fr1-dtx.bin frame 0x8ff1 +000088b19cabee19a8569052aa16b922fa9a86ab97b38d46e990a5b9e5b1fc54e904de938adceaff + +# A BFI-no-data frame whose buffered bit content erroneously triggers +# SID detection, but is marked as SID=0 in out-of-band flag bits + +ID fr1-dtx.bin frame 0x104d1 +000088b8ee49c3b2e00691e58000800080f1889fa000800086948004c8008000821b90009000caff diff --git a/tests/trau_conv/trau16_fr_std.ok b/tests/trau_conv/trau16_fr_std.ok new file mode 100644 index 0000000..584bade --- /dev/null +++ b/tests/trau_conv/trau16_fr_std.ok @@ -0,0 +1,94 @@ +ID fr1-dtx.bin frame 0x6ed1 +0000880885a5a009e1b8f6aaba318cb4f67fca1ac37fc94df1fba117e9e48c1bf5cff04ad135eeff + TRAU frame type: FR + osmo_trau2rtp() result: 0 +ID fr1-dtx.bin frame 0x6f71 +000088088499e0ade1bcf769ba318cb4f64dcc9ac37fc94df4dda117e9e48c18f5d7f04ad135eeff + TRAU frame type: FR + osmo_trau2rtp() result: 0 +ID fr1-dtx.bin frame 0x7011 +00008808f493a0ed81d7ef67cda2d099d74f89badd7ac666d9fef3d3fe9b9c758fa591d0d14886ff + TRAU frame type: FR + osmo_trau2rtp() result: 0 +ID fr1-dtx.bin frame 0x71f1 +00008809c6998721f08e995ac68aeb4db9efd0eece95b7749eeedfaefadea54f9bbbd65ba0a6deff + TRAU frame type: FR + osmo_trau2rtp() result: 0 +ID fr1-dtx.bin frame 0x7511 +000088b0bd72ba9a94288012a492a492a2808124c924c9248710edb69468b5b5bc12a49ca685c6ff + TRAU frame type: FR + osmo_trau2rtp() result: 33 + FR frame: + LARc 30 29 18 11 9 5 4 2 + 40 0 0 0 4 4 4 4 4 4 4 4 4 4 4 4 4 + 40 0 0 0 4 4 4 4 4 4 4 4 4 4 4 4 4 + 64 3 0 2 3 3 3 3 3 4 2 4 5 0 6 2 3 + 43 3 3 32 4 4 4 4 4 3 4 4 5 0 2 3 4 + SID recompute: 0 +ID fr1-dtx.bin frame 0x75b1 +000088b08c0fce6ee368831ba4edd833a38f82e4e46b8eb8ec68eba1d3d29c8ec50b86139d8792ff + TRAU frame type: FR + osmo_trau2rtp() result: 33 + FR frame: + LARc 24 32 15 14 6 7 3 4 + 45 0 0 24 4 5 5 4 4 3 3 3 3 0 6 4 5 + 56 0 3 3 2 7 4 4 1 1 6 2 3 4 3 5 3 + 108 0 2 5 3 5 3 1 4 5 4 7 2 2 4 3 2 + 92 0 2 2 5 1 4 1 4 4 1 7 6 0 6 1 1 + SID recompute: 0 +ID fr1-dtx.bin frame 0x7651 +000088b0cc29bedc9c46a83ce650af55cee8c234e947943caa90ea92e2cecba6ed05e663b1cfb2ff + TRAU frame type: FR + osmo_trau2rtp() result: 33 + FR frame: + LARc 25 40 20 15 11 3 4 3 + 68 1 2 2 6 3 6 4 1 5 0 4 6 3 5 2 3 + 110 1 1 4 2 4 5 4 5 4 2 4 3 2 1 4 7 + 40 1 1 2 3 5 2 2 2 3 4 6 4 3 1 5 3 + 89 1 3 2 2 7 4 1 3 4 5 1 6 1 7 5 1 + SID recompute: 0 +ID fr1-dtx.bin frame 0x8051 +000088b4b58ee6ee92008000800080008000800080008000800080008000800080008000800082ff + TRAU frame type: FR + osmo_trau2rtp() result: 33 + FR frame: + LARc 22 35 27 12 7 7 4 4 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + SID recompute: 2 +ID fr1-dtx.bin frame 0x80f1 +000088b5b50ae6e6dc008000800080008000800080008000800080008000800080008000800082ff + TRAU frame type: FR + osmo_trau2rtp() result: 33 + FR frame: + LARc 22 33 26 12 7 6 5 3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + SID recompute: 2 +ID fr1-dtx.bin frame 0x8191 +000088bcf48ae6ee9c0080009240800180028000800280008000c9008024880080008248c02082ff + TRAU frame type: FR + osmo_trau2rtp() result: 0 +ID fr1-dtx.bin frame 0x8231 +000088b8ce61b2b2c02d88cdc752c173890ef796f49ac82fd0e0a925e874d8c59751db08b9a1faff + TRAU frame type: FR + osmo_trau2rtp() result: 0 +ID fr1-dtx.bin frame 0x8ff1 +000088b19cabee19a8569052aa16b922fa9a86ab97b38d46e990a5b9e5b1fc54e904de938adceaff + TRAU frame type: FR + osmo_trau2rtp() result: 33 + FR frame: + LARc 28 42 30 14 8 9 2 1 + 84 1 0 1 5 4 4 2 1 4 6 4 3 2 2 4 6 + 43 2 1 1 3 5 2 3 2 7 5 1 3 4 5 2 4 + 45 2 1 2 2 2 3 7 4 3 2 3 3 4 7 3 4 + 74 1 1 2 2 2 7 5 4 4 1 2 5 5 3 6 2 + SID recompute: 0 +ID fr1-dtx.bin frame 0x104d1 +000088b8ee49c3b2e00691e58000800080f1889fa000800086948004c8008000821b90009000caff + TRAU frame type: FR + osmo_trau2rtp() result: 0 diff --git a/tests/trau_conv/trau16_fr_twts001.ok b/tests/trau_conv/trau16_fr_twts001.ok new file mode 100644 index 0000000..a26439b --- /dev/null +++ b/tests/trau_conv/trau16_fr_twts001.ok @@ -0,0 +1,156 @@ +ID fr1-dtx.bin frame 0x6ed1 +0000880885a5a009e1b8f6aaba318cb4f67fca1ac37fc94df1fba117e9e48c1bf5cff04ad135eeff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE2 + FR frame: + LARc 16 11 21 0 0 9 3 0 + 59 0 3 45 2 5 4 3 1 6 0 1 6 4 6 2 6 + 77 3 3 39 2 0 3 5 0 6 6 7 7 4 4 2 6 + 30 2 3 55 2 0 1 2 7 3 1 7 1 1 0 3 0 + 118 3 2 14 7 7 1 0 1 5 2 1 2 6 2 7 6 + SID recompute: 0 +ID fr1-dtx.bin frame 0x6f71 +000088088499e0ade1bcf769ba318cb4f64dcc9ac37fc94df4dda117e9e48c18f5d7f04ad135eeff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE2 + FR frame: + LARc 16 50 28 0 5 11 3 0 + 123 0 3 29 3 1 5 3 1 6 0 1 6 4 6 2 6 + 77 0 3 38 1 1 3 5 0 6 6 7 7 4 4 2 6 + 94 0 3 46 2 0 1 2 7 3 1 7 1 1 0 3 0 + 70 3 2 46 6 7 1 0 1 5 2 1 2 6 2 7 6 + SID recompute: 0 +ID fr1-dtx.bin frame 0x7011 +00008808f493a0ed81d7ef67cda2d099d74f89badd7ac666d9fef3d3fe9b9c758fa591d0d14886ff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE2 + FR frame: + LARc 23 18 22 0 7 11 0 0 + 87 3 3 30 3 6 3 6 6 2 4 2 1 4 4 1 3 + 93 0 3 35 4 5 3 5 6 5 6 3 5 0 3 6 4 + 53 2 3 31 7 4 7 2 6 7 7 2 6 6 4 3 4 + 43 0 3 23 2 1 1 6 5 0 2 1 2 1 1 0 4 + SID recompute: 0 +ID fr1-dtx.bin frame 0x71f1 +00008809c6998721f08e995ac68aeb4db9efd0eece95b7749eeedfaefadea54f9bbbd65ba0a6deff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE3 + FR frame: + LARc 49 50 4 28 4 8 7 0 + 98 1 0 19 5 5 2 4 5 0 5 6 2 3 1 3 5 + 115 1 3 23 0 7 6 5 4 3 1 5 2 3 7 6 5 + 112 1 3 29 5 7 3 5 3 7 5 6 6 3 2 2 5 + 60 2 1 55 5 3 5 1 5 5 5 0 4 2 6 2 7 + SID recompute: 0 +ID fr1-dtx.bin frame 0x7511 +000088b0bd72ba9a94288012a492a492a2808124c924c9248710edb69468b5b5bc12a49ca685c6ff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE0 + FR frame: + LARc 30 29 18 11 9 5 4 2 + 40 0 0 0 4 4 4 4 4 4 4 4 4 4 4 4 4 + 40 0 0 0 4 4 4 4 4 4 4 4 4 4 4 4 4 + 64 3 0 2 3 3 3 3 3 4 2 4 5 0 6 2 3 + 43 3 3 32 4 4 4 4 4 3 4 4 5 0 2 3 4 + SID recompute: 0 +ID fr1-dtx.bin frame 0x75b1 +000088b08c0fce6ee368831ba4edd833a38f82e4e46b8eb8ec68eba1d3d29c8ec50b86139d8792ff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE0 + FR frame: + LARc 24 32 15 14 6 7 3 4 + 45 0 0 24 4 5 5 4 4 3 3 3 3 0 6 4 5 + 56 0 3 3 2 7 4 4 1 1 6 2 3 4 3 5 3 + 108 0 2 5 3 5 3 1 4 5 4 7 2 2 4 3 2 + 92 0 2 2 5 1 4 1 4 4 1 7 6 0 6 1 1 + SID recompute: 0 +ID fr1-dtx.bin frame 0x7651 +000088b0cc29bedc9c46a83ce650af55cee8c234e947943caa90ea92e2cecba6ed05e663b1cfb2ff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE0 + FR frame: + LARc 25 40 20 15 11 3 4 3 + 68 1 2 2 6 3 6 4 1 5 0 4 6 3 5 2 3 + 110 1 1 4 2 4 5 4 5 4 2 4 3 2 1 4 7 + 40 1 1 2 3 5 2 2 2 3 4 6 4 3 1 5 3 + 89 1 3 2 2 7 4 1 3 4 5 1 6 1 7 5 1 + SID recompute: 0 +ID fr1-dtx.bin frame 0x8051 +000088b4b58ee6ee92008000800080008000800080008000800080008000800080008000800082ff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE0 + FR frame: + LARc 22 35 27 12 7 7 4 4 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + SID recompute: 2 +ID fr1-dtx.bin frame 0x80f1 +000088b5b50ae6e6dc008000800080008000800080008000800080008000800080008000800082ff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE1 + FR frame: + LARc 22 33 26 12 7 6 5 3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + SID recompute: 2 +ID fr1-dtx.bin frame 0x8191 +000088bcf48ae6ee9c0080009240800180028000800280008000c9008024880080008248c02082ff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE2 + FR frame: + LARc 23 34 26 12 7 7 4 3 + 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 + 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 + 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 1 0 + 0 0 0 0 0 0 0 1 1 1 2 0 0 2 0 0 0 + SID recompute: 2 +ID fr1-dtx.bin frame 0x8231 +000088b8ce61b2b2c02d88cdc752c173890ef796f49ac82fd0e0a925e874d8c59751db08b9a1faff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE2 + FR frame: + LARc 57 12 20 9 13 4 1 0 + 104 2 0 34 1 3 3 4 3 5 4 2 0 2 7 4 1 + 18 0 3 29 7 1 5 5 3 1 1 3 5 4 0 4 6 + 23 0 3 1 2 1 1 1 5 3 1 4 3 1 5 1 6 + 40 2 2 43 0 3 3 3 0 1 4 3 6 2 0 7 3 + SID recompute: 0 +ID fr1-dtx.bin frame 0x8ff1 +000088b19cabee19a8569052aa16b922fa9a86ab97b38d46e990a5b9e5b1fc54e904de938adceaff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE1 + FR frame: + LARc 28 42 30 14 8 9 2 1 + 84 1 0 1 5 4 4 2 1 4 6 4 3 2 2 4 6 + 43 2 1 1 3 5 2 3 2 7 5 1 3 4 5 2 4 + 45 2 1 2 2 2 3 7 4 3 2 3 3 4 7 3 4 + 74 1 1 2 2 2 7 5 4 4 1 2 5 5 3 6 2 + SID recompute: 0 +ID fr1-dtx.bin frame 0x104d1 +000088b8ee49c3b2e00691e58000800080f1889fa000800086948004c8008000821b90009000caff + TRAU frame type: FR + osmo_trau2rtp() result: 34 + TW-TS-001 TEH octet: 0xE2 + FR frame: + LARc 59 36 12 24 13 4 3 0 + 64 1 0 49 3 2 1 0 0 0 0 0 0 0 0 0 0 + 96 3 0 34 0 1 7 3 1 0 0 0 0 0 0 0 0 + 64 1 1 10 0 0 0 0 1 1 1 0 0 0 0 0 0 + 0 0 0 33 5 1 1 0 0 0 0 1 0 0 0 2 2 + SID recompute: 1 diff --git a/tests/trau_conv/trau16_to_rtp.c b/tests/trau_conv/trau16_to_rtp.c new file mode 100644 index 0000000..9884e89 --- /dev/null +++ b/tests/trau_conv/trau16_to_rtp.c @@ -0,0 +1,405 @@ +/* + * This program is a libosmotrau unit test for osmo_trau_frame_decode_16k() + * and osmo_trau2rtp() functions. It reads input in the form of hex lines, + * with each line representing a TRAU-16k frame as a string of 80 hex digits. + * For each test frame thus read, we first call osmo_trau_frame_decode_16k() + * and print the frame type decoded by that function. We then call + * osmo_trau2rtp() and report its integer result, as in length of returned + * RTP payload or error code. Finally, for known frame types (initially + * FR and EFR speech) we break the RTP payload into an array of codec + * parameters and print them out in the same format as used in Themyscira + * Wireless GSM codec libraries and utilities. + * + * Author: Mychaela N. Falconia falcon@freecalypso.org, 2024 - however, + * Mother Mychaela's contributions are NOT subject to copyright. + * No rights reserved, all rights relinquished. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include <osmocom/core/bits.h> +#include <osmocom/core/utils.h> +#include <osmocom/codec/codec.h> +#include <osmocom/trau/trau_frame.h> +#include <osmocom/trau/trau_rtp.h> +#include <osmocom/gsm/rtp_extensions.h> + +static enum osmo_trau_frame_direction direction; +static struct osmo_trau2rtp_state trau2rtp_st; + +/* + * The following function has been copied from Themyscira libgsmfr2 - + * but it is mostly generated code, produced with 'sweet' utility + * from classic libgsm source. + */ +static void gsmfr_unpack_to_array(const uint8_t *frame, int16_t *params) +{ + const uint8_t *c = frame; + unsigned sub; + + params[0] = (*c++ & 0xF) << 2; + params[0] |= (*c >> 6) & 0x3; + params[1] = *c++ & 0x3F; + params[2] = (*c >> 3) & 0x1F; + params[3] = (*c++ & 0x7) << 2; + params[3] |= (*c >> 6) & 0x3; + params[4] = (*c >> 2) & 0xF; + params[5] = (*c++ & 0x3) << 2; + params[5] |= (*c >> 6) & 0x3; + params[6] = (*c >> 3) & 0x7; + params[7] = *c++ & 0x7; + params += 8; + for (sub = 0; sub < 4; sub++) { + params[0] = (*c >> 1) & 0x7F; + params[1] = (*c++ & 0x1) << 1; + params[1] |= (*c >> 7) & 0x1; + params[2] = (*c >> 5) & 0x3; + params[3] = (*c++ & 0x1F) << 1; + params[3] |= (*c >> 7) & 0x1; + params[4] = (*c >> 4) & 0x7; + params[5] = (*c >> 1) & 0x7; + params[6] = (*c++ & 0x1) << 2; + params[6] |= (*c >> 6) & 0x3; + params[7] = (*c >> 3) & 0x7; + params[8] = *c++ & 0x7; + params[9] = (*c >> 5) & 0x7; + params[10] = (*c >> 2) & 0x7; + params[11] = (*c++ & 0x3) << 1; + params[11] |= (*c >> 7) & 0x1; + params[12] = (*c >> 4) & 0x7; + params[13] = (*c >> 1) & 0x7; + params[14] = (*c++ & 0x1) << 2; + params[14] |= (*c >> 6) & 0x3; + params[15] = (*c >> 3) & 0x7; + params[16] = *c++ & 0x7; + params += 17; + } +} + +/* + * The following function has been copied from Themyscira libgsmefr - + * but it is mostly generated code, produced with 'sweet' utility + * from classic libgsm source. + */ +static void EFR_frame2params(const uint8_t *frame, int16_t *params) +{ + const uint8_t *c = frame; + + /* EFR_MAGIC = (*c >> 4) & 0xF; */ + params[0] = (*c++ & 0xF) << 3; + params[0] |= (*c >> 5) & 0x7; + params[1] = (*c++ & 0x1F) << 3; + params[1] |= (*c >> 5) & 0x7; + params[2] = (*c++ & 0x1F) << 4; + params[2] |= (*c >> 4) & 0xF; + params[3] = (*c++ & 0xF) << 4; + params[3] |= (*c >> 4) & 0xF; + params[4] = (*c++ & 0xF) << 2; + params[4] |= (*c >> 6) & 0x3; + params[5] = (*c++ & 0x3F) << 3; + params[5] |= (*c >> 5) & 0x7; + params[6] = (*c >> 1) & 0xF; + params[7] = (*c++ & 0x1) << 3; + params[7] |= (*c >> 5) & 0x7; + params[8] = (*c >> 1) & 0xF; + params[9] = (*c++ & 0x1) << 3; + params[9] |= (*c >> 5) & 0x7; + params[10] = (*c >> 1) & 0xF; + params[11] = (*c++ & 0x1) << 3; + params[11] |= (*c >> 5) & 0x7; + params[12] = (*c >> 2) & 0x7; + params[13] = (*c++ & 0x3) << 1; + params[13] |= (*c >> 7) & 0x1; + params[14] = (*c >> 4) & 0x7; + params[15] = (*c >> 1) & 0x7; + params[16] = (*c++ & 0x1) << 2; + params[16] |= (*c >> 6) & 0x3; + params[17] = (*c >> 1) & 0x1F; + params[18] = (*c++ & 0x1) << 5; + params[18] |= (*c >> 3) & 0x1F; + params[19] = (*c++ & 0x7) << 1; + params[19] |= (*c >> 7) & 0x1; + params[20] = (*c >> 3) & 0xF; + params[21] = (*c++ & 0x7) << 1; + params[21] |= (*c >> 7) & 0x1; + params[22] = (*c >> 3) & 0xF; + params[23] = (*c++ & 0x7) << 1; + params[23] |= (*c >> 7) & 0x1; + params[24] = (*c >> 3) & 0xF; + params[25] = *c++ & 0x7; + params[26] = (*c >> 5) & 0x7; + params[27] = (*c >> 2) & 0x7; + params[28] = (*c++ & 0x3) << 1; + params[28] |= (*c >> 7) & 0x1; + params[29] = (*c >> 4) & 0x7; + params[30] = (*c++ & 0xF) << 1; + params[30] |= (*c >> 7) & 0x1; + params[31] = (*c++ & 0x7F) << 2; + params[31] |= (*c >> 6) & 0x3; + params[32] = (*c >> 2) & 0xF; + params[33] = (*c++ & 0x3) << 2; + params[33] |= (*c >> 6) & 0x3; + params[34] = (*c >> 2) & 0xF; + params[35] = (*c++ & 0x3) << 2; + params[35] |= (*c >> 6) & 0x3; + params[36] = (*c >> 2) & 0xF; + params[37] = (*c++ & 0x3) << 2; + params[37] |= (*c >> 6) & 0x3; + params[38] = (*c >> 3) & 0x7; + params[39] = *c++ & 0x7; + params[40] = (*c >> 5) & 0x7; + params[41] = (*c >> 2) & 0x7; + params[42] = (*c++ & 0x3) << 1; + params[42] |= (*c >> 7) & 0x1; + params[43] = (*c >> 2) & 0x1F; + params[44] = (*c++ & 0x3) << 4; + params[44] |= (*c >> 4) & 0xF; + params[45] = *c++ & 0xF; + params[46] = (*c >> 4) & 0xF; + params[47] = *c++ & 0xF; + params[48] = (*c >> 4) & 0xF; + params[49] = *c++ & 0xF; + params[50] = (*c >> 4) & 0xF; + params[51] = (*c >> 1) & 0x7; + params[52] = (*c++ & 0x1) << 2; + params[52] |= (*c >> 6) & 0x3; + params[53] = (*c >> 3) & 0x7; + params[54] = *c++ & 0x7; + params[55] = (*c >> 5) & 0x7; + params[56] = *c++ & 0x1F; +} + +static void decode_fr(const uint8_t *rtp_pl, int conv_result) +{ + int16_t params[76]; + int i, j, p; + + if (conv_result <= 0) + return; + switch (conv_result) { + case 1: + /* The only valid 1-byte payload is TEH by itself + * in the case of TW-TS-001 output. */ + if ((rtp_pl[0] & 0xF0) != 0xE0) + goto inv_payload; + printf(" TW-TS-001 TEH octet: 0x%02X\n", rtp_pl[0]); + return; + case GSM_FR_BYTES: + if ((rtp_pl[0] & 0xF0) != 0xD0) + goto inv_payload; + /* standard FR payload without TW-TS-001 */ + break; + case GSM_FR_BYTES+1: + if ((rtp_pl[0] & 0xF0) != 0xE0) + goto inv_payload; + if ((rtp_pl[1] & 0xF0) != 0xD0) + goto inv_payload; + /* TW-TS-001 extended RTP payload for FR */ + printf(" TW-TS-001 TEH octet: 0x%02X\n", rtp_pl[0]); + rtp_pl++; + break; + default: + goto inv_payload; + } + + printf(" FR frame:\n"); + gsmfr_unpack_to_array(rtp_pl, params); + /* print frame in the same format as used in ThemWi tools */ + p = 0; + printf(" LARc"); + for (i = 0; i < 8; i++) + printf(" %d", params[p++]); + putchar('\n'); + for (i = 0; i < 4; i++) { + printf(" "); + for (j = 0; j < 17; j++) + printf(" %d", params[p++]); + putchar('\n'); + } + printf(" SID recompute: %d\n", (int) osmo_fr_sid_classify(rtp_pl)); + return; + +inv_payload: + printf(" Error: conversion result is not a valid FR payload\n"); +} + +static void decode_efr(const uint8_t *rtp_pl, int conv_result) +{ + int16_t params[57]; + int i, j, p; + + if (conv_result <= 0) + return; + switch (conv_result) { + case 1: + /* The only valid 1-byte payload is TEH by itself + * in the case of TW-TS-001 output. */ + if ((rtp_pl[0] & 0xF0) != 0xE0) + goto inv_payload; + printf(" TW-TS-001 TEH octet: 0x%02X\n", rtp_pl[0]); + return; + case GSM_EFR_BYTES: + if ((rtp_pl[0] & 0xF0) != 0xC0) + goto inv_payload; + /* standard EFR payload without TW-TS-001 */ + break; + case GSM_EFR_BYTES+1: + if ((rtp_pl[0] & 0xF0) != 0xE0) + goto inv_payload; + if ((rtp_pl[1] & 0xF0) != 0xC0) + goto inv_payload; + /* TW-TS-001 extended RTP payload for EFR */ + printf(" TW-TS-001 TEH octet: 0x%02X\n", rtp_pl[0]); + rtp_pl++; + break; + default: + goto inv_payload; + } + + printf(" EFR frame:\n"); + EFR_frame2params(rtp_pl, params); + /* print frame in the same format as used in ThemWi tools */ + p = 0; + printf(" LPC"); + for (i = 0; i < 5; i++) + printf(" %d", params[p++]); + putchar('\n'); + for (i = 0; i < 4; i++) { + printf(" "); + for (j = 0; j < 13; j++) + printf(" %d", params[p++]); + putchar('\n'); + } + printf(" SID recompute: %d\n", (int) osmo_efr_sid_classify(rtp_pl)); + return; + +inv_payload: + printf(" Error: conversion result is not a valid EFR payload\n"); +} + +static void process_record(const char *hex_str) +{ + uint8_t input_bytes[40]; + ubit_t trau_bits[320]; + struct osmo_trau_frame tf; + uint8_t rtp_pl[160]; /* maximum length for CSD */ + int decode_result, conv_result; + + /* In the output, we reprint each input line followed by + * our analysis thereof. */ + printf("%s\n", hex_str); + osmo_hexparse(hex_str, input_bytes, sizeof(input_bytes)); + osmo_pbit2ubit(trau_bits, input_bytes, sizeof(trau_bits)); + decode_result = osmo_trau_frame_decode_16k(&tf, trau_bits, direction); + if (decode_result < 0) { + printf(" osmo_trau_frame_decode_16k() returned %d\n", + decode_result); + return; + } + printf(" TRAU frame type: %s\n", osmo_trau_frame_type_name(tf.type)); + trau2rtp_st.type = tf.type; + conv_result = osmo_trau2rtp(rtp_pl, sizeof(rtp_pl), &tf, &trau2rtp_st); + printf(" osmo_trau2rtp() result: %d\n", conv_result); + /* additional decoding for specific frame types */ + switch (tf.type) { + case OSMO_TRAU16_FT_FR: + decode_fr(rtp_pl, conv_result); + break; + case OSMO_TRAU16_FT_EFR: + decode_efr(rtp_pl, conv_result); + break; + default: + break; /* do nothing */ + } +} + +static void process_line(char *linebuf, const char *infname, int lineno) +{ + char *cp = linebuf, *hex_str; + int ndig; + + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + return; + /* pass ID lines through to output */ + if (!strncmp(cp, "ID", 2)) { + fputs(cp, stdout); + return; + } + /* expect string of 80 hex digits */ + hex_str = cp; + for (ndig = 0; ndig < 80; ndig++) { + if (!isxdigit(*cp)) + goto inv; + cp++; + } + if (*cp) { + if (!isspace(*cp)) + goto inv; + *cp++ = '\0'; + } + /* must be end of non-comment line */ + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto inv; + + process_record(hex_str); + return; + +inv: fprintf(stderr, "%s line %d: invalid syntax\n", infname, lineno); + exit(1); +} + +int main(int argc, char **argv) +{ + const char *infname; + FILE *inf; + char linebuf[256]; + int lineno; + + if (argc != 4) + goto usage; + infname = argv[1]; + inf = fopen(infname, "r"); + if (!inf) { + perror(infname); + exit(1); + } + if (!strcmp(argv[2], "ul")) + direction = OSMO_TRAU_DIR_UL; + else if (!strcmp(argv[2], "dl")) + direction = OSMO_TRAU_DIR_DL; + else + goto usage; + if (!strcmp(argv[3], "std")) + trau2rtp_st.rtp_extensions = 0; + else if (!strcmp(argv[3], "tw-ts-001")) + trau2rtp_st.rtp_extensions = OSMO_RTP_EXT_TWTS001; + else + goto usage; + + for (lineno = 1; fgets(linebuf, sizeof(linebuf), inf); lineno++) + process_line(linebuf, infname, lineno); + fclose(inf); + exit(0); + +usage: fprintf(stderr, "usage: %s input-file ul|dl std|tw-ts-001\n", argv[0]); + exit(1); +}