diff loadtools/buzplaypwt.c @ 828:502aec4c1e8e

fc-buzplay: implement playt command for PWT melodies
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 30 May 2021 20:54:02 +0000
parents loadtools/buzplay.c@684eddecbc62
children 85091e14be9c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/buzplaypwt.c	Sun May 30 20:54:02 2021 +0000
@@ -0,0 +1,220 @@
+/*
+ * fc-buzplay: in this module we are going to implement parsing,
+ * uploading and play of PWT melodies.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+
+static struct pwt_note {
+	char	*name;
+	int	code;
+} pwt_notes_table[] = {
+	{"f4",	47},	/* 349 Hz */
+	{"fs4",	43},	/* 370 Hz */
+	{"g4",	39},	/* 392 Hz */
+	{"gs4",	35},	/* 415 Hz */
+	{"a4",	31},	/* 440 Hz */
+	{"as4",	27},	/* 466 Hz */
+	{"b4",	23},	/* 494 Hz */
+	{"c5",	19},	/* 523 Hz */
+	{"cs5",	15},	/* 554 Hz */
+	{"d5",	11},	/* 587 Hz */
+	{"ds5",	7},	/* 622 Hz */
+	{"e5",	3},	/* 659 Hz */
+	{"f5",	46},	/* 698 Hz */
+	{"fs5",	42},	/* 740 Hz */
+	{"g5",	38},	/* 784 Hz */
+	{"gs5",	34},	/* 831 Hz */
+	{"a5",	30},	/* 880 Hz */
+	{"as5",	26},	/* 932 Hz */
+	{"b5",	22},	/* 988 Hz */
+	{"c6",	18},	/* 1047 Hz */
+	{"cs6",	14},	/* 1109 Hz */
+	{"d6",	10},	/* 1175 Hz */
+	{"ds6",	6},	/* 1245 Hz */
+	{"e6",	2},	/* 1319 Hz */
+	{"f6",	45},	/* 1397 Hz */
+	{"fs6",	41},	/* 1480 Hz */
+	{"g6",	37},	/* 1568 Hz */
+	{"gs6",	33},	/* 1661 Hz */
+	{"a6",	29},	/* 1760 Hz */
+	{"as6",	25},	/* 1865 Hz */
+	{"b6",	21},	/* 1976 Hz */
+	{"c7",	17},	/* 2093 Hz */
+	{"cs7",	13},	/* 2217 Hz */
+	{"d7",	9},	/* 2349 Hz */
+	{"ds7",	5},	/* 2489 Hz */
+	{"e7",	1},	/* 2637 Hz */
+	{"f7",	44},	/* 2794 Hz */
+	{"fs7",	40},	/* 2960 Hz */
+	{"g7",	36},	/* 3136 Hz */
+	{"gs7",	32},	/* 3322 Hz */
+	{"a7",	28},	/* 3520 Hz */
+	{"as7",	24},	/* 3729 Hz */
+	{"b7",	20},	/* 3951 Hz */
+	{"c8",	16},	/* 4186 Hz */
+	{"cs8",	12},	/* 4435 Hz */
+	{"d8",	8},	/* 4699 Hz */
+	{"ds8",	4},	/* 4978 Hz */
+	{"e8",	0},	/* 5274 Hz */
+	/* table search terminator */
+	{0,	-1}
+};
+
+cmd_playt(argc, argv)
+	char **argv;
+{
+	FILE *f;
+	char linebuf[256], *cp, *fields[3];
+	int lineno, nfields;
+	char *targv[5], argbuf1[16], argbuf2[16], argbuf3[16];
+	struct pwt_note *tp;
+	u_long global_vol, note_vol, duration, total_ms;
+	int rc, timeout;
+
+	f = fopen(argv[1], "r");
+	if (!f) {
+		perror(argv[1]);
+		return(-1);
+	}
+	if (argv[2]) {
+		global_vol = strtoul(argv[2], 0, 0);
+		if (global_vol < 1 || global_vol > 64) {
+			fprintf(stderr,
+				"error: invalid global volume argument\n");
+			fclose(f);
+			return(-1);
+		}
+	} else
+		global_vol = 64;
+	printf("Uploading the melody to the target\n");
+	targv[0] = "IT";
+	targv[1] = 0;
+	tpinterf_make_cmd(targv);
+	if (tpinterf_send_cmd() < 0) {
+		fclose(f);
+		return(-1);
+	}
+	rc = tpinterf_pass_output(1);
+	if (rc) {
+		fclose(f);
+		return(rc);
+	}
+	total_ms = 0;
+	for (lineno = 1; fgets(linebuf, sizeof linebuf, f); lineno++) {
+		cp = index(linebuf, '\n');
+		if (!cp) {
+			fprintf(stderr, "%s line %d: missing newline\n",
+				argv[1], lineno);
+			fclose(f);
+			return(-1);
+		}
+		cp = linebuf;
+		nfields = 0;
+		for (;;) {
+			while (isspace(*cp))
+				cp++;
+			if (*cp == '\0' || *cp == '#')
+				break;
+			if (nfields >= 3) {
+				fprintf(stderr, "%s line %d: too many fields\n",
+					argv[1], lineno);
+				fclose(f);
+				return(-1);
+			}
+			fields[nfields++] = cp;
+			while (*cp && !isspace(*cp))
+				cp++;
+			if (*cp)
+				*cp++ = '\0';
+		}
+		if (!nfields)
+			continue;
+		if (nfields == 3) {
+			for (tp = pwt_notes_table; tp->name; tp++)
+				if (!strcmp(tp->name, fields[0]))
+					break;
+			if (tp->code < 0) {
+				fprintf(stderr,
+					"%s line %d: invalid note name\n",
+					argv[1], lineno);
+				fclose(f);
+				return(-1);
+			}
+			note_vol = strtoul(fields[1], 0, 0);
+			if (note_vol < 1 || note_vol > 64) {
+				fprintf(stderr,
+					"%s line %d: invalid note volume\n",
+					argv[1], lineno);
+				fclose(f);
+				return(-1);
+			}
+			duration = strtoul(fields[2], 0, 0);
+			if (duration < 1 || duration > 0xFFFF) {
+				fprintf(stderr,
+			"%s line %d: the duration number is out of range\n",
+					argv[1], lineno);
+				fclose(f);
+				return(-1);
+			}
+			sprintf(argbuf1, "%u", (unsigned) tp->code);
+			sprintf(argbuf2, "%u",
+				((global_vol * note_vol + 63) >> 6) - 1);
+			sprintf(argbuf3, "%u", duration);
+			targv[0] = "ET";
+			targv[1] = argbuf1;
+			targv[2] = argbuf2;
+			targv[3] = argbuf3;
+			targv[4] = 0;
+		} else if (nfields == 2 && !strcmp(fields[0], "rest")) {
+			duration = strtoul(fields[1], 0, 0);
+			if (duration < 1 || duration > 0xFFFF) {
+				fprintf(stderr,
+			"%s line %d: the duration number is out of range\n",
+					argv[1], lineno);
+				fclose(f);
+				return(-1);
+			}
+			sprintf(argbuf1, "%u", duration);
+			targv[0] = "EP";
+			targv[1] = argbuf1;
+			targv[2] = 0;
+		} else {
+			fprintf(stderr, "%s line %d: invalid syntax\n",
+				argv[1], lineno);
+			fclose(f);
+			return(-1);
+		}
+		/* send it to the target */
+		tpinterf_make_cmd(targv);
+		if (tpinterf_send_cmd() < 0) {
+			fclose(f);
+			return(-1);
+		}
+		rc = tpinterf_pass_output(1);
+		if (rc) {
+			fclose(f);
+			return(rc);
+		}
+		/* account for the duration */
+		total_ms += duration * 5;
+	}
+	fclose(f);
+	if (!total_ms) {
+		fprintf(stderr, "%s is empty!\n", argv[1]);
+		return(-1);
+	}
+	printf("Requesting play of the uploaded melody on the target\n");
+	targv[0] = "P";
+	targv[1] = 0;
+	tpinterf_make_cmd(targv);
+	if (tpinterf_send_cmd() < 0)
+		return(-1);
+	timeout = total_ms / 1000 + 2;
+	return tpinterf_pass_output(timeout);
+}