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 static void fluid_midi_event_get_sysex_LOCAL(fluid_midi_event_t *evt, void **data, int *size);
40 #define READ_FULL_INITIAL_BUFLEN 1024
42 static fluid_track_t *new_fluid_track(int num);
43 static void delete_fluid_track(fluid_track_t *track);
44 static int fluid_track_set_name(fluid_track_t *track, char *name);
45 static int fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt);
46 static fluid_midi_event_t *fluid_track_next_event(fluid_track_t *track);
47 static int fluid_track_get_duration(fluid_track_t *track);
48 static int fluid_track_reset(fluid_track_t *track);
50 static int fluid_track_send_events(fluid_track_t *track,
52 fluid_player_t *player,
56 static int fluid_player_add_track(fluid_player_t *player, fluid_track_t *track);
57 static int fluid_player_callback(void *data, unsigned int msec);
58 static int fluid_player_reset(fluid_player_t *player);
59 static int fluid_player_load(fluid_player_t *player, fluid_playlist_item *item);
60 static void fluid_player_advancefile(fluid_player_t *player);
61 static void fluid_player_playlist_load(fluid_player_t *player, unsigned int msec);
63 static fluid_midi_file *new_fluid_midi_file(const char *buffer, size_t length);
64 static void delete_fluid_midi_file(fluid_midi_file *mf);
65 static int fluid_midi_file_read_mthd(fluid_midi_file *midifile);
66 static int fluid_midi_file_load_tracks(fluid_midi_file *midifile, fluid_player_t *player);
67 static int fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num);
68 static int fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track);
69 static int fluid_midi_file_read_varlen(fluid_midi_file *mf);
70 static int fluid_midi_file_getc(fluid_midi_file *mf);
71 static int fluid_midi_file_push(fluid_midi_file *mf, int c);
72 static int fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len);
73 static int fluid_midi_file_skip(fluid_midi_file *mf, int len);
74 static int fluid_midi_file_eof(fluid_midi_file *mf);
75 static int fluid_midi_file_read_tracklen(fluid_midi_file *mf);
76 static int fluid_midi_file_eot(fluid_midi_file *mf);
77 static int fluid_midi_file_get_division(fluid_midi_file *midifile);
79 #if 0 // disable file I/O with Ardour
80 /***************************************************************
86 * Check if a file is a MIDI file.
87 * @param filename Path to the file to check
88 * @return TRUE if it could be a MIDI file, FALSE otherwise
90 * The current implementation only checks for the "MThd" header in the file.
91 * It is useful only to distinguish between SoundFont and MIDI files.
93 int fluid_is_midifile(const char *filename)
95 FILE *fp = FLUID_FOPEN(filename, "rb");
106 if(FLUID_FREAD(&id, sizeof(id), 1, fp) != 1)
111 retcode = (id == FLUID_FOURCC('M', 'T', 'h', 'd'));
121 * Return a new MIDI file handle for parsing an already-loaded MIDI file.
123 * @param buffer Pointer to full contents of MIDI file (borrows the pointer).
124 * The caller must not free buffer until after the fluid_midi_file is deleted.
125 * @param length Size of the buffer in bytes.
126 * @return New MIDI file handle or NULL on error.
129 new_fluid_midi_file(const char *buffer, size_t length)
133 mf = FLUID_NEW(fluid_midi_file);
137 FLUID_LOG(FLUID_ERR, "Out of memory");
141 FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file));
144 mf->running_status = -1;
147 mf->buf_len = length;
151 if(fluid_midi_file_read_mthd(mf) != FLUID_OK)
161 fluid_file_read_full(fluid_file fp, size_t *length)
167 /* Work out the length of the file in advance */
168 if(FLUID_FSEEK(fp, 0, SEEK_END) != 0)
170 FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
176 if(FLUID_FSEEK(fp, 0, SEEK_SET) != 0)
178 FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
182 FLUID_LOG(FLUID_DBG, "File load: Allocating %d bytes", buflen);
183 buffer = FLUID_MALLOC(buflen);
187 FLUID_LOG(FLUID_PANIC, "Out of memory");
191 n = FLUID_FREAD(buffer, 1, buflen, fp);
195 FLUID_LOG(FLUID_ERR, "Only read %d bytes; expected %d", n,
207 * Delete a MIDI file handle.
209 * @param mf MIDI file handle to close and free.
212 delete_fluid_midi_file(fluid_midi_file *mf)
214 fluid_return_if_fail(mf != NULL);
220 * Gets the next byte in a MIDI file, taking into account previous running status.
222 * returns -1 if EOF or read error
225 fluid_midi_file_getc(fluid_midi_file *mf)
236 if(mf->buf_pos >= mf->buf_len)
242 c = mf->buffer[mf->buf_pos++];
250 * Saves a byte to be returned the next time fluid_midi_file_getc() is called,
251 * when it is necessary according to running status.
254 fluid_midi_file_push(fluid_midi_file *mf, int c)
261 * fluid_midi_file_read
264 fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len)
266 int num = len < mf->buf_len - mf->buf_pos
267 ? len : mf->buf_len - mf->buf_pos;
279 /* Note: Read bytes, even if there aren't enough, but only increment
280 * trackpos if successful (emulates old behaviour of fluid_midi_file_read)
282 FLUID_MEMCPY(buf, mf->buffer + mf->buf_pos, num);
293 FLUID_LOG(FLUID_DBG, "Could not read the requested number of bytes");
297 return (num != len) ? FLUID_FAILED : FLUID_OK;
301 * fluid_midi_file_skip
304 fluid_midi_file_skip(fluid_midi_file *mf, int skip)
306 int new_pos = mf->buf_pos + skip;
308 /* Mimic the behaviour of fseek: Error to seek past the start of file, but
309 * OK to seek past end (this just puts it into the EOF state). */
312 FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
316 /* Clear the EOF flag, even if moved past the end of the file (this is
317 * consistent with the behaviour of fseek). */
319 mf->buf_pos = new_pos;
324 * fluid_midi_file_eof
326 int fluid_midi_file_eof(fluid_midi_file *mf)
328 /* Note: This does not simply test whether the file read pointer is past
329 * the end of the file. It mimics the behaviour of feof by actually
330 * testing the stateful EOF condition, which is set to TRUE if getc or
331 * fread have attempted to read past the end (but not if they have
332 * precisely reached the end), but reset to FALSE upon a successful seek.
338 * fluid_midi_file_read_mthd
341 fluid_midi_file_read_mthd(fluid_midi_file *mf)
345 if(fluid_midi_file_read(mf, mthd, sizeof(mthd)) != FLUID_OK)
350 if((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6)
354 "Doesn't look like a MIDI file: invalid MThd header");
359 mf->ntracks = (unsigned) mthd[11];
360 mf->ntracks += (unsigned int)(mthd[10]) << 16;
362 if((signed char)mthd[12] < 0)
365 mf->smpte_fps = -(signed char)mthd[12];
366 mf->smpte_res = (unsigned) mthd[13];
367 FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet");
373 mf->division = ((unsigned)mthd[12] << 8) | ((unsigned)mthd[13] & 0xff);
374 FLUID_LOG(FLUID_DBG, "Division=%d", mf->division);
381 * fluid_midi_file_load_tracks
384 fluid_midi_file_load_tracks(fluid_midi_file *mf, fluid_player_t *player)
388 for(i = 0; i < mf->ntracks; i++)
390 if(fluid_midi_file_read_track(mf, player, i) != FLUID_OK)
400 * fluid_isasciistring
403 fluid_isasciistring(char *s)
406 #define fluid_isascii(c) (((c) & ~0x7f) == 0)
409 int len = (int) FLUID_STRLEN(s);
411 for(i = 0; i < len; i++)
413 if(!fluid_isascii(s[i]))
428 fluid_getlength(unsigned char *s)
431 i = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24);
436 * fluid_midi_file_read_tracklen
439 fluid_midi_file_read_tracklen(fluid_midi_file *mf)
441 unsigned char length[5];
443 if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
448 mf->tracklen = fluid_getlength(length);
455 * fluid_midi_file_eot
458 fluid_midi_file_eot(fluid_midi_file *mf)
462 if(mf->trackpos > mf->tracklen)
464 printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen);
468 return mf->eot || (mf->trackpos >= mf->tracklen);
472 * fluid_midi_file_read_track
475 fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
477 fluid_track_t *track;
478 unsigned char id[5], length[5];
482 if(fluid_midi_file_read(mf, id, 4) != FLUID_OK)
493 if(fluid_isasciistring((char *) id) == 0)
496 "An non-ascii track header found, corrupt file");
500 else if(FLUID_STRCMP((char *) id, "MTrk") == 0)
505 if(fluid_midi_file_read_tracklen(mf) != FLUID_OK)
510 track = new_fluid_track(num);
514 FLUID_LOG(FLUID_ERR, "Out of memory");
518 while(!fluid_midi_file_eot(mf))
520 if(fluid_midi_file_read_event(mf, track) != FLUID_OK)
522 delete_fluid_track(track);
527 /* Skip remaining track data, if any */
528 if(mf->trackpos < mf->tracklen)
530 if(fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos) != FLUID_OK)
532 delete_fluid_track(track);
537 if(fluid_player_add_track(player, track) != FLUID_OK)
539 delete_fluid_track(track);
548 if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
553 skip = fluid_getlength(length);
555 /* fseek(mf->fp, skip, SEEK_CUR); */
556 if(fluid_midi_file_skip(mf, skip) != FLUID_OK)
563 if(fluid_midi_file_eof(mf))
565 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
573 * fluid_midi_file_read_varlen
576 fluid_midi_file_read_varlen(fluid_midi_file *mf)
586 FLUID_LOG(FLUID_ERR, "Invalid variable length number");
590 c = fluid_midi_file_getc(mf);
594 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
600 mf->varlen |= (int)(c & 0x7F);
614 * fluid_midi_file_read_event
617 fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track)
622 unsigned char *metadata = NULL;
623 unsigned char *dyn_buf = NULL;
624 unsigned char static_buf[256];
625 int nominator, denominator, clocks, notes;
626 fluid_midi_event_t *evt;
632 /* read the delta-time of the event */
633 if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
638 mf->dtime += mf->varlen;
640 /* read the status byte */
641 status = fluid_midi_file_getc(mf);
645 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
649 /* not a valid status byte: use the running status instead */
650 if((status & 0x80) == 0)
652 if((mf->running_status & 0x80) == 0)
654 FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
658 fluid_midi_file_push(mf, status);
659 status = mf->running_status;
662 /* check what message we have */
664 mf->running_status = status;
666 if(status == MIDI_SYSEX) /* system exclusif */
668 /* read the length of the message */
669 if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
676 FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
677 __LINE__, mf->varlen);
678 metadata = FLUID_MALLOC(mf->varlen + 1);
682 FLUID_LOG(FLUID_PANIC, "Out of memory");
686 /* read the data of the message */
687 if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
689 FLUID_FREE(metadata);
693 evt = new_fluid_midi_event();
697 FLUID_LOG(FLUID_ERR, "Out of memory");
698 FLUID_FREE(metadata);
702 evt->dtime = mf->dtime;
705 if(metadata[mf->varlen - 1] == MIDI_EOX)
710 /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */
711 fluid_midi_event_set_sysex(evt, metadata, size, TRUE);
712 fluid_track_add_event(track, evt);
719 else if(status == MIDI_META_EVENT) /* meta events */
722 int result = FLUID_OK;
724 /* get the type of the meta message */
725 type = fluid_midi_file_getc(mf);
729 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
733 /* get the length of the data part */
734 if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
741 metadata = &static_buf[0];
745 FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
746 __LINE__, mf->varlen);
747 dyn_buf = FLUID_MALLOC(mf->varlen + 1);
751 FLUID_LOG(FLUID_PANIC, "Out of memory");
761 if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
772 /* handle meta data */
777 metadata[mf->varlen] = 0;
780 case MIDI_TRACK_NAME:
781 metadata[mf->varlen] = 0;
782 fluid_track_set_name(track, (char *) metadata);
786 metadata[mf->varlen] = 0;
793 int size = mf->varlen + 1;
795 /* NULL terminate strings for safety */
796 metadata[size - 1] = '\0';
798 evt = new_fluid_midi_event();
802 FLUID_LOG(FLUID_ERR, "Out of memory");
803 result = FLUID_FAILED;
807 evt->dtime = mf->dtime;
809 tmp = FLUID_MALLOC(size);
813 FLUID_LOG(FLUID_PANIC, "Out of memory");
814 delete_fluid_midi_event(evt);
816 result = FLUID_FAILED;
820 FLUID_MEMCPY(tmp, metadata, size);
822 fluid_midi_event_set_sysex_LOCAL(evt, type, tmp, size, TRUE);
823 fluid_track_add_event(track, evt);
832 break; /* don't care much for text events */
837 FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
838 result = FLUID_FAILED;
843 evt = new_fluid_midi_event();
847 FLUID_LOG(FLUID_ERR, "Out of memory");
848 result = FLUID_FAILED;
852 evt->dtime = mf->dtime;
853 evt->type = MIDI_EOT;
854 fluid_track_add_event(track, evt);
862 "Invalid length for SetTempo meta event");
863 result = FLUID_FAILED;
867 tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
868 evt = new_fluid_midi_event();
872 FLUID_LOG(FLUID_ERR, "Out of memory");
873 result = FLUID_FAILED;
877 evt->dtime = mf->dtime;
878 evt->type = MIDI_SET_TEMPO;
882 fluid_track_add_event(track, evt);
886 case MIDI_SMPTE_OFFSET:
890 "Invalid length for SMPTE Offset meta event");
891 result = FLUID_FAILED;
895 break; /* we don't use smtp */
897 case MIDI_TIME_SIGNATURE:
901 "Invalid length for TimeSignature meta event");
902 result = FLUID_FAILED;
906 nominator = metadata[0];
907 denominator = pow(2.0, (double) metadata[1]);
908 clocks = metadata[2];
912 "signature=%d/%d, metronome=%d, 32nd-notes=%d",
913 nominator, denominator, clocks, notes);
917 case MIDI_KEY_SIGNATURE:
921 "Invalid length for KeySignature meta event");
922 result = FLUID_FAILED;
926 /* We don't care about key signatures anyway */
931 case MIDI_SEQUENCER_EVENT:
940 FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
947 else /* channel messages */
950 type = status & 0xf0;
951 channel = status & 0x0f;
953 /* all channel message have at least 1 byte of associated data */
954 if((param1 = fluid_midi_file_getc(mf)) < 0)
956 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
964 if((param2 = fluid_midi_file_getc(mf)) < 0)
966 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
973 if((param2 = fluid_midi_file_getc(mf)) < 0)
975 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
982 if((param2 = fluid_midi_file_getc(mf)) < 0)
984 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
991 if((param2 = fluid_midi_file_getc(mf)) < 0)
993 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
1002 case CHANNEL_PRESSURE:
1006 if((param2 = fluid_midi_file_getc(mf)) < 0)
1008 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
1009 return FLUID_FAILED;
1012 param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
1017 /* Can't possibly happen !? */
1018 FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
1019 return FLUID_FAILED;
1022 evt = new_fluid_midi_event();
1026 FLUID_LOG(FLUID_ERR, "Out of memory");
1027 return FLUID_FAILED;
1030 evt->dtime = mf->dtime;
1032 evt->channel = channel;
1033 evt->param1 = param1;
1034 evt->param2 = param2;
1035 fluid_track_add_event(track, evt);
1043 * fluid_midi_file_get_division
1046 fluid_midi_file_get_division(fluid_midi_file *midifile)
1048 return midifile->division;
1052 /******************************************************
1058 * Create a MIDI event structure.
1059 * @return New MIDI event structure or NULL when out of memory.
1061 fluid_midi_event_t *
1062 new_fluid_midi_event()
1064 fluid_midi_event_t *evt;
1065 evt = FLUID_NEW(fluid_midi_event_t);
1069 FLUID_LOG(FLUID_ERR, "Out of memory");
1079 evt->paramptr = NULL;
1084 * Delete MIDI event structure.
1085 * @param evt MIDI event structure
1088 delete_fluid_midi_event(fluid_midi_event_t *evt)
1090 fluid_midi_event_t *temp;
1091 fluid_return_if_fail(evt != NULL);
1097 /* Dynamic SYSEX event? - free (param2 indicates if dynamic) */
1098 if((evt->type == MIDI_SYSEX || (evt-> type == MIDI_TEXT) || (evt->type == MIDI_LYRIC)) &&
1099 evt->paramptr && evt->param2)
1101 FLUID_FREE(evt->paramptr);
1110 * Get the event type field of a MIDI event structure.
1111 * @param evt MIDI event structure
1112 * @return Event type field (MIDI status byte without channel)
1115 fluid_midi_event_get_type(fluid_midi_event_t *evt)
1121 * Set the event type field of a MIDI event structure.
1122 * @param evt MIDI event structure
1123 * @param type Event type field (MIDI status byte without channel)
1124 * @return Always returns #FLUID_OK
1127 fluid_midi_event_set_type(fluid_midi_event_t *evt, int type)
1134 * Get the channel field of a MIDI event structure.
1135 * @param evt MIDI event structure
1136 * @return Channel field
1139 fluid_midi_event_get_channel(fluid_midi_event_t *evt)
1141 return evt->channel;
1145 * Set the channel field of a MIDI event structure.
1146 * @param evt MIDI event structure
1147 * @param chan MIDI channel field
1148 * @return Always returns #FLUID_OK
1151 fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan)
1153 evt->channel = chan;
1158 * Get the key field of a MIDI event structure.
1159 * @param evt MIDI event structure
1160 * @return MIDI note number (0-127)
1163 fluid_midi_event_get_key(fluid_midi_event_t *evt)
1169 * Set the key field of a MIDI event structure.
1170 * @param evt MIDI event structure
1171 * @param v MIDI note number (0-127)
1172 * @return Always returns #FLUID_OK
1175 fluid_midi_event_set_key(fluid_midi_event_t *evt, int v)
1182 * Get the velocity field of a MIDI event structure.
1183 * @param evt MIDI event structure
1184 * @return MIDI velocity number (0-127)
1187 fluid_midi_event_get_velocity(fluid_midi_event_t *evt)
1193 * Set the velocity field of a MIDI event structure.
1194 * @param evt MIDI event structure
1195 * @param v MIDI velocity value
1196 * @return Always returns #FLUID_OK
1199 fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int v)
1206 * Get the control number of a MIDI event structure.
1207 * @param evt MIDI event structure
1208 * @return MIDI control number
1211 fluid_midi_event_get_control(fluid_midi_event_t *evt)
1217 * Set the control field of a MIDI event structure.
1218 * @param evt MIDI event structure
1219 * @param v MIDI control number
1220 * @return Always returns #FLUID_OK
1223 fluid_midi_event_set_control(fluid_midi_event_t *evt, int v)
1230 * Get the value field from a MIDI event structure.
1231 * @param evt MIDI event structure
1232 * @return Value field
1235 fluid_midi_event_get_value(fluid_midi_event_t *evt)
1241 * Set the value field of a MIDI event structure.
1242 * @param evt MIDI event structure
1243 * @param v Value to assign
1244 * @return Always returns #FLUID_OK
1247 fluid_midi_event_set_value(fluid_midi_event_t *evt, int v)
1254 * Get the program field of a MIDI event structure.
1255 * @param evt MIDI event structure
1256 * @return MIDI program number (0-127)
1259 fluid_midi_event_get_program(fluid_midi_event_t *evt)
1265 * Set the program field of a MIDI event structure.
1266 * @param evt MIDI event structure
1267 * @param val MIDI program number (0-127)
1268 * @return Always returns #FLUID_OK
1271 fluid_midi_event_set_program(fluid_midi_event_t *evt, int val)
1278 * Get the pitch field of a MIDI event structure.
1279 * @param evt MIDI event structure
1280 * @return Pitch value (14 bit value, 0-16383, 8192 is center)
1283 fluid_midi_event_get_pitch(fluid_midi_event_t *evt)
1289 * Set the pitch field of a MIDI event structure.
1290 * @param evt MIDI event structure
1291 * @param val Pitch value (14 bit value, 0-16383, 8192 is center)
1292 * @return Always returns FLUID_OK
1295 fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val)
1302 * Assign sysex data to a MIDI event structure.
1303 * @param evt MIDI event structure
1304 * @param data Pointer to SYSEX data
1305 * @param size Size of SYSEX data in bytes
1306 * @param dynamic TRUE if the SYSEX data has been dynamically allocated and
1307 * should be freed when the event is freed (only applies if event gets destroyed
1308 * with delete_fluid_midi_event())
1309 * @return Always returns #FLUID_OK
1312 fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1314 fluid_midi_event_set_sysex_LOCAL(evt, MIDI_SYSEX, data, size, dynamic);
1319 * Assign text data to a MIDI event structure.
1320 * @param evt MIDI event structure
1321 * @param data Pointer to text data
1322 * @param size Size of text data in bytes
1323 * @param dynamic TRUE if the data has been dynamically allocated and
1324 * should be freed when the event is freed via delete_fluid_midi_event()
1325 * @return Always returns #FLUID_OK
1330 fluid_midi_event_set_text(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1332 fluid_midi_event_set_sysex_LOCAL(evt, MIDI_TEXT, data, size, dynamic);
1337 * Get the text of a MIDI event structure.
1338 * @param evt MIDI event structure
1339 * @param data Pointer to return text data on.
1340 * @param size Pointer to return text size on.
1341 * @return Returns #FLUID_OK if \p data and \p size previously set by
1342 * fluid_midi_event_set_text() have been successfully retrieved.
1343 * Else #FLUID_FAILED is returned and \p data and \p size are not changed.
1346 int fluid_midi_event_get_text(fluid_midi_event_t *evt, void **data, int *size)
1348 fluid_return_val_if_fail(evt != NULL, FLUID_FAILED);
1349 fluid_return_val_if_fail(evt->type == MIDI_TEXT, FLUID_FAILED);
1351 fluid_midi_event_get_sysex_LOCAL(evt, data, size);
1356 * Assign lyric data to a MIDI event structure.
1357 * @param evt MIDI event structure
1358 * @param data Pointer to lyric data
1359 * @param size Size of lyric data in bytes
1360 * @param dynamic TRUE if the data has been dynamically allocated and
1361 * should be freed when the event is freed via delete_fluid_midi_event()
1362 * @return Always returns #FLUID_OK
1367 fluid_midi_event_set_lyrics(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1369 fluid_midi_event_set_sysex_LOCAL(evt, MIDI_LYRIC, data, size, dynamic);
1374 * Get the lyric of a MIDI event structure.
1375 * @param evt MIDI event structure
1376 * @param data Pointer to return lyric data on.
1377 * @param size Pointer to return lyric size on.
1378 * @return Returns #FLUID_OK if \p data and \p size previously set by
1379 * fluid_midi_event_set_lyrics() have been successfully retrieved.
1380 * Else #FLUID_FAILED is returned and \p data and \p size are not changed.
1383 int fluid_midi_event_get_lyrics(fluid_midi_event_t *evt, void **data, int *size)
1385 fluid_return_val_if_fail(evt != NULL, FLUID_FAILED);
1386 fluid_return_val_if_fail(evt->type == MIDI_LYRIC, FLUID_FAILED);
1388 fluid_midi_event_get_sysex_LOCAL(evt, data, size);
1392 static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic)
1395 evt->paramptr = data;
1397 evt->param2 = dynamic;
1400 static void fluid_midi_event_get_sysex_LOCAL(fluid_midi_event_t *evt, void **data, int *size)
1404 *data = evt->paramptr;
1409 *size = evt->param1;
1413 /******************************************************
1417 #if 0 // disable fluid file player in Ardour
1422 new_fluid_track(int num)
1424 fluid_track_t *track;
1425 track = FLUID_NEW(fluid_track_t);
1434 track->first = NULL;
1442 * delete_fluid_track
1445 delete_fluid_track(fluid_track_t *track)
1447 fluid_return_if_fail(track != NULL);
1449 FLUID_FREE(track->name);
1450 delete_fluid_midi_event(track->first);
1455 * fluid_track_set_name
1458 fluid_track_set_name(fluid_track_t *track, char *name)
1462 if(track->name != NULL)
1464 FLUID_FREE(track->name);
1473 len = FLUID_STRLEN(name);
1474 track->name = FLUID_MALLOC(len + 1);
1476 if(track->name == NULL)
1478 FLUID_LOG(FLUID_ERR, "Out of memory");
1479 return FLUID_FAILED;
1482 FLUID_STRCPY(track->name, name);
1487 * fluid_track_get_duration
1490 fluid_track_get_duration(fluid_track_t *track)
1493 fluid_midi_event_t *evt = track->first;
1505 * fluid_track_add_event
1508 fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt)
1512 if(track->first == NULL)
1520 track->last->next = evt;
1528 * fluid_track_next_event
1530 fluid_midi_event_t *
1531 fluid_track_next_event(fluid_track_t *track)
1533 if(track->cur != NULL)
1535 track->cur = track->cur->next;
1545 fluid_track_reset(fluid_track_t *track)
1548 track->cur = track->first;
1553 * fluid_track_send_events
1556 fluid_track_send_events(fluid_track_t *track,
1557 fluid_synth_t *synth,
1558 fluid_player_t *player,
1561 int status = FLUID_OK;
1562 fluid_midi_event_t *event;
1563 int seeking = player->seek_ticks >= 0;
1567 ticks = player->seek_ticks; /* update target ticks */
1569 if(track->ticks > ticks)
1571 fluid_track_reset(track); /* reset track if seeking backwards */
1585 /* printf("track=%02d\tticks=%05u\ttrack=%05u\tdtime=%05u\tnext=%05u\n", */
1590 /* track->ticks + event->dtime); */
1592 if(track->ticks + event->dtime > ticks)
1597 track->ticks += event->dtime;
1599 if(!player || event->type == MIDI_EOT)
1602 else if(seeking && (event->type == NOTE_ON || event->type == NOTE_OFF))
1604 /* skip on/off messages */
1608 if(player->playback_callback)
1610 player->playback_callback(player->playback_userdata, event);
1614 if(event->type == MIDI_SET_TEMPO)
1616 fluid_player_set_midi_tempo(player, event->param1);
1619 fluid_track_next_event(track);
1626 /******************************************************
1631 fluid_player_handle_reset_synth(void *data, const char *name, int value)
1633 fluid_player_t *player = data;
1634 fluid_return_if_fail(player != NULL);
1636 player->reset_synth_between_songs = value;
1640 * Create a new MIDI player.
1641 * @param synth Fluid synthesizer instance to create player for
1642 * @return New MIDI player instance or NULL on error (out of memory)
1645 new_fluid_player(fluid_synth_t *synth)
1648 fluid_player_t *player;
1649 player = FLUID_NEW(fluid_player_t);
1653 FLUID_LOG(FLUID_ERR, "Out of memory");
1657 player->status = FLUID_PLAYER_READY;
1659 player->ntracks = 0;
1661 for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1663 player->track[i] = NULL;
1666 player->synth = synth;
1667 player->system_timer = NULL;
1668 player->sample_timer = NULL;
1669 player->playlist = NULL;
1670 player->currentfile = NULL;
1671 player->division = 0;
1672 player->send_program_change = 1;
1673 player->miditempo = 480000;
1674 player->deltatime = 4.0;
1675 player->cur_msec = 0;
1676 player->cur_ticks = 0;
1677 player->seek_ticks = -1;
1678 fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth);
1679 player->use_system_timer = fluid_settings_str_equal(synth->settings,
1680 "player.timing-source", "system");
1682 fluid_settings_getint(synth->settings, "player.reset-synth", &i);
1683 fluid_player_handle_reset_synth(player, NULL, i);
1685 fluid_settings_callback_int(synth->settings, "player.reset-synth",
1686 fluid_player_handle_reset_synth, player);
1692 * Delete a MIDI player instance.
1693 * @param player MIDI player instance
1696 delete_fluid_player(fluid_player_t *player)
1699 fluid_playlist_item *pi;
1701 fluid_return_if_fail(player != NULL);
1703 fluid_player_stop(player);
1704 fluid_player_reset(player);
1706 while(player->playlist != NULL)
1708 q = player->playlist->next;
1709 pi = (fluid_playlist_item *) player->playlist->data;
1710 FLUID_FREE(pi->filename);
1711 FLUID_FREE(pi->buffer);
1713 delete1_fluid_list(player->playlist);
1714 player->playlist = q;
1721 * Registers settings related to the MIDI player
1724 fluid_player_settings(fluid_settings_t *settings)
1726 /* player.timing-source can be either "system" (use system timer)
1727 or "sample" (use timer based on number of written samples) */
1728 fluid_settings_register_str(settings, "player.timing-source", "sample", 0);
1729 fluid_settings_add_option(settings, "player.timing-source", "sample");
1730 fluid_settings_add_option(settings, "player.timing-source", "system");
1732 /* Selects whether the player should reset the synth between songs, or not. */
1733 fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1, FLUID_HINT_TOGGLED);
1738 fluid_player_reset(fluid_player_t *player)
1742 for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1744 if(player->track[i] != NULL)
1746 delete_fluid_track(player->track[i]);
1747 player->track[i] = NULL;
1751 /* player->current_file = NULL; */
1752 /* player->status = FLUID_PLAYER_READY; */
1753 /* player->loop = 1; */
1754 player->ntracks = 0;
1755 player->division = 0;
1756 player->send_program_change = 1;
1757 player->miditempo = 480000;
1758 player->deltatime = 4.0;
1763 * fluid_player_add_track
1766 fluid_player_add_track(fluid_player_t *player, fluid_track_t *track)
1768 if(player->ntracks < MAX_NUMBER_OF_TRACKS)
1770 player->track[player->ntracks++] = track;
1775 return FLUID_FAILED;
1780 * Change the MIDI callback function. This is usually set to
1781 * fluid_synth_handle_midi_event, but can optionally be changed
1782 * to a user-defined function instead, for intercepting all MIDI
1783 * messages sent to the synth. You can also use a midi router as
1784 * the callback function to modify the MIDI messages before sending
1785 * them to the synth.
1786 * @param player MIDI player instance
1787 * @param handler Pointer to callback function
1788 * @param handler_data Parameter sent to the callback function
1793 fluid_player_set_playback_callback(fluid_player_t *player,
1794 handle_midi_event_func_t handler, void *handler_data)
1796 player->playback_callback = handler;
1797 player->playback_userdata = handler_data;
1802 * Add a MIDI file to a player queue.
1803 * @param player MIDI player instance
1804 * @param midifile File name of the MIDI file to add
1805 * @return #FLUID_OK or #FLUID_FAILED
1808 fluid_player_add(fluid_player_t *player, const char *midifile)
1810 fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1811 char *f = FLUID_STRDUP(midifile);
1817 FLUID_LOG(FLUID_PANIC, "Out of memory");
1818 return FLUID_FAILED;
1824 player->playlist = fluid_list_append(player->playlist, pi);
1829 * Add a MIDI file to a player queue, from a buffer in memory.
1830 * @param player MIDI player instance
1831 * @param buffer Pointer to memory containing the bytes of a complete MIDI
1832 * file. The data is copied, so the caller may free or modify it immediately
1833 * without affecting the playlist.
1834 * @param len Length of the buffer, in bytes.
1835 * @return #FLUID_OK or #FLUID_FAILED
1838 fluid_player_add_mem(fluid_player_t *player, const void *buffer, size_t len)
1840 /* Take a copy of the buffer, so the caller can free immediately. */
1841 fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1842 void *buf_copy = FLUID_MALLOC(len);
1844 if(!pi || !buf_copy)
1847 FLUID_FREE(buf_copy);
1848 FLUID_LOG(FLUID_PANIC, "Out of memory");
1849 return FLUID_FAILED;
1852 FLUID_MEMCPY(buf_copy, buffer, len);
1853 pi->filename = NULL;
1854 pi->buffer = buf_copy;
1855 pi->buffer_len = len;
1856 player->playlist = fluid_list_append(player->playlist, pi);
1864 fluid_player_load(fluid_player_t *player, fluid_playlist_item *item)
1866 fluid_midi_file *midifile;
1868 size_t buffer_length;
1871 if(item->filename != NULL)
1874 /* This file is specified by filename; load the file from disk */
1875 FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__,
1877 /* Read the entire contents of the file into the buffer */
1878 fp = FLUID_FOPEN(item->filename, "rb");
1882 FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
1883 return FLUID_FAILED;
1886 buffer = fluid_file_read_full(fp, &buffer_length);
1891 return FLUID_FAILED;
1899 /* This file is specified by a pre-loaded buffer; load from memory */
1900 FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile from memory (%p)",
1901 __FILE__, __LINE__, item->buffer);
1902 buffer = (char *) item->buffer;
1903 buffer_length = item->buffer_len;
1904 /* Do not free the buffer (it is owned by the playlist) */
1908 midifile = new_fluid_midi_file(buffer, buffer_length);
1910 if(midifile == NULL)
1917 return FLUID_FAILED;
1920 player->division = fluid_midi_file_get_division(midifile);
1921 fluid_player_set_midi_tempo(player, player->miditempo); // Update deltatime
1922 /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */
1924 if(fluid_midi_file_load_tracks(midifile, player) != FLUID_OK)
1931 delete_fluid_midi_file(midifile);
1932 return FLUID_FAILED;
1935 delete_fluid_midi_file(midifile);
1946 fluid_player_advancefile(fluid_player_t *player)
1948 if(player->playlist == NULL)
1950 return; /* No files to play */
1953 if(player->currentfile != NULL)
1955 player->currentfile = fluid_list_next(player->currentfile);
1958 if(player->currentfile == NULL)
1960 if(player->loop == 0)
1962 return; /* We're done playing */
1965 if(player->loop > 0)
1970 player->currentfile = player->playlist;
1975 fluid_player_playlist_load(fluid_player_t *player, unsigned int msec)
1977 fluid_playlist_item *current_playitem;
1982 fluid_player_advancefile(player);
1984 if(player->currentfile == NULL)
1986 /* Failed to find next song, probably since we're finished */
1987 player->status = FLUID_PLAYER_DONE;
1991 fluid_player_reset(player);
1992 current_playitem = (fluid_playlist_item *) player->currentfile->data;
1994 while(fluid_player_load(player, current_playitem) != FLUID_OK);
1996 /* Successfully loaded midi file */
1998 player->begin_msec = msec;
1999 player->start_msec = msec;
2000 player->start_ticks = 0;
2001 player->cur_ticks = 0;
2003 if(player->reset_synth_between_songs)
2005 fluid_synth_system_reset(player->synth);
2008 for(i = 0; i < player->ntracks; i++)
2010 if(player->track[i] != NULL)
2012 fluid_track_reset(player->track[i]);
2018 * fluid_player_callback
2021 fluid_player_callback(void *data, unsigned int msec)
2025 int status = FLUID_PLAYER_DONE;
2026 fluid_player_t *player;
2027 fluid_synth_t *synth;
2028 player = (fluid_player_t *) data;
2029 synth = player->synth;
2031 loadnextfile = player->currentfile == NULL ? 1 : 0;
2038 fluid_player_playlist_load(player, msec);
2040 if(player->currentfile == NULL)
2046 player->cur_msec = msec;
2047 player->cur_ticks = (player->start_ticks
2048 + (int)((double)(player->cur_msec - player->start_msec)
2049 / player->deltatime + 0.5)); /* 0.5 to average overall error when casting */
2051 if(player->seek_ticks >= 0)
2053 fluid_synth_all_sounds_off(synth, -1); /* avoid hanging notes */
2056 for(i = 0; i < player->ntracks; i++)
2058 if(!fluid_track_eot(player->track[i]))
2060 status = FLUID_PLAYER_PLAYING;
2062 if(fluid_track_send_events(player->track[i], synth, player,
2063 player->cur_ticks) != FLUID_OK)
2070 if(player->seek_ticks >= 0)
2072 player->start_ticks = player->seek_ticks; /* tick position of last tempo value (which is now) */
2073 player->cur_ticks = player->seek_ticks;
2074 player->begin_msec = msec; /* only used to calculate the duration of playing */
2075 player->start_msec = msec; /* should be the (synth)-time of the last tempo change */
2076 player->seek_ticks = -1; /* clear seek_ticks */
2079 if(status == FLUID_PLAYER_DONE)
2081 FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
2082 __LINE__, (msec - player->begin_msec) / 1000.0);
2086 while(loadnextfile);
2088 player->status = status;
2094 * Activates play mode for a MIDI player if not already playing.
2095 * @param player MIDI player instance
2096 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2099 fluid_player_play(fluid_player_t *player)
2101 if(player->status == FLUID_PLAYER_PLAYING)
2106 if(player->playlist == NULL)
2111 player->status = FLUID_PLAYER_PLAYING;
2113 if(player->use_system_timer)
2115 player->system_timer = new_fluid_timer((int) player->deltatime,
2116 fluid_player_callback, (void *) player, TRUE, FALSE, TRUE);
2118 if(player->system_timer == NULL)
2120 return FLUID_FAILED;
2125 player->sample_timer = new_fluid_sample_timer(player->synth,
2126 fluid_player_callback, (void *) player);
2128 if(player->sample_timer == NULL)
2130 return FLUID_FAILED;
2138 * Stops a MIDI player.
2139 * @param player MIDI player instance
2140 * @return Always returns #FLUID_OK
2143 fluid_player_stop(fluid_player_t *player)
2145 if(player->system_timer != NULL)
2147 delete_fluid_timer(player->system_timer);
2150 if(player->sample_timer != NULL)
2152 delete_fluid_sample_timer(player->synth, player->sample_timer);
2155 player->status = FLUID_PLAYER_DONE;
2156 player->sample_timer = NULL;
2157 player->system_timer = NULL;
2162 * Get MIDI player status.
2163 * @param player MIDI player instance
2164 * @return Player status (#fluid_player_status)
2168 fluid_player_get_status(fluid_player_t *player)
2170 return player->status;
2174 * Seek in the currently playing file.
2175 * @param player MIDI player instance
2176 * @param ticks the position to seek to in the current file
2177 * @return #FLUID_FAILED if ticks is negative or after the latest tick of the file,
2178 * #FLUID_OK otherwise
2181 * The actual seek is performed during the player_callback.
2183 int fluid_player_seek(fluid_player_t *player, int ticks)
2185 if(ticks < 0 || ticks > fluid_player_get_total_ticks(player))
2187 return FLUID_FAILED;
2190 player->seek_ticks = ticks;
2196 * Enable looping of a MIDI player
2197 * @param player MIDI player instance
2198 * @param loop Times left to loop the playlist. -1 means loop infinitely.
2199 * @return Always returns #FLUID_OK
2202 * For example, if you want to loop the playlist twice, set loop to 2
2203 * and call this function before you start the player.
2205 int fluid_player_set_loop(fluid_player_t *player, int loop)
2207 player->loop = loop;
2212 * Set the tempo of a MIDI player.
2213 * @param player MIDI player instance
2214 * @param tempo Tempo to set playback speed to (in microseconds per quarter note, as per MIDI file spec)
2215 * @return Always returns #FLUID_OK
2217 int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo)
2219 player->miditempo = tempo;
2220 player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */
2221 player->start_msec = player->cur_msec;
2222 player->start_ticks = player->cur_ticks;
2224 FLUID_LOG(FLUID_DBG,
2225 "tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
2226 tempo, player->deltatime, player->cur_msec, player->cur_ticks);
2232 * Set the tempo of a MIDI player in beats per minute.
2233 * @param player MIDI player instance
2234 * @param bpm Tempo in beats per minute
2235 * @return Always returns #FLUID_OK
2237 int fluid_player_set_bpm(fluid_player_t *player, int bpm)
2239 return fluid_player_set_midi_tempo(player, 60000000L / bpm);
2243 * Wait for a MIDI player to terminate (when done playing).
2244 * @param player MIDI player instance
2245 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2248 fluid_player_join(fluid_player_t *player)
2250 if(player->system_timer)
2252 return fluid_timer_join(player->system_timer);
2254 else if(player->sample_timer)
2256 /* Busy-wait loop, since there's no thread to wait for... */
2257 while(player->status != FLUID_PLAYER_DONE)
2267 * Get the number of tempo ticks passed.
2268 * @param player MIDI player instance
2269 * @return The number of tempo ticks passed
2272 int fluid_player_get_current_tick(fluid_player_t *player)
2274 return player->cur_ticks;
2278 * Looks through all available MIDI tracks and gets the absolute tick of the very last event to play.
2279 * @param player MIDI player instance
2280 * @return Total tick count of the sequence
2283 int fluid_player_get_total_ticks(fluid_player_t *player)
2288 for(i = 0; i < player->ntracks; i++)
2290 if(player->track[i] != NULL)
2292 int ticks = fluid_track_get_duration(player->track[i]);
2294 if(ticks > maxTicks)
2305 * Get the tempo of a MIDI player in beats per minute.
2306 * @param player MIDI player instance
2307 * @return MIDI player tempo in BPM
2310 int fluid_player_get_bpm(fluid_player_t *player)
2312 return 60000000L / player->miditempo;
2316 * Get the tempo of a MIDI player.
2317 * @param player MIDI player instance
2318 * @return Tempo of the MIDI player (in microseconds per quarter note, as per MIDI file spec)
2321 int fluid_player_get_midi_tempo(fluid_player_t *player)
2323 return player->miditempo;
2326 /************************************************************************
2332 * new_fluid_midi_parser
2334 fluid_midi_parser_t *
2335 new_fluid_midi_parser()
2337 fluid_midi_parser_t *parser;
2338 parser = FLUID_NEW(fluid_midi_parser_t);
2342 FLUID_LOG(FLUID_ERR, "Out of memory");
2346 parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */
2351 * delete_fluid_midi_parser
2354 delete_fluid_midi_parser(fluid_midi_parser_t *parser)
2356 fluid_return_if_fail(parser != NULL);
2362 * Parse a MIDI stream one character at a time.
2363 * @param parser Parser instance
2364 * @param c Next character in MIDI stream
2365 * @return A parsed MIDI event or NULL if none. Event is internal and should
2366 * not be modified or freed and is only valid until next call to this function.
2367 * @internal Do not expose this function to the public API. It would allow downstream
2368 * apps to abuse fluidsynth as midi parser, e.g. feeding it with rawmidi and pull out
2369 * the needed midi information using the getter functions of fluid_midi_event_t.
2370 * This parser however is incomplete as it e.g. only provides a limited buffer to
2371 * store and process SYSEX data (i.e. doesnt allow arbitrary lengths)
2373 fluid_midi_event_t *
2374 fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c)
2376 fluid_midi_event_t *event;
2378 /* Real-time messages (0xF8-0xFF) can occur anywhere, even in the middle
2379 * of another message. */
2382 if(c == MIDI_SYSTEM_RESET)
2384 parser->event.type = c;
2385 parser->status = 0; /* clear the status */
2386 return &parser->event;
2392 /* Status byte? - If previous message not yet complete, it is discarded (re-sync). */
2395 /* Any status byte terminates SYSEX messages (not just 0xF7) */
2396 if(parser->status == MIDI_SYSEX && parser->nr_bytes > 0)
2398 event = &parser->event;
2399 fluid_midi_event_set_sysex(event, parser->data, parser->nr_bytes,
2407 if(c < 0xF0) /* Voice category message? */
2409 parser->channel = c & 0x0F;
2410 parser->status = c & 0xF0;
2412 /* The event consumes x bytes of data... (subtract 1 for the status byte) */
2413 parser->nr_bytes_total = fluid_midi_event_length(parser->status)
2416 parser->nr_bytes = 0; /* 0 bytes read so far */
2418 else if(c == MIDI_SYSEX)
2420 parser->status = MIDI_SYSEX;
2421 parser->nr_bytes = 0;
2425 parser->status = 0; /* Discard other system messages (0xF1-0xF7) */
2428 return event; /* Return SYSEX event or NULL */
2431 /* Data/parameter byte */
2433 /* Discard data bytes for events we don't care about */
2434 if(parser->status == 0)
2439 /* Max data size exceeded? (SYSEX messages only really) */
2440 if(parser->nr_bytes == FLUID_MIDI_PARSER_MAX_DATA_SIZE)
2442 parser->status = 0; /* Discard the rest of the message */
2446 /* Store next byte */
2447 parser->data[parser->nr_bytes++] = c;
2449 /* Do we still need more data to get this event complete? */
2450 if(parser->status == MIDI_SYSEX || parser->nr_bytes < parser->nr_bytes_total)
2455 /* Event is complete, return it.
2456 * Running status byte MIDI feature is also handled here. */
2457 parser->event.type = parser->status;
2458 parser->event.channel = parser->channel;
2459 parser->nr_bytes = 0; /* Reset data size, in case there are additional running status messages */
2461 switch(parser->status)
2466 case CONTROL_CHANGE:
2467 case PROGRAM_CHANGE:
2468 case CHANNEL_PRESSURE:
2469 parser->event.param1 = parser->data[0]; /* For example key number */
2470 parser->event.param2 = parser->data[1]; /* For example velocity */
2474 /* Pitch-bend is transmitted with 14-bit precision. */
2475 parser->event.param1 = (parser->data[1] << 7) | parser->data[0];
2478 default: /* Unlikely */
2482 return &parser->event;
2486 * Returns the length of a MIDI message. */
2488 fluid_midi_event_length(unsigned char event)
2490 switch(event & 0xF0)
2495 case CONTROL_CHANGE:
2499 case PROGRAM_CHANGE:
2500 case CHANNEL_PRESSURE:
2506 case MIDI_TIME_CODE:
2507 case MIDI_SONG_SELECT:
2512 case MIDI_TUNE_REQUEST:
2515 case MIDI_SONG_POSITION: