changeset 2:b2ef2c80fef1

trau-parse: add FR decoding
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 24 May 2024 08:11:25 +0000
parents b0dcd48a1c8a
children 64b15810dc4c
files .hgignore Makefile trau-decode/Makefile trau-decode/parse-fr.c trau-decode/parse-main.c trau-parse.c
diffstat 6 files changed, 343 insertions(+), 225 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri May 24 07:25:11 2024 +0000
+++ b/.hgignore	Fri May 24 08:11:25 2024 +0000
@@ -2,4 +2,4 @@
 
 \.[oa]$
 
-^trau-parse$
+^trau-decode/trau-parse$
--- a/Makefile	Fri May 24 07:25:11 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-CC=	gcc
-CFLAGS=	-O2
-PROGS=	trau-parse
-
-all:	${PROGS}
-
-trau-parse:	trau-parse.c
-	${CC} ${CFLAGS} -o $@ $@.c
-
-clean:
-	rm -f *.o ${PROGS}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trau-decode/Makefile	Fri May 24 08:11:25 2024 +0000
@@ -0,0 +1,11 @@
+CC=	gcc
+CFLAGS=	-O2
+PROGS=	trau-parse
+
+all:	${PROGS}
+
+trau-parse:	parse-fr.o parse-main.o
+	${CC} ${CFLAGS} -o $@ $^ -lgsmfr2
+
+clean:
+	rm -f *.o ${PROGS}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trau-decode/parse-fr.c	Fri May 24 08:11:25 2024 +0000
@@ -0,0 +1,89 @@
+/*
+ * This module implements the FR decoding part of trau-parse.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <tw_gsmfr.h>
+
+/* this corresponds to the bit-lengths of the individual codec
+ * parameters as indicated in Table 1.1 of TS 46.010 */
+static const uint8_t gsm_fr_map[GSMFR_NUM_PARAMS] = {
+	6, 6, 5, 5, 4, 4, 3, 3,
+	7, 2, 2, 6, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3,
+	3, 7, 2, 2, 6, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 7, 2, 2, 6, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 7, 2, 2, 6, 3,
+	3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3
+};
+
+static unsigned
+get_le(bits, nbits)
+	uint8_t *bits;
+	unsigned nbits;
+{
+	unsigned accum, mask;
+	unsigned n;
+
+	accum = 0;
+	mask = 1;
+	for (n = 0; n < nbits; n++) {
+		if (*bits)
+			accum |= mask;
+		bits++;
+		mask <<= 1;
+	}
+	return accum;
+}
+
+static void
+dbits_to_params(d_bits, params)
+	uint8_t *d_bits;
+	int16_t *params;
+{
+	unsigned np, len;
+	uint8_t *ip;
+	int16_t *op;
+
+	ip = d_bits;
+	op = params;
+	for (np = 0; np < GSMFR_NUM_PARAMS; np++) {
+		len = gsm_fr_map[np];
+		*op++ = get_le(ip, len);
+		ip += len;
+	}
+}
+
+void
+print_fr_frame(d_bits)
+	uint8_t d_bits;
+{
+	int16_t params[GSMFR_NUM_PARAMS];
+	uint8_t rtp_pack[GSMFR_RTP_FRAME_LEN];
+	int i, j, n, sid;
+
+	dbits_to_params(d_bits, params);
+	fputs("  FR frame:\n    ", stdout);
+	n = 0;
+	for (i = 0; i < 8; i++)
+		printf(" %d", params[n++]);
+	putchar('\n');
+	for (i = 0; i < 4; i++) {
+		fputs("     ", stdout);
+		for (j = 0; j < 17; j++)
+			printf(" %d", params[n++]);
+		putchar('\n');
+	}
+	gsmfr_pack_from_array(params, rtp_pack);
+	sid = gsmfr_preproc_sid_classify(rtp_pack);
+	printf("    SID recompute: %d\n", sid);
+	if (!bcmp(rtp_pack, gsmfr_decoder_homing_frame, GSMFR_RTP_FRAME_LEN))
+		puts("    Matches DHF");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trau-decode/parse-main.c	Fri May 24 08:11:25 2024 +0000
@@ -0,0 +1,242 @@
+/*
+ * This program reads a 64 kbit/s timeslot recording file, examines one
+ * of the four 16 kbit/s subslots (selected), looks for GSM 08.60 TRAU
+ * frames, and dumps whatever it finds.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+static unsigned file_offset;
+
+static enum {
+	HUNT_FOR_0,
+	HUNT_FOUND_0,
+	GOT_8_ZEROS,
+	SYNCED
+} state;
+static unsigned hunt_for_0_count, frame_pos_count;
+static uint8_t in_frame_2bit[160], frame_bits[320], d_bits[260];
+
+static void
+unpack_dibits()
+{
+	int i, inb;
+	uint8_t *op;
+
+	op = frame_bits;
+	for (i = 0; i < 160; i++) {
+		inb = in_frame_2bit[i];
+		if (inb & 2)
+			*op++ = 1;
+		else
+			*op++ = 0;
+		if (inb & 1)
+			*op++ = 1;
+		else
+			*op++ = 0;
+	}
+}
+
+static unsigned
+bits_to_num(bits, nbits)
+	uint8_t *bits;
+	unsigned nbits;
+{
+	unsigned accum;
+	unsigned n;
+
+	accum = 0;
+	for (n = 0; n < nbits; n++) {
+		accum <<= 1;
+		if (*bits)
+			accum |= 1;
+		bits++;
+	}
+	return accum;
+}
+
+static void
+collect_d_bits()
+{
+	bcopy(frame_bits + 33, d_bits, 15);
+	bcopy(frame_bits + 49, d_bits + 15, 15);
+	bcopy(frame_bits + 65, d_bits + 30, 15);
+	bcopy(frame_bits + 81, d_bits + 45, 15);
+	bcopy(frame_bits + 97, d_bits + 60, 15);
+	bcopy(frame_bits + 113, d_bits + 75, 15);
+	bcopy(frame_bits + 129, d_bits + 90, 15);
+	bcopy(frame_bits + 145, d_bits + 105, 15);
+	bcopy(frame_bits + 161, d_bits + 120, 15);
+	bcopy(frame_bits + 177, d_bits + 135, 15);
+	bcopy(frame_bits + 193, d_bits + 150, 15);
+	bcopy(frame_bits + 209, d_bits + 165, 15);
+	bcopy(frame_bits + 225, d_bits + 180, 15);
+	bcopy(frame_bits + 241, d_bits + 195, 15);
+	bcopy(frame_bits + 257, d_bits + 210, 15);
+	bcopy(frame_bits + 273, d_bits + 225, 15);
+	bcopy(frame_bits + 289, d_bits + 240, 15);
+	bcopy(frame_bits + 305, d_bits + 255, 5);
+}
+
+static void
+process_frame()
+{
+	unsigned c1_5, c6_11;
+
+	printf("Frame at 0x%x:\n", file_offset - 160);
+	printf("  C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18],
+		frame_bits[19], frame_bits[20], frame_bits[21]);
+	c1_5 = bits_to_num(frame_bits + 17, 5);
+	switch (c1_5) {
+	case 0x02:
+		fputs(" (FR UL)", stdout);
+		break;
+	case 0x1C:
+		fputs(" (FR DL)", stdout);
+		break;
+	case 0x1A:
+		fputs(" (EFR)", stdout);
+		break;
+	case 0x10:
+		fputs(" (idle UL)", stdout);
+		break;
+	case 0x0E:
+		fputs(" (idle DL)", stdout);
+		break;
+	}
+	putchar('\n');
+	c6_11 = bits_to_num(frame_bits + 22, 6);
+	printf("  C6-C11: %u\n", c6_11);
+	printf("  C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28],
+		frame_bits[29], frame_bits[30], frame_bits[31]);
+	switch (c1_5) {
+	case 0x02:
+	case 0x1C:
+		collect_d_bits();
+		print_fr_frame(d_bits);
+		break;
+	}
+	printf("  C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n",
+		frame_bits[310], frame_bits[311], frame_bits[312],
+		frame_bits[313], frame_bits[314], frame_bits[315]);
+	printf("  T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317],
+		frame_bits[318], frame_bits[319]);
+}
+
+static int
+check_sync_zeros()
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		if (frame_bits[i])
+			return 0;
+	}
+	return 1;
+}
+
+static int
+check_sync_ones()
+{
+	int i;
+
+	for (i = 1; i < 20; i++) {
+		if (!frame_bits[i*16])
+			return 0;
+	}
+	return 1;
+}
+
+static void
+check_sync()
+{
+	if (check_sync_zeros() && check_sync_ones())
+		return;
+	printf("Bad frame sync, returning to hunt state\n");
+	state = HUNT_FOR_0;
+}
+
+static void
+byte_input(inb)
+{
+	switch (state) {
+	case HUNT_FOR_0:
+		if (inb != 0)
+			return;
+		state = HUNT_FOUND_0;
+		hunt_for_0_count = 1;
+		return;
+	case HUNT_FOUND_0:
+		if (inb != 0) {
+			state = HUNT_FOR_0;
+			return;
+		}
+		hunt_for_0_count++;
+		if (hunt_for_0_count >= 8)
+			state = GOT_8_ZEROS;
+		return;
+	case GOT_8_ZEROS:
+		if (inb & 2) {
+			printf("Found frame sync at file offset 0x%x\n",
+				file_offset - 8);
+			bzero(in_frame_2bit, 8);
+			in_frame_2bit[8] = inb;
+			frame_pos_count = 9;
+			state = SYNCED;
+			return;
+		}
+		if (inb != 0)
+			state = HUNT_FOR_0;
+		return;
+	case SYNCED:
+		in_frame_2bit[frame_pos_count++] = inb;
+		if (frame_pos_count < 160)
+			return;
+		frame_pos_count = 0;
+		unpack_dibits();
+		process_frame();
+		check_sync();
+		return;
+	default:
+		fprintf(stderr, "BUG: bad sync state\n");
+		abort();
+	}
+}
+
+main(argc, argv)
+	char **argv;
+{
+	FILE *inf;
+	int subslot, right_shift;
+	int inb;
+
+	if (argc != 3) {
+		fprintf(stderr, "usage: %s binfile subslot\n", argv[0]);
+		exit(1);
+	}
+	inf = fopen(argv[1], "r");
+	if (!inf) {
+		perror(argv[1]);
+		exit(1);
+	}
+	subslot = atoi(argv[2]);
+	if (subslot < 0 || subslot > 3) {
+		fprintf(stderr, "error: invalid subslot argument\n");
+		exit(1);
+	}
+	right_shift = (3 - subslot) * 2;
+	state = HUNT_FOR_0;
+	for (file_offset = 0; ; file_offset++) {
+		inb = getc(inf);
+		if (inb < 0)
+			break;
+		inb >>= right_shift;
+		inb &= 3;
+		byte_input(inb);
+	}
+	exit(0);
+}
--- a/trau-parse.c	Fri May 24 07:25:11 2024 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*
- * This program reads a 64 kbit/s timeslot recording file, examines one
- * of the four 16 kbit/s subslots (selected), looks for GSM 08.60 TRAU
- * frames, and dumps whatever it finds.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-
-static unsigned file_offset;
-
-static enum {
-	HUNT_FOR_0,
-	HUNT_FOUND_0,
-	GOT_8_ZEROS,
-	SYNCED
-} state;
-static unsigned hunt_for_0_count, frame_pos_count;
-static uint8_t in_frame_2bit[160], frame_bits[320];
-
-static void
-unpack_dibits()
-{
-	int i, inb;
-	uint8_t *op;
-
-	op = frame_bits;
-	for (i = 0; i < 160; i++) {
-		inb = in_frame_2bit[i];
-		if (inb & 2)
-			*op++ = 1;
-		else
-			*op++ = 0;
-		if (inb & 1)
-			*op++ = 1;
-		else
-			*op++ = 0;
-	}
-}
-
-static unsigned
-bits_to_num(bits, nbits)
-	uint8_t *bits;
-	unsigned nbits;
-{
-	unsigned accum;
-	unsigned n;
-
-	accum = 0;
-	for (n = 0; n < nbits; n++) {
-		accum <<= 1;
-		if (*bits)
-			accum |= 1;
-		bits++;
-	}
-	return accum;
-}
-
-static void
-process_frame()
-{
-	unsigned c1_5, c6_11;
-
-	printf("Frame at 0x%x:\n", file_offset - 160);
-	printf("  C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18],
-		frame_bits[19], frame_bits[20], frame_bits[21]);
-	c1_5 = bits_to_num(frame_bits + 17, 5);
-	switch (c1_5) {
-	case 0x02:
-		fputs(" (FR UL)", stdout);
-		break;
-	case 0x1C:
-		fputs(" (FR DL)", stdout);
-		break;
-	case 0x1A:
-		fputs(" (EFR)", stdout);
-		break;
-	case 0x10:
-		fputs(" (idle UL)", stdout);
-		break;
-	case 0x0E:
-		fputs(" (idle DL)", stdout);
-		break;
-	}
-	putchar('\n');
-	c6_11 = bits_to_num(frame_bits + 22, 6);
-	printf("  C6-C11: %u\n", c6_11);
-	printf("  C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28],
-		frame_bits[29], frame_bits[30], frame_bits[31]);
-	/* payload to be handled */
-	printf("  C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n",
-		frame_bits[310], frame_bits[311], frame_bits[312],
-		frame_bits[313], frame_bits[314], frame_bits[315]);
-	printf("  T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317],
-		frame_bits[318], frame_bits[319]);
-}
-
-static int
-check_sync_zeros()
-{
-	int i;
-
-	for (i = 0; i < 16; i++) {
-		if (frame_bits[i])
-			return 0;
-	}
-	return 1;
-}
-
-static int
-check_sync_ones()
-{
-	int i;
-
-	for (i = 1; i < 20; i++) {
-		if (!frame_bits[i*16])
-			return 0;
-	}
-	return 1;
-}
-
-static void
-check_sync()
-{
-	if (check_sync_zeros() && check_sync_ones())
-		return;
-	printf("Bad frame sync, returning to hunt state\n");
-	state = HUNT_FOR_0;
-}
-
-static void
-byte_input(inb)
-{
-	switch (state) {
-	case HUNT_FOR_0:
-		if (inb != 0)
-			return;
-		state = HUNT_FOUND_0;
-		hunt_for_0_count = 1;
-		return;
-	case HUNT_FOUND_0:
-		if (inb != 0) {
-			state = HUNT_FOR_0;
-			return;
-		}
-		hunt_for_0_count++;
-		if (hunt_for_0_count >= 8)
-			state = GOT_8_ZEROS;
-		return;
-	case GOT_8_ZEROS:
-		if (inb & 2) {
-			printf("Found frame sync at file offset 0x%x\n",
-				file_offset - 8);
-			bzero(in_frame_2bit, 8);
-			in_frame_2bit[8] = inb;
-			frame_pos_count = 9;
-			state = SYNCED;
-			return;
-		}
-		if (inb != 0)
-			state = HUNT_FOR_0;
-		return;
-	case SYNCED:
-		in_frame_2bit[frame_pos_count++] = inb;
-		if (frame_pos_count < 160)
-			return;
-		frame_pos_count = 0;
-		unpack_dibits();
-		process_frame();
-		check_sync();
-		return;
-	default:
-		fprintf(stderr, "BUG: bad sync state\n");
-		abort();
-	}
-}
-
-main(argc, argv)
-	char **argv;
-{
-	FILE *inf;
-	int subslot, right_shift;
-	int inb;
-
-	if (argc != 3) {
-		fprintf(stderr, "usage: %s binfile subslot\n", argv[0]);
-		exit(1);
-	}
-	inf = fopen(argv[1], "r");
-	if (!inf) {
-		perror(argv[1]);
-		exit(1);
-	}
-	subslot = atoi(argv[2]);
-	if (subslot < 0 || subslot > 3) {
-		fprintf(stderr, "error: invalid subslot argument\n");
-		exit(1);
-	}
-	right_shift = (3 - subslot) * 2;
-	state = HUNT_FOR_0;
-	for (file_offset = 0; ; file_offset++) {
-		inb = getc(inf);
-		if (inb < 0)
-			break;
-		inb >>= right_shift;
-		inb &= 3;
-		byte_input(inb);
-	}
-	exit(0);
-}