view tchtools/fc-vm2gsmx.c @ 905:546bf873ccc8

tchtools: new program fc-vm2gsmx
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 28 Dec 2022 09:08:50 +0000
parents tchtools/fc-vm2hex.c@5041bcb8140f
children
line wrap: on
line source

/*
 * This utility converts old-fashioned (non-AMR) TCS211 voice memo files
 * read out of FFS into Themyscira Wireless gsmx (extended-libgsm) format,
 * allowing further decoding into playable speech with gsmfr-decode.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

static char *infname;
static FILE *inf, *outf;
static u_long file_offset;

static const u_char bfi_marker[2] = {0xBF, 0x00};

static unsigned
get_word()
{
	u_char b[2];
	int i, c;

	for (i = 0; i < 2; i++) {
		c = getc(inf);
		if (c < 0) {
			fprintf(stderr, "error: premature EOF in %s\n",
				infname);
			exit(1);
		}
		b[i] = c;
		file_offset++;
	}
	return((b[1] << 8) | b[0]);
}

static void
read_dsp_bytes(bytes)
	u_char *bytes;
{
	int i, dp;
	unsigned word;

	dp = 0;
	for (i = 0; i < 17; i++) {
		word = get_word();
		bytes[dp++] = word >> 8;
		bytes[dp++] = word;
	}
}

static void
convert_speech_sample()
{
	u_char tidsp_bytes[34], libgsm_bytes[33];

	read_dsp_bytes(tidsp_bytes);
	gsm0610_tidsp_to_libgsm(tidsp_bytes, libgsm_bytes);
	fwrite(libgsm_bytes, 1, 33, outf);
}

main(argc, argv)
	char **argv;
{
	unsigned first_word;

	if (argc != 3) {
		fprintf(stderr, "usage: %s infile outfile\n", argv[0]);
		exit(1);
	}
	infname = argv[1];
	inf = fopen(infname, "r");
	if (!inf) {
		perror(infname);
		exit(1);
	}
	outf = fopen(argv[2], "w");
	if (!outf) {
		perror(argv[2]);
		exit(1);
	}
	for (;;) {
		first_word = get_word();
		if (first_word == 0xFBFF)	/* SC_VM_END_MASK */
			break;
		if ((first_word & 0xB7FF) == 0x8400) {
			/* skip dummy header words 1 and 2 */
			get_word();
			get_word();
			/* process the actual speech or SID frame */
			convert_speech_sample();
		} else if (first_word == 0x0400) {
			/* it's a skipped frame, aka BFI */
			fwrite(bfi_marker, 1, 2, outf);
		} else {
			fprintf(stderr,
	"error in %s at offset 0x%lx: invalid frame header word 0x%04X\n",
				infname, file_offset, first_word);
			exit(1);
		}
	}
	fclose(outf);
	exit(0);
}