1 /* FluidSynth - A Software Synthesizer
3 * Copyright (C) 2003 Peter Hanappe and others.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1 of
8 * the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include "fluid_midi.h"
22 #include "fluid_sys.h"
23 #include "fluid_synth.h"
24 #include "fluid_settings.h"
27 static int fluid_midi_event_length(unsigned char event);
28 static int fluid_isasciistring(char *s);
29 static long fluid_getlength(unsigned char *s);
32 /* Read the entire contents of a file into memory, allocating enough memory
33 * for the file, and returning the length and the buffer.
34 * Note: This rewinds the file to the start before reading.
35 * Returns NULL if there was an error reading or allocating memory.
37 static char *fluid_file_read_full(fluid_file fp, size_t *length);
38 static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic);
39 #define READ_FULL_INITIAL_BUFLEN 1024
41 static fluid_track_t *new_fluid_track(int num);
42 static void delete_fluid_track(fluid_track_t *track);
43 static int fluid_track_set_name(fluid_track_t *track, char *name);
44 static int fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt);
45 static fluid_midi_event_t *fluid_track_next_event(fluid_track_t *track);
46 static int fluid_track_get_duration(fluid_track_t *track);
47 static int fluid_track_reset(fluid_track_t *track);
49 static int fluid_track_send_events(fluid_track_t *track,
51 fluid_player_t *player,
55 static int fluid_player_add_track(fluid_player_t *player, fluid_track_t *track);
56 static int fluid_player_callback(void *data, unsigned int msec);
57 static int fluid_player_reset(fluid_player_t *player);
58 static int fluid_player_load(fluid_player_t *player, fluid_playlist_item *item);
59 static void fluid_player_advancefile(fluid_player_t *player);
60 static void fluid_player_playlist_load(fluid_player_t *player, unsigned int msec);
62 static fluid_midi_file *new_fluid_midi_file(const char *buffer, size_t length);
63 static void delete_fluid_midi_file(fluid_midi_file *mf);
64 static int fluid_midi_file_read_mthd(fluid_midi_file *midifile);
65 static int fluid_midi_file_load_tracks(fluid_midi_file *midifile, fluid_player_t *player);
66 static int fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num);
67 static int fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track);
68 static int fluid_midi_file_read_varlen(fluid_midi_file *mf);
69 static int fluid_midi_file_getc(fluid_midi_file *mf);
70 static int fluid_midi_file_push(fluid_midi_file *mf, int c);
71 static int fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len);
72 static int fluid_midi_file_skip(fluid_midi_file *mf, int len);
73 static int fluid_midi_file_eof(fluid_midi_file *mf);
74 static int fluid_midi_file_read_tracklen(fluid_midi_file *mf);
75 static int fluid_midi_file_eot(fluid_midi_file *mf);
76 static int fluid_midi_file_get_division(fluid_midi_file *midifile);
78 #if 0 // disable file I/O with Ardour
79 /***************************************************************
85 * Return a new MIDI file handle for parsing an already-loaded MIDI file.
87 * @param buffer Pointer to full contents of MIDI file (borrows the pointer).
88 * The caller must not free buffer until after the fluid_midi_file is deleted.
89 * @param length Size of the buffer in bytes.
90 * @return New MIDI file handle or NULL on error.
93 new_fluid_midi_file(const char *buffer, size_t length)
97 mf = FLUID_NEW(fluid_midi_file);
101 FLUID_LOG(FLUID_ERR, "Out of memory");
105 FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file));
108 mf->running_status = -1;
111 mf->buf_len = length;
115 if(fluid_midi_file_read_mthd(mf) != FLUID_OK)
125 fluid_file_read_full(fluid_file fp, size_t *length)
131 /* Work out the length of the file in advance */
132 if(FLUID_FSEEK(fp, 0, SEEK_END) != 0)
134 FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
140 if(FLUID_FSEEK(fp, 0, SEEK_SET) != 0)
142 FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
146 FLUID_LOG(FLUID_DBG, "File load: Allocating %d bytes", buflen);
147 buffer = FLUID_MALLOC(buflen);
151 FLUID_LOG(FLUID_PANIC, "Out of memory");
155 n = FLUID_FREAD(buffer, 1, buflen, fp);
159 FLUID_LOG(FLUID_ERR, "Only read %d bytes; expected %d", n,
171 * Delete a MIDI file handle.
173 * @param mf MIDI file handle to close and free.
176 delete_fluid_midi_file(fluid_midi_file *mf)
178 fluid_return_if_fail(mf != NULL);
184 * Gets the next byte in a MIDI file, taking into account previous running status.
186 * returns -1 if EOF or read error
189 fluid_midi_file_getc(fluid_midi_file *mf)
200 if(mf->buf_pos >= mf->buf_len)
206 c = mf->buffer[mf->buf_pos++];
214 * Saves a byte to be returned the next time fluid_midi_file_getc() is called,
215 * when it is necessary according to running status.
218 fluid_midi_file_push(fluid_midi_file *mf, int c)
225 * fluid_midi_file_read
228 fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len)
230 int num = len < mf->buf_len - mf->buf_pos
231 ? len : mf->buf_len - mf->buf_pos;
243 /* Note: Read bytes, even if there aren't enough, but only increment
244 * trackpos if successful (emulates old behaviour of fluid_midi_file_read)
246 FLUID_MEMCPY(buf, mf->buffer + mf->buf_pos, num);
257 FLUID_LOG(FLUID_DBG, "Could not read the requested number of bytes");
261 return (num != len) ? FLUID_FAILED : FLUID_OK;
265 * fluid_midi_file_skip
268 fluid_midi_file_skip(fluid_midi_file *mf, int skip)
270 int new_pos = mf->buf_pos + skip;
272 /* Mimic the behaviour of fseek: Error to seek past the start of file, but
273 * OK to seek past end (this just puts it into the EOF state). */
276 FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
280 /* Clear the EOF flag, even if moved past the end of the file (this is
281 * consistent with the behaviour of fseek). */
283 mf->buf_pos = new_pos;
288 * fluid_midi_file_eof
290 int fluid_midi_file_eof(fluid_midi_file *mf)
292 /* Note: This does not simply test whether the file read pointer is past
293 * the end of the file. It mimics the behaviour of feof by actually
294 * testing the stateful EOF condition, which is set to TRUE if getc or
295 * fread have attempted to read past the end (but not if they have
296 * precisely reached the end), but reset to FALSE upon a successful seek.
302 * fluid_midi_file_read_mthd
305 fluid_midi_file_read_mthd(fluid_midi_file *mf)
309 if(fluid_midi_file_read(mf, mthd, sizeof(mthd)) != FLUID_OK)
314 if((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6)
318 "Doesn't look like a MIDI file: invalid MThd header");
323 mf->ntracks = (unsigned) mthd[11];
324 mf->ntracks += (unsigned int)(mthd[10]) << 16;
326 if((signed char)mthd[12] < 0)
329 mf->smpte_fps = -(signed char)mthd[12];
330 mf->smpte_res = (unsigned) mthd[13];
331 FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet");
337 mf->division = ((unsigned)mthd[12] << 8) | ((unsigned)mthd[13] & 0xff);
338 FLUID_LOG(FLUID_DBG, "Division=%d", mf->division);
345 * fluid_midi_file_load_tracks
348 fluid_midi_file_load_tracks(fluid_midi_file *mf, fluid_player_t *player)
352 for(i = 0; i < mf->ntracks; i++)
354 if(fluid_midi_file_read_track(mf, player, i) != FLUID_OK)
364 * fluid_isasciistring
367 fluid_isasciistring(char *s)
370 #define fluid_isascii(c) (((c) & ~0x7f) == 0)
373 int len = (int) FLUID_STRLEN(s);
375 for(i = 0; i < len; i++)
377 if(!fluid_isascii(s[i]))
392 fluid_getlength(unsigned char *s)
395 i = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24);
400 * fluid_midi_file_read_tracklen
403 fluid_midi_file_read_tracklen(fluid_midi_file *mf)
405 unsigned char length[5];
407 if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
412 mf->tracklen = fluid_getlength(length);
419 * fluid_midi_file_eot
422 fluid_midi_file_eot(fluid_midi_file *mf)
426 if(mf->trackpos > mf->tracklen)
428 printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen);
432 return mf->eot || (mf->trackpos >= mf->tracklen);
436 * fluid_midi_file_read_track
439 fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
441 fluid_track_t *track;
442 unsigned char id[5], length[5];
446 if(fluid_midi_file_read(mf, id, 4) != FLUID_OK)
457 if(fluid_isasciistring((char *) id) == 0)
460 "An non-ascii track header found, corrupt file");
464 else if(FLUID_STRCMP((char *) id, "MTrk") == 0)
469 if(fluid_midi_file_read_tracklen(mf) != FLUID_OK)
474 track = new_fluid_track(num);
478 FLUID_LOG(FLUID_ERR, "Out of memory");
482 while(!fluid_midi_file_eot(mf))
484 if(fluid_midi_file_read_event(mf, track) != FLUID_OK)
486 delete_fluid_track(track);
491 /* Skip remaining track data, if any */
492 if(mf->trackpos < mf->tracklen)
494 if(fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos) != FLUID_OK)
496 delete_fluid_track(track);
501 if(fluid_player_add_track(player, track) != FLUID_OK)
503 delete_fluid_track(track);
512 if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
517 skip = fluid_getlength(length);
519 /* fseek(mf->fp, skip, SEEK_CUR); */
520 if(fluid_midi_file_skip(mf, skip) != FLUID_OK)
527 if(fluid_midi_file_eof(mf))
529 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
537 * fluid_midi_file_read_varlen
540 fluid_midi_file_read_varlen(fluid_midi_file *mf)
550 FLUID_LOG(FLUID_ERR, "Invalid variable length number");
554 c = fluid_midi_file_getc(mf);
558 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
564 mf->varlen |= (int)(c & 0x7F);
578 * fluid_midi_file_read_event
581 fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track)
586 unsigned char *metadata = NULL;
587 unsigned char *dyn_buf = NULL;
588 unsigned char static_buf[256];
589 int nominator, denominator, clocks, notes;
590 fluid_midi_event_t *evt;
596 /* read the delta-time of the event */
597 if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
602 mf->dtime += mf->varlen;
604 /* read the status byte */
605 status = fluid_midi_file_getc(mf);
609 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
613 /* not a valid status byte: use the running status instead */
614 if((status & 0x80) == 0)
616 if((mf->running_status & 0x80) == 0)
618 FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
622 fluid_midi_file_push(mf, status);
623 status = mf->running_status;
626 /* check what message we have */
628 mf->running_status = status;
630 if(status == MIDI_SYSEX) /* system exclusif */
632 /* read the length of the message */
633 if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
640 FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
641 __LINE__, mf->varlen);
642 metadata = FLUID_MALLOC(mf->varlen + 1);
646 FLUID_LOG(FLUID_PANIC, "Out of memory");
650 /* read the data of the message */
651 if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
653 FLUID_FREE(metadata);
657 evt = new_fluid_midi_event();
661 FLUID_LOG(FLUID_ERR, "Out of memory");
662 FLUID_FREE(metadata);
666 evt->dtime = mf->dtime;
669 if(metadata[mf->varlen - 1] == MIDI_EOX)
674 /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */
675 fluid_midi_event_set_sysex(evt, metadata, size, TRUE);
676 fluid_track_add_event(track, evt);
683 else if(status == MIDI_META_EVENT) /* meta events */
686 int result = FLUID_OK;
688 /* get the type of the meta message */
689 type = fluid_midi_file_getc(mf);
693 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
697 /* get the length of the data part */
698 if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
705 metadata = &static_buf[0];
709 FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
710 __LINE__, mf->varlen);
711 dyn_buf = FLUID_MALLOC(mf->varlen + 1);
715 FLUID_LOG(FLUID_PANIC, "Out of memory");
725 if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
736 /* handle meta data */
741 metadata[mf->varlen] = 0;
744 case MIDI_TRACK_NAME:
745 metadata[mf->varlen] = 0;
746 fluid_track_set_name(track, (char *) metadata);
750 metadata[mf->varlen] = 0;
757 int size = mf->varlen + 1;
759 /* NULL terminate strings for safety */
760 metadata[size - 1] = '\0';
762 evt = new_fluid_midi_event();
766 FLUID_LOG(FLUID_ERR, "Out of memory");
767 result = FLUID_FAILED;
771 evt->dtime = mf->dtime;
773 tmp = FLUID_MALLOC(size);
777 FLUID_LOG(FLUID_PANIC, "Out of memory");
778 delete_fluid_midi_event(evt);
780 result = FLUID_FAILED;
784 FLUID_MEMCPY(tmp, metadata, size);
786 fluid_midi_event_set_sysex_LOCAL(evt, type, tmp, size, TRUE);
787 fluid_track_add_event(track, evt);
796 break; /* don't care much for text events */
801 FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
802 result = FLUID_FAILED;
807 evt = new_fluid_midi_event();
811 FLUID_LOG(FLUID_ERR, "Out of memory");
812 result = FLUID_FAILED;
816 evt->dtime = mf->dtime;
817 evt->type = MIDI_EOT;
818 fluid_track_add_event(track, evt);
826 "Invalid length for SetTempo meta event");
827 result = FLUID_FAILED;
831 tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
832 evt = new_fluid_midi_event();
836 FLUID_LOG(FLUID_ERR, "Out of memory");
837 result = FLUID_FAILED;
841 evt->dtime = mf->dtime;
842 evt->type = MIDI_SET_TEMPO;
846 fluid_track_add_event(track, evt);
850 case MIDI_SMPTE_OFFSET:
854 "Invalid length for SMPTE Offset meta event");
855 result = FLUID_FAILED;
859 break; /* we don't use smtp */
861 case MIDI_TIME_SIGNATURE:
865 "Invalid length for TimeSignature meta event");
866 result = FLUID_FAILED;
870 nominator = metadata[0];
871 denominator = pow(2.0, (double) metadata[1]);
872 clocks = metadata[2];
876 "signature=%d/%d, metronome=%d, 32nd-notes=%d",
877 nominator, denominator, clocks, notes);
881 case MIDI_KEY_SIGNATURE:
885 "Invalid length for KeySignature meta event");
886 result = FLUID_FAILED;
890 /* We don't care about key signatures anyway */
895 case MIDI_SEQUENCER_EVENT:
904 FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
911 else /* channel messages */
914 type = status & 0xf0;
915 channel = status & 0x0f;
917 /* all channel message have at least 1 byte of associated data */
918 if((param1 = fluid_midi_file_getc(mf)) < 0)
920 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
928 if((param2 = fluid_midi_file_getc(mf)) < 0)
930 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
937 if((param2 = fluid_midi_file_getc(mf)) < 0)
939 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
946 if((param2 = fluid_midi_file_getc(mf)) < 0)
948 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
955 if((param2 = fluid_midi_file_getc(mf)) < 0)
957 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
966 case CHANNEL_PRESSURE:
970 if((param2 = fluid_midi_file_getc(mf)) < 0)
972 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
976 param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
981 /* Can't possibly happen !? */
982 FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
986 evt = new_fluid_midi_event();
990 FLUID_LOG(FLUID_ERR, "Out of memory");
994 evt->dtime = mf->dtime;
996 evt->channel = channel;
997 evt->param1 = param1;
998 evt->param2 = param2;
999 fluid_track_add_event(track, evt);
1007 * fluid_midi_file_get_division
1010 fluid_midi_file_get_division(fluid_midi_file *midifile)
1012 return midifile->division;
1016 /******************************************************
1022 * Create a MIDI event structure.
1023 * @return New MIDI event structure or NULL when out of memory.
1025 fluid_midi_event_t *
1026 new_fluid_midi_event()
1028 fluid_midi_event_t *evt;
1029 evt = FLUID_NEW(fluid_midi_event_t);
1033 FLUID_LOG(FLUID_ERR, "Out of memory");
1043 evt->paramptr = NULL;
1048 * Delete MIDI event structure.
1049 * @param evt MIDI event structure
1052 delete_fluid_midi_event(fluid_midi_event_t *evt)
1054 fluid_midi_event_t *temp;
1055 fluid_return_if_fail(evt != NULL);
1061 /* Dynamic SYSEX event? - free (param2 indicates if dynamic) */
1062 if((evt->type == MIDI_SYSEX || (evt-> type == MIDI_TEXT) || (evt->type == MIDI_LYRIC)) &&
1063 evt->paramptr && evt->param2)
1065 FLUID_FREE(evt->paramptr);
1074 * Get the event type field of a MIDI event structure.
1075 * @param evt MIDI event structure
1076 * @return Event type field (MIDI status byte without channel)
1079 fluid_midi_event_get_type(fluid_midi_event_t *evt)
1085 * Set the event type field of a MIDI event structure.
1086 * @param evt MIDI event structure
1087 * @param type Event type field (MIDI status byte without channel)
1088 * @return Always returns #FLUID_OK
1091 fluid_midi_event_set_type(fluid_midi_event_t *evt, int type)
1098 * Get the channel field of a MIDI event structure.
1099 * @param evt MIDI event structure
1100 * @return Channel field
1103 fluid_midi_event_get_channel(fluid_midi_event_t *evt)
1105 return evt->channel;
1109 * Set the channel field of a MIDI event structure.
1110 * @param evt MIDI event structure
1111 * @param chan MIDI channel field
1112 * @return Always returns #FLUID_OK
1115 fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan)
1117 evt->channel = chan;
1122 * Get the key field of a MIDI event structure.
1123 * @param evt MIDI event structure
1124 * @return MIDI note number (0-127)
1127 fluid_midi_event_get_key(fluid_midi_event_t *evt)
1133 * Set the key field of a MIDI event structure.
1134 * @param evt MIDI event structure
1135 * @param v MIDI note number (0-127)
1136 * @return Always returns #FLUID_OK
1139 fluid_midi_event_set_key(fluid_midi_event_t *evt, int v)
1146 * Get the velocity field of a MIDI event structure.
1147 * @param evt MIDI event structure
1148 * @return MIDI velocity number (0-127)
1151 fluid_midi_event_get_velocity(fluid_midi_event_t *evt)
1157 * Set the velocity field of a MIDI event structure.
1158 * @param evt MIDI event structure
1159 * @param v MIDI velocity value
1160 * @return Always returns #FLUID_OK
1163 fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int v)
1170 * Get the control number of a MIDI event structure.
1171 * @param evt MIDI event structure
1172 * @return MIDI control number
1175 fluid_midi_event_get_control(fluid_midi_event_t *evt)
1181 * Set the control field of a MIDI event structure.
1182 * @param evt MIDI event structure
1183 * @param v MIDI control number
1184 * @return Always returns #FLUID_OK
1187 fluid_midi_event_set_control(fluid_midi_event_t *evt, int v)
1194 * Get the value field from a MIDI event structure.
1195 * @param evt MIDI event structure
1196 * @return Value field
1199 fluid_midi_event_get_value(fluid_midi_event_t *evt)
1205 * Set the value field of a MIDI event structure.
1206 * @param evt MIDI event structure
1207 * @param v Value to assign
1208 * @return Always returns #FLUID_OK
1211 fluid_midi_event_set_value(fluid_midi_event_t *evt, int v)
1218 * Get the program field of a MIDI event structure.
1219 * @param evt MIDI event structure
1220 * @return MIDI program number (0-127)
1223 fluid_midi_event_get_program(fluid_midi_event_t *evt)
1229 * Set the program field of a MIDI event structure.
1230 * @param evt MIDI event structure
1231 * @param val MIDI program number (0-127)
1232 * @return Always returns #FLUID_OK
1235 fluid_midi_event_set_program(fluid_midi_event_t *evt, int val)
1242 * Get the pitch field of a MIDI event structure.
1243 * @param evt MIDI event structure
1244 * @return Pitch value (14 bit value, 0-16383, 8192 is center)
1247 fluid_midi_event_get_pitch(fluid_midi_event_t *evt)
1253 * Set the pitch field of a MIDI event structure.
1254 * @param evt MIDI event structure
1255 * @param val Pitch value (14 bit value, 0-16383, 8192 is center)
1256 * @return Always returns FLUID_OK
1259 fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val)
1266 * Assign sysex data to a MIDI event structure.
1267 * @param evt MIDI event structure
1268 * @param data Pointer to SYSEX data
1269 * @param size Size of SYSEX data in bytes
1270 * @param dynamic TRUE if the SYSEX data has been dynamically allocated and
1271 * should be freed when the event is freed (only applies if event gets destroyed
1272 * with delete_fluid_midi_event())
1273 * @return Always returns #FLUID_OK
1275 * @note Unlike the other event assignment functions, this one sets evt->type.
1278 fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1280 fluid_midi_event_set_sysex_LOCAL(evt, MIDI_SYSEX, data, size, dynamic);
1285 * Assign text data to a MIDI event structure.
1286 * @param evt MIDI event structure
1287 * @param data Pointer to text data
1288 * @param size Size of text data in bytes
1289 * @param dynamic TRUE if the data has been dynamically allocated and
1290 * should be freed when the event is freed via delete_fluid_midi_event()
1291 * @return Always returns #FLUID_OK
1294 * @note Unlike the other event assignment functions, this one sets evt->type.
1297 fluid_midi_event_set_text(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1299 fluid_midi_event_set_sysex_LOCAL(evt, MIDI_TEXT, data, size, dynamic);
1304 * Assign lyric data to a MIDI event structure.
1305 * @param evt MIDI event structure
1306 * @param data Pointer to lyric data
1307 * @param size Size of lyric data in bytes
1308 * @param dynamic TRUE if the data has been dynamically allocated and
1309 * should be freed when the event is freed via delete_fluid_midi_event()
1310 * @return Always returns #FLUID_OK
1313 * @note Unlike the other event assignment functions, this one sets evt->type.
1316 fluid_midi_event_set_lyrics(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1318 fluid_midi_event_set_sysex_LOCAL(evt, MIDI_LYRIC, data, size, dynamic);
1322 static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic)
1325 evt->paramptr = data;
1327 evt->param2 = dynamic;
1330 /******************************************************
1334 #if 0 // disable fluid file player in Ardour
1339 new_fluid_track(int num)
1341 fluid_track_t *track;
1342 track = FLUID_NEW(fluid_track_t);
1351 track->first = NULL;
1359 * delete_fluid_track
1362 delete_fluid_track(fluid_track_t *track)
1364 fluid_return_if_fail(track != NULL);
1366 FLUID_FREE(track->name);
1367 delete_fluid_midi_event(track->first);
1372 * fluid_track_set_name
1375 fluid_track_set_name(fluid_track_t *track, char *name)
1379 if(track->name != NULL)
1381 FLUID_FREE(track->name);
1390 len = FLUID_STRLEN(name);
1391 track->name = FLUID_MALLOC(len + 1);
1393 if(track->name == NULL)
1395 FLUID_LOG(FLUID_ERR, "Out of memory");
1396 return FLUID_FAILED;
1399 FLUID_STRCPY(track->name, name);
1404 * fluid_track_get_duration
1407 fluid_track_get_duration(fluid_track_t *track)
1410 fluid_midi_event_t *evt = track->first;
1422 * fluid_track_add_event
1425 fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt)
1429 if(track->first == NULL)
1437 track->last->next = evt;
1445 * fluid_track_next_event
1447 fluid_midi_event_t *
1448 fluid_track_next_event(fluid_track_t *track)
1450 if(track->cur != NULL)
1452 track->cur = track->cur->next;
1462 fluid_track_reset(fluid_track_t *track)
1465 track->cur = track->first;
1470 * fluid_track_send_events
1473 fluid_track_send_events(fluid_track_t *track,
1474 fluid_synth_t *synth,
1475 fluid_player_t *player,
1478 int status = FLUID_OK;
1479 fluid_midi_event_t *event;
1480 int seeking = player->seek_ticks >= 0;
1484 ticks = player->seek_ticks; /* update target ticks */
1486 if(track->ticks > ticks)
1488 fluid_track_reset(track); /* reset track if seeking backwards */
1502 /* printf("track=%02d\tticks=%05u\ttrack=%05u\tdtime=%05u\tnext=%05u\n", */
1507 /* track->ticks + event->dtime); */
1509 if(track->ticks + event->dtime > ticks)
1514 track->ticks += event->dtime;
1516 if(!player || event->type == MIDI_EOT)
1519 else if(seeking && (event->type == NOTE_ON || event->type == NOTE_OFF))
1521 /* skip on/off messages */
1525 if(player->playback_callback)
1527 player->playback_callback(player->playback_userdata, event);
1531 if(event->type == MIDI_SET_TEMPO)
1533 fluid_player_set_midi_tempo(player, event->param1);
1536 fluid_track_next_event(track);
1543 /******************************************************
1548 fluid_player_handle_reset_synth(void *data, const char *name, int value)
1550 fluid_player_t *player = data;
1551 fluid_return_if_fail(player != NULL);
1553 player->reset_synth_between_songs = value;
1557 * Create a new MIDI player.
1558 * @param synth Fluid synthesizer instance to create player for
1559 * @return New MIDI player instance or NULL on error (out of memory)
1562 new_fluid_player(fluid_synth_t *synth)
1565 fluid_player_t *player;
1566 player = FLUID_NEW(fluid_player_t);
1570 FLUID_LOG(FLUID_ERR, "Out of memory");
1574 player->status = FLUID_PLAYER_READY;
1576 player->ntracks = 0;
1578 for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1580 player->track[i] = NULL;
1583 player->synth = synth;
1584 player->system_timer = NULL;
1585 player->sample_timer = NULL;
1586 player->playlist = NULL;
1587 player->currentfile = NULL;
1588 player->division = 0;
1589 player->send_program_change = 1;
1590 player->miditempo = 480000;
1591 player->deltatime = 4.0;
1592 player->cur_msec = 0;
1593 player->cur_ticks = 0;
1594 player->seek_ticks = -1;
1595 fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth);
1596 player->use_system_timer = fluid_settings_str_equal(synth->settings,
1597 "player.timing-source", "system");
1599 fluid_settings_getint(synth->settings, "player.reset-synth", &i);
1600 fluid_player_handle_reset_synth(player, NULL, i);
1602 fluid_settings_callback_int(synth->settings, "player.reset-synth",
1603 fluid_player_handle_reset_synth, player);
1609 * Delete a MIDI player instance.
1610 * @param player MIDI player instance
1613 delete_fluid_player(fluid_player_t *player)
1616 fluid_playlist_item *pi;
1618 fluid_return_if_fail(player != NULL);
1620 fluid_player_stop(player);
1621 fluid_player_reset(player);
1623 while(player->playlist != NULL)
1625 q = player->playlist->next;
1626 pi = (fluid_playlist_item *) player->playlist->data;
1627 FLUID_FREE(pi->filename);
1628 FLUID_FREE(pi->buffer);
1630 delete1_fluid_list(player->playlist);
1631 player->playlist = q;
1638 * Registers settings related to the MIDI player
1641 fluid_player_settings(fluid_settings_t *settings)
1643 /* player.timing-source can be either "system" (use system timer)
1644 or "sample" (use timer based on number of written samples) */
1645 fluid_settings_register_str(settings, "player.timing-source", "sample", 0);
1646 fluid_settings_add_option(settings, "player.timing-source", "sample");
1647 fluid_settings_add_option(settings, "player.timing-source", "system");
1649 /* Selects whether the player should reset the synth between songs, or not. */
1650 fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1, FLUID_HINT_TOGGLED);
1655 fluid_player_reset(fluid_player_t *player)
1659 for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1661 if(player->track[i] != NULL)
1663 delete_fluid_track(player->track[i]);
1664 player->track[i] = NULL;
1668 /* player->current_file = NULL; */
1669 /* player->status = FLUID_PLAYER_READY; */
1670 /* player->loop = 1; */
1671 player->ntracks = 0;
1672 player->division = 0;
1673 player->send_program_change = 1;
1674 player->miditempo = 480000;
1675 player->deltatime = 4.0;
1680 * fluid_player_add_track
1683 fluid_player_add_track(fluid_player_t *player, fluid_track_t *track)
1685 if(player->ntracks < MAX_NUMBER_OF_TRACKS)
1687 player->track[player->ntracks++] = track;
1692 return FLUID_FAILED;
1697 * Change the MIDI callback function. This is usually set to
1698 * fluid_synth_handle_midi_event, but can optionally be changed
1699 * to a user-defined function instead, for intercepting all MIDI
1700 * messages sent to the synth. You can also use a midi router as
1701 * the callback function to modify the MIDI messages before sending
1702 * them to the synth.
1703 * @param player MIDI player instance
1704 * @param handler Pointer to callback function
1705 * @param handler_data Parameter sent to the callback function
1710 fluid_player_set_playback_callback(fluid_player_t *player,
1711 handle_midi_event_func_t handler, void *handler_data)
1713 player->playback_callback = handler;
1714 player->playback_userdata = handler_data;
1719 * Add a MIDI file to a player queue.
1720 * @param player MIDI player instance
1721 * @param midifile File name of the MIDI file to add
1722 * @return #FLUID_OK or #FLUID_FAILED
1725 fluid_player_add(fluid_player_t *player, const char *midifile)
1727 fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1728 char *f = FLUID_STRDUP(midifile);
1734 FLUID_LOG(FLUID_PANIC, "Out of memory");
1735 return FLUID_FAILED;
1741 player->playlist = fluid_list_append(player->playlist, pi);
1746 * Add a MIDI file to a player queue, from a buffer in memory.
1747 * @param player MIDI player instance
1748 * @param buffer Pointer to memory containing the bytes of a complete MIDI
1749 * file. The data is copied, so the caller may free or modify it immediately
1750 * without affecting the playlist.
1751 * @param len Length of the buffer, in bytes.
1752 * @return #FLUID_OK or #FLUID_FAILED
1755 fluid_player_add_mem(fluid_player_t *player, const void *buffer, size_t len)
1757 /* Take a copy of the buffer, so the caller can free immediately. */
1758 fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1759 void *buf_copy = FLUID_MALLOC(len);
1761 if(!pi || !buf_copy)
1764 FLUID_FREE(buf_copy);
1765 FLUID_LOG(FLUID_PANIC, "Out of memory");
1766 return FLUID_FAILED;
1769 FLUID_MEMCPY(buf_copy, buffer, len);
1770 pi->filename = NULL;
1771 pi->buffer = buf_copy;
1772 pi->buffer_len = len;
1773 player->playlist = fluid_list_append(player->playlist, pi);
1781 fluid_player_load(fluid_player_t *player, fluid_playlist_item *item)
1783 fluid_midi_file *midifile;
1785 size_t buffer_length;
1788 if(item->filename != NULL)
1791 /* This file is specified by filename; load the file from disk */
1792 FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__,
1794 /* Read the entire contents of the file into the buffer */
1795 fp = FLUID_FOPEN(item->filename, "rb");
1799 FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
1800 return FLUID_FAILED;
1803 buffer = fluid_file_read_full(fp, &buffer_length);
1808 return FLUID_FAILED;
1816 /* This file is specified by a pre-loaded buffer; load from memory */
1817 FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile from memory (%p)",
1818 __FILE__, __LINE__, item->buffer);
1819 buffer = (char *) item->buffer;
1820 buffer_length = item->buffer_len;
1821 /* Do not free the buffer (it is owned by the playlist) */
1825 midifile = new_fluid_midi_file(buffer, buffer_length);
1827 if(midifile == NULL)
1834 return FLUID_FAILED;
1837 player->division = fluid_midi_file_get_division(midifile);
1838 fluid_player_set_midi_tempo(player, player->miditempo); // Update deltatime
1839 /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */
1841 if(fluid_midi_file_load_tracks(midifile, player) != FLUID_OK)
1848 delete_fluid_midi_file(midifile);
1849 return FLUID_FAILED;
1852 delete_fluid_midi_file(midifile);
1863 fluid_player_advancefile(fluid_player_t *player)
1865 if(player->playlist == NULL)
1867 return; /* No files to play */
1870 if(player->currentfile != NULL)
1872 player->currentfile = fluid_list_next(player->currentfile);
1875 if(player->currentfile == NULL)
1877 if(player->loop == 0)
1879 return; /* We're done playing */
1882 if(player->loop > 0)
1887 player->currentfile = player->playlist;
1892 fluid_player_playlist_load(fluid_player_t *player, unsigned int msec)
1894 fluid_playlist_item *current_playitem;
1899 fluid_player_advancefile(player);
1901 if(player->currentfile == NULL)
1903 /* Failed to find next song, probably since we're finished */
1904 player->status = FLUID_PLAYER_DONE;
1908 fluid_player_reset(player);
1909 current_playitem = (fluid_playlist_item *) player->currentfile->data;
1911 while(fluid_player_load(player, current_playitem) != FLUID_OK);
1913 /* Successfully loaded midi file */
1915 player->begin_msec = msec;
1916 player->start_msec = msec;
1917 player->start_ticks = 0;
1918 player->cur_ticks = 0;
1920 if(player->reset_synth_between_songs)
1922 fluid_synth_system_reset(player->synth);
1925 for(i = 0; i < player->ntracks; i++)
1927 if(player->track[i] != NULL)
1929 fluid_track_reset(player->track[i]);
1935 * fluid_player_callback
1938 fluid_player_callback(void *data, unsigned int msec)
1942 int status = FLUID_PLAYER_DONE;
1943 fluid_player_t *player;
1944 fluid_synth_t *synth;
1945 player = (fluid_player_t *) data;
1946 synth = player->synth;
1948 loadnextfile = player->currentfile == NULL ? 1 : 0;
1955 fluid_player_playlist_load(player, msec);
1957 if(player->currentfile == NULL)
1963 player->cur_msec = msec;
1964 player->cur_ticks = (player->start_ticks
1965 + (int)((double)(player->cur_msec - player->start_msec)
1966 / player->deltatime + 0.5)); /* 0.5 to average overall error when casting */
1968 if(player->seek_ticks >= 0)
1970 fluid_synth_all_sounds_off(synth, -1); /* avoid hanging notes */
1973 for(i = 0; i < player->ntracks; i++)
1975 if(!fluid_track_eot(player->track[i]))
1977 status = FLUID_PLAYER_PLAYING;
1979 if(fluid_track_send_events(player->track[i], synth, player,
1980 player->cur_ticks) != FLUID_OK)
1987 if(player->seek_ticks >= 0)
1989 player->start_ticks = player->seek_ticks; /* tick position of last tempo value (which is now) */
1990 player->cur_ticks = player->seek_ticks;
1991 player->begin_msec = msec; /* only used to calculate the duration of playing */
1992 player->start_msec = msec; /* should be the (synth)-time of the last tempo change */
1993 player->seek_ticks = -1; /* clear seek_ticks */
1996 if(status == FLUID_PLAYER_DONE)
1998 FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
1999 __LINE__, (msec - player->begin_msec) / 1000.0);
2003 while(loadnextfile);
2005 player->status = status;
2011 * Activates play mode for a MIDI player if not already playing.
2012 * @param player MIDI player instance
2013 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2016 fluid_player_play(fluid_player_t *player)
2018 if(player->status == FLUID_PLAYER_PLAYING)
2023 if(player->playlist == NULL)
2028 player->status = FLUID_PLAYER_PLAYING;
2030 if(player->use_system_timer)
2032 player->system_timer = new_fluid_timer((int) player->deltatime,
2033 fluid_player_callback, (void *) player, TRUE, FALSE, TRUE);
2035 if(player->system_timer == NULL)
2037 return FLUID_FAILED;
2042 player->sample_timer = new_fluid_sample_timer(player->synth,
2043 fluid_player_callback, (void *) player);
2045 if(player->sample_timer == NULL)
2047 return FLUID_FAILED;
2055 * Stops a MIDI player.
2056 * @param player MIDI player instance
2057 * @return Always returns #FLUID_OK
2060 fluid_player_stop(fluid_player_t *player)
2062 if(player->system_timer != NULL)
2064 delete_fluid_timer(player->system_timer);
2067 if(player->sample_timer != NULL)
2069 delete_fluid_sample_timer(player->synth, player->sample_timer);
2072 player->status = FLUID_PLAYER_DONE;
2073 player->sample_timer = NULL;
2074 player->system_timer = NULL;
2079 * Get MIDI player status.
2080 * @param player MIDI player instance
2081 * @return Player status (#fluid_player_status)
2085 fluid_player_get_status(fluid_player_t *player)
2087 return player->status;
2091 * Seek in the currently playing file.
2092 * @param player MIDI player instance
2093 * @param ticks the position to seek to in the current file
2094 * @return #FLUID_FAILED if ticks is negative or after the latest tick of the file,
2095 * #FLUID_OK otherwise
2098 * The actual seek is performed during the player_callback.
2100 int fluid_player_seek(fluid_player_t *player, int ticks)
2102 if(ticks < 0 || ticks > fluid_player_get_total_ticks(player))
2104 return FLUID_FAILED;
2107 player->seek_ticks = ticks;
2113 * Enable looping of a MIDI player
2114 * @param player MIDI player instance
2115 * @param loop Times left to loop the playlist. -1 means loop infinitely.
2116 * @return Always returns #FLUID_OK
2119 * For example, if you want to loop the playlist twice, set loop to 2
2120 * and call this function before you start the player.
2122 int fluid_player_set_loop(fluid_player_t *player, int loop)
2124 player->loop = loop;
2129 * Set the tempo of a MIDI player.
2130 * @param player MIDI player instance
2131 * @param tempo Tempo to set playback speed to (in microseconds per quarter note, as per MIDI file spec)
2132 * @return Always returns #FLUID_OK
2134 int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo)
2136 player->miditempo = tempo;
2137 player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
2138 player->start_msec = player->cur_msec;
2139 player->start_ticks = player->cur_ticks;
2141 FLUID_LOG(FLUID_DBG,
2142 "tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
2143 tempo, player->deltatime, player->cur_msec, player->cur_ticks);
2149 * Set the tempo of a MIDI player in beats per minute.
2150 * @param player MIDI player instance
2151 * @param bpm Tempo in beats per minute
2152 * @return Always returns #FLUID_OK
2154 int fluid_player_set_bpm(fluid_player_t *player, int bpm)
2156 return fluid_player_set_midi_tempo(player, 60000000L / bpm);
2160 * Wait for a MIDI player to terminate (when done playing).
2161 * @param player MIDI player instance
2162 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2165 fluid_player_join(fluid_player_t *player)
2167 if(player->system_timer)
2169 return fluid_timer_join(player->system_timer);
2171 else if(player->sample_timer)
2173 /* Busy-wait loop, since there's no thread to wait for... */
2174 while(player->status != FLUID_PLAYER_DONE)
2184 * Get the number of tempo ticks passed.
2185 * @param player MIDI player instance
2186 * @return The number of tempo ticks passed
2189 int fluid_player_get_current_tick(fluid_player_t *player)
2191 return player->cur_ticks;
2195 * Looks through all available MIDI tracks and gets the absolute tick of the very last event to play.
2196 * @param player MIDI player instance
2197 * @return Total tick count of the sequence
2200 int fluid_player_get_total_ticks(fluid_player_t *player)
2205 for(i = 0; i < player->ntracks; i++)
2207 if(player->track[i] != NULL)
2209 int ticks = fluid_track_get_duration(player->track[i]);
2211 if(ticks > maxTicks)
2222 * Get the tempo of a MIDI player in beats per minute.
2223 * @param player MIDI player instance
2224 * @return MIDI player tempo in BPM
2227 int fluid_player_get_bpm(fluid_player_t *player)
2229 return 60000000L / player->miditempo;
2233 * Get the tempo of a MIDI player.
2234 * @param player MIDI player instance
2235 * @return Tempo of the MIDI player (in microseconds per quarter note, as per MIDI file spec)
2238 int fluid_player_get_midi_tempo(fluid_player_t *player)
2240 return player->miditempo;
2243 /************************************************************************
2249 * new_fluid_midi_parser
2251 fluid_midi_parser_t *
2252 new_fluid_midi_parser()
2254 fluid_midi_parser_t *parser;
2255 parser = FLUID_NEW(fluid_midi_parser_t);
2259 FLUID_LOG(FLUID_ERR, "Out of memory");
2263 parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */
2268 * delete_fluid_midi_parser
2271 delete_fluid_midi_parser(fluid_midi_parser_t *parser)
2273 fluid_return_if_fail(parser != NULL);
2279 * Parse a MIDI stream one character at a time.
2280 * @param parser Parser instance
2281 * @param c Next character in MIDI stream
2282 * @return A parsed MIDI event or NULL if none. Event is internal and should
2283 * not be modified or freed and is only valid until next call to this function.
2284 * @internal Do not expose this function to the public API. It would allow downstream
2285 * apps to abuse fluidsynth as midi parser, e.g. feeding it with rawmidi and pull out
2286 * the needed midi information using the getter functions of fluid_midi_event_t.
2287 * This parser however is incomplete as it e.g. only provides a limited buffer to
2288 * store and process SYSEX data (i.e. doesnt allow arbitrary lengths)
2290 fluid_midi_event_t *
2291 fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c)
2293 fluid_midi_event_t *event;
2295 /* Real-time messages (0xF8-0xFF) can occur anywhere, even in the middle
2296 * of another message. */
2299 if(c == MIDI_SYSTEM_RESET)
2301 parser->event.type = c;
2302 parser->status = 0; /* clear the status */
2303 return &parser->event;
2309 /* Status byte? - If previous message not yet complete, it is discarded (re-sync). */
2312 /* Any status byte terminates SYSEX messages (not just 0xF7) */
2313 if(parser->status == MIDI_SYSEX && parser->nr_bytes > 0)
2315 event = &parser->event;
2316 fluid_midi_event_set_sysex(event, parser->data, parser->nr_bytes,
2324 if(c < 0xF0) /* Voice category message? */
2326 parser->channel = c & 0x0F;
2327 parser->status = c & 0xF0;
2329 /* The event consumes x bytes of data... (subtract 1 for the status byte) */
2330 parser->nr_bytes_total = fluid_midi_event_length(parser->status)
2333 parser->nr_bytes = 0; /* 0 bytes read so far */
2335 else if(c == MIDI_SYSEX)
2337 parser->status = MIDI_SYSEX;
2338 parser->nr_bytes = 0;
2342 parser->status = 0; /* Discard other system messages (0xF1-0xF7) */
2345 return event; /* Return SYSEX event or NULL */
2348 /* Data/parameter byte */
2350 /* Discard data bytes for events we don't care about */
2351 if(parser->status == 0)
2356 /* Max data size exceeded? (SYSEX messages only really) */
2357 if(parser->nr_bytes == FLUID_MIDI_PARSER_MAX_DATA_SIZE)
2359 parser->status = 0; /* Discard the rest of the message */
2363 /* Store next byte */
2364 parser->data[parser->nr_bytes++] = c;
2366 /* Do we still need more data to get this event complete? */
2367 if(parser->status == MIDI_SYSEX || parser->nr_bytes < parser->nr_bytes_total)
2372 /* Event is complete, return it.
2373 * Running status byte MIDI feature is also handled here. */
2374 parser->event.type = parser->status;
2375 parser->event.channel = parser->channel;
2376 parser->nr_bytes = 0; /* Reset data size, in case there are additional running status messages */
2378 switch(parser->status)
2383 case CONTROL_CHANGE:
2384 case PROGRAM_CHANGE:
2385 case CHANNEL_PRESSURE:
2386 parser->event.param1 = parser->data[0]; /* For example key number */
2387 parser->event.param2 = parser->data[1]; /* For example velocity */
2391 /* Pitch-bend is transmitted with 14-bit precision. */
2392 parser->event.param1 = (parser->data[1] << 7) | parser->data[0];
2395 default: /* Unlikely */
2399 return &parser->event;
2403 * Returns the length of a MIDI message. */
2405 fluid_midi_event_length(unsigned char event)
2407 switch(event & 0xF0)
2412 case CONTROL_CHANGE:
2416 case PROGRAM_CHANGE:
2417 case CHANNEL_PRESSURE:
2423 case MIDI_TIME_CODE:
2424 case MIDI_SONG_SELECT:
2429 case MIDI_TUNE_REQUEST:
2432 case MIDI_SONG_POSITION: