view frtest/hand-test.c @ 105:ecfbced76fea

gsm-amr2efr: add -w option to simulate common wrong implementation
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 27 Nov 2022 05:59:10 +0000
parents d21c68b8f16c
children
line wrap: on
line source

/*
 * This program is a debug aid that allows a developer to hand-craft input
 * to the GSM 06.10 decoder (libgsm) and see what output magnitude it results
 * in, in the style of gsmfr-max-out.  This program reads input from an
 * ASCII text file in the same format as gsmrec-dump, performs gsm_implode()
 * and gsm_decode() operations and reports maximum output magnitude for
 * each processed frame.
 */

#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <gsm.h>

static char *infname;
static FILE *inf;
static char linebuf[256];
static int lineno;

static
get_line()
{
	if (!fgets(linebuf, sizeof linebuf, inf))
		return 0;
	lineno++;
	if (!index(linebuf, '\n')) {
		fprintf(stderr, "%s line %d: too long or missing newline\n",
			infname, lineno);
		exit(1);
	}
	return 1;
}

static
read_lar_params(params)
	gsm_signal *params;
{
	char *cp;
	unsigned n;

	for (;;) {
		if (!get_line())
			return 0;
		for (cp = linebuf; isspace(*cp); cp++)
			;
		if (*cp)
			break;
	}
	if (*cp == '#') {
		cp++;
		if (!isdigit(*cp)) {
inv_syntax:		fprintf(stderr,
				"%s line %d: invalid syntax (expected LAR)\n",
				infname, lineno);
			exit(1);
		}
		while (isdigit(*cp))
			cp++;
		if (*cp++ != ':')
			goto inv_syntax;
		while (isspace(*cp))
			cp++;
	}
	if (cp[0] != 'F' || cp[1] != 'R' || !isspace(cp[2]))
		goto inv_syntax;
	cp += 3;
	for (n = 0; n < 8; n++) {
		while (isspace(*cp))
			cp++;
		if (!isdigit(*cp))
			goto inv_syntax;
		params[n] = strtoul(cp, &cp, 10);
		if (!isspace(*cp))
			goto inv_syntax;
	}
	fputs(linebuf, stdout);
	return 1;
}

static void
read_subframe_params(params)
	gsm_signal *params;
{
	char *cp;
	unsigned n;

	for (;;) {
		if (!get_line()) {
			fprintf(stderr,
				"%s bad: EOF in the middle of a frame\n",
				infname);
			exit(1);
		}
		for (cp = linebuf; isspace(*cp); cp++)
			;
		if (*cp)
			break;
	}
	for (n = 0; n < 17; n++) {
		while (isspace(*cp))
			cp++;
		if (!isdigit(*cp)) {
inv_syntax:		fprintf(stderr,
			"%s line %d: invalid syntax (expected subframe)\n",
				infname, lineno);
			exit(1);
		}
		params[n] = strtoul(cp, &cp, 10);
		if (!isspace(*cp))
			goto inv_syntax;
	}
	fputs(linebuf, stdout);
}

static
read_frame(params)
	gsm_signal *params;
{
	int rc;
	unsigned n, idx;

	rc = read_lar_params(params);
	if (!rc)
		return 0;
	idx = 8;
	for (n = 0; n < 4; n++) {
		read_subframe_params(params + idx);
		idx += 17;
	}
	return 1;
}

main(argc, argv)
	char **argv;
{
	gsm dec_state;
	gsm_signal params[76];
	uint8_t frame[33];
	int16_t pcm[160];
	int rc, i;
	unsigned samp_abs, samp_max;

	if (argc != 2) {
		fprintf(stderr, "usage: %s input-file\n", argv[0]);
		exit(1);
	}
	infname = argv[1];
	inf = fopen(infname, "r");
	if (!inf) {
		perror(infname);
		exit(1);
	}
	dec_state = gsm_create();
	if (!dec_state) {
		fprintf(stderr, "gsm_create() failed!\n");
		exit(1);
	}
	for (;;) {
		rc = read_frame(params);
		if (!rc)
			break;
		gsm_implode(dec_state, params, frame);
		gsm_decode(dec_state, frame, pcm);
		samp_max = 0;
		for (i = 0; i < 160; i++) {
			if (pcm[i] >= 0)
				samp_abs = pcm[i];
			else
				samp_abs = -pcm[i];
			if (samp_abs > samp_max)
				samp_max = samp_abs;
		}
		printf("  MAX=%u\n", samp_max);
	}
	exit(0);
}