comparison 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
comparison
equal deleted inserted replaced
827:0af2529d9376 828:502aec4c1e8e
1 /*
2 * fc-buzplay: in this module we are going to implement parsing,
3 * uploading and play of PWT melodies.
4 */
5
6 #include <sys/types.h>
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <strings.h>
11 #include <stdlib.h>
12
13 static struct pwt_note {
14 char *name;
15 int code;
16 } pwt_notes_table[] = {
17 {"f4", 47}, /* 349 Hz */
18 {"fs4", 43}, /* 370 Hz */
19 {"g4", 39}, /* 392 Hz */
20 {"gs4", 35}, /* 415 Hz */
21 {"a4", 31}, /* 440 Hz */
22 {"as4", 27}, /* 466 Hz */
23 {"b4", 23}, /* 494 Hz */
24 {"c5", 19}, /* 523 Hz */
25 {"cs5", 15}, /* 554 Hz */
26 {"d5", 11}, /* 587 Hz */
27 {"ds5", 7}, /* 622 Hz */
28 {"e5", 3}, /* 659 Hz */
29 {"f5", 46}, /* 698 Hz */
30 {"fs5", 42}, /* 740 Hz */
31 {"g5", 38}, /* 784 Hz */
32 {"gs5", 34}, /* 831 Hz */
33 {"a5", 30}, /* 880 Hz */
34 {"as5", 26}, /* 932 Hz */
35 {"b5", 22}, /* 988 Hz */
36 {"c6", 18}, /* 1047 Hz */
37 {"cs6", 14}, /* 1109 Hz */
38 {"d6", 10}, /* 1175 Hz */
39 {"ds6", 6}, /* 1245 Hz */
40 {"e6", 2}, /* 1319 Hz */
41 {"f6", 45}, /* 1397 Hz */
42 {"fs6", 41}, /* 1480 Hz */
43 {"g6", 37}, /* 1568 Hz */
44 {"gs6", 33}, /* 1661 Hz */
45 {"a6", 29}, /* 1760 Hz */
46 {"as6", 25}, /* 1865 Hz */
47 {"b6", 21}, /* 1976 Hz */
48 {"c7", 17}, /* 2093 Hz */
49 {"cs7", 13}, /* 2217 Hz */
50 {"d7", 9}, /* 2349 Hz */
51 {"ds7", 5}, /* 2489 Hz */
52 {"e7", 1}, /* 2637 Hz */
53 {"f7", 44}, /* 2794 Hz */
54 {"fs7", 40}, /* 2960 Hz */
55 {"g7", 36}, /* 3136 Hz */
56 {"gs7", 32}, /* 3322 Hz */
57 {"a7", 28}, /* 3520 Hz */
58 {"as7", 24}, /* 3729 Hz */
59 {"b7", 20}, /* 3951 Hz */
60 {"c8", 16}, /* 4186 Hz */
61 {"cs8", 12}, /* 4435 Hz */
62 {"d8", 8}, /* 4699 Hz */
63 {"ds8", 4}, /* 4978 Hz */
64 {"e8", 0}, /* 5274 Hz */
65 /* table search terminator */
66 {0, -1}
67 };
68
69 cmd_playt(argc, argv)
70 char **argv;
71 {
72 FILE *f;
73 char linebuf[256], *cp, *fields[3];
74 int lineno, nfields;
75 char *targv[5], argbuf1[16], argbuf2[16], argbuf3[16];
76 struct pwt_note *tp;
77 u_long global_vol, note_vol, duration, total_ms;
78 int rc, timeout;
79
80 f = fopen(argv[1], "r");
81 if (!f) {
82 perror(argv[1]);
83 return(-1);
84 }
85 if (argv[2]) {
86 global_vol = strtoul(argv[2], 0, 0);
87 if (global_vol < 1 || global_vol > 64) {
88 fprintf(stderr,
89 "error: invalid global volume argument\n");
90 fclose(f);
91 return(-1);
92 }
93 } else
94 global_vol = 64;
95 printf("Uploading the melody to the target\n");
96 targv[0] = "IT";
97 targv[1] = 0;
98 tpinterf_make_cmd(targv);
99 if (tpinterf_send_cmd() < 0) {
100 fclose(f);
101 return(-1);
102 }
103 rc = tpinterf_pass_output(1);
104 if (rc) {
105 fclose(f);
106 return(rc);
107 }
108 total_ms = 0;
109 for (lineno = 1; fgets(linebuf, sizeof linebuf, f); lineno++) {
110 cp = index(linebuf, '\n');
111 if (!cp) {
112 fprintf(stderr, "%s line %d: missing newline\n",
113 argv[1], lineno);
114 fclose(f);
115 return(-1);
116 }
117 cp = linebuf;
118 nfields = 0;
119 for (;;) {
120 while (isspace(*cp))
121 cp++;
122 if (*cp == '\0' || *cp == '#')
123 break;
124 if (nfields >= 3) {
125 fprintf(stderr, "%s line %d: too many fields\n",
126 argv[1], lineno);
127 fclose(f);
128 return(-1);
129 }
130 fields[nfields++] = cp;
131 while (*cp && !isspace(*cp))
132 cp++;
133 if (*cp)
134 *cp++ = '\0';
135 }
136 if (!nfields)
137 continue;
138 if (nfields == 3) {
139 for (tp = pwt_notes_table; tp->name; tp++)
140 if (!strcmp(tp->name, fields[0]))
141 break;
142 if (tp->code < 0) {
143 fprintf(stderr,
144 "%s line %d: invalid note name\n",
145 argv[1], lineno);
146 fclose(f);
147 return(-1);
148 }
149 note_vol = strtoul(fields[1], 0, 0);
150 if (note_vol < 1 || note_vol > 64) {
151 fprintf(stderr,
152 "%s line %d: invalid note volume\n",
153 argv[1], lineno);
154 fclose(f);
155 return(-1);
156 }
157 duration = strtoul(fields[2], 0, 0);
158 if (duration < 1 || duration > 0xFFFF) {
159 fprintf(stderr,
160 "%s line %d: the duration number is out of range\n",
161 argv[1], lineno);
162 fclose(f);
163 return(-1);
164 }
165 sprintf(argbuf1, "%u", (unsigned) tp->code);
166 sprintf(argbuf2, "%u",
167 ((global_vol * note_vol + 63) >> 6) - 1);
168 sprintf(argbuf3, "%u", duration);
169 targv[0] = "ET";
170 targv[1] = argbuf1;
171 targv[2] = argbuf2;
172 targv[3] = argbuf3;
173 targv[4] = 0;
174 } else if (nfields == 2 && !strcmp(fields[0], "rest")) {
175 duration = strtoul(fields[1], 0, 0);
176 if (duration < 1 || duration > 0xFFFF) {
177 fprintf(stderr,
178 "%s line %d: the duration number is out of range\n",
179 argv[1], lineno);
180 fclose(f);
181 return(-1);
182 }
183 sprintf(argbuf1, "%u", duration);
184 targv[0] = "EP";
185 targv[1] = argbuf1;
186 targv[2] = 0;
187 } else {
188 fprintf(stderr, "%s line %d: invalid syntax\n",
189 argv[1], lineno);
190 fclose(f);
191 return(-1);
192 }
193 /* send it to the target */
194 tpinterf_make_cmd(targv);
195 if (tpinterf_send_cmd() < 0) {
196 fclose(f);
197 return(-1);
198 }
199 rc = tpinterf_pass_output(1);
200 if (rc) {
201 fclose(f);
202 return(rc);
203 }
204 /* account for the duration */
205 total_ms += duration * 5;
206 }
207 fclose(f);
208 if (!total_ms) {
209 fprintf(stderr, "%s is empty!\n", argv[1]);
210 return(-1);
211 }
212 printf("Requesting play of the uploaded melody on the target\n");
213 targv[0] = "P";
214 targv[1] = 0;
215 tpinterf_make_cmd(targv);
216 if (tpinterf_send_cmd() < 0)
217 return(-1);
218 timeout = total_ms / 1000 + 2;
219 return tpinterf_pass_output(timeout);
220 }