| 1 | /* Copyright (c) 1995, 1996, 1997, 1998, 2002, 2003, 2004, 2006 |
| 2 | * by Arkkra Enterprises */ |
| 3 | /* All rights reserved */ |
| 4 | /* |
| 5 | * Name: mkchords.c |
| 6 | * |
| 7 | * Description: This file contains functions for creating CHORD linked lists |
| 8 | * and erasing invisible voices. |
| 9 | */ |
| 10 | |
| 11 | #include "defines.h" |
| 12 | #include "structs.h" |
| 13 | #include "globals.h" |
| 14 | |
| 15 | |
| 16 | static void swingmidi P((void)); |
| 17 | static struct GRPSYL *voicevis P((struct GRPSYL *gs_p)); |
| 18 | static void combine_voices P((void)); |
| 19 | static void chkhand1 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p)); |
| 20 | static int chk2groups P((struct GRPSYL *hi_p, struct GRPSYL *lo_p, |
| 21 | struct MAINLL *mll_p, int qual)); |
| 22 | static void chkhand2 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p)); |
| 23 | static int chk2neighbors P((struct GRPSYL *first_p, struct GRPSYL *second_p, |
| 24 | struct GRPSYL *gs1_p, struct MAINLL *mll_p)); |
| 25 | static void dohand P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p)); |
| 26 | static void comb2groups P((struct GRPSYL *dest_p, struct GRPSYL *src_p, |
| 27 | struct MAINLL *mll_p)); |
| 28 | static void addsrc2dest P((struct GRPSYL *dest_p, struct GRPSYL *src_p)); |
| 29 | static int setgrpptrs P((struct GRPSYL *gs1_p, struct GRPSYL *v_p[])); |
| 30 | static int hastieslur P((struct GRPSYL *gs_p)); |
| 31 | \f |
| 32 | /* |
| 33 | * Name: makechords() |
| 34 | * |
| 35 | * Abstract: Set up the linked lists of chords. |
| 36 | * |
| 37 | * Returns: void |
| 38 | * |
| 39 | * Description: This function scans through the main linked list looking |
| 40 | * for STAFF structures. It joins the GRPSYL structures in |
| 41 | * the lists that they head, into perpendicular linked lists, |
| 42 | * allocating a CHORD to head each of these. It also links |
| 43 | * the CHORDs for each measure together into a linked list. |
| 44 | * |
| 45 | * While doing the above, it also calls voicevis() to check if a |
| 46 | * voice should be invisible, and if so changes it to a measure |
| 47 | * space. It also applies the swingunit and voicecombine |
| 48 | * parameters. |
| 49 | */ |
| 50 | |
| 51 | |
| 52 | void |
| 53 | makechords() |
| 54 | |
| 55 | { |
| 56 | struct MAINLL *mainll_p; /* point at item in main linked list */ |
| 57 | struct MAINLL *mainch_p; /* for headcell of a chord list */ |
| 58 | |
| 59 | RATIONAL *vtime; /* cum. time of each voice and verse */ |
| 60 | struct GRPSYL **grpsyl_p; /* pointers along GRPSYL lists */ |
| 61 | struct STAFF *staff_p; /* point at a staff structure */ |
| 62 | |
| 63 | RATIONAL mintime; /* the minimum vtime */ |
| 64 | register int num; /* no. of visible voices/verses */ |
| 65 | register int v; /* index into grpsyl_p[] */ |
| 66 | struct CHORD *ch_p; /* pointer to current chord */ |
| 67 | struct CHORD *och_p; /* pointer to old chord */ |
| 68 | struct GRPSYL *gs_p; /* pointer to current group/syllable */ |
| 69 | int n; /* loop variable */ |
| 70 | int firstgs; /* flag for first group/syllable */ |
| 71 | int quit; /* flag for being done */ |
| 72 | |
| 73 | |
| 74 | debug(16, "makechords"); |
| 75 | /* |
| 76 | * If we are generating MIDI, we may need to change lengths (fulltimes) |
| 77 | * of groups. This has to be done now, before we link groups together |
| 78 | * into chords. |
| 79 | */ |
| 80 | if (Doing_MIDI == YES) { |
| 81 | swingmidi(); |
| 82 | } |
| 83 | |
| 84 | gs_p = 0; /* keep lint happy; will be set before used */ |
| 85 | |
| 86 | /* malloc enough of these for all voices and verses */ |
| 87 | MALLOC(rational, vtime, MAXSTAFFS * (MAXVOICES + Maxverses)); |
| 88 | MALLOC(GRPSYL *, grpsyl_p, MAXSTAFFS * (MAXVOICES + Maxverses)); |
| 89 | |
| 90 | mainll_p = Mainllhc_p; /* point at first thing in main LL */ |
| 91 | |
| 92 | initstructs(); /* clean out old SSV info */ |
| 93 | |
| 94 | /* |
| 95 | * Loop once for each measure in the input. |
| 96 | */ |
| 97 | for (;;) { |
| 98 | num = 0; /* number of linked lists in measure */ |
| 99 | |
| 100 | /* |
| 101 | * Look for the first structure in this measure that points off |
| 102 | * to a linked list of groups/syllables. If we hit the end of |
| 103 | * the main linked list, we're all done, so break out. |
| 104 | */ |
| 105 | while (mainll_p != 0 && mainll_p->str != S_STAFF) { |
| 106 | if (mainll_p->str == S_SSV) |
| 107 | asgnssv(mainll_p->u.ssv_p); |
| 108 | mainll_p = mainll_p->next; |
| 109 | } |
| 110 | |
| 111 | if (mainll_p == 0) { |
| 112 | FREE(vtime); |
| 113 | FREE(grpsyl_p); |
| 114 | break; |
| 115 | } |
| 116 | |
| 117 | /* |
| 118 | * We've found another measure with STAFF in it. Allocate |
| 119 | * a chord headcell for this measure, and put it in the |
| 120 | * main linked list. |
| 121 | */ |
| 122 | mainch_p = newMAINLLstruct(S_CHHEAD, 0); |
| 123 | insertMAINLL(mainch_p, mainll_p->prev); |
| 124 | |
| 125 | /* |
| 126 | * Look for the last STAFF structure in the measure. While |
| 127 | * doing this, point at first element of all the group/syllable |
| 128 | * linked lists, and keep count of them. Ignore invisible |
| 129 | * staffs. Skip over any grace groups. |
| 130 | */ |
| 131 | while (mainll_p != 0 && mainll_p->str == S_STAFF) { |
| 132 | staff_p = mainll_p->u.staff_p; |
| 133 | |
| 134 | if (staff_p->visible == YES) { |
| 135 | |
| 136 | /* do all the voices on this staff */ |
| 137 | for (n = 0; n < MAXVOICES && |
| 138 | staff_p->groups_p[n] != 0; n++) { |
| 139 | /* |
| 140 | * Zap voice if invisible. Set both |
| 141 | * of these to point at the first |
| 142 | * GRPSYL, which will be a new one if |
| 143 | * we zapped it. |
| 144 | */ |
| 145 | grpsyl_p[num] = staff_p->groups_p[n] = |
| 146 | voicevis(staff_p->groups_p[n]); |
| 147 | |
| 148 | /* skip leading grace groups */ |
| 149 | while (grpsyl_p[num] != 0 && |
| 150 | grpsyl_p[num]->grpvalue == GV_ZERO) |
| 151 | grpsyl_p[num] = grpsyl_p[num]->next; |
| 152 | if (grpsyl_p[num] == 0) |
| 153 | pfatal("nothing but grace groups found"); |
| 154 | num++; |
| 155 | } |
| 156 | |
| 157 | /* do all the verses on this staff */ |
| 158 | for (n = 0; n < staff_p->nsyllists; n++) |
| 159 | grpsyl_p[num++] = staff_p->syls_p[n]; |
| 160 | } |
| 161 | mainll_p = mainll_p->next; |
| 162 | } |
| 163 | |
| 164 | /* |
| 165 | * Set up the first chord from the first note in each |
| 166 | * voice/verse. Its linked list of GRPSYLs will include |
| 167 | * the first GRPSYL in every linked list off of a visible |
| 168 | * STAFF. |
| 169 | */ |
| 170 | MALLOC(CHORD, ch_p, 1); |
| 171 | mainch_p->u.chhead_p->ch_p = ch_p; /* point at first chord */ |
| 172 | ch_p->ch_p = 0; /* only member on list so far */ |
| 173 | ch_p->starttime = Zero; /* start time = any voice */ |
| 174 | |
| 175 | /* point headcell at first and set its first group's time */ |
| 176 | ch_p->gs_p = grpsyl_p[0]; |
| 177 | vtime[0] = grpsyl_p[0]->fulltime; |
| 178 | |
| 179 | /* for each remaining one, point prev one at it & set time */ |
| 180 | for (v = 1; v < num; v++) { |
| 181 | grpsyl_p[v-1]->gs_p = grpsyl_p[v]; |
| 182 | vtime[v] = grpsyl_p[v]->fulltime; |
| 183 | } |
| 184 | grpsyl_p[num-1]->gs_p = 0; /* terminate linked list */ |
| 185 | |
| 186 | /* point at second GRPSYL in each voice/verse, if any */ |
| 187 | for (v = 0; v < num; v++) |
| 188 | grpsyl_p[v] = grpsyl_p[v]->next; |
| 189 | |
| 190 | /* |
| 191 | * Loop until groups/syllables in the voices/verses are used |
| 192 | * up. Form a chord for each time at which any voice/verse |
| 193 | * has a GRPSYL structure, though ignore grace groups. |
| 194 | */ |
| 195 | for (;;) { |
| 196 | /* |
| 197 | * If every GRPSYL currently pointed at by a grpsyl_p[] |
| 198 | * is the last in its list (the measure), there are no |
| 199 | * more chords in this measure, and quit will remain |
| 200 | * YES. |
| 201 | */ |
| 202 | quit = YES; /* first assume "quit" */ |
| 203 | for (v = 0; v < num; v++) { |
| 204 | /* find next item (if any) not a grace group */ |
| 205 | while (grpsyl_p[v] != 0 && |
| 206 | grpsyl_p[v]->grpsyl == GS_GROUP && |
| 207 | grpsyl_p[v]->grpvalue == GV_ZERO) { |
| 208 | |
| 209 | grpsyl_p[v] = grpsyl_p[v]->next; |
| 210 | } |
| 211 | |
| 212 | /* check if voice/verse has another item */ |
| 213 | if (grpsyl_p[v] != 0) { |
| 214 | quit = NO; /* yes, so don't quit yet */ |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | /* if time to quit, skip rest of loop, and get out */ |
| 219 | if (quit == YES) |
| 220 | break; |
| 221 | |
| 222 | /* |
| 223 | * At least one voice/verse has another note in it. |
| 224 | * Find the earliest time at which something changes. |
| 225 | */ |
| 226 | mintime = vtime[0]; |
| 227 | for (v = 1; v < num; v++) |
| 228 | if (LT(vtime[v], mintime)) |
| 229 | mintime = vtime[v]; |
| 230 | |
| 231 | /* allocate memory for another chord */ |
| 232 | och_p = ch_p; /* remember where previous chord is */ |
| 233 | MALLOC(CHORD, ch_p, 1); |
| 234 | och_p->ch_p = ch_p; /* point previous chord at it*/ |
| 235 | ch_p->ch_p = 0; /* terminate in case last */ |
| 236 | |
| 237 | ch_p->starttime = mintime; /* starting time for chord*/ |
| 238 | |
| 239 | /* |
| 240 | * Form a new linked list. The head cell is the new |
| 241 | * chord, and the list connects it to all the groups/ |
| 242 | * syllables that start at this time. |
| 243 | */ |
| 244 | firstgs = YES; |
| 245 | for (v = 0; v < num; v++) { |
| 246 | if (EQ(vtime[v], mintime)) { |
| 247 | /* |
| 248 | * This voice/verse has a grpsyl at |
| 249 | * this time. Make the previous one |
| 250 | * point at it, set its pointer to 0 |
| 251 | * in case it turns out to be the last, |
| 252 | * and add its length to vtime[v]. |
| 253 | */ |
| 254 | if (firstgs == YES) { |
| 255 | /* point headcell at first */ |
| 256 | ch_p->gs_p = grpsyl_p[v]; |
| 257 | firstgs = NO; |
| 258 | } else { |
| 259 | /* point previous one at ours*/ |
| 260 | gs_p->gs_p = grpsyl_p[v]; |
| 261 | } |
| 262 | |
| 263 | /* set gs_p to point at our new one */ |
| 264 | gs_p = grpsyl_p[v]; |
| 265 | |
| 266 | vtime[v] = radd(vtime[v], |
| 267 | gs_p->fulltime); |
| 268 | |
| 269 | /* get next GRPSYL in voice/verse */ |
| 270 | grpsyl_p[v] = gs_p->next; |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | gs_p->gs_p = 0; /* terminate linked list */ |
| 275 | } |
| 276 | |
| 277 | /* |
| 278 | * Set the duration of each chord in this measure. It's the |
| 279 | * next chord's start time minus this chord's start time. |
| 280 | * But for the last chord, it's the time signature minus |
| 281 | * this chord's start time. Also set pseudodur, which is a |
| 282 | * function of the duration. The amount of width the chord |
| 283 | * "deserves" to be allocated is proportional to pseudodur. |
| 284 | */ |
| 285 | for (ch_p = mainch_p->u.chhead_p->ch_p; ch_p->ch_p != 0; |
| 286 | ch_p = ch_p->ch_p) { |
| 287 | ch_p->duration = rsub(ch_p->ch_p->starttime, |
| 288 | ch_p->starttime); |
| 289 | ch_p->pseudodur = pow(RAT2FLOAT(ch_p->duration), |
| 290 | Score.packexp); |
| 291 | } |
| 292 | ch_p->duration = rsub(Score.time, ch_p->starttime); |
| 293 | ch_p->pseudodur = pow(RAT2FLOAT(ch_p->duration), Score.packexp); |
| 294 | } |
| 295 | |
| 296 | /* if voicecombine parm was ever set, combine voices if possible */ |
| 297 | if (Vcombused == YES) { |
| 298 | combine_voices(); |
| 299 | } |
| 300 | } |
| 301 | \f |
| 302 | /* |
| 303 | * Name: swingmidi() |
| 304 | * |
| 305 | * Abstract: Alter groups' time to implement the "swingunit" parameter. |
| 306 | * |
| 307 | * Returns: void |
| 308 | * |
| 309 | * Description: This function loops through every GRPSYL in every voice, |
| 310 | * adjusting their fulltime so that they will start and end at |
| 311 | * different times, if necessary, to follow the "swingunit" parm. |
| 312 | * Each measure is divided into durations of "swingunit", starting |
| 313 | * at the beginning. (Usually the timesig divided by swingunit |
| 314 | * will be an integer, but if not, the last piece will be shorter.) |
| 315 | * The time where one group ends and the next group starts will be |
| 316 | * altered in either of these two circumstances: |
| 317 | * 1. The current boundary time is halfway into a swingunit, and |
| 318 | * each group is at least half a swingunit long. |
| 319 | * 2. The current boundary time is 3/4 of the way into a swingunit, |
| 320 | * and the first group is at least 3/4 of a swingunit long, and |
| 321 | * and the second group is at least 1/4 of a swingunit long. |
| 322 | * In both of these cases, the fulltimes are altered so that the |
| 323 | * meeting point is 2/3 of the way into the swingunit. |
| 324 | */ |
| 325 | |
| 326 | void |
| 327 | swingmidi() |
| 328 | { |
| 329 | struct MAINLL *mainll_p; /* point along main linked list */ |
| 330 | struct GRPSYL *gs_p; /* point along a GRPSYL list */ |
| 331 | struct GRPSYL *prev_p; /* the GRPSYL before gs_p */ |
| 332 | int vidx; /* voice index, 0 to MAXVOICES-1 */ |
| 333 | RATIONAL quot; /* quotient */ |
| 334 | RATIONAL swingunit; /* from SSV */ |
| 335 | RATIONAL starttime; /* offset into measure of gs_p */ |
| 336 | RATIONAL halfswing; /* swingunit/2 */ |
| 337 | RATIONAL sixthswing; /* swingunit/6 */ |
| 338 | RATIONAL twelfthswing; /* swingunit/12 */ |
| 339 | RATIONAL threefourthsswing; /* 3/4 * swingunit */ |
| 340 | RATIONAL onefourthswing; /* 1/4 * swingunit */ |
| 341 | static RATIONAL six = {6,1}; |
| 342 | static RATIONAL twelve = {12,1}; |
| 343 | |
| 344 | |
| 345 | initstructs(); |
| 346 | |
| 347 | for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) { |
| 348 | |
| 349 | switch (mainll_p->str) { |
| 350 | case S_SSV: |
| 351 | /* need to keep swingunit up to date */ |
| 352 | asgnssv(mainll_p->u.ssv_p); |
| 353 | continue; |
| 354 | case S_STAFF: |
| 355 | break; /* break out and handle this staff */ |
| 356 | default: |
| 357 | continue; |
| 358 | } |
| 359 | |
| 360 | /* loop through every voice on this staff */ |
| 361 | for (vidx = 0; vidx < MAXVOICES; vidx++) { |
| 362 | |
| 363 | swingunit = vvpath(mainll_p->u.staff_p->staffno, |
| 364 | vidx + 1, SWINGUNIT)->swingunit; |
| 365 | |
| 366 | /* skip this voice if swingunit was not set */ |
| 367 | if (EQ(swingunit, Zero)) { |
| 368 | continue; |
| 369 | } |
| 370 | |
| 371 | /* various rationals we will need in the loop below */ |
| 372 | halfswing = rdiv(swingunit, Two); |
| 373 | threefourthsswing = rmul(swingunit, Three_fourths); |
| 374 | onefourthswing = rmul(swingunit, One_fourth); |
| 375 | sixthswing = rdiv(swingunit, six); |
| 376 | twelfthswing = rdiv(swingunit, twelve); |
| 377 | |
| 378 | /* accumulate starttime */ |
| 379 | starttime = Zero; |
| 380 | |
| 381 | /* for lint; we'll never really check it when it's 0 */ |
| 382 | prev_p = 0; |
| 383 | |
| 384 | /* find first nongrace group in voice (0 if none) */ |
| 385 | gs_p = mainll_p->u.staff_p->groups_p[vidx]; |
| 386 | gs_p = gs_p != 0 && gs_p->grpvalue == GV_ZERO ? |
| 387 | nextnongrace(gs_p) : gs_p; |
| 388 | |
| 389 | /* loop through every nongrace group in this voice */ |
| 390 | for ( ; gs_p != 0; gs_p = nextnongrace(gs_p)) { |
| 391 | |
| 392 | quot = rdiv(starttime, swingunit); |
| 393 | |
| 394 | /* set starttime for the following group here |
| 395 | * because we may alter fulltime below */ |
| 396 | starttime = radd(starttime, gs_p->fulltime); |
| 397 | |
| 398 | /* handle case 1 (see prolog above) */ |
| 399 | if (quot.d == 2 && |
| 400 | GE(gs_p->fulltime, halfswing) && |
| 401 | GE(prev_p->fulltime, halfswing)) { |
| 402 | |
| 403 | prev_p->fulltime = radd( |
| 404 | prev_p->fulltime, sixthswing); |
| 405 | gs_p->fulltime = rsub( |
| 406 | gs_p->fulltime, sixthswing); |
| 407 | } |
| 408 | |
| 409 | /* handle case 2 (see prolog above) */ |
| 410 | if (quot.d == 4 && quot.n % 4 == 3 && |
| 411 | GE(gs_p->fulltime, onefourthswing) && |
| 412 | GE(prev_p->fulltime, threefourthsswing)) { |
| 413 | |
| 414 | prev_p->fulltime = rsub( |
| 415 | prev_p->fulltime, twelfthswing); |
| 416 | gs_p->fulltime = radd( |
| 417 | gs_p->fulltime, twelfthswing); |
| 418 | } |
| 419 | |
| 420 | prev_p = gs_p; |
| 421 | } |
| 422 | } |
| 423 | } |
| 424 | } |
| 425 | \f |
| 426 | /* |
| 427 | * Name: voicevis() |
| 428 | * |
| 429 | * Abstract: If this voice is to be invisible, make it a measure space. |
| 430 | * |
| 431 | * Returns: pointer to first GRPSYL; this equals the input pointer if the |
| 432 | * voice is visible, else it points at the new measure space GRPSYL |
| 433 | * |
| 434 | * Description: This function finds out if the given voice is supposed to be |
| 435 | * invisible this measure. If so, it throws away the current |
| 436 | * GRPSYL list, replacing it with a single GRPSYL that is a |
| 437 | * measure space. See the big comment in svpath() in ssv.c. |
| 438 | */ |
| 439 | |
| 440 | |
| 441 | static struct GRPSYL * |
| 442 | voicevis(gs_p) |
| 443 | |
| 444 | struct GRPSYL *gs_p; /* first GRPSYL in this voice's linked list */ |
| 445 | |
| 446 | { |
| 447 | struct GRPSYL *ngs_p; /* pointer to the new GRPSYL */ |
| 448 | |
| 449 | |
| 450 | /* |
| 451 | * At this point we know that the command line -s option allows this |
| 452 | * staff to be printed, and in fact this staff will be printed, because |
| 453 | * at least one of its voice(s) is supposed to be. (We know this |
| 454 | * because where we were called from, staff_p->visible == YES, and that |
| 455 | * was set by calling svpath().) If the staff weren't being printed, |
| 456 | * we wouldn't need to bother wiping out its invisible voice(s). |
| 457 | */ |
| 458 | |
| 459 | /* |
| 460 | * This voice must be changed to a measure space if the -s option says |
| 461 | * it should be invisible, or if the SSVs say so. The vvpath function |
| 462 | * checks both things. |
| 463 | */ |
| 464 | if (vvpath(gs_p->staffno, gs_p->vno, VISIBLE)->visible == NO) { |
| 465 | |
| 466 | /* |
| 467 | * Allocate a new GRPSYL and make it a measure space, with the |
| 468 | * same inputlineno etc. as the first in the current list. |
| 469 | */ |
| 470 | ngs_p = newGRPSYL(GS_GROUP); |
| 471 | |
| 472 | ngs_p->inputlineno = gs_p->inputlineno; |
| 473 | ngs_p->inputfile = gs_p->inputfile; |
| 474 | ngs_p->staffno = gs_p->staffno; |
| 475 | ngs_p->vno = gs_p->vno; |
| 476 | ngs_p->grpsyl = GS_GROUP; |
| 477 | ngs_p->is_meas = YES; |
| 478 | ngs_p->basictime = -1; |
| 479 | |
| 480 | /* in one compiler the following had to be done separately */ |
| 481 | /* like this, because it couldn't do the structure assignment */ |
| 482 | ngs_p->fulltime.n = Score.time.n; |
| 483 | ngs_p->fulltime.d = Score.time.d; |
| 484 | |
| 485 | ngs_p->grpcont = GC_SPACE; |
| 486 | ngs_p->prev = 0; |
| 487 | ngs_p->next = 0; |
| 488 | ngs_p->gs_p = 0; |
| 489 | |
| 490 | /* throw away the old GRPSYL list */ |
| 491 | free_grpsyls(gs_p); |
| 492 | |
| 493 | return (ngs_p); /* ret pointer to the measure space */ |
| 494 | } |
| 495 | |
| 496 | return (gs_p); /* ret pointer to the original, unchanged GRPSYL */ |
| 497 | } |
| 498 | \f |
| 499 | /* |
| 500 | * Name: combine_voices() |
| 501 | * |
| 502 | * Abstract: Combine GRPSYLs in voices according to the voicecombine parm. |
| 503 | * |
| 504 | * Returns: void |
| 505 | * |
| 506 | * Description: This function, if requested by the voicecombine parameter, |
| 507 | * combines the appropriate groups in each chord on each staff |
| 508 | * where it can. (The set of groups in one chord on one staff is |
| 509 | * called a "hand" in the following code and in some other places |
| 510 | * in Mup, because I get tired of spelling out the whole phrase.) |
| 511 | * Because of beaming and ties/slurs, some groups may need to |
| 512 | * remain uncombined because their neighbors can't be combined. |
| 513 | * So the work is done in three passes. The first pass looks at |
| 514 | * each hand individually to see what can be done there. The |
| 515 | * second pass applies the neighbor rules. The third pass does |
| 516 | * the actual combining. |
| 517 | */ |
| 518 | /* |
| 519 | * NOTE: GRPSYL.pvno is used as a scratch area in these functions. The macro |
| 520 | * below defines COMB to be pvno for this use. We rely on the fact that CALLOC |
| 521 | * initialized it to 0. We count the low order bit as bit 0. Two sets of bits |
| 522 | * are used, as follows. |
| 523 | * |
| 524 | * Bit "x+y" being set to 1 means that the GRPSYLs of voices x and y can be |
| 525 | * combined (looking only at the groups in this chord, not groups they may be |
| 526 | * tie/beamed to, etc.). This scheme works only because the only voice numbers |
| 527 | * are 1, 2, and 3, so that uses bits 3, 4, and 5. The first pass sets them, |
| 528 | * and the second pass reads them. |
| 529 | * |
| 530 | * Bits 6 through 13 are used in pairs for voice numbers of groups that really |
| 531 | * should be combined, with all rules applied. The SHIFT macros below give the |
| 532 | * rightmost bit of each of the voice numbers, for the two possible sources and |
| 533 | * destinations that can happen, given that only 3 voices can exist. Pass 2 |
| 534 | * sets these bits, and pass 3 reads them. |
| 535 | */ |
| 536 | #define COMB pvno |
| 537 | #define SRC1SHIFT 6 |
| 538 | #define DEST1SHIFT 8 |
| 539 | #define SRC2SHIFT 10 |
| 540 | #define DEST2SHIFT 12 |
| 541 | |
| 542 | static void |
| 543 | combine_voices() |
| 544 | { |
| 545 | struct MAINLL *mll_p; /* point along main linked list */ |
| 546 | struct MAINLL *staffmll_p; /* point a group's staff's MLL struct */ |
| 547 | struct CHORD *ch_p; /* point along a chord list */ |
| 548 | struct GRPSYL *gs1_p; /* point along the GRPSYL list of a chord */ |
| 549 | int staff; /* staff number we are working on */ |
| 550 | int pass; /* the three passes we must make */ |
| 551 | |
| 552 | |
| 553 | /* run the three passes */ |
| 554 | for (pass = 1; pass <= 3; pass++) { |
| 555 | |
| 556 | initstructs(); /* clean out old SSV info */ |
| 557 | |
| 558 | for (mll_p = Mainllhc_p; mll_p != 0; mll_p = mll_p->next) { |
| 559 | |
| 560 | switch (mll_p->str) { |
| 561 | case S_SSV: |
| 562 | /* keep SSVs up to date (but midmeasure SSVs |
| 563 | * don't matter for what we're doing here) */ |
| 564 | asgnssv(mll_p->u.ssv_p); |
| 565 | continue; |
| 566 | case S_CHHEAD: |
| 567 | break; /* break out to handle the chords */ |
| 568 | default: |
| 569 | continue; /* ignore everything else */ |
| 570 | } |
| 571 | |
| 572 | /* |
| 573 | * Loop through each chord in this list. |
| 574 | */ |
| 575 | for (ch_p = mll_p->u.chhead_p->ch_p; ch_p != 0; |
| 576 | ch_p = ch_p->ch_p) { |
| 577 | /* |
| 578 | * Loop through the linked list of GRPSYLs |
| 579 | * hanging off this chord. Skip the syllables; |
| 580 | * just deal with the groups. |
| 581 | */ |
| 582 | gs1_p = ch_p->gs_p; |
| 583 | staff = 0; /* before first staff */ |
| 584 | for (;;) { |
| 585 | /* find first group on next staff */ |
| 586 | while (gs1_p != 0 && |
| 587 | gs1_p->staffno == staff) { |
| 588 | gs1_p = gs1_p->gs_p; |
| 589 | } |
| 590 | if (gs1_p == 0) { /* no next staff */ |
| 591 | break; |
| 592 | } |
| 593 | |
| 594 | /* remember this new staff number */ |
| 595 | staff = gs1_p->staffno; |
| 596 | |
| 597 | /* tab ignores vcombine */ |
| 598 | if (is_tab_staff(staff)) { |
| 599 | continue; |
| 600 | } |
| 601 | |
| 602 | /* 1-line ignores vcombine */ |
| 603 | if (svpath(staff, STAFFLINES)-> |
| 604 | stafflines == 1) { |
| 605 | continue; |
| 606 | } |
| 607 | |
| 608 | /* if no groups, only syls, ignore */ |
| 609 | if (gs1_p->grpsyl == GS_SYLLABLE) { |
| 610 | continue; |
| 611 | } |
| 612 | |
| 613 | /* skip staff if only one voice */ |
| 614 | if (svpath(staff, VSCHEME)->vscheme |
| 615 | == V_1) { |
| 616 | continue; |
| 617 | } |
| 618 | |
| 619 | /* get the staff's MLL struct */ |
| 620 | staffmll_p = chmgrp2staffm( |
| 621 | mll_p, gs1_p); |
| 622 | |
| 623 | switch (pass) { |
| 624 | case 1: |
| 625 | /* |
| 626 | * Set individual combineability |
| 627 | * in the "COMB" field. |
| 628 | */ |
| 629 | chkhand1(gs1_p, staffmll_p); |
| 630 | break; |
| 631 | case 2: |
| 632 | /* |
| 633 | * Apply the neighbor rules. |
| 634 | */ |
| 635 | chkhand2(gs1_p, staffmll_p); |
| 636 | break; |
| 637 | case 3: |
| 638 | /* |
| 639 | * Do the actual combining. |
| 640 | */ |
| 641 | dohand(gs1_p, staffmll_p); |
| 642 | break; |
| 643 | } |
| 644 | } |
| 645 | } |
| 646 | } |
| 647 | } |
| 648 | } |
| 649 | \f |
| 650 | /* |
| 651 | * Name: chkhand1() |
| 652 | * |
| 653 | * Abstract: Find which voices are combineable, ignoring neighbor rules. |
| 654 | * |
| 655 | * Returns: void |
| 656 | * |
| 657 | * Description: This function finds out which groups in this hand can be |
| 658 | * combined, of the ones requested by the voicecombine parameter, |
| 659 | * but ignoring neighbor rules. It stores the results in |
| 660 | * the COMB field of all the groups. |
| 661 | */ |
| 662 | |
| 663 | static void |
| 664 | chkhand1(gs1_p, mll_p) |
| 665 | |
| 666 | struct GRPSYL *gs1_p; /* first group in this hand */ |
| 667 | struct MAINLL *mll_p; /* MLL struct for this group */ |
| 668 | |
| 669 | { |
| 670 | /* |
| 671 | * Index the following by voice number to find the expected "height" of |
| 672 | * the voices, relative to each other. A higher number means we expect |
| 673 | * that that voice should normally be higher. |
| 674 | */ /* v1 v2 v3 */ |
| 675 | static int pitch[MAXVOICES + 1] = { 0, 3, 1, 2 }; |
| 676 | |
| 677 | struct SSV *ssv_p; /* the SSV with voice combine info */ |
| 678 | struct GRPSYL *gs_p; /* point along GRPSYLs of the chord */ |
| 679 | /* index the following by vno; it points at the GRPSYL for this vno */ |
| 680 | struct GRPSYL *v_p[MAXVOICES + 1]; |
| 681 | int slot1, slot2; /* indices into SSV's vcombine array */ |
| 682 | int firstvno, secondvno; /* two voices from ssv_p->vcombine[] */ |
| 683 | int combineable; /* YES or NO */ |
| 684 | int comb; /* accumulate combineable bits */ |
| 685 | |
| 686 | |
| 687 | /* point at each group; if only one, no combining can be done */ |
| 688 | if (setgrpptrs(gs1_p, v_p) == 1) { |
| 689 | return; |
| 690 | } |
| 691 | |
| 692 | /* get the list of groups we want to combine */ |
| 693 | ssv_p = svpath(gs1_p->staffno, VCOMBINE); |
| 694 | |
| 695 | /* for each pair of voices to be combined, see if they can be */ |
| 696 | comb = 0; |
| 697 | for (slot1 = 0; slot1 < MAXVOICES; slot1++) { |
| 698 | firstvno = ssv_p->vcombine[slot1]; |
| 699 | if (firstvno == 0) { |
| 700 | break; /* end of list, done with outer loop */ |
| 701 | } |
| 702 | /* voice must have a group in this chord */ |
| 703 | if (v_p[firstvno] == 0) { |
| 704 | continue; /* skip this iteration */ |
| 705 | } |
| 706 | for (slot2 = slot1 + 1; slot2 < MAXVOICES; slot2++) { |
| 707 | secondvno = ssv_p->vcombine[slot2]; |
| 708 | if (secondvno == 0) { |
| 709 | break; /* end of list, done with inner loop */ |
| 710 | } |
| 711 | /* voice must have a group in this chord */ |
| 712 | if (v_p[secondvno] == 0) { |
| 713 | continue; /* skip this iteration */ |
| 714 | } |
| 715 | /* must pass higher voice first */ |
| 716 | if (pitch[firstvno] > pitch[secondvno]) { |
| 717 | combineable = chk2groups(v_p[firstvno], |
| 718 | v_p[secondvno], mll_p, |
| 719 | ssv_p->vcombinequal); |
| 720 | } else { |
| 721 | combineable = chk2groups(v_p[secondvno], |
| 722 | v_p[firstvno], mll_p, |
| 723 | ssv_p->vcombinequal); |
| 724 | } |
| 725 | |
| 726 | /* if this pair was combineable, remember that */ |
| 727 | if (combineable == YES) { |
| 728 | comb |= 1 << (firstvno + secondvno); |
| 729 | } |
| 730 | } |
| 731 | } |
| 732 | |
| 733 | /* save comb in all the groups, for easy access */ |
| 734 | for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno && |
| 735 | gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) { |
| 736 | gs_p->COMB = comb; |
| 737 | } |
| 738 | } |
| 739 | \f |
| 740 | /* |
| 741 | * Name: chk2groups() |
| 742 | * |
| 743 | * Abstract: Find whether two groups are combineable. |
| 744 | * |
| 745 | * Returns: YES or NO |
| 746 | * |
| 747 | * Description: This function finds out if the given groups can be combined, |
| 748 | * ignoring beam and tie/slur issues. If either has preceding |
| 749 | * grace groups, they are also checked (via recursive calls) and |
| 750 | * they must also be able to be combined, to get a YES answer. |
| 751 | */ |
| 752 | |
| 753 | static int |
| 754 | chk2groups(hi_p, lo_p, mll_p, qual) |
| 755 | |
| 756 | struct GRPSYL *hi_p; /* group that should have higher pitch */ |
| 757 | struct GRPSYL *lo_p; /* group that should have lower pitch */ |
| 758 | struct MAINLL *mll_p; /* MLL struct for this group */ |
| 759 | int qual; /* voice combine qualifier */ |
| 760 | |
| 761 | { |
| 762 | struct GRPSYL *phi_p; /* group before hi_p */ |
| 763 | struct GRPSYL *plo_p; /* group before lo_p */ |
| 764 | struct MAINLL *tempmll_p; /* temp copy of mll_p */ |
| 765 | int widx; /* index into "with" lists */ |
| 766 | int hidx, lidx; /* index into note lists */ |
| 767 | int mintop; /* steps above c0 of top group's lowest note */ |
| 768 | int maxbot; /* steps above c0 of bot group's highest note */ |
| 769 | int n; /* loop variable */ |
| 770 | struct NOTE *hnote_p; /* point at a note in the high group */ |
| 771 | struct NOTE *lnote_p; /* point at a note in the low group */ |
| 772 | struct SLURTO *hslur_p; /* point at a slur in the high group */ |
| 773 | struct SLURTO *lslur_p; /* point at a slur in the high group */ |
| 774 | |
| 775 | |
| 776 | /* |
| 777 | * Since the groups are in the same chord, we know they start at the |
| 778 | * same time. Require that they end at the same time. |
| 779 | */ |
| 780 | if (NE(hi_p->fulltime, lo_p->fulltime)) { |
| 781 | return (NO); |
| 782 | } |
| 783 | |
| 784 | /* covered by the fulltime check, except for bizarre tuplet cases */ |
| 785 | if (hi_p->basictime != lo_p->basictime) { |
| 786 | return (NO); |
| 787 | } |
| 788 | if (hi_p->dots != lo_p->dots) { |
| 789 | return (NO); |
| 790 | } |
| 791 | |
| 792 | /* don't allow "mr" and "1r" (for example) to combine */ |
| 793 | if (hi_p->is_meas != lo_p->is_meas) { |
| 794 | return (NO); |
| 795 | } |
| 796 | |
| 797 | /* tuploc must agree */ |
| 798 | if (hi_p->tuploc != lo_p->tuploc) { |
| 799 | return (NO); |
| 800 | } |
| 801 | |
| 802 | /* tupcont must agree */ |
| 803 | if (hi_p->tupcont != lo_p->tupcont) { |
| 804 | return (NO); |
| 805 | } |
| 806 | |
| 807 | /* if printtup is set in both groups, they must agree */ |
| 808 | if (hi_p->printtup != PT_DEFAULT && lo_p->printtup != PT_DEFAULT && |
| 809 | hi_p->printtup != lo_p->printtup) { |
| 810 | return (NO); |
| 811 | } |
| 812 | |
| 813 | /* if tupside is set in both groups, they must agree */ |
| 814 | if (hi_p->tupside != PL_UNKNOWN && lo_p->tupside != PL_UNKNOWN && |
| 815 | hi_p->tupside != lo_p->tupside) { |
| 816 | return (NO); |
| 817 | } |
| 818 | |
| 819 | /* don't allow cross staff beamed groups */ |
| 820 | if (hi_p->beamto != CS_SAME || lo_p->beamto != CS_SAME) { |
| 821 | return (NO); |
| 822 | } |
| 823 | |
| 824 | /* don't allow cross staff stemmed groups */ |
| 825 | if (hi_p->stemto != CS_SAME || lo_p->stemto != CS_SAME) { |
| 826 | return (NO); |
| 827 | } |
| 828 | |
| 829 | /* if either is a space, there can be no other conflict */ |
| 830 | if (hi_p->grpcont == GC_SPACE || lo_p->grpcont == GC_SPACE) { |
| 831 | return (YES); |
| 832 | } |
| 833 | |
| 834 | /***** both groups are GC_NOTES and/or GC_REST *****/ |
| 835 | |
| 836 | /* group size must agree */ |
| 837 | if (hi_p->grpsize != lo_p->grpsize) { |
| 838 | return (NO); |
| 839 | } |
| 840 | |
| 841 | /* if both are rests, there can be no other conflict */ |
| 842 | if (hi_p->grpcont == GC_REST && lo_p->grpcont == GC_REST) { |
| 843 | return (YES); |
| 844 | } |
| 845 | |
| 846 | /* if only one is a rest, there is a conflict */ |
| 847 | if (hi_p->grpcont == GC_REST || lo_p->grpcont == GC_REST) { |
| 848 | return (NO); |
| 849 | } |
| 850 | |
| 851 | /***** both groups are GC_NOTES *****/ |
| 852 | |
| 853 | /* head shape must agree */ |
| 854 | if (hi_p->headshape != lo_p->headshape) { |
| 855 | return (NO); |
| 856 | } |
| 857 | |
| 858 | /* beaming must be the same on both, except on grace beamloc doesn't |
| 859 | * matter, since if we combine them we'll beam them all anyway */ |
| 860 | if (hi_p->beamloc != lo_p->beamloc && hi_p->grpvalue == GV_NORMAL) { |
| 861 | return (NO); |
| 862 | } |
| 863 | if (hi_p->breakbeam != lo_p->breakbeam) { |
| 864 | return (NO); |
| 865 | } |
| 866 | if (hi_p->beamslope != NOBEAMANGLE && lo_p->beamslope != NOBEAMANGLE && |
| 867 | hi_p->beamslope != lo_p->beamslope) { |
| 868 | return (NO); |
| 869 | } |
| 870 | |
| 871 | /* if both stemdirs are set, they must agree */ |
| 872 | if (hi_p->stemlen != STEMLEN_UNKNOWN && |
| 873 | lo_p->stemlen != STEMLEN_UNKNOWN && |
| 874 | hi_p->stemlen != lo_p->stemlen) { |
| 875 | return (NO); |
| 876 | } |
| 877 | |
| 878 | /* if both stemdirs are forced, they must agree */ |
| 879 | if (hi_p->stemdir != UNKNOWN && lo_p->stemdir != UNKNOWN && |
| 880 | hi_p->stemdir != lo_p->stemdir) { |
| 881 | return (NO); |
| 882 | } |
| 883 | |
| 884 | /* group ties out of this group must agree */ |
| 885 | if (hi_p->tie != lo_p->tie) { |
| 886 | return (NO); |
| 887 | } |
| 888 | |
| 889 | /* group ties into this group must agree */ |
| 890 | tempmll_p = mll_p; |
| 891 | phi_p = prevgrpsyl(hi_p, &tempmll_p); |
| 892 | tempmll_p = mll_p; |
| 893 | plo_p = prevgrpsyl(lo_p, &tempmll_p); |
| 894 | if (phi_p != 0 && plo_p != 0 && phi_p->tie != plo_p->tie) { |
| 895 | return (NO); |
| 896 | } |
| 897 | |
| 898 | /* tremelo slashes or alternation slashes must agree */ |
| 899 | if (hi_p->slash_alt != lo_p->slash_alt) { |
| 900 | return (NO); |
| 901 | } |
| 902 | |
| 903 | /* neither group can have a horizontal offset */ |
| 904 | if (hi_p->ho_usage != HO_NONE || lo_p->ho_usage != HO_NONE) { |
| 905 | return (NO); |
| 906 | } |
| 907 | |
| 908 | /* "with" lists must both be nonexistent, or else identical */ |
| 909 | if (hi_p->nwith != lo_p->nwith) { |
| 910 | return (NO); |
| 911 | } |
| 912 | for (widx = 0; widx < hi_p->nwith; widx++) { |
| 913 | if (strcmp(hi_p->withlist[widx], lo_p->withlist[widx]) != 0) { |
| 914 | return (NO); |
| 915 | } |
| 916 | } |
| 917 | |
| 918 | /* |
| 919 | * Rolls aren't really implemented for voice 3. Voice 3 is just along |
| 920 | * for the ride, if it's in the middle of a roll. So we'll let it |
| 921 | * combine as long as both groups are in a roll, or not. But for |
| 922 | * voices 1 and 2, only allow specific combinations that make sense. |
| 923 | */ |
| 924 | if (hi_p->vno == 1 && lo_p->vno == 2) { |
| 925 | switch ((hi_p->roll << 8) | lo_p->roll) { |
| 926 | case (NOITEM << 8) | NOITEM: |
| 927 | break; |
| 928 | case (STARTITEM << 8) | INITEM: |
| 929 | case (STARTITEM << 8) | ENDITEM: |
| 930 | case (INITEM << 8) | INITEM: |
| 931 | case (INITEM << 8) | ENDITEM: |
| 932 | if (hi_p->rolldir != lo_p->rolldir) { |
| 933 | return (NO); |
| 934 | } |
| 935 | break; |
| 936 | default: |
| 937 | return (NO); |
| 938 | } |
| 939 | } else { |
| 940 | if ((hi_p->roll == NOITEM) != (lo_p->roll == NOITEM)) { |
| 941 | return (NO); |
| 942 | } |
| 943 | } |
| 944 | |
| 945 | /* |
| 946 | * If each group is preceded by a grace group, those grace groups must |
| 947 | * also be combineable. Notice that if there are multiple preceding |
| 948 | * grace groups, more recursive calls will occur. If one is preceded |
| 949 | * and the other isn't, there is no problem and nothing to check. |
| 950 | */ |
| 951 | if (hi_p->prev != 0 && hi_p->prev->grpvalue == GV_ZERO && |
| 952 | lo_p->prev != 0 && lo_p->prev->grpvalue == GV_ZERO) { |
| 953 | if (chk2groups(hi_p->prev, lo_p->prev, mll_p, qual) == NO) { |
| 954 | return (NO); |
| 955 | } |
| 956 | } |
| 957 | |
| 958 | /* if either is a mrpt, the other must be, and there is no conflict */ |
| 959 | if (hi_p->is_meas == YES) { |
| 960 | return (YES); |
| 961 | } |
| 962 | |
| 963 | /***** both groups have a notelist *****/ |
| 964 | |
| 965 | /* |
| 966 | * Do some checks involving overlapping of the groups. We'd like to |
| 967 | * use stepsup, but it won't be set to its correct value until |
| 968 | * setnotes.c. Fortunately, we don't need to know the absolute |
| 969 | * vertical position, only the relative. So just use steps above c0. |
| 970 | */ |
| 971 | mintop = hi_p->notelist[hi_p->nnotes - 1].octave * 7 + |
| 972 | Letshift[hi_p->notelist[hi_p->nnotes - 1].letter - 'a']; |
| 973 | maxbot = lo_p->notelist[0].octave * 7 + |
| 974 | Letshift[lo_p->notelist[0].letter - 'a']; |
| 975 | /* |
| 976 | * If the lowest note of the high group is higher than the highest of |
| 977 | * the low group, we are okay regardless of the vcombine qualifier, |
| 978 | * and there are no shared notes to check. |
| 979 | */ |
| 980 | if (mintop > maxbot) { |
| 981 | return (YES); |
| 982 | } |
| 983 | |
| 984 | /* if they are equal, and parm doesn't allow it, fail */ |
| 985 | if (mintop == maxbot && qual == VC_NOOVERLAP) { |
| 986 | return (NO); |
| 987 | } |
| 988 | |
| 989 | /* if there is true overlap, and parm doesn't allow it, fail */ |
| 990 | if (mintop < maxbot && qual != VC_OVERLAP) { |
| 991 | return (NO); |
| 992 | } |
| 993 | |
| 994 | /* |
| 995 | * Any shared notes must be compatible, so check every note in the top |
| 996 | * group against every note in the bottom group. If any are equal, |
| 997 | * they must be compatible. |
| 998 | */ |
| 999 | for (hidx = 0; hidx < hi_p->nnotes; hidx++) { |
| 1000 | |
| 1001 | hnote_p = &hi_p->notelist[hidx]; |
| 1002 | |
| 1003 | for (lidx = 0; lidx < lo_p->nnotes; lidx++) { |
| 1004 | |
| 1005 | lnote_p = &lo_p->notelist[lidx]; |
| 1006 | |
| 1007 | /* if the notes aren't equal, don't check them */ |
| 1008 | if (hnote_p->octave != lnote_p->octave || |
| 1009 | hnote_p->letter != lnote_p->letter) { |
| 1010 | /* the notes differ; no problem */ |
| 1011 | continue; |
| 1012 | } |
| 1013 | |
| 1014 | /* notes match; check all the items that must agree */ |
| 1015 | |
| 1016 | /* any slurs they have must be the same */ |
| 1017 | if (hnote_p->nslurto != lnote_p->nslurto) { |
| 1018 | return (NO); |
| 1019 | } |
| 1020 | for (n = 0; n < hnote_p->nslurto; n++) { |
| 1021 | hslur_p = &hnote_p->slurtolist[n]; |
| 1022 | lslur_p = &lnote_p->slurtolist[n]; |
| 1023 | if (hslur_p->letter != lslur_p->letter) { |
| 1024 | return (NO); |
| 1025 | } |
| 1026 | if (hslur_p->octave != lslur_p->octave) { |
| 1027 | return (NO); |
| 1028 | } |
| 1029 | if (hslur_p->slurstyle != lslur_p->slurstyle) { |
| 1030 | return (NO); |
| 1031 | } |
| 1032 | if (hslur_p->slurdir != lslur_p->slurdir) { |
| 1033 | return (NO); |
| 1034 | } |
| 1035 | } |
| 1036 | |
| 1037 | /* must have same accidental, or none */ |
| 1038 | if (hnote_p->accidental != lnote_p->accidental) { |
| 1039 | return (NO); |
| 1040 | } |
| 1041 | |
| 1042 | /* head shape override, or none, must agree */ |
| 1043 | if (hnote_p->headshape != lnote_p->headshape) { |
| 1044 | return (NO); |
| 1045 | } |
| 1046 | |
| 1047 | /* note size must agree */ |
| 1048 | if (hnote_p->notesize != lnote_p->notesize) { |
| 1049 | return (NO); |
| 1050 | } |
| 1051 | |
| 1052 | /* tie related attributes must be the same */ |
| 1053 | if (hnote_p->tie != lnote_p->tie) { |
| 1054 | return (NO); |
| 1055 | } |
| 1056 | if (hnote_p->tiestyle != lnote_p->tiestyle) { |
| 1057 | return (NO); |
| 1058 | } |
| 1059 | if (hnote_p->tiedir != lnote_p->tiedir) { |
| 1060 | return (NO); |
| 1061 | } |
| 1062 | if (hnote_p->is_bend != lnote_p->is_bend) { |
| 1063 | return (NO); |
| 1064 | } |
| 1065 | if (hnote_p->smallbend != lnote_p->smallbend) { |
| 1066 | return (NO); |
| 1067 | } |
| 1068 | } |
| 1069 | } |
| 1070 | |
| 1071 | return (YES); /* passed all tests, the groups are combineable */ |
| 1072 | } |
| 1073 | \f |
| 1074 | /* |
| 1075 | * Name: chkhand2() |
| 1076 | * |
| 1077 | * Abstract: Make final decision on what can be combined in this hand. |
| 1078 | * |
| 1079 | * Returns: void |
| 1080 | * |
| 1081 | * Description: This function applies the additional rules about beaming and |
| 1082 | * ties/slurs to the results of chkhand1(), to decide what groups |
| 1083 | * in this hand truly should be combined. It stores the results |
| 1084 | * in the COMB field of all the groups. |
| 1085 | */ |
| 1086 | |
| 1087 | static void |
| 1088 | chkhand2(gs1_p, mll_p) |
| 1089 | |
| 1090 | struct GRPSYL *gs1_p; /* first group in this hand */ |
| 1091 | struct MAINLL *mll_p; /* MLL struct for this group */ |
| 1092 | |
| 1093 | { |
| 1094 | struct SSV *ssv_p; /* the SSV with voice combine info */ |
| 1095 | /* index the following by vno; it points at the GRPSYL for this vno */ |
| 1096 | struct GRPSYL *v_p[MAXVOICES + 1]; |
| 1097 | int slot1, slot2; /* indices into SSV's vcombine array */ |
| 1098 | int firstvno, secondvno; /* two voices from ssv_p->vcombine[] */ |
| 1099 | int keep_going; /* try some more? */ |
| 1100 | |
| 1101 | |
| 1102 | /* if we already know no combining can be done, get out */ |
| 1103 | if (gs1_p->COMB == 0) { |
| 1104 | return; |
| 1105 | } |
| 1106 | |
| 1107 | /* point at all the groups in this hand */ |
| 1108 | (void)setgrpptrs(gs1_p, v_p); |
| 1109 | |
| 1110 | /* get the list of groups we want to combine */ |
| 1111 | ssv_p = svpath(gs1_p->staffno, VCOMBINE); |
| 1112 | |
| 1113 | /* for each pair of voices to be combined, apply the neighbor rules */ |
| 1114 | for (slot1 = 0; slot1 < MAXVOICES; slot1++) { |
| 1115 | firstvno = ssv_p->vcombine[slot1]; |
| 1116 | if (firstvno == 0) { |
| 1117 | break; /* end of list, done with outer loop */ |
| 1118 | } |
| 1119 | /* voice must have a group in this chord */ |
| 1120 | if (v_p[firstvno] == 0) { |
| 1121 | continue; /* skip this iteration */ |
| 1122 | } |
| 1123 | for (slot2 = slot1 + 1; slot2 < MAXVOICES; slot2++) { |
| 1124 | secondvno = ssv_p->vcombine[slot2]; |
| 1125 | if (secondvno == 0) { |
| 1126 | break; /* end of list, done with inner loop */ |
| 1127 | } |
| 1128 | /* voice must have a group in this chord */ |
| 1129 | if (v_p[secondvno] == 0) { |
| 1130 | continue; /* skip this iteration */ |
| 1131 | } |
| 1132 | /* |
| 1133 | * The group with the lower voice number should be the |
| 1134 | * one that absorbs the other. Pass it first. |
| 1135 | */ |
| 1136 | if (firstvno < secondvno) { |
| 1137 | keep_going = chk2neighbors(v_p[firstvno], |
| 1138 | v_p[secondvno], gs1_p, mll_p); |
| 1139 | } else { |
| 1140 | keep_going = chk2neighbors(v_p[secondvno], |
| 1141 | v_p[firstvno], gs1_p, mll_p); |
| 1142 | } |
| 1143 | |
| 1144 | /* get out now if we are told to */ |
| 1145 | if (keep_going == NO) { |
| 1146 | return; |
| 1147 | } |
| 1148 | } |
| 1149 | } |
| 1150 | } |
| 1151 | \f |
| 1152 | /* |
| 1153 | * Name: chk2neighbors() |
| 1154 | * |
| 1155 | * Abstract: Apply beaming and tie/slur rules to two groups in a hand. |
| 1156 | * |
| 1157 | * Returns: YES or NO: should any further combining be attempted? |
| 1158 | * |
| 1159 | * Description: This function checks whether the two groups should be combined, |
| 1160 | * by looking at neighboring groups if beaming or ties/slurs |
| 1161 | * are involved. It stores the answer in the COMB field of all |
| 1162 | * the groups. |
| 1163 | * |
| 1164 | * If we shouldn't combine the groups, we return YES so that we |
| 1165 | * can come back and try a different pair, if appropriate. If we |
| 1166 | * can combine the groups, we may return YES or NO; see comments |
| 1167 | * below. |
| 1168 | */ |
| 1169 | |
| 1170 | static int |
| 1171 | chk2neighbors(dest_p, src_p, gs1_p, mll_p) |
| 1172 | |
| 1173 | struct GRPSYL *dest_p; /* group that should absorb the other */ |
| 1174 | struct GRPSYL *src_p; /* group that should be absorbed */ |
| 1175 | struct GRPSYL *gs1_p; /* first group in staff/chord */ |
| 1176 | struct MAINLL *mll_p; /* MLL struct for these groups' staff */ |
| 1177 | |
| 1178 | { |
| 1179 | struct GRPSYL *d2_p, *s2_p; /* point at neighboring groups */ |
| 1180 | struct GRPSYL *gs_p; /* point at groups in this chord */ |
| 1181 | struct MAINLL *mll2_p, *mll3_p; /* more pointers into MLL */ |
| 1182 | short mask; /* to be applied to "COMB" */ |
| 1183 | short comb; /* hold combineability bits */ |
| 1184 | int keep_going; /* return code */ |
| 1185 | |
| 1186 | |
| 1187 | /* |
| 1188 | * Set up the bit that we must check in each chord to see if these two |
| 1189 | * voices are combineable. |
| 1190 | */ |
| 1191 | mask = 1 << (dest_p->vno + src_p->vno); |
| 1192 | |
| 1193 | /* |
| 1194 | * Start at this chord, and keep looking to the right as long as the |
| 1195 | * groups are beamed or tied/slurred. |
| 1196 | */ |
| 1197 | mll2_p = mll_p; |
| 1198 | for (d2_p = dest_p, s2_p = src_p; d2_p != 0 && s2_p != 0; |
| 1199 | d2_p = nextglobnongrace(d2_p, &mll2_p), |
| 1200 | s2_p = nextglobnongrace(s2_p, &mll2_p)) { |
| 1201 | /* |
| 1202 | * If the groups in that chord are not combineable, we must not |
| 1203 | * combine our original groups either. The same flags are set |
| 1204 | * in d2_p and s2_p, so we could have checked either. |
| 1205 | */ |
| 1206 | if ((d2_p->COMB & mask) == 0) { |
| 1207 | return (YES); |
| 1208 | } |
| 1209 | |
| 1210 | /* |
| 1211 | * If the groups are not beamed or tied/slurred to the right, |
| 1212 | * we don't have to look any farther. For beams, we only have |
| 1213 | * to check one group, since the other must agree or we |
| 1214 | * wouldn't be here. For ties/slurs, we only have to check the |
| 1215 | * the src, since those are the ones that wouldn't work if |
| 1216 | * these groups were combined and the next ones weren't. |
| 1217 | */ |
| 1218 | if ((s2_p->beamloc == NOITEM || s2_p->beamloc == ENDITEM) && |
| 1219 | hastieslur(s2_p) == NO) { |
| 1220 | break; |
| 1221 | } |
| 1222 | } |
| 1223 | |
| 1224 | /* |
| 1225 | * Start at this chord, and keep looking to the left as long as the |
| 1226 | * groups are beamed or tied/slurred. |
| 1227 | */ |
| 1228 | mll2_p = mll_p; |
| 1229 | for (d2_p = dest_p, s2_p = src_p; d2_p != 0 && s2_p != 0; |
| 1230 | d2_p = prevglobnongrace(d2_p, &mll2_p), |
| 1231 | s2_p = prevglobnongrace(s2_p, &mll2_p)) { |
| 1232 | |
| 1233 | if ((d2_p->COMB & mask) == 0) { |
| 1234 | return (YES); |
| 1235 | } |
| 1236 | |
| 1237 | mll3_p = mll2_p; /* don't alter mll2_p */ |
| 1238 | if ((s2_p->beamloc == NOITEM || s2_p->beamloc == STARTITEM) && |
| 1239 | hastieslur(prevglobnongrace(s2_p, &mll3_p)) == NO) { |
| 1240 | break; |
| 1241 | } |
| 1242 | } |
| 1243 | |
| 1244 | /* for convenience, copy the COMB bits into a local variable */ |
| 1245 | comb = dest_p->COMB; |
| 1246 | |
| 1247 | /* |
| 1248 | * We passed all the tests, so remember that we should combine the |
| 1249 | * original groups. Also decide whether any more should be tried. |
| 1250 | */ |
| 1251 | if (((comb >> SRC1SHIFT) & 0x3) == 0) { |
| 1252 | /* first groups to be combined in this hand */ |
| 1253 | comb |= src_p->vno << SRC1SHIFT; |
| 1254 | comb |= dest_p->vno << DEST1SHIFT; |
| 1255 | /* |
| 1256 | * If chkhand1() said all the groups in this hand were |
| 1257 | * combineable, we can come back later and try to combine the |
| 1258 | * other group. Otherwise, don't. We know the non-combineable |
| 1259 | * group will fail to combine, so don't waste the time. |
| 1260 | */ |
| 1261 | if ((comb & 0x38) == ((1 << (1 + 2)) | (1 << (1 + 3)) | |
| 1262 | (1 << (2 + 3)))) { |
| 1263 | keep_going = YES; |
| 1264 | } else { |
| 1265 | keep_going = NO; |
| 1266 | } |
| 1267 | } else { |
| 1268 | /* second groups to be combined in this hand */ |
| 1269 | comb |= src_p->vno << SRC2SHIFT; |
| 1270 | comb |= dest_p->vno << DEST2SHIFT; |
| 1271 | keep_going = NO; /* only 2 combinings can be done */ |
| 1272 | } |
| 1273 | |
| 1274 | /* |
| 1275 | * Since we will combine these two groups, the new dest group has |
| 1276 | * inherited any incompatibility that src might have had with the |
| 1277 | * other group (if any). So find the new value of the comb bits. |
| 1278 | * Set this new comb value into all the groups in this hand. We do |
| 1279 | * this for the benefit of later chords on this staff, if they are |
| 1280 | * beamed or tied/slurred to us. |
| 1281 | */ |
| 1282 | switch (dest_p->vno + src_p->vno) { |
| 1283 | case 1 + 2: /* combined 2 into 1 */ |
| 1284 | /* if 2 and 3 can't combine, now 1 and 3 can't */ |
| 1285 | if ((comb & (1 << (2 + 3))) == 0) { |
| 1286 | comb &= ~(1 << (1 + 3)); |
| 1287 | } |
| 1288 | break; |
| 1289 | case 1 + 3: /* combined 3 into 1 */ |
| 1290 | /* if 3 and 2 can't combine, now 1 and 2 can't */ |
| 1291 | if ((comb & (1 << (3 + 2))) == 0) { |
| 1292 | comb &= ~(1 << (1 + 2)); |
| 1293 | } |
| 1294 | break; |
| 1295 | case 2 + 3: /* combined 3 into 2 */ |
| 1296 | /* if 3 and 1 can't combine, now 2 and 1 can't */ |
| 1297 | if ((comb & (1 << (3 + 1))) == 0) { |
| 1298 | comb &= ~(1 << (2 + 1)); |
| 1299 | } |
| 1300 | break; |
| 1301 | } |
| 1302 | for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno && |
| 1303 | gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) { |
| 1304 | gs_p->COMB = comb; |
| 1305 | } |
| 1306 | |
| 1307 | return (keep_going); |
| 1308 | } |
| 1309 | \f |
| 1310 | /* |
| 1311 | * Name: dohand() |
| 1312 | * |
| 1313 | * Abstract: Combine the appropriate GRPSYLs in one chord on one staff. |
| 1314 | * |
| 1315 | * Returns: void |
| 1316 | * |
| 1317 | * Description: This function combines GRPSYLs in one chord on one staff. It |
| 1318 | * uses the previously determined list of what is combineable in |
| 1319 | * gs1_p->COMB. |
| 1320 | */ |
| 1321 | |
| 1322 | static void |
| 1323 | dohand(gs1_p, mll_p) |
| 1324 | |
| 1325 | struct GRPSYL *gs1_p; /* first group on this staff in this chord */ |
| 1326 | struct MAINLL *mll_p; /* MLL struct for this group */ |
| 1327 | |
| 1328 | { |
| 1329 | /* index the following by vno; it points at the GRPSYL for this vno */ |
| 1330 | struct GRPSYL *v_p[MAXVOICES + 1]; |
| 1331 | int srcv, destv; /* src and dest voice numbers */ |
| 1332 | |
| 1333 | |
| 1334 | /* if we already know no combining can be done, get out */ |
| 1335 | if (gs1_p->COMB == 0) { |
| 1336 | return; |
| 1337 | } |
| 1338 | |
| 1339 | /* point at all the groups in this hand */ |
| 1340 | (void)setgrpptrs(gs1_p, v_p); |
| 1341 | |
| 1342 | /* get first src group's voice number */ |
| 1343 | srcv = (gs1_p->COMB >> SRC1SHIFT) & 0x3; |
| 1344 | |
| 1345 | if (srcv != 0) { |
| 1346 | /* find the dest's voice and combine */ |
| 1347 | destv = (gs1_p->COMB >> DEST1SHIFT) & 0x3; |
| 1348 | comb2groups(v_p[destv], v_p[srcv], mll_p); |
| 1349 | |
| 1350 | /* get second src group's voice number */ |
| 1351 | srcv = (gs1_p->COMB >> SRC2SHIFT) & 0x3; |
| 1352 | |
| 1353 | if (srcv != 0) { |
| 1354 | /* find the dest's voice and combine */ |
| 1355 | destv = (gs1_p->COMB >> DEST2SHIFT) & 0x3; |
| 1356 | comb2groups(v_p[destv], v_p[srcv], mll_p); |
| 1357 | } |
| 1358 | } |
| 1359 | } |
| 1360 | \f |
| 1361 | /* |
| 1362 | * Name: comb2groups() |
| 1363 | * |
| 1364 | * Abstract: Combine one group into another. |
| 1365 | * |
| 1366 | * Returns: void |
| 1367 | * |
| 1368 | * Description: This function combines the src group into the dest group, |
| 1369 | * including handling any preceding grace groups. |
| 1370 | */ |
| 1371 | |
| 1372 | static void |
| 1373 | comb2groups(dest_p, src_p, mll_p) |
| 1374 | |
| 1375 | struct GRPSYL *dest_p; /* group that should absorb the other */ |
| 1376 | struct GRPSYL *src_p; /* group that should be absorbed */ |
| 1377 | struct MAINLL *mll_p; /* MLL struct for these groups' staff */ |
| 1378 | |
| 1379 | { |
| 1380 | struct GRPSYL *dgrace_p; /* dest grace group */ |
| 1381 | struct GRPSYL *sgrace_p; /* src grace group */ |
| 1382 | struct GRPSYL *dmem_p; /* remember a group from dest voice */ |
| 1383 | struct GRPSYL *smem_p; /* remember a group from src voice */ |
| 1384 | struct GRPSYL *temp_p; /* temp pointer */ |
| 1385 | struct GRPSYL *fgs_p; /* first grace in src voice */ |
| 1386 | |
| 1387 | |
| 1388 | /* |
| 1389 | * Add the src into the dest, and make the src group into a space if it |
| 1390 | * isn't already a space. |
| 1391 | */ |
| 1392 | addsrc2dest(dest_p, src_p); |
| 1393 | if (src_p->grpcont != GC_SPACE) { |
| 1394 | src_p->grpcont = GC_SPACE; |
| 1395 | src_p->grpvalue = GV_NORMAL; |
| 1396 | src_p->grpsize = GS_NORMAL; |
| 1397 | src_p->headshape = HS_UNKNOWN; |
| 1398 | src_p->beamloc = NOITEM; |
| 1399 | src_p->beamslope = NOBEAMANGLE; |
| 1400 | src_p->stemlen = STEMLEN_UNKNOWN; |
| 1401 | src_p->stemdir = UNKNOWN; |
| 1402 | src_p->breakbeam = NO; |
| 1403 | src_p->beamloc = NOITEM; |
| 1404 | src_p->notelist = 0; |
| 1405 | src_p->nnotes = 0; |
| 1406 | src_p->tie = NO; |
| 1407 | src_p->slash_alt = 0; |
| 1408 | src_p->restdist = NORESTDIST; |
| 1409 | src_p->nwith = 0; |
| 1410 | src_p->roll = NOITEM; |
| 1411 | } |
| 1412 | |
| 1413 | /* if source has no grace notes, we're done */ |
| 1414 | if (src_p->prev == 0 || src_p->prev->grpvalue == GV_NORMAL) { |
| 1415 | return; |
| 1416 | } |
| 1417 | |
| 1418 | /* |
| 1419 | * Loop through the matching grace groups preceding the src and dest |
| 1420 | * groups, adding the src into the dest. Remember the leftmost pair, |
| 1421 | * or the nongrace groups if there are no matching pairs. |
| 1422 | */ |
| 1423 | dmem_p = dest_p; |
| 1424 | smem_p = src_p; |
| 1425 | for (sgrace_p = src_p->prev, dgrace_p = dest_p->prev; |
| 1426 | sgrace_p != 0 && sgrace_p->grpvalue == GV_ZERO && |
| 1427 | dgrace_p != 0 && dgrace_p->grpvalue == GV_ZERO; |
| 1428 | sgrace_p = sgrace_p->prev, dgrace_p = dgrace_p->prev) { |
| 1429 | |
| 1430 | addsrc2dest(dgrace_p, sgrace_p); |
| 1431 | dmem_p = dgrace_p; /* remember last one done */ |
| 1432 | smem_p = sgrace_p; |
| 1433 | } |
| 1434 | |
| 1435 | if (sgrace_p != 0 && sgrace_p->grpvalue == GV_ZERO) { |
| 1436 | /* extra src grace group(s) left over must be moved */ |
| 1437 | |
| 1438 | /* sgrace_p is the last (rightmost) grace to move */ |
| 1439 | for (temp_p = sgrace_p; temp_p != 0 && temp_p->grpvalue == |
| 1440 | GV_ZERO; temp_p = temp_p->prev) { |
| 1441 | fgs_p = temp_p; |
| 1442 | } |
| 1443 | /* fgs_p is the first (leftmost) grace to move */ |
| 1444 | |
| 1445 | if (dgrace_p == 0) { /* at start of measure? */ |
| 1446 | /* in src voice, skip over all the graces */ |
| 1447 | mll_p->u.staff_p->groups_p[src_p->vno-1] = src_p; |
| 1448 | src_p->prev = 0; |
| 1449 | |
| 1450 | /* splice the left grace into the dest voice */ |
| 1451 | mll_p->u.staff_p->groups_p[dest_p->vno-1] = fgs_p; |
| 1452 | fgs_p->prev = 0; |
| 1453 | } else { |
| 1454 | /* in src voice, skip over all the graces */ |
| 1455 | fgs_p->prev->next = src_p; |
| 1456 | src_p->prev = fgs_p->prev; |
| 1457 | |
| 1458 | /* splice the left grace into the dest voice */ |
| 1459 | dgrace_p->next = fgs_p; |
| 1460 | fgs_p->prev = dgrace_p; |
| 1461 | } |
| 1462 | |
| 1463 | /* splice the rightmost left over grace into the dest voice */ |
| 1464 | dmem_p->prev = sgrace_p; |
| 1465 | sgrace_p->next = dmem_p; |
| 1466 | |
| 1467 | /* |
| 1468 | * If there is now more than one grace in the dest, we have to |
| 1469 | * correct beamloc in a couple places. |
| 1470 | */ |
| 1471 | if (fgs_p != dest_p->prev) { |
| 1472 | /* |
| 1473 | * If the dest voice had multiple graces before, the |
| 1474 | * leftmost one, which was STARTITEM, must be made |
| 1475 | * INITEM. If it had only one, it was NOITEM and |
| 1476 | * must be made ENDITEM, but go ahead and set INITEM; |
| 1477 | * it'll be set correctly below. |
| 1478 | */ |
| 1479 | if (dmem_p != dest_p) { /* if dest had grace(s) */ |
| 1480 | dmem_p->beamloc = INITEM; |
| 1481 | } |
| 1482 | |
| 1483 | /* rightmost dest grace must always be made ENDITEM */ |
| 1484 | dest_p->prev->beamloc = ENDITEM; |
| 1485 | } |
| 1486 | |
| 1487 | /* change the voice number of the moved graces */ |
| 1488 | for (temp_p = fgs_p; temp_p != sgrace_p->next; |
| 1489 | temp_p = temp_p->next) { |
| 1490 | temp_p->vno = dest_p->vno; |
| 1491 | } |
| 1492 | } else { |
| 1493 | /* no extra src grace group(s); just remove all src graces */ |
| 1494 | if (sgrace_p == 0) { |
| 1495 | mll_p->u.staff_p->groups_p[src_p->vno-1] = src_p; |
| 1496 | src_p->prev = 0; |
| 1497 | } else { |
| 1498 | smem_p->prev->next = src_p; |
| 1499 | src_p->prev = smem_p->prev; |
| 1500 | } |
| 1501 | } |
| 1502 | /* could free the src graces, but is it worth the trouble? */ |
| 1503 | } |
| 1504 | \f |
| 1505 | /* |
| 1506 | * Name: addsrc2dest() |
| 1507 | * |
| 1508 | * Abstract: Adds src group to dest group. |
| 1509 | * |
| 1510 | * Returns: void |
| 1511 | * |
| 1512 | * Description: This function adds the src group info (if the src group exists) |
| 1513 | * into the dest group. But it doesn't mess with linkages. That |
| 1514 | * is the calling function's job. |
| 1515 | */ |
| 1516 | |
| 1517 | static void |
| 1518 | addsrc2dest(dest_p, src_p) |
| 1519 | |
| 1520 | struct GRPSYL *dest_p; /* destination group must exist */ |
| 1521 | struct GRPSYL *src_p; /* source group, or can be NULL */ |
| 1522 | |
| 1523 | { |
| 1524 | struct NOTE *dnote_p; /* point at a note in the destination group */ |
| 1525 | struct NOTE *snote_p; /* point at a note in the source group */ |
| 1526 | struct NOTE *newlist; /* combined notelist */ |
| 1527 | int didx, sidx; /* index into dest and src note lists */ |
| 1528 | int totnotes; /* total number of notes after combining */ |
| 1529 | int n; /* loop variable */ |
| 1530 | |
| 1531 | |
| 1532 | /* if src doesn't exist, there is nothing to do */ |
| 1533 | if (src_p == 0) { |
| 1534 | return; |
| 1535 | } |
| 1536 | |
| 1537 | /* move references to the src group's coords */ |
| 1538 | upd_ref(src_p->c, dest_p->c); |
| 1539 | |
| 1540 | /* if src is space, nothing to do except carry over this space field */ |
| 1541 | if (src_p->grpcont == GC_SPACE) { |
| 1542 | if (dest_p->grpcont == GC_SPACE && |
| 1543 | src_p->uncompressible == YES) { |
| 1544 | dest_p->uncompressible = YES; |
| 1545 | } |
| 1546 | return; |
| 1547 | } |
| 1548 | |
| 1549 | /* padding is the max of the two groups */ |
| 1550 | dest_p->padding = MAX(dest_p->padding, src_p->padding); |
| 1551 | |
| 1552 | /* |
| 1553 | * Some fields were allowed to disagree between the groups as long as |
| 1554 | * one was defaulted. The non-default value should prevail. |
| 1555 | */ |
| 1556 | if (src_p->printtup != PT_DEFAULT) { |
| 1557 | dest_p->printtup = src_p->printtup; |
| 1558 | } |
| 1559 | if (src_p->tupside != PL_UNKNOWN) { |
| 1560 | dest_p->tupside = src_p->tupside; |
| 1561 | } |
| 1562 | if (src_p->beamslope != NOBEAMANGLE) { |
| 1563 | dest_p->beamslope = src_p->beamslope; |
| 1564 | } |
| 1565 | if (src_p->stemlen != STEMLEN_UNKNOWN) { |
| 1566 | dest_p->stemlen = src_p->stemlen; |
| 1567 | } |
| 1568 | if (src_p->stemdir != UNKNOWN) { |
| 1569 | dest_p->stemdir = src_p->stemdir; |
| 1570 | } |
| 1571 | |
| 1572 | /* only when combining 1 & 2 might we have to adjust roll */ |
| 1573 | if (dest_p->vno == 1 && src_p->vno == 2) { |
| 1574 | switch ((dest_p->roll << 8) | src_p->roll) { |
| 1575 | case (NOITEM << 8) | NOITEM: |
| 1576 | /* dest remains NOITEM */ |
| 1577 | break; |
| 1578 | case (STARTITEM << 8) | INITEM: |
| 1579 | /* dest remains STARTITEM */ |
| 1580 | break; |
| 1581 | case (STARTITEM << 8) | ENDITEM: |
| 1582 | dest_p->roll = LONEITEM; |
| 1583 | break; |
| 1584 | case (INITEM << 8) | INITEM: |
| 1585 | /* dest remains INITEM */ |
| 1586 | break; |
| 1587 | case (INITEM << 8) | ENDITEM: |
| 1588 | dest_p->roll = ENDITEM; |
| 1589 | break; |
| 1590 | } |
| 1591 | } |
| 1592 | |
| 1593 | /* if one is a rest, so is the other; combine */ |
| 1594 | if (dest_p->grpcont == GC_REST) { |
| 1595 | /* throw away any restdist; probably would be inappropriate */ |
| 1596 | dest_p->restdist = 0; |
| 1597 | return; |
| 1598 | } |
| 1599 | |
| 1600 | /* if either is a mrpt, the other must be; nothing to copy */ |
| 1601 | if (dest_p->is_meas == YES) { |
| 1602 | return; |
| 1603 | } |
| 1604 | |
| 1605 | /* at this point we know src has notes, & dest has notes or is space */ |
| 1606 | |
| 1607 | /* |
| 1608 | * Make a new notelist. First copy the old dest notes into there, and |
| 1609 | * then add the src notes. We can't just realloc the dest, since |
| 1610 | * pointers into the array must be updated by calling upd_ref for each |
| 1611 | * array element. If any notes are shared, we won't really need this |
| 1612 | * many, but it doesn't waste much memory. |
| 1613 | */ |
| 1614 | MALLOC(NOTE, newlist, dest_p->nnotes + src_p->nnotes); |
| 1615 | for (n = 0; n < dest_p->nnotes; n++) { |
| 1616 | newlist[n] = dest_p->notelist[n]; |
| 1617 | } |
| 1618 | |
| 1619 | /* |
| 1620 | * Keep track of the number of total resulting notes, which starts out |
| 1621 | * as the number of notes in dest. Loop through the src notes. |
| 1622 | */ |
| 1623 | totnotes = dest_p->nnotes; |
| 1624 | for (sidx = 0; sidx < src_p->nnotes; sidx++) { |
| 1625 | snote_p = &src_p->notelist[sidx]; |
| 1626 | |
| 1627 | /* see if it matches any of the dest notes in the result array*/ |
| 1628 | for (didx = 0; didx < dest_p->nnotes; didx++) { |
| 1629 | dnote_p = &newlist[didx]; |
| 1630 | if (dnote_p->octave == snote_p->octave && |
| 1631 | dnote_p->letter == snote_p->letter) { |
| 1632 | /* |
| 1633 | * If one has parens on the note or acc and the |
| 1634 | * other doesn't, ensure no parens in result. |
| 1635 | */ |
| 1636 | if (dnote_p->note_has_paren != |
| 1637 | snote_p->note_has_paren) { |
| 1638 | dnote_p->note_has_paren = NO; |
| 1639 | } |
| 1640 | if (dnote_p->acc_has_paren != |
| 1641 | snote_p->acc_has_paren) { |
| 1642 | dnote_p->acc_has_paren = NO; |
| 1643 | } |
| 1644 | break; |
| 1645 | } |
| 1646 | } |
| 1647 | if (didx == dest_p->nnotes) { |
| 1648 | /* didn't find a match, so add it to the end */ |
| 1649 | newlist[totnotes++] = *snote_p; |
| 1650 | } |
| 1651 | } |
| 1652 | |
| 1653 | /* sort the combined list in pitch order */ |
| 1654 | qsort((char *)newlist, (unsigned int)totnotes, |
| 1655 | sizeof (struct NOTE), notecomp); |
| 1656 | |
| 1657 | /* |
| 1658 | * For every original dest and src note, find out where it ended up in |
| 1659 | * the combined list, and update and location tag references. |
| 1660 | */ |
| 1661 | for (didx = 0; didx < dest_p->nnotes; didx++) { |
| 1662 | dnote_p = &dest_p->notelist[didx]; |
| 1663 | for (n = 0; n < totnotes; n++) { |
| 1664 | if (newlist[n].octave == dnote_p->octave && |
| 1665 | newlist[n].octave == dnote_p->letter) { |
| 1666 | upd_ref(newlist[n].c, dnote_p->c); |
| 1667 | } |
| 1668 | } |
| 1669 | } |
| 1670 | for (sidx = 0; sidx < src_p->nnotes; sidx++) { |
| 1671 | dnote_p = &src_p->notelist[sidx]; |
| 1672 | for (n = 0; n < totnotes; n++) { |
| 1673 | if (newlist[n].octave == dnote_p->octave && |
| 1674 | newlist[n].octave == dnote_p->letter) { |
| 1675 | upd_ref(newlist[n].c, dnote_p->c); |
| 1676 | } |
| 1677 | } |
| 1678 | } |
| 1679 | |
| 1680 | /* free old dest list, and install the new one and its note count */ |
| 1681 | if (dest_p->notelist != 0) { /* not a space */ |
| 1682 | FREE(dest_p->notelist); |
| 1683 | } |
| 1684 | dest_p->notelist = newlist; |
| 1685 | dest_p->nnotes = totnotes; |
| 1686 | } |
| 1687 | \f |
| 1688 | /* |
| 1689 | * Name: setgrpptrs() |
| 1690 | * |
| 1691 | * Abstract: Set pointers to the groups in a hand. |
| 1692 | * |
| 1693 | * Returns: number of GRPSYLs found in this hand |
| 1694 | * |
| 1695 | * Description: This function fill in the given array with pointers to the |
| 1696 | * groups in this hand. When a group doesn't exist for some |
| 1697 | * voice, a null pointer is used. |
| 1698 | */ |
| 1699 | |
| 1700 | static int |
| 1701 | setgrpptrs(gs1_p, v_p) |
| 1702 | |
| 1703 | struct GRPSYL *gs1_p; /* first group in this hand */ |
| 1704 | struct GRPSYL *v_p[]; /* fill this in, index by voice number */ |
| 1705 | |
| 1706 | { |
| 1707 | struct GRPSYL *gs_p; /* point along GRPSYLs of the chord */ |
| 1708 | int v; /* a voice number */ |
| 1709 | int num; /* number of groups found */ |
| 1710 | |
| 1711 | |
| 1712 | /* null out the list of pointers initially (note [0] is not used) */ |
| 1713 | for (v = 1; v <= MAXVOICES; v++) { |
| 1714 | v_p[v] = 0; |
| 1715 | } |
| 1716 | /* for each group in the hand, set pointer to it */ |
| 1717 | num = 0; |
| 1718 | for (gs_p = gs1_p; gs_p != 0 && gs_p->staffno == gs1_p->staffno && |
| 1719 | gs_p->grpsyl == GS_GROUP; gs_p = gs_p->gs_p) { |
| 1720 | v_p[gs_p->vno] = gs_p; |
| 1721 | num++; |
| 1722 | } |
| 1723 | |
| 1724 | return (num); |
| 1725 | } |
| 1726 | \f |
| 1727 | /* |
| 1728 | * Name: hastieslur() |
| 1729 | * |
| 1730 | * Abstract: Is this group tied/slurred/bent to the next? |
| 1731 | * |
| 1732 | * Returns: YES or NO |
| 1733 | * |
| 1734 | * Description: This function checks whether there are any ties/slurs/bends to |
| 1735 | * the next group. If the given group doesn't exist, the answer |
| 1736 | * is NO. |
| 1737 | */ |
| 1738 | |
| 1739 | static int |
| 1740 | hastieslur(gs_p) |
| 1741 | |
| 1742 | struct GRPSYL *gs_p; /* group to check */ |
| 1743 | |
| 1744 | { |
| 1745 | int idx; /* index into note list */ |
| 1746 | |
| 1747 | |
| 1748 | /* if there's no group, it isn't tied/slurred */ |
| 1749 | if (gs_p == 0) { |
| 1750 | return (NO); |
| 1751 | } |
| 1752 | |
| 1753 | /* check group tie */ |
| 1754 | if (gs_p->tie == YES) { |
| 1755 | return (YES); |
| 1756 | } |
| 1757 | |
| 1758 | /* check note ties and slurs (bends are covered by slurs) */ |
| 1759 | for (idx = 0; idx < gs_p->nnotes; idx++) { |
| 1760 | if (gs_p->notelist[idx].tie == YES || |
| 1761 | gs_p->notelist[idx].nslurto != 0) { |
| 1762 | return (YES); |
| 1763 | } |
| 1764 | } |
| 1765 | |
| 1766 | return (NO); |
| 1767 | } |