changeset 56:e95e145f4b32

fr-sid: generate test sequence
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 22 Aug 2024 06:39:12 +0000
parents f27bc1e17311
children a64e5ed217c0
files .hgignore fr-sid/Makefile fr-sid/mk-sid-test.c
diffstat 3 files changed, 184 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu Aug 22 05:00:08 2024 +0000
+++ b/.hgignore	Thu Aug 22 06:39:12 2024 +0000
@@ -29,6 +29,8 @@
 ^efr-sid/mk-sid-test$
 ^efr-sid/mk-sid-test2$
 
+^fr-sid/mk-sid-test$
+
 ^hr-sid/misorder$
 ^hr-sid/sidgen$
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fr-sid/Makefile	Thu Aug 22 06:39:12 2024 +0000
@@ -0,0 +1,26 @@
+CC=	gcc
+CFLAGS=	-O2
+PROG=	mk-sid-test
+INPUT=	goodsp-frame41.gsmx
+
+OUT_NATIVE=	fr1-sid-test.gsmx
+OUT_HEX=	fr1-sid-test.hex
+OUT_TCH=	fr1-sid-test.tch
+OUTPUTS=	${OUT_NATIVE} ${OUT_HEX} ${OUT_TCH}
+
+all:	${PROG} ${OUTPUTS}
+
+${PROG}:	${PROG}.c
+	${CC} ${CFLAGS} -o $@ $@.c
+
+${OUT_NATIVE}:	${PROG} ${INPUT}
+	./${PROG} ${INPUT} $@
+
+${OUT_HEX}:	${OUT_NATIVE}
+	../utils/gen-hex-lines ${OUT_NATIVE} $@ 33
+
+${OUT_TCH}:	${OUT_NATIVE}
+	fc-fr2tch ${OUT_NATIVE} $@
+
+clean:
+	rm -f ${PROG} *.o ${OUT_NATIVE} *.hex *.tch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fr-sid/mk-sid-test.c	Thu Aug 22 06:39:12 2024 +0000
@@ -0,0 +1,156 @@
+/*
+ * This program generates a set of FRv1 codec frames based on a single input
+ * frame (in gsmx packed binary format) that is expected to be a perfect SID.
+ * The output frame set is intended to serve as a unit test for the
+ * bit-counting SID classification function; it will contain different
+ * extents of bit alteration to produce valid SID, invalid SID and non-SID
+ * speech classifications.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <tw_gsmfr.h>
+
+static uint8_t input_frame[GSMFR_RTP_FRAME_LEN];
+static FILE *outf;
+
+static void
+read_input_file(filename)
+	char *filename;
+{
+	FILE *inf;
+	int cc;
+
+	inf = fopen(filename, "r");
+	if (!inf) {
+		perror(filename);
+		exit(1);
+	}
+	cc = fread(input_frame, GSMFR_RTP_FRAME_LEN, 1, inf);
+	if (cc < 1) {
+		fprintf(stderr, "error: short read from %s\n", filename);
+		exit(1);
+	}
+	fclose(inf);
+	if ((input_frame[0] & 0xF0) != 0xD0) {
+		fprintf(stderr,
+			"error: bytes read from %s are not a GSM-FR frame\n",
+			filename);
+		exit(1);
+	}
+}
+
+static const unsigned short sid_field_bits[95] = {
+	57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73,
+	75, 76, 78, 79, 81, 82, 84, 85, 87, 88, 90, 91,
+	93, 94, 113, 114, 116, 117, 119, 120, 122, 123,
+	125, 126, 128, 129, 131, 132, 134, 135, 137,
+	138, 140, 141, 143, 144, 146, 147, 149, 150,
+	169, 170, 172, 173, 175, 176, 178, 179, 181,
+	182, 184, 185, 187, 188, 190, 191, 193, 194,
+	196, 197, 199, 200, 202, 203, 205, 206, 225,
+	226, 228, 229, 231, 232, 234, 235, 237, 240,
+	243, 246, 249, 252, 255, 258, 261
+};
+
+static void
+set_bit(frame, bitnum)
+	uint8_t *frame;
+	unsigned bitnum;
+{
+	unsigned bytenum = bitnum >> 3;
+	unsigned bit_in_byte = 7 - (bitnum & 7);
+	unsigned bitmask = 1 << bit_in_byte;
+
+	frame[bytenum] |= bitmask;
+}
+
+static void
+emit_out_frame(frame)
+	uint8_t *frame;
+{
+	fwrite(frame, GSMFR_RTP_FRAME_LEN, 1, outf);
+}
+
+static void
+emit_1bit_errors()
+{
+	uint8_t frame[GSMFR_RTP_FRAME_LEN];
+	unsigned n;
+
+	for (n = 0; n < 95; n++) {
+		bcopy(input_frame, frame, GSMFR_RTP_FRAME_LEN);
+		set_bit(frame, sid_field_bits[n]);
+		emit_out_frame(frame);
+	}
+}
+
+static void
+emit_2bit_errors()
+{
+	uint8_t frame[GSMFR_RTP_FRAME_LEN];
+	unsigned n;
+
+	for (n = 0; n < 48; n++) {
+		bcopy(input_frame, frame, GSMFR_RTP_FRAME_LEN);
+		set_bit(frame, sid_field_bits[n]);
+		set_bit(frame, sid_field_bits[n + 47]);
+		emit_out_frame(frame);
+	}
+}
+
+static void
+emit_15bit_errors()
+{
+	uint8_t frame[GSMFR_RTP_FRAME_LEN];
+	unsigned i, j;
+
+	for (i = 0; i < 11; i++) {
+		bcopy(input_frame, frame, GSMFR_RTP_FRAME_LEN);
+		for (j = 0; j < 15; j++)
+			set_bit(frame, sid_field_bits[j * 6 + i]);
+		emit_out_frame(frame);
+	}
+}
+
+static void
+emit_16bit_errors()
+{
+	uint8_t frame[GSMFR_RTP_FRAME_LEN];
+	unsigned i, j;
+
+	for (i = 0; i < 20; i++) {
+		bcopy(input_frame, frame, GSMFR_RTP_FRAME_LEN);
+		for (j = 0; j < 16; j++)
+			set_bit(frame, sid_field_bits[j * 5 + i]);
+		emit_out_frame(frame);
+	}
+}
+
+main(argc, argv)
+	char **argv;
+{
+	if (argc != 3) {
+		fprintf(stderr, "usage: %s input.gsmx output.gsmx\n", argv[0]);
+		exit(1);
+	}
+	read_input_file(argv[1]);
+	outf = fopen(argv[2], "w");
+	if (!outf) {
+		perror(argv[2]);
+		exit(1);
+	}
+	/* emit the perfect, error-free SID first */
+	emit_out_frame(input_frame);
+	/* now different bit-error possibilities */
+	emit_1bit_errors();
+	emit_2bit_errors();
+	emit_15bit_errors();
+	emit_16bit_errors();
+	/* all done */
+	fclose(outf);
+	exit(0);
+}