1 /* Copyright (c) 1997, 1998, 2000, 2001, 2002, 2004 by Arkkra Enterprises */
2 /* All rights reserved */
6 * Description: This file contains functions for translating tablature staffs
7 * to their corresponding tabnote staffs.
15 * Define a temp structure for holding info about the note generated from a
16 * NOTE on a tablature staff.
19 char letter
; /* 'a' to 'g' */
20 char accidental
; /* '\0', 'x', '#', 'n', '&', 'B'(double flat)*/
21 int octave
; /* 0 to 9 */
22 int hs
; /* half steps above c0 */
23 int strno
; /* the string this note is played on */
24 struct NOTE
*note_p
; /* point to the NOTE this is derived from */
27 static void tabv2tabnotev
P((struct MAINLL
*mainll_p
, int vidx
));
28 static void fixprevmeas
P((struct GRPSYL
*ngs_p
, struct MAINLL
*mll_p
));
29 static int hasprebend
P((struct GRPSYL
*gs_p
));
30 static int cancombine
P((struct MAINLL
*mll_p
, struct GRPSYL
*tgs_p
,
32 static RATIONAL calctime
P((struct GRPSYL
*gs_p
));
33 static void translate_group
P((struct GRPSYL
*tgs_p
, struct GRPSYL
*pregs_p
,
34 struct GRPSYL
*ngs_p
, struct MAINLL
*mll_p
, int combine
));
35 static void calcnote
P((struct STRINGINFO
*sinfo_p
, int fretno
, RATIONAL bend
,
36 int sharps
, struct TABNOTENOTE
*note_p
, struct GRPSYL
*tgs_p
));
37 static int findfret
P((struct GRPSYL
*tgs_p
, struct MAINLL
*mll_p
, int strno
));
38 static void popnotes
P((struct GRPSYL
*gs_p
, struct TABNOTENOTE tnn
[],
39 int ntnn
, struct GRPSYL
*tgs_p
, struct MAINLL
*mll_p
,
40 int is_prebend
, int combine
, int sharps
));
41 static int neighbor
P((struct TABNOTENOTE
*high_p
, struct TABNOTENOTE
*low_p
));
42 static int inkeysig
P((struct TABNOTENOTE
*note_p
, int sharps
));
43 static int upletter
P((struct TABNOTENOTE
*note_p
));
44 static int downletter
P((struct TABNOTENOTE
*note_p
));
45 static void cleanaccs
P((struct GRPSYL
*gs_p
, struct MAINLL
*mll_p
));
50 * Abstract: Populate tabnote staffs' voices from corresponding tab voices.
54 * Description: This function loops through the MLL looking for tab staffs.
55 * For each it does some work, but the main thing is that it loops
56 * through each voice and calls tabv2tabnotev() for each GRPSYL
57 * list. That function populates the corresponding tabnote voice.
64 struct MAINLL
*mainll_p
; /* point along main linked list */
65 struct STAFF
*nstaff_p
; /* tabnote STAFF */
66 struct GRPSYL
*ngs_p
; /* tabnote GRPSYL */
70 debug(2, "tab2tabnote");
73 for (mainll_p
= Mainllhc_p
; mainll_p
!= 0; mainll_p
= mainll_p
->next
) {
75 if (mainll_p
->str
== S_SSV
) {
76 asgnssv(mainll_p
->u
.ssv_p
); /* keep SSVs up to date */
80 /* if not a tab staff, there's nothing to do */
81 if (mainll_p
->str
!= S_STAFF
||
82 is_tab_staff(mainll_p
->u
.staff_p
->staffno
) == NO
) {
87 * The previous staff must be a tabnote staff. Set pointers to
88 * this tabnote staff and its first voice's first GRPSYL.
90 nstaff_p
= mainll_p
->prev
->u
.staff_p
;
91 ngs_p
= nstaff_p
->groups_p
[0];
94 * If this is a multirest, adjust any octave marks in progress.
96 if (ngs_p
->basictime
< -1 &&
97 Octave_bars
[nstaff_p
->staffno
] > 0) {
99 /* add negative bars plus 1; barline will count as 1 */
100 Octave_bars
[nstaff_p
->staffno
] += ngs_p
->basictime
+ 1;
102 /* if whole octave stuff is done, re-init */
103 if (Octave_bars
[nstaff_p
->staffno
] < 0) {
104 Octave_bars
[nstaff_p
->staffno
] = 0;
105 Octave_count
[nstaff_p
->staffno
] = 0.0;
106 Octave_adjust
[nstaff_p
->staffno
] = 0;
110 /* loop through all possible voices, populating tabnote */
111 for (vidx
= 0; vidx
< MAXVOICES
; vidx
++) {
112 tabv2tabnotev(mainll_p
, vidx
);
118 * Name: tabv2tabnotev()
120 * Abstract: Populate a tabnote voice from its corresponding tab voice.
124 * Description: This function populates a tabnote GRPSYL list based on its
125 * corresponding tab GRPSYL list, after making sure that the voice
130 tabv2tabnotev(mainll_p
, vidx
)
132 struct MAINLL
*mainll_p
; /* main LL struct for this staff */
133 int vidx
; /* voice index, 0 to MAXVOICES-1 */
136 struct STAFF
*tstaff_p
; /* tablature STAFF */
137 struct STAFF
*nstaff_p
; /* tabnote STAFF */
138 struct GRPSYL
*tgs_p
; /* tablature GRPSYL */
139 struct GRPSYL
*ngs_p
; /* tabnote GRPSYL */
140 struct GRPSYL
*nngs_p
; /* next tabnote GRPSYL */
141 struct GRPSYL
*gs_p
; /* newly allocated GRPSYL */
142 struct GRPSYL
*pregs_p
; /* GRPSYL for prebend's grace group */
143 int combine
; /* should two groups be combined? */
144 RATIONAL totdur
; /* total duration of combined groups */
145 int n
; /* loop variable */
146 char *acc_p
; /* pointer to accidental string */
150 * Set pointers to the tablature staff's STAFF structure and the first
151 * GRPSYL in the voice we're working on.
153 tstaff_p
= mainll_p
->u
.staff_p
;
154 tgs_p
= tstaff_p
->groups_p
[vidx
];
156 /* if this voice doesn't exist, there is nothing to copy to tabnote */
162 * The previous staff must be a tabnote staff. Set pointers to this
163 * tabnote staff and the first GRPSYL of the given voice.
165 nstaff_p
= mainll_p
->prev
->u
.staff_p
;
166 ngs_p
= nstaff_p
->groups_p
[vidx
];
168 /* tabnote staff must have at least as many voices as tab staff */
170 l_ufatal(tgs_p
->inputfile
, tgs_p
->inputlineno
,
171 "tab staff %d has a voice %d, but tabnote staff %d doesn't; change vscheme for tabnote staff",
172 nstaff_p
->staffno
+ 1, vidx
+ 1, nstaff_p
->staffno
);
176 * If the tabnote staff/voice doesn't have a measure space, it was
177 * manually entered, and we will leave it alone. However, it is
178 * possible that this staff/voice in the previous measure was
179 * generated, and that the last GRPSYL there had note(s) that were to
180 * slide to our GRPSYL. If so, that slurtolist needs to be adjusted.
182 if (ngs_p
->is_meas
== NO
|| ngs_p
->grpcont
!= GC_SPACE
) {
183 fixprevmeas(ngs_p
, mainll_p
->prev
);
187 FREE(ngs_p
); /* throw away the measure space */
190 * Loop once for each GRPSYL in this measure on the tablature staff/
191 * voice. Usually, for each one found, we allocate one for the tabnote
192 * staff/voice. But in cases involving prebends, we allocate a second
193 * one, since they translate to a grace note (in parentheses) and a
194 * normal note. And in certain cases of bends of <= 1/4 step, we don't
195 * allocate any, since we combine the two notes into one.
198 for ( ; tgs_p
!= 0; tgs_p
= tgs_p
->next
) {
200 * If this group was combined into the previous group because
201 * of 1/4 step bends, we don't allocate any group now.
209 * Check whether any of the notes in this tab group have
210 * prebends. If so, allocate a special GRPSYL for the grace
211 * note(s) in parentheses before the main group. Link it and
214 if (hasprebend(tgs_p
)) {
215 CALLOC(GRPSYL
, pregs_p
, 1);
216 if (tgs_p
== tstaff_p
->groups_p
[vidx
]) {
217 /* first GRPSYL in list; no previous one, */
218 /* staff points at us */
220 nstaff_p
->groups_p
[vidx
] = pregs_p
;
222 /* a later one; set both links */
223 pregs_p
->prev
= ngs_p
;
224 ngs_p
->next
= pregs_p
;
226 pregs_p
->next
= 0; /* last one so far */
229 /* set fields unless they'd be just hardcoded 0 */
230 pregs_p
->inputlineno
= tgs_p
->inputlineno
;
231 pregs_p
->inputfile
= tgs_p
->inputfile
;
232 pregs_p
->staffno
= nstaff_p
->staffno
;
233 pregs_p
->vno
= vidx
+ 1;
234 pregs_p
->grpsyl
= GS_GROUP
;
235 pregs_p
->basictime
= 4; /* stemless 1/4 note */
236 pregs_p
->is_meas
= NO
;
237 pregs_p
->tuploc
= NOITEM
;
238 pregs_p
->fulltime
= Zero
;
239 pregs_p
->grpcont
= GC_NOTES
;
240 pregs_p
->grpvalue
= GV_ZERO
;
241 pregs_p
->grpsize
= GS_SMALL
;
242 pregs_p
->headshape
= HS_UNKNOWN
;
243 pregs_p
->clef
= NOCLEF
;
244 pregs_p
->beamloc
= NOITEM
;
245 pregs_p
->beamto
= CS_SAME
;
246 pregs_p
->stemto
= CS_SAME
;
248 pregs_p
->roll
= NOITEM
;
249 pregs_p
->ho_usage
= HO_NONE
;
250 /* nnotes and notelist get set later */
252 pregs_p
= 0; /* no prebend grace */
256 * Allocate a GRPSYL. Initialize it to be the same as the tab
257 * GRPSYL, since most fields are the same. Later we'll change
258 * the ones that are different. Link it appropriately to the
259 * staff (if it's the first one) or else the previous GRPSYL.
261 CALLOC(GRPSYL
, gs_p
, 1);
263 if (tgs_p
== tstaff_p
->groups_p
[vidx
] && pregs_p
== 0) {
264 /* first one; no previous one, staff points at us */
266 nstaff_p
->groups_p
[vidx
] = gs_p
;
268 /* later one; set both links */
272 gs_p
->next
= 0; /* last one so far */
273 ngs_p
= gs_p
; /* use ngs_p var for new one */
275 /* set the correct staff number */
276 ngs_p
->staffno
= nstaff_p
->staffno
;
278 /* can't share same withlist because fonts may be */
279 /* changed in them differently later */
280 clone_withlist(ngs_p
, tgs_p
);
282 /* notelist will be reset later; nnotes might change */
284 combine
= cancombine(mainll_p
, tgs_p
, &totdur
);
286 /* calc basictime and dots of combined note */
287 ngs_p
->basictime
= reconstruct_basictime(totdur
);
288 ngs_p
->dots
= recalc_dots(totdur
, ngs_p
->basictime
);
290 /* combine fulltime (works even for tuplets) */
291 ngs_p
->fulltime
= radd(tgs_p
->fulltime
,
292 tgs_p
->next
->fulltime
);
295 if (tgs_p
->grpcont
== GC_NOTES
&& ! is_mrpt(ngs_p
)) {
296 translate_group(tgs_p
, pregs_p
, ngs_p
,
302 * For measure repeats, mark the staff and get out. If there is more
303 * than one voice, each will hit this code, but that's okay.
305 if (is_mrpt(ngs_p
)) {
306 nstaff_p
->mrptnum
= tstaff_p
->mrptnum
;
310 /* blow away unneeded accidentals */
311 cleanaccs(nstaff_p
->groups_p
[vidx
], mainll_p
->prev
);
314 * Because we may have combined some groups, we might have lost the
315 * STARTITEM or ENDITEM of some beamed groups. So find this situation
316 * and fix it. This can only affect nongrace groups, so ignore grace
319 ngs_p
= nstaff_p
->groups_p
[vidx
]; /* first group in measure */
320 if (ngs_p
->grpvalue
== GV_ZERO
) /* if grace, */
321 ngs_p
= nextnongrace(ngs_p
); /* get first nongrace*/
323 for ( ; ngs_p
!= 0; ngs_p
= nngs_p
) {
324 /* get the next group, if any, excluding graces */
325 nngs_p
= nextnongrace(ngs_p
);
328 * For this and the next group, if it's a quarter or longer,
329 * make sure it won't get beamed.
331 if (ngs_p
->basictime
<= 4)
332 ngs_p
->beamloc
= NOITEM
;
333 if (nngs_p
!= 0 && nngs_p
->basictime
<= 4)
334 nngs_p
->beamloc
= NOITEM
;
336 /* based on this and next group, change this group */
337 switch (ngs_p
->beamloc
) {
340 nngs_p
->beamloc
== STARTITEM
||
341 nngs_p
->beamloc
== NOITEM
)
342 ngs_p
->beamloc
= NOITEM
;
346 nngs_p
->beamloc
== STARTITEM
||
347 nngs_p
->beamloc
== NOITEM
)
348 ngs_p
->beamloc
= ENDITEM
;
353 if (nngs_p
->beamloc
== INITEM
)
354 nngs_p
->beamloc
= STARTITEM
;
355 else if (nngs_p
->beamloc
== ENDITEM
)
356 nngs_p
->beamloc
= NOITEM
;
363 * Now we have start and end items on every beamed set, but it is
364 * possible that some of them are rests (if there were rests embedded
365 * in the original set). So revise to get them out of there.
367 ngs_p
= nstaff_p
->groups_p
[vidx
]; /* first group in measure */
368 if (ngs_p
->grpvalue
== GV_ZERO
) /* if grace, */
369 ngs_p
= nextnongrace(ngs_p
); /* get first nongrace*/
371 for ( ; ngs_p
!= 0; ngs_p
= nextnongrace(ngs_p
)) {
372 int notegroups
; /* number in this set */
373 struct GRPSYL
*end_p
; /* point at the enditem */
375 if (ngs_p
->beamloc
!= STARTITEM
)
378 * We found a startitem; count how many note groups in the set.
379 * Also set end_p to point at the end item in case we need it
383 end_p
= 0; /* avoid useless warnings */
384 for (nngs_p
= ngs_p
; nngs_p
!= 0 &&
385 (nngs_p
->prev
== 0 ||
386 nngs_p
->prev
->beamloc
!= ENDITEM
);
387 nngs_p
= nextnongrace(nngs_p
)) {
388 if (nngs_p
->grpcont
== GC_NOTES
)
393 if (notegroups
<= 1) {
394 /* 0 or 1 note groups; blow away the set */
395 for (nngs_p
= ngs_p
; nngs_p
!= 0 &&
396 (nngs_p
->prev
== 0 ||
397 nngs_p
->prev
->beamloc
!=ENDITEM
);
398 nngs_p
= nextnongrace(nngs_p
)) {
399 nngs_p
->beamloc
= NOITEM
;
403 * There are at least two note groups, so we will keep
404 * the set, but we may need to move the endpoints to
407 /* remove any rests at the start */
408 for (nngs_p
= ngs_p
; nngs_p
->grpcont
== GC_REST
;
409 nngs_p
= nextnongrace(nngs_p
)) {
410 nngs_p
->beamloc
= NOITEM
;
412 nngs_p
->beamloc
= STARTITEM
;
413 /* remove any rests at the end */
414 for (nngs_p
= end_p
; nngs_p
->grpcont
== GC_REST
;
415 nngs_p
= prevnongrace(nngs_p
)) {
416 nngs_p
->beamloc
= NOITEM
;
418 nngs_p
->beamloc
= ENDITEM
;
422 /* do beaming of tabnote staff based on beamstyle */
423 if (has_cust_beaming(nstaff_p
->groups_p
[vidx
]) == NO
) {
424 do_beaming(nstaff_p
->groups_p
[vidx
], GS_NORMAL
,
425 nstaff_p
->staffno
, vidx
+ 1);
426 do_beaming(nstaff_p
->groups_p
[vidx
], GS_SMALL
,
427 nstaff_p
->staffno
, vidx
+ 1);
431 * When there are octave marks on the tabnote staff, adjust the notes
432 * the opposite way so that the result is correct. Then check to make
433 * sure nothing is out of range.
435 octave_transpose(nstaff_p
, mainll_p
, vidx
, NO
);
437 for (ngs_p
= nstaff_p
->groups_p
[vidx
]; ngs_p
!= 0; ngs_p
= ngs_p
->next
){
438 for (n
= 0; n
< ngs_p
->nnotes
; n
++) {
439 if (ngs_p
->notelist
[n
].octave
< MINOCTAVE
||
440 ngs_p
->notelist
[n
].octave
> MAXOCTAVE
) {
442 acc_p
= ngs_p
->notelist
[n
].accidental
== '\0' ?
443 "" : Acctostr
[strchr(Acclets
, ngs_p
->
444 notelist
[n
].accidental
) - Acclets
];
446 l_ufatal(ngs_p
->inputfile
,
448 "'octave' string on tabnote staff transposes note %c%s to out of range octave %d",
449 ngs_p
->notelist
[n
].letter
,
451 ngs_p
->notelist
[n
].octave
);
458 * Name: fixprevmeas()
460 * Abstract: Fixed unresolved slides in the previous tabnote measure.
464 * Description: This function is called for the first GRPSYL of a manually
465 * entered tabnote measure. If the previous tabnote measure was
466 * generated, it might be trying to slide to a note in our GRPSYL.
467 * If so, its slurtolist would have a string number in place of a
468 * letter and NOFRET for the octave. This function resolves this
469 * to the true letter and octave.
473 fixprevmeas(ngs_p
, mll_p
)
475 struct GRPSYL
*ngs_p
; /* tabnote GRPSYL */
476 struct MAINLL
*mll_p
; /* MLL for this GRPSYL */
479 struct GRPSYL
*prevngs_p
; /* previous GRPSYL */
480 struct SLURTO
*s_p
; /* point at a SLURTO structure */
481 int j
, k
; /* for looping through notes */
484 /* find previous GRPSYL, if any; if not notes, nothing to do */
485 prevngs_p
= prevgrpsyl(ngs_p
, &mll_p
);
486 if (prevngs_p
== 0 || prevngs_p
->grpcont
!= GC_NOTES
)
490 * Check every note in the preceding group. Don't break out after
491 * finding one, since multiple ones could slide to our note. But there
492 * is a max of one slur/bend coming from each note.
494 s_p
= 0; /* prevent useless 'used before set' warning */
495 for (k
= 0; k
< prevngs_p
->nnotes
; k
++) {
496 /* check every slur from that note */
497 for (j
= 0; j
< prevngs_p
->notelist
[k
].nslurto
; j
++) {
498 s_p
= &prevngs_p
->notelist
[k
].slurtolist
[j
];
500 /* only deal with unresolved tabslurs */
501 if (s_p
->letter
< MAXTABLINES
&& s_p
->octave
== NOFRET
)
504 /* if found a tabslur to our GRPSYL */
505 if (j
< prevngs_p
->notelist
[k
].nslurto
) {
506 /* if our GRPSYL has no notes, this is no good */
507 if (ngs_p
->grpcont
!= GC_NOTES
) {
508 l_warning(prevngs_p
->inputfile
,
509 prevngs_p
->inputlineno
,
510 "no note on tabnote staff to slide to from %c%s%d",
511 prevngs_p
->notelist
[k
].letter
,
512 prevngs_p
->notelist
[k
].accidental
== '\0' ?
"" :
513 Acctostr
[ strchr(Acclets
, prevngs_p
->notelist
[k
]
514 .accidental
) - Acclets
],
515 prevngs_p
->notelist
[k
].octave
);
517 prevngs_p
->notelist
[k
].nslurto
= 0;
519 /* if our GRPSYL has >= 2 notes, this is no good */
520 } else if (ngs_p
->nnotes
>= 2) {
521 l_warning(prevngs_p
->inputfile
,
522 prevngs_p
->inputlineno
,
523 "can't slide from %c%s%d because multiple notes in the next group",
524 prevngs_p
->notelist
[k
].letter
,
525 prevngs_p
->notelist
[k
].accidental
== '\0' ?
"" :
526 Acctostr
[ strchr(Acclets
, prevngs_p
->notelist
[k
]
527 .accidental
) - Acclets
],
528 prevngs_p
->notelist
[k
].octave
);
530 prevngs_p
->notelist
[k
].nslurto
= 0;
531 /* there is one note, so we can do the slide */
533 s_p
->letter
= ngs_p
->notelist
[0].letter
;
534 s_p
->octave
= ngs_p
->notelist
[0].octave
;
543 * Abstract: Check whether any of the notes in this group have a prebend.
547 * Description: This function checks whether any of the notes in this group
548 * have a prebend. That's the case where a NOTE structure has
549 * both a fret number and a bend other than "". A bend of "" is
550 * the release of a bend. It will also return NO if this group
551 * is a rest or space.
557 struct GRPSYL
*tgs_p
;
560 int n
; /* for looping through notes */
563 for (n
= 0; n
< tgs_p
->nnotes
; n
++) {
564 /* check for a fret with a nonnull bend */
565 if (tgs_p
->notelist
[n
].FRETNO
!= NOFRET
&&
566 HASREALBEND(tgs_p
->notelist
[n
])) {
577 * Abstract: Check two groups can be joined into one on the tabnote staff.
581 * Description: This function checks whether the two given groups are joined
582 * by 1/4 step or less bends and should be combined into one group
583 * on the tabnote staff. There are a number of other conditions
584 * that must be met for this to be allowed. If the answer is YES,
585 * it sets *comb_p to the total duration, ignoring the effect of
590 cancombine(mll_p
, tgs_p
, comb_p
)
592 struct MAINLL
*mll_p
; /* main linked list structure we are hanging off of */
593 struct GRPSYL
*tgs_p
; /* tablature GRPSYL for the first of the two groups */
594 RATIONAL
*comb_p
; /* for returning total time if combinable */
597 struct GRPSYL
*nexttgs_p
; /* the second GRPSYL */
598 struct GRPSYL
*next2tgs_p
; /* the next one after that */
599 int n
; /* for looping through note lists */
602 /* must be a note group */
603 if (tgs_p
->grpcont
!= GC_NOTES
)
606 /* must not be grace */
607 if (tgs_p
->grpvalue
== GV_ZERO
)
610 for (n
= 0; n
< tgs_p
->nnotes
; n
++) {
611 /* no note can be the destination of a nonnull bend */
612 if (HASREALBEND(tgs_p
->notelist
[n
]))
616 nexttgs_p
= tgs_p
->next
; /* find the next group */
618 /* first group must not be at the end of a measure */
622 /* first and second group must have same number of notes */
623 if (tgs_p
->nnotes
!= nexttgs_p
->nnotes
)
626 /* each pair of notes must be joined by a bend of <= 1/4 step */
627 for (n
= 0; n
< nexttgs_p
->nnotes
; n
++) {
628 if ( ! HASBEND(nexttgs_p
->notelist
[n
]) ||
629 GT(ratbend(&nexttgs_p
->notelist
[n
]), One_fourth
))
633 /* find the following (3rd) group, if there is one */
634 next2tgs_p
= nextgrpsyl(nexttgs_p
, &mll_p
);
636 /* no notes in the second group are allowed to bend into the third */
637 if (next2tgs_p
!= 0) {
638 for (n
= 0; n
< next2tgs_p
->nnotes
; n
++) {
639 if (HASBEND(next2tgs_p
->notelist
[n
]))
644 /* first group must not be at the end of a tuplet */
645 if (tgs_p
->tuploc
== ENDITEM
|| tgs_p
->tuploc
== LONEITEM
)
648 /* second group must not be at the start of a tuplet */
649 if (nexttgs_p
->tuploc
== STARTITEM
|| nexttgs_p
->tuploc
== LONEITEM
)
652 /* get total duration of the two groups */
653 *comb_p
= radd(calctime(tgs_p
), calctime(nexttgs_p
));
655 /* total must be double whole, or else numerator must be 2**n - 1 */
656 if (NE(*comb_p
, Two
) && (comb_p
->n
& (comb_p
->n
+ 1)) != 0)
665 * Abstract: Calculate time duration, considering basictime and dots.
667 * Returns: The rational number answer.
669 * Description: This function, given a GRPSYL structure, returns the duration
670 * as a rational number. It considers basictime and dots, but it
671 * does not include the effect of tuplets. It assumes nongrace,
672 * it assumes GC_NOTES (thus no quadruple wholes), and it assumes
685 if (gs_p
->basictime
== 0) {
686 /* double whole note is 2 */
690 /* anything else is 1/basictime */
692 base
.d
= gs_p
->basictime
;
695 /* return ( base * (2 - (1/2)**dots) ) */
696 return (rmul(base
, rsub(Two
, rrai(One_half
, gs_p
->dots
))));
700 * Name: translate_group()
702 * Abstract: Translate tablature group notes to tabnote group notes.
706 * Description: This function is given a tablature staff group. It normally
707 * translates the notes in this one group to the notes in the
708 * corresponding tabnote staff group. But in the case where the
709 * tab staff group has note(s) that are prebends, it also creates
710 * the notes for the tabnote grace group. And in the case where
711 * this tab group is to be combined with the following one, it
712 * translates the two together into one tabnote group.
716 translate_group(tgs_p
, pregs_p
, ngs_p
, mll_p
, combine
)
718 struct GRPSYL
*tgs_p
; /* tablature GRPSYL */
719 struct GRPSYL
*ngs_p
; /* corresponding main tabnote GRPSYL */
720 struct GRPSYL
*pregs_p
; /* GRPSYL for prebend's grace group */
721 struct MAINLL
*mll_p
; /* main LL struct we come from */
722 int combine
; /* combining two tab groups into one tabnote?*/
725 struct TABNOTENOTE notes
[MAXTABLINES
]; /* notes in the main group */
726 struct TABNOTENOTE prenotes
[MAXTABLINES
]; /* notes in prebend group */
727 struct TABNOTENOTE tempnote
; /* temporary storage for sorting */
728 struct STRINGINFO
*strinfo
; /* info about the strings */
729 int fret
; /* fret number */
730 int idx
, pidx
; /* indices into regular and prebend arrays */
731 int n
, k
; /* loop variables */
732 int strno
; /* string number */
733 RATIONAL bend
; /* bend distance as a rational number */
734 int sharps
; /* number of sharps in tabnote staff's keysig*/
737 /* find the key signature; flats count negative */
738 sharps
= svpath(ngs_p
->staffno
, SHARPS
)->sharps
;
740 /* point to the array of structures describing the strings */
741 strinfo
= svpath(tgs_p
->staffno
, STAFFLINES
)->strinfo
;
744 * Loop through the note structures in the tab staff's GRPSYL, filling
745 * the prebend and regular note arrays.
748 for (n
= 0; n
< tgs_p
->nnotes
; n
++) {
750 /* get string and fret number */
751 strno
= tgs_p
->notelist
[n
].STRINGNO
;
752 fret
= tgs_p
->notelist
[n
].FRETNO
;
755 * If this note is a prebend note, put the original (unbent)
756 * note in the prenotes array. Link this to the tab staff's
757 * GRPSYL. Keep the array sorted so that the highest notes
760 if (fret
!= NOFRET
&& HASREALBEND(tgs_p
->notelist
[n
])) {
761 calcnote(&strinfo
[strno
], fret
, Zero
, sharps
,
762 &prenotes
[pidx
++], tgs_p
);
763 prenotes
[pidx
-1].strno
= strno
;
764 prenotes
[pidx
-1].note_p
= &tgs_p
->notelist
[n
];
765 for (k
= pidx
- 1; k
> 0; k
--) {
766 if (prenotes
[k
].hs
> prenotes
[k
-1].hs
) {
767 tempnote
= prenotes
[k
-1];
768 prenotes
[k
-1] = prenotes
[k
];
769 prenotes
[k
] = tempnote
;
774 /* find the bend amount; if none we will get Zero */
775 bend
= ratbend(&tgs_p
->notelist
[n
]);
778 * If there is no fret number in this note, it must be the
779 * destination of a bend. Call findfret to search backwards
780 * through earlier notes on this string, until we find the fret
781 * number, which is where the bend started.
784 fret
= findfret(tgs_p
, mll_p
, strno
);
786 pfatal("cannot find fret number for tablature note");
789 * Now we have the fret, and maybe a bend too. Calculate what
790 * note this comes out to, and put it in the notes array.
791 * Link this to the GRPSYL it was derived from. Keep the
792 * array sorted so that the highest notes come first.
794 calcnote(&strinfo
[strno
], fret
, bend
, sharps
, ¬es
[idx
++],
796 notes
[idx
-1].note_p
= &tgs_p
->notelist
[n
];
797 notes
[idx
-1].strno
= strno
;
798 for (k
= idx
- 1; k
> 0; k
--) {
799 if (notes
[k
].hs
> notes
[k
-1].hs
) {
800 tempnote
= notes
[k
-1];
801 notes
[k
-1] = notes
[k
];
808 * If we are generating a prebend group, populate NOTE structures for
809 * it. Then, in any case, populate NOTE structures for the main group.
812 popnotes(pregs_p
, prenotes
, pidx
, tgs_p
, mll_p
, YES
, NO
,sharps
);
814 popnotes(ngs_p
, notes
, idx
, tgs_p
, mll_p
, NO
, combine
, sharps
);
820 * Abstract: Calculate note info for a tabnote NOTE structure.
824 * Description: This function is given the info about the string in question,
825 * the fret number on that string, and the amount of bend (which
826 * might be zero). From this it calculates what note that results
827 * in, and how best to represent it, which depends on what the
828 * key sig is. Bends are rounded to the nearest half step,
829 * rounding downward when they fall on an exact quarter step.
830 * The results are put in the TABNOTENOTE structure provided.
834 calcnote(sinfo_p
, fret
, bend
, sharps
, note_p
, tgs_p
)
836 struct STRINGINFO
*sinfo_p
; /* pointer to info about the string */
837 int fret
; /* fret number on the string */
838 RATIONAL bend
; /* bend distance */
839 int sharps
; /* number of sharps in tabnote staff's keysig*/
840 struct TABNOTENOTE
*note_p
; /* note structure to be filled */
841 struct GRPSYL
*tgs_p
; /* pointer to tab group */
845 * The following table, indexed by a note letter minus 'a', tells how
846 * many half steps that note is above C.
848 static int hstab
[] = { 9, 11, 0, 2, 4, 5, 7 };
851 * The following table, given the number of sharps in a major key
852 * (flats count negative), is to be indexed by (sharps + 7). The
853 * result is the number of half steps the key note is above C.
855 static int sh2keyhs
[] = { 11,6, 1, 8, 3,10, 5, 0, 7, 2, 9, 4,11, 6, 1 };
856 /* c& g& d& a& e& b& f c g d a e b f# c#*/
857 /* -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 */
859 * The following table, given the number of sharps in a major key
860 * (flats count negative), is to be indexed by (sharps + 7). The
861 * result is the number of letters the key note is above C.
863 static int sh2keylet
[] ={ 0, 4, 1, 5, 2, 6, 3, 0, 4, 1, 5, 2, 6, 3, 0 };
864 /* c& g& d& a& e& b& f c g d a e b f# c#*/
865 /* -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 */
868 * The following table, given the number of half steps a note is above
869 * the key note, tells how many letters above the key note letter the
870 * given note should be written as. For example, in the key of C, the
871 * note 6 half steps up (augmented 4th, f#), should be written with
872 * the letter 3 letters above c (c + 3 = f), thus f# and not g&.
874 static int hs2s
[] = { 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6 };
875 /* intervals: P1 A1 M2 m3 M3 P4 A4 P5 A5 M6 m7 M7 */
876 /* key of C example: c c# d e& e f f# g g# a b& b */
879 int hs
; /* half steps above c0 */
880 RATIONAL bendqs
; /* bend quarter steps */
881 int keyhs
; /* hs above C the key note is */
882 int intervhs
; /* hs above key note the given note is */
883 int intervlet
; /* letters above key note the given note is */
884 int keyletidx
; /* the key letter (c=1, d=1, etc.) */
885 int octacc
; /* half steps due to octave & accidental */
886 int accoffset
; /* resulting note's acc (&=-1, #=1, etc.) */
890 * Convert the bend to quarter steps. If the result is an odd integer,
891 * dividing by 2 will give the number of half steps we want (we are
892 * rounding downward). Otherwise, we round to the nearest half step.
894 bendqs
= rmul(bend
, Four
);
895 if (bendqs
.n
% 2 == 1 && bendqs
.d
== 1) {
898 bendqs
= radd(bendqs
, One
);
899 hs
= bendqs
.n
/ bendqs
.d
/ 2;
902 /* add on the half steps due to letter, octave, and fret */
903 hs
+= hstab
[ sinfo_p
->letter
- 'a' ] + 12 * sinfo_p
->octave
+ fret
;
905 /* adjust if string has an accidental; only '#' and '&' are allowed */
906 switch (sinfo_p
->accidental
) {
915 /* hs is now the correct note, in half steps above c0 */
919 * Now that we know the note, we still have to decide how to represent
920 * it, like G# versus A&. If the note falls within the key signature,
921 * we go with that. Otherwise, we take our best shot at which way to
924 * For C major, for example, it seems clear that F# and C# are more
925 * likely to be appropriate than G& and D&, due to borrowed dominant
926 * chords. G# is probably better than A&, since it's in the dominant
927 * of the relative minor, though it's not good for the flat 6 chord.
928 * But D# is getting a little extreme, and E& is probably better.
929 * Certainly B& is better than A#.
931 * For A minor, a similar analysis shows that the same note choices
932 * are good, except that D# is probably better than E&. We could use
933 * the is_minor flag from the key sig to make this difference. But
934 * since it's only one note, which is questionable anyway, and since
935 * people wouldn't normally bother to set that flag except for some
936 * unknown MIDI purpose, we elect not to differentiate, but rather
937 * simply go with the "major" analysis. Of course, we have to
938 * transpose this to the appropriate major key.
942 * Find how many half steps above a C the key note is, assuming major.
943 * Then find how many half steps higher the given note is, being
944 * careful to add 12 in there because hs could be as small as -1.
946 keyhs
= sh2keyhs
[sharps
+ 7];
947 intervhs
= (hs
+ 12 - keyhs
) % 12;
949 /* find how many letters above the key letter this note should be */
950 intervlet
= hs2s
[intervhs
];
952 /* find the key letter (c = 0, d = 1, etc.) */
953 keyletidx
= sh2keylet
[sharps
+ 7];
955 /* find the letter that should be used for this note */
956 note_p
->letter
= "cdefgab"[(keyletidx
+ intervlet
) % 7];
959 * Subtract out the half steps due to letter (half steps the letter is
960 * above C). This leaves the half steps due to the octave & accidental.
962 octacc
= hs
- hstab
[ note_p
->letter
- 'a' ];
965 * The nearest multiple of 12 gives the octave. What's left gives the
966 * accidental from -2 to 2 (double flat to double sharp). Index a
967 * character array by that plus 2 to get the right character.
969 note_p
->octave
= (octacc
+ 12 + 6) / 12 - 1;
970 accoffset
= octacc
- 12 * note_p
->octave
;
971 note_p
->accidental
= Acclets
[accoffset
+ 2];
973 if (note_p
->octave
< MINOCTAVE
|| note_p
->octave
> MAXOCTAVE
) {
974 l_ufatal(tgs_p
->inputfile
, tgs_p
->inputlineno
,
975 "the indicated note on the %s string is out of range, too %s",
976 format_string_name(sinfo_p
->letter
, sinfo_p
->accidental
,
977 sinfo_p
->nticks
), note_p
->octave
> MAXOCTAVE ?
"high" : "low");
984 * Abstract: Find fret number that applies to the given GRPSYL.
986 * Returns: The fret number, or NOFRET if none found.
988 * Description: This function starts at the given GRPSYL and works backwards
989 * through that voice until it find a GRPSYL containing a fret
990 * number. This is needed since when there is a bend (other than
991 * a prebend), the fret number does not exist in this GRPSYL, but
992 * in some earlier GRPSYL which is "bent" to this GRPSYL by a
993 * series of one or more bends. Every intervening GRPSYL must
994 * have a "note" for this string. If the function hits an
995 * invalid GRPSYL or the beginning of the MLL, it returns NOFRET.
996 * This should never happen.
1000 findfret(tgs_p
, mll_p
, strno
)
1002 struct GRPSYL
*tgs_p
; /* tab GRPSYL to start from */
1003 struct MAINLL
*mll_p
; /* MLL struct it hangs off of */
1004 int strno
; /* string number */
1007 int n
; /* for looping through notelist */
1010 /* loop until we find the fret or something goes wrong */
1012 /* the GRPSYL must contain notes */
1013 if (tgs_p
->grpcont
!= GC_NOTES
)
1016 /* find the note for the string in question; it must exist */
1017 for (n
= 0; n
< tgs_p
->nnotes
; n
++) {
1018 if (tgs_p
->notelist
[n
].STRINGNO
== strno
)
1021 if (n
== tgs_p
->nnotes
)
1024 /* if this note (string) has a valid fret, return it */
1025 if (tgs_p
->notelist
[n
].FRETNO
!= NOFRET
)
1026 return (tgs_p
->notelist
[n
].FRETNO
);
1028 /* search backwards for the next GRPSYL, which must exist */
1029 tgs_p
= prevgrpsyl(tgs_p
, &mll_p
);
1038 * Abstract: Adjust the desired notes and populate the NOTE structures.
1042 * Description: This function is given the notes desired for one tabnote
1043 * GRPSYL. If too many notes are too close together to print, it
1044 * throws some away, with warnings. Then it allocates NOTE
1045 * structures and fills them in.
1049 popnotes(ngs_p
, tnn
, ntnn
, tgs_p
, mll_p
, is_prebend
, combine
, sharps
)
1051 struct GRPSYL
*ngs_p
; /* tabnote GRPSYL */
1052 struct TABNOTENOTE tnn
[]; /* array of TABNOTENOTE structures */
1053 int ntnn
; /* number of the above structures */
1054 struct GRPSYL
*tgs_p
; /* tablature GRPSYL we came from */
1055 struct MAINLL
*mll_p
; /* main LL structure we came from */
1056 int is_prebend
; /* is this a prebend group? */
1057 int combine
; /* this group formed by combining tab grps? */
1058 int sharps
; /* current key signature */
1061 struct NOTE
*newnote_p
; /* handy pointer to an allocated NOTE */
1062 struct GRPSYL
*nexttgs_p
; /* the tab GRPSYL following ours */
1063 struct GRPSYL
*prevngs_p
; /* the tabnote GRPSYL preceding ours */
1064 struct SLURTO
*s_p
; /* point at a SLURTO structure */
1065 struct MAINLL
*mainll_p
;/* place to store mll_p */
1066 int hightight
, lowtight
;/* are notes next to a conflict neighboring? */
1067 int remnote
; /* should a note be removed? */
1068 int keysigidx
; /* index to the note that is in the key sig */
1069 int nonkeysigidx
; /* index to the note not in the key sig */
1070 int n
, k
, j
; /* loop variables */
1074 * Loop through the notes, throwing away duplicates. They are already
1075 * in order, highest note first.
1077 for (n
= 1; n
< ntnn
; n
++) {
1078 if (tnn
[n
- 1].hs
== tnn
[n
].hs
) {
1079 l_warning(tgs_p
->inputfile
, tgs_p
->inputlineno
,
1080 "throwing away duplicate note %c%c%d on tabnote staff",
1081 tnn
[n
].letter
, tnn
[n
].accidental
, tnn
[n
].octave
);
1083 for (k
= n
; k
< ntnn
; k
++)
1084 tnn
[k
- 1] = tnn
[k
];
1091 * Loop through the remaining notes, looking for conflicts, such as f
1092 * versus f#. Because of the way the notes were generated, and because
1093 * of the previous loop, at this point any remaining conflicts will
1094 * consist of two notes, one fitting the key signature and one not.
1095 * Try to rewrite enharmonically the one that is not in the key sig.
1096 * The only problem that can arise is if there is a neighoring note in
1097 * the way. Like, with f and f# in the key of 0 sharps, we'd like to
1098 * change f# to g&, but we can't if there's already a g. So if this
1099 * happens, try to rewrite the other note (in this case, we'd get e#
1100 * and f#). If there's already an e, give up and throw one note away.
1101 * Yes, we could rewrite g as a&& to make room, but this is so rare
1102 * that it's not worth the effort.
1104 for (n
= 1; n
< ntnn
; n
++) {
1105 if (tnn
[n
- 1].letter
== tnn
[n
].letter
&&
1106 tnn
[n
- 1].octave
== tnn
[n
].octave
) {
1108 * We have a conflict. See whether the notes next to
1109 * the conflicting notes (if any) are on neighboring
1112 if (n
> 1 && neighbor(&tnn
[n
- 2], &tnn
[n
- 1]) == YES
)
1117 if (n
< ntnn
-1 && neighbor(&tnn
[n
], &tnn
[n
+ 1]) == YES
)
1122 /* remember which of the notes is in the key sig */
1123 if (inkeysig(&tnn
[n
], sharps
) == YES
) {
1125 nonkeysigidx
= n
- 1;
1131 remnote
= NO
; /* init to not remove any note */
1133 if (hightight
== YES
&& lowtight
== YES
) {
1134 /* no room to move either note */
1136 } else if (hightight
== YES
) {
1137 /* no room to move high note; move low note */
1138 if (downletter(&tnn
[n
]) == NO
) {
1142 } else if (lowtight
== YES
) {
1143 /* no room to move low note; move high note */
1144 if (upletter(&tnn
[n
- 1]) == NO
) {
1149 /* room on both sides */
1150 if (keysigidx
== n
) {
1151 /* try moving nonkeysig note first */
1152 if (upletter(&tnn
[n
- 1]) == NO
&&
1153 downletter(&tnn
[n
]) == NO
) {
1154 /* can't move either */
1158 /* try moving nonkeysig note first */
1159 if (downletter(&tnn
[n
]) == NO
&&
1160 upletter(&tnn
[n
- 1]) == NO
) {
1161 /* can't move either */
1168 * We have to remove one of the two notes in this
1169 * conflict. Arbitrarily, remove the one that doesn't
1170 * fit the key signature.
1172 if (remnote
== YES
) {
1173 l_warning(tgs_p
->inputfile
, tgs_p
->inputlineno
,
1174 "throwing away note %c%c%d on tabnote staff due to conflict with %c%c%d",
1175 tnn
[nonkeysigidx
].letter
,
1176 tnn
[nonkeysigidx
].accidental
,
1177 tnn
[nonkeysigidx
].octave
,
1178 tnn
[keysigidx
].letter
,
1179 tnn
[keysigidx
].accidental
,
1180 tnn
[keysigidx
].octave
);
1182 for (k
= nonkeysigidx
+ 1; k
< ntnn
; k
++)
1183 tnn
[k
- 1] = tnn
[k
];
1190 /* find the tab GRPSYL following our tab GRPSYL, if there is one */
1191 mainll_p
= mll_p
; /* save mll_p */
1192 nexttgs_p
= nextgrpsyl(tgs_p
, &mll_p
);
1194 /* find the tabnote GRPSYL preceding ours, if there is one */
1195 mll_p
= mainll_p
; /* restore mll_p in case it was changed */
1196 prevngs_p
= prevgrpsyl(ngs_p
, &mll_p
);
1198 CALLOC(NOTE
, ngs_p
->notelist
, ntnn
);
1199 ngs_p
->nnotes
= (short)ntnn
;
1202 * Loop through the newly allocated notes, setting all their fields.
1204 for (n
= 0; n
< ntnn
; n
++) {
1205 newnote_p
= &ngs_p
->notelist
[n
]; /* set short cut pointer */
1207 /* allocate the array of coordinates */
1208 MALLOCA(float, ngs_p
->notelist
[n
].c
, NUMCTYPE
);
1210 /* copy the calculated letter/accidental/octave */
1211 newnote_p
->letter
= tnn
[n
].letter
;
1212 newnote_p
->accidental
= tnn
[n
].accidental
;
1213 newnote_p
->octave
= tnn
[n
].octave
;
1215 /* copy note size, except that prebend graces are always small*/
1216 newnote_p
->notesize
= is_prebend
== YES ?
1217 GS_SMALL
: tnn
[n
].note_p
->notesize
;
1219 newnote_p
->headshape
= tnn
[n
].note_p
->headshape
;
1220 newnote_p
->tie
= tnn
[n
].note_p
->tie
;
1221 newnote_p
->tiestyle
= tnn
[n
].note_p
->tiestyle
;
1223 /* flag to draw curved line after notes */
1225 newnote_p
->smallbend
= YES
;
1227 /* copy whether note has paren; but if prebend, always set it*/
1228 newnote_p
->note_has_paren
= tnn
[n
].note_p
->note_has_paren
;
1230 newnote_p
->note_has_paren
= YES
;
1233 * If this note has slur(s), allocate a slur-to list. If a
1234 * slur is to real frets, set the string number in the letter
1235 * for now, and fix it up later when we know the true letter
1236 * and octave. If it's a slur to or from nowhere, copy over
1237 * the "octave" (pseudo fret) as is. The letter on these is
1238 * meaningless. Note: a maximum of one slur can be to a real
1239 * fret and a maximum of two slurs can exist.
1241 if (tnn
[n
].note_p
->nslurto
!= 0) {
1242 newnote_p
->nslurto
= tnn
[n
].note_p
->nslurto
;
1243 CALLOC(SLURTO
, newnote_p
->slurtolist
,
1244 newnote_p
->nslurto
);
1246 for (k
= 0; k
< newnote_p
->nslurto
; k
++) {
1247 s_p
= &tnn
[n
].note_p
->slurtolist
[k
];
1249 if (IS_NOWHERE(s_p
->octave
)) {
1250 /* slur to or from nowhere */
1251 /* letter is meaningless */
1252 newnote_p
->slurtolist
[k
].octave
=
1254 } else { /* real fret number */
1255 newnote_p
->slurtolist
[k
].letter
=
1257 newnote_p
->slurtolist
[k
].octave
=
1258 NOFRET
; /* unknown */
1261 /* always copy slur style */
1262 newnote_p
->slurtolist
[k
].slurstyle
=
1268 * If we are a prebend note, allocate a slur-to list.
1271 CALLOC(SLURTO
, newnote_p
->slurtolist
, 1);
1272 newnote_p
->is_bend
= YES
;
1273 newnote_p
->nslurto
= 1;
1275 * Although the bent-to note has been calculated, at
1276 * this point in the code we don't know what it is.
1277 * For now, we store the string number in the letter.
1278 * When we are doing the next GRPSYL on this staff, we
1279 * will change this to be the true bent-to letter, and
1280 * set the octave too.
1282 newnote_p
->slurtolist
[0].letter
= tnn
[n
].strno
;
1283 newnote_p
->slurtolist
[0].octave
= NOFRET
;
1287 * If we are not a prebend group (those are handled elsewhere)
1288 * and our group was not formed by combining two tab groups
1289 * and there is a next GRPSYL on the tablature staff (in this
1290 * or the next measure), our note might be bent to a note in
1291 * that next GRPSYL. So search it to see if it contains a note
1292 * that our current note is bent to. If so, allocate a slur-to
1295 if ( ! is_prebend
&& ! combine
&& nexttgs_p
!= 0) {
1296 for (k
= 0; k
< nexttgs_p
->nnotes
; k
++) {
1298 * Find matching string with a bend but either
1299 * no fret or else it has to be a null bend.
1300 * This eliminates finding a prebend.
1302 if (nexttgs_p
->notelist
[k
].STRINGNO
== tnn
[n
].
1303 strno
&& HASBEND(nexttgs_p
->notelist
[k
]) &&
1304 (nexttgs_p
->notelist
[k
].FRETNO
== NOFRET
||
1305 HASNULLBEND(nexttgs_p
->notelist
[k
])))
1308 if (k
< nexttgs_p
->nnotes
) {
1309 if (newnote_p
->nslurto
!= 0)
1310 pfatal("slur and bend on the same note [popnotes]");
1312 CALLOC(SLURTO
, newnote_p
->slurtolist
, 1);
1313 newnote_p
->is_bend
= YES
;
1314 newnote_p
->nslurto
= 1;
1316 * We don't yet know what the bent-to note is
1317 * going to be. For now, we store the string
1318 * number in the letter. When we are doing the
1319 * next GRPSYL on this staff, we will change
1320 * this to be the true bent-to letter, and set
1323 newnote_p
->slurtolist
[0].letter
= tnn
[n
].strno
;
1328 * If we are not a prebend note and there is a previous GRPSYL
1329 * on the tabnote staff (in this or the previous measure), our
1330 * note may be the destination of a bend or a slur. Try to
1331 * find the note in the previous GRPSYL that bends or slurs to
1332 * our note, if any. If found, set its slur-to list correctly,
1333 * now that we know what should be put in it.
1335 if ( ! is_prebend
&& prevngs_p
!= 0) {
1337 * Check every note in the preceding group. Don't
1338 * break out after finding one, since multiple ones
1339 * could slide to our note if our note was a duplicate
1340 * (derived from multiple strings). But there is a
1341 * max of one slur/bend coming from each note.
1343 for (k
= 0; k
< prevngs_p
->nnotes
; k
++) {
1344 /* check every slur from that note */
1345 s_p
= 0; /* avoid 'used before set' */
1346 for (j
= 0; j
< prevngs_p
->notelist
[k
].nslurto
;
1348 s_p
= &prevngs_p
->notelist
[k
].
1350 if (s_p
->letter
== tnn
[n
].strno
&&
1351 ! IS_NOWHERE(s_p
->octave
))
1354 /* if found a slur to our note */
1355 if (j
< prevngs_p
->notelist
[k
].nslurto
) {
1356 s_p
->letter
= ngs_p
->notelist
[n
].letter
;
1357 s_p
->octave
= ngs_p
->notelist
[n
].octave
;
1367 * Abstract: Find whether the given notes are on neighboring letters.
1369 * Returns: YES or NO
1371 * Description: This function figures out whether the given notes are on
1372 * neighboring letter, taking octaves into account.
1376 neighbor(high_p
, low_p
)
1378 struct TABNOTENOTE
*high_p
; /* the higher note */
1379 struct TABNOTENOTE
*low_p
; /* the lower note */
1382 /* if the letter themselves aren't right, return NO */
1383 if (low_p
->letter
== 'g') {
1384 if (high_p
->letter
!= 'a')
1387 if (high_p
->letter
!= low_p
->letter
+ 1)
1391 /* if the octaves aren't right, return NO */
1392 if (low_p
->letter
== 'b') {
1393 if (high_p
->octave
!= low_p
->octave
+ 1)
1396 if (high_p
->octave
!= low_p
->octave
)
1406 * Abstract: Find whether the given note fits the key signature.
1408 * Returns: YES or NO
1410 * Description: This function figures out whether the given note fits the key
1411 * signature, and returns the answer.
1415 inkeysig(note_p
, sharps
)
1417 struct TABNOTENOTE
*note_p
; /* note contained in a TABNOTENOTE structure */
1418 int sharps
; /* current key signature */
1421 int circnum
; /* position in the circle of 5ths */
1422 int accnum
; /* B = 0, & = 1, n = 2, # = 3, x = 4 */
1423 int sharpness
; /* how "sharp" is the note */
1426 circnum
= strchr(Circle
, note_p
->letter
) - Circle
;
1427 accnum
= strchr(Acclets
, note_p
->accidental
) - Acclets
;
1428 sharpness
= circnum
+ 7 * (accnum
- 2);
1430 if (sharpness
>= sharps
&& sharpness
<= sharps
+ 6)
1439 * Abstract: Alter note enharmonically, incrementing the letter.
1443 * Description: This function alters the given note enharmonically. It raises
1444 * the letter, and adjusts the accidental and octave as needed.
1450 struct TABNOTENOTE
*note_p
; /* note contained in a TABNOTENOTE structure */
1453 int accnum
; /* B = 0, & = 1, n = 2, # = 3, x = 4 */
1456 accnum
= strchr(Acclets
, note_p
->accidental
) - Acclets
;
1459 * If the old letter is e or b, the next higher white note is only a
1460 * half step away, so the accidental has to be a half step flatter.
1461 * Otherwise, it's a whole step. If the result would be flatter than
1462 * a double flat, we can't do this, so return NO.
1464 if (note_p
->letter
== 'e' || note_p
->letter
== 'b') {
1465 if (accnum
== 0) /* double flat */
1469 if (accnum
<= 1) /* flat or double flat */
1474 /* if the note is b, increment the octave; fail if impossible */
1475 if (note_p
->letter
== 'b') {
1476 if (note_p
->octave
== MAXOCTAVE
)
1481 /* increment the letter; g wraps around to a */
1482 if (note_p
->letter
== 'g')
1483 note_p
->letter
= 'a';
1487 note_p
->accidental
= Acclets
[accnum
];
1493 * Name: downletter()
1495 * Abstract: Alter note enharmonically, decrementing the letter.
1499 * Description: This function alters the given note enharmonically. It lowers
1500 * the letter, and adjusts the accidental and octave as needed.
1506 struct TABNOTENOTE
*note_p
; /* note contained in a TABNOTENOTE structure */
1509 int accnum
; /* B = 0, & = 1, n = 2, # = 3, x = 4 */
1512 accnum
= strchr(Acclets
, note_p
->accidental
) - Acclets
;
1515 * If the old letter is f or c, the next lower white note is only a
1516 * half step away, so the accidental has to be a half step sharper.
1517 * Otherwise, it's a whole step. If the result would be sharper than
1518 * a double sharp, we can't do this, so return NO.
1520 if (note_p
->letter
== 'f' || note_p
->letter
== 'c') {
1521 if (accnum
== 4) /* double sharp */
1525 if (accnum
>= 3) /* sharp or double sharp */
1530 /* if the note is c, decrement the octave; fail if impossible */
1531 if (note_p
->letter
== 'c') {
1532 if (note_p
->octave
== MINOCTAVE
)
1537 /* decrement the letter; a wraps around to g */
1538 if (note_p
->letter
== 'a')
1539 note_p
->letter
= 'g';
1543 note_p
->accidental
= Acclets
[accnum
];
1551 * Abstract: Remove unnecessary accidentals from a tabnote staff measure.
1555 * Description: This function removes all the unnecessary accidentals from one
1556 * measure of a tabnote staff. It takes into consideration the
1557 * key signature and the fact that accidentals last for the
1558 * duration of the measure unless changed by another accidental.
1559 * Also, if a note in the first group was tied from the previous
1560 * measure, any accidental is carried over to this note and
1561 * any series of notes it ties into, but if the note occurs again
1562 * in this measure it reverts to the key signature; so the bottom
1563 * line is we can ignore this and pretend that the tied note is in
1564 * the key signature.
1568 cleanaccs(gs_p
, mll_p
)
1570 struct GRPSYL
*gs_p
; /* starts at first tabnote GRPSYL */
1571 struct MAINLL
*mll_p
; /* main LL struct that tabnote staff hangs off*/
1574 /* current accidental for letter and octave */
1575 char curacc
[7][MAXOCTAVE
+ 1]; /* assumes MINOCTAVE == 0 */
1577 int oct
; /* octave number */
1578 char let
; /* note letter */
1579 int sharps
; /* number of sharps in tabnote staff's keysig*/
1580 int cidx
; /* index into circle of fifths */
1581 struct GRPSYL
*prevgs_p
;/* pointer to preceding GRPSYL */
1582 struct NOTE
*note_p
; /* pointer to a NOTE structure */
1583 int n
, k
; /* loop variables */
1588 * Initialize the table to say that for all octaves of all letters,
1589 * the accidental is a natural.
1591 for (oct
= 0; oct
<= MAXOCTAVE
; oct
++) {
1592 for (let
= 'a'; let
<= 'g'; let
++) {
1593 curacc
[let
- 'a'] [oct
] = 'n';
1597 /* find the key signature; flats count negative */
1598 sharps
= svpath(gs_p
->staffno
, SHARPS
)->sharps
;
1601 * Load the key signature's accidentals into the array for every
1604 for (oct
= 0; oct
<= 9; oct
++) {
1605 for (cidx
= 0; cidx
< sharps
; cidx
++) {
1606 curacc
[ Circle
[cidx
] - 'a' ] [oct
] = '#';
1608 for (cidx
= 0; cidx
> sharps
; cidx
--) {
1609 curacc
[ Circle
[6 + cidx
] - 'a' ] [oct
] = '&';
1614 * Loop through every note group and every note in them, clearing
1615 * accidentals when that accidental is already in force, and updating
1616 * the table when not.
1618 for ( ; gs_p
!= 0; gs_p
= gs_p
->next
) {
1619 if (gs_p
->grpcont
!= GC_NOTES
)
1622 /* find previous group; could be in previous measure if any */
1623 prevgs_p
= prevgrpsyl(gs_p
, &mll_p
);
1625 for (n
= 0; n
< gs_p
->nnotes
; n
++) {
1626 note_p
= &gs_p
->notelist
[n
];
1629 * If the note is the destination of a tie, blow away
1630 * its accidental. This wouldn't have to be a special
1631 * check if it weren't for ties across bar lines.
1633 if (prevgs_p
!= 0 && prevgs_p
->grpcont
== GC_NOTES
) {
1634 for (k
= 0; k
< prevgs_p
->nnotes
; k
++) {
1635 if (prevgs_p
->notelist
[k
].tie
== YES
&&
1636 prevgs_p
->notelist
[k
].letter
==
1637 note_p
->letter
&& prevgs_p
->notelist
1638 [k
].octave
== note_p
->octave
) {
1639 note_p
->accidental
= '\0';
1643 /* if we found it was tied, continue to next */
1644 if (k
< prevgs_p
->nnotes
)
1648 * If this note's accidental agrees with the accidental
1649 * already in force for this letter and octave, wipe it
1650 * out. If it doesn't, leave it alone, and update the
1651 * table to show the new accidental that is in force.
1653 if (note_p
->accidental
== curacc
[ note_p
->letter
- 'a' ]
1654 [ note_p
->octave
]) {
1655 note_p
->accidental
= '\0';
1657 curacc
[ note_p
->letter
- 'a' ] [ note_p
->
1658 octave
] = note_p
->accidental
;