view fr-sid/mk-sid-test.c @ 57:a64e5ed217c0 default tip

top Makefile: add fr-sid
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 22 Aug 2024 06:43:31 +0000
parents e95e145f4b32
children
line wrap: on
line source

/*
 * 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);
}