| 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 | } |