comparison ringtools/imy/convert.c @ 882:fd4c9bc7835d

fc-imy2pwt program written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 03 Apr 2022 03:30:27 +0000
parents
children 3e398f9c31a0
comparison
equal deleted inserted replaced
881:bb8ad7c0cee8 882:fd4c9bc7835d
1 /*
2 * This module implements the second pass of fc-imy2pwt processing:
3 * stepping through the captured melody and converting it to PWT.
4 */
5
6 #include <ctype.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <strings.h>
11
12 extern char melody_str_buf[];
13 extern unsigned tdma_durations[6][4];
14 extern FILE *outF;
15
16 static int cur_octave = 4;
17
18 static char *pwt_note_names[12] = {"c", "cs", "d", "ds", "e", "f", "fs",
19 "g", "gs", "a", "as", "b"};
20
21 static void
22 process_octave_cmd(octchar)
23 {
24 if (!isdigit(octchar)) {
25 fprintf(stderr,
26 "melody error: '*' octave prefix not followed by digit\n");
27 exit(1);
28 }
29 cur_octave = octchar - '0';
30 }
31
32 static int
33 process_note(str, type)
34 char *str;
35 {
36 int note, dur_basic, dur_mod;
37
38 switch (*str) {
39 case 'c':
40 note = 0;
41 break;
42 case 'd':
43 note = 2;
44 break;
45 case 'e':
46 note = 4;
47 break;
48 case 'f':
49 note = 5;
50 break;
51 case 'g':
52 note = 7;
53 break;
54 case 'a':
55 note = 9;
56 break;
57 case 'b':
58 note = 11;
59 break;
60 default:
61 fprintf(stderr,
62 "melody error: note letter expected after '&' or '#'\n");
63 exit(1);
64 }
65 switch (type) {
66 case 1:
67 if (note == 0 || note == 5) {
68 fprintf(stderr, "melody error: invalid flat note\n");
69 exit(1);
70 }
71 note--;
72 break;
73 case 2:
74 if (note == 4 || note == 11) {
75 fprintf(stderr, "melody error: invalid sharp note\n");
76 exit(1);
77 }
78 note++;
79 break;
80 }
81 if (str[1] < '0' || str[1] > '5') {
82 fprintf(stderr,
83 "melody error: missing expected note duration digit\n");
84 exit(1);
85 }
86 dur_basic = str[1] - '0';
87 switch (str[2]) {
88 case '.':
89 dur_mod = 1;
90 break;
91 case ':':
92 dur_mod = 2;
93 break;
94 case ';':
95 dur_mod = 3;
96 break;
97 default:
98 dur_mod = 0;
99 break;
100 }
101 fprintf(outF, "%s%d\t64\t%u\n", pwt_note_names[note], cur_octave + 1,
102 tdma_durations[dur_basic][dur_mod]);
103 if (dur_mod)
104 return 3;
105 else
106 return 2;
107 }
108
109 static int
110 process_rest(str)
111 char *str;
112 {
113 int dur_basic, dur_mod;
114
115 if (str[1] < '0' || str[1] > '5') {
116 fprintf(stderr,
117 "melody error: missing expected rest duration digit\n");
118 exit(1);
119 }
120 dur_basic = str[1] - '0';
121 switch (str[2]) {
122 case '.':
123 dur_mod = 1;
124 break;
125 case ':':
126 dur_mod = 2;
127 break;
128 case ';':
129 dur_mod = 3;
130 break;
131 default:
132 dur_mod = 0;
133 break;
134 }
135 fprintf(outF, "rest\t\t%u\n", tdma_durations[dur_basic][dur_mod]);
136 if (dur_mod)
137 return 3;
138 else
139 return 2;
140 }
141
142 melody_convert_pass()
143 {
144 char *cp, *repeat_start_ptr;
145 int repeat_start_octave, repeat_count, rpt_set;
146
147 repeat_start_ptr = 0;
148 for (cp = melody_str_buf; *cp; ) {
149 /* skip junk first */
150 if (!strncmp(cp, "vibeon", 6)) {
151 cp += 6;
152 continue;
153 }
154 if (!strncmp(cp, "vibeoff", 7)) {
155 cp += 7;
156 continue;
157 }
158 if (!strncmp(cp, "ledon", 5)) {
159 cp += 5;
160 continue;
161 }
162 if (!strncmp(cp, "ledoff", 6)) {
163 cp += 6;
164 continue;
165 }
166 if (!strncmp(cp, "backon", 6)) {
167 cp += 6;
168 continue;
169 }
170 if (!strncmp(cp, "backoff", 7)) {
171 cp += 7;
172 continue;
173 }
174 /* real stuff */
175 switch (*cp) {
176 case '*':
177 process_octave_cmd(cp[1]);
178 cp += 2;
179 continue;
180 case 'c':
181 case 'd':
182 case 'e':
183 case 'f':
184 case 'g':
185 case 'a':
186 case 'b':
187 cp += process_note(cp, 0);
188 continue;
189 case '&':
190 cp++;
191 cp += process_note(cp, 1);
192 continue;
193 case '#':
194 cp++;
195 cp += process_note(cp, 2);
196 continue;
197 case 'r':
198 cp += process_rest(cp);
199 continue;
200 case 'V':
201 /* skip unimplemented volume control */
202 cp++;
203 if (*cp == '+' || *cp == '-') {
204 cp++;
205 continue;
206 }
207 if (!isdigit(*cp)) {
208 fprintf(stderr,
209 "melody error: invalid character after 'V'\n");
210 exit(1);
211 }
212 if (*cp == '1' && cp[1] >= '0' && cp[1] <= '5')
213 cp += 2;
214 else
215 cp++;
216 continue;
217 case '(':
218 if (repeat_start_ptr) {
219 fprintf(stderr,
220 "melody error: nested repeat\n");
221 exit(1);
222 }
223 cp++;
224 repeat_start_ptr = cp;
225 repeat_start_octave = cur_octave;
226 repeat_count = 0;
227 continue;
228 case '@':
229 if (!repeat_start_ptr) {
230 fprintf(stderr,
231 "melody error: '@' not in repeat block\n");
232 exit(1);
233 }
234 cp++;
235 if (!isdigit(*cp)) {
236 fprintf(stderr,
237 "melody error: '@' not followed by digit\n");
238 exit(1);
239 }
240 rpt_set = *cp - '0';
241 if (!rpt_set) {
242 fprintf(stderr,
243 "melody error: infinite repeat not supported\n");
244 exit(1);
245 }
246 cp++;
247 if (!repeat_count)
248 repeat_count = rpt_set;
249 continue;
250 case ')':
251 if (!repeat_start_ptr) {
252 fprintf(stderr,
253 "melody error: ')' without opening '('\n");
254 exit(1);
255 }
256 if (!repeat_count) {
257 fprintf(stderr,
258 "melody error: repeat block without count\n");
259 exit(1);
260 }
261 repeat_count--;
262 if (repeat_count) {
263 cp = repeat_start_ptr;
264 cur_octave = repeat_start_octave;
265 } else {
266 cp++;
267 repeat_start_ptr = 0;
268 }
269 continue;
270 default:
271 fprintf(stderr,
272 "melody error: non-understood character\n");
273 exit(1);
274 }
275 }
276 }