view compal/melody-extr/extr-onemel.c @ 392:35009c936a4a

compal/melody-extr: first attempt at actual melody extraction
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 01 Apr 2022 06:03:47 +0000
parents
children
line wrap: on
line source

/*
 * This program is our attempt at extracting built-in melodies
 * from Mot C1xx firmware images.
 */

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

FILE *binf;
int freq_offset;
unsigned time_factor;

char *note_names[48] = {
	"f4","fs4","g4","gs4","a4","as4","b4", "c5","cs5","d5","ds5","e5",
	"f5","fs5","g5","gs5","a5","as5","b5", "c6","cs6","d6","ds6","e6",
	"f6","fs6","g6","gs6","a6","as6","b6", "c7","cs7","d7","ds7","e7",
	"f7","fs7","g7","gs7","a7","as7","b7", "c8","cs8","d8","ds8","e8"
};

open_and_seek_input(binfname, offset_arg)
	char *binfname, *offset_arg;
{
	u_long offset;

	binf = fopen(binfname, "r");
	if (!binf) {
		perror(binfname);
		exit(1);
	}
	offset = strtoul(offset_arg, 0, 0);
	fseek(binf, offset, SEEK_SET);
}

process_record()
{
	u_char record[4];
	int note, vol_adj;
	unsigned duration;

	if (fread(&record, sizeof record, 1, binf) != 1) {
		fprintf(stderr, "error reading from binary file\n");
		exit(1);
	}
	duration = record[0] * time_factor + 1;
	if (record[2]) {
		note = record[2] + freq_offset;
		if (note < 1 || note > 48) {
			fprintf(stderr, "error: note is out of range\n");
			exit(1);
		}
		note--;
		printf("%s\t64\t%u", note_names[note], duration);
		vol_adj = record[1];
		if (vol_adj) {
			if (vol_adj >= 128)
				vol_adj -= 256;
			printf("\t# Vol %+d", vol_adj);
		}
		fputs("\nrest\t\t2\n", stdout);
	} else {
		printf("rest\t\t%u\n", duration);
	}
}

main(argc, argv)
	char **argv;
{
	unsigned n, num_entries;

	if (argc != 6) {
		fprintf(stderr,
	"usage: %s fw-image-file file-offset num-entries freq-off time-mult\n",
			argv[0]);
		exit(1);
	}
	open_and_seek_input(argv[1], argv[2]);
	num_entries = strtoul(argv[3], 0, 0);
	freq_offset = atoi(argv[4]);
	time_factor = atoi(argv[5]);
	for (n = 0; n < num_entries; n++)
		process_record();
	exit(0);
}