FreeCalypso > hg > freecalypso-tools
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); +}