chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / trantab.c
CommitLineData
69695f33
MW
1/* Copyright (c) 1997, 1998, 2000, 2001, 2002, 2004 by Arkkra Enterprises */
2/* All rights reserved */
3/*
4 * Name: trantab.c
5 *
6 * Description: This file contains functions for translating tablature staffs
7 * to their corresponding tabnote staffs.
8 */
9
10#include "defines.h"
11#include "structs.h"
12#include "globals.h"
13
14/*
15 * Define a temp structure for holding info about the note generated from a
16 * NOTE on a tablature staff.
17 */
18struct TABNOTENOTE {
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 */
25};
26
27static void tabv2tabnotev P((struct MAINLL *mainll_p, int vidx));
28static void fixprevmeas P((struct GRPSYL *ngs_p, struct MAINLL *mll_p));
29static int hasprebend P((struct GRPSYL *gs_p));
30static int cancombine P((struct MAINLL *mll_p, struct GRPSYL *tgs_p,
31 RATIONAL *comp_p));
32static RATIONAL calctime P((struct GRPSYL *gs_p));
33static void translate_group P((struct GRPSYL *tgs_p, struct GRPSYL *pregs_p,
34 struct GRPSYL *ngs_p, struct MAINLL *mll_p, int combine));
35static void calcnote P((struct STRINGINFO *sinfo_p, int fretno, RATIONAL bend,
36 int sharps, struct TABNOTENOTE *note_p, struct GRPSYL *tgs_p));
37static int findfret P((struct GRPSYL *tgs_p, struct MAINLL *mll_p, int strno));
38static 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));
41static int neighbor P((struct TABNOTENOTE *high_p, struct TABNOTENOTE *low_p));
42static int inkeysig P((struct TABNOTENOTE *note_p, int sharps));
43static int upletter P((struct TABNOTENOTE *note_p));
44static int downletter P((struct TABNOTENOTE *note_p));
45static void cleanaccs P((struct GRPSYL *gs_p, struct MAINLL *mll_p));
46\f
47/*
48 * Name: tab2tabnote()
49 *
50 * Abstract: Populate tabnote staffs' voices from corresponding tab voices.
51 *
52 * Returns: void
53 *
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.
58 */
59
60void
61tab2tabnote()
62
63{
64 struct MAINLL *mainll_p; /* point along main linked list */
65 struct STAFF *nstaff_p; /* tabnote STAFF */
66 struct GRPSYL *ngs_p; /* tabnote GRPSYL */
67 int vidx;
68
69
70 debug(2, "tab2tabnote");
71 initstructs();
72
73 for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) {
74
75 if (mainll_p->str == S_SSV) {
76 asgnssv(mainll_p->u.ssv_p); /* keep SSVs up to date */
77 continue;
78 }
79
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) {
83 continue;
84 }
85
86 /*
87 * The previous staff must be a tabnote staff. Set pointers to
88 * this tabnote staff and its first voice's first GRPSYL.
89 */
90 nstaff_p = mainll_p->prev->u.staff_p;
91 ngs_p = nstaff_p->groups_p[0];
92
93 /*
94 * If this is a multirest, adjust any octave marks in progress.
95 */
96 if (ngs_p->basictime < -1 &&
97 Octave_bars[nstaff_p->staffno] > 0) {
98
99 /* add negative bars plus 1; barline will count as 1 */
100 Octave_bars[nstaff_p->staffno] += ngs_p->basictime + 1;
101
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;
107 }
108 }
109
110 /* loop through all possible voices, populating tabnote */
111 for (vidx = 0; vidx < MAXVOICES; vidx++) {
112 tabv2tabnotev(mainll_p, vidx);
113 }
114 }
115}
116\f
117/*
118 * Name: tabv2tabnotev()
119 *
120 * Abstract: Populate a tabnote voice from its corresponding tab voice.
121 *
122 * Returns: void
123 *
124 * Description: This function populates a tabnote GRPSYL list based on its
125 * corresponding tab GRPSYL list, after making sure that the voice
126 * exists for each.
127 */
128
129static void
130tabv2tabnotev(mainll_p, vidx)
131
132struct MAINLL *mainll_p; /* main LL struct for this staff */
133int vidx; /* voice index, 0 to MAXVOICES-1 */
134
135{
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 */
147
148
149 /*
150 * Set pointers to the tablature staff's STAFF structure and the first
151 * GRPSYL in the voice we're working on.
152 */
153 tstaff_p = mainll_p->u.staff_p;
154 tgs_p = tstaff_p->groups_p[vidx];
155
156 /* if this voice doesn't exist, there is nothing to copy to tabnote */
157 if (tgs_p == 0) {
158 return;
159 }
160
161 /*
162 * The previous staff must be a tabnote staff. Set pointers to this
163 * tabnote staff and the first GRPSYL of the given voice.
164 */
165 nstaff_p = mainll_p->prev->u.staff_p;
166 ngs_p = nstaff_p->groups_p[vidx];
167
168 /* tabnote staff must have at least as many voices as tab staff */
169 if (ngs_p == 0) {
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);
173 }
174
175 /*
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.
181 */
182 if (ngs_p->is_meas == NO || ngs_p->grpcont != GC_SPACE) {
183 fixprevmeas(ngs_p, mainll_p->prev);
184 return;
185 }
186
187 FREE(ngs_p); /* throw away the measure space */
188
189 /*
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.
196 */
197 combine = NO;
198 for ( ; tgs_p != 0; tgs_p = tgs_p->next) {
199 /*
200 * If this group was combined into the previous group because
201 * of 1/4 step bends, we don't allocate any group now.
202 */
203 if (combine) {
204 combine = NO;
205 continue;
206 }
207
208 /*
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
212 * set its fields.
213 */
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 */
219 pregs_p->prev = 0;
220 nstaff_p->groups_p[vidx] = pregs_p;
221 } else {
222 /* a later one; set both links */
223 pregs_p->prev = ngs_p;
224 ngs_p->next = pregs_p;
225 }
226 pregs_p->next = 0; /* last one so far */
227 ngs_p = pregs_p;
228
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;
247 pregs_p->tie = NO;
248 pregs_p->roll = NOITEM;
249 pregs_p->ho_usage = HO_NONE;
250 /* nnotes and notelist get set later */
251 } else {
252 pregs_p = 0; /* no prebend grace */
253 }
254
255 /*
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.
260 */
261 CALLOC(GRPSYL, gs_p, 1);
262 *gs_p = *tgs_p;
263 if (tgs_p == tstaff_p->groups_p[vidx] && pregs_p == 0) {
264 /* first one; no previous one, staff points at us */
265 gs_p->prev = 0;
266 nstaff_p->groups_p[vidx] = gs_p;
267 } else {
268 /* later one; set both links */
269 gs_p->prev = ngs_p;
270 ngs_p->next = gs_p;
271 }
272 gs_p->next = 0; /* last one so far */
273 ngs_p = gs_p; /* use ngs_p var for new one */
274
275 /* set the correct staff number */
276 ngs_p->staffno = nstaff_p->staffno;
277
278 /* can't share same withlist because fonts may be */
279 /* changed in them differently later */
280 clone_withlist(ngs_p, tgs_p);
281
282 /* notelist will be reset later; nnotes might change */
283
284 combine = cancombine(mainll_p, tgs_p, &totdur);
285 if (combine) {
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);
289
290 /* combine fulltime (works even for tuplets) */
291 ngs_p->fulltime = radd(tgs_p->fulltime,
292 tgs_p->next->fulltime);
293 }
294
295 if (tgs_p->grpcont == GC_NOTES && ! is_mrpt(ngs_p)) {
296 translate_group(tgs_p, pregs_p, ngs_p,
297 mainll_p, combine);
298 }
299 }
300
301 /*
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.
304 */
305 if (is_mrpt(ngs_p)) {
306 nstaff_p->mrptnum = tstaff_p->mrptnum;
307 return;
308 }
309
310 /* blow away unneeded accidentals */
311 cleanaccs(nstaff_p->groups_p[vidx], mainll_p->prev);
312
313 /*
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
317 * groups.
318 */
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*/
322
323 for ( ; ngs_p != 0; ngs_p = nngs_p) {
324 /* get the next group, if any, excluding graces */
325 nngs_p = nextnongrace(ngs_p);
326
327 /*
328 * For this and the next group, if it's a quarter or longer,
329 * make sure it won't get beamed.
330 */
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;
335
336 /* based on this and next group, change this group */
337 switch (ngs_p->beamloc) {
338 case STARTITEM:
339 if (nngs_p == 0 ||
340 nngs_p->beamloc == STARTITEM ||
341 nngs_p->beamloc == NOITEM)
342 ngs_p->beamloc = NOITEM;
343 break;
344 case INITEM:
345 if (nngs_p == 0 ||
346 nngs_p->beamloc == STARTITEM ||
347 nngs_p->beamloc == NOITEM)
348 ngs_p->beamloc = ENDITEM;
349 break;
350 case ENDITEM:
351 case NOITEM:
352 if (nngs_p != 0) {
353 if (nngs_p->beamloc == INITEM)
354 nngs_p->beamloc = STARTITEM;
355 else if (nngs_p->beamloc == ENDITEM)
356 nngs_p->beamloc = NOITEM;
357 }
358 break;
359 }
360 }
361
362 /*
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.
366 */
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*/
370
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 */
374
375 if (ngs_p->beamloc != STARTITEM)
376 continue;
377 /*
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
380 * later.
381 */
382 notegroups = 0;
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)
389 notegroups++;
390 end_p = nngs_p;
391 }
392
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;
400 }
401 } else {
402 /*
403 * There are at least two note groups, so we will keep
404 * the set, but we may need to move the endpoints to
405 * avoid rests.
406 */
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;
411 }
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;
417 }
418 nngs_p->beamloc = ENDITEM;
419 }
420 }
421
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);
428 }
429
430 /*
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.
434 */
435 octave_transpose(nstaff_p, mainll_p, vidx, NO);
436
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) {
441
442 acc_p = ngs_p->notelist[n].accidental == '\0' ?
443 "" : Acctostr[strchr(Acclets, ngs_p->
444 notelist[n].accidental) - Acclets];
445
446 l_ufatal(ngs_p->inputfile,
447 ngs_p->inputlineno,
448 "'octave' string on tabnote staff transposes note %c%s to out of range octave %d",
449 ngs_p->notelist[n].letter,
450 acc_p,
451 ngs_p->notelist[n].octave);
452 }
453 }
454 }
455}
456\f
457/*
458 * Name: fixprevmeas()
459 *
460 * Abstract: Fixed unresolved slides in the previous tabnote measure.
461 *
462 * Returns: void
463 *
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.
470 */
471
472static void
473fixprevmeas(ngs_p, mll_p)
474
475struct GRPSYL *ngs_p; /* tabnote GRPSYL */
476struct MAINLL *mll_p; /* MLL for this GRPSYL */
477
478{
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 */
482
483
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)
487 return;
488
489 /*
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.
493 */
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];
499
500 /* only deal with unresolved tabslurs */
501 if (s_p->letter < MAXTABLINES && s_p->octave == NOFRET)
502 break;
503 }
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);
516
517 prevngs_p->notelist[k].nslurto = 0;
518
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);
529
530 prevngs_p->notelist[k].nslurto = 0;
531 /* there is one note, so we can do the slide */
532 } else {
533 s_p->letter = ngs_p->notelist[0].letter;
534 s_p->octave = ngs_p->notelist[0].octave;
535 }
536 }
537 }
538}
539\f
540/*
541 * Name: hasprebend()
542 *
543 * Abstract: Check whether any of the notes in this group have a prebend.
544 *
545 * Returns: YES or NO
546 *
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.
552 */
553
554static int
555hasprebend(tgs_p)
556
557struct GRPSYL *tgs_p;
558
559{
560 int n; /* for looping through notes */
561
562
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])) {
567 return (YES);
568 }
569 }
570
571 return (NO);
572}
573\f
574/*
575 * Name: cancombine()
576 *
577 * Abstract: Check two groups can be joined into one on the tabnote staff.
578 *
579 * Returns: YES or NO
580 *
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
586 * tuplets.
587 */
588
589static int
590cancombine(mll_p, tgs_p, comb_p)
591
592struct MAINLL *mll_p; /* main linked list structure we are hanging off of */
593struct GRPSYL *tgs_p; /* tablature GRPSYL for the first of the two groups */
594RATIONAL *comb_p; /* for returning total time if combinable */
595
596{
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 */
600
601
602 /* must be a note group */
603 if (tgs_p->grpcont != GC_NOTES)
604 return (NO);
605
606 /* must not be grace */
607 if (tgs_p->grpvalue == GV_ZERO)
608 return (NO);
609
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]))
613 return (NO);
614 }
615
616 nexttgs_p = tgs_p->next; /* find the next group */
617
618 /* first group must not be at the end of a measure */
619 if (nexttgs_p == 0)
620 return (NO);
621
622 /* first and second group must have same number of notes */
623 if (tgs_p->nnotes != nexttgs_p->nnotes)
624 return (NO);
625
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))
630 return (NO);
631 }
632
633 /* find the following (3rd) group, if there is one */
634 next2tgs_p = nextgrpsyl(nexttgs_p, &mll_p);
635
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]))
640 return (NO);
641 }
642 }
643
644 /* first group must not be at the end of a tuplet */
645 if (tgs_p->tuploc == ENDITEM || tgs_p->tuploc == LONEITEM)
646 return (NO);
647
648 /* second group must not be at the start of a tuplet */
649 if (nexttgs_p->tuploc == STARTITEM || nexttgs_p->tuploc == LONEITEM)
650 return (NO);
651
652 /* get total duration of the two groups */
653 *comb_p = radd(calctime(tgs_p), calctime(nexttgs_p));
654
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)
657 return (NO);
658
659 return (YES);
660}
661\f
662/*
663 * Name: calctime()
664 *
665 * Abstract: Calculate time duration, considering basictime and dots.
666 *
667 * Returns: The rational number answer.
668 *
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
673 * not multirest.
674 */
675
676static RATIONAL
677calctime(gs_p)
678
679struct GRPSYL *gs_p;
680
681{
682 RATIONAL base;
683
684
685 if (gs_p->basictime == 0) {
686 /* double whole note is 2 */
687 base.n = 2;
688 base.d = 1;
689 } else {
690 /* anything else is 1/basictime */
691 base.n = 1;
692 base.d = gs_p->basictime;
693 }
694
695 /* return ( base * (2 - (1/2)**dots) ) */
696 return (rmul(base, rsub(Two, rrai(One_half, gs_p->dots))));
697}
698\f
699/*
700 * Name: translate_group()
701 *
702 * Abstract: Translate tablature group notes to tabnote group notes.
703 *
704 * Returns: void
705 *
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.
713 */
714
715static void
716translate_group(tgs_p, pregs_p, ngs_p, mll_p, combine)
717
718struct GRPSYL *tgs_p; /* tablature GRPSYL */
719struct GRPSYL *ngs_p; /* corresponding main tabnote GRPSYL */
720struct GRPSYL *pregs_p; /* GRPSYL for prebend's grace group */
721struct MAINLL *mll_p; /* main LL struct we come from */
722int combine; /* combining two tab groups into one tabnote?*/
723
724{
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*/
735
736
737 /* find the key signature; flats count negative */
738 sharps = svpath(ngs_p->staffno, SHARPS)->sharps;
739
740 /* point to the array of structures describing the strings */
741 strinfo = svpath(tgs_p->staffno, STAFFLINES)->strinfo;
742
743 /*
744 * Loop through the note structures in the tab staff's GRPSYL, filling
745 * the prebend and regular note arrays.
746 */
747 idx = pidx = 0;
748 for (n = 0; n < tgs_p->nnotes; n++) {
749
750 /* get string and fret number */
751 strno = tgs_p->notelist[n].STRINGNO;
752 fret = tgs_p->notelist[n].FRETNO;
753
754 /*
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
758 * come first.
759 */
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;
770 }
771 }
772 }
773
774 /* find the bend amount; if none we will get Zero */
775 bend = ratbend(&tgs_p->notelist[n]);
776
777 /*
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.
782 */
783 if (fret == NOFRET)
784 fret = findfret(tgs_p, mll_p, strno);
785 if (fret == NOFRET)
786 pfatal("cannot find fret number for tablature note");
787
788 /*
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.
793 */
794 calcnote(&strinfo[strno], fret, bend, sharps, &notes[idx++],
795 tgs_p);
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];
802 notes[k] = tempnote;
803 }
804 }
805 }
806
807 /*
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.
810 */
811 if (pregs_p != 0)
812 popnotes(pregs_p, prenotes, pidx, tgs_p, mll_p, YES, NO,sharps);
813
814 popnotes(ngs_p, notes, idx, tgs_p, mll_p, NO, combine, sharps);
815}
816\f
817/*
818 * Name: calcnote()
819 *
820 * Abstract: Calculate note info for a tabnote NOTE structure.
821 *
822 * Returns: void
823 *
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.
831 */
832
833static void
834calcnote(sinfo_p, fret, bend, sharps, note_p, tgs_p)
835
836struct STRINGINFO *sinfo_p; /* pointer to info about the string */
837int fret; /* fret number on the string */
838RATIONAL bend; /* bend distance */
839int sharps; /* number of sharps in tabnote staff's keysig*/
840struct TABNOTENOTE *note_p; /* note structure to be filled */
841struct GRPSYL *tgs_p; /* pointer to tab group */
842
843{
844 /*
845 * The following table, indexed by a note letter minus 'a', tells how
846 * many half steps that note is above C.
847 */
848 static int hstab[] = { 9, 11, 0, 2, 4, 5, 7 };
849 /* a b c d e f g */
850 /*
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.
854 */
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 */
858 /*
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.
862 */
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 */
866
867 /*
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&.
873 */
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 */
877
878
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.) */
887
888
889 /*
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.
893 */
894 bendqs = rmul(bend, Four);
895 if (bendqs.n % 2 == 1 && bendqs.d == 1) {
896 hs = bendqs.n / 2;
897 } else {
898 bendqs = radd(bendqs, One);
899 hs = bendqs.n / bendqs.d / 2;
900 }
901
902 /* add on the half steps due to letter, octave, and fret */
903 hs += hstab[ sinfo_p->letter - 'a' ] + 12 * sinfo_p->octave + fret;
904
905 /* adjust if string has an accidental; only '#' and '&' are allowed */
906 switch (sinfo_p->accidental) {
907 case '#':
908 hs++; /* sharp */
909 break;
910 case '&':
911 hs--; /* flat */
912 break;
913 }
914
915 /* hs is now the correct note, in half steps above c0 */
916 note_p->hs = hs;
917
918 /*
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
922 * do it.
923 *
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#.
930 *
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.
939 */
940
941 /*
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.
945 */
946 keyhs = sh2keyhs[sharps + 7];
947 intervhs = (hs + 12 - keyhs) % 12;
948
949 /* find how many letters above the key letter this note should be */
950 intervlet = hs2s[intervhs];
951
952 /* find the key letter (c = 0, d = 1, etc.) */
953 keyletidx = sh2keylet[sharps + 7];
954
955 /* find the letter that should be used for this note */
956 note_p->letter = "cdefgab"[(keyletidx + intervlet) % 7];
957
958 /*
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.
961 */
962 octacc = hs - hstab[ note_p->letter - 'a' ];
963
964 /*
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.
968 */
969 note_p->octave = (octacc + 12 + 6) / 12 - 1;
970 accoffset = octacc - 12 * note_p->octave;
971 note_p->accidental = Acclets[accoffset + 2];
972
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");
978 }
979}
980\f
981/*
982 * Name: findfret()
983 *
984 * Abstract: Find fret number that applies to the given GRPSYL.
985 *
986 * Returns: The fret number, or NOFRET if none found.
987 *
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.
997 */
998
999static int
1000findfret(tgs_p, mll_p, strno)
1001
1002struct GRPSYL *tgs_p; /* tab GRPSYL to start from */
1003struct MAINLL *mll_p; /* MLL struct it hangs off of */
1004int strno; /* string number */
1005
1006{
1007 int n; /* for looping through notelist */
1008
1009
1010 /* loop until we find the fret or something goes wrong */
1011 for (;;) {
1012 /* the GRPSYL must contain notes */
1013 if (tgs_p->grpcont != GC_NOTES)
1014 return (NOFRET);
1015
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)
1019 break;
1020 }
1021 if (n == tgs_p->nnotes)
1022 return (NOFRET);
1023
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);
1027
1028 /* search backwards for the next GRPSYL, which must exist */
1029 tgs_p = prevgrpsyl(tgs_p, &mll_p);
1030 if (tgs_p == 0)
1031 return (NOFRET);
1032 }
1033}
1034\f
1035/*
1036 * Name: popnotes()
1037 *
1038 * Abstract: Adjust the desired notes and populate the NOTE structures.
1039 *
1040 * Returns: void
1041 *
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.
1046 */
1047
1048static void
1049popnotes(ngs_p, tnn, ntnn, tgs_p, mll_p, is_prebend, combine, sharps)
1050
1051struct GRPSYL *ngs_p; /* tabnote GRPSYL */
1052struct TABNOTENOTE tnn[]; /* array of TABNOTENOTE structures */
1053int ntnn; /* number of the above structures */
1054struct GRPSYL *tgs_p; /* tablature GRPSYL we came from */
1055struct MAINLL *mll_p; /* main LL structure we came from */
1056int is_prebend; /* is this a prebend group? */
1057int combine; /* this group formed by combining tab grps? */
1058int sharps; /* current key signature */
1059
1060{
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 */
1071
1072
1073 /*
1074 * Loop through the notes, throwing away duplicates. They are already
1075 * in order, highest note first.
1076 */
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);
1082
1083 for (k = n; k < ntnn; k++)
1084 tnn[k - 1] = tnn[k];
1085 ntnn--;
1086 n--;
1087 }
1088 }
1089
1090 /*
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.
1103 */
1104 for (n = 1; n < ntnn; n++) {
1105 if (tnn[n - 1].letter == tnn[n].letter &&
1106 tnn[n - 1].octave == tnn[n].octave) {
1107 /*
1108 * We have a conflict. See whether the notes next to
1109 * the conflicting notes (if any) are on neighboring
1110 * steps.
1111 */
1112 if (n > 1 && neighbor(&tnn[n - 2], &tnn[n - 1]) == YES)
1113 hightight = YES;
1114 else
1115 hightight = NO;
1116
1117 if (n < ntnn-1 && neighbor(&tnn[n], &tnn[n + 1]) == YES)
1118 lowtight = YES;
1119 else
1120 lowtight = NO;
1121
1122 /* remember which of the notes is in the key sig */
1123 if (inkeysig(&tnn[n], sharps) == YES) {
1124 keysigidx = n;
1125 nonkeysigidx = n - 1;
1126 } else {
1127 keysigidx = n - 1;
1128 nonkeysigidx = n;
1129 }
1130
1131 remnote = NO; /* init to not remove any note */
1132
1133 if (hightight == YES && lowtight == YES) {
1134 /* no room to move either note */
1135 remnote = YES;
1136 } else if (hightight == YES) {
1137 /* no room to move high note; move low note */
1138 if (downletter(&tnn[n]) == NO) {
1139 /* can't move it */
1140 remnote = YES;
1141 }
1142 } else if (lowtight == YES) {
1143 /* no room to move low note; move high note */
1144 if (upletter(&tnn[n - 1]) == NO) {
1145 /* can't move it */
1146 remnote = YES;
1147 }
1148 } else {
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 */
1155 remnote = YES;
1156 }
1157 } else {
1158 /* try moving nonkeysig note first */
1159 if (downletter(&tnn[n]) == NO &&
1160 upletter(&tnn[n - 1]) == NO) {
1161 /* can't move either */
1162 remnote = YES;
1163 }
1164 }
1165 }
1166
1167 /*
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.
1171 */
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);
1181
1182 for (k = nonkeysigidx + 1; k < ntnn; k++)
1183 tnn[k - 1] = tnn[k];
1184 ntnn--;
1185 n--;
1186 }
1187 }
1188 }
1189
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);
1193
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);
1197
1198 CALLOC(NOTE, ngs_p->notelist, ntnn);
1199 ngs_p->nnotes = (short)ntnn;
1200
1201 /*
1202 * Loop through the newly allocated notes, setting all their fields.
1203 */
1204 for (n = 0; n < ntnn; n++) {
1205 newnote_p = &ngs_p->notelist[n]; /* set short cut pointer */
1206
1207 /* allocate the array of coordinates */
1208 MALLOCA(float, ngs_p->notelist[n].c, NUMCTYPE);
1209
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;
1214
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;
1218
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;
1222
1223 /* flag to draw curved line after notes */
1224 if (combine)
1225 newnote_p->smallbend = YES;
1226
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;
1229 if (is_prebend)
1230 newnote_p->note_has_paren = YES;
1231
1232 /*
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.
1240 */
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);
1245
1246 for (k = 0; k < newnote_p->nslurto; k++) {
1247 s_p = &tnn[n].note_p->slurtolist[k];
1248
1249 if (IS_NOWHERE(s_p->octave)) {
1250 /* slur to or from nowhere */
1251 /* letter is meaningless */
1252 newnote_p->slurtolist[k].octave =
1253 s_p->octave;
1254 } else { /* real fret number */
1255 newnote_p->slurtolist[k].letter =
1256 tnn[n].strno;
1257 newnote_p->slurtolist[k].octave =
1258 NOFRET; /* unknown */
1259 }
1260
1261 /* always copy slur style */
1262 newnote_p->slurtolist[k].slurstyle =
1263 s_p->slurstyle;
1264 }
1265 }
1266
1267 /*
1268 * If we are a prebend note, allocate a slur-to list.
1269 */
1270 if (is_prebend) {
1271 CALLOC(SLURTO, newnote_p->slurtolist, 1);
1272 newnote_p->is_bend = YES;
1273 newnote_p->nslurto = 1;
1274 /*
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.
1281 */
1282 newnote_p->slurtolist[0].letter = tnn[n].strno;
1283 newnote_p->slurtolist[0].octave = NOFRET;
1284 }
1285
1286 /*
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
1293 * list.
1294 */
1295 if ( ! is_prebend && ! combine && nexttgs_p != 0) {
1296 for (k = 0; k < nexttgs_p->nnotes; k++) {
1297 /*
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.
1301 */
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])))
1306 break;
1307 }
1308 if (k < nexttgs_p->nnotes) {
1309 if (newnote_p->nslurto != 0)
1310 pfatal("slur and bend on the same note [popnotes]");
1311
1312 CALLOC(SLURTO, newnote_p->slurtolist, 1);
1313 newnote_p->is_bend = YES;
1314 newnote_p->nslurto = 1;
1315 /*
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
1321 * the octave too.
1322 */
1323 newnote_p->slurtolist[0].letter = tnn[n].strno;
1324 }
1325 }
1326
1327 /*
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.
1334 */
1335 if ( ! is_prebend && prevngs_p != 0) {
1336 /*
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.
1342 */
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;
1347 j++) {
1348 s_p = &prevngs_p->notelist[k].
1349 slurtolist[j];
1350 if (s_p->letter == tnn[n].strno &&
1351 ! IS_NOWHERE(s_p->octave))
1352 break;
1353 }
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;
1358 }
1359 }
1360 }
1361 }
1362}
1363\f
1364/*
1365 * Name: neighbor()
1366 *
1367 * Abstract: Find whether the given notes are on neighboring letters.
1368 *
1369 * Returns: YES or NO
1370 *
1371 * Description: This function figures out whether the given notes are on
1372 * neighboring letter, taking octaves into account.
1373 */
1374
1375static int
1376neighbor(high_p, low_p)
1377
1378struct TABNOTENOTE *high_p; /* the higher note */
1379struct TABNOTENOTE *low_p; /* the lower note */
1380
1381{
1382 /* if the letter themselves aren't right, return NO */
1383 if (low_p->letter == 'g') {
1384 if (high_p->letter != 'a')
1385 return (NO);
1386 } else {
1387 if (high_p->letter != low_p->letter + 1)
1388 return (NO);
1389 }
1390
1391 /* if the octaves aren't right, return NO */
1392 if (low_p->letter == 'b') {
1393 if (high_p->octave != low_p->octave + 1)
1394 return (NO);
1395 } else {
1396 if (high_p->octave != low_p->octave)
1397 return (NO);
1398 }
1399
1400 return (YES);
1401}
1402\f
1403/*
1404 * Name: inkeysig()
1405 *
1406 * Abstract: Find whether the given note fits the key signature.
1407 *
1408 * Returns: YES or NO
1409 *
1410 * Description: This function figures out whether the given note fits the key
1411 * signature, and returns the answer.
1412 */
1413
1414static int
1415inkeysig(note_p, sharps)
1416
1417struct TABNOTENOTE *note_p; /* note contained in a TABNOTENOTE structure */
1418int sharps; /* current key signature */
1419
1420{
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 */
1424
1425
1426 circnum = strchr(Circle, note_p->letter) - Circle;
1427 accnum = strchr(Acclets, note_p->accidental) - Acclets;
1428 sharpness = circnum + 7 * (accnum - 2);
1429
1430 if (sharpness >= sharps && sharpness <= sharps + 6)
1431 return (YES);
1432 else
1433 return (NO);
1434}
1435\f
1436/*
1437 * Name: upletter()
1438 *
1439 * Abstract: Alter note enharmonically, incrementing the letter.
1440 *
1441 * Returns: void
1442 *
1443 * Description: This function alters the given note enharmonically. It raises
1444 * the letter, and adjusts the accidental and octave as needed.
1445 */
1446
1447static int
1448upletter(note_p)
1449
1450struct TABNOTENOTE *note_p; /* note contained in a TABNOTENOTE structure */
1451
1452{
1453 int accnum; /* B = 0, & = 1, n = 2, # = 3, x = 4 */
1454
1455
1456 accnum = strchr(Acclets, note_p->accidental) - Acclets;
1457
1458 /*
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.
1463 */
1464 if (note_p->letter == 'e' || note_p->letter == 'b') {
1465 if (accnum == 0) /* double flat */
1466 return (NO);
1467 accnum--;
1468 } else {
1469 if (accnum <= 1) /* flat or double flat */
1470 return (NO);
1471 accnum -= 2;
1472 }
1473
1474 /* if the note is b, increment the octave; fail if impossible */
1475 if (note_p->letter == 'b') {
1476 if (note_p->octave == MAXOCTAVE)
1477 return (NO);
1478 note_p->octave++;
1479 }
1480
1481 /* increment the letter; g wraps around to a */
1482 if (note_p->letter == 'g')
1483 note_p->letter = 'a';
1484 else
1485 note_p->letter++;
1486
1487 note_p->accidental = Acclets[accnum];
1488
1489 return (YES);
1490}
1491\f
1492/*
1493 * Name: downletter()
1494 *
1495 * Abstract: Alter note enharmonically, decrementing the letter.
1496 *
1497 * Returns: void
1498 *
1499 * Description: This function alters the given note enharmonically. It lowers
1500 * the letter, and adjusts the accidental and octave as needed.
1501 */
1502
1503static int
1504downletter(note_p)
1505
1506struct TABNOTENOTE *note_p; /* note contained in a TABNOTENOTE structure */
1507
1508{
1509 int accnum; /* B = 0, & = 1, n = 2, # = 3, x = 4 */
1510
1511
1512 accnum = strchr(Acclets, note_p->accidental) - Acclets;
1513
1514 /*
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.
1519 */
1520 if (note_p->letter == 'f' || note_p->letter == 'c') {
1521 if (accnum == 4) /* double sharp */
1522 return (NO);
1523 accnum++;
1524 } else {
1525 if (accnum >= 3) /* sharp or double sharp */
1526 return (NO);
1527 accnum += 2;
1528 }
1529
1530 /* if the note is c, decrement the octave; fail if impossible */
1531 if (note_p->letter == 'c') {
1532 if (note_p->octave == MINOCTAVE)
1533 return (NO);
1534 note_p->octave--;
1535 }
1536
1537 /* decrement the letter; a wraps around to g */
1538 if (note_p->letter == 'a')
1539 note_p->letter = 'g';
1540 else
1541 note_p->letter--;
1542
1543 note_p->accidental = Acclets[accnum];
1544
1545 return (YES);
1546}
1547\f
1548/*
1549 * Name: cleanaccs()
1550 *
1551 * Abstract: Remove unnecessary accidentals from a tabnote staff measure.
1552 *
1553 * Returns: void
1554 *
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.
1565 */
1566
1567static void
1568cleanaccs(gs_p, mll_p)
1569
1570struct GRPSYL *gs_p; /* starts at first tabnote GRPSYL */
1571struct MAINLL *mll_p; /* main LL struct that tabnote staff hangs off*/
1572
1573{
1574 /* current accidental for letter and octave */
1575 char curacc[7][MAXOCTAVE + 1]; /* assumes MINOCTAVE == 0 */
1576
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 */
1584
1585
1586
1587 /*
1588 * Initialize the table to say that for all octaves of all letters,
1589 * the accidental is a natural.
1590 */
1591 for (oct = 0; oct <= MAXOCTAVE; oct++) {
1592 for (let = 'a'; let <= 'g'; let++) {
1593 curacc[let - 'a'] [oct] = 'n';
1594 }
1595 }
1596
1597 /* find the key signature; flats count negative */
1598 sharps = svpath(gs_p->staffno, SHARPS)->sharps;
1599
1600 /*
1601 * Load the key signature's accidentals into the array for every
1602 * octave.
1603 */
1604 for (oct = 0; oct <= 9; oct++) {
1605 for (cidx = 0; cidx < sharps; cidx++) {
1606 curacc[ Circle[cidx] - 'a' ] [oct] = '#';
1607 }
1608 for (cidx = 0; cidx > sharps; cidx--) {
1609 curacc[ Circle[6 + cidx] - 'a' ] [oct] = '&';
1610 }
1611 }
1612
1613 /*
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.
1617 */
1618 for ( ; gs_p != 0; gs_p = gs_p->next) {
1619 if (gs_p->grpcont != GC_NOTES)
1620 continue;
1621
1622 /* find previous group; could be in previous measure if any */
1623 prevgs_p = prevgrpsyl(gs_p, &mll_p);
1624
1625 for (n = 0; n < gs_p->nnotes; n++) {
1626 note_p = &gs_p->notelist[n];
1627
1628 /*
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.
1632 */
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';
1640 break;
1641 }
1642 }
1643 /* if we found it was tied, continue to next */
1644 if (k < prevgs_p->nnotes)
1645 continue;
1646 }
1647 /*
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.
1652 */
1653 if (note_p->accidental == curacc[ note_p->letter - 'a' ]
1654 [ note_p->octave ]) {
1655 note_p->accidental = '\0';
1656 } else {
1657 curacc[ note_p->letter - 'a' ] [ note_p->
1658 octave ] = note_p->accidental;
1659 }
1660 }
1661 }
1662}