chiark / gitweb /
Merge branch 'arkkra' into shiny
[mup] / mup / mup / midi.c
CommitLineData
69695f33
MW
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. */
46struct 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. */
59struct 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 */
79static struct MIDISTUFF *Midistufflist_p;
80
81/* list of pending rolls to do */
82static struct MIDIROLL *Midirollinfo_p;
83
84/* tables for mapping voices to tracks and vice versa */
85static short Voice2track_map [MAXSTAFFS + 1] [MAXVOICES];
86static short Track2staff_map [MAXSTAFFS * MAXVOICES];
87static short Track2voice_map [MAXSTAFFS * MAXVOICES];
88
89static 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# */
96static 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. */
100static 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 */
104static RATIONAL Absolute_time;
105static RATIONAL Sum_of_deltas;
106
107static 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
111static short Channel = 0; /* MIDI channel, 0-15 */
112static char Onvelocity[MAXHAND]; /* note on velocity */
113static char Offvelocity[MAXHAND]; /* note off velocity */
114static short Time_specified_by_user = NO; /* YES if user had a score SSV
115 * setting the time before any music data */
116static short Key_specified_by_user = NO; /* YES if user had a score SSV
117 * setting the key before any music data */
118static int Division = DEFDIVISION; /* clock ticks per quarter note */
119
120static UINT32B Usec_per_quarter_note = DFLT_USEC_PER_QUARTER;
121
122static short Pedbounce = NO; /* if pedal bounce pending */
123
124/* local functions */
125static void repeats P((struct MAINLL **mll_p_p, int *doing_repeat_p,
126 struct MAINLL **repeat_start_p_p));
127static RATIONAL eff_meas_time P((struct MAINLL *mll_p));
128static void midi_header P((int mfile, int ntracks));
129static void track_header P((int mfile));
130static UINT32B write_midi_data P((int mfile, struct GRPSYL *gs_p));
131static void init_accidental_map P((int staffno));
132static void mark_accidental P((int pitch_offset, int acc));
133static UINT32B midi_multirest P((int mfile, struct STAFF *staff_p, int staffno,
134 int vno, int nummeas));
135static void init_tie_table P((void));
136static int xlate_note P((struct NOTE *note_p, char *fname, int lineno,
137 int *raw_notenum_p));
138static void prepmidi_stuff P((struct STAFF *staff_p, int vno, int all));
139static UINT32B do_midi_stuff P((RATIONAL timeval, int mfile, int all));
140static UINT32B midihex P((int mfile, char *str, char *fname, int lineno));
141static UINT32B midi_item P((struct STUFF *stuff_p, int mfile, int all));
142static UINT32B wr_meta P((int mfile, int evtype, char *str));
143static UINT32B all_midi P((int mfile));
144static void midi_adjust P((void));
145static void adjust_notes P((struct GRPSYL *gs_p, int staffno, int v,
146 struct MAINLL *mll_p));
147static void add_release P((struct GRPSYL *gs_p, RATIONAL release_adjust,
148 struct MAINLL *mll_p));
149static UINT32B pedswitch P((int nfile, int on));
150static void midi_roll P((struct GRPSYL *gs_p, struct GRPSYL **gslist_p_p));
151static RATIONAL roll_time P((RATIONAL grptime, int nnotes));
152static void do_mroll P((struct GRPSYL *gs_p, struct GRPSYL **gslist_p_p,
153 RATIONAL rolltime, int notesbefore));
154static void addrollgrp P((struct GRPSYL *gs_p, RATIONAL duration, int start,
155 int end, struct GRPSYL **link_p_p, struct GRPSYL *prev_p));
156static void savemidiroll P((struct GRPSYL *gs_p, int notesbefore,
157 RATIONAL duration));
158static struct MIDIROLL *getmidiroll P((struct GRPSYL *gs_p));
159static void fix_tempo P((int to_end));
160static void free_midistuff P((struct MIDISTUFF *ms_p));
161static 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
169void
170gen_midi(midifilename)
171
172char *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
463static void
464repeats (mll_p_p, doing_repeat_p, repeat_start_p_p)
465
466struct MAINLL **mll_p_p; /* points to a BAR */
467int *doing_repeat_p; /* return YES or NO via this pointer to
468 * indicate whether now doing a repeat */
469struct 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
545static RATIONAL
546eff_meas_time(mll_p)
547
548struct 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
591static void
592midi_header(mfile, ntracks)
593
594int mfile; /* file descriptor to write to */
595int 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
666static void
667track_header(mfile)
668
669int 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
686static UINT32B
687write_midi_data(mfile, gs_p)
688
689int mfile; /* write MIDI data to this file descriptor */
690struct 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
819UINT32B
820write_delta(mfile)
821
822int 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
892static int
893xlate_note(note_p, fname, lineno, raw_notenum_p)
894
895struct NOTE *note_p;
896char *fname; /* input file */
897int lineno; /* input line number */
898int *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
982static void
983init_accidental_map(staffno)
984
985int 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
1077static void
1078init_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
1093static void
1094mark_accidental(pitch_offset, acc)
1095
1096int pitch_offset; /* 0 = C, 2 = D, 4 = E, 5 = F, 7 = G, 9 = A, 11 = B */
1097int 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
1116static UINT32B
1117midi_multirest(mfile, staff_p, staffno, vno, nummeas)
1118
1119int mfile; /* MIDI file */
1120struct STAFF *staff_p;
1121int staffno;
1122int vno; /* voice number */
1123int 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
1155static void
1156prepmidi_stuff(staff_p, vindex, all)
1157
1158struct STAFF *staff_p; /* do STUFF off of here */
1159int vindex; /* voice index, 0 or 1 for voice 1 or 2 */
1160int 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
1234static UINT32B
1235do_midi_stuff(timeval, mfile, all)
1236
1237RATIONAL timeval;
1238int mfile; /* MIDI file */
1239int 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
1291static UINT32B
1292midi_item(stuff_p, mfile, all)
1293
1294struct STUFF *stuff_p; /* which STUFF to process */
1295int mfile; /* the MIDI file */
1296int 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
1620static UINT32B
1621midihex(mfile, str, fname, lineno)
1622
1623int mfile;
1624char *str;
1625char *fname;
1626int 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
1674static UINT32B
1675wr_meta(mfile, evtype, str)
1676
1677int mfile; /* midi file */
1678int evtype; /* meta event type */
1679char *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
1701static UINT32B
1702all_midi(mfile)
1703
1704int 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
1848static void
1849midi_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
1938static void
1939adjust_notes(gs_p, staffno, v, mll_p)
1940
1941struct GRPSYL *gs_p; /* adjust groups in this list */
1942int staffno;
1943int v;
1944struct 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
2340static void
2341add_release(gs_p, release_adjust, mll_p)
2342
2343struct GRPSYL *gs_p;
2344RATIONAL release_adjust;
2345struct 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
2381static UINT32B
2382pedswitch(mfile, on)
2383
2384int mfile;
2385int 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
2403static void
2404midi_roll(gs_p, gslist_p_p)
2405
2406struct GRPSYL *gs_p;
2407struct 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
2501static RATIONAL
2502roll_time(grptime, nnotes)
2503
2504RATIONAL grptime; /* duration of rolled chord */
2505int 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
2534static void
2535do_mroll(gs_p, gslist_p_p, rolltime, notesbefore)
2536
2537struct GRPSYL *gs_p; /* group having roll */
2538struct GRPSYL **gslist_p_p; /* addr of groups_p list containing gs_p */
2539RATIONAL rolltime; /* duration per roll note */
2540int 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
2600static void
2601addrollgrp(gs_p, duration, start, end, link_p_p, prev_p)
2602
2603struct GRPSYL *gs_p;
2604RATIONAL duration;
2605int start; /* index into notelist, where to start copying notes */
2606int end; /* index into notelist, where to stop copying notes */
2607struct GRPSYL **link_p_p; /* where to link into list */
2608struct 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
2643static void
2644savemidiroll(gs_p, notesbefore, duration)
2645
2646struct GRPSYL *gs_p;
2647int notesbefore;
2648RATIONAL 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
2666static struct MIDIROLL *
2667getmidiroll(gs_p)
2668
2669struct 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
2696static void
2697fix_tempo(to_end)
2698
2699int 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
2740static void
2741free_midistuff(ms_p)
2742
2743struct 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
2769static void
2770adj4squeeze(timeval)
2771
2772RATIONAL 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
2796int
2797voice_used(staffno, vno)
2798
2799int staffno;
2800int vno;
2801
2802{
2803 return (Voice2track_map [staffno] [vno] != 0 ? YES : NO);
2804}