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