Commit | Line | Data |
---|---|---|
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 | */ | |
18 | struct 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 | ||
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, | |
31 | RATIONAL *comp_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)); | |
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 | ||
60 | void | |
61 | tab2tabnote() | |
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 | ||
129 | static void | |
130 | tabv2tabnotev(mainll_p, vidx) | |
131 | ||
132 | struct MAINLL *mainll_p; /* main LL struct for this staff */ | |
133 | int 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 | ||
472 | static void | |
473 | fixprevmeas(ngs_p, mll_p) | |
474 | ||
475 | struct GRPSYL *ngs_p; /* tabnote GRPSYL */ | |
476 | struct 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 | ||
554 | static int | |
555 | hasprebend(tgs_p) | |
556 | ||
557 | struct 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 | ||
589 | static int | |
590 | cancombine(mll_p, tgs_p, comb_p) | |
591 | ||
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 */ | |
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 | ||
676 | static RATIONAL | |
677 | calctime(gs_p) | |
678 | ||
679 | struct 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 | ||
715 | static void | |
716 | translate_group(tgs_p, pregs_p, ngs_p, mll_p, combine) | |
717 | ||
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?*/ | |
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, ¬es[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 | ||
833 | static void | |
834 | calcnote(sinfo_p, fret, bend, sharps, note_p, tgs_p) | |
835 | ||
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 */ | |
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 | ||
999 | static int | |
1000 | findfret(tgs_p, mll_p, strno) | |
1001 | ||
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 */ | |
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 | ||
1048 | static void | |
1049 | popnotes(ngs_p, tnn, ntnn, tgs_p, mll_p, is_prebend, combine, sharps) | |
1050 | ||
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 */ | |
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 | ||
1375 | static int | |
1376 | neighbor(high_p, low_p) | |
1377 | ||
1378 | struct TABNOTENOTE *high_p; /* the higher note */ | |
1379 | struct 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 | ||
1414 | static int | |
1415 | inkeysig(note_p, sharps) | |
1416 | ||
1417 | struct TABNOTENOTE *note_p; /* note contained in a TABNOTENOTE structure */ | |
1418 | int 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 | ||
1447 | static int | |
1448 | upletter(note_p) | |
1449 | ||
1450 | struct 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 | ||
1503 | static int | |
1504 | downletter(note_p) | |
1505 | ||
1506 | struct 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 | ||
1567 | static void | |
1568 | cleanaccs(gs_p, mll_p) | |
1569 | ||
1570 | struct GRPSYL *gs_p; /* starts at first tabnote GRPSYL */ | |
1571 | struct 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 | } |