view ringtools/fc-e1decode.c @ 805:a43c5dc251dc

doc/User-phone-tools: new sms-pdu-decode backslash escapes
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 25 Mar 2021 05:10:43 +0000
parents c8806a5d4a6a
children
line wrap: on
line source

/*
 * This program decodes a binary Melody E1 file into the ASCII source format
 * of our own invention which fc-e1gen accepts as input.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>

char *infname;
FILE *inf, *outf;

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;
	}
	return((b[1] << 8) | b[0]);
}

do_global_osc_set()
{
	unsigned word, osc;

	word = get_word();
	fprintf(outf, "osc-set (%u)", word & 0xFF);
	for (osc = 0; osc < 8; osc++)
		if (word & (1 << (osc + 8)))
			fprintf(outf, " %u", osc);
	putc('\n', outf);
	putc('\n', outf);
}

convert_signed_14bit(u)
	unsigned u;
{
	int i;

	i = u;
	if (i >= 8192)
		i -= 16384;
	return (i);
}

convert_signed_5bit(u)
	unsigned u;
{
	int i;

	i = u;
	if (i >= 16)
		i -= 32;
	return (i);
}

process_oscwords(osc, warnflags)
	unsigned osc, *warnflags;
{
	unsigned word0, word1, extraword;

	word0 = get_word();
	word1 = get_word();
	if (word1 & 0xF)
		*warnflags |= 1;
	fprintf(outf, "osc %u (%u)", osc, word0 & 1);
	if (word0 & 2) {
		fprintf(outf, " df %d %u", convert_signed_14bit(word0 >> 2),
			word1 >> 6);
	} else {
		if (word0 & 4)
			fputs(" sq1", outf);
		if (word0 & 8)
			fputs(" sq2", outf);
		fprintf(outf, " %u %u %u", (word0 >> 4) & 0x3F, word0 >> 10,
			word1 >> 6);
	}
	if (word1 & 0x10) {
		extraword = get_word();
		if (extraword & 0xFF)
			*warnflags |= 2;
		fprintf(outf, " trem %u %d", (extraword >> 8) & 7,
			convert_signed_5bit(extraword >> 11));
	}
	if (word1 & 0x20) {
		extraword = get_word();
		fprintf(outf, " env %u %u %u %u %u", extraword & 0xF,
			extraword >> 13, (extraword >> 10) & 7,
			(extraword >> 7) & 7, (extraword >> 4) & 7);
	}
	putc('\n', outf);
}

process_block(timeword)
	unsigned timeword;
{
	unsigned osc, warnflags[8], anywarn;

	fprintf(outf, "time %u\n", timeword & 0xFF);
	for (osc = 0; osc < 8; osc++) {
		warnflags[osc] = 0;
		if (timeword & (1 << (osc + 8)))
			process_oscwords(osc, warnflags + osc);
	}
	putc('\n', outf);
	anywarn = 0;
	for (osc = 0; osc < 8; osc++) {
		if (warnflags[osc] & 1) {
			fprintf(outf,
			"# warning: reserved bits set in osc %u word1 above\n",
				osc);
			anywarn = 1;
		}
		if (warnflags[osc] & 2) {
			fprintf(outf,
			"# warning: reserved bits set in osc %u word2 above\n",
				osc);
			anywarn = 1;
		}
	}
	if (anywarn)
		putc('\n', outf);
}

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

	if (argc < 2 || 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);
	}
	if (argc > 2) {
		outf = fopen(argv[2], "w");
		if (!outf) {
			perror(argv[2]);
			exit(1);
		}
	} else
		outf = stdout;
	do_global_osc_set();
	for (;;) {
		timeword = get_word();
		if (timeword == 0)
			break;
		process_block(timeword);
	}
	fputs("end\n", outf);
	exit(0);
}