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