chiark / gitweb /
Import upstream version 5.3.
[mup] / mup / mup / midi.c
1
2 /* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 by Arkkra Enterprises */
3 /* All rights reserved */
4
5 /* generate a MIDI file from the Mup internal representation */
6
7 #include <fcntl.h>
8 #include <string.h>
9 #include <unistd.h>
10 #ifdef __WATCOMC__
11 #include <io.h>
12 #endif
13 #include "defines.h"
14 #include "structs.h"
15 #include "globals.h"
16
17
18 /* Minimum and maximum number of quarter notes per minute.
19  * This should be ridiculously wide enough range and
20  * also prevents division by zero when calculating microsecs per quarter */
21 #define MINQNPM         (10)
22 #define MAXQNPM         (1000)
23
24 /* Default value for microseconds per quarter note */
25 #define DFLT_USEC_PER_QUARTER   (500000L)
26
27 #define USEC_PER_MINUTE         (60L * 1000000)
28
29 /* it is possible to get a legitimate rational overflow, and we don't really
30  * care about absolutely precise time, so when a rational gets bigger than
31  * MAXMIDI_RAT, throw away the lower bits and reduce */
32 #define MAXMIDI_RAT     1000000L
33 /* delta can get multiplied by MIDI_FACTOR. Need to make sure it can
34  * never overflow a signed long, or bad things can happen,
35  * so need smaller limit. */
36 #define MAXDELTA_RAT    300000L
37
38 /* This marks that we don't have to defer a sharp/flat. We have to defer
39  * them if a note is tied over a barline. The value has to be something
40  * outside the normal accidental range of -2 (double flat) to +2 (double sharp)
41  */
42 #define NO_DEFERRED_ACC (-100)
43
44 /* save information about stuff for the current measure so that it can
45  * be applied at the proper time. */
46 struct MIDISTUFF {
47         RATIONAL        time;           /* when to do the MIDI event */
48         struct STUFF    *stuff_p;       /* STUFF to do */
49         struct MIDISTUFF *next;         /* linked list */
50 };
51
52 /* if a roll spans multiple groups, save information about the other
53  * groups. The reason for saving it around rather than just walking down the
54  * gs_p chord list is that if the added groups have to go at the very
55  * beginning of the measure, the only way to find where to link them is to
56  * go back to the main list and search for the appropriate STAFF and follow
57  * one of the groups_p lists. Since we'll get around to visiting that STAFF
58  * eventually anyway, just save the info and do it when we get there. */
59 struct MIDIROLL {
60         struct GRPSYL   *gs_p;          /* group roll applies to */
61         short           notesbefore;    /* how many notes duration of rest
62                                          * to add before this group's portion
63                                          * of the roll */
64         RATIONAL        duration;       /* duration of each note in roll */
65         struct MIDIROLL *link_p;        /* linked list  */
66 };
67
68 /* stuff is in floating point, but we keep track of time in RATIONAL. So
69  * when we need to convert, put in terms of 1/F2RFACTOR of a count */
70 #define F2RFACTOR       ((UINT32B)(192L * 256L))
71
72 /* Number of ticks in a whole note */
73 #define MIDI_FACTOR     ((UINT32B)(4L * Division))
74
75 /* default note on velocity */
76 #define DFLT_VELOCITY   (64)
77
78 /* the MIDI STUFF info for current measure/voice */
79 static struct MIDISTUFF *Midistufflist_p;
80
81 /* list of pending rolls to do */
82 static struct MIDIROLL *Midirollinfo_p;
83
84 /* tables for mapping voices to tracks and vice versa */
85 static short Voice2track_map [MAXSTAFFS + 1] [MAXVOICES];
86 static short Track2staff_map [MAXSTAFFS * MAXVOICES];
87 static short Track2voice_map [MAXSTAFFS * MAXVOICES];
88
89 static short Accidental_map[128];/* if a note has an implied accidental, either
90                                  * due to the key signature or an accidental
91                                  * earlier in the measure, this table tells
92                                  * how to adjust the note. For example, if
93                                  * we have a C, but are in the key of D, the
94                                  * table entry for C would have a 1 to say to
95                                  * add 1 because it should really be a C# */
96 static short Deferred_acc[128]; /* If set to something other than
97                                  * NO_DEFERRED_ACC, then once the current
98                                  * tie on this note ends, we need to set the
99                                  * Accidental_map entry to this value. */
100 static short Tie_table[128];    /* YES if note number has a tie on it */
101
102 /* keep track of all time to an absolute reference so that all tracks stay
103  * in sync, even though midi times are stored as delta times */
104 static RATIONAL Absolute_time;
105 static RATIONAL Sum_of_deltas;
106
107 static int Status;      /* 0 if haven't yet written first MIDI status byte
108                          * for current track. Otherwise is the current MIDI
109                          * status byte. */
110
111 static short Channel = 0;       /* MIDI channel, 0-15 */
112 static char Onvelocity[MAXHAND];        /* note on velocity */
113 static char Offvelocity[MAXHAND];       /* note off velocity */
114 static short Time_specified_by_user = NO;       /* YES if user had a score SSV
115                                  * setting the time before any music data */
116 static short Key_specified_by_user = NO;        /* YES if user had a score SSV
117                                  * setting the key before any music data */
118 static int Division = DEFDIVISION;      /* clock ticks per quarter note */
119
120 static UINT32B Usec_per_quarter_note = DFLT_USEC_PER_QUARTER;
121
122 static short Pedbounce = NO;    /* if pedal bounce pending */
123
124 /* local functions */
125 static void repeats P((struct MAINLL **mll_p_p, int *doing_repeat_p,
126                 struct MAINLL **repeat_start_p_p));
127 static RATIONAL eff_meas_time P((struct MAINLL *mll_p));
128 static void midi_header P((int mfile, int ntracks));
129 static void track_header P((int mfile));
130 static UINT32B write_midi_data P((int mfile, struct GRPSYL *gs_p));
131 static void init_accidental_map P((int staffno));
132 static void mark_accidental P((int pitch_offset, int acc));
133 static UINT32B midi_multirest P((int mfile, struct STAFF *staff_p, int staffno,
134                 int vno, int nummeas));
135 static void init_tie_table P((void));
136 static int xlate_note P((struct NOTE *note_p, char *fname, int lineno,
137                 int *raw_notenum_p));
138 static void prepmidi_stuff P((struct STAFF *staff_p, int vno, int all));
139 static UINT32B do_midi_stuff P((RATIONAL timeval, int mfile, int all));
140 static UINT32B midihex P((int mfile, char *str, char *fname, int lineno));
141 static UINT32B midi_item P((struct STUFF *stuff_p, int mfile, int all));
142 static UINT32B wr_meta P((int mfile, int evtype, char *str));
143 static UINT32B all_midi P((int mfile));
144 static void midi_adjust P((void));
145 static void adjust_notes P((struct GRPSYL *gs_p, int staffno, int v,
146                 struct MAINLL *mll_p));
147 static void add_release P((struct GRPSYL *gs_p, RATIONAL release_adjust,
148                 struct MAINLL *mll_p));
149 static UINT32B pedswitch P((int nfile, int on));
150 static void midi_roll P((struct GRPSYL *gs_p, struct GRPSYL **gslist_p_p));
151 static RATIONAL roll_time P((RATIONAL grptime, int nnotes));
152 static void do_mroll P((struct GRPSYL *gs_p, struct GRPSYL **gslist_p_p,
153                 RATIONAL rolltime, int notesbefore));
154 static void addrollgrp P((struct GRPSYL *gs_p, RATIONAL duration, int start,
155                 int end, struct GRPSYL **link_p_p, struct GRPSYL *prev_p));
156 static void savemidiroll P((struct GRPSYL *gs_p, int notesbefore,
157                 RATIONAL duration));
158 static struct MIDIROLL *getmidiroll P((struct GRPSYL *gs_p));
159 static void fix_tempo P((int to_end));
160 static void free_midistuff P((struct MIDISTUFF *ms_p));
161 static void adj4squeeze P((RATIONAL timeval));
162 \f
163
164 /* generate a MIDI file. Assigns each staff/voice combo to a MIDI track.
165  * Write MIDI file header and first track with tempo, etc info. Then for
166  * each staff/voice, generate a MIDI track with all note on/off and
167  * whatever STUFF we know how to deal with. */
168
169 void
170 gen_midi(midifilename)
171
172 char *midifilename;             /* put MIDI data in this file */
173
174 {
175         struct MAINLL *mll_p;   /* to index through main list */
176         int i;
177         int track = 0;
178         int staff;
179         int vno;                /* voice index */
180         int mfile;              /* file descriptor for MIDI output file */
181         UINT32B track_size;     /* bytes in track */
182         UINT32B track_start;    /* offset in file where track begins */
183         int t;                  /* track index */
184         int doing_repeat;       /* YES or NO */
185         int got_data;           /* YES or NO, to deal with case where the
186                                  * number of staffs/voices changes mid-stream */
187         struct MAINLL *repeat_start_p;  /* pointer to first measure of a
188                                          * repeated section, so we know where to
189                                          * jump back to when we hit the end of
190                                          * the repeat. */
191         struct STAFF *staff_p;  /* need to refer to STAFF a lot, so keep a
192                                  * pointer to it. */
193         struct STAFF *last_staff_p = (struct STAFF *) 0;/* in case measure
194                                  * was invisible or something,
195                                  * this points to the most recent
196                                  * staff for current loop */
197         struct GRPSYL *g_p;
198         int first;              /* YES/NO if processing first meas */
199
200
201         debug(256, "gen_midi");
202
203         /* first go through main list, and find out which staff/voice pairs
204          * are used, and assign each to a track. */
205         for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
206                                         mll_p = mll_p->next) {
207
208                 if (mll_p->str == S_STAFF) {
209                         staff = mll_p->u.staff_p->staffno;
210
211                         /* ignore tab staffs -- we use the notes on the
212                          * associated tabnote staff above it instead */
213                         if (is_tab_staff(staff) == YES) {
214                                 continue;
215                         }
216
217                         for (vno = 0; vno < MAXVOICES; vno++) {
218
219                                 if (mll_p->u.staff_p->groups_p[vno] ==
220                                                 (struct GRPSYL *) 0) {
221                                         continue;
222                                 }
223
224                                 if (Voice2track_map [staff] [vno] == 0) {
225                                         /* haven't allocated this staffno/vno to
226                                          * a track yet, so do so now. */
227                                         Track2staff_map [track] = (short) staff;
228                                         Track2voice_map [track] = (short) vno;
229                                         Voice2track_map [staff] [vno] = ++track;
230                                         debug(512, "assigned staff %d voice %d to track %d",
231                                                         staff, vno + 1, track);
232                                 }
233                         }
234                 }
235         }
236
237         if (track == 0) {
238                 ufatal("no note data found");
239         }
240
241         /* open the specified MIDI file */
242 #ifdef O_BINARY
243         if ((mfile = open(midifilename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666))
244 #else
245         if ((mfile = open(midifilename, O_WRONLY | O_CREAT | O_TRUNC, 0666))
246 #endif
247                                                                         < 0) {
248                 ufatal("can't open MIDI file '%s'", midifilename);
249         }
250
251         /* adjust grace notes to get a little time, etc */
252         midi_adjust();
253
254         /* squeeze out any all-space chords */
255         midi_squeeze();
256
257         /* the default Guitar tablature staff notes get transposed an octave,
258          * so do that if appropriate */
259         guitar_transpose();
260
261         /* generate MIDI file header */
262         initstructs();
263         Usec_per_quarter_note = DFLT_USEC_PER_QUARTER;
264         midi_header(mfile, track);
265
266         /* go through  the main list once for each staff/voice, generating a
267          * MIDI track for it. */
268         for (t = 0; t < track; t++)  {
269
270                 /* initialize everything for this track */
271                 initstructs();
272                 init_tie_table();
273                 track_start = lseek(mfile, 0L, SEEK_CUR);
274                 track_header(mfile);
275                 staff = Track2staff_map[t];
276                 vno = Track2voice_map[t];
277                 track_size = 0;
278                 doing_repeat = NO;
279                 repeat_start_p = Mainllhc_p;
280                 got_data = NO;
281                 Octave_adjust[staff] = 0;
282                 Octave_bars[staff] = 0;
283                 Octave_count[staff] = 0.0;
284                 Channel = 0;
285                 first = YES;
286                 for (i = 0; i < MAXHAND; i++) {
287                         Onvelocity[i] = (char) DFLT_VELOCITY;
288                         Offvelocity[i] = (char) 0;
289                 }
290
291                 /* go through main list */
292                 for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
293                                                 mll_p = mll_p->next) {
294
295                         switch (mll_p->str) {
296
297                         case S_STAFF:
298                                 /* There may be an implicit repeatstart at
299                                  * the beginning of the piece, so we need
300                                  * to save the current SSV state, in case
301                                  * the user repeats back to this implicit
302                                  * repeatstart. */
303                                 if (first == YES) {
304                                         repeat_start_p = mll_p;
305                                         first = NO;
306                                 }
307
308                                 staff_p = mll_p->u.staff_p;
309                                 /* check if this is for the staff we are
310                                  * currently generating midi data for */
311                                 if (staff_p->staffno == staff
312                                                 && staff_p->groups_p[vno]
313                                                 != (struct GRPSYL *) 0) {
314
315                                         /* treat invisible staffs as
316                                          * inaudible as well */
317                                         if (svpath(staff, VISIBLE) ->visible
318                                                                 == NO) {
319                                                 /* if next staff is a tab staff,
320                                                  * and it is visible, then we
321                                                  * want this staff to still be
322                                                  * audible, otherwise skip */
323                                                 if (staff >= Score.staffs ||
324                                                         ! is_tab_staff(staff+1)
325                                                         || svpath(staff+1, VISIBLE)->visible == NO) {
326                                                     /* convert notes to rests.
327                                                      * Can't just ignore,
328                                                      * because if we do, space
329                                                      * that has been squeezed
330                                                      * out isn't handled right,
331                                                      * and tracks can get out of
332                                                      * sync with each other */
333                                                     for (g_p = staff_p->groups_p[vno];
334                                                     g_p != (struct GRPSYL *) 0;
335                                                     g_p = g_p->next) {
336                                                         if (g_p->nnotes > 0) {
337                                                                 g_p->grpcont
338                                                                 = GC_REST;
339                                                         }
340                                                     }
341                                                 }
342                                         }
343
344                                         /* found information for the track/voice
345                                          * we are currently generating */
346                                         got_data = YES;
347
348                                         /* check for multi-rest */
349                                         if (staff_p->groups_p[vno]->basictime
350                                                                         < -1) {
351                                                 track_size += midi_multirest
352                                                         (mfile, staff_p,
353                                                         staff, vno,
354                                                         -(staff_p->groups_p[vno]
355                                                         ->basictime) );
356                                                 break;
357                                         }
358
359                                         /* generate MIDI data */
360                                         /* Handle octave marks, but only first
361                                          * time through a repeat, or it will
362                                          * get transposed twice! */
363                                         if (doing_repeat == NO) {
364                                                 octave_transpose(staff_p, mll_p,
365                                                                 vno, YES);
366                                         }
367                                         init_accidental_map(staff);
368                                         prepmidi_stuff(staff_p, vno, NO);
369                                         track_size += write_midi_data(mfile,
370                                                 staff_p->groups_p[vno]);
371                                 }
372                                 else if (staff_p->staffno == staff) {
373                                         /* Voice doesn't exist in this meas,
374                                          * so just keep track of the staff
375                                          * so when we hit the bar we can
376                                          * add the silence, and update any
377                                          * midi parameters and such. */
378                                         last_staff_p = staff_p;
379                                 }
380                                 break;
381
382                         case S_SSV:
383                                 asgnssv(mll_p->u.ssv_p);
384
385                                 /* update key signature for this track
386                                  * if necessary. Note that score-wide
387                                  * key signature changes will be written
388                                  * out via all_midi(). */
389                                 if (mll_p->u.ssv_p->context == C_STAFF &&
390                                                 mll_p->u.ssv_p->staffno
391                                                 == staff &&
392                                                 (mll_p->u.ssv_p->used[SHARPS]
393                                                 == YES ||
394                                                 mll_p->u.ssv_p->used[TRANSPOSITION]
395                                                 == YES ||
396                                                 mll_p->u.ssv_p->used[ADDTRANSPOSITION]
397                                                 == YES) ) {
398                                         track_size += midi_keysig(mfile,
399                                                 eff_key(mll_p->u.ssv_p->staffno),
400                                                 mll_p->u.ssv_p->is_minor);
401                                 }
402                                 break;
403
404                         case S_BAR:
405                                 /* if this voice is defined somewhere in the
406                                  * song, but not in this measure, need to add
407                                  * virtual measure of rest. (This could happen
408                                  * if user changed the number of staffs
409                                  * and/or voices in mid-stream */
410                                 if (got_data == NO && mll_p->inputlineno != -1) {
411                                         /* Arrange to do any midi things
412                                          * for this voice, even though it
413                                          * doesn't exist at the moment. */
414                                         if (last_staff_p != (struct STAFF *) 0) {
415                                                 prepmidi_stuff(last_staff_p,
416                                                                 vno, NO);
417                                         }
418                                         /* This will update the current
419                                          * absolute time to include the
420                                          * effective time for this measure. */
421                                         track_size += do_midi_stuff(
422                                                         eff_meas_time(mll_p),
423                                                         mfile, NO);
424                                         last_staff_p = (struct STAFF *) 0;
425                                 }
426                                 else {
427                                         got_data = NO;
428                                 }
429
430                                 /* handle repeats */
431                                 repeats(&mll_p, &doing_repeat, &repeat_start_p);
432
433                                 break;
434
435                         default:
436                                 break;
437                         }
438
439                         if (mll_p == (struct MAINLL *) 0) {
440                                 /* shouldn't happen, but repeats() can change
441                                  * mll_p, and if it ever became null, we'd
442                                  * try to take the ->next of it, which isn't
443                                  * good, so take precautions */
444                                 break;
445                         }
446                 }
447
448                 /* add end of track mark */
449                 track_size += write(mfile, "\0\377/\0", 4);
450
451                 /* now that we know the track size, fill it in */
452                 fix_track_size(mfile, track_start, track_size);
453         }
454
455         (void) close(mfile);
456 }
457 \f
458
459 /* given a bar, handle repeats at that bar line. First time we hit the end
460  * of a repeated section, go back to its beginning. Handles the case where
461  * the repeat end is at the end of an ending. */
462
463 static void
464 repeats (mll_p_p, doing_repeat_p, repeat_start_p_p)
465
466 struct MAINLL **mll_p_p;        /* points to a BAR */
467 int *doing_repeat_p;            /* return YES or NO via this pointer to
468                                  * indicate whether now doing a repeat */
469 struct MAINLL **repeat_start_p_p;       /* indicates where repeated section
470                                  * begins. May be updated by this function if
471                                  * we hit a repeat sign */
472
473 {
474         struct MAINLL *m_p;
475
476         /* handle endings (simple case only). If we
477          * hit the beginning of an ending while doing second time through
478          * a repeated section, assume we should jump to the end
479          * of the repeat */
480         if ((*mll_p_p)->u.bar_p->endingloc == STARTITEM
481                                                 && *doing_repeat_p == YES) {
482
483                 for (*mll_p_p = (*mll_p_p)->next;
484                             *mll_p_p != (struct MAINLL *)0;
485                             *mll_p_p = (*mll_p_p)->next) {
486
487                         if ((*mll_p_p)->str == S_BAR &&
488                                 ((*mll_p_p)->u.bar_p->bartype == REPEATEND ||
489                                 (*mll_p_p)->u.bar_p->bartype == REPEATBOTH)) {
490                             break;
491                         }
492                 }
493                 *doing_repeat_p = NO;
494                 *repeat_start_p_p = *mll_p_p;
495                 return;
496         }
497
498
499         /* handle repeats. At beginning of a repeat,
500          * remember where it is. At end, if first time
501          * through, jump back. */
502         switch ((*mll_p_p)->u.bar_p->bartype) {
503
504         case REPEATSTART:
505                 /* remember where repeat begins */
506                 *repeat_start_p_p = *mll_p_p;
507                 break;
508
509         case REPEATEND:
510         case REPEATBOTH:
511                 if (*doing_repeat_p == YES) {
512                         /* 2nd time through */
513                         *doing_repeat_p = NO;
514                         *repeat_start_p_p = *mll_p_p;
515                 }
516                 else {
517                         /* first time through */
518                         *doing_repeat_p = YES;
519                         *mll_p_p = *repeat_start_p_p;
520                         /* set the SSV's back to what they were at the
521                          * beginning of the repeat. */
522                         initstructs();
523                         for (m_p = Mainllhc_p; m_p != *repeat_start_p_p;
524                                                         m_p = m_p->next) {
525                                 if (m_p->str == S_SSV) {
526                                         asgnssv(m_p->u.ssv_p);
527                                 }
528                         }
529                 }
530                 break;
531
532         default:
533                 break;
534         }
535 }
536 \f
537
538 /* Find the "effective" duration of a measure. Because of squeezing of
539  * space chords, a measure may be shorter than the time signature.
540  * Given a spot in the main list, this finds the first visible voice
541  * at or above that place, and counts up the time of the GRPSYLS in it,
542  * ignoring squeezed-out spaces.
543  */
544
545 static RATIONAL
546 eff_meas_time(mll_p)
547
548 struct MAINLL *mll_p;
549
550 {
551         RATIONAL eff_time;      /* calculated value to return */
552         struct GRPSYL *g_p;     /* to loop through groups */
553         int v = 0;              /* voice index. Initialization is just
554                                  * to avoid bogus "used before set"
555                                   */
556
557         /* find top visible voice */
558         for (   ; mll_p != 0; mll_p = mll_p->prev) {
559                 if (mll_p->str == S_STAFF && svpath(mll_p->u.staff_p->staffno,
560                                         VISIBLE)->visible == YES) {
561                         for (v = 0; v < MAXVOICES; v++) {
562                                 if (vvpath(mll_p->u.staff_p->staffno, v+1,
563                                                 VISIBLE)->visible == YES) {
564                                         break;
565                                 }
566                         }
567                         if (v < MAXVOICES) {
568                                 break;
569                         }
570                 }
571         }
572         if (mll_p == 0) {
573                 pfatal("eff_meas_time couldn't find a visible voice");
574         }
575
576         /* All up the time in this voice */
577         eff_time = Zero;
578         for (g_p = mll_p->u.staff_p->groups_p[v]; g_p != 0; g_p = g_p->next) {
579                 if (g_p->grpvalue == GV_ZERO && g_p->grpcont == GC_SPACE) {
580                         /* squeezed out space, so doesn't count */
581                         continue;
582                 }
583                 eff_time = radd(eff_time, g_p->fulltime);
584         }
585         return(eff_time);
586 }
587 \f
588
589 /* write MIDI header to file */
590
591 static void 
592 midi_header(mfile, ntracks)
593
594 int mfile;      /* file descriptor to write to */
595 int ntracks;    /* how many tracks are to be written */
596
597 {
598         unsigned char buff[8];
599         UINT32B track1start;
600         UINT32B trklength;
601
602
603         debug(512, "midi_header");
604
605         trklength = write(mfile, "MThd\0\0\0\6\0", 9);
606
607         /* always use format 1 */
608         buff[0] = 1;
609
610         /* 2 bytes for number of tracks */
611         /* add 1 for the track giving time signature, etc */
612         buff[1] = (unsigned char) (ntracks + 1) >> 8;
613         buff[2] = (unsigned char) (ntracks + 1) & 0xff;
614
615         /* division field. */
616         buff[3] = (unsigned char) (Division >> 8);
617         buff[4] = (unsigned char) (Division & 0xff);
618         (void) write(mfile, buff, 5);
619
620         /* now do first track, which gives time and key signature info */
621         track1start = lseek(mfile, 0L, SEEK_CUR);
622         track_header(mfile);
623         trklength = 0;
624
625         /* if there is a header and the first item to print is centered,
626          * it's probably a title, so do it as a text event. */
627         if (Header.printdata_p != (struct PRINTDATA *) 0) {
628                 if (Header.printdata_p->justifytype == J_CENTER &&
629                                 Header.printdata_p->string != (char *) 0) {
630                         trklength += write_delta(mfile);
631                         buff[0] = 0xff;
632                         buff[1] = 0x01;
633                         trklength += write(mfile, buff, 2);
634                         trklength += midi_wrstring(mfile,
635                                         Header.printdata_p->string, YES);
636                 }
637         }
638         /* do default time signature if necessary */
639         if (Time_specified_by_user == NO) {
640                 trklength += midi_timesig(mfile);
641         }
642
643         /* do default key signature if necessary */
644         if (Key_specified_by_user == NO) {
645                 trklength += midi_keysig(mfile, eff_key(0), Score.is_minor);
646         }
647
648         /* output usecs per quarter note */
649         trklength += write(mfile, "\0\377Q\3", 4);
650         buff[0] = (Usec_per_quarter_note >> 16) & 0xff;
651         buff[1] = (Usec_per_quarter_note >> 8) & 0xff;
652         buff[2] = Usec_per_quarter_note & 0xff;
653         trklength += write(mfile, buff, 3);
654
655         /* do everything else for track 1 */
656         trklength += all_midi(mfile);
657
658         /* end of track marker */
659         trklength += write(mfile, "\0\377/\0", 4);
660         fix_track_size(mfile, track1start, trklength);
661 }
662 \f
663
664 /* write a MIDI track header */
665
666 static void
667 track_header(mfile)
668
669 int mfile;      /* write track header to this file descriptor */
670
671 {
672         debug(512, "track_header");
673
674         (void) write(mfile, "MTrk\0\0\0\0", 8);
675
676         /* reset time reference */
677         Absolute_time = Sum_of_deltas = Zero;
678
679         /* reset "running status" */
680         Status = 0;
681 }
682 \f
683
684 /* write MIDI info. Return number of bytes written to mfile */
685
686 static UINT32B
687 write_midi_data(mfile, gs_p)
688
689 int mfile;              /* write MIDI data to this file descriptor */
690 struct GRPSYL *gs_p;    /* write info about these chords */
691
692 {
693         UINT32B bytes = 0;      /* number of bytes written */
694         int n;                  /* walk through notes of chord */
695         unsigned char buff[4];  /* temp storage for MIDI data */
696         int notenum;            /* MIDI note number 0-127 */
697         int raw_notenum;        /* note numer not counting accidentals */
698         short newstatus;        /* running status */
699
700
701         /* go through each GRPSYL in the measure */
702         for (  ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
703
704                 /* do any MIDI stuffs that happen right on this beat. They
705                  * should happen after notes have been turned off for previous
706                  * chord but before the notes for the following chord */
707                 bytes += do_midi_stuff(Zero, mfile, NO);
708
709                 /* if rest or space, just keep track of time used. */
710                 if ( gs_p->grpcont != GC_NOTES) {
711                         /* special case of all-space chord. It gets no time.
712                          * Just adjust pending MIDI events so they happen
713                          * at the right time */
714                         if (gs_p->grpcont == GC_SPACE && gs_p->grpvalue == GV_ZERO) {
715                                 adj4squeeze(gs_p->fulltime);
716                                 bytes += do_midi_stuff(Zero, mfile, NO);
717                         }
718                         else {
719                                 bytes += do_midi_stuff(gs_p->fulltime, mfile, NO);
720                         }
721                         continue;
722                 }
723
724                 /* turn on each note in chord */
725                 for (n = 0; n < gs_p->nnotes; n++) {
726
727                         notenum = xlate_note( &(gs_p->notelist[n]),
728                                         gs_p->inputfile, gs_p->inputlineno,
729                                         &raw_notenum);
730
731                         /* if this note is tied from previous, it is already
732                          * turned on, so just mark off that we've done the tie.
733                          */
734                         if (Tie_table[raw_notenum] == YES) {
735                                 Tie_table[raw_notenum] = NO;
736                         }
737
738                         else {
739                                 /* not tied from previous, so turn note on */
740                                 bytes += write_delta(mfile);
741         
742                                 /* first time through have to put the status.
743                                  * After that we can use running status */
744                                 newstatus = (0x90 | Channel) & 0xff;
745                                 if (Status != newstatus) {
746                                         buff[0] = (unsigned char) newstatus;
747                                         (void) write(mfile, buff, 1);
748                                         Status = newstatus;
749                                         bytes++;
750                                 }
751
752                                 buff[0] = (unsigned char) notenum;
753                                 buff[1] = (unsigned char) Onvelocity[n];
754                                 (void) write(mfile, buff, 2);
755                                 bytes += 2;
756                         }
757                 }
758                 
759                 bytes += do_midi_stuff(gs_p->fulltime, mfile, NO);
760
761                 /* now turn all the notes off, unless tied */
762                 for (n = 0; n < gs_p->nnotes; n++) {
763
764                         notenum = xlate_note( &(gs_p->notelist[n]),
765                                 gs_p->inputfile, gs_p->inputlineno,
766                                 &raw_notenum);
767
768                         /* if this note is tied to next, mark that */
769                         if ( (gs_p->notelist[n].tie == YES) ||
770                                                 (gs_p->tie == YES) ) {
771                                 Tie_table[raw_notenum] = YES;
772                         }
773                         else {
774                                 /* not tied to next, so turn off */
775                                 bytes += write_delta(mfile);
776
777                                 /* use note on with onvelocity 0 (which means
778                                  * note off), unless user explicitly set an
779                                  * off velocity */
780                                 if (Offvelocity[n] != 0) {
781                                         newstatus = (0x80 | Channel) & 0xff;
782                                 }
783                                 else {
784                                         newstatus = (0x90 | Channel) & 0xff;
785                                 }
786                                 if (Status != newstatus) {
787                                         buff[0] = (unsigned char) newstatus;
788                                         (void) write(mfile, buff, 1);
789                                         Status = newstatus;
790                                         bytes++;
791                                 }
792                                 buff[0] = (unsigned char) notenum;
793                                 buff[1] = (unsigned char) Offvelocity[n];
794                                 (void) write(mfile, buff, 2);
795                                 bytes += 2;
796
797                                 /* If we had to defer the setting of
798                                  * sharps/flats because of a tie into the
799                                  * measure, do that now. */
800                                 if (Deferred_acc[raw_notenum] != NO_DEFERRED_ACC) {
801                                         Accidental_map[raw_notenum] =
802                                                 Deferred_acc[raw_notenum];
803                                         Deferred_acc[raw_notenum] = NO_DEFERRED_ACC;
804                                 }
805                         }
806                 }
807         }
808
809         /* do any midi events that happen at the end of the measure after
810          * the notes. */
811         bytes += do_midi_stuff(Zero, mfile, NO);
812
813         return(bytes);
814 }
815 \f
816
817 /* write out delta value. Return number of bytes written */
818
819 UINT32B
820 write_delta(mfile)
821
822 int mfile;      /* file descriptor of MIDI file */
823
824 {
825         UINT32B idelta;         /* delta rounded to 32-bit integer */
826         RATIONAL delta;
827         RATIONAL rounded;       /* idelta converted back to RATIONAL */
828
829
830         /* avoid rational overflow, which can happen under certain
831          * circumstances with lots of grace, rolls, etc */
832         while (Absolute_time.n > MAXMIDI_RAT
833                                 || Absolute_time.d > MAXMIDI_RAT) {
834                 /* avoid rational divide by zero */
835                 if (Absolute_time.d > 1) {
836                         Absolute_time.n >>= 1;
837                         Absolute_time.d >>= 1;
838                         rred ( &Absolute_time );
839                 }
840                 else {
841                         break;
842                 }
843         }
844         while( Sum_of_deltas.n > MAXMIDI_RAT
845                                 || Sum_of_deltas.d > MAXMIDI_RAT) {
846                 if (Sum_of_deltas.d > 1) {
847                         Sum_of_deltas.n >>= 1;
848                         Sum_of_deltas.d >>= 1;
849                         rred ( &Sum_of_deltas );
850                 }
851                 else {
852                         break;
853                 }
854         }
855
856         delta = rsub(Absolute_time, Sum_of_deltas);
857         if (LT(delta, Zero)) {
858                 delta = Zero;
859         }
860
861         /* Multiply by factor to get delta value in MIDI clock ticks,
862          * then round off to UINT32B. Entire calculation must be done
863          * in floating point, then cast to UINT32B, otherwise overflow
864          * can occur, which really messes things up!! */
865         idelta = (UINT32B)((((double) MIDI_FACTOR * (double) delta.n)
866                                                 / (double) delta.d) + 0.5);
867
868         /* now convert the rounded-off value back to a RATIONAL,
869          * and add it to the Sum_of_deltas, so we'll know exactly how far
870          * off we are the next time around and can compensate. */
871         rounded.n = idelta;
872         rounded.d = MIDI_FACTOR;
873         rred(&rounded);
874         /* certain combinations of division value, release values, and
875          * input could cause rounded to overflow and become negative.
876          * Because of all the other code added to try to avoid overflow,
877          * this should be extremely unlikely, but it's better to catch
878          * it and give an error than leave the user to wonder why the
879          * generated MIDI file says to hold a note for several days. */
880         if (LT(rounded, Zero)) {
881                 pfatal("arithmetic overflow on MIDI delta calculation, input probably too complex\n  (hint: changing the 'release' parameter might help)");
882         }
883
884         Sum_of_deltas = radd(Sum_of_deltas, rounded);
885
886         return(wr_varlength(mfile, idelta));
887 }
888 \f
889
890 /* given a NOTE, return the corresponding MIDI note number */
891
892 static int
893 xlate_note(note_p, fname, lineno, raw_notenum_p)
894
895 struct NOTE *note_p;
896 char *fname;    /* input file */
897 int lineno;     /* input line number */
898 int *raw_notenum_p;     /* return the note number without accidentals */
899
900 {
901         int val;
902
903         switch (note_p->letter) {
904         case 'a':
905                 val = 9;
906                 break;
907         case 'b':
908                 val = 11;
909                 break;
910         case 'c':
911                 val = 0;
912                 break;
913         case 'd':
914                 val = 2;
915                 break;
916         case 'e':
917                 val = 4;
918                 break;
919         case 'f':
920                 val = 5;
921                 break;
922         case 'g':
923                 val = 7;
924                 break;
925         default:
926                 pfatal("invalid note\n");
927                 /*NOTREACHED*/
928                 return(0);
929         }
930
931         /* adjust for octave */
932         val += 12 * (note_p->octave + 1);
933
934         /* If user overlaps octave marks inside a measure, which we don't
935          * catch, or if they transpose a note so many octaves that it is out
936          * of range (like transposing something down when it's already in
937          * octave 0) a note could end up out of range, so catch that here. */
938         if (note_p->octave < MINOCTAVE || note_p->octave > MAXOCTAVE ||
939                                 val < 0 || val > 127) {
940                 l_ufatal(fname, lineno, "note is out of range");
941         }
942
943
944         /* return the value not considering accidentals. This is needed to
945          * keep track of ties properly. */
946         *raw_notenum_p = val;
947
948         switch (note_p->accidental) {
949         case '#':
950                 Accidental_map[val] = 1;
951                 break;
952         case '&':
953                 Accidental_map[val] = -1;
954                 break;
955         case 'x':
956                 Accidental_map[val] = 2;
957                 break;
958         case 'B':
959                 Accidental_map[val] = -2;
960                 break;
961         case 'n':
962                 Accidental_map[val] = 0;
963                 break;
964         case '\0':
965                 /* leave note as is */
966                 break;
967         default:
968                 pfatal("unknown accidental type '%c'", note_p->accidental);
969                 break;
970         }
971
972         /* the top few notes in octave 9 are outside midi range */
973         if (val + Accidental_map[val] > 127) {
974                 l_ufatal(fname, lineno, "note out of range");
975         }
976         return (val + Accidental_map[val]);
977 }
978 \f
979
980 /* initialize map of accidentals, based on key signature. */
981
982 static void
983 init_accidental_map(staffno)
984
985 int staffno;
986
987 {
988         register int n;
989
990         /* first clear the map for all MIDI notes */
991         for (n = 0; n < 128; n++) {
992                 /* If a note with any sort of accidental on it is currently
993                  * tied, then we don't clear that note's accidental map,
994                  * but mark that we will need to set the key signature
995                  * value later, after the tie ends. Otherwise we set it
996                  * immediately. */
997                 if (Tie_table[n] == YES) {
998                         /* set to zero for now. Will set to something else
999                          * in mark_accidental later if appropriate. */
1000                         Deferred_acc[n] = 0;
1001                 }
1002                 else {
1003                         Accidental_map[n] = 0;
1004                         Deferred_acc[n] = NO_DEFERRED_ACC;
1005                 }
1006         }
1007
1008         /* now fill in the key signature items in all octaves */
1009         switch (eff_key(staffno) ) {
1010         case 7:
1011                 /* B# */
1012                 mark_accidental(11, 1);
1013                 /*FALLTHRU*/
1014         case 6:
1015                 /* E# */
1016                 mark_accidental(4, 1);
1017                 /*FALLTHRU*/
1018         case 5:
1019                 /* A# */
1020                 mark_accidental(9, 1);
1021                 /*FALLTHRU*/
1022         case 4:
1023                 /* D# */
1024                 mark_accidental(2, 1);
1025                 /*FALLTHRU*/
1026         case 3:
1027                 /* G# */
1028                 mark_accidental(7, 1);
1029                 /*FALLTHRU*/
1030         case 2:
1031                 /* C# */
1032                 mark_accidental(0, 1);
1033                 /*FALLTHRU*/
1034         case 1:
1035                 /* F# */
1036                 mark_accidental(5, 1);
1037                 break;
1038         case 0:
1039                 break;
1040         case -7:
1041                 /* F& */
1042                 mark_accidental(5, -1);
1043                 /*FALLTHRU*/
1044         case -6:
1045                 /* C& */
1046                 mark_accidental(0, -1);
1047                 /*FALLTHRU*/
1048         case -5:
1049                 /* G& */
1050                 mark_accidental(7, -1);
1051                 /*FALLTHRU*/
1052         case -4:
1053                 /* D& */
1054                 mark_accidental(2, -1);
1055                 /*FALLTHRU*/
1056         case -3:
1057                 /* A& */
1058                 mark_accidental(9, -1);
1059                 /*FALLTHRU*/
1060         case -2:
1061                 /* E& */
1062                 mark_accidental(4, -1);
1063                 /*FALLTHRU*/
1064         case -1:
1065                 /* B& */
1066                 mark_accidental(11, -1);
1067                 break;
1068         default:
1069                 pfatal("unknown key signature");
1070                 break;
1071         }
1072 }
1073 \f
1074
1075 /* initialize table to say that no notes are tied */
1076
1077 static void
1078 init_tie_table()
1079
1080 {
1081         register int i;
1082
1083
1084         for (i = 0; i < 128; i++) {
1085                 Tie_table[i] = NO;
1086         }
1087 }
1088 \f
1089
1090 /* in each octave, mark the given note as having the given accidental, if not
1091  * tied. If tied, mark to set it later. */
1092
1093 static void
1094 mark_accidental(pitch_offset, acc)
1095
1096 int pitch_offset;       /* 0 = C, 2 = D, 4 = E, 5 = F, 7 = G, 9 = A, 11 = B */
1097 int acc;                /* 1 = sharp, -1 = flat */
1098
1099 {
1100         register int n;
1101
1102         for (n = pitch_offset; n < 128; n += 12) {
1103                 if (Tie_table[n] == YES) {
1104                         Deferred_acc[n] = (short) acc;
1105                 }
1106                 else {
1107                         Accidental_map[n] = (short) acc;
1108                 }
1109         }
1110 }
1111 \f
1112
1113 /* handle a multi-rest. Adjust the absolute time reference value to account
1114  * for the length of the multi-rest */
1115
1116 static UINT32B
1117 midi_multirest(mfile, staff_p, staffno, vno, nummeas)
1118
1119 int mfile;              /* MIDI file */
1120 struct STAFF *staff_p;
1121 int staffno;
1122 int vno;        /* voice number */
1123 int nummeas;    /* how many measure of rest */
1124
1125 {
1126         RATIONAL rat_nummeas;   /* number of measure as a rational */
1127
1128
1129         if (staff_p != (struct STAFF *) 0) {
1130                 prepmidi_stuff(staff_p, vno, NO);
1131         }
1132
1133         /* if truly a multirest and if octave were in progress,
1134          * need to adjust number of measures remaining */
1135         if (nummeas > 1 && Octave_bars[staffno] > 0) {
1136                 /* subtract 1 'cause the barline will count as one */
1137                 Octave_bars[staffno] -= nummeas - 1;
1138                 /* if whole octave stuff is done, re-init */
1139                 if (Octave_bars[staffno] < 0) {
1140                         Octave_bars[staffno] = 0;
1141                         Octave_count[staffno] = 0.0;
1142                         Octave_adjust[staffno] = 0;
1143                 }
1144         }
1145
1146         rat_nummeas.n = nummeas;
1147         rat_nummeas.d = 1;
1148         return(do_midi_stuff(rmul(rat_nummeas, Score.time), mfile, NO));
1149 }
1150 \f
1151
1152 /* go through STUFF in a measure, saving away info about MIDI stuff for
1153  * later use. */
1154
1155 static void
1156 prepmidi_stuff(staff_p, vindex, all)
1157
1158 struct STAFF *staff_p;  /* do STUFF off of here */
1159 int vindex;             /* voice index, 0 or 1 for voice 1 or 2 */
1160 int all;                /* YES if processing 'all' stuff */
1161
1162 {
1163         struct STUFF *st_p;             /* walk through staff_p->stuff_p */
1164         struct MIDISTUFF *ms_p;         /* walk through Midistufflist_p */
1165         struct MIDISTUFF **ms_p_p;      /* for inserting into list */
1166
1167
1168         Midistufflist_p = (struct MIDISTUFF *) 0;
1169         for (st_p = staff_p->stuff_p; st_p != (struct STUFF *) 0;
1170                                                         st_p = st_p->next) {
1171
1172                 if (st_p->stuff_type == ST_MIDI
1173                                         || st_p->stuff_type == ST_PEDAL) {
1174
1175                         /* only do those with proper 'all' value */
1176                         if (st_p->all != all) {
1177                                 continue;
1178                         }
1179
1180                         if (st_p->place == PL_ABOVE && vindex != 0) {
1181                                 /* above only applies to voice 1 */
1182                                 continue;
1183                         }
1184                         if (st_p->place == PL_BELOW && vindex != 1) {
1185                                 /* below only applies to voice 2 */
1186                                 if (st_p->stuff_type != ST_PEDAL) {
1187                                         continue;
1188                                 }
1189                         }
1190                         if (st_p->place == PL_BETWEEN && vindex != 2) {
1191                                 /* between only applies to voice 3 */
1192                                 continue;
1193                         }
1194
1195                         CALLOC(MIDISTUFF, ms_p, 1);
1196                         /* figure out when to do this event. Have in floating
1197                          * point, but need in RATIONAL. So convert. From MIDI's
1198                          * point of view, the first beat of a measure occurs at
1199                          * time zero, but stuff calls that time 1, and may have
1200                          * things happening before that. So adjust for that,
1201                          * and consider anything happening from stuff time 0 to
1202                          * 1 to happen instantaneously at midi time 0. */
1203                         ms_p->time.n = (UINT32B) ( (st_p->start.count - 1.0)
1204                                                                 * F2RFACTOR);
1205                         ms_p->time.d = F2RFACTOR * Score.timeden;
1206                         rred( &(ms_p->time) );
1207                         if ( LT(ms_p->time, Zero) ) {
1208                                 ms_p->time = Zero;
1209                         }
1210                         ms_p->time = radd(ms_p->time, Absolute_time);
1211
1212                         ms_p->stuff_p = st_p;
1213
1214                         /* insertion sort into list */
1215                         for (ms_p_p = &Midistufflist_p; *ms_p_p !=
1216                                                 (struct MIDISTUFF *) 0;
1217                                                 ms_p_p = &((*ms_p_p)->next)) {
1218                                 if (GT( (*ms_p_p)->time, ms_p->time)) {
1219                                         break;
1220                                 }
1221                         }
1222                         ms_p->next = *ms_p_p;
1223                         *ms_p_p = ms_p;
1224                 }
1225         }
1226 }
1227 \f
1228
1229 /* given a timeval to add to Absolute_time, see if there are any MIDI
1230  * STUFF events that come before then. If so, do them first. If timeval
1231  * is Zero, do any events happening exactly at Absolute_time. In any case
1232  * update Absolute_time appropriately. Return number of bytes written */
1233
1234 static UINT32B
1235 do_midi_stuff(timeval, mfile, all)
1236
1237 RATIONAL timeval;
1238 int mfile;              /* MIDI file */
1239 int all;                /* YES if processing 'all' stuffs */
1240
1241 {
1242         RATIONAL new_abs_time;  /* Absolute_time plus timeval */
1243         struct MIDISTUFF *ms_p; /* index through MIDISTUFF list */
1244         UINT32B bytes = 0;      /* bytes written */
1245
1246
1247         /* If need to bounce pedal, do that now */
1248         if (Pedbounce == YES && NE(timeval, Zero)) {
1249                 RATIONAL instant;
1250
1251                 instant.n = 1;
1252                 instant.d = MIDI_FACTOR;
1253                 Absolute_time = radd(Absolute_time, instant);
1254                 bytes += pedswitch(mfile, YES);
1255                 Absolute_time = rsub(Absolute_time, instant);
1256                 Pedbounce = NO;
1257         }
1258
1259         /* find out what final time will be */
1260         new_abs_time = radd(Absolute_time, timeval);
1261
1262         /* go through list of MIDI STUFF, to see if anything to do before
1263          * final time */
1264         for (ms_p = Midistufflist_p; ms_p != (struct MIDISTUFF *) 0;  ) {
1265
1266                 if ( LT(ms_p->time, new_abs_time) || (EQ(timeval, Zero) &&
1267                                         EQ(ms_p->time, new_abs_time) ) ) {
1268
1269                         /* an item to do. Do it */
1270                         Absolute_time = ms_p->time;
1271                         bytes += midi_item(ms_p->stuff_p, mfile, all);
1272
1273                         /* free this item and move to next one */
1274                         ms_p = ms_p->next;
1275                         FREE(Midistufflist_p);
1276                         Midistufflist_p = ms_p;
1277                 }
1278                 else {
1279                         break;
1280                 }
1281         }
1282         Absolute_time = new_abs_time;
1283
1284         /* return number of bytes written */
1285         return(bytes);
1286 }
1287 \f
1288
1289 /* handle a MIDI stuff item */
1290
1291 static UINT32B
1292 midi_item(stuff_p, mfile, all)
1293
1294 struct STUFF *stuff_p;  /* which STUFF to process */
1295 int mfile;              /* the MIDI file */
1296 int all;                /* YES if processing "all" type items now */
1297
1298 {
1299         UINT32B bytes = 0;      /* bytes written */
1300         unsigned char buff[8];
1301         char *key;              /* midi directive keyword */
1302         int leng;               /* length of key */
1303         char *arg;              /* arg after the =  */
1304         int num;                /* atoi value of argument */
1305         int n;                  /* note velocity index */
1306         char *nextvel_p;        /* location in string of next velocity value */
1307
1308
1309         if (stuff_p->stuff_type == ST_PEDAL) {
1310                 int font, size;
1311                 char *string;
1312
1313
1314                 if (stuff_p->string == (char *) 0) {
1315                         /* continuation of pedal into an ending or something
1316                          * similar. I don't think this will every actually
1317                          * happen, since that's done in a later phase. */
1318                         return(0);
1319                 }
1320
1321                 /* extract the pedal character */
1322                 font = stuff_p->string[0];
1323                 size = stuff_p->string[1];
1324                 string = stuff_p->string + 2;
1325
1326                 /* turn pedal switch on or off as appropriate */
1327                 switch(next_str_char(&string, &font, &size) & 0xff) {
1328
1329                 case C_BEGPED:
1330                         bytes += pedswitch(mfile, YES);
1331                         break;
1332                 
1333                 case C_PEDAL:
1334                         bytes += pedswitch(mfile, NO);
1335                         /* have to put pedal back up after the next chord */
1336                         Pedbounce = YES;
1337                         break;
1338
1339                 case C_ENDPED:
1340                         bytes += pedswitch(mfile, NO);
1341                         break;
1342                 
1343                 default:
1344                         pfatal("bad character in pedal string");
1345                         /*NOTREACHED*/
1346                         break;
1347                 }
1348                 return(bytes);
1349         }
1350
1351         /* figure out which keyword was specified */
1352         if (getkeyword(stuff_p->string + 2, &key, &leng, &arg) == NO) {
1353                 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
1354                                 "midi directive not in keyword=value format");
1355                 return(0);
1356         }
1357         
1358         /* do the code for the appropriate keyword. There are enough keywords
1359          * that it would almost be worthwhile doing a hash or binary search
1360          * rather than sequentially checking each. However, most of them will
1361          * probably be rarely used, so by checking the most common ones first,
1362          * there will rarely be more than half a dozen checks anyway. */
1363         if (matches(key, leng, "program") == YES) {
1364                 if (stuff_p->all == YES) {
1365                         l_warning(stuff_p->inputfile, stuff_p->inputlineno,
1366                                 "midi program cannot be used with 'all'");
1367                         return(0);
1368                 }
1369                 if (all == YES) {
1370                         return(0);
1371                 }
1372
1373                 num = atoi(arg);
1374                 if (l_rangecheck(num, 0, 127, "program", stuff_p->inputfile,
1375                                 stuff_p->inputlineno) == YES) {
1376                         bytes = write_delta(mfile);
1377                         Status = buff[0] = (unsigned char) (0xc0 | Channel);
1378                         buff[1] = (unsigned char) num;
1379                         bytes += write(mfile, buff, 2);
1380                 }
1381         }
1382
1383         else if (matches(key, leng, "tempo") == YES) {
1384                 UINT32B quarter_notes_per_minute;
1385
1386                 /* tempo only applies to 'all' */
1387                 if (stuff_p->all == NO) {
1388                         l_warning( stuff_p->inputfile, stuff_p->inputlineno,
1389                                 "midi tempo can only be set using 'all'");
1390                         return(0);
1391                 }
1392
1393                 if (all == NO) {
1394                         return(0);
1395                 }
1396
1397                 quarter_notes_per_minute = atoi(arg);
1398                 if (l_rangecheck(quarter_notes_per_minute, MINQNPM, MAXQNPM,
1399                                 "tempo", stuff_p->inputfile,
1400                                 stuff_p->inputlineno) == YES) {
1401                         bytes = write_delta(mfile);
1402                         buff[0] = (unsigned char) 0xff;
1403                         buff[1] = (unsigned char) 0x51;
1404                         buff[2] = (unsigned char) 0x3;
1405                         Usec_per_quarter_note = USEC_PER_MINUTE
1406                                                 /  quarter_notes_per_minute;
1407                         buff[3] = (Usec_per_quarter_note >> 16) & 0xff;
1408                         buff[4] = (Usec_per_quarter_note >> 8) & 0xff;
1409                         buff[5] = (Usec_per_quarter_note & 0xff);
1410                         bytes += write(mfile, buff, 6);
1411                         Status = 0;
1412                 }
1413         }
1414
1415         else if (matches(key, leng, "onvelocity") == YES) {
1416                 if (stuff_p->all == YES) {
1417                         l_warning(stuff_p->inputfile, stuff_p->inputlineno,
1418                                 "midi onvelocity cannot be used with 'all'");
1419                         return(0);
1420                 }
1421                 if (all == YES) {
1422                         return(0);
1423                 }
1424                 num = atoi(arg);
1425                 if (l_rangecheck(num, 1, 127, "onvelocity", stuff_p->inputfile,
1426                                 stuff_p->inputlineno) == YES) {
1427                         Onvelocity[0] = (char) num;
1428                 }
1429                 /* if there are more velocities given, process them. If
1430                  * there are N velocities given, they give the velocities
1431                  * to use for the top N notes, the first for the top note,
1432                  * the second for the second to the top, etc. If there are
1433                  * more than N notes in a chord, the remaining notes are
1434                  * given the velocity of the final velocity specified.
1435                  * Thus, if only one is specified, it applies to all notes
1436                  * in the chord, whereas if two are given, the top note
1437                  * will have the first velocity and the remaining notes will
1438                  * have the second (which could be useful for emphasizing
1439                  * the melody, for example). And the user can specify each
1440                  * note's velocity separately if they want to.
1441                  */
1442                 nextvel_p = strchr(arg, ',');
1443                 for (n = 1; n < MAXHAND; n++) {
1444                         
1445                         /* if user has listed another velocity, save it */
1446                         if (nextvel_p != (char *) 0) {
1447                                 num = atoi(++nextvel_p);
1448                                 if (l_rangecheck(num, 1, 127, "onvelocity",
1449                                                 stuff_p->inputfile,
1450                                                 stuff_p->inputlineno) == YES) {
1451                                         Onvelocity[n] = (char) num;
1452                                 }
1453
1454                                 /* point to next velocity, if any, for next
1455                                  * time through the loop */
1456                                 nextvel_p = strchr(nextvel_p, ',');
1457                         }
1458                         else {
1459                                 /* use the last user-specified velocity for
1460                                  * all subsequent notes */
1461                                 Onvelocity[n] = (char) num;
1462                         }
1463                 }
1464         }
1465
1466         /* Note: have to check "channel" before "chanpressure" so that
1467          * channel takes precedence if the keyword is abbreviated */
1468         else if (matches(key, leng, "channel") == YES) {
1469                 if (stuff_p->all == YES) {
1470                         l_warning(stuff_p->inputfile, stuff_p->inputlineno,
1471                                 "midi channel cannot be used with 'all'");
1472                         return(0);
1473                 }
1474                 if (all == YES) {
1475                         return(0);
1476                 }
1477
1478                 num = atoi(arg);
1479                 if (l_rangecheck(num, 1, 16, "channel", stuff_p->inputfile,
1480                                         stuff_p->inputlineno) == YES) {
1481                         /* external MIDI channel numbers are 1-16,
1482                          * internal are 0-15 */
1483                         Channel = num - 1;
1484                 }
1485         }
1486
1487         else if (matches(key, leng, "parameter") == YES) {
1488                 int parmnum;    /* parameter number */
1489                 int parmval;    /* parameter value */
1490
1491                 if (get_param(arg, stuff_p->inputfile, stuff_p->inputlineno,
1492                                         &parmnum, &parmval) == YES) {
1493                         bytes += write_delta(mfile);
1494                         Status = buff[0] = 0xb0 | Channel;
1495                         buff[1] = (unsigned char) parmnum;
1496                         buff[2] = (unsigned char) parmval;
1497                         bytes += write(mfile, buff, 3);
1498                 }
1499         }
1500
1501         else if (matches(key, leng, "offvelocity") == YES) {
1502                 if (stuff_p->all == YES) {
1503                         l_warning(stuff_p->inputfile, stuff_p->inputlineno,
1504                                 "midi offvelocity cannot be used with 'all'");
1505                         return(0);
1506                 }
1507                 if (all == YES) {
1508                         return(0);
1509                 }
1510                 num = atoi(arg);
1511                 if (l_rangecheck(num, 0, 127, "offvelocity", stuff_p->inputfile,
1512                                 stuff_p->inputlineno) == YES) {
1513                         Offvelocity[0] = (char) num;
1514                 }
1515                 /* if there are more velocities given, process them. 
1516                  * See description of onvelocity above for details.
1517                  */
1518                 nextvel_p = strchr(arg, ',');
1519                 for (n = 1; n < MAXHAND; n++) {
1520                         
1521                         /* if user has listed another velocity, save it */
1522                         if (nextvel_p != (char *) 0) {
1523                                 num = atoi(++nextvel_p);
1524                                 if (l_rangecheck(num, 1, 127, "onvelocity",
1525                                                 stuff_p->inputfile,
1526                                                 stuff_p->inputlineno) == YES) {
1527                                         Offvelocity[n] = (char) num;
1528                                 }
1529
1530                                 /* point to next velocity, if any, for next
1531                                  * time through the loop */
1532                                 nextvel_p = strchr(nextvel_p, ',');
1533                         }
1534                         else {
1535                                 /* use the last user-specified velocity for
1536                                  * all subsequent notes */
1537                                 Offvelocity[n] = (char) num;
1538                         }
1539                 }
1540         }
1541
1542         else if (matches(key, leng, "hex") == YES) {
1543                 return(midihex(mfile, arg, stuff_p->inputfile, stuff_p->inputlineno));
1544         }
1545         else if (matches(key, leng, "text") == YES) {
1546                 return(wr_meta(mfile, 0x01, arg));
1547         }
1548         else if (matches(key, leng, "copyright") == YES) {
1549                 return(wr_meta(mfile, 0x02, arg));
1550         }
1551         else if (matches(key, leng, "name") == YES) {
1552                 return(wr_meta(mfile, 0x03, arg));
1553         }
1554         else if (matches(key, leng, "instrument") == YES) {
1555                 return(wr_meta(mfile, 0x04, arg));
1556         }
1557         else if (matches(key, leng, "marker") == YES) {
1558                 return(wr_meta(mfile, 0x06, arg));
1559         }
1560         else if (matches(key, leng, "cue") == YES) {
1561                 return(wr_meta(mfile, 0x07, arg));
1562         }
1563
1564         else if (matches(key, leng, "seqnum") == YES) {
1565                 num = atoi(arg);
1566                 if (l_rangecheck(num, 0, 32767, "seqnum", stuff_p->inputfile,
1567                                 stuff_p->inputlineno) == YES) {
1568                         bytes = write_delta(mfile);
1569                         buff[0] = 0xff;
1570                         buff[1] = 0x00;
1571                         buff[2] = 0x02;
1572                         buff[3] = (num >> 8) & 0xff;
1573                         buff[4] = num & 0xff;
1574                         bytes += write(mfile, buff, 5);
1575                         Status = 0;
1576                 }
1577         }
1578
1579         else if (matches(key, leng, "port") == YES) {
1580                 num = atoi(arg);
1581                 if (l_rangecheck(num, 0, 127, "port", stuff_p->inputfile,
1582                                 stuff_p->inputlineno) == YES) {
1583                         bytes = write_delta(mfile);
1584                         buff[0] = 0xff;
1585                         buff[1] = 0x21;
1586                         buff[2] = 0x01;
1587                         buff[3] = num;
1588                         bytes += write(mfile, buff, 4);
1589                         Status = 0;
1590                 }
1591         }
1592
1593         /* Note: have to check "channel" before "chanpressure" so that
1594          * channel takes precedence if the keyword is abbreviated */
1595         else if (matches(key, leng, "chanpressure") == YES) {
1596                 num = atoi(arg);
1597                 if (l_rangecheck(num, 0, 127, "chanpressure",
1598                                 stuff_p->inputfile, stuff_p->inputlineno)
1599                                 == YES) {
1600                         bytes += write_delta(mfile);
1601                         buff[0] = 0xd0 | Channel;
1602                         buff[1] = (unsigned char) num;
1603                         bytes += write(mfile, buff, 2);
1604                         Status = 0;
1605                 }
1606         }
1607
1608         else {
1609                 l_warning(stuff_p->inputfile, stuff_p->inputlineno,
1610                                 "unrecognized midi item\n");
1611         }
1612
1613         return(bytes);
1614 }
1615 \f
1616
1617 /* handle raw hex to output to midi file. Allow white space. Set running
1618  * status to 0. */
1619
1620 static UINT32B
1621 midihex(mfile, str, fname, lineno)
1622
1623 int mfile;
1624 char *str;
1625 char *fname;
1626 int lineno;
1627
1628 {
1629         short nibble = 0;       /* 0 = upper nibble, 1 = lower */
1630         UINT32B bytes = 0;      /* how many bytes written */
1631         unsigned char data;     /* a byte of data to write */
1632
1633
1634         bytes += write_delta(mfile);
1635         for (   ; *str != '\0'; str++) {
1636
1637                 /* skip white space */
1638                 if (isspace(*str)) {
1639                         continue;
1640                 }
1641
1642                 /* collect two hex digits per byte to write */
1643                 if (isxdigit(*str)) {
1644                         if (nibble == 0) {
1645                                 data = hexdig(*str) << 4;
1646                         }
1647                         else {
1648                                 data |= hexdig(*str);
1649                                 (void) write(mfile, &data, 1);
1650                                 bytes++;
1651                         }
1652                         nibble ^= 1;
1653                 }
1654                 else {
1655                         l_ufatal(fname, lineno, "illegal hex character");
1656                 }
1657         }
1658
1659         if (nibble != 0) {
1660                 l_ufatal(fname, lineno, "odd number of hex digits");
1661         }
1662
1663         /* set running status to unknown and return number of bytes written */
1664         Status = 0;
1665         return(bytes);
1666 }
1667 \f
1668
1669 /* write a meta event of the form
1670  *      FF xx length text
1671  * Return number of bytes written.
1672  */
1673
1674 static UINT32B
1675 wr_meta(mfile, evtype, str)
1676
1677 int mfile;      /* midi file */
1678 int evtype;     /* meta event type */
1679 char *str;      /* text string */
1680
1681 {
1682         UINT32B bytes;
1683         unsigned char buff[4];
1684
1685
1686         bytes = write_delta(mfile);
1687         buff[0] = 0xff;
1688         buff[1] = (unsigned char) (evtype & 0xff);
1689         (void) write(mfile, buff, 2);
1690         bytes += 2;
1691         bytes += midi_wrstring(mfile, str, NO);
1692
1693         Status = 0;
1694         return(bytes);
1695 }
1696 \f
1697
1698 /* walk through main list. For each top-visible staff, check the stuff
1699  * list for any "midi all" items */
1700
1701 static UINT32B
1702 all_midi(mfile)
1703
1704 int mfile;
1705
1706 {
1707         struct MAINLL *mll_p;
1708         UINT32B bytes = 0;      /* number of bytes written */
1709         unsigned char buff[4];
1710         int doing_repeat = NO;
1711         struct MAINLL *repeat_start_p = Mainllhc_p;
1712         struct GRPSYL *gs_p;
1713
1714
1715         debug(256, "all_midi");
1716
1717         initstructs();
1718         for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
1719                                                 mll_p = mll_p->next) {
1720                 switch (mll_p->str) {
1721                 case S_STAFF:
1722                         if ( svpath(mll_p->u.staff_p->staffno, VISIBLE)->visible
1723                                                         == YES) {
1724
1725                                 /* Find the top visible voice */
1726                                 int vindex;
1727                                 for (vindex = 0; vindex < MAXVOICES; vindex++) {
1728                                         if (vvpath(mll_p->u.staff_p->staffno,
1729                                                         vindex+1, VISIBLE)->
1730                                                         visible == YES) {
1731                                                 break;
1732                                         }
1733                                 }
1734                                 if (vindex >= MAXVOICES) {
1735                                         pfatal("top visible staff has no visible voice");
1736                                 }
1737
1738                                 prepmidi_stuff(mll_p->u.staff_p, vindex, YES);
1739                                 /* We have to do groups one at a time in order
1740                                  * to adjust for any squeezed-out spaces. */
1741                                 for (gs_p = mll_p->u.staff_p->groups_p[vindex];
1742                                                 gs_p != (struct GRPSYL *) 0;
1743                                                 gs_p = gs_p->next) {
1744
1745                                         /* if we find a squeezed-out space
1746                                          * group, adjust to account for that */
1747                                         if (gs_p->grpcont == GC_SPACE &&
1748                                                         gs_p->grpvalue
1749                                                         == GV_ZERO) {
1750                                                 adj4squeeze(gs_p->fulltime);
1751                                                 bytes += do_midi_stuff(Zero,
1752                                                                 mfile, YES);
1753                                         }
1754                                         else {
1755                                                 if (gs_p->basictime < -1) {
1756                                                         /* multirest */
1757                                                         RATIONAL fulltime;
1758                                                         fulltime.n =
1759                                                             gs_p->fulltime.n *
1760                                                             -(gs_p->basictime);
1761                                                         fulltime.d =
1762                                                             gs_p->fulltime.d;
1763                                                         rred( &fulltime );
1764                                                         bytes += do_midi_stuff(
1765                                                         fulltime,
1766                                                         mfile, YES);
1767                                                 }
1768                                                 else {
1769                                                         bytes += do_midi_stuff(
1770                                                         gs_p->fulltime,
1771                                                         mfile, YES);
1772                                                 }
1773                                         }
1774                                 }
1775
1776                                 /* do any remaining MIDI stuffs. This would
1777                                  * be any that occur at exactly the time
1778                                  * signature denominator plus one. */
1779                                 bytes += do_midi_stuff(Zero, mfile, YES);
1780
1781
1782                                 /* can skip any immediately following STAFFs,
1783                                  * because we've already found the top
1784                                  * visible one, which is the only one that
1785                                  * should have any "midi all" stuff */
1786                                 while (mll_p->next != (struct MAINLL *) 0 &&
1787                                                 mll_p->next->str == S_STAFF) {
1788                                         mll_p = mll_p->next;
1789                                 }
1790                         }
1791                         break;
1792
1793                 case S_SSV:
1794                         asgnssv(mll_p->u.ssv_p);
1795
1796                         /* if key sig changes, handle that */
1797                         if (mll_p->u.ssv_p->context == C_SCORE &&
1798                                         (mll_p->u.ssv_p->used[SHARPS] == YES ||
1799                                         mll_p->u.ssv_p->used[TRANSPOSITION] == YES ||
1800                                         mll_p->u.ssv_p->used[ADDTRANSPOSITION] == YES) ) {
1801                                 bytes += midi_keysig(mfile,
1802                                                 eff_key(mll_p->u.ssv_p->staffno),
1803                                                 mll_p->u.ssv_p->is_minor);
1804                         }
1805
1806                         /* if time signature changes, handle that */
1807                         if (mll_p->u.ssv_p->used[TIME] == YES) {
1808                                 bytes += midi_timesig(mfile);
1809                         }
1810
1811                         break;
1812
1813                 case S_BAR:
1814                         /* rehearsal mark --> midi cue point */
1815                         if (mll_p->u.bar_p->reh_string != (char *) 0) {
1816                                 bytes += write_delta(mfile);
1817                                 buff[0] = 0xff;
1818                                 buff[1] = 0x07;
1819                                 (void) write(mfile, buff, 2);
1820                                 bytes += 2;
1821                                 bytes += midi_wrstring(mfile,
1822                                         mll_p->u.bar_p->reh_string, YES);
1823                         }
1824
1825                         repeats(&mll_p, &doing_repeat, &repeat_start_p);
1826
1827                         break;
1828
1829                 default:
1830                         break;
1831                 }
1832
1833                 if (mll_p == (struct MAINLL *) 0) {
1834                         /* shouldn't happen, but repeats() can change mll_p,
1835                          * and if it became null, we'd try
1836                          * to take the ->next of it, which is not good */
1837                         break;
1838                 }
1839         }
1840
1841         return(bytes);
1842 }
1843 \f
1844
1845 /* go through main list and adjust for grace notes, alternation groups,
1846  * staccato, etc */
1847
1848 static void
1849 midi_adjust()
1850
1851 {
1852         struct MAINLL *mll_p;   /* index through main list */
1853         int v;                  /* voice index */
1854         int got_data = NO;      /* if got any music data yet */
1855         int did_all = NO;       /* if processed "all" stuff for this meas */
1856         UINT32B begin_usec;     /* usec per quarter at beginning of measure */
1857
1858
1859         debug(256, "midi_adjust");
1860
1861         initstructs();
1862         begin_usec = Usec_per_quarter_note;
1863         for (mll_p = Mainllhc_p; mll_p != (struct MAINLL *) 0;
1864                                                         mll_p = mll_p->next) {
1865                 if (mll_p->str == S_STAFF) {
1866
1867                         if (is_tab_staff(mll_p->u.staff_p->staffno) == YES) {
1868                                 continue;
1869                         }
1870
1871                         /* If accidentals on one voice should apply to notes
1872                          * on the other voice, fix that */
1873                         other_voice_accidentals(mll_p->u.staff_p);
1874
1875                         /* need to check stufflist on top visible to
1876                          * update Usec_per_quarter if necessary */
1877                         if (did_all == NO && svpath(mll_p->u.staff_p->staffno,
1878                                         VISIBLE)->visible == YES) {
1879                                 begin_usec = Usec_per_quarter_note;
1880                                 Absolute_time = Zero;
1881                                 prepmidi_stuff(mll_p->u.staff_p, 0, YES);
1882                                 did_all = YES;
1883                         }
1884
1885                         /* go through all groups, making adjustments */
1886                         for (v = 0; v < MAXVOICES; v++) {
1887                                 Usec_per_quarter_note = begin_usec;
1888                                 Absolute_time = Zero;
1889                                 adjust_notes(mll_p->u.staff_p->groups_p[v],
1890                                         mll_p->u.staff_p->staffno, v, mll_p);
1891                         }
1892                         got_data = YES;
1893                 }
1894                 else if (mll_p->str == S_SSV) {
1895                         asgnssv(mll_p->u.ssv_p);
1896                         if (got_data == NO &&
1897                                         mll_p->u.ssv_p->context == C_SCORE) {
1898                                 if (mll_p->u.ssv_p->used[TIME] == YES) {
1899                                         Time_specified_by_user = YES;
1900                                 }
1901                                 if (mll_p->u.ssv_p->used[SHARPS] == YES) {
1902                                         Key_specified_by_user = YES;
1903                                 }
1904                                 if (mll_p->u.ssv_p->used[DIVISION] == YES) {
1905                                         Division = mll_p->u.ssv_p->division;
1906                                 }
1907                                 /* setting transposition implicitly sets a key */
1908                                 if (mll_p->u.ssv_p->used[TRANSPOSITION] == YES ||
1909                                 mll_p->u.ssv_p->used[ADDTRANSPOSITION] == YES) {
1910                                         Key_specified_by_user = YES;
1911                                 }
1912                                 
1913                         }
1914                 }
1915                 else if (mll_p->str == S_BAR) {
1916                         /* reset for next measure */
1917                         did_all = NO;
1918                         fix_tempo(YES);
1919                         /* free up saved stuff info */
1920                         free_midistuff(Midistufflist_p);
1921                         Midistufflist_p = (struct MIDISTUFF *) 0;
1922                 }
1923         }
1924 }
1925 \f
1926
1927 /* adjust any grace notes to get a little time. We
1928  * don't know for sure how much time they should get, and whether they should
1929  * be on the beat or before or when, so make some guesses.
1930  * Take half of the fulltime of the preceeding group and divide that time
1931  * among the number of grace notes.
1932  * Compare that value with 0.1 second, and use whichever is shorter.
1933  * Also shorten groups slightly to give a little release time between
1934  * notes (so that repeated notes don't run together so much), and
1935  * shorten groups that have staccato or wedge in their "with" list, and do
1936  * alternation groups and rolls */
1937
1938 static void
1939 adjust_notes(gs_p, staffno, v, mll_p)
1940
1941 struct GRPSYL *gs_p;    /* adjust groups in this list */
1942 int staffno;
1943 int v;
1944 struct MAINLL *mll_p;   /* groups are attached to main list here */
1945
1946 {
1947         int numgrace = 0;
1948         struct GRPSYL *gracelist_p;     /* one or more grace notes */
1949         RATIONAL gracetime;             /* duration of grace notes */
1950         RATIONAL time_adj;              /* adjustment for alt groups */
1951         int pairs;                      /* how many pair of GRPSYLS to add
1952                                          * for an alt pair */
1953         struct GRPSYL *add1_p, *add2_p; /* groups added for alt pairs */
1954         int alt;                        /* alternation number */
1955         int nn;                         /* number of number due to slashes */
1956         int d;                          /* number of dots */
1957         int dot, wedge, legato;         /* YES if these set in "with" list */
1958         int font, size;
1959         char *str;                      /* string in with list */
1960         int ch;                         /* music character in with list */
1961         int w;                          /* index through with list */
1962         struct GRPSYL *prevgs_p;        /* group before grace note(s) */
1963         RATIONAL tenthsec;              /* note value that is about 0.1 sec */
1964         RATIONAL release;               /* how soon to release note */
1965         RATIONAL release_adjust;        /* how soon to release current note,
1966                                          * the shorter of release and 1/4
1967                                          * of the group's time value */
1968         RATIONAL graceadj;              /* for calculating grace durations */
1969         RATIONAL fulltime;
1970         RATIONAL total_time;            /* time so far in measure */
1971         struct MAINLL *m_p;             /* for finding TIMEDSSVs, if any */
1972         struct TIMEDSSV *tssv_p;        /* for mid-measure release changes */
1973         static int had_tssv = NO;       /* If have any timed SSVs anywhere,
1974                                          * we'll always call setssvstate() to
1975                                          * make sure RELEASE is up to date.
1976                                          * Just knowing if they were in this
1977                                          * measure is not sufficient.
1978                                          * Could be done on some granularity
1979                                          * smaller than the whole song,
1980                                          * but this is simple, and probably
1981                                          * efficient enough.
1982                                          */
1983
1984
1985         /* Some compilers warn that gracelist_p might be used uninitialized.
1986          * Actually it won't be, but keep them quiet.
1987          */
1988         gracelist_p = (struct GRPSYL *) 0;
1989
1990         /* See if there are any timed SSVs to worry about */
1991         for (tssv_p = 0, m_p = mll_p; m_p != 0; m_p = m_p->next) {
1992                 if (m_p->str == S_BAR) {
1993                         tssv_p = m_p->u.bar_p->timedssv_p;
1994                         if (tssv_p != 0) {
1995                                 had_tssv = YES;
1996                         }
1997                         break;
1998                 }
1999         }
2000         if (had_tssv == YES) {
2001                 setssvstate(mll_p);
2002         }
2003
2004         total_time = Zero;
2005         for (   ; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) {
2006
2007                 /* apply any timed SSVs */
2008                 if (gs_p->prev != 0) {
2009                         total_time = radd(total_time, gs_p->prev->fulltime);
2010                 }
2011                 while (tssv_p != 0 && LE(tssv_p->time_off, total_time)) {
2012                         asgnssv(&tssv_p->ssv);
2013                         tssv_p = tssv_p->next;
2014                 }
2015
2016                 if (gs_p->grpvalue == GV_ZERO)  {
2017                         if (numgrace == 0) {
2018                                 /* save starting point of list of grace notes */
2019                                 gracelist_p = gs_p;
2020                         }
2021                         /* count how many grace notes */
2022                         numgrace++;
2023                 }
2024
2025                 else {
2026                         /* if there were grace groups before this group,
2027                          * adjust to give them some time. */
2028                         if (numgrace > 0) {
2029                                 /* find the previous group */
2030                                 prevgs_p = grp_before(gracelist_p, mll_p,
2031                                                                 staffno, v);
2032
2033                                 /* If the previous group is notes,
2034                                  * take 1/2 of that groups time value and
2035                                  * apportion among the grace notes.
2036                                  * If rest or space, we can probably afford
2037                                  * to use more. Exactly how much is unclear,
2038                                  * so we'll use 3/4 */
2039                                 if (prevgs_p->grpcont == GC_NOTES) {
2040                                         graceadj.n = 1;
2041                                         graceadj.d = 2 * numgrace;
2042                                 }
2043                                 else {
2044                                         graceadj.n = 3;
2045                                         graceadj.d = 4 * numgrace;
2046                                 }
2047                                 rred( &graceadj );
2048                                 gracetime = rmul(prevgs_p->fulltime,
2049                                                                 graceadj);
2050
2051                                 /* If grace notes come out to more than
2052                                  * about 1/10th second, use 1/10th second
2053                                  * instead. First figure out what sort of
2054                                  * fulltime value would be 0.1 second, by
2055                                  * taking 1 over the number of microseconds
2056                                  * in a whole note divided by 100000 */
2057                                 tenthsec.n = 1L;
2058                                 tenthsec.d = 4L * Usec_per_quarter_note / 100000L;
2059
2060                                 if (tenthsec.d == 0) {
2061                                         /* we're in some outrageously fast
2062                                          * tempo, over 600 quarter notes
2063                                          * per minute, which is so fast
2064                                          * that even a whole note
2065                                          * isn't a tenth of a second.
2066                                          * Make sure the denominator
2067                                          * isn't zero, so we won't
2068                                          * core dump. At this absurd tempo,
2069                                          * we'd not going to be using this
2070                                          * value anyway, except to compare
2071                                          * against gracetime, so if it's
2072                                          * off some, it won't matter. */
2073                                         tenthsec.d = 1L;
2074                                 }
2075                                 rred ( &tenthsec );
2076
2077                                 if ( LT(tenthsec, gracetime)) {
2078                                         gracetime = tenthsec;
2079                                 }
2080                                 /* round to nearest 2048 note to try to
2081                                  * avoid arithmetic overflows */
2082                                 gracetime.n = 2048 * gracetime.n / gracetime.d;
2083                                 gracetime.d = 2048;
2084                                 rred ( &gracetime );
2085
2086                                 /* subtract time from previous group */
2087                                 graceadj.n = numgrace;
2088                                 graceadj.d = 1;
2089                                 prevgs_p->fulltime = rsub(prevgs_p->fulltime,
2090                                         rmul(gracetime, graceadj));
2091
2092                                 /* give each grace note that much time */
2093                                 for (   ; numgrace > 0; numgrace--) {
2094                                         gracelist_p->fulltime = gracetime;
2095                                         gracelist_p = gracelist_p->next;
2096                                 }
2097                         }
2098                         numgrace = 0;
2099                         fulltime = gs_p->fulltime;
2100
2101                         /* check for alternation.
2102                          * For each alt, double the number
2103                          * of notes and make each half as long. */
2104                         if (gs_p->slash_alt < 0) {
2105
2106                                 alt = -(gs_p->slash_alt);
2107
2108                                 /* for long notes, adjust so we get down to
2109                                  * 8th notes for alternation */
2110                                 if (gs_p->basictime == 0) {
2111                                         alt += 2;
2112                                 }
2113                                 else if (gs_p->basictime == 1) {
2114                                         alt += 1;
2115                                 }
2116                                 else if (gs_p->basictime >= 4) {
2117                                         alt -= 1;
2118                                 }
2119
2120                                 /* adjust time values */
2121                                 time_adj.n = 1;
2122                                 time_adj.d = 1 << alt;
2123                                 gs_p->fulltime = rmul(gs_p->fulltime, time_adj);
2124                                 rred ( &(gs_p->fulltime) );
2125                                 gs_p->next->fulltime = gs_p->fulltime;
2126
2127                                 /* turn off slash_alt so we won't do it again
2128                                  * on the added pairs */
2129                                 gs_p->slash_alt = 0;
2130                                 gs_p->next->slash_alt = 0;
2131
2132                                 /* add as many more pairs as necessary */
2133                                 /* If user specifies an insane
2134                                  * alt number, we could try to make
2135                                  * millions of groups. So limit to 1000.
2136                                  */
2137                                 pairs = (1 << alt) - 1;
2138                                 if (pairs > 1000) {
2139                                         pairs = 1000;
2140                                 }
2141                                 for (  ; pairs > 0; pairs--) {
2142                                         /* create a new pair clone */
2143                                         add1_p = newGRPSYL(GS_GROUP);
2144                                         copy_attributes(add1_p, gs_p);
2145                                         add1_p->fulltime = gs_p->fulltime;
2146                                         copy_notes(add1_p, gs_p);
2147                                         add2_p = newGRPSYL(GS_GROUP);
2148                                         copy_attributes(add2_p, gs_p->next);
2149                                         add2_p->fulltime = gs_p->next->fulltime;
2150                                         copy_notes(add2_p, gs_p->next);
2151
2152                                         /* link pair into list */
2153                                         add1_p->next = add2_p;
2154                                         add2_p->prev = add1_p;
2155                                         add2_p->next = gs_p->next->next;
2156                                         if (add2_p->next != (struct GRPSYL *) 0) {
2157                                                 add2_p->next->prev = add2_p;
2158                                         }
2159                                         gs_p->next->next = add1_p;
2160                                         add1_p->prev = gs_p->next;
2161                                 }
2162                         }
2163                         else if (gs_p->slash_alt > 0
2164                                                 && gs_p->grpvalue != GV_ZERO) {
2165                                 /* do slashed notes */
2166                                 /* figure out how many actual chords are
2167                                  * represented by the slashed chord */
2168                                 switch (gs_p->basictime) {
2169                                 case 0:
2170                                         nn = 16;
2171                                         break;
2172                                 case 1:
2173                                         nn = 8;
2174                                         break;
2175                                 case 2:
2176                                         nn = 4;
2177                                         break;
2178                                 default:
2179                                         nn = 2;
2180                                         break;
2181                                 }
2182                                 /* multiply by two for each additional slash
2183                                  * beyond the first.  Need to keep this IF
2184                                  * here to avoid hitting potential optimizer
2185                                  * bug. See comment in grpsyl.c */
2186                                 if (gs_p->slash_alt > 1) {
2187                                         nn = nn << (gs_p->slash_alt - 1);
2188                                 }
2189
2190                                 if (nn == 0) {
2191                                         /* shifted left into oblivion */
2192                                         /* parser should have caught this */
2193                                         pfatal("bug in slash handling");
2194                                 }
2195                                 /* Add an additional 1 bit at the right for
2196                                  * each dot */
2197                                 else {
2198                                         for (d = gs_p->dots; d > 0; d--) {
2199                                                  nn |= 1 << (drmo(nn) - 1);
2200                                         }
2201                                 }
2202                                 /* adjust time of notes, by dividing the
2203                                  * fulltime of the group by the number of
2204                                  * notes. We don't look at the basictime
2205                                  * or dots again, so can leave them */
2206                                 gs_p->fulltime.d *= nn;
2207                                 rred ( &(gs_p->fulltime) );
2208
2209                                 /* mark that we have done the slash */
2210                                 gs_p->slash_alt = 0;
2211
2212                                 /* create as many clones of the groups as
2213                                  * needed. Use > 1 because we
2214                                  * already have the original group. */
2215                                 for (    ; nn > 1; nn--) {
2216                                         add1_p = newGRPSYL(GS_GROUP);
2217                                         copy_attributes(add1_p, gs_p);
2218                                         add1_p->fulltime = gs_p->fulltime;
2219                                         copy_notes(add1_p, gs_p);
2220                                         /* link into list */
2221                                         add1_p->next = gs_p->next;
2222                                         add1_p->prev = gs_p;
2223                                         gs_p->next = add1_p;
2224                                         if (add1_p->next != (struct GRPSYL *) 0) {
2225                                                 add1_p->next->prev = add1_p;
2226                                         }
2227                                 }
2228                         }
2229
2230                         /* now shorten any groups with dots or wedges */
2231                         dot = wedge = legato = NO;
2232                         for (w = 0; w < gs_p->nwith; w++) {
2233                                 if (is_music_symbol(gs_p->withlist[w]) == NO) {
2234                                         continue;
2235                                 }
2236                                 font = gs_p->withlist[w][0];
2237                                 size =  gs_p->withlist[w][1];
2238                                 str = gs_p->withlist[w] + 2;
2239                                 ch = next_str_char(&str, &font, &size);
2240                                 switch (ch) {
2241                                 case C_DOT:
2242                                         dot = YES;
2243                                         break;
2244                                 case C_WEDGE:
2245                                 case C_UWEDGE:
2246                                         wedge = YES;
2247                                         break;
2248                                 case C_LEG:
2249                                         legato = YES;
2250                                         break;
2251                                 }
2252                         }
2253                         if (wedge == YES) {
2254                                 /* reduce to 1/3 time, add rest for other 2/3 */
2255                                 add_rest(gs_p, rmul(gs_p->fulltime, Two_thirds));
2256                                 gs_p->fulltime = rmul(gs_p->fulltime, One_third);
2257                         }
2258                         else if (dot == YES) {
2259                                 if (legato == YES) {
2260                                         /* reduce by 1/4 */
2261                                         add_rest(gs_p, rmul(gs_p->fulltime,
2262                                                                 One_fourth));
2263                                         gs_p->fulltime = rmul(gs_p->fulltime,
2264                                                                 Three_fourths);
2265                                 }
2266                                 else {
2267                                         /* reduce by half */
2268                                         add_rest(gs_p, rmul(gs_p->fulltime,
2269                                                                 One_half));
2270                                         gs_p->fulltime = rmul(gs_p->fulltime,
2271                                                                 One_half);
2272                                 }
2273                         }
2274
2275                         else if (gs_p->grpcont == GC_NOTES) {
2276
2277                                 /* Figure out fulltime value for
2278                                  * milliseconds of release time */
2279                                 release.n = (UINT32B)
2280                                         vvpath(staffno, v + 1, RELEASE)->release;
2281                                 release.d = 4L * Usec_per_quarter_note / 1000L;
2282
2283                                 if (GT(release, Zero)) {
2284                                         /* shorten by a little bit.
2285                                          * Otherwise repeated notes
2286                                          * run together so much they can sound
2287                                          * like a single note
2288                                          * on some instruments. */
2289
2290                                         /* round off to nearest 1024 note.
2291                                          * Otherwise we can very quickly
2292                                          * get to the point that the
2293                                          * lowest common denominator of
2294                                          * accumulated time values will get
2295                                          * so big we overflow an UINT32B,
2296                                          * which can cause lots of problems.
2297                                          * Besides, this is going to get
2298                                          * rounded off to the granularity
2299                                          * of MIDI clock tick eventually anyway,
2300                                          * and will be affected by MIDI latency,
2301                                          * so if it is off by a few
2302                                          * microseconds, it is very doubtful
2303                                          * anyone will notice. */
2304                                         release.n = 1024 * release.n
2305                                                                 / release.d;
2306                                         release.d = 1024;
2307
2308                                         rred (&release);
2309
2310                                         /* Shorten by the lesser of 1/4 of the
2311                                          * note time or the amount user
2312                                          * asked for */
2313                                         release_adjust = rmul(gs_p->fulltime,
2314                                                                 One_fourth);
2315                                         if (LT(release, release_adjust)) {
2316                                                 release_adjust = release;
2317                                         }
2318                                         add_release(gs_p, release_adjust, mll_p);
2319                                 }
2320                         }
2321
2322                         /* handle any rolls */
2323                         fix_tempo(NO);
2324                         midi_roll(gs_p, &(mll_p->u.staff_p->groups_p[v]));
2325                         Absolute_time = radd(Absolute_time, fulltime);
2326                 }
2327         }
2328 }
2329 \f
2330
2331 /* Usually we can just add in the release as is. But if the next group is
2332  * a grace group, it could end up being really short, because it steals
2333  * from the previous group, which would be this added release rest, which
2334  * is likely to be quite short. So peek ahead. If the next group is a grace,
2335  * only add in the release if it is at least 135 ms per following grace
2336  * group, which would allow them about 100 ms each. If it's shorter than
2337  * that, don't add any release, and just let the grace(s) steal from the
2338  * note group. */
2339
2340 static void
2341 add_release(gs_p, release_adjust, mll_p)
2342
2343 struct GRPSYL *gs_p;
2344 RATIONAL release_adjust;
2345 struct MAINLL *mll_p;
2346
2347 {
2348         struct GRPSYL *nextgs_p;
2349         int numgrace;
2350         double rel_time;        /* release adjust in milliseconds */
2351
2352         if ((nextgs_p = nextgrpsyl(gs_p, &mll_p)) != (struct GRPSYL *) 0) {
2353                 /* count how many grace notes coming up after our gs_p */
2354                 for (numgrace = 0; nextgs_p->grpvalue == GV_ZERO;
2355                                                 nextgs_p = nextgs_p->next) {
2356                         numgrace++;
2357                 }
2358
2359                 if (numgrace > 0) {
2360                         /* Calculate length of proposed release,
2361                          * by multiplying its time value by the number
2362                          * of milliseconds in a whole note. */
2363                         rel_time = RAT2FLOAT(release_adjust) *
2364                                 Usec_per_quarter_note * 4L / 1000L;
2365
2366                         /* now see if it's too short */
2367                         if ( rel_time < 135.0 * numgrace) {
2368                                 return;
2369                         }
2370                 }
2371         }
2372
2373         /* add in a rest to accomplish the release */
2374         add_rest(gs_p, release_adjust);
2375         gs_p->fulltime = rsub(gs_p->fulltime, release_adjust);
2376 }
2377 \f
2378
2379 /* turn damper pedal switch on or off. Return number of bytes written */
2380
2381 static UINT32B
2382 pedswitch(mfile, on)
2383
2384 int mfile;
2385 int on;         /* YES if to turn damper pedal on, NO if to turn off */
2386
2387 {
2388         UINT32B bytes;
2389         unsigned char buff[4];
2390
2391
2392         bytes = write_delta(mfile);
2393         Status = buff[0] = (unsigned char) (0xb0 | Channel);
2394         buff[1] = (unsigned char) 64;
2395         buff[2] = (on ? 127 : 0);
2396         bytes += write(mfile, buff, 3);
2397         return(bytes);
2398 }
2399 \f
2400
2401 /* do rolls. Separate into several groups with notes tied together */
2402
2403 static void
2404 midi_roll(gs_p, gslist_p_p)
2405
2406 struct GRPSYL *gs_p;
2407 struct GRPSYL **gslist_p_p;     /* head of list of groups for this voice/meas */
2408
2409 {
2410         RATIONAL rolltime;              /* roll time adjust per note */
2411         struct GRPSYL *g_p;             /* walk through groups in roll */
2412         RATIONAL shortest;              /* shortest group in roll */
2413         int nnotes;                     /* how many notes in roll */
2414         struct MIDIROLL *mrinfo;        /* information about a roll */
2415
2416
2417         switch (gs_p->roll) {
2418         case LONEITEM:
2419                 if (gs_p->nnotes  < 2) {
2420                         /* degenerate roll */
2421                         return;
2422                 }
2423
2424                 rolltime = roll_time(gs_p->fulltime, gs_p->nnotes);
2425                 do_mroll(gs_p, gslist_p_p, rolltime, 0);
2426                 break;
2427
2428         case STARTITEM:
2429                 /* count how many notes total to roll, and get duration of
2430                  * shortest group in the roll */
2431                 nnotes = gs_p->nnotes;
2432                 shortest = gs_p->fulltime;
2433                 for (g_p = gs_p->gs_p; g_p != (struct GRPSYL *) 0;
2434                                                         g_p = g_p->gs_p) {
2435                         nnotes += g_p->nnotes;
2436                         if (LT(g_p->fulltime, shortest)) {
2437                                 shortest = g_p->fulltime;
2438                         }
2439                         if (g_p->roll == ENDITEM) {
2440                                 break;
2441                         }
2442                 }
2443
2444                 rolltime = roll_time(shortest, nnotes);
2445
2446                 /* do first group */
2447                 if (gs_p->rolldir != DOWN) {
2448                         nnotes -= gs_p->nnotes;
2449                         do_mroll(gs_p, gslist_p_p, rolltime, nnotes);
2450                 }
2451                 else {
2452                         do_mroll(gs_p, gslist_p_p, rolltime, 0);
2453                         nnotes = gs_p->nnotes;
2454                 }
2455
2456                 /* now go down the chord again saving information about the
2457                  * roll on other groups */
2458                 for (g_p = gs_p->gs_p; g_p != (struct GRPSYL *) 0;
2459                                                         g_p = g_p->gs_p) {
2460                         if (gs_p->rolldir != DOWN) {
2461                                 nnotes -= g_p->nnotes;
2462                                 savemidiroll(g_p, nnotes, rolltime);
2463                         }
2464                         else {
2465                                 savemidiroll(g_p, nnotes, rolltime);
2466                                 nnotes += g_p->nnotes;
2467                         }
2468                         if (g_p->roll == ENDITEM) {
2469                                 break;
2470                         }
2471                 }
2472                 break;
2473
2474         case INITEM:
2475         case ENDITEM:
2476                 /* retrieve info about this roll and do it */
2477                 if ((mrinfo = getmidiroll(gs_p)) == (struct MIDIROLL *) 0) {
2478                         /* if staff is invisible, this is okay, otherwise
2479                          * something must have gone wrong */
2480                         if (svpath(gs_p->staffno, VISIBLE)->visible == YES) {
2481                                 pfatal("info about roll is missing");
2482                         }
2483                 }
2484                 else {
2485                         do_mroll(gs_p, gslist_p_p, mrinfo->duration,
2486                                                 mrinfo->notesbefore);
2487                         FREE(mrinfo);
2488                 }
2489                 break;
2490
2491         default:
2492                 break;
2493         }
2494 }
2495 \f
2496
2497 /* given a chord duration and number of notes, return how long to make
2498  * each note of roll. Use 1/20 second or whatever would add up to a total
2499  * of half the duration, whichever is shorter */
2500
2501 static RATIONAL
2502 roll_time(grptime, nnotes)
2503
2504 RATIONAL grptime;       /* duration of rolled chord */
2505 int nnotes;             /* how many notes in the chord */
2506
2507 {
2508         RATIONAL rolltime;              /* roll time adjust per note */
2509         RATIONAL maxdur;                /* note equal to 0.05 second */
2510
2511
2512         /* if not enough notes to roll, don't do anything here */
2513         if (nnotes < 2) {
2514                 return(Zero);
2515         }
2516
2517         /* as first guess, apportion the extra groups into half of
2518          * the group time */
2519         rolltime = rmul(grptime, One_half);
2520         rolltime.d *= (nnotes - 1);
2521         rred ( &rolltime );
2522
2523         /* find 0.05 second time */
2524         maxdur.n = 1;
2525         maxdur.d = 4L * Usec_per_quarter_note / 50000L;
2526
2527         /* use whichever is shorter */
2528         return( LT(maxdur, rolltime) ? maxdur : rolltime);
2529 }
2530 \f
2531
2532 /* create and link the extra groups to implement roll sound */
2533
2534 static void
2535 do_mroll(gs_p, gslist_p_p, rolltime, notesbefore)
2536
2537 struct GRPSYL *gs_p;            /* group having roll */
2538 struct GRPSYL **gslist_p_p;     /* addr of groups_p list containing gs_p */
2539 RATIONAL rolltime;              /* duration per roll note */
2540 int notesbefore;                /* how many notes of roll before this in
2541                                  * chords in other voices */
2542
2543 {
2544         register int i;
2545         struct GRPSYL **link_p_p;       /* where to link added groups */
2546         struct GRPSYL *prev_p;          /* previous group */
2547         RATIONAL factor;                /* multiplier of duration */
2548         struct GRPSYL *newgs_p;         /* added rest group */
2549
2550
2551         /* figure out where to link added groups */
2552         if (gs_p->prev == (struct GRPSYL *) 0) {
2553                 link_p_p = gslist_p_p;
2554         }
2555         else {
2556                 link_p_p = &( gs_p->prev->next);
2557         }
2558         prev_p = gs_p->prev;
2559
2560         /* add in groups with appropriate subset of notes, tied to
2561          * the existing group */
2562         if (gs_p->rolldir != DOWN) {
2563                 for (i = 1; i < gs_p->nnotes; i++) {
2564                         addrollgrp(gs_p, rolltime, i, gs_p->nnotes - 1,
2565                                                 link_p_p, prev_p);
2566                 }
2567         }
2568         else {
2569                 for (i = gs_p->nnotes - 2; i >= 0; i--) {
2570                         addrollgrp(gs_p, rolltime, 0, i,
2571                                                 link_p_p, prev_p);
2572                 }
2573         }
2574
2575         /* adjust group time */
2576         factor.n = gs_p->nnotes - 1 + notesbefore;
2577         factor.d = 1;
2578         gs_p->fulltime = rsub(gs_p->fulltime, rmul(rolltime, factor));
2579
2580         /* add rest before if necessary */
2581         if (notesbefore > 0) {
2582                 factor.n = notesbefore;
2583                 CALLOC(GRPSYL, newgs_p, 1);
2584                 newgs_p->grpcont = GC_REST;
2585                 newgs_p->fulltime = rmul(rolltime, factor);
2586                 /* mark as internally generated, so octave adjust works */
2587                 newgs_p->inputlineno = -1;
2588
2589                 /* stitch into list */
2590                 (*link_p_p)->prev = newgs_p;
2591                 newgs_p->next = *link_p_p;
2592                 newgs_p->prev = prev_p;
2593                 *link_p_p = newgs_p;
2594         }
2595 }
2596 \f
2597
2598 /* add group to form part of a roll */
2599
2600 static void
2601 addrollgrp(gs_p, duration, start, end, link_p_p, prev_p)
2602
2603 struct GRPSYL *gs_p;
2604 RATIONAL duration;
2605 int start;              /* index into notelist, where to start copying notes */
2606 int end;                /* index into notelist, where to stop copying notes */
2607 struct GRPSYL **link_p_p; /* where to link into list */
2608 struct GRPSYL *prev_p;  /* previous group */
2609
2610 {
2611         struct GRPSYL *newgs_p;
2612         int i;
2613
2614
2615         newgs_p = newGRPSYL(GS_GROUP);
2616         newgs_p->grpcont = GC_NOTES;
2617         newgs_p->fulltime = duration;
2618         newgs_p->nnotes = end - start + 1;
2619         /* mark as internally generated, so octave adjusting will work */
2620         newgs_p->inputlineno = -1;
2621
2622         /* copy appropriate subset of notes from original group */
2623         CALLOC(NOTE, newgs_p->notelist, newgs_p->nnotes);
2624         for (i = 0; start <= end; i++, start++) {
2625                 newgs_p->notelist[i].letter = gs_p->notelist[start].letter;
2626                 newgs_p->notelist[i].accidental
2627                                         = gs_p->notelist[start].accidental;
2628                 newgs_p->notelist[i].octave = gs_p->notelist[start].octave;
2629                 newgs_p->tie = YES;
2630         }
2631         
2632         /* stitch into list */
2633         (*link_p_p)->prev = newgs_p;
2634         newgs_p->next = *link_p_p;
2635         newgs_p->prev = prev_p;
2636         *link_p_p = newgs_p;
2637 }
2638 \f
2639
2640 /* Create struct to hold info about roll that crosses groups and fill it in.
2641  * Link onto list of info of this type */
2642
2643 static void
2644 savemidiroll(gs_p, notesbefore, duration)
2645
2646 struct GRPSYL *gs_p;
2647 int notesbefore;
2648 RATIONAL duration;
2649
2650 {
2651         struct MIDIROLL *new_p;
2652
2653         CALLOC(MIDIROLL, new_p, 1);
2654         new_p->gs_p = gs_p;
2655         new_p->notesbefore = (short) notesbefore;
2656         new_p->duration = duration;
2657         new_p->link_p = Midirollinfo_p;
2658         Midirollinfo_p = new_p;
2659 }
2660 \f
2661
2662 /* given a GRPSYL, return pointer to the MIDIROLL struct associated with it,
2663  * after detaching it from the list.  Caller is responsible for freeing it.
2664  * Returns null if not on the list */
2665
2666 static struct MIDIROLL *
2667 getmidiroll(gs_p)
2668
2669 struct GRPSYL *gs_p;
2670
2671 {
2672         struct MIDIROLL **mr_p_p;
2673         struct MIDIROLL *the_one;       /* the one matching gs_p */
2674
2675
2676         /* walk down list. Since there aren't likely to be all that many
2677          * multi-voice rolls per measure, we just use a linked list instead
2678          * of hashing or something. */
2679         for (mr_p_p = &Midirollinfo_p; *mr_p_p != (struct MIDIROLL *) 0;
2680                         mr_p_p = &( (*mr_p_p)->link_p) ){
2681
2682                 if ( (*mr_p_p)->gs_p == gs_p) {
2683                         /* found it. detach and return it */
2684                         the_one = *mr_p_p;
2685                         *mr_p_p = (*mr_p_p)->link_p;
2686                         return(the_one);
2687                 }
2688         }
2689         return (struct MIDIROLL *) 0;
2690 }
2691 \f
2692
2693 /* go through list of STUFFs for this measure. If there is a MIDI "tempo"
2694  * STUFF prior to the current time, update Usec_per_quarter_note */
2695
2696 static void
2697 fix_tempo(to_end)
2698
2699 int to_end;     /* if YES, go all the way to end of Midistufflist_p */
2700
2701 {
2702         struct MIDISTUFF *ms_p;         /* index through list of STUFF */
2703         char *key;                      /* to check for "tempo" */
2704         int leng;                       /* length of key */
2705         char *arg;                      /* tempo argument */
2706         int quarter_notes_per_min;      /* notes per minute */
2707
2708
2709         /* check stuff in this measure */
2710         for (ms_p = Midistufflist_p; ms_p != (struct MIDISTUFF *) 0;
2711                                         ms_p = ms_p->next) {
2712                 if (GE(ms_p->time, Absolute_time) && to_end == NO) {
2713                         /* beyond where we are in time so far */
2714                         return;
2715                 }
2716
2717                 /* see if MIDI tempo */
2718                 if (ms_p->stuff_p->stuff_type == ST_MIDI) {
2719                         if (getkeyword(ms_p->stuff_p->string + 2, &key, &leng,
2720                                                         &arg) == YES) {
2721                                 if (matches(key, leng, "tempo") == YES) {
2722                                         /* is it tempo. Update */
2723                                         quarter_notes_per_min = atoi(arg);
2724                                         if (quarter_notes_per_min >= MINQNPM
2725                                                 && quarter_notes_per_min
2726                                                 <= MAXQNPM)  {
2727                                             Usec_per_quarter_note =
2728                                                 USEC_PER_MINUTE
2729                                                 /  quarter_notes_per_min;
2730                                         }
2731                                 }
2732                         }
2733                 }
2734         }
2735 }
2736 \f
2737
2738 /* recursively free MIDISTUFF list */
2739
2740 static void
2741 free_midistuff(ms_p)
2742
2743 struct MIDISTUFF *ms_p;
2744
2745 {
2746         if (ms_p == (struct MIDISTUFF *) 0) {
2747                 return;
2748         }
2749
2750         free_midistuff(ms_p->next);
2751         FREE(ms_p);
2752 }
2753 \f
2754
2755 /* when a group is squeezed to zero time because the chord was all spaces,
2756  * we need to adjust the time to do any pending stuffs by the amount
2757  * of time squeezed out. So go through the list of pending stuffs, and
2758  * mark them as occurring that much earlier, or immediately if the time
2759  * would end up negative. Octave marks are handled a measure at a time,
2760  * so we don't have to worry about them.
2761  * If user put a stuff in the middle of an all-space chord,
2762  * maybe they really wanted the space not squeezed, but tough.
2763  * If they really want time taken up they should use rest, not space.
2764  * It isn't worth the effort to figure out that some particular space
2765  * chord has a stuff in the middle of it, so that it should be treated
2766  * specially.
2767  */
2768
2769 static void
2770 adj4squeeze(timeval)
2771
2772 RATIONAL timeval;       /* adjust by this much */
2773
2774 {
2775         struct MIDISTUFF *ms_p; /* walk through list of MIDI stuff to do */
2776
2777
2778         for (ms_p = Midistufflist_p; ms_p != (struct MIDISTUFF *) 0;
2779                                         ms_p = ms_p->next) {
2780
2781                 /* adjust the time */
2782                 ms_p->time = rsub(ms_p->time, timeval);
2783
2784                 if (LT(ms_p->time, Zero)) {
2785                         /* Oops. User put a stuff in the middle of an
2786                          * all-space group. Schedule the stuff to happen
2787                          * immediately */
2788                         ms_p->time = Zero;
2789                 }
2790         }
2791 }
2792 \f
2793
2794 /* return YES if specified staff/voice is used somewhere in the piece */
2795
2796 int
2797 voice_used(staffno, vno)
2798
2799 int staffno;
2800 int vno;
2801
2802 {
2803         return (Voice2track_map [staffno] [vno] != 0 ? YES : NO);
2804 }