Commit | Line | Data |
---|---|---|
69695f33 MW |
1 | |
2 | /* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2005 by Arkkra Enterprises */ | |
3 | /* All rights reserved */ | |
4 | ||
5 | /* utility functions for creating MIDI output from Mup input. These functions | |
6 | * are split out into this file to keep midi.c from being so huge */ | |
7 | ||
8 | #ifdef __WATCOMC__ | |
9 | #include <io.h> | |
10 | #endif | |
11 | #include "defines.h" | |
12 | #include "structs.h" | |
13 | #include "globals.h" | |
14 | ||
15 | ||
16 | static struct GRPSYL *create_prev_grp P((struct MAINLL *mll_p, int staffno, | |
17 | int v)); | |
18 | static struct GRPSYL *create_meas_space P((struct MAINLL *mll_p)); | |
19 | static void fix_spacechord P((struct MAINLL *chmll_p, struct CHORD *ch_p)); | |
20 | static void splitspace P((struct GRPSYL *gs_p, RATIONAL duration)); | |
21 | static void splicechord P((struct GRPSYL *gs_p, struct CHORD *ch_p)); | |
22 | static void guitar_grpsyl_transpose P((struct GRPSYL *gs_p)); | |
23 | static RATIONAL find_acc_end_time P((RATIONAL begin_time, struct GRPSYL *gs_p, | |
24 | int n)); | |
25 | static void propogate_accidental P((struct NOTE *note_p, RATIONAL begin_time, | |
26 | RATIONAL end_time, struct GRPSYL *gs_p)); | |
27 | static void mv_skipped_midi P((struct STUFF *stuff_p, int staffno, | |
28 | struct MAINLL *topstaff_mll_p)); | |
29 | \f | |
30 | ||
31 | /* seek back to where header size is in file, and fill in the correct size, | |
32 | * now that we know what it is. */ | |
33 | ||
34 | void | |
35 | fix_track_size(mfile, track_start, track_size) | |
36 | ||
37 | int mfile; /* file descriptor of MIDI file */ | |
38 | long track_start; /* offset in file where size needs to be put */ | |
39 | long track_size; /* track length in bytes */ | |
40 | ||
41 | { | |
42 | unsigned char buff[4]; | |
43 | ||
44 | ||
45 | debug(512, "fix_track_size"); | |
46 | ||
47 | /* go to where track size is stored in file */ | |
48 | (void) lseek(mfile, track_start + 4, SEEK_SET); | |
49 | ||
50 | /* convert to 4-byte number with correct byte ordering regardless | |
51 | * of machine byte ordering */ | |
52 | buff[0] = (track_size >> 24) & 0xff; | |
53 | buff[1] = (track_size >> 16) & 0xff; | |
54 | buff[2] = (track_size >> 8) & 0xff; | |
55 | buff[3] = track_size & 0xff; | |
56 | (void) write(mfile, buff, 4); | |
57 | ||
58 | /* go back to end of file in case there are more track to write */ | |
59 | (void) lseek(mfile, 0L, SEEK_END); | |
60 | } | |
61 | \f | |
62 | ||
63 | /* given an octave mark string, return number of octaves to tranpose (could | |
64 | * be negative if transposing down) */ | |
65 | ||
66 | int | |
67 | parse_octave(string, place, fname, lineno) | |
68 | ||
69 | char *string; /* typically "8va" */ | |
70 | int place; /* PL_ABOVE or PL_BELOW */ | |
71 | char *fname; /* file name for errors */ | |
72 | int lineno; | |
73 | ||
74 | ||
75 | { | |
76 | int font, size; | |
77 | int octave_value = 0; | |
78 | int code; /* ASCII of character in string */ | |
79 | ||
80 | ||
81 | font = string[0]; | |
82 | size = string[1]; | |
83 | string += 2; | |
84 | code = next_str_char(&string, &font, &size); | |
85 | if (isdigit(code)) { | |
86 | octave_value = code - '0'; | |
87 | code = next_str_char(&string, &font, &size); | |
88 | /* might be a second digit. If user is crazy enough to use | |
89 | * an octave number greater than 2 digits, ignore the rest */ | |
90 | if (isdigit(code)) { | |
91 | octave_value = (octave_value * 10) + (code - '0'); | |
92 | } | |
93 | } | |
94 | ||
95 | /* must be either a non-zero multiple of 8, or things like 15, 22, | |
96 | * etc if some musical mathematician adds 7 instead of 8 */ | |
97 | if (octave_value < 8 || ((octave_value - 8) % 7 != 0 && | |
98 | (octave_value - 8) % 8 != 0)) { | |
99 | l_ufatal(fname, lineno, "invalid octave mark string"); | |
100 | } | |
101 | if (octave_value % 8 == 0) { | |
102 | octave_value /= 8; | |
103 | } else { | |
104 | octave_value = 1 + (octave_value - 8) % 7; | |
105 | } | |
106 | ||
107 | return(place == PL_BELOW ? -octave_value : octave_value); | |
108 | } | |
109 | \f | |
110 | ||
111 | /* determine "clocks per metronome tick." It not entirely clear to me | |
112 | * how that is supposed to work, but... if the time signature denominator is | |
113 | * 4, we'll use 24. If 8, use 12, etc. Only go down as far as 3, since that's | |
114 | * not divisible by 2. Really, in fast tempo triple time, the denominator | |
115 | * isn't the beat, but this will do for now. */ | |
116 | ||
117 | int | |
118 | clocks(num) | |
119 | ||
120 | int num; | |
121 | ||
122 | { | |
123 | switch(num) { | |
124 | case 1: | |
125 | return(96); | |
126 | case 2: | |
127 | return(48); | |
128 | case 4: | |
129 | return(24); | |
130 | case 8: | |
131 | return(12); | |
132 | case 16: | |
133 | return(6); | |
134 | default: | |
135 | return(3); | |
136 | } | |
137 | } | |
138 | \f | |
139 | ||
140 | /* given a string, if it contains a word followed by an =, followed by a word, | |
141 | * any of which may be separated by white space, return, via pointers, | |
142 | * a pointer to the beginning of the word, the length of the word, and a pointer | |
143 | * to the first non-white-space character after the =, and return YES. | |
144 | * Otherwise, return NO. A "word" is a sequence of non-white-space chars. */ | |
145 | ||
146 | int | |
147 | getkeyword(string, key_p, leng_p, arg_p_p) | |
148 | ||
149 | char *string; /* check this string */ | |
150 | char **key_p; /* return pointer to keyword via this */ | |
151 | int *leng_p; /* return length of keyword via this */ | |
152 | char **arg_p_p; /* return pointer to argument after = via this */ | |
153 | ||
154 | { | |
155 | char *tok; | |
156 | ||
157 | ||
158 | /* skip leading white space */ | |
159 | for (*key_p = string; **key_p == ' ' || **key_p == '\t'; (*key_p)++) { | |
160 | ; | |
161 | } | |
162 | ||
163 | /* go till hit white space or equals sign */ | |
164 | for (tok = *key_p; *tok != '\0'; tok++) { | |
165 | if (*tok == ' ' || *tok == '\t' || *tok == '=') { | |
166 | break; | |
167 | } | |
168 | } | |
169 | ||
170 | /* fill in length of key */ | |
171 | *leng_p = tok - *key_p; | |
172 | ||
173 | if (*leng_p == 0) { | |
174 | return(NO); | |
175 | } | |
176 | ||
177 | /* find first non-white beyond the = */ | |
178 | for ( ; *tok != '\0'; tok++) { | |
179 | if (*tok == '=') { | |
180 | for (tok++; *tok != '\0'; tok++) { | |
181 | if (*tok != ' ' && *tok != '\t') { | |
182 | *arg_p_p = tok; | |
183 | return(YES); | |
184 | } | |
185 | } | |
186 | } | |
187 | } | |
188 | return(NO); | |
189 | } | |
190 | \f | |
191 | ||
192 | /* given a user-specified key, see if it matches the given command name. Return | |
193 | * YES if it does, NO if it doesn't. User only has to specify the first 3 or | |
194 | * more characters of the command, because that's enough to make it unique, | |
195 | * and saves them from typing longer names. */ | |
196 | ||
197 | int | |
198 | matches(key, leng, cmd) | |
199 | ||
200 | char *key; /* user specified key to be checked */ | |
201 | int leng; /* length of key */ | |
202 | char *cmd; /* check if key matches this command */ | |
203 | ||
204 | { | |
205 | if (leng < 3) { | |
206 | return(NO); | |
207 | } | |
208 | return(strncmp(key, cmd, leng) == 0 ? YES : NO); | |
209 | } | |
210 | \f | |
211 | ||
212 | /* given an ASCII hex digit, return its value 0-15 */ | |
213 | ||
214 | int | |
215 | hexdig(ch) | |
216 | ||
217 | int ch; | |
218 | ||
219 | { | |
220 | if (ch >= '0' && ch <= '9') { | |
221 | return(ch - '0'); | |
222 | } | |
223 | else if (ch >= 'a' && ch <= 'f') { | |
224 | return(ch - 'a' + 10); | |
225 | } | |
226 | else if (ch >= 'A' && ch <= 'F') { | |
227 | return(ch - 'A' + 10); | |
228 | } | |
229 | pfatal("bad hex digit"); | |
230 | /*NOTREACHED*/ | |
231 | return(0); | |
232 | } | |
233 | \f | |
234 | ||
235 | /* given a string, output it to midi file, prefixed by its length. */ | |
236 | /* return number of bytes written */ | |
237 | ||
238 | UINT32B | |
239 | midi_wrstring(mfile, str, internalform) | |
240 | ||
241 | int mfile; /* MIDI file */ | |
242 | char *str; /* string to write to file */ | |
243 | int internalform; /* YES if str is in Mup format, NO if just ASCII, | |
244 | * C-style null-terminated string to be copied */ | |
245 | ||
246 | { | |
247 | char *buff; /* for all-ASCII version of str */ | |
248 | UINT32B bytes; /* number of bytes in length value */ | |
249 | int length; /* of string */ | |
250 | ||
251 | ||
252 | /* get plain ascii version of string. Write out length of | |
253 | * string, then plain string itself */ | |
254 | if (internalform == YES) { | |
255 | buff = ascii_str(str, NO, YES, TM_NONE); | |
256 | length = strlen(buff); | |
257 | bytes = wr_varlength(mfile, (UINT32B) length); | |
258 | bytes += write(mfile, buff, (unsigned) length); | |
259 | } | |
260 | else { | |
261 | length = strlen(str); | |
262 | bytes = wr_varlength(mfile, (UINT32B) length); | |
263 | bytes += write(mfile, str, (unsigned) length); | |
264 | } | |
265 | ||
266 | /* return number of bytes written */ | |
267 | return(bytes); | |
268 | } | |
269 | \f | |
270 | ||
271 | /* given a number, write to MIDI file in MIDI variable length format. | |
272 | * Return number of bytes written. */ | |
273 | ||
274 | UINT32B | |
275 | wr_varlength(mfile, num) | |
276 | ||
277 | UINT32B num; | |
278 | ||
279 | { | |
280 | unsigned char buff[4]; | |
281 | int i; | |
282 | int shift; | |
283 | ||
284 | ||
285 | /* Because only 7 bits of each MIDI byte can be used, | |
286 | * there is only support for numbers up to 28 bits long. */ | |
287 | if ((num & 0xf0000000) != 0) { | |
288 | ufatal("midi value too large"); | |
289 | } | |
290 | ||
291 | /* convert value to the MIDI variable-length number, which | |
292 | * uses the lower 7 bits of each byte as parts of the number, and | |
293 | * the high order bit as a flag to say which is the last byte of | |
294 | * the (potentially) multi-byte number */ | |
295 | for (i = 0, shift = 21; shift >= 7; shift -= 7) { | |
296 | if ( (num >> shift) || (i > 0)) { | |
297 | buff[i++] = 0x80 | ((num >> shift) & 0x7f); | |
298 | } | |
299 | } | |
300 | buff[i] = num & 0x7f; | |
301 | (void) write(mfile, buff, (unsigned) (i + 1)); | |
302 | return (UINT32B) (i+1); | |
303 | } | |
304 | \f | |
305 | ||
306 | /* do key signature. Return number of bytes written */ | |
307 | ||
308 | UINT32B | |
309 | midi_keysig(mfile, sharps, is_minor) | |
310 | ||
311 | int mfile; | |
312 | int sharps; | |
313 | int is_minor; /* YES if minor */ | |
314 | ||
315 | { | |
316 | UINT32B bytes; | |
317 | unsigned char buff[8]; | |
318 | ||
319 | ||
320 | bytes = write_delta(mfile); | |
321 | buff[0] = 0xff; | |
322 | buff[1] = 0x59; | |
323 | buff[2] = 0x02; | |
324 | buff[3] = (char) sharps; | |
325 | buff[4] = (is_minor == YES ? 1 : 0); | |
326 | (void) write(mfile, buff, 5); | |
327 | ||
328 | return(bytes + 5); | |
329 | } | |
330 | \f | |
331 | ||
332 | /* write out the timesig in Score SSV. Return number of bytes written */ | |
333 | ||
334 | UINT32B | |
335 | midi_timesig(mfile) | |
336 | ||
337 | int mfile; | |
338 | { | |
339 | UINT32B bytes; | |
340 | unsigned char buff[8]; | |
341 | ||
342 | ||
343 | /* With additive time signatures, it is possible to get an effective | |
344 | * time signature that won't fit in 7 bits. In that case, we don't | |
345 | * do any time signature, since we can't represent it. */ | |
346 | if (Score.timenum > 127) { | |
347 | return(0); | |
348 | } | |
349 | ||
350 | bytes = write_delta(mfile); | |
351 | buff[0] = 0xff; | |
352 | buff[1] = 0x58; | |
353 | buff[2] = 0x04; | |
354 | buff[3] = (char) Score.timenum; | |
355 | buff[4] = (unsigned char) drmo(Score.timeden); | |
356 | buff[5] = clocks(Score.timeden); | |
357 | buff[6] = 0x8; | |
358 | bytes += write(mfile, buff, 7); | |
359 | return(bytes); | |
360 | } | |
361 | \f | |
362 | ||
363 | /* find group before given group. If none before it in current measure, | |
364 | * back up in main list to find corresponding group list, and use final group | |
365 | * in that list. If no group exists, create one. */ | |
366 | ||
367 | struct GRPSYL * | |
368 | grp_before(gs_p, mll_p, staffno, v) | |
369 | ||
370 | struct GRPSYL *gs_p; /* find group before this one */ | |
371 | struct MAINLL *mll_p; /* the list containing gs_p is attached to main list here */ | |
372 | int staffno; | |
373 | int v; /* voice */ | |
374 | ||
375 | { | |
376 | int found_bar = NO; | |
377 | ||
378 | ||
379 | if (gs_p->prev != (struct GRPSYL *) 0) { | |
380 | /* oh good. There's another group before this one in the | |
381 | * current measure, so just return it */ | |
382 | return(gs_p->prev); | |
383 | } | |
384 | ||
385 | /* have to go back to previous measure, if any. Start searching | |
386 | * backwards in main list. */ | |
387 | for (mll_p = mll_p->prev; mll_p != (struct MAINLL *) 0; | |
388 | mll_p = mll_p->prev) { | |
389 | switch (mll_p->str) { | |
390 | case S_STAFF: | |
391 | if (found_bar == NO) { | |
392 | /* still in current measure */ | |
393 | break; | |
394 | } | |
395 | ||
396 | if (mll_p->u.staff_p->staffno == staffno) { | |
397 | /* we found the previous measure */ | |
398 | if (mll_p->u.staff_p->groups_p[v] | |
399 | != (struct GRPSYL *) 0) { | |
400 | /* find and return last group */ | |
401 | for (gs_p=mll_p->u.staff_p->groups_p[v]; | |
402 | gs_p->next != | |
403 | (struct GRPSYL *) 0; | |
404 | gs_p = gs_p->next) { | |
405 | ; | |
406 | } | |
407 | return(gs_p); | |
408 | } | |
409 | else { | |
410 | /* this voice wasn't present before. | |
411 | * Will have to create a measure */ | |
412 | return(create_meas_space(mll_p)); | |
413 | } | |
414 | } | |
415 | else if (mll_p->u.staff_p->staffno < staffno) { | |
416 | /* corresponding staff does not exist in this | |
417 | * measure. The only time this should happen is | |
418 | * if user changed the number of staffs. | |
419 | * So create staff */ | |
420 | return(create_prev_grp(mll_p, staffno, v)); | |
421 | } | |
422 | break; | |
423 | ||
424 | case S_BAR: | |
425 | found_bar = YES; | |
426 | break; | |
427 | ||
428 | default: | |
429 | /* ignore other things */ | |
430 | break; | |
431 | } | |
432 | } | |
433 | ||
434 | /* Fell off the top of the list. This used to be possible, | |
435 | * and we called create_prev_grp() to create a measure. | |
436 | * But the measure really needs to be created much earlier-- | |
437 | * before makechords() is run--in order for squeezing to work right. | |
438 | * So that's what we do now. So we should never get here. */ | |
439 | pfatal("fell off top of list in grp_before()"); | |
440 | /* NOTREACHED */ | |
441 | return(create_prev_grp(mll_p, staffno, v)); | |
442 | } | |
443 | \f | |
444 | ||
445 | /* create a new STAFF struct and insert in main list, with grpcont of | |
446 | * space and fulltime of the measure. Return pointer to the GRPSYL of | |
447 | * appropriate voice of the STAFF that was created. */ | |
448 | ||
449 | static struct GRPSYL * | |
450 | create_prev_grp(mll_p, staffno, v) | |
451 | ||
452 | struct MAINLL *mll_p; /* insert here */ | |
453 | int staffno; | |
454 | int v; | |
455 | ||
456 | { | |
457 | struct MAINLL *new_p; /* new STAFF */ | |
458 | int i; | |
459 | ||
460 | ||
461 | new_p = newMAINLLstruct(S_STAFF, -1); | |
462 | new_p->u.staff_p->staffno = (short) staffno; | |
463 | insertMAINLL(new_p, mll_p); | |
464 | for (i = 0; i < MAXVOICES; i++) { | |
465 | new_p->u.staff_p->groups_p[i] | |
466 | = create_meas_space(mll_p); | |
467 | } | |
468 | ||
469 | /* if added to beginning of list, have to add bar as well */ | |
470 | if (mll_p == (struct MAINLL *) 0) { | |
471 | struct MAINLL *mbar_p; | |
472 | ||
473 | mbar_p = newMAINLLstruct(S_BAR, -1); | |
474 | insertMAINLL(mbar_p, new_p); | |
475 | } | |
476 | ||
477 | return(new_p->u.staff_p->groups_p[v]); | |
478 | } | |
479 | \f | |
480 | ||
481 | /* create a measure space as long as that of the reference measure (or of 4/4 | |
482 | * if no reference) and return it */ | |
483 | ||
484 | static struct GRPSYL * | |
485 | create_meas_space(mll_p) | |
486 | ||
487 | struct MAINLL *mll_p; /* use this for reference to get measure length */ | |
488 | ||
489 | { | |
490 | struct GRPSYL *gs_p; /* new grpsyl */ | |
491 | struct GRPSYL *egs_p; /* existing grpsyl */ | |
492 | ||
493 | ||
494 | gs_p = newGRPSYL(GS_GROUP); | |
495 | gs_p->grpcont = GC_SPACE; | |
496 | ||
497 | /* figure out how much full time to give the group. If mll_p is not | |
498 | * null, we are adding a staff to an existing measure, so use | |
499 | * length of its first voice. Count up the length of existing measure */ | |
500 | gs_p->fulltime = Zero; | |
501 | if (mll_p != (struct MAINLL *) 0 && mll_p->str == S_STAFF) { | |
502 | for (egs_p = mll_p->u.staff_p->groups_p[0]; | |
503 | egs_p != (struct GRPSYL *) 0; | |
504 | egs_p = egs_p->next) { | |
505 | ||
506 | gs_p->fulltime = radd(gs_p->fulltime, egs_p->fulltime); | |
507 | } | |
508 | } | |
509 | else { | |
510 | /* at beginning of list, use default of 1/1 (the reduced | |
511 | * form of 4/4) */ | |
512 | gs_p->fulltime.n = gs_p->fulltime.d = 1; | |
513 | } | |
514 | ||
515 | return(gs_p); | |
516 | } | |
517 | \f | |
518 | ||
519 | /* add a rest of the specified fulltime duration after the specified group. | |
520 | * Since this is just for midi purposes, don't worry about filling in all | |
521 | * the fields. */ | |
522 | ||
523 | void | |
524 | add_rest(gs_p, fulltime) | |
525 | ||
526 | struct GRPSYL *gs_p; /* add rest after this group */ | |
527 | RATIONAL fulltime; /* make it this long */ | |
528 | ||
529 | { | |
530 | struct GRPSYL *newgs_p; | |
531 | ||
532 | ||
533 | if (gs_p == (struct GRPSYL *) 0) { | |
534 | pfatal("null group passed to add_rest"); | |
535 | } | |
536 | ||
537 | newgs_p = newGRPSYL(GS_GROUP); | |
538 | newgs_p->grpcont = GC_REST; | |
539 | rred (&fulltime); | |
540 | newgs_p->fulltime = fulltime; | |
541 | newgs_p->next = gs_p->next; | |
542 | newgs_p->prev = gs_p; | |
543 | gs_p->next = newgs_p; | |
544 | if (newgs_p->next != (struct GRPSYL *) 0) { | |
545 | newgs_p->next->prev = newgs_p; | |
546 | } | |
547 | } | |
548 | \f | |
549 | ||
550 | /* when all voices have space, that should be squeezed to zero time. | |
551 | * Go through main list. For each CHHEAD found, | |
552 | * go down the list of chords. For each chord, see if | |
553 | * if it is an all-space chord. If so, call fix_spacechord() to | |
554 | * handle it. | |
555 | */ | |
556 | ||
557 | void | |
558 | midi_squeeze() | |
559 | ||
560 | { | |
561 | struct MAINLL *mll_p; /* walk through main list */ | |
562 | struct CHORD *ch_p; /* walk through list of chords */ | |
563 | ||
564 | ||
565 | debug(256, "midi_squeeze"); | |
566 | ||
567 | initstructs(); | |
568 | for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0; | |
569 | mll_p = mll_p->next) { | |
570 | ||
571 | /* skip everything except CHHEADs and SSV updates */ | |
572 | if (mll_p->str != S_CHHEAD) { | |
573 | if (mll_p->str == S_SSV) { | |
574 | asgnssv(mll_p->u.ssv_p); | |
575 | } | |
576 | continue; | |
577 | } | |
578 | ||
579 | /* do each chord */ | |
580 | for (ch_p = mll_p->u.chhead_p->ch_p; | |
581 | ch_p != (struct CHORD *) 0; | |
582 | ch_p = ch_p->ch_p) { | |
583 | ||
584 | if (ch_p->width == 0.0) { | |
585 | /* found one to squeeze, do it */ | |
586 | fix_spacechord(mll_p, ch_p); | |
587 | } | |
588 | } | |
589 | } | |
590 | } | |
591 | \f | |
592 | ||
593 | /* given an all-space chord to crunch, split up any groups that | |
594 | * spill into this chord or extend beyond it. Then set the grpvalue of each | |
595 | * group in the chord to GV_ZERO. | |
596 | */ | |
597 | ||
598 | static void | |
599 | fix_spacechord(chmll_p, ch_p) | |
600 | ||
601 | struct MAINLL *chmll_p; /* chord is hanging off this CHHEAD */ | |
602 | struct CHORD *ch_p; /* zero-width chord */ | |
603 | ||
604 | { | |
605 | struct MAINLL *mll_p; /* walk through STAFFs in main list */ | |
606 | struct GRPSYL *gs_p; /* walk through groups in chord */ | |
607 | struct GRPSYL *group_p; /* head of list of grpsyls in measure */ | |
608 | RATIONAL minspacetime; /* time of shortest space in chord */ | |
609 | RATIONAL chordstart; /* where in measure chord begins */ | |
610 | RATIONAL chordend; /* where the space ends */ | |
611 | RATIONAL new_chordend; /* tentative new value for chordend */ | |
612 | RATIONAL grpstart; /* where in measure grpsyl begins */ | |
613 | int v; /* voice index */ | |
614 | ||
615 | ||
616 | /* first find the smallest duration in the chord. Can't use | |
617 | * ch_p->duration here because grace notes have been adjusted | |
618 | * by now to take some time */ | |
619 | minspacetime = ch_p->gs_p->fulltime; | |
620 | for (gs_p = ch_p->gs_p->gs_p; gs_p != (struct GRPSYL *) 0; | |
621 | gs_p = gs_p->gs_p) { | |
622 | ||
623 | /* skip lyrics */ | |
624 | if (gs_p->grpsyl == GS_SYLLABLE) { | |
625 | continue; | |
626 | } | |
627 | ||
628 | /* skip things on tab staff--we use the associated tabnotes | |
629 | * staff instead */ | |
630 | if (is_tab_staff(gs_p->staffno) == YES) { | |
631 | continue; | |
632 | } | |
633 | ||
634 | /* double check */ | |
635 | if (gs_p->grpcont != GC_SPACE) { | |
636 | pfatal("non-space in zero-width chord"); | |
637 | } | |
638 | ||
639 | /* find minimum time value of space */ | |
640 | if (LT(gs_p->fulltime, minspacetime)) { | |
641 | minspacetime = gs_p->fulltime; | |
642 | } | |
643 | } | |
644 | ||
645 | /* find the start of the chord. Can't use ch_p->startime because | |
646 | * we may have squeezed out time earlier in the measure and need | |
647 | * to compensate for that. So have to count up the time before | |
648 | * the group at the top of the chord. */ | |
649 | for (chordstart = Zero, gs_p = ch_p->gs_p->prev; | |
650 | gs_p != (struct GRPSYL *) 0; | |
651 | gs_p = gs_p->prev) { | |
652 | chordstart = radd(chordstart, gs_p->fulltime); | |
653 | } | |
654 | ||
655 | /* if spaces are overlapped in strange ways between different | |
656 | * voices, the minspacetime we found above may actually be too long. | |
657 | * If the time between this chord and the next is less than the | |
658 | * minspacetime found so far, make minspacetime the time till the | |
659 | * next chord */ | |
660 | if (ch_p->ch_p != (struct CHORD *) 0) { | |
661 | if (LT(rsub(ch_p->ch_p->starttime, chordstart), minspacetime)) { | |
662 | minspacetime = rsub(ch_p->ch_p->starttime, chordstart); | |
663 | } | |
664 | } | |
665 | ||
666 | /* That still isn't completely adequate to find where the space actually | |
667 | * ends, because if there were lots of grace notes moved back into a | |
668 | * space, and a very short space in another voice, they could overlap. | |
669 | * So go through the list of voices, seeing where the real end is. | |
670 | * This code is unfortunately very similar to the code below it, | |
671 | * yet different enough to make it hard to make it | |
672 | * into a common function. */ | |
673 | chordend = radd(chordstart, minspacetime); | |
674 | for (mll_p = chmll_p->next; mll_p != (struct MAINLL *) 0; | |
675 | mll_p = mll_p->next) { | |
676 | ||
677 | /* CHHEAD is followed immediately by STAFFS, so when we | |
678 | * hit something other than STAFF, we are done */ | |
679 | if (mll_p->str != S_STAFF) { | |
680 | break; | |
681 | } | |
682 | ||
683 | /* do each voice */ | |
684 | for (v = 0; v < MAXVOICES; v++ ) { | |
685 | /* Check if we have a special case where the actual | |
686 | * space is shorter than we thought. We unfortunately | |
687 | * cannot use hasspace() here, because it ignores grace | |
688 | * notes, and by now, grace notes have some time. | |
689 | * Find the chord that begins the space in question. */ | |
690 | grpstart = Zero; | |
691 | ||
692 | if ((gs_p = mll_p->u.staff_p->groups_p[v]) | |
693 | == (struct GRPSYL *) 0) { | |
694 | /* no voice here, so that's all space. | |
695 | * That's good: we're done with this voice */ | |
696 | continue; | |
697 | } | |
698 | ||
699 | /* grace notes at the beginning of the measure | |
700 | * have effectively been moved timewise | |
701 | * into previous measure, so discount them. */ | |
702 | for ( ; gs_p->grpvalue == GV_ZERO | |
703 | && gs_p->grpcont == GC_NOTES; | |
704 | gs_p = gs_p->next) { | |
705 | ; | |
706 | } | |
707 | ||
708 | for ( ; gs_p != (struct GRPSYL *) 0; | |
709 | gs_p = gs_p->next) { | |
710 | ||
711 | /* see if this group start corresponds | |
712 | * with start of chord, or spills into | |
713 | * the chord or is the last chord. If | |
714 | * so, that's the one we want. */ | |
715 | if (EQ(grpstart, chordstart) || | |
716 | GT(radd(grpstart, | |
717 | gs_p->fulltime), | |
718 | chordstart) || | |
719 | gs_p->next == | |
720 | (struct GRPSYL *) 0) { | |
721 | /* found appropriate group */ | |
722 | break; | |
723 | } | |
724 | else { | |
725 | /* accummulate time so far */ | |
726 | grpstart = radd(grpstart, gs_p->fulltime); | |
727 | } | |
728 | } | |
729 | ||
730 | if (gs_p == (struct GRPSYL *) 0) { | |
731 | pfatal("failed to find space group"); | |
732 | } | |
733 | ||
734 | if (gs_p->grpcont != GC_SPACE) { | |
735 | /* things overlapped so much after the | |
736 | * grace note adjustments and such | |
737 | * that this isn't really a | |
738 | * crunch-able chord after all. */ | |
739 | return; | |
740 | } | |
741 | ||
742 | /* need to adjust amount of space we | |
743 | * can really crunch. Find where this chord | |
744 | * ends, and add in the time of any immediately | |
745 | * following space groups. */ | |
746 | new_chordend = radd(grpstart, gs_p->fulltime); | |
747 | for (gs_p = gs_p->next; gs_p != (struct GRPSYL *) 0; | |
748 | gs_p = gs_p->next) { | |
749 | ||
750 | if (gs_p->grpcont == GC_SPACE) { | |
751 | new_chordend = radd(new_chordend, | |
752 | gs_p->fulltime); | |
753 | } | |
754 | else { | |
755 | break; | |
756 | } | |
757 | } | |
758 | ||
759 | /* if the newly calculated end is sooner than | |
760 | * what we had before, then adjust accordingly. */ | |
761 | if (LT(new_chordend, chordend)) { | |
762 | chordend = new_chordend; | |
763 | } | |
764 | } | |
765 | } | |
766 | ||
767 | /* recalculate the minspace time after any adjustment */ | |
768 | minspacetime = rsub(chordend, chordstart); | |
769 | ||
770 | ||
771 | /* go down each voice of each staff. | |
772 | * For each, find the space group associated with the chord. | |
773 | * If it has the same starttime as the chord and has minspacetime | |
774 | * duration, it's easy: we just mark it GV_ZERO. Otherwise, if | |
775 | * it starts earlier, we have to split off a group in the front | |
776 | * first, and if it lasts longer than the end of the chord, we | |
777 | * have to split off a group at the end first. | |
778 | */ | |
779 | for (mll_p = chmll_p->next; mll_p != (struct MAINLL *) 0; | |
780 | mll_p = mll_p->next) { | |
781 | /* CHHEAD is followed immediately by STAFFS, so when we | |
782 | * hit something other than STAFF, we are done */ | |
783 | if (mll_p->str != S_STAFF) { | |
784 | break; | |
785 | } | |
786 | ||
787 | /* do each voice */ | |
788 | for (v = 0; v < MAXVOICES; v++ ) { | |
789 | ||
790 | /* get shorter name for list of grpsyls */ | |
791 | group_p = mll_p->u.staff_p->groups_p[v]; | |
792 | ||
793 | if (group_p == (struct GRPSYL *) 0) { | |
794 | continue; | |
795 | } | |
796 | ||
797 | /* go through groups, add up time till we find the | |
798 | * group we're looking for */ | |
799 | grpstart = Zero; | |
800 | ||
801 | /* grace notes at the beginning of the measure | |
802 | * have effectively been moved timewise | |
803 | * into previous measure, so discount them. */ | |
804 | for (gs_p = group_p; gs_p->grpvalue == GV_ZERO | |
805 | && gs_p->grpcont == GC_NOTES; | |
806 | gs_p = gs_p->next) { | |
807 | ; | |
808 | } | |
809 | ||
810 | for ( ; gs_p != (struct GRPSYL *) 0; | |
811 | gs_p = gs_p->next) { | |
812 | ||
813 | /* see if this group start corresponds with | |
814 | * start of chord */ | |
815 | if (EQ(grpstart, chordstart)) { | |
816 | /* found appropriate group */ | |
817 | break; | |
818 | } | |
819 | ||
820 | else if (GT(radd(grpstart,gs_p->fulltime), | |
821 | chordstart)) { | |
822 | /* This group spills into space | |
823 | * to be crunched. | |
824 | * Split off beginning of group. */ | |
825 | splitspace(gs_p, | |
826 | rsub(chordstart, grpstart)); | |
827 | ||
828 | /* point to added group */ | |
829 | gs_p = gs_p->next; | |
830 | ||
831 | /* splice added group into chord */ | |
832 | splicechord(gs_p, ch_p); | |
833 | ||
834 | /* found appropriate group */ | |
835 | break; | |
836 | } | |
837 | else { | |
838 | /* haven't gotten to the group yet. | |
839 | * Add on the time taken by this | |
840 | * group in preparation for next | |
841 | * trip around the loop */ | |
842 | grpstart = radd(grpstart, gs_p->fulltime); | |
843 | /* if last group in measure, this has | |
844 | * to be the appropriate one */ | |
845 | if (gs_p->next == (struct GRPSYL *) 0) { | |
846 | break; | |
847 | } | |
848 | } | |
849 | } | |
850 | ||
851 | if (gs_p == (struct GRPSYL *) 0) { | |
852 | pfatal("failed to find space group"); | |
853 | } | |
854 | ||
855 | /* if group extended beyond end of | |
856 | * chord, split the group and splice added group | |
857 | * into chord */ | |
858 | if (GT(gs_p->fulltime, minspacetime)) { | |
859 | splitspace(gs_p, minspacetime); | |
860 | splicechord(gs_p->next, ch_p->ch_p); | |
861 | } | |
862 | ||
863 | /* mark as taking no time */ | |
864 | gs_p->grpvalue = GV_ZERO; | |
865 | } | |
866 | } | |
867 | } | |
868 | \f | |
869 | ||
870 | /* split a space grpsyl into two. The original group becomes the first | |
871 | * group, having the specified duration. A new group is added after it, | |
872 | * having the remainder of the time taken by the original group. */ | |
873 | ||
874 | static void | |
875 | splitspace(gs_p, duration) | |
876 | ||
877 | struct GRPSYL *gs_p; /* split this group */ | |
878 | RATIONAL duration; /* make the first group of split this long */ | |
879 | ||
880 | { | |
881 | struct GRPSYL *newgs_p; /* added group */ | |
882 | ||
883 | ||
884 | /* bug insurance */ | |
885 | if (gs_p == (struct GRPSYL *) 0 || | |
886 | (gs_p->grpcont != GC_SPACE && | |
887 | svpath(gs_p->staffno, VISIBLE)->visible == YES) ) { | |
888 | pfatal("bad group passed to splitspace"); | |
889 | } | |
890 | ||
891 | /* split into 2 groups, one taking duration, and the | |
892 | * other taking the remainder */ | |
893 | newgs_p = newGRPSYL(GS_GROUP); | |
894 | copy_attributes(newgs_p, gs_p); | |
895 | newgs_p->grpcont = GC_SPACE; | |
896 | newgs_p->fulltime = rsub(gs_p->fulltime, duration); | |
897 | gs_p->fulltime = duration; | |
898 | ||
899 | /* link new one into list */ | |
900 | newgs_p->next = gs_p->next; | |
901 | newgs_p->prev = gs_p; | |
902 | gs_p->next = newgs_p; | |
903 | if (newgs_p->next != (struct GRPSYL *) 0) { | |
904 | newgs_p->next->prev = newgs_p; | |
905 | } | |
906 | } | |
907 | \f | |
908 | ||
909 | /* splice a grpsyl into a chord */ | |
910 | ||
911 | static void | |
912 | splicechord(gs_p, ch_p) | |
913 | ||
914 | struct GRPSYL *gs_p; /* splice in this group */ | |
915 | struct CHORD *ch_p; /* splice into this chord */ | |
916 | ||
917 | { | |
918 | struct GRPSYL *nxtgs_p; /* next group in chord list */ | |
919 | struct GRPSYL **ins_p_p; /* where to insert new grpsyl */ | |
920 | ||
921 | ||
922 | if (ch_p == (struct CHORD *) 0) { | |
923 | /* this could happen if user gave measure of space, and | |
924 | * then following measure started with a grace note. The | |
925 | * grace note got moved into the space, but there was no | |
926 | * chhead created for it. It should be safe to just | |
927 | * not link it into a chhead, so return */ | |
928 | return; | |
929 | } | |
930 | ||
931 | if (gs_p == (struct GRPSYL *) 0) { | |
932 | pfatal("null pointer in splicechord"); | |
933 | } | |
934 | ||
935 | /* Figure out where to insert. */ | |
936 | for (ins_p_p = &(ch_p->gs_p); (*ins_p_p) != (struct GRPSYL *) 0; | |
937 | ins_p_p = &((*ins_p_p)->gs_p)) { | |
938 | ||
939 | /* gets inserted here if next group is for a higher staffno or | |
940 | * for a higher voice number of the same staffno */ | |
941 | nxtgs_p = *ins_p_p; | |
942 | if (nxtgs_p == (struct GRPSYL *) 0) { | |
943 | /* goes at end of list */ | |
944 | break; | |
945 | } | |
946 | if (nxtgs_p->staffno > gs_p->staffno || | |
947 | (nxtgs_p->staffno == gs_p->staffno && | |
948 | nxtgs_p->vno > gs_p->vno)) { | |
949 | break; | |
950 | } | |
951 | } | |
952 | ||
953 | if (ins_p_p == (struct GRPSYL **) 0) { | |
954 | pfatal("couldn't find where to insert new grpsyl into chord"); | |
955 | } | |
956 | ||
957 | /* insert it */ | |
958 | gs_p->gs_p = *ins_p_p; | |
959 | *ins_p_p = gs_p; | |
960 | } | |
961 | \f | |
962 | ||
963 | /* if user specifies the default guitar tab staff, then we want to transpose | |
964 | * everything down an octave, because a standard guitar sounds an octave | |
965 | * lower than it is written. */ | |
966 | ||
967 | void | |
968 | guitar_transpose() | |
969 | ||
970 | { | |
971 | struct MAINLL *mll_p; | |
972 | ||
973 | ||
974 | /* go through the main list looking for things to transpose */ | |
975 | initstructs(); | |
976 | for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0; mll_p = mll_p->next) { | |
977 | if (mll_p->str == S_STAFF) { | |
978 | /* if there is a staff below this and that staff is a | |
979 | * guitar tab staff, then we need to transpose. | |
980 | * Index into Staff by this staff's number, because | |
981 | * staff numbers start at 1, but Staff index starts at 0 | |
982 | */ | |
983 | if (mll_p->u.staff_p->staffno < Score.staffs && | |
984 | Staff[mll_p->u.staff_p->staffno] | |
985 | .strinfo == Guitar) { | |
986 | guitar_grpsyl_transpose(mll_p->u.staff_p->groups_p[0]); | |
987 | } | |
988 | } | |
989 | else if (mll_p->str == S_SSV) { | |
990 | asgnssv(mll_p->u.ssv_p); | |
991 | } | |
992 | } | |
993 | } | |
994 | \f | |
995 | ||
996 | /* given a group, transpose everything down by an octave */ | |
997 | ||
998 | static void | |
999 | guitar_grpsyl_transpose(gs_p) | |
1000 | ||
1001 | struct GRPSYL *gs_p; | |
1002 | ||
1003 | { | |
1004 | register int n; | |
1005 | ||
1006 | for( ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) { | |
1007 | for (n = 0; n < gs_p->nnotes; n++) { | |
1008 | if (gs_p->notelist[n].octave > 0) { | |
1009 | (gs_p->notelist[n].octave)--; | |
1010 | } | |
1011 | else { | |
1012 | pfatal("guitar transposition results in note below octave 0"); | |
1013 | } | |
1014 | } | |
1015 | } | |
1016 | } | |
1017 | \f | |
1018 | ||
1019 | /* If there is an accidental on a note on one voice, it should really apply | |
1020 | * the other voice on that same staff too. So propogate these accidentals | |
1021 | * to the other voice if necessary. | |
1022 | */ | |
1023 | ||
1024 | void | |
1025 | other_voice_accidentals(staff_p) | |
1026 | ||
1027 | struct STAFF *staff_p; | |
1028 | ||
1029 | { | |
1030 | struct GRPSYL *gs_p; | |
1031 | int v; /* voice */ | |
1032 | int n; /* notelist index */ | |
1033 | RATIONAL begin_time, end_time; | |
1034 | ||
1035 | /* if there is only one voice on the staff, or if either | |
1036 | * voice is a measure space or rest or multirest, nothing to do. Since | |
1037 | * we're doing MIDI, we know a "measure" GRPSYL | |
1038 | * will be rest or space, not mrpt, so can just check that. */ | |
1039 | if ( (staff_p->groups_p[0]->is_meas == YES) || | |
1040 | (staff_p->groups_p[1] == (struct GRPSYL *) 0) || | |
1041 | (staff_p->groups_p[1]->is_meas == YES) ) { | |
1042 | return; | |
1043 | } | |
1044 | ||
1045 | /* do each voice */ | |
1046 | for (v = 0; v < MAXVOICES; v++) { | |
1047 | ||
1048 | /* do each note of each chord */ | |
1049 | begin_time = Zero; | |
1050 | for (gs_p = staff_p->groups_p[v]; gs_p != (struct GRPSYL *) 0; | |
1051 | gs_p = gs_p->next) { | |
1052 | ||
1053 | for (n = 0; n < gs_p->nnotes; n++) { | |
1054 | ||
1055 | /* if this note doesn't have an accidental | |
1056 | * nothing more to do on it */ | |
1057 | if (gs_p->notelist[n].accidental == '\0') { | |
1058 | continue; | |
1059 | } | |
1060 | ||
1061 | /* This note does have an accidental. | |
1062 | * Go forward and see how long it lasts. | |
1063 | * It will last until there is another | |
1064 | * accidental on the same note letter/octave | |
1065 | * or until end of measure. | |
1066 | */ | |
1067 | end_time = find_acc_end_time(begin_time, gs_p, n); | |
1068 | ||
1069 | /* now check the other voice. | |
1070 | * If the same letter/octave note appears | |
1071 | * on that voice on or after the begin time but | |
1072 | * before the end time, and that note | |
1073 | * does not already have an accidental, | |
1074 | * give it the same accidental as | |
1075 | * was found on the other voice. | |
1076 | */ | |
1077 | propogate_accidental( &(gs_p->notelist[n]), | |
1078 | begin_time, end_time, | |
1079 | staff_p->groups_p[v == 0 ? 1 : 0]); | |
1080 | } | |
1081 | ||
1082 | /* accumulate time so far in measure */ | |
1083 | begin_time = radd(begin_time, gs_p->fulltime); | |
1084 | } | |
1085 | } | |
1086 | } | |
1087 | ||
1088 | /* Given an GRPSYL and a note n in its notelist, and a begin_time, return | |
1089 | * the end_time which is either the end of the measure or the next instance | |
1090 | * of the given note which has an accidental on it. */ | |
1091 | ||
1092 | static RATIONAL | |
1093 | find_acc_end_time(begin_time, gs_p, n) | |
1094 | ||
1095 | RATIONAL begin_time; | |
1096 | struct GRPSYL *gs_p; | |
1097 | int n; | |
1098 | ||
1099 | { | |
1100 | RATIONAL end_time; | |
1101 | struct GRPSYL *end_gs_p; | |
1102 | int n2; | |
1103 | ||
1104 | ||
1105 | end_time = begin_time; | |
1106 | end_gs_p = gs_p; | |
1107 | for ( ; ; ) { | |
1108 | /* Add up time that accidental lasts */ | |
1109 | end_time = radd(end_time, end_gs_p->fulltime); | |
1110 | ||
1111 | if ((end_gs_p = end_gs_p->next) == (struct GRPSYL *) 0) { | |
1112 | /* Hit end of measure */ | |
1113 | return(end_time); | |
1114 | } | |
1115 | ||
1116 | /* See if this group has the same note as had the accidental, | |
1117 | * and if so, whether it has a new accidental. */ | |
1118 | for (n2 = 0; n2 < end_gs_p->nnotes; n2++) { | |
1119 | if ((gs_p->notelist[n].letter | |
1120 | == end_gs_p->notelist[n2].letter) && | |
1121 | (gs_p->notelist[n].octave | |
1122 | == end_gs_p->notelist[n2].octave)) { | |
1123 | ||
1124 | /* does have the same note. check accidental */ | |
1125 | if (end_gs_p->notelist[n2].accidental != '\0') { | |
1126 | /* a new accidental, so this cancels | |
1127 | * the one we had */ | |
1128 | return(end_time); | |
1129 | } | |
1130 | break; | |
1131 | } | |
1132 | } | |
1133 | } | |
1134 | } | |
1135 | \f | |
1136 | ||
1137 | /* Check the groups in list pointed to by gs_p. | |
1138 | * If the letter/octave of the given note_p appears on or after the begin time | |
1139 | * but before the end time, and that note does not already have an accidental, | |
1140 | * give it the same accidental as was found on note_p. */ | |
1141 | ||
1142 | static void | |
1143 | propogate_accidental(note_p, begin_time, end_time, gs_p) | |
1144 | ||
1145 | struct NOTE *note_p; /* look for note matching this one */ | |
1146 | RATIONAL begin_time; /* look between the begin_time and end_time */ | |
1147 | RATIONAL end_time; | |
1148 | struct GRPSYL *gs_p; /* look in this list and adjust if needed */ | |
1149 | ||
1150 | { | |
1151 | RATIONAL accumulated_time; | |
1152 | int n; | |
1153 | ||
1154 | ||
1155 | for (accumulated_time = Zero; | |
1156 | gs_p != (struct GRPSYL *) 0; | |
1157 | accumulated_time = radd(accumulated_time, | |
1158 | gs_p->fulltime), gs_p = gs_p->next) { | |
1159 | ||
1160 | if (LT(accumulated_time, begin_time)) { | |
1161 | /* haven't gotten to begin yet */ | |
1162 | continue; | |
1163 | } | |
1164 | ||
1165 | if (GE(accumulated_time, end_time)) { | |
1166 | /* reached end time */ | |
1167 | return; | |
1168 | } | |
1169 | ||
1170 | /* See if this group contains the note of interest */ | |
1171 | for (n = 0; n < gs_p->nnotes; n++) { | |
1172 | if ( (gs_p->notelist[n].letter == note_p->letter) && | |
1173 | (gs_p->notelist[n].octave == note_p->octave) ) { | |
1174 | /* if note already has an accidental, | |
1175 | * the one from the other voice doesn't | |
1176 | * count. Otherwise propogate the | |
1177 | * accidental from the other voice */ | |
1178 | if (gs_p->notelist[n].accidental == '\0') { | |
1179 | gs_p->notelist[n].accidental | |
1180 | = note_p->accidental; | |
1181 | } | |
1182 | ||
1183 | /* Found the note and fixed it if needed, | |
1184 | * so our job here is done */ | |
1185 | return; | |
1186 | } | |
1187 | } | |
1188 | } | |
1189 | } | |
1190 | \f | |
1191 | ||
1192 | /* If doing MIDI with the -x option, we move all the midi STUFFs in the | |
1193 | * skipped leading measures to the "extra" empty measure that exists for MIDI. | |
1194 | * This ensure that any MIDI parameters, instruments, etc are correct | |
1195 | * for the place in the song where we are actually starting. | |
1196 | */ | |
1197 | ||
1198 | void | |
1199 | mv_midi_items(mll_p, topstaff_mll_p) | |
1200 | ||
1201 | struct MAINLL *mll_p; /* points to a STAFF that may have MIDI items to move */ | |
1202 | struct MAINLL *topstaff_mll_p; /* points to STAFF where "all" MIDI items will go */ | |
1203 | ||
1204 | { | |
1205 | struct STUFF *stuff_p; /* stuff currently being processed */ | |
1206 | struct STUFF *next; /* we may move the current STUFF to another | |
1207 | * list, so need to save its "next" */ | |
1208 | char *key; /* midi directive keyword */ | |
1209 | int leng; /* length of key */ | |
1210 | char *arg; /* arg after the = */ | |
1211 | int staffno; | |
1212 | ||
1213 | ||
1214 | staffno = mll_p->u.staff_p->staffno; | |
1215 | for (stuff_p = mll_p->u.staff_p->stuff_p; stuff_p != 0; stuff_p = next) { | |
1216 | /* keep track of next, in case we delete the current */ | |
1217 | next = stuff_p->next; | |
1218 | ||
1219 | if (next == stuff_p) { | |
1220 | pfatal("loop detected in MIDI list"); | |
1221 | } | |
1222 | ||
1223 | if (stuff_p->stuff_type == ST_MIDI) { | |
1224 | if (getkeyword(stuff_p->string+2, &key, &leng, &arg) | |
1225 | == NO) { | |
1226 | /* invalid, so ignore it. */ | |
1227 | continue; | |
1228 | } | |
1229 | ||
1230 | /* Some MIDI things, like cue point should just be | |
1231 | * ignored if we are skipping over the music, | |
1232 | * so just check for and move things we care about. | |
1233 | */ | |
1234 | if (matches(key, leng, "program") == YES || | |
1235 | matches(key, leng, "tempo") == YES || | |
1236 | matches(key, leng, "onvelocity") == YES || | |
1237 | matches(key, leng, "channel") == YES || | |
1238 | matches(key, leng, "parameter") == YES || | |
1239 | matches(key, leng, "offvelocity") == YES || | |
1240 | matches(key, leng, "name") == YES || | |
1241 | matches(key, leng, "instrument") == YES || | |
1242 | matches(key, leng, "hex") == YES || | |
1243 | matches(key, leng, "port") == YES || | |
1244 | matches(key, leng, "chanpressure") == YES) { | |
1245 | /* Found something to move; move it */ | |
1246 | mv_skipped_midi(stuff_p, staffno, topstaff_mll_p); | |
1247 | } | |
1248 | } | |
1249 | } | |
1250 | } | |
1251 | \f | |
1252 | ||
1253 | /* With -x option and MIDI, this moves a MIDI STUFF from where it was in | |
1254 | * a skipped measure to the special "empty" measure at the beginning of the | |
1255 | * piece. In general, for any given MIDI thing, only the last one matters, | |
1256 | * so we only need to keep the last one. | |
1257 | */ | |
1258 | ||
1259 | static void | |
1260 | mv_skipped_midi(stuff_p, staffno, topstaff_mll_p) | |
1261 | ||
1262 | struct STUFF *stuff_p; /* Midi STUFF to be moved */ | |
1263 | int staffno; /* Which staff it is for */ | |
1264 | struct MAINLL *topstaff_mll_p; /* The STAFF where midi "all" STUFF go. | |
1265 | * Other STAFFs, if any, will surround it. */ | |
1266 | ||
1267 | { | |
1268 | int leng; /* length of MIDI keyword */ | |
1269 | char *oldtext; /* text of STUFF that already | |
1270 | * exists in the list */ | |
1271 | char *newtext; /* text of STUFF to be added */ | |
1272 | struct MAINLL *mll_p; /* for finding STAFF to link to */ | |
1273 | struct STAFF *staff_p = 0; /* the STAFF to link to */ | |
1274 | struct STUFF **stuff_p_p; /* for finding where to add | |
1275 | * the new stuff_p into list */ | |
1276 | static char *alphabet = "abcdefghijklmnopqrstuvwxyz"; | |
1277 | ||
1278 | /* Find the correct STAFF to attach to. We all passed a pointer | |
1279 | * to the STAFF for midi "all" items. For non-"all" items, | |
1280 | * we search in the main list for the correct STAFF. | |
1281 | */ | |
1282 | if (stuff_p->all == YES || staffno == topstaff_mll_p->u.staff_p->staffno) { | |
1283 | staff_p = topstaff_mll_p->u.staff_p; | |
1284 | } | |
1285 | else if (staffno < topstaff_mll_p->u.staff_p->staffno) { | |
1286 | /* Search backward for correct staff from the "all" staff. | |
1287 | * This case probably won't happen often--only if some | |
1288 | * staffs at the top are currently invisible (so they are | |
1289 | * not the current "top visible staff"). | |
1290 | */ | |
1291 | for (mll_p = topstaff_mll_p; mll_p->str == S_STAFF; | |
1292 | mll_p = mll_p->prev) { | |
1293 | if (mll_p->u.staff_p->staffno == staffno) { | |
1294 | staff_p = mll_p->u.staff_p; | |
1295 | break; | |
1296 | } | |
1297 | } | |
1298 | } | |
1299 | else { | |
1300 | /* Search forwards for correct staff from the "all" staff. */ | |
1301 | for (mll_p = topstaff_mll_p; mll_p->str == S_STAFF; | |
1302 | mll_p = mll_p->next) { | |
1303 | if (mll_p->u.staff_p->staffno == staffno) { | |
1304 | staff_p = mll_p->u.staff_p; | |
1305 | break; | |
1306 | } | |
1307 | } | |
1308 | } | |
1309 | if (staff_p == 0) { | |
1310 | /* User must have reduced the number of staffs during the | |
1311 | * skipped part, so this one is irrelevant. */ | |
1312 | return; | |
1313 | } | |
1314 | ||
1315 | /* Add to end of list. When going through the list, | |
1316 | * see if there is already an item of that type (for param | |
1317 | * have to check the specific param matches too), and if so delete | |
1318 | * the earlier one, because this new one overrides it. | |
1319 | */ | |
1320 | newtext = stuff_p->string + 2; | |
1321 | for (stuff_p_p = &(staff_p->stuff_p); *stuff_p_p != 0; | |
1322 | stuff_p_p = &((*stuff_p_p)->next) ) { | |
1323 | ||
1324 | /* If for different place, | |
1325 | * this one doesn't count for matching */ | |
1326 | if ( (*stuff_p_p)->place != stuff_p->place) { | |
1327 | continue; | |
1328 | } | |
1329 | ||
1330 | oldtext = (*stuff_p_p)->string + 2; | |
1331 | ||
1332 | /* Since hex is arbitrary data, we always keep it */ | |
1333 | if (matches(oldtext, strlen(oldtext), "hex")) { | |
1334 | continue; | |
1335 | } | |
1336 | ||
1337 | /* Names can be abbreviated, | |
1338 | * so match up to whichever is shorter */ | |
1339 | leng = MIN(strspn(oldtext, alphabet), strspn(newtext, alphabet)); | |
1340 | if (matches(newtext, leng, oldtext)== YES) { | |
1341 | /* If it's something other than param, we can get | |
1342 | * rid of the existing one */ | |
1343 | if (strncmp(newtext, "par", 3) != 0) { | |
1344 | *stuff_p_p = (*stuff_p_p)->next; | |
1345 | } | |
1346 | else { | |
1347 | /* Compare parameter numbers and if they match, | |
1348 | * delete the existing one. | |
1349 | */ | |
1350 | char *new_eq_p, *old_eq_p; /* loc of '=' */ | |
1351 | int oldparm, oldval; | |
1352 | int newparm, newval; | |
1353 | ||
1354 | new_eq_p = strchr(newtext, '='); | |
1355 | old_eq_p = strchr(oldtext, '='); | |
1356 | if (new_eq_p != 0 && old_eq_p != 0) { | |
1357 | if (get_param(new_eq_p + 1, | |
1358 | stuff_p->inputfile, | |
1359 | stuff_p->inputlineno, | |
1360 | &newparm, &newval) | |
1361 | == YES && | |
1362 | get_param(old_eq_p + 1, | |
1363 | (*stuff_p_p)->inputfile, | |
1364 | (*stuff_p_p)->inputlineno, | |
1365 | &oldparm, &oldval) | |
1366 | == YES && | |
1367 | oldparm == newparm) { | |
1368 | *stuff_p_p = (*stuff_p_p)->next; | |
1369 | } | |
1370 | } | |
1371 | } | |
1372 | ||
1373 | if (*stuff_p_p == 0) { | |
1374 | /* If deleted last item in the existing list, | |
1375 | * jump out, so we won't try to deference | |
1376 | * this null pointer. */ | |
1377 | break; | |
1378 | } | |
1379 | } | |
1380 | } | |
1381 | ||
1382 | /* Just do everything at beat zero. The beat at which user specified | |
1383 | * might not even exist in the current time signature, and basically | |
1384 | * we just want to do everything ASAP anyway. We know there is never | |
1385 | * a 'til' on midi, so no need to deal with that. We could end up | |
1386 | * with a lot to do at count zero, potentially enough to overwhelm | |
1387 | * the limited MIDI bandwidth and delay the first actual note. | |
1388 | * But that potential is always there, and by discarding things | |
1389 | * that were overwritten later, which we did above, unless there | |
1390 | * are an awfully lot of parameters on every possible channel, | |
1391 | * it's probably only going to take less than 0.1 second, | |
1392 | * so it doesn't seem worth the bother to try to do something | |
1393 | * fancy to calculate how much time we need for this stuff | |
1394 | * and delay the actual music by that much. */ | |
1395 | stuff_p->start.count = 0.0; | |
1396 | stuff_p->start.steps = 0.0; | |
1397 | ||
1398 | /* link onto end of list */ | |
1399 | *stuff_p_p = stuff_p; | |
1400 | stuff_p->next = 0; | |
1401 | } | |
1402 | \f | |
1403 | ||
1404 | /* Given the argument to a MIDI "parameter" command, extract and return | |
1405 | * (via pointers) the two numbers (the parameter number and its value). | |
1406 | * If successful, returns YES, else prints a warning and returns NO. | |
1407 | * If NO is returned, the pointed to return values are not fill in. | |
1408 | */ | |
1409 | ||
1410 | int | |
1411 | get_param(arg, inputfile, inputlineno, parmnum_p, parmval_p) | |
1412 | ||
1413 | char *arg; /* the argument part after "parameter=" */ | |
1414 | char *inputfile; /* for error messages */ | |
1415 | int inputlineno; /* for error messages */ | |
1416 | int *parmnum_p; /* parameter number is returned here */ | |
1417 | int *parmval_p; /* parameter value is returned here */ | |
1418 | ||
1419 | { | |
1420 | int parmnum; /* parameter number */ | |
1421 | int parmval; /* parameter value */ | |
1422 | char *parm_p; /* pointer to current place in string */ | |
1423 | ||
1424 | ||
1425 | /* extract first number */ | |
1426 | parmnum = strtol(arg, &parm_p, 10); | |
1427 | if (parm_p == arg) { | |
1428 | l_warning(inputfile, inputlineno, | |
1429 | "parameter requires two values"); | |
1430 | return(NO); | |
1431 | } | |
1432 | /* skip white space, if any */ | |
1433 | while (*parm_p == ' ' || *parm_p == '\t') { | |
1434 | parm_p++; | |
1435 | } | |
1436 | /* next we better have a comma */ | |
1437 | if (*parm_p != ','){ | |
1438 | l_warning(inputfile, inputlineno, | |
1439 | "parameter is missing required comma"); | |
1440 | return(NO); | |
1441 | } | |
1442 | /* extract the second number */ | |
1443 | arg = parm_p + 1; | |
1444 | parmval = strtol(arg, &parm_p, 10); | |
1445 | if (parm_p == arg) { | |
1446 | l_warning(inputfile, inputlineno, | |
1447 | "parameter is missing second value"); | |
1448 | return(NO); | |
1449 | } | |
1450 | /* verify both numbers are within range */ | |
1451 | if ((l_rangecheck(parmnum, 0, 127, "parameter number", | |
1452 | inputfile, inputlineno) == YES) && | |
1453 | (l_rangecheck(parmval, 0, 127, "parameter value", | |
1454 | inputfile, inputlineno) == YES)) { | |
1455 | *parmnum_p = parmnum; | |
1456 | *parmval_p = parmval; | |
1457 | return(YES); | |
1458 | } | |
1459 | return(NO); | |
1460 | } |