2 /* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2006 by Arkkra Enterprises */
3 /* All rights reserved */
5 /* This file contains functions for mapping input to individual voices.
6 * The user can give a single line of input
7 * that gets expanded into several voices.
8 * There are two flavors of this:
9 * voice-at-a-time input and chord-at-a-time input.
10 * For the former, the GRPSYL list just gets cloned and altered as needed.
11 * For the latter, brand new GRPSYL lists are created
12 * by distributing individual notes from the user's input.
13 * For any given staff/voice, only one type of input can be used per measure.
14 * For chord-at-a-time, a given staff/voice can appear more than once
15 * within a single input line, but not on multiple input lines per measure.
22 /* mark whether we mapped user data, only mapped implicit spaces, or nothing */
23 #define MAPPED_NOTHING (0)
24 #define MAPPED_IMPLICIT (1)
25 #define MAPPED_EXPLICIT (2)
27 /* This struct tells how to map one note for chord-at-a-time input,
28 * i.e., which staff/voice combinations it should be mapped to.
29 * Each map item in input (semicolon-separated)
30 * gets saved in one of these. */
32 struct SVRANGELIST
*svlist_p
; /* staffs/voices to map this note to */
33 struct NOTEMAP
*next
; /* linked list */
36 /* This struct gives the mapping for a particular number of notes.
37 * The set of things inside a pair of brackets gets saved in one of these. */
39 int num_entries
; /* how many item in list */
40 struct NOTEMAP
*notemap_p
; /* one entry for each note in chord */
41 struct MAP
*next
; /* linked list */
44 /* This points to the list of maps, or to 0 if doing voice-at-a-time input */
45 static struct MAP
*Map_p
;
46 /* This points to where to add to the map list */
47 static struct MAP
**End_map_p_p
= &Map_p
;
49 /* This is where to insert the next NOTEMAP */
50 static struct NOTEMAP
**Note_p_p
;
52 /* It is handy to be able to treat both input styles identically
53 * as much as possible. So for when input is voice-at-a-time, it can be handy
54 * to have a MAP that just points to Svrangelist_p. These two structs are
55 * used for that purpose. Since the value of Svrangelist_p changes
56 * at runtime, we have to set Sv_notemap->svlist_p each time
57 * before these are used. */
58 static struct NOTEMAP Sv_notemap
= {
59 (struct SVRANGELIST
*) 0, (struct NOTEMAP
*) 0
61 static struct MAP Voice_at_a_time_map
= {
62 1, &Sv_notemap
, (struct MAP
*) 0
65 /* Keep track of which input style was used */
66 static short Input_style
[MAXSTAFFS
][MAXVOICES
];
68 static int map_groups
P((void));
69 static void clean_map_data
P((void));
70 static void free_maps
P((struct MAP
*map_p
));
71 static void free_notemaps
P((struct NOTEMAP
*notemap_p
));
72 static struct NOTEMAP
*find_notemap
P((int num_notes
));
73 static void map1note
P((struct GRPSYL
*from_gs_p
, int n
, int staff
, int voice
,
74 short allocated
[MAXSTAFFS
][MAXVOICES
]));
75 static void do_link_groups
P((void));
76 static void link_a_grouplist
P((int staffno
, int vno
, int copies
));
77 static void convert_rest_space
P((struct GRPSYL
*grpsyl_p
, int staffno
, int vno
));
78 static void conv_grpsyl
P((struct GRPSYL
*grpsyl_p
, int staffno
, int vno
));
79 static void mult_def
P((int staff
, int voice
));
82 /* Initialize Input_style to default of IS_VOICE_INPUT */
91 for (staff
= 0; staff
< MAXSTAFFS
; staff
++) {
92 for (voice
= 0; voice
< MAXVOICES
; voice
++) {
93 Input_style
[staff
][voice
] = IS_VOICE_INPUT
;
99 /* Return the current input style for a given staff/voice */
102 input_style(staff
, voice
)
108 return(Input_style
[staff
-1][voice
-1]);
112 /* This is called when a '[' is encountered in input, starting a new map */
121 /* allocate space for a new map */
122 CALLOC(MAP
, new_p
, 1);
124 /* Keep track of where to link on the first NOTEMAP */
125 Note_p_p
= &(new_p
->notemap_p
);
127 /* Add to MAP list */
128 *End_map_p_p
= new_p
;
134 /* Save one item of a map. Items are the semicolon-separated specifications. */
139 CALLOC(NOTEMAP
, *Note_p_p
, 1);
141 /* Save the current range */
142 (*Note_p_p
)->svlist_p
= Svrangelist_p
;
143 ((*End_map_p_p
)->num_entries
)++;
145 /* prepare for another, if any */
146 Note_p_p
= &( (*Note_p_p
)->next
);
149 begin_range(PL_UNKNOWN
);
153 /* At the end of a map specification, this function is called to save the
154 * info about the map for later use, and prepare for another map, if any.
161 /* prepare for another map, if any */
162 End_map_p_p
= &( (*End_map_p_p
)->next
);
168 /* Map chord-at-a-time input so it looks just like voice-at-a-time input.
169 * Return YES if current measure is chord-at-a-time, and thus
170 * mapping was done, NO if current measure is voice-at-a-time.
178 /* Multiple notes in a chord might get mapped to a single staff/voice.
179 * In that case, after the first note for that staff/voice,
180 * we need to just add a note to the existing GRPSYL rather than
181 * allocating a new one. This keeps track of whether we have already
182 * allocated a GRPSYL for the current chord of a given staff/voice. */
183 short allocated
[MAXSTAFFS
][MAXVOICES
];
184 /* This array tells us which staffs/voices we are mapping things to */
185 short used
[MAXSTAFFS
][MAXVOICES
];
186 /* This array will have MAPPED_EXPLICIT
187 * in entries where we mapped actual user data.
188 * If we only mapped implicit spaces (MAPPED_IMPLICIT),
189 * we can treat things as if user didn't use the voice
190 * on this input line. */
191 short mapped_something
[MAXSTAFFS
][MAXVOICES
];
192 /* This says if we've printed an error yet for multiply defined voice,
193 * to make sure we only print it once. */
194 short printed_mult_err
[MAXSTAFFS
][MAXVOICES
];
195 /* This tells which numbers of notes we have maps for. */
196 short have_map
[MAXHAND
];
197 int s
; /* staff number */
198 int v
; /* voice number */
199 int n
; /* note index */
200 struct NOTEMAP
*notemap_p
; /* how to map notes to voices */
201 struct SVRANGELIST
*svr_p
;
202 struct RANGELIST
*sr_p
; /* range of staffs being defined */
203 struct RANGELIST
*vr_p
; /* range of vno's being defined */
209 if (Map_p
== (struct MAP
*) 0) {
210 /* not chord-at-a-time mapping, so nothing to do here */
214 /* remember current error count */
217 /* Initialize arrays. These will later tell us
218 * which GRPSYL lists we are mapping to, and whether we mapped
219 * any actual user input, or just implicit spaces. */
220 for (s
= 0; s
< Score
.staffs
; s
++) {
221 for (v
= 0; v
< MAXVOICES
; v
++) {
223 mapped_something
[s
][v
] = MAPPED_NOTHING
;
224 printed_mult_err
[s
][v
] = NO
;
227 /* This tells for which numbers of notes we have maps */
228 for (n
= 0; n
< MAXHAND
; n
++) {
232 /* Do some error checking on the MAP list */
233 for (map_p
= Map_p
; map_p
!= (struct MAP
*) 0; map_p
= map_p
->next
) {
235 if (have_map
[map_p
->num_entries
] == YES
) {
236 l_yyerror(Curr_filename
, yylineno
,
237 "more than one map for chords with %d notes",
242 have_map
[map_p
->num_entries
] = YES
;
245 for (notemap_p
= map_p
->notemap_p
;
246 notemap_p
!= (struct NOTEMAP
*) 0;
247 notemap_p
= notemap_p
->next
) {
248 for (svr_p
= notemap_p
->svlist_p
;
249 svr_p
!= (struct SVRANGELIST
*) 0;
250 svr_p
= svr_p
->next
) {
251 for (sr_p
= svr_p
->stafflist_p
; sr_p
!= 0;
253 for (s
= sr_p
->begin
; s
<= sr_p
->end
; s
++) {
255 if (s
> Score
.staffs
) {
256 l_yyerror(Curr_filename
,
258 "staff %d does not exist",
263 for (vr_p
= svr_p
->vnolist_p
; vr_p
!= 0;
265 for (v
= vr_p
->begin
;
266 v
<= vr_p
->end
; v
++) {
268 /* make sure voice exists */
269 if (v
> 1 && svpath(s
, VSCHEME
)
271 l_yyerror(Curr_filename
,
273 "there is no voice %d on staff %d",
276 used
[s
-1][v
-1] = YES
;
277 Input_style
[s
-1][v
-1]
287 if (Errorcount
> errors
) {
292 /* process each chord in the GRPSYL list */
293 for (gs_p
= Curr_gs_list_p
; gs_p
!= (struct GRPSYL
*) 0;
295 /* initialize the allocation array for current chord */
296 for (s
= 0; s
< Score
.staffs
; s
++) {
297 for (v
= 0; v
< MAXVOICES
; v
++) {
298 allocated
[s
][v
] = NO
;
302 /* With voice-at-a-time input, we allow the first group
303 * to have no pitch specified iff it is on a 1-line staff.
304 * For chord-at-a-time, to allow that
305 * we would have to allow a mapping of zero notes,
306 * which doesn't make sense, or map an implicit note,
307 * which seems questionable at best.
308 * If there is a mixture of 1-line and not-1-line
309 * staffs being mapped, things get even more confusing.
310 * So we disallow implicit pitch on chord-at-at-time. */
311 if (gs_p
->nnotes
== 1 && gs_p
->notelist
[0].letter
== PP_NO_PITCH
) {
312 l_yyerror(Curr_filename
, yylineno
, "no notes specified");
313 notemap_p
= (struct NOTEMAP
*) 0;
316 /* Find the pattern matching the number of notes.
317 * If none is found, this will return 0, and the 'for'
318 * below will get skipped, and we'll add spaces */
319 notemap_p
= find_notemap(gs_p
->nnotes
);
322 /* Go through each note in the chord, and copy it
323 * to the appropriate staffs/voices */
324 for (n
= 0; notemap_p
!= (struct NOTEMAP
*) 0;
325 n
++, notemap_p
= notemap_p
->next
) {
326 for (svr_p
= notemap_p
->svlist_p
;
327 svr_p
!= (struct SVRANGELIST
*) 0;
328 svr_p
= svr_p
->next
) {
329 for (sr_p
= svr_p
->stafflist_p
; sr_p
!= 0;
331 for (s
= sr_p
->begin
; s
<= sr_p
->end
; s
++) {
332 for (vr_p
= svr_p
->vnolist_p
; vr_p
!= 0;
334 for (v
= vr_p
->begin
;
335 v
<= vr_p
->end
; v
++) {
336 /* If we have not yet mapped
337 * anything from the current
338 * input line, yet there is
339 * something in the grpsyl
340 * list for this staff/voice,
341 * that means user must have
342 * already defined data for
343 * this staff/voice on some
344 * other input line, and thus
345 * is not allowed to map
346 * anything from the current
348 if (mapped_something
[s
-1][v
-1]
350 && Staffmap_p
[s
]->u
.staff_p
->groups_p
[v
-1] != 0
351 && printed_mult_err
[s
-1][v
-1] == NO
) {
353 printed_mult_err
[s
-1][v
-1] = YES
;
356 map1note(gs_p
, n
, s
, v
,
358 mapped_something
[s
-1][v
-1]
367 /* For any staff/voice that is being mapped to, but which
368 * didn't get anything mapped for this particular chord,
369 * add a space group. This could happen either because
370 * user specified several patterns and some patterns don't
371 * contain all the staffs/voices, which implies they want
372 * us to fill in spaces, or because there was an error in
373 * input. If there was an error, it's still nice to add the
374 * space, because it prevents extra error messages */
375 for (s
= 1; s
<= Score
.staffs
; s
++) {
376 for (v
= 1; v
<= MAXVOICES
; v
++) {
377 /* If we haven't mapped anything to this
378 * voice, but there is something there,
379 * user must have defined it on an earlier
380 * input line. In that case we should leave
381 * it be, because either (1) user didn't
382 * actually use any pattern that uses this
383 * voice, or (2) they multiply defined the
384 * voice, in which case the error is caught
385 * elsewhere. In either case, their
386 * earlier input should stand. */
387 if (mapped_something
[s
-1][v
-1] == MAPPED_NOTHING
388 && Staffmap_p
[s
]->u
.staff_p
->groups_p
[v
-1] != 0) {
392 if (used
[s
-1][v
-1] == YES
&&
393 allocated
[s
-1][v
-1] == NO
) {
394 map1note(gs_p
, -1, s
, v
, allocated
);
395 if (mapped_something
[s
-1][v
-1] !=
397 mapped_something
[s
-1][v
-1]
405 /* If this particular input line didn't actually use some of the
406 * patterns, some voices might not *really* have been used--we
407 * merely filled in implicit spaces for it. So we can undo that
408 * so user can specify the voice via voice-at-a-time if they want to.
409 * If they don't, the regular filling in of missing voices with
410 * implicit spaces will happen later. */
411 for (s
= 0; s
< Score
.staffs
; s
++) {
412 for (v
= 0; v
< MAXVOICES
; v
++) {
413 if (used
[s
][v
] == YES
&&
414 mapped_something
[s
][v
] != MAPPED_EXPLICIT
) {
416 Input_style
[s
][v
] = IS_VOICE_INPUT
;
418 /* If only implict, we free that up */
419 if (mapped_something
[s
][v
] == MAPPED_IMPLICIT
) {
420 free_grpsyls(Staffmap_p
[s
+1]->u
.staff_p
->groups_p
[v
]);
421 Staffmap_p
[s
+1]->u
.staff_p
->groups_p
[v
] = 0;
427 /* Now we can go through and free up any wasted space */
428 for (s
= 0; s
< Score
.staffs
; s
++) {
429 for (v
= 0; v
< MAXVOICES
; v
++) {
430 if (used
[s
][v
] == YES
) {
431 /* Rests and spaces get moved from
432 * NOTE pseudo-pitches to GRPSYL */
433 convert_rest_space(Staffmap_p
[s
+1]->u
.
434 staff_p
->groups_p
[v
], s
+1, v
+1);
435 for (g_p
= Staffmap_p
[s
+1]->u
.staff_p
->groups_p
[v
];
436 g_p
!= (struct GRPSYL
*) 0;
438 resize_notelist(g_p
);
446 /* Everything in the original GRPSYL list
447 * has been copied to other lists, so original can be freed */
454 /* map one note to one staff/voice */
457 map1note(from_gs_p
, n
, staff
, voice
, allocated
)
459 struct GRPSYL
*from_gs_p
; /* copy from here */
460 int n
; /* copy the nth note in from_gs_p, or if -1,
461 * create a space group */
464 short allocated
[MAXSTAFFS
][MAXVOICES
]; /* tracks whether to allocate a new
465 * GRPSYL; may be updated */
468 struct GRPSYL
*to_gs_p
; /* where to map note to */
469 struct GRPSYL
**add_p_p
; /* where to add to_gs_p */
470 struct NOTE
*from_note_p
;
471 struct NOTE
*to_note_p
;
472 struct GRPSYL
*prev
; /* value to set to_gs_p->prev to */
475 /* If original group is a grace group, we don't need to add a
476 * space group, since grace already take no time */
477 if (n
== -1 && from_gs_p
->grpvalue
== GV_ZERO
) {
481 /* If this is the first note allocated to this staff/voice for
482 * current chord, have to allocate a GRPSYL for it. */
483 if (allocated
[staff
- 1] [voice
- 1] == NO
) {
484 to_gs_p
= newGRPSYL(GS_GROUP
);
485 copy_attributes(to_gs_p
, from_gs_p
);
486 /* by the time we get here, we've already gone past the
487 * newline, so the input line number is one too much */
488 to_gs_p
->inputlineno
--;
490 allocated
[staff
- 1] [voice
- 1] = YES
;
492 /* Add to end of list */
493 prev
= (struct GRPSYL
*) 0;
494 for (add_p_p
= &(Staffmap_p
[staff
]->u
.staff_p
->groups_p
[voice
-1]);
495 *add_p_p
!= (struct GRPSYL
*) 0;
496 add_p_p
= &((*add_p_p
)->next
) ) {
499 to_gs_p
->prev
= prev
;
502 /* copy the other attributes */
503 to_gs_p
->staffno
= staff
;
504 to_gs_p
->vno
= voice
;
505 to_gs_p
->basictime
= from_gs_p
->basictime
;
506 to_gs_p
->fulltime
= from_gs_p
->fulltime
;
507 to_gs_p
->dots
= from_gs_p
->dots
;
508 to_gs_p
->is_meas
= from_gs_p
->is_meas
;
509 to_gs_p
->tuploc
= from_gs_p
->tuploc
;
510 to_gs_p
->tupcont
= from_gs_p
->tupcont
;
511 to_gs_p
->tupside
= from_gs_p
->tupside
;
512 to_gs_p
->beamloc
= from_gs_p
->beamloc
;
513 to_gs_p
->breakbeam
= from_gs_p
->breakbeam
;
514 to_gs_p
->beamto
= from_gs_p
->beamto
;
515 to_gs_p
->printtup
= from_gs_p
->printtup
;
516 to_gs_p
->tie
= from_gs_p
->tie
;
517 to_gs_p
->inhibitprint
= from_gs_p
->inhibitprint
;
518 to_gs_p
->ho_usage
= from_gs_p
->ho_usage
;
519 to_gs_p
->ho_value
= from_gs_p
->ho_value
;
522 /* find the last group for this staff/voice */
523 for (to_gs_p
= Staffmap_p
[staff
]->u
.staff_p
->groups_p
[voice
-1];
524 to_gs_p
->next
!= (struct GRPSYL
*) 0;
525 to_gs_p
= to_gs_p
->next
) {
530 /* Special case: If n == -1, make this a space group */
532 to_gs_p
->grpcont
= GC_SPACE
;
533 /* some things don't make sense with space,
534 * so nullify the things that just apply to notes */
535 to_gs_p
->grpvalue
= GV_NORMAL
;
536 to_gs_p
->headshape
= HS_UNKNOWN
;
537 to_gs_p
->grpsize
= GS_NORMAL
;
538 to_gs_p
->stemdir
= UNKNOWN
;
539 to_gs_p
->stemlen
= STEMLEN_UNKNOWN
;
540 to_gs_p
->roll
= NOITEM
;
541 to_gs_p
->beamloc
= NOITEM
;
542 to_gs_p
->breakbeam
= NO
;
543 to_gs_p
->beamto
= CS_SAME
;
544 to_gs_p
->stemto
= CS_SAME
;
545 to_gs_p
->slash_alt
= 0;
549 from_note_p
= &(from_gs_p
->notelist
[n
]);
550 if (Doing_tab_staff
== YES
) {
551 /* fret, nticks, and bendstring exist in from_note_p
552 * in an internal format, whereas add_note() needs them
553 * in something close to user input format,
554 * so we have to reconstruct
555 * what the user input must have been. */
556 add_note(to_gs_p
, from_gs_p
->notelist
[n
].letter
,
557 from_note_p
->accidental
,
558 TMP_FRET(from_note_p
),
559 TMP_NTICKS(from_note_p
),
560 from_note_p
->acc_has_paren
,
561 (HASBEND(from_gs_p
->notelist
[n
])
562 ?
bend_string(from_note_p
)
566 add_note(to_gs_p
, from_gs_p
->notelist
[n
].letter
,
567 from_note_p
->accidental
,
570 from_note_p
->acc_has_paren
,
574 /* copy remaining note attributes: tie, slur, etc */
575 to_note_p
= &(to_gs_p
->notelist
[to_gs_p
->nnotes
- 1]);
576 to_note_p
->tie
= from_note_p
->tie
;
577 to_note_p
->tiestyle
= from_note_p
->tiestyle
;
578 to_note_p
->tiedir
= from_note_p
->tiedir
;
579 to_note_p
->nslurto
= from_note_p
->nslurto
;
580 if (from_note_p
->nslurto
> 0) {
581 /* slurto lists cannot be safely shared, so make copy */
582 MALLOC(SLURTO
, to_note_p
->slurtolist
,
583 from_note_p
->nslurto
);
584 (void) memcpy(to_note_p
->slurtolist
,
585 from_note_p
->slurtolist
,
586 sizeof(struct SLURTO
) *
587 from_note_p
->nslurto
);
590 to_note_p
->slurtolist
= (struct SLURTO
*) 0;
592 to_note_p
->notesize
= from_note_p
->notesize
;
593 to_note_p
->note_has_paren
= from_note_p
->note_has_paren
;
594 to_note_p
->is_bend
= from_note_p
->is_bend
;
595 to_note_p
->smallbend
= from_note_p
->smallbend
;
599 /* When done with temporary map data, clean everything up, to prepare
600 * for potentially getting another set of data */
606 /* free up the lists */
609 /* reset pointers to be ready for more data */
610 Map_p
= (struct MAP
*) 0;
611 End_map_p_p
= &Map_p
;
615 /* free up the MAP list and everything hanging off of it */
623 if (map_p
== (struct MAP
*) 0) {
628 /* free the list hanging off of this struct */
629 free_notemaps(map_p
->notemap_p
);
632 free_maps(map_p
->next
);
634 /* free the passed-in struct */
638 /* free up a NOTEMAP list and everything hanging off of it */
641 free_notemaps(notemap_p
)
643 struct NOTEMAP
*notemap_p
;
646 if (notemap_p
== (struct NOTEMAP
*) 0) {
650 free_sv_list(notemap_p
->svlist_p
);
651 free_notemaps(notemap_p
->next
);
656 /* Given a number of notes, find the NOTEMAP list for that many and return it.
657 * If not found, return 0. */
659 static struct NOTEMAP
*
660 find_notemap(num_notes
)
667 for (m_p
= Map_p
; m_p
!= (struct MAP
*) 0; m_p
= m_p
->next
) {
668 if (m_p
->num_entries
== num_notes
) {
669 return(m_p
->notemap_p
);
673 l_yyerror(Curr_filename
, yylineno
,
674 "there is no bracketed mapping for chords containing %d note%s", num_notes
, num_notes
== 1 ?
"" : "s");
675 return ((struct NOTEMAP
*) 0);
679 /* Once a measure-worth of data is gathered for one or more staffs/voices,
680 * link copies onto the appropriate STAFF structs */
686 /* if haven't yet set up the STAFFs for this measure, do so now */
689 /* if we are in this function, user specified some music data */
693 /* do error check--can't have notes and multirest in same measure */
694 if (Got_multirest
== 1) {
699 /* Do either chord-to-voice-mapping or standard voice mapping,
701 if (map_groups() == NO
) {
705 /* re-initialize for next measure */
706 Curr_gs_list_p
= (struct GRPSYL
*) 0;
711 /* Go through Svrangelist, creating copies of the GRPSYL lists and
712 * linking them to the appropriate STAFFs. */
718 struct SVRANGELIST
*svr_p
; /* list of ranges of staffs and vnos */
719 register int s
; /* staff index */
720 register int v
; /* voice index */
721 struct RANGELIST
*sr_p
; /* range of staffs being defined */
722 struct RANGELIST
*vr_p
; /* range of vno's being defined */
723 int copies
= 0; /* how many copies of grpsyl list made so far */
726 for (svr_p
= Svrangelist_p
; svr_p
!= (struct SVRANGELIST
*) 0;
727 svr_p
= svr_p
->next
) {
729 for (sr_p
= svr_p
->stafflist_p
; sr_p
!= (struct RANGELIST
*) 0;
732 for (s
= sr_p
->begin
; s
<= sr_p
->end
; s
++) {
734 for (vr_p
= svr_p
->vnolist_p
;
735 vr_p
!= (struct RANGELIST
*) 0;
738 for (v
= vr_p
->begin
;
739 v
<= vr_p
->end
; v
++) {
740 link_a_grouplist(s
, v
, copies
++);
749 /* connect list of GRPSYLs to a staff. If copies == 0, use the current
750 * grpsyl list, otherwise make a copy of it and use the copy */
753 link_a_grouplist(staffno
, vno
, copies
)
757 int copies
; /* if non-zero, need to make a copy */
760 if (rangecheck(staffno
, MINSTAFFS
, Score
.staffs
, "staff number")
765 if (rangecheck(vno
, MINVOICES
, MAXVOICES
, "voice number") == NO
) {
769 if (Staffmap_p
[staffno
] == (struct MAINLL
*) 0) {
773 if (Staffmap_p
[staffno
]->u
.staff_p
== (struct STAFF
*) 0) {
774 pfatal("null staff pointer while linking group list");
777 if (Staffmap_p
[staffno
]->u
.staff_p
->groups_p
[vno
-1]
778 != (struct GRPSYL
*) 0) {
779 mult_def(staffno
, vno
);
783 /* the first time through, we can use the
784 * existing list. After that we need to
785 * make a clone of the list */
787 (Staffmap_p
[staffno
])->u
.staff_p
->groups_p
[vno
-1]
789 convert_rest_space(Staffmap_p
[staffno
]->u
.
790 staff_p
->groups_p
[vno
-1], staffno
, vno
);
793 (Staffmap_p
[staffno
])->u
.staff_p
->groups_p
[vno
-1]
794 = clone_gs_list(Curr_gs_list_p
, YES
);
799 /* With chord-at-a-time input style, it is legal to have
800 * a mixture of pitches, spaces, and rests. However, once
801 * everything has been distributed to individual voices, we need to check
802 * that there aren't still any mixtures, and convert the rest and
803 * space pseudo-notes into rest and space groups. Some error checks
804 * also get done that couldn't be done till after this conversion. */
807 convert_rest_space(grpsyl_p
, staffno
, vno
)
809 struct GRPSYL
*grpsyl_p
;
814 for ( ; grpsyl_p
!= (struct GRPSYL
*) 0; grpsyl_p
= grpsyl_p
->next
) {
815 conv_grpsyl(grpsyl_p
, staffno
, vno
);
820 /* Given a GRPSYL, convert all the rest and space
821 * pseudo notes to groups and do related error checking */
824 conv_grpsyl(grpsyl_p
, staffno
, vno
)
826 struct GRPSYL
*grpsyl_p
;
831 int notes
, rests
, spaces
, rpts
;/* count how many of each in chord */
832 int n
; /* index through notes */
834 /* Count how many notes, rests, and spaces in the group */
835 rests
= spaces
= notes
= rpts
= 0;
836 for (n
= 0; n
< grpsyl_p
->nnotes
; n
++) {
837 if (grpsyl_p
->notelist
[n
].letter
== PP_REST
) {
840 else if (grpsyl_p
->notelist
[n
].letter
== PP_SPACE
) {
843 else if (grpsyl_p
->notelist
[n
].letter
== PP_RPT
) {
851 /* Group may not mix space, rest, rpt, and notes */
852 if (spaces
> 0 && spaces
!= grpsyl_p
->nnotes
) {
853 l_yyerror(grpsyl_p
->inputfile
, grpsyl_p
->inputlineno
,
854 "staff %d voice %d: mixture of space and non-space",
858 if (rests
> 0 && rests
!= grpsyl_p
->nnotes
) {
859 l_yyerror(grpsyl_p
->inputfile
, grpsyl_p
->inputlineno
,
860 "staff %d voice %d: mixture of rest and non-rest",
864 if (rpts
> 0 && rpts
!= grpsyl_p
->nnotes
) {
865 l_yyerror(grpsyl_p
->inputfile
, grpsyl_p
->inputlineno
,
866 "staff %d voice %d: mixture of rpt and non-rpt",
871 /* convert rest, space, and rpt pseudo-notes to groups */
872 if (notes
< grpsyl_p
->nnotes
) {
874 /* This is actually a rest group */
875 grpsyl_p
->grpcont
= GC_REST
;
877 /* If entire group was marked cue, leave it that way.
878 * Otherwise, if multiple rests map to this group,
879 * grpsize should be the biggest of them.
880 * So initialize to small size,
881 * and if we find any normal size,
882 * set to normal and jump out of the loop. */
883 if (grpsyl_p
->grpsize
!= GS_SMALL
) {
884 grpsyl_p
->grpsize
= GS_SMALL
;
885 for (n
= 0; n
< grpsyl_p
->nnotes
; n
++) {
886 if (grpsyl_p
->notelist
[n
].notesize
== GS_NORMAL
) {
888 grpsyl_p
->grpsize
= GS_NORMAL
;
894 else if (spaces
> 0) {
895 /* This is actually a space group */
896 grpsyl_p
->grpcont
= GC_SPACE
;
898 /* Uncompressibility was temporarily saved
899 * in octave, so move it now. If multiple spaces
900 * mapped to this group, if any of them are
901 * uncompressible, make the group uncompressible. */
902 for (n
= 0; n
< grpsyl_p
->nnotes
; n
++) {
903 if (grpsyl_p
->notelist
[n
].octave
== YES
) {
904 grpsyl_p
->uncompressible
= YES
;
910 /* This is actually a rpt. Internally, that is stored
911 * as a note group with no notes (nnotes gets zeroed
912 * a few lines down from here). This should
913 * already be notes but doesn't hurt to set again. */
914 grpsyl_p
->grpcont
= GC_NOTES
;
916 if (grpsyl_p
->notelist
[0].slurtolist
!= (struct SLURTO
*) 0) {
917 l_yyerror(grpsyl_p
->inputfile
, grpsyl_p
->inputlineno
,
918 "can't have slur on rest, space, or rpt");
920 free_notelist(grpsyl_p
);
921 grpsyl_p
->notelist
= 0;
922 grpsyl_p
->nnotes
= 0;
925 if (grpsyl_p
->grpcont
== GC_NOTES
) {
926 if (grpsyl_p
->is_meas
== YES
&& grpsyl_p
->nnotes
> 0) {
927 l_yyerror(grpsyl_p
->inputfile
, grpsyl_p
->inputlineno
,
928 "'m' can only be used with rest, space, or rpt, not notes");
933 /* grace can only apply to notes */
934 if (grpsyl_p
->grpvalue
== GV_ZERO
&& (grpsyl_p
->grpcont
!= GC_NOTES
||
935 grpsyl_p
->nnotes
== 0)) {
936 l_yyerror(grpsyl_p
->inputfile
, grpsyl_p
->inputlineno
,
937 "grace can only be used with notes");
942 /* If first group of a measure has no time value specified, we have to use
943 * the default. This is complicated by the fact that the user could be
944 * defining mulitples staffs/voices at once. If they are, we need to make
945 * sure that all of them have the same default. */
948 get_dflt_timeunit_ssv()
951 struct MAP
*map_p
; /* list of maps */
952 struct NOTEMAP
*notemap_p
; /* list of notemaps per map */
953 struct SVRANGELIST
*svr_p
; /* list of staff/voice ranges */
954 struct RANGELIST
*sr_p
; /* list of staffs being defined */
955 struct RANGELIST
*vr_p
; /* list of voices being defined */
956 int s
; /* staff number */
958 int got_one
= NO
; /* YES if have found a dflt value */
959 RATIONAL this_timeunit
; /* value for current staff/voice */
960 RATIONAL dflt_timeunit
; /* the default time unit to use */
961 struct SSV
*tu_ssv_p
; /* SSV containing relevent timeunit */
962 struct SSV
*ref_ssv_p
; /* SSV we had checked on prev
963 * staff/voice being defined together */
966 /* If doing voice-at-a-time input, use the special MAP for that case,
967 * otherwise use the Map_p */
968 if (Map_p
== (struct MAP
*) 0) {
969 map_p
= &Voice_at_a_time_map
;
970 map_p
->notemap_p
->svlist_p
= Svrangelist_p
;
976 /* score value is the ultimate default */
977 dflt_timeunit
= Score
.timeunit
;
978 tu_ssv_p
= ref_ssv_p
= &Score
;
980 /* check each map/notemap/svrangelist/svrange/staff/voice combination */
981 for ( ; map_p
!= (struct MAP
*) 0; map_p
= map_p
->next
) {
982 for (notemap_p
= map_p
->notemap_p
;
983 notemap_p
!= (struct NOTEMAP
*) 0;
984 notemap_p
= notemap_p
->next
) {
985 for (svr_p
= notemap_p
->svlist_p
;
986 svr_p
!= (struct SVRANGELIST
*) 0;
987 svr_p
= svr_p
->next
) {
988 for (sr_p
= svr_p
->stafflist_p
;
989 sr_p
!= (struct RANGELIST
*) 0;
991 for (s
= sr_p
->begin
; s
<= sr_p
->end
; s
++) {
992 for (vr_p
= svr_p
->vnolist_p
;
993 vr_p
!= (struct RANGELIST
*) 0;
995 for (v
= vr_p
->begin
; v
<= vr_p
->end
; v
++) {
997 /* find default timeunit for
998 * this staff/voice */
999 tu_ssv_p
= vvpath(s
, v
, TIMEUNIT
);
1000 this_timeunit
= tu_ssv_p
->timeunit
;
1002 if (got_one
== NO
) {
1003 /* now we have one to
1004 * compare against */
1005 dflt_timeunit
= this_timeunit
;
1006 ref_ssv_p
= tu_ssv_p
;
1009 else if ( NE(this_timeunit
, dflt_timeunit
)
1011 tu_ssv_p
->timelist_p
,
1012 ref_ssv_p
->timelist_p
)
1014 yyerror("timeunit value must be the same for all staffs being defined on the same input line");
1028 /* Return YES if the given lists are equivalent, NO if they aren't. */
1031 timelists_equal(list1_p
, list2_p
)
1033 struct TIMELIST
*list1_p
;
1034 struct TIMELIST
*list2_p
;
1037 for ( ; list1_p
!= 0 && list2_p
!= 0;
1038 list1_p
= list1_p
->next
, list2_p
= list2_p
->next
) {
1039 if ( NE(list1_p
->fulltime
, list2_p
->fulltime
) ) {
1043 return((list1_p
== 0 && list2_p
== 0) ? YES
: NO
);
1047 /* Return YES if the current staff range is for all tablature staffs.
1048 * Return NO if not. If there are a mixture, this is an error, so print
1049 * a message. It still returns NO in this case, so if the user wanted tab,
1050 * they may get a lot of errors. Oh well. After all, they did make an error.
1058 struct NOTEMAP
*notemap_p
;
1059 struct SVRANGELIST
*svr_p
;
1060 struct RANGELIST
*sr_p
;
1061 int s
; /* staff number */
1062 int found_tab_staff
= NO
;
1063 int found_non_tab_staff
= NO
;
1065 /* If doing voice-at-a-time input, use the special MAP for that case,
1066 * otherwise use the Map_p */
1067 if (Map_p
== (struct MAP
*) 0) {
1068 map_p
= &Voice_at_a_time_map
;
1069 map_p
->notemap_p
->svlist_p
= Svrangelist_p
;
1075 /* check each map/notemap/svrangelist/svrange/staff/voice combination */
1076 for ( ; map_p
!= (struct MAP
*) 0; map_p
= map_p
->next
) {
1077 for (notemap_p
= map_p
->notemap_p
;
1078 notemap_p
!= (struct NOTEMAP
*) 0;
1079 notemap_p
= notemap_p
->next
) {
1080 for (svr_p
= notemap_p
->svlist_p
;
1081 svr_p
!= (struct SVRANGELIST
*) 0;
1082 svr_p
= svr_p
->next
) {
1083 for (sr_p
= svr_p
->stafflist_p
;
1084 sr_p
!= (struct RANGELIST
*) 0;
1085 sr_p
= sr_p
->next
) {
1086 for (s
= sr_p
->begin
; s
<= sr_p
->end
; s
++) {
1087 if (is_tab_staff(s
) == YES
) {
1088 found_tab_staff
= YES
;
1091 found_non_tab_staff
= YES
;
1099 if (found_tab_staff
== YES
&& found_non_tab_staff
== YES
) {
1100 yyerror("mixture of tab and non-tab staffs not allowed");
1103 return(found_tab_staff
);
1107 /* When two notes in a chord are duplicates from chord-at-a-time input,
1108 * we want to merge the notes, and get rid of the extra. This function will
1109 * change the value of gs_p->nnotes and the size of the notelist array. */
1112 merge_dup_notes(gs_p
, n
)
1114 struct GRPSYL
*gs_p
; /* remove duplicate from here */
1115 int n
; /* merge note n and n+1 into slot n, then remove
1116 * the note in slot n+1 by moving any remaining
1121 int sn
, sn1
; /* slurto index */
1122 struct NOTE
*note_p
, *extra_p
;
1125 /* get shorter names for what we will use a lot */
1126 note_p
= &(gs_p
->notelist
[n
]);
1127 extra_p
= &(gs_p
->notelist
[n
+1]);
1128 /* Merge the data between the two as best we can.
1129 * In general, if one has a "stronger" version of some attribute,
1130 * go with that one. We check the second; if it is "stronger",
1131 * force the result to that--if it was already set the same, fine--
1132 * probably faster to just assign than check and maybe assign.
1133 * If second wasn't stronger, go with whatever the first was. */
1135 /* If one is normal, one small, override the small */
1136 if (extra_p
->notesize
== GS_NORMAL
) {
1137 note_p
->notesize
= GS_NORMAL
;
1140 /* If either has a tie, do a tie */
1141 if (extra_p
->tie
== YES
) {
1144 /* Consider normal tie the strongest, then dashed, then dotted */
1145 if (extra_p
->tiestyle
== L_NORMAL
) {
1146 note_p
->tiestyle
= L_NORMAL
;
1148 else if (extra_p
->tiestyle
== L_DASHED
&&
1149 note_p
->tiestyle
!= L_NORMAL
) {
1150 note_p
->tiestyle
= L_DASHED
;
1152 if ( (extra_p
->tiedir
== UP
&& note_p
->tiedir
== DOWN
) ||
1153 (extra_p
->tiedir
== DOWN
&& note_p
->tiedir
== UP
)) {
1154 /* It would be nice to allow both up and down tie,
1155 * especially since we can do that for slurs,
1156 * but we only support one tie per note. */
1157 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
1158 "duplicate notes with opposite tie direction not allowed");
1160 else if (extra_p
->tiedir
!= UNKNOWN
) {
1161 note_p
->tiedir
= extra_p
->tiedir
;
1165 /* Parentheses around an accidental means "just in case you forgot..."
1166 * which is weaker than no parentheses, so only use parentheses if
1168 if (extra_p
->acc_has_paren
== NO
) {
1169 note_p
->acc_has_paren
= NO
;
1171 /* Parentheses around a note generally means the note is optional.
1172 * An optional merged with a non-optional, is non-optional. */
1173 if (extra_p
->note_has_paren
== NO
) {
1174 note_p
->note_has_paren
= NO
;
1177 /* Sorry, we don't deal with incompatible bends */
1178 if (note_p
->is_bend
!= extra_p
->is_bend
||
1179 extra_p
->smallbend
!= note_p
->smallbend
) {
1180 l_yyerror(gs_p
->inputfile
, gs_p
->inputlineno
,
1181 "duplicate notes with bend mismatch not allowed");
1184 /* Slurs... If duplicate between the two slurto lists, just leave
1185 * the one, but use strongest slurstyle. If there is one in the
1186 * NOTE to be deleted but not in the one to keep, move it. */
1187 for (sn1
= 0; sn1
< extra_p
->nslurto
; sn1
++) {
1188 for (sn
= 0; sn
< note_p
->nslurto
; sn
++) {
1189 if (note_p
->slurtolist
[sn
].letter
==
1190 extra_p
->slurtolist
[sn1
].letter
&&
1191 note_p
->slurtolist
[sn
].slurdir
==
1192 extra_p
->slurtolist
[sn1
].slurdir
&&
1193 note_p
->slurtolist
[sn
].octave
==
1194 extra_p
->slurtolist
[sn1
].octave
) {
1195 /* duplicate; just fix style if necessary */
1196 if (extra_p
->slurtolist
[sn1
].slurstyle
1198 note_p
->slurtolist
[sn
].slurstyle
1201 else if (extra_p
->slurtolist
[sn1
].slurstyle
1203 note_p
->slurtolist
[sn
].slurstyle
1205 note_p
->slurtolist
[sn
].slurstyle
1211 if (sn
== note_p
->nslurto
) {
1212 /* wasn't on the list to keep, so add it */
1213 add_slurto(gs_p
, extra_p
->slurtolist
[sn1
].letter
,
1214 extra_p
->slurtolist
[sn1
].octave
,
1216 extra_p
->slurtolist
[sn1
].slurstyle
);
1220 /* Move things down in the notelist to remove the extra */
1221 for (i
= n
+ 1; i
< gs_p
->nnotes
- 1; i
++) {
1222 gs_p
->notelist
[i
] = gs_p
->notelist
[i
+1];
1225 REALLOC(NOTE
, gs_p
->notelist
, gs_p
->nnotes
);
1229 /* print error message for multiply defined voice */
1232 mult_def(staff
, voice
)
1238 l_yyerror(Curr_filename
, yylineno
,
1239 "staff %d voice %d multiply defined (first defined on line %d)",
1241 Staffmap_p
[staff
]->u
.staff_p
->groups_p
[voice
-1]->inputlineno
);