Commit | Line | Data |
---|---|---|
69695f33 MW |
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 | } |