1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
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.
9  *
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.
14  *
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
18  * 02110-1301, USA
19  */
20 
21 #include "fluid_midi.h"
22 #include "fluid_sys.h"
23 #include "fluid_synth.h"
24 #include "fluid_settings.h"
25 
26 
27 static int fluid_midi_event_length(unsigned char event);
28 static int fluid_isasciistring(char *s);
29 static long fluid_getlength(const unsigned char *s);
30 
31 
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.
36  */
37 typedef FILE  *fluid_file;
38 static char *fluid_file_read_full(fluid_file fp, size_t *length);
39 static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic);
40 static void fluid_midi_event_get_sysex_LOCAL(fluid_midi_event_t *evt, void **data, int *size);
41 #define READ_FULL_INITIAL_BUFLEN 1024
42 
43 static fluid_track_t *new_fluid_track(int num);
44 static void delete_fluid_track(fluid_track_t *track);
45 static int fluid_track_set_name(fluid_track_t *track, char *name);
46 static int fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt);
47 static fluid_midi_event_t *fluid_track_next_event(fluid_track_t *track);
48 static int fluid_track_get_duration(fluid_track_t *track);
49 static int fluid_track_reset(fluid_track_t *track);
50 
51 static int fluid_player_add_track(fluid_player_t *player, fluid_track_t *track);
52 static int fluid_player_callback(void *data, unsigned int msec);
53 static int fluid_player_reset(fluid_player_t *player);
54 static int fluid_player_load(fluid_player_t *player, fluid_playlist_item *item);
55 static void fluid_player_advancefile(fluid_player_t *player);
56 static void fluid_player_playlist_load(fluid_player_t *player, unsigned int msec);
57 static void fluid_player_update_tempo(fluid_player_t *player);
58 
59 static fluid_midi_file *new_fluid_midi_file(const char *buffer, size_t length);
60 static void delete_fluid_midi_file(fluid_midi_file *mf);
61 static int fluid_midi_file_read_mthd(fluid_midi_file *midifile);
62 static int fluid_midi_file_load_tracks(fluid_midi_file *midifile, fluid_player_t *player);
63 static int fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num);
64 static int fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track);
65 static int fluid_midi_file_read_varlen(fluid_midi_file *mf);
66 static int fluid_midi_file_getc(fluid_midi_file *mf);
67 static int fluid_midi_file_push(fluid_midi_file *mf, int c);
68 static int fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len);
69 static int fluid_midi_file_skip(fluid_midi_file *mf, int len);
70 static int fluid_midi_file_eof(fluid_midi_file *mf);
71 static int fluid_midi_file_read_tracklen(fluid_midi_file *mf);
72 static int fluid_midi_file_eot(fluid_midi_file *mf);
73 static int fluid_midi_file_get_division(fluid_midi_file *midifile);
74 
75 
76 /***************************************************************
77  *
78  *                      MIDIFILE
79  */
80 
81 /**
82  * Check if a file is a MIDI file.
83  * @param filename Path to the file to check
84  * @return TRUE if it could be a MIDI file, FALSE otherwise
85  *
86  * The current implementation only checks for the "MThd" header in the file.
87  * It is useful only to distinguish between SoundFont and MIDI files.
88  */
fluid_is_midifile(const char * filename)89 int fluid_is_midifile(const char *filename)
90 {
91     FILE    *fp;
92     uint32_t id;
93     int      retcode = FALSE;
94 
95     do
96     {
97         if((fp = fluid_file_open(filename, NULL)) == NULL)
98         {
99             return retcode;
100         }
101 
102         if(FLUID_FREAD(&id, sizeof(id), 1, fp) != 1)
103         {
104             break;
105         }
106 
107         retcode = (id == FLUID_FOURCC('M', 'T', 'h', 'd'));
108     }
109     while(0);
110 
111     FLUID_FCLOSE(fp);
112 
113     return retcode;
114 }
115 
116 /**
117  * Return a new MIDI file handle for parsing an already-loaded MIDI file.
118  * @internal
119  * @param buffer Pointer to full contents of MIDI file (borrows the pointer).
120  *  The caller must not free buffer until after the fluid_midi_file is deleted.
121  * @param length Size of the buffer in bytes.
122  * @return New MIDI file handle or NULL on error.
123  */
124 fluid_midi_file *
new_fluid_midi_file(const char * buffer,size_t length)125 new_fluid_midi_file(const char *buffer, size_t length)
126 {
127     fluid_midi_file *mf;
128 
129     mf = FLUID_NEW(fluid_midi_file);
130 
131     if(mf == NULL)
132     {
133         FLUID_LOG(FLUID_ERR, "Out of memory");
134         return NULL;
135     }
136 
137     FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file));
138 
139     mf->c = -1;
140     mf->running_status = -1;
141 
142     mf->buffer = buffer;
143     mf->buf_len = length;
144     mf->buf_pos = 0;
145     mf->eof = FALSE;
146 
147     if(fluid_midi_file_read_mthd(mf) != FLUID_OK)
148     {
149         FLUID_FREE(mf);
150         return NULL;
151     }
152 
153     return mf;
154 }
155 
156 static char *
fluid_file_read_full(fluid_file fp,size_t * length)157 fluid_file_read_full(fluid_file fp, size_t *length)
158 {
159     size_t buflen;
160     char *buffer;
161     size_t n;
162 
163     /* Work out the length of the file in advance */
164     if(FLUID_FSEEK(fp, 0, SEEK_END) != 0)
165     {
166         FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
167         return NULL;
168     }
169 
170     buflen = ftell(fp);
171 
172     if(FLUID_FSEEK(fp, 0, SEEK_SET) != 0)
173     {
174         FLUID_LOG(FLUID_ERR, "File load: Could not seek within file");
175         return NULL;
176     }
177 
178     FLUID_LOG(FLUID_DBG, "File load: Allocating %lu bytes", (unsigned long)buflen);
179     buffer = FLUID_MALLOC(buflen);
180 
181     if(buffer == NULL)
182     {
183         FLUID_LOG(FLUID_PANIC, "Out of memory");
184         return NULL;
185     }
186 
187     n = FLUID_FREAD(buffer, 1, buflen, fp);
188 
189     if(n != buflen)
190     {
191         FLUID_LOG(FLUID_ERR, "Only read %lu bytes; expected %lu", (unsigned long)n,
192                   (unsigned long)buflen);
193         FLUID_FREE(buffer);
194         return NULL;
195     };
196 
197     *length = n;
198 
199     return buffer;
200 }
201 
202 /**
203  * Delete a MIDI file handle.
204  * @internal
205  * @param mf MIDI file handle to close and free.
206  */
207 void
delete_fluid_midi_file(fluid_midi_file * mf)208 delete_fluid_midi_file(fluid_midi_file *mf)
209 {
210     fluid_return_if_fail(mf != NULL);
211 
212     FLUID_FREE(mf);
213 }
214 
215 /*
216  * Gets the next byte in a MIDI file, taking into account previous running status.
217  *
218  * returns -1 if EOF or read error
219  */
220 int
fluid_midi_file_getc(fluid_midi_file * mf)221 fluid_midi_file_getc(fluid_midi_file *mf)
222 {
223     unsigned char c;
224 
225     if(mf->c >= 0)
226     {
227         c = mf->c;
228         mf->c = -1;
229     }
230     else
231     {
232         if(mf->buf_pos >= mf->buf_len)
233         {
234             mf->eof = TRUE;
235             return -1;
236         }
237 
238         c = mf->buffer[mf->buf_pos++];
239         mf->trackpos++;
240     }
241 
242     return (int) c;
243 }
244 
245 /*
246  * Saves a byte to be returned the next time fluid_midi_file_getc() is called,
247  * when it is necessary according to running status.
248  */
249 int
fluid_midi_file_push(fluid_midi_file * mf,int c)250 fluid_midi_file_push(fluid_midi_file *mf, int c)
251 {
252     mf->c = c;
253     return FLUID_OK;
254 }
255 
256 /*
257  * fluid_midi_file_read
258  */
259 int
fluid_midi_file_read(fluid_midi_file * mf,void * buf,int len)260 fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len)
261 {
262     int num = len < mf->buf_len - mf->buf_pos
263               ? len : mf->buf_len - mf->buf_pos;
264 
265     if(num != len)
266     {
267         mf->eof = TRUE;
268     }
269 
270     if(num < 0)
271     {
272         num = 0;
273     }
274 
275     /* Note: Read bytes, even if there aren't enough, but only increment
276      * trackpos if successful (emulates old behaviour of fluid_midi_file_read)
277      */
278     FLUID_MEMCPY(buf, mf->buffer + mf->buf_pos, num);
279     mf->buf_pos += num;
280 
281     if(num == len)
282     {
283         mf->trackpos += num;
284     }
285 
286 #if DEBUG
287     else
288     {
289         FLUID_LOG(FLUID_DBG, "Could not read the requested number of bytes");
290     }
291 
292 #endif
293     return (num != len) ? FLUID_FAILED : FLUID_OK;
294 }
295 
296 /*
297  * fluid_midi_file_skip
298  */
299 int
fluid_midi_file_skip(fluid_midi_file * mf,int skip)300 fluid_midi_file_skip(fluid_midi_file *mf, int skip)
301 {
302     int new_pos = mf->buf_pos + skip;
303 
304     /* Mimic the behaviour of fseek: Error to seek past the start of file, but
305      * OK to seek past end (this just puts it into the EOF state). */
306     if(new_pos < 0)
307     {
308         FLUID_LOG(FLUID_ERR, "Failed to seek position in file");
309         return FLUID_FAILED;
310     }
311 
312     /* Clear the EOF flag, even if moved past the end of the file (this is
313      * consistent with the behaviour of fseek). */
314     mf->eof = FALSE;
315     mf->buf_pos = new_pos;
316     return FLUID_OK;
317 }
318 
319 /*
320  * fluid_midi_file_eof
321  */
fluid_midi_file_eof(fluid_midi_file * mf)322 int fluid_midi_file_eof(fluid_midi_file *mf)
323 {
324     /* Note: This does not simply test whether the file read pointer is past
325      * the end of the file. It mimics the behaviour of feof by actually
326      * testing the stateful EOF condition, which is set to TRUE if getc or
327      * fread have attempted to read past the end (but not if they have
328      * precisely reached the end), but reset to FALSE upon a successful seek.
329      */
330     return mf->eof;
331 }
332 
333 /*
334  * fluid_midi_file_read_mthd
335  */
336 int
fluid_midi_file_read_mthd(fluid_midi_file * mf)337 fluid_midi_file_read_mthd(fluid_midi_file *mf)
338 {
339     char mthd[14];
340 
341     if(fluid_midi_file_read(mf, mthd, sizeof(mthd)) != FLUID_OK)
342     {
343         return FLUID_FAILED;
344     }
345 
346     if((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6)
347             || (mthd[9] > 2))
348     {
349         FLUID_LOG(FLUID_ERR,
350                   "Doesn't look like a MIDI file: invalid MThd header");
351         return FLUID_FAILED;
352     }
353 
354     mf->type = mthd[9];
355     mf->ntracks = (unsigned) mthd[11];
356     mf->ntracks += (unsigned int)(mthd[10]) << 16;
357 
358     if((signed char)mthd[12] < 0)
359     {
360         mf->uses_smpte = 1;
361         mf->smpte_fps = -(signed char)mthd[12];
362         mf->smpte_res = (unsigned) mthd[13];
363         FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet");
364         return FLUID_FAILED;
365     }
366     else
367     {
368         mf->uses_smpte = 0;
369         mf->division = ((unsigned)mthd[12] << 8) | ((unsigned)mthd[13] & 0xff);
370         FLUID_LOG(FLUID_DBG, "Division=%d", mf->division);
371     }
372 
373     return FLUID_OK;
374 }
375 
376 /*
377  * fluid_midi_file_load_tracks
378  */
379 int
fluid_midi_file_load_tracks(fluid_midi_file * mf,fluid_player_t * player)380 fluid_midi_file_load_tracks(fluid_midi_file *mf, fluid_player_t *player)
381 {
382     int i;
383 
384     for(i = 0; i < mf->ntracks; i++)
385     {
386         if(fluid_midi_file_read_track(mf, player, i) != FLUID_OK)
387         {
388             return FLUID_FAILED;
389         }
390     }
391 
392     return FLUID_OK;
393 }
394 
395 /*
396  * fluid_isasciistring
397  */
398 int
fluid_isasciistring(char * s)399 fluid_isasciistring(char *s)
400 {
401     /* From ctype.h */
402 #define fluid_isascii(c)    (((c) & ~0x7f) == 0)
403 
404     size_t i, len = FLUID_STRLEN(s);
405 
406     for(i = 0; i < len; i++)
407     {
408         if(!fluid_isascii(s[i]))
409         {
410             return 0;
411         }
412     }
413 
414     return 1;
415 
416 #undef fluid_isascii
417 }
418 
419 /*
420  * fluid_getlength
421  */
422 long
fluid_getlength(const unsigned char * s)423 fluid_getlength(const unsigned char *s)
424 {
425     long i = 0;
426     i = s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24);
427     return i;
428 }
429 
430 /*
431  * fluid_midi_file_read_tracklen
432  */
433 int
fluid_midi_file_read_tracklen(fluid_midi_file * mf)434 fluid_midi_file_read_tracklen(fluid_midi_file *mf)
435 {
436     unsigned char length[5];
437 
438     if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
439     {
440         return FLUID_FAILED;
441     }
442 
443     mf->tracklen = fluid_getlength(length);
444     mf->trackpos = 0;
445     mf->eot = 0;
446     return FLUID_OK;
447 }
448 
449 /*
450  * fluid_midi_file_eot
451  */
452 int
fluid_midi_file_eot(fluid_midi_file * mf)453 fluid_midi_file_eot(fluid_midi_file *mf)
454 {
455 #if DEBUG
456 
457     if(mf->trackpos > mf->tracklen)
458     {
459         printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen);
460     }
461 
462 #endif
463     return mf->eot || (mf->trackpos >= mf->tracklen);
464 }
465 
466 /*
467  * fluid_midi_file_read_track
468  */
469 int
fluid_midi_file_read_track(fluid_midi_file * mf,fluid_player_t * player,int num)470 fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
471 {
472     fluid_track_t *track;
473     unsigned char id[5], length[5];
474     int found_track = 0;
475     int skip;
476 
477     if(fluid_midi_file_read(mf, id, 4) != FLUID_OK)
478     {
479         return FLUID_FAILED;
480     }
481 
482     id[4] = '\0';
483     mf->dtime = 0;
484 
485     while(!found_track)
486     {
487 
488         if(fluid_isasciistring((char *) id) == 0)
489         {
490             FLUID_LOG(FLUID_ERR,
491                       "An non-ascii track header found, corrupt file");
492             return FLUID_FAILED;
493 
494         }
495         else if(FLUID_STRCMP((char *) id, "MTrk") == 0)
496         {
497 
498             found_track = 1;
499 
500             if(fluid_midi_file_read_tracklen(mf) != FLUID_OK)
501             {
502                 return FLUID_FAILED;
503             }
504 
505             track = new_fluid_track(num);
506 
507             if(track == NULL)
508             {
509                 FLUID_LOG(FLUID_ERR, "Out of memory");
510                 return FLUID_FAILED;
511             }
512 
513             while(!fluid_midi_file_eot(mf))
514             {
515                 if(fluid_midi_file_read_event(mf, track) != FLUID_OK)
516                 {
517                     delete_fluid_track(track);
518                     return FLUID_FAILED;
519                 }
520             }
521 
522             /* Skip remaining track data, if any */
523             if(mf->trackpos < mf->tracklen)
524             {
525                 if(fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos) != FLUID_OK)
526                 {
527                     delete_fluid_track(track);
528                     return FLUID_FAILED;
529                 }
530             }
531 
532             if(fluid_player_add_track(player, track) != FLUID_OK)
533             {
534                 delete_fluid_track(track);
535                 return FLUID_FAILED;
536             }
537 
538         }
539         else
540         {
541             found_track = 0;
542 
543             if(fluid_midi_file_read(mf, length, 4) != FLUID_OK)
544             {
545                 return FLUID_FAILED;
546             }
547 
548             skip = fluid_getlength(length);
549 
550             /* fseek(mf->fp, skip, SEEK_CUR); */
551             if(fluid_midi_file_skip(mf, skip) != FLUID_OK)
552             {
553                 return FLUID_FAILED;
554             }
555         }
556     }
557 
558     if(fluid_midi_file_eof(mf))
559     {
560         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
561         return FLUID_FAILED;
562     }
563 
564     return FLUID_OK;
565 }
566 
567 /*
568  * fluid_midi_file_read_varlen
569  */
570 int
fluid_midi_file_read_varlen(fluid_midi_file * mf)571 fluid_midi_file_read_varlen(fluid_midi_file *mf)
572 {
573     int i;
574     int c;
575     mf->varlen = 0;
576 
577     for(i = 0;; i++)
578     {
579         if(i == 4)
580         {
581             FLUID_LOG(FLUID_ERR, "Invalid variable length number");
582             return FLUID_FAILED;
583         }
584 
585         c = fluid_midi_file_getc(mf);
586 
587         if(c < 0)
588         {
589             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
590             return FLUID_FAILED;
591         }
592 
593         if(c & 0x80)
594         {
595             mf->varlen |= (int)(c & 0x7F);
596             mf->varlen <<= 7;
597         }
598         else
599         {
600             mf->varlen += c;
601             break;
602         }
603     }
604 
605     return FLUID_OK;
606 }
607 
608 /*
609  * fluid_midi_file_read_event
610  */
611 int
fluid_midi_file_read_event(fluid_midi_file * mf,fluid_track_t * track)612 fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track)
613 {
614     int status;
615     int type;
616     int tempo;
617     unsigned char *metadata = NULL;
618     unsigned char *dyn_buf = NULL;
619     unsigned char static_buf[256];
620     int nominator, denominator, clocks, notes;
621     fluid_midi_event_t *evt;
622     int channel = 0;
623     int param1 = 0;
624     int param2 = 0;
625     int size;
626 
627     /* read the delta-time of the event */
628     if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
629     {
630         return FLUID_FAILED;
631     }
632 
633     mf->dtime += mf->varlen;
634 
635     /* read the status byte */
636     status = fluid_midi_file_getc(mf);
637 
638     if(status < 0)
639     {
640         FLUID_LOG(FLUID_ERR, "Unexpected end of file");
641         return FLUID_FAILED;
642     }
643 
644     /* not a valid status byte: use the running status instead */
645     if((status & 0x80) == 0)
646     {
647         if((mf->running_status & 0x80) == 0)
648         {
649             FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
650             return FLUID_FAILED;
651         }
652 
653         fluid_midi_file_push(mf, status);
654         status = mf->running_status;
655     }
656 
657     /* check what message we have */
658 
659     mf->running_status = status;
660 
661     if(status == MIDI_SYSEX)    /* system exclusif */
662     {
663         /* read the length of the message */
664         if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
665         {
666             return FLUID_FAILED;
667         }
668 
669         if(mf->varlen)
670         {
671             FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
672                       __LINE__, mf->varlen);
673             metadata = FLUID_MALLOC(mf->varlen + 1);
674 
675             if(metadata == NULL)
676             {
677                 FLUID_LOG(FLUID_PANIC, "Out of memory");
678                 return FLUID_FAILED;
679             }
680 
681             /* read the data of the message */
682             if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
683             {
684                 FLUID_FREE(metadata);
685                 return FLUID_FAILED;
686             }
687 
688             evt = new_fluid_midi_event();
689 
690             if(evt == NULL)
691             {
692                 FLUID_LOG(FLUID_ERR, "Out of memory");
693                 FLUID_FREE(metadata);
694                 return FLUID_FAILED;
695             }
696 
697             evt->dtime = mf->dtime;
698             size = mf->varlen;
699 
700             if(metadata[mf->varlen - 1] == MIDI_EOX)
701             {
702                 size--;
703             }
704 
705             /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */
706             fluid_midi_event_set_sysex(evt, metadata, size, TRUE);
707             fluid_track_add_event(track, evt);
708             mf->dtime = 0;
709         }
710 
711         return FLUID_OK;
712 
713     }
714     else if(status == MIDI_META_EVENT)      /* meta events */
715     {
716 
717         int result = FLUID_OK;
718 
719         /* get the type of the meta message */
720         type = fluid_midi_file_getc(mf);
721 
722         if(type < 0)
723         {
724             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
725             return FLUID_FAILED;
726         }
727 
728         /* get the length of the data part */
729         if(fluid_midi_file_read_varlen(mf) != FLUID_OK)
730         {
731             return FLUID_FAILED;
732         }
733 
734         if(mf->varlen < 255)
735         {
736             metadata = &static_buf[0];
737         }
738         else
739         {
740             FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
741                       __LINE__, mf->varlen);
742             dyn_buf = FLUID_MALLOC(mf->varlen + 1);
743 
744             if(dyn_buf == NULL)
745             {
746                 FLUID_LOG(FLUID_PANIC, "Out of memory");
747                 return FLUID_FAILED;
748             }
749 
750             metadata = dyn_buf;
751         }
752 
753         /* read the data */
754         if(mf->varlen)
755         {
756             if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK)
757             {
758                 if(dyn_buf)
759                 {
760                     FLUID_FREE(dyn_buf);
761                 }
762 
763                 return FLUID_FAILED;
764             }
765         }
766 
767         /* handle meta data */
768         switch(type)
769         {
770 
771         case MIDI_COPYRIGHT:
772             metadata[mf->varlen] = 0;
773             break;
774 
775         case MIDI_TRACK_NAME:
776             metadata[mf->varlen] = 0;
777             fluid_track_set_name(track, (char *) metadata);
778             break;
779 
780         case MIDI_INST_NAME:
781             metadata[mf->varlen] = 0;
782             break;
783 
784         case MIDI_LYRIC:
785         case MIDI_TEXT:
786         {
787             void *tmp;
788             int size = mf->varlen + 1;
789 
790             /* NULL terminate strings for safety */
791             metadata[size - 1] = '\0';
792 
793             evt = new_fluid_midi_event();
794 
795             if(evt == NULL)
796             {
797                 FLUID_LOG(FLUID_ERR, "Out of memory");
798                 result = FLUID_FAILED;
799                 break;
800             }
801 
802             evt->dtime = mf->dtime;
803 
804             tmp = FLUID_MALLOC(size);
805 
806             if(tmp == NULL)
807             {
808                 FLUID_LOG(FLUID_PANIC, "Out of memory");
809                 delete_fluid_midi_event(evt);
810                 evt = NULL;
811                 result = FLUID_FAILED;
812                 break;
813             }
814 
815             FLUID_MEMCPY(tmp, metadata, size);
816 
817             fluid_midi_event_set_sysex_LOCAL(evt, type, tmp, size, TRUE);
818             fluid_track_add_event(track, evt);
819             mf->dtime = 0;
820         }
821         break;
822 
823         case MIDI_MARKER:
824             break;
825 
826         case MIDI_CUE_POINT:
827             break; /* don't care much for text events */
828 
829         case MIDI_EOT:
830             if(mf->varlen != 0)
831             {
832                 FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
833                 result = FLUID_FAILED;
834                 break;
835             }
836 
837             mf->eot = 1;
838             evt = new_fluid_midi_event();
839 
840             if(evt == NULL)
841             {
842                 FLUID_LOG(FLUID_ERR, "Out of memory");
843                 result = FLUID_FAILED;
844                 break;
845             }
846 
847             evt->dtime = mf->dtime;
848             evt->type = MIDI_EOT;
849             fluid_track_add_event(track, evt);
850             mf->dtime = 0;
851             break;
852 
853         case MIDI_SET_TEMPO:
854             if(mf->varlen != 3)
855             {
856                 FLUID_LOG(FLUID_ERR,
857                           "Invalid length for SetTempo meta event");
858                 result = FLUID_FAILED;
859                 break;
860             }
861 
862             tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
863             evt = new_fluid_midi_event();
864 
865             if(evt == NULL)
866             {
867                 FLUID_LOG(FLUID_ERR, "Out of memory");
868                 result = FLUID_FAILED;
869                 break;
870             }
871 
872             evt->dtime = mf->dtime;
873             evt->type = MIDI_SET_TEMPO;
874             evt->channel = 0;
875             evt->param1 = tempo;
876             evt->param2 = 0;
877             fluid_track_add_event(track, evt);
878             mf->dtime = 0;
879             break;
880 
881         case MIDI_SMPTE_OFFSET:
882             if(mf->varlen != 5)
883             {
884                 FLUID_LOG(FLUID_ERR,
885                           "Invalid length for SMPTE Offset meta event");
886                 result = FLUID_FAILED;
887                 break;
888             }
889 
890             break; /* we don't use smtp */
891 
892         case MIDI_TIME_SIGNATURE:
893             if(mf->varlen != 4)
894             {
895                 FLUID_LOG(FLUID_ERR,
896                           "Invalid length for TimeSignature meta event");
897                 result = FLUID_FAILED;
898                 break;
899             }
900 
901             nominator = metadata[0];
902             denominator = pow(2.0, (double) metadata[1]);
903             clocks = metadata[2];
904             notes = metadata[3];
905 
906             FLUID_LOG(FLUID_DBG,
907                       "signature=%d/%d, metronome=%d, 32nd-notes=%d",
908                       nominator, denominator, clocks, notes);
909 
910             break;
911 
912         case MIDI_KEY_SIGNATURE:
913             if(mf->varlen != 2)
914             {
915                 FLUID_LOG(FLUID_ERR,
916                           "Invalid length for KeySignature meta event");
917                 result = FLUID_FAILED;
918                 break;
919             }
920 
921             /* We don't care about key signatures anyway */
922             /* sf = metadata[0];
923             mi = metadata[1]; */
924             break;
925 
926         case MIDI_SEQUENCER_EVENT:
927             break;
928 
929         default:
930             break;
931         }
932 
933         if(dyn_buf)
934         {
935             FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
936             FLUID_FREE(dyn_buf);
937         }
938 
939         return result;
940 
941     }
942     else     /* channel messages */
943     {
944 
945         type = status & 0xf0;
946         channel = status & 0x0f;
947 
948         /* all channel message have at least 1 byte of associated data */
949         if((param1 = fluid_midi_file_getc(mf)) < 0)
950         {
951             FLUID_LOG(FLUID_ERR, "Unexpected end of file");
952             return FLUID_FAILED;
953         }
954 
955         switch(type)
956         {
957 
958         case NOTE_ON:
959             if((param2 = fluid_midi_file_getc(mf)) < 0)
960             {
961                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
962                 return FLUID_FAILED;
963             }
964 
965             break;
966 
967         case NOTE_OFF:
968             if((param2 = fluid_midi_file_getc(mf)) < 0)
969             {
970                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
971                 return FLUID_FAILED;
972             }
973 
974             break;
975 
976         case KEY_PRESSURE:
977             if((param2 = fluid_midi_file_getc(mf)) < 0)
978             {
979                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
980                 return FLUID_FAILED;
981             }
982 
983             break;
984 
985         case CONTROL_CHANGE:
986             if((param2 = fluid_midi_file_getc(mf)) < 0)
987             {
988                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
989                 return FLUID_FAILED;
990             }
991 
992             break;
993 
994         case PROGRAM_CHANGE:
995             break;
996 
997         case CHANNEL_PRESSURE:
998             break;
999 
1000         case PITCH_BEND:
1001             if((param2 = fluid_midi_file_getc(mf)) < 0)
1002             {
1003                 FLUID_LOG(FLUID_ERR, "Unexpected end of file");
1004                 return FLUID_FAILED;
1005             }
1006 
1007             param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
1008             param2 = 0;
1009             break;
1010 
1011         default:
1012             /* Can't possibly happen !? */
1013             FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
1014             return FLUID_FAILED;
1015         }
1016 
1017         evt = new_fluid_midi_event();
1018 
1019         if(evt == NULL)
1020         {
1021             FLUID_LOG(FLUID_ERR, "Out of memory");
1022             return FLUID_FAILED;
1023         }
1024 
1025         evt->dtime = mf->dtime;
1026         evt->type = type;
1027         evt->channel = channel;
1028         evt->param1 = param1;
1029         evt->param2 = param2;
1030         fluid_track_add_event(track, evt);
1031         mf->dtime = 0;
1032     }
1033 
1034     return FLUID_OK;
1035 }
1036 
1037 /*
1038  * fluid_midi_file_get_division
1039  */
1040 int
fluid_midi_file_get_division(fluid_midi_file * midifile)1041 fluid_midi_file_get_division(fluid_midi_file *midifile)
1042 {
1043     return midifile->division;
1044 }
1045 
1046 /******************************************************
1047  *
1048  *     fluid_track_t
1049  */
1050 
1051 /**
1052  * Create a MIDI event structure.
1053  * @return New MIDI event structure or NULL when out of memory.
1054  */
1055 fluid_midi_event_t *
new_fluid_midi_event()1056 new_fluid_midi_event()
1057 {
1058     fluid_midi_event_t *evt;
1059     evt = FLUID_NEW(fluid_midi_event_t);
1060 
1061     if(evt == NULL)
1062     {
1063         FLUID_LOG(FLUID_ERR, "Out of memory");
1064         return NULL;
1065     }
1066 
1067     evt->dtime = 0;
1068     evt->type = 0;
1069     evt->channel = 0;
1070     evt->param1 = 0;
1071     evt->param2 = 0;
1072     evt->next = NULL;
1073     evt->paramptr = NULL;
1074     return evt;
1075 }
1076 
1077 /**
1078  * Delete MIDI event structure.
1079  * @param evt MIDI event structure
1080  */
1081 void
delete_fluid_midi_event(fluid_midi_event_t * evt)1082 delete_fluid_midi_event(fluid_midi_event_t *evt)
1083 {
1084     fluid_midi_event_t *temp;
1085     fluid_return_if_fail(evt != NULL);
1086 
1087     while(evt)
1088     {
1089         temp = evt->next;
1090 
1091         /* Dynamic SYSEX event? - free (param2 indicates if dynamic) */
1092         if((evt->type == MIDI_SYSEX || (evt-> type == MIDI_TEXT) || (evt->type == MIDI_LYRIC)) &&
1093                 evt->paramptr && evt->param2)
1094         {
1095             FLUID_FREE(evt->paramptr);
1096         }
1097 
1098         FLUID_FREE(evt);
1099         evt = temp;
1100     }
1101 }
1102 
1103 /**
1104  * Get the event type field of a MIDI event structure.
1105  * @param evt MIDI event structure
1106  * @return Event type field (MIDI status byte without channel)
1107  */
1108 int
fluid_midi_event_get_type(fluid_midi_event_t * evt)1109 fluid_midi_event_get_type(fluid_midi_event_t *evt)
1110 {
1111     return evt->type;
1112 }
1113 
1114 /**
1115  * Set the event type field of a MIDI event structure.
1116  * @param evt MIDI event structure
1117  * @param type Event type field (MIDI status byte without channel)
1118  * @return Always returns #FLUID_OK
1119  */
1120 int
fluid_midi_event_set_type(fluid_midi_event_t * evt,int type)1121 fluid_midi_event_set_type(fluid_midi_event_t *evt, int type)
1122 {
1123     evt->type = type;
1124     return FLUID_OK;
1125 }
1126 
1127 /**
1128  * Get the channel field of a MIDI event structure.
1129  * @param evt MIDI event structure
1130  * @return Channel field
1131  */
1132 int
fluid_midi_event_get_channel(fluid_midi_event_t * evt)1133 fluid_midi_event_get_channel(fluid_midi_event_t *evt)
1134 {
1135     return evt->channel;
1136 }
1137 
1138 /**
1139  * Set the channel field of a MIDI event structure.
1140  * @param evt MIDI event structure
1141  * @param chan MIDI channel field
1142  * @return Always returns #FLUID_OK
1143  */
1144 int
fluid_midi_event_set_channel(fluid_midi_event_t * evt,int chan)1145 fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan)
1146 {
1147     evt->channel = chan;
1148     return FLUID_OK;
1149 }
1150 
1151 /**
1152  * Get the key field of a MIDI event structure.
1153  * @param evt MIDI event structure
1154  * @return MIDI note number (0-127)
1155  */
1156 int
fluid_midi_event_get_key(fluid_midi_event_t * evt)1157 fluid_midi_event_get_key(fluid_midi_event_t *evt)
1158 {
1159     return evt->param1;
1160 }
1161 
1162 /**
1163  * Set the key field of a MIDI event structure.
1164  * @param evt MIDI event structure
1165  * @param v MIDI note number (0-127)
1166  * @return Always returns #FLUID_OK
1167  */
1168 int
fluid_midi_event_set_key(fluid_midi_event_t * evt,int v)1169 fluid_midi_event_set_key(fluid_midi_event_t *evt, int v)
1170 {
1171     evt->param1 = v;
1172     return FLUID_OK;
1173 }
1174 
1175 /**
1176  * Get the velocity field of a MIDI event structure.
1177  * @param evt MIDI event structure
1178  * @return MIDI velocity number (0-127)
1179  */
1180 int
fluid_midi_event_get_velocity(fluid_midi_event_t * evt)1181 fluid_midi_event_get_velocity(fluid_midi_event_t *evt)
1182 {
1183     return evt->param2;
1184 }
1185 
1186 /**
1187  * Set the velocity field of a MIDI event structure.
1188  * @param evt MIDI event structure
1189  * @param v MIDI velocity value
1190  * @return Always returns #FLUID_OK
1191  */
1192 int
fluid_midi_event_set_velocity(fluid_midi_event_t * evt,int v)1193 fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int v)
1194 {
1195     evt->param2 = v;
1196     return FLUID_OK;
1197 }
1198 
1199 /**
1200  * Get the control number of a MIDI event structure.
1201  * @param evt MIDI event structure
1202  * @return MIDI control number
1203  */
1204 int
fluid_midi_event_get_control(fluid_midi_event_t * evt)1205 fluid_midi_event_get_control(fluid_midi_event_t *evt)
1206 {
1207     return evt->param1;
1208 }
1209 
1210 /**
1211  * Set the control field of a MIDI event structure.
1212  * @param evt MIDI event structure
1213  * @param v MIDI control number
1214  * @return Always returns #FLUID_OK
1215  */
1216 int
fluid_midi_event_set_control(fluid_midi_event_t * evt,int v)1217 fluid_midi_event_set_control(fluid_midi_event_t *evt, int v)
1218 {
1219     evt->param1 = v;
1220     return FLUID_OK;
1221 }
1222 
1223 /**
1224  * Get the value field from a MIDI event structure.
1225  * @param evt MIDI event structure
1226  * @return Value field
1227  */
1228 int
fluid_midi_event_get_value(fluid_midi_event_t * evt)1229 fluid_midi_event_get_value(fluid_midi_event_t *evt)
1230 {
1231     return evt->param2;
1232 }
1233 
1234 /**
1235  * Set the value field of a MIDI event structure.
1236  * @param evt MIDI event structure
1237  * @param v Value to assign
1238  * @return Always returns #FLUID_OK
1239  */
1240 int
fluid_midi_event_set_value(fluid_midi_event_t * evt,int v)1241 fluid_midi_event_set_value(fluid_midi_event_t *evt, int v)
1242 {
1243     evt->param2 = v;
1244     return FLUID_OK;
1245 }
1246 
1247 /**
1248  * Get the program field of a MIDI event structure.
1249  * @param evt MIDI event structure
1250  * @return MIDI program number (0-127)
1251  */
1252 int
fluid_midi_event_get_program(fluid_midi_event_t * evt)1253 fluid_midi_event_get_program(fluid_midi_event_t *evt)
1254 {
1255     return evt->param1;
1256 }
1257 
1258 /**
1259  * Set the program field of a MIDI event structure.
1260  * @param evt MIDI event structure
1261  * @param val MIDI program number (0-127)
1262  * @return Always returns #FLUID_OK
1263  */
1264 int
fluid_midi_event_set_program(fluid_midi_event_t * evt,int val)1265 fluid_midi_event_set_program(fluid_midi_event_t *evt, int val)
1266 {
1267     evt->param1 = val;
1268     return FLUID_OK;
1269 }
1270 
1271 /**
1272  * Get the pitch field of a MIDI event structure.
1273  * @param evt MIDI event structure
1274  * @return Pitch value (14 bit value, 0-16383, 8192 is center)
1275  */
1276 int
fluid_midi_event_get_pitch(fluid_midi_event_t * evt)1277 fluid_midi_event_get_pitch(fluid_midi_event_t *evt)
1278 {
1279     return evt->param1;
1280 }
1281 
1282 /**
1283  * Set the pitch field of a MIDI event structure.
1284  * @param evt MIDI event structure
1285  * @param val Pitch value (14 bit value, 0-16383, 8192 is center)
1286  * @return Always returns FLUID_OK
1287  */
1288 int
fluid_midi_event_set_pitch(fluid_midi_event_t * evt,int val)1289 fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val)
1290 {
1291     evt->param1 = val;
1292     return FLUID_OK;
1293 }
1294 
1295 /**
1296  * Assign sysex data to a MIDI event structure.
1297  * @param evt MIDI event structure
1298  * @param data Pointer to SYSEX data
1299  * @param size Size of SYSEX data in bytes
1300  * @param dynamic TRUE if the SYSEX data has been dynamically allocated and
1301  *   should be freed when the event is freed (only applies if event gets destroyed
1302  *   with delete_fluid_midi_event())
1303  * @return Always returns #FLUID_OK
1304  */
1305 int
fluid_midi_event_set_sysex(fluid_midi_event_t * evt,void * data,int size,int dynamic)1306 fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1307 {
1308     fluid_midi_event_set_sysex_LOCAL(evt, MIDI_SYSEX, data, size, dynamic);
1309     return FLUID_OK;
1310 }
1311 
1312 /**
1313  * Assign text data to a MIDI event structure.
1314  * @param evt MIDI event structure
1315  * @param data Pointer to text data
1316  * @param size Size of text data in bytes
1317  * @param dynamic TRUE if the data has been dynamically allocated and
1318  *   should be freed when the event is freed via delete_fluid_midi_event()
1319  * @return Always returns #FLUID_OK
1320  *
1321  * @since 2.0.0
1322  */
1323 int
fluid_midi_event_set_text(fluid_midi_event_t * evt,void * data,int size,int dynamic)1324 fluid_midi_event_set_text(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1325 {
1326     fluid_midi_event_set_sysex_LOCAL(evt, MIDI_TEXT, data, size, dynamic);
1327     return FLUID_OK;
1328 }
1329 
1330 /**
1331  * Get the text of a MIDI event structure.
1332  * @param evt MIDI event structure
1333  * @param data Pointer to return text data on.
1334  * @param size Pointer to return text size on.
1335  * @return Returns #FLUID_OK if \p data and \p size previously set by
1336  * fluid_midi_event_set_text() have been successfully retrieved.
1337  * Else #FLUID_FAILED is returned and \p data and \p size are not changed.
1338  * @since 2.0.3
1339  */
fluid_midi_event_get_text(fluid_midi_event_t * evt,void ** data,int * size)1340 int fluid_midi_event_get_text(fluid_midi_event_t *evt, void **data, int *size)
1341 {
1342     fluid_return_val_if_fail(evt != NULL, FLUID_FAILED);
1343     fluid_return_val_if_fail(evt->type == MIDI_TEXT, FLUID_FAILED);
1344 
1345     fluid_midi_event_get_sysex_LOCAL(evt, data, size);
1346     return FLUID_OK;
1347 }
1348 
1349 /**
1350  * Assign lyric data to a MIDI event structure.
1351  * @param evt MIDI event structure
1352  * @param data Pointer to lyric data
1353  * @param size Size of lyric data in bytes
1354  * @param dynamic TRUE if the data has been dynamically allocated and
1355  *   should be freed when the event is freed via delete_fluid_midi_event()
1356  * @return Always returns #FLUID_OK
1357  *
1358  * @since 2.0.0
1359  */
1360 int
fluid_midi_event_set_lyrics(fluid_midi_event_t * evt,void * data,int size,int dynamic)1361 fluid_midi_event_set_lyrics(fluid_midi_event_t *evt, void *data, int size, int dynamic)
1362 {
1363     fluid_midi_event_set_sysex_LOCAL(evt, MIDI_LYRIC, data, size, dynamic);
1364     return FLUID_OK;
1365 }
1366 
1367 /**
1368  * Get the lyric of a MIDI event structure.
1369  * @param evt MIDI event structure
1370  * @param data Pointer to return lyric data on.
1371  * @param size Pointer to return lyric size on.
1372  * @return Returns #FLUID_OK if \p data and \p size previously set by
1373  * fluid_midi_event_set_lyrics() have been successfully retrieved.
1374  * Else #FLUID_FAILED is returned and \p data and \p size are not changed.
1375  * @since 2.0.3
1376  */
fluid_midi_event_get_lyrics(fluid_midi_event_t * evt,void ** data,int * size)1377 int fluid_midi_event_get_lyrics(fluid_midi_event_t *evt, void **data, int *size)
1378 {
1379     fluid_return_val_if_fail(evt != NULL, FLUID_FAILED);
1380     fluid_return_val_if_fail(evt->type == MIDI_LYRIC, FLUID_FAILED);
1381 
1382     fluid_midi_event_get_sysex_LOCAL(evt, data, size);
1383     return FLUID_OK;
1384 }
1385 
fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t * evt,int type,void * data,int size,int dynamic)1386 static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic)
1387 {
1388     evt->type = type;
1389     evt->paramptr = data;
1390     evt->param1 = size;
1391     evt->param2 = dynamic;
1392 }
1393 
fluid_midi_event_get_sysex_LOCAL(fluid_midi_event_t * evt,void ** data,int * size)1394 static void fluid_midi_event_get_sysex_LOCAL(fluid_midi_event_t *evt, void **data, int *size)
1395 {
1396     if(data)
1397     {
1398         *data = evt->paramptr;
1399     }
1400 
1401     if(size)
1402     {
1403         *size = evt->param1;
1404     }
1405 }
1406 
1407 /******************************************************
1408  *
1409  *     fluid_track_t
1410  */
1411 
1412 /*
1413  * new_fluid_track
1414  */
1415 fluid_track_t *
new_fluid_track(int num)1416 new_fluid_track(int num)
1417 {
1418     fluid_track_t *track;
1419     track = FLUID_NEW(fluid_track_t);
1420 
1421     if(track == NULL)
1422     {
1423         return NULL;
1424     }
1425 
1426     track->name = NULL;
1427     track->num = num;
1428     track->first = NULL;
1429     track->cur = NULL;
1430     track->last = NULL;
1431     track->ticks = 0;
1432     return track;
1433 }
1434 
1435 /*
1436  * delete_fluid_track
1437  */
1438 void
delete_fluid_track(fluid_track_t * track)1439 delete_fluid_track(fluid_track_t *track)
1440 {
1441     fluid_return_if_fail(track != NULL);
1442 
1443     FLUID_FREE(track->name);
1444     delete_fluid_midi_event(track->first);
1445     FLUID_FREE(track);
1446 }
1447 
1448 /*
1449  * fluid_track_set_name
1450  */
1451 int
fluid_track_set_name(fluid_track_t * track,char * name)1452 fluid_track_set_name(fluid_track_t *track, char *name)
1453 {
1454     size_t len;
1455 
1456     if(track->name != NULL)
1457     {
1458         FLUID_FREE(track->name);
1459     }
1460 
1461     if(name == NULL)
1462     {
1463         track->name = NULL;
1464         return FLUID_OK;
1465     }
1466 
1467     len = FLUID_STRLEN(name);
1468     track->name = FLUID_MALLOC(len + 1);
1469 
1470     if(track->name == NULL)
1471     {
1472         FLUID_LOG(FLUID_ERR, "Out of memory");
1473         return FLUID_FAILED;
1474     }
1475 
1476     FLUID_STRCPY(track->name, name);
1477     return FLUID_OK;
1478 }
1479 
1480 /*
1481  * fluid_track_get_duration
1482  */
1483 int
fluid_track_get_duration(fluid_track_t * track)1484 fluid_track_get_duration(fluid_track_t *track)
1485 {
1486     int time = 0;
1487     fluid_midi_event_t *evt = track->first;
1488 
1489     while(evt != NULL)
1490     {
1491         time += evt->dtime;
1492         evt = evt->next;
1493     }
1494 
1495     return time;
1496 }
1497 
1498 /*
1499  * fluid_track_add_event
1500  */
1501 int
fluid_track_add_event(fluid_track_t * track,fluid_midi_event_t * evt)1502 fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt)
1503 {
1504     evt->next = NULL;
1505 
1506     if(track->first == NULL)
1507     {
1508         track->first = evt;
1509         track->cur = evt;
1510         track->last = evt;
1511     }
1512     else
1513     {
1514         track->last->next = evt;
1515         track->last = evt;
1516     }
1517 
1518     return FLUID_OK;
1519 }
1520 
1521 /*
1522  * fluid_track_next_event
1523  */
1524 fluid_midi_event_t *
fluid_track_next_event(fluid_track_t * track)1525 fluid_track_next_event(fluid_track_t *track)
1526 {
1527     if(track->cur != NULL)
1528     {
1529         track->cur = track->cur->next;
1530     }
1531 
1532     return track->cur;
1533 }
1534 
1535 /*
1536  * fluid_track_reset
1537  */
1538 int
fluid_track_reset(fluid_track_t * track)1539 fluid_track_reset(fluid_track_t *track)
1540 {
1541     track->ticks = 0;
1542     track->cur = track->first;
1543     return FLUID_OK;
1544 }
1545 
1546 /*
1547  * fluid_track_send_events
1548  */
1549 static void
fluid_track_send_events(fluid_track_t * track,fluid_synth_t * synth,fluid_player_t * player,unsigned int ticks,int seek_ticks)1550 fluid_track_send_events(fluid_track_t *track,
1551                         fluid_synth_t *synth,
1552                         fluid_player_t *player,
1553                         unsigned int ticks,
1554                         int seek_ticks
1555                        )
1556 {
1557     fluid_midi_event_t *event;
1558     int seeking = seek_ticks >= 0;
1559 
1560     if(seeking)
1561     {
1562         ticks = seek_ticks; /* update target ticks */
1563 
1564         if(track->ticks > ticks)
1565         {
1566             fluid_track_reset(track);    /* reset track if seeking backwards */
1567         }
1568     }
1569 
1570     while(1)
1571     {
1572 
1573         event = track->cur;
1574 
1575         if(event == NULL)
1576         {
1577             return;
1578         }
1579 
1580         /*         printf("track=%02d\tticks=%05u\ttrack=%05u\tdtime=%05u\tnext=%05u\n", */
1581         /*                track->num, */
1582         /*                ticks, */
1583         /*                track->ticks, */
1584         /*                event->dtime, */
1585         /*                track->ticks + event->dtime); */
1586 
1587         if(track->ticks + event->dtime > ticks)
1588         {
1589             return;
1590         }
1591 
1592         track->ticks += event->dtime;
1593 
1594         if(!player || event->type == MIDI_EOT)
1595         {
1596             /* don't send EOT events to the callback */
1597         }
1598         else if(seeking && track->ticks != ticks && (event->type == NOTE_ON || event->type == NOTE_OFF))
1599         {
1600             /* skip on/off messages */
1601         }
1602         else
1603         {
1604             if(player->playback_callback)
1605             {
1606                 player->playback_callback(player->playback_userdata, event);
1607                 if(event->type == NOTE_ON && event->param2 != 0 && !player->channel_isplaying[event->channel])
1608                 {
1609                     player->channel_isplaying[event->channel] = TRUE;
1610                 }
1611             }
1612         }
1613 
1614         if(event->type == MIDI_SET_TEMPO && player != NULL)
1615         {
1616             /* memorize the tempo change value coming from the MIDI file */
1617             fluid_atomic_int_set(&player->miditempo, event->param1);
1618             fluid_player_update_tempo(player);
1619         }
1620 
1621         fluid_track_next_event(track);
1622 
1623     }
1624 }
1625 
1626 /******************************************************
1627  *
1628  *     fluid_player
1629  */
1630 static void
fluid_player_handle_reset_synth(void * data,const char * name,int value)1631 fluid_player_handle_reset_synth(void *data, const char *name, int value)
1632 {
1633     fluid_player_t *player = data;
1634     fluid_return_if_fail(player != NULL);
1635 
1636     player->reset_synth_between_songs = value;
1637 }
1638 
1639 /**
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)
1643  */
1644 fluid_player_t *
new_fluid_player(fluid_synth_t * synth)1645 new_fluid_player(fluid_synth_t *synth)
1646 {
1647     int i;
1648     fluid_player_t *player;
1649     player = FLUID_NEW(fluid_player_t);
1650 
1651     if(player == NULL)
1652     {
1653         FLUID_LOG(FLUID_ERR, "Out of memory");
1654         return NULL;
1655     }
1656 
1657     fluid_atomic_int_set(&player->status, FLUID_PLAYER_READY);
1658     fluid_atomic_int_set(&player->stopping, 0);
1659     player->loop = 1;
1660     player->ntracks = 0;
1661 
1662     for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1663     {
1664         player->track[i] = NULL;
1665     }
1666 
1667     player->synth = synth;
1668     player->system_timer = NULL;
1669     player->sample_timer = NULL;
1670     player->playlist = NULL;
1671     player->currentfile = NULL;
1672     player->division = 0;
1673 
1674     /* internal tempo (from MIDI file) in micro seconds per quarter note */
1675     player->sync_mode = 1; /* the player follows internal tempo change */
1676     player->miditempo = 500000;
1677     /* external tempo in micro seconds per quarter note */
1678     player->exttempo = 500000;
1679     /* tempo multiplier */
1680     player->multempo = 1.0F;
1681 
1682     player->deltatime = 4.0;
1683     player->cur_msec = 0;
1684     player->cur_ticks = 0;
1685     player->last_callback_ticks = -1;
1686     fluid_atomic_int_set(&player->seek_ticks, -1);
1687     fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth);
1688     fluid_player_set_tick_callback(player, NULL, NULL);
1689     player->use_system_timer = fluid_settings_str_equal(synth->settings,
1690                                "player.timing-source", "system");
1691     if(player->use_system_timer)
1692     {
1693         player->system_timer = new_fluid_timer((int) player->deltatime,
1694                                                fluid_player_callback, player, TRUE, FALSE, TRUE);
1695 
1696         if(player->system_timer == NULL)
1697         {
1698             goto err;
1699         }
1700     }
1701     else
1702     {
1703         player->sample_timer = new_fluid_sample_timer(player->synth,
1704                                fluid_player_callback, player);
1705 
1706         if(player->sample_timer == NULL)
1707         {
1708             goto err;
1709         }
1710     }
1711 
1712     fluid_settings_getint(synth->settings, "player.reset-synth", &i);
1713     fluid_player_handle_reset_synth(player, NULL, i);
1714 
1715     fluid_settings_callback_int(synth->settings, "player.reset-synth",
1716                                 fluid_player_handle_reset_synth, player);
1717 
1718     return player;
1719 
1720 err:
1721     delete_fluid_player(player);
1722     return NULL;
1723 }
1724 
1725 /**
1726  * Delete a MIDI player instance.
1727  * @param player MIDI player instance
1728  * @warning Do not call when the synthesizer associated to this \p player renders audio,
1729  * i.e. an audio driver is running or any other synthesizer thread concurrently calls
1730  * fluid_synth_process() or fluid_synth_nwrite_float() or fluid_synth_write_*() !
1731  */
1732 void
delete_fluid_player(fluid_player_t * player)1733 delete_fluid_player(fluid_player_t *player)
1734 {
1735     fluid_list_t *q;
1736     fluid_playlist_item *pi;
1737 
1738     fluid_return_if_fail(player != NULL);
1739 
1740     fluid_settings_callback_int(player->synth->settings, "player.reset-synth",
1741                                 NULL, NULL);
1742 
1743     fluid_player_stop(player);
1744     fluid_player_reset(player);
1745 
1746     delete_fluid_timer(player->system_timer);
1747     delete_fluid_sample_timer(player->synth, player->sample_timer);
1748 
1749     while(player->playlist != NULL)
1750     {
1751         q = player->playlist->next;
1752         pi = (fluid_playlist_item *) player->playlist->data;
1753         FLUID_FREE(pi->filename);
1754         FLUID_FREE(pi->buffer);
1755         FLUID_FREE(pi);
1756         delete1_fluid_list(player->playlist);
1757         player->playlist = q;
1758     }
1759 
1760     FLUID_FREE(player);
1761 }
1762 
1763 /**
1764  * Registers settings related to the MIDI player
1765  */
1766 void
fluid_player_settings(fluid_settings_t * settings)1767 fluid_player_settings(fluid_settings_t *settings)
1768 {
1769     /* player.timing-source can be either "system" (use system timer)
1770      or "sample" (use timer based on number of written samples) */
1771     fluid_settings_register_str(settings, "player.timing-source", "sample", 0);
1772     fluid_settings_add_option(settings, "player.timing-source", "sample");
1773     fluid_settings_add_option(settings, "player.timing-source", "system");
1774 
1775     /* Selects whether the player should reset the synth between songs, or not. */
1776     fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1, FLUID_HINT_TOGGLED);
1777 }
1778 
1779 
1780 int
fluid_player_reset(fluid_player_t * player)1781 fluid_player_reset(fluid_player_t *player)
1782 {
1783     int i;
1784 
1785     for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++)
1786     {
1787         if(player->track[i] != NULL)
1788         {
1789             delete_fluid_track(player->track[i]);
1790             player->track[i] = NULL;
1791         }
1792     }
1793 
1794     for(i = 0; i < MAX_NUMBER_OF_CHANNELS; i++)
1795     {
1796         player->channel_isplaying[i] = FALSE;
1797     }
1798 
1799     /*    player->current_file = NULL; */
1800     /*    player->status = FLUID_PLAYER_READY; */
1801     /*    player->loop = 1; */
1802     player->ntracks = 0;
1803     player->division = 0;
1804     player->miditempo = 500000;
1805     player->deltatime = 4.0;
1806     return 0;
1807 }
1808 
1809 /*
1810  * fluid_player_add_track
1811  */
1812 int
fluid_player_add_track(fluid_player_t * player,fluid_track_t * track)1813 fluid_player_add_track(fluid_player_t *player, fluid_track_t *track)
1814 {
1815     if(player->ntracks < MAX_NUMBER_OF_TRACKS)
1816     {
1817         player->track[player->ntracks++] = track;
1818         return FLUID_OK;
1819     }
1820     else
1821     {
1822         return FLUID_FAILED;
1823     }
1824 }
1825 
1826 /**
1827  * Change the MIDI callback function.
1828  *
1829  * @param player MIDI player instance
1830  * @param handler Pointer to callback function
1831  * @param handler_data Parameter sent to the callback function
1832  * @returns FLUID_OK
1833  *
1834  * This is usually set to fluid_synth_handle_midi_event(), but can optionally
1835  * be changed to a user-defined function instead, for intercepting all MIDI
1836  * messages sent to the synth. You can also use a midi router as the callback
1837  * function to modify the MIDI messages before sending them to the synth.
1838  *
1839  * @since 1.1.4
1840  */
1841 int
fluid_player_set_playback_callback(fluid_player_t * player,handle_midi_event_func_t handler,void * handler_data)1842 fluid_player_set_playback_callback(fluid_player_t *player,
1843                                    handle_midi_event_func_t handler, void *handler_data)
1844 {
1845     player->playback_callback = handler;
1846     player->playback_userdata = handler_data;
1847     return FLUID_OK;
1848 }
1849 
1850 /**
1851  * Add a listener function for every MIDI tick change.
1852  *
1853  * @param player MIDI player instance
1854  * @param handler Pointer to callback function
1855  * @param handler_data Opaque parameter to be sent to the callback function
1856  * @returns #FLUID_OK
1857  *
1858  * This callback is not set by default, but can optionally
1859  * be changed to a user-defined function for intercepting all MIDI
1860  * tick changes and react to them with precision.
1861  *
1862  * @since 2.2.0
1863  */
1864 int
fluid_player_set_tick_callback(fluid_player_t * player,handle_midi_tick_func_t handler,void * handler_data)1865 fluid_player_set_tick_callback(fluid_player_t *player, handle_midi_tick_func_t handler, void *handler_data)
1866 {
1867     player->tick_callback = handler;
1868     player->tick_userdata = handler_data;
1869     return FLUID_OK;
1870 }
1871 
1872 /**
1873  * Add a MIDI file to a player queue.
1874  * @param player MIDI player instance
1875  * @param midifile File name of the MIDI file to add
1876  * @return #FLUID_OK or #FLUID_FAILED
1877  */
1878 int
fluid_player_add(fluid_player_t * player,const char * midifile)1879 fluid_player_add(fluid_player_t *player, const char *midifile)
1880 {
1881     fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1882     char *f = FLUID_STRDUP(midifile);
1883 
1884     if(!pi || !f)
1885     {
1886         FLUID_FREE(pi);
1887         FLUID_FREE(f);
1888         FLUID_LOG(FLUID_PANIC, "Out of memory");
1889         return FLUID_FAILED;
1890     }
1891 
1892     pi->filename = f;
1893     pi->buffer = NULL;
1894     pi->buffer_len = 0;
1895     player->playlist = fluid_list_append(player->playlist, pi);
1896     return FLUID_OK;
1897 }
1898 
1899 /**
1900  * Add a MIDI file to a player queue, from a buffer in memory.
1901  * @param player MIDI player instance
1902  * @param buffer Pointer to memory containing the bytes of a complete MIDI
1903  *   file. The data is copied, so the caller may free or modify it immediately
1904  *   without affecting the playlist.
1905  * @param len Length of the buffer, in bytes.
1906  * @return #FLUID_OK or #FLUID_FAILED
1907  */
1908 int
fluid_player_add_mem(fluid_player_t * player,const void * buffer,size_t len)1909 fluid_player_add_mem(fluid_player_t *player, const void *buffer, size_t len)
1910 {
1911     /* Take a copy of the buffer, so the caller can free immediately. */
1912     fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item));
1913     void *buf_copy = FLUID_MALLOC(len);
1914 
1915     if(!pi || !buf_copy)
1916     {
1917         FLUID_FREE(pi);
1918         FLUID_FREE(buf_copy);
1919         FLUID_LOG(FLUID_PANIC, "Out of memory");
1920         return FLUID_FAILED;
1921     }
1922 
1923     FLUID_MEMCPY(buf_copy, buffer, len);
1924     pi->filename = NULL;
1925     pi->buffer = buf_copy;
1926     pi->buffer_len = len;
1927     player->playlist = fluid_list_append(player->playlist, pi);
1928     return FLUID_OK;
1929 }
1930 
1931 /*
1932  * fluid_player_load
1933  */
1934 int
fluid_player_load(fluid_player_t * player,fluid_playlist_item * item)1935 fluid_player_load(fluid_player_t *player, fluid_playlist_item *item)
1936 {
1937     fluid_midi_file *midifile;
1938     char *buffer;
1939     size_t buffer_length;
1940     int buffer_owned;
1941 
1942     if(item->filename != NULL)
1943     {
1944         fluid_file fp;
1945         /* This file is specified by filename; load the file from disk */
1946         FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__,
1947                   item->filename);
1948         /* Read the entire contents of the file into the buffer */
1949         fp = FLUID_FOPEN(item->filename, "rb");
1950 
1951         if(fp == NULL)
1952         {
1953             FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file");
1954             return FLUID_FAILED;
1955         }
1956 
1957         buffer = fluid_file_read_full(fp, &buffer_length);
1958 
1959         FLUID_FCLOSE(fp);
1960 
1961         if(buffer == NULL)
1962         {
1963             return FLUID_FAILED;
1964         }
1965 
1966         buffer_owned = 1;
1967     }
1968     else
1969     {
1970         /* This file is specified by a pre-loaded buffer; load from memory */
1971         FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile from memory (%p)",
1972                   __FILE__, __LINE__, item->buffer);
1973         buffer = (char *) item->buffer;
1974         buffer_length = item->buffer_len;
1975         /* Do not free the buffer (it is owned by the playlist) */
1976         buffer_owned = 0;
1977     }
1978 
1979     midifile = new_fluid_midi_file(buffer, buffer_length);
1980 
1981     if(midifile == NULL)
1982     {
1983         if(buffer_owned)
1984         {
1985             FLUID_FREE(buffer);
1986         }
1987 
1988         return FLUID_FAILED;
1989     }
1990 
1991     player->division = fluid_midi_file_get_division(midifile);
1992     fluid_player_update_tempo(player);  // Update deltatime
1993     /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */
1994 
1995     if(fluid_midi_file_load_tracks(midifile, player) != FLUID_OK)
1996     {
1997         if(buffer_owned)
1998         {
1999             FLUID_FREE(buffer);
2000         }
2001 
2002         delete_fluid_midi_file(midifile);
2003         return FLUID_FAILED;
2004     }
2005 
2006     delete_fluid_midi_file(midifile);
2007 
2008     if(buffer_owned)
2009     {
2010         FLUID_FREE(buffer);
2011     }
2012 
2013     return FLUID_OK;
2014 }
2015 
2016 void
fluid_player_advancefile(fluid_player_t * player)2017 fluid_player_advancefile(fluid_player_t *player)
2018 {
2019     if(player->playlist == NULL)
2020     {
2021         return; /* No files to play */
2022     }
2023 
2024     if(player->currentfile != NULL)
2025     {
2026         player->currentfile = fluid_list_next(player->currentfile);
2027     }
2028 
2029     if(player->currentfile == NULL)
2030     {
2031         if(player->loop == 0)
2032         {
2033             return; /* We're done playing */
2034         }
2035 
2036         if(player->loop > 0)
2037         {
2038             player->loop--;
2039         }
2040 
2041         player->currentfile = player->playlist;
2042     }
2043 }
2044 
2045 void
fluid_player_playlist_load(fluid_player_t * player,unsigned int msec)2046 fluid_player_playlist_load(fluid_player_t *player, unsigned int msec)
2047 {
2048     fluid_playlist_item *current_playitem;
2049     int i;
2050 
2051     do
2052     {
2053         fluid_player_advancefile(player);
2054 
2055         if(player->currentfile == NULL)
2056         {
2057             /* Failed to find next song, probably since we're finished */
2058             fluid_atomic_int_set(&player->status, FLUID_PLAYER_DONE);
2059             return;
2060         }
2061 
2062         fluid_player_reset(player);
2063         current_playitem = (fluid_playlist_item *) player->currentfile->data;
2064     }
2065     while(fluid_player_load(player, current_playitem) != FLUID_OK);
2066 
2067     /* Successfully loaded midi file */
2068 
2069     player->begin_msec = msec;
2070     player->start_msec = msec;
2071     player->start_ticks = 0;
2072     player->cur_ticks = 0;
2073 
2074     for(i = 0; i < player->ntracks; i++)
2075     {
2076         if(player->track[i] != NULL)
2077         {
2078             fluid_track_reset(player->track[i]);
2079         }
2080     }
2081 }
2082 
2083 /*
2084  * fluid_player_callback
2085  */
2086 int
fluid_player_callback(void * data,unsigned int msec)2087 fluid_player_callback(void *data, unsigned int msec)
2088 {
2089     int i;
2090     int loadnextfile;
2091     int status = FLUID_PLAYER_DONE;
2092     fluid_midi_event_t mute_event;
2093     fluid_player_t *player;
2094     fluid_synth_t *synth;
2095     player = (fluid_player_t *) data;
2096     synth = player->synth;
2097 
2098     loadnextfile = player->currentfile == NULL ? 1 : 0;
2099 
2100     fluid_midi_event_set_type(&mute_event, CONTROL_CHANGE);
2101     mute_event.param1 = ALL_SOUND_OFF;
2102     mute_event.param2 = 1;
2103 
2104     if(fluid_player_get_status(player) != FLUID_PLAYER_PLAYING)
2105     {
2106         if(fluid_atomic_int_get(&player->stopping))
2107         {
2108             for(i = 0; i < synth->midi_channels; i++)
2109             {
2110                 if(player->channel_isplaying[i])
2111                 {
2112                     fluid_midi_event_set_channel(&mute_event, i);
2113                     player->playback_callback(player->playback_userdata, &mute_event);
2114                 }
2115             }
2116             fluid_atomic_int_set(&player->stopping, 0);
2117         }
2118         return 1;
2119     }
2120     do
2121     {
2122         float deltatime;
2123         int seek_ticks;
2124 
2125         if(loadnextfile)
2126         {
2127             loadnextfile = 0;
2128             fluid_player_playlist_load(player, msec);
2129 
2130             if(player->currentfile == NULL)
2131             {
2132                 return 0;
2133             }
2134         }
2135 
2136         player->cur_msec = msec;
2137         deltatime = fluid_atomic_float_get(&player->deltatime);
2138         player->cur_ticks = (player->start_ticks
2139                              + (int)((double)(player->cur_msec - player->start_msec)
2140                                      / deltatime + 0.5)); /* 0.5 to average overall error when casting */
2141 
2142         seek_ticks = fluid_atomic_int_get(&player->seek_ticks);
2143         if(seek_ticks >= 0)
2144         {
2145             for(i = 0; i < synth->midi_channels; i++)
2146             {
2147                 if(player->channel_isplaying[i])
2148                 {
2149                     fluid_midi_event_set_channel(&mute_event, i);
2150                     player->playback_callback(player->playback_userdata, &mute_event);
2151                 }
2152             }
2153         }
2154 
2155         for(i = 0; i < player->ntracks; i++)
2156         {
2157             if(!fluid_track_eot(player->track[i]))
2158             {
2159                 status = FLUID_PLAYER_PLAYING;
2160                 fluid_track_send_events(player->track[i], synth, player, player->cur_ticks, seek_ticks);
2161             }
2162         }
2163 
2164         if(seek_ticks >= 0)
2165         {
2166             player->start_ticks = seek_ticks;   /* tick position of last tempo value (which is now) */
2167             player->cur_ticks = seek_ticks;
2168             player->begin_msec = msec;      /* only used to calculate the duration of playing */
2169             player->start_msec = msec;      /* should be the (synth)-time of the last tempo change */
2170             fluid_atomic_int_set(&player->seek_ticks, -1); /* clear seek_ticks */
2171         }
2172 
2173         if(status == FLUID_PLAYER_DONE)
2174         {
2175             FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__,
2176                       __LINE__, (msec - player->begin_msec) / 1000.0);
2177 
2178             if(player->reset_synth_between_songs)
2179             {
2180                 fluid_synth_system_reset(player->synth);
2181             }
2182 
2183             loadnextfile = 1;
2184         }
2185 
2186         if (player->tick_callback != NULL && player->last_callback_ticks != player->cur_ticks) {
2187             player->tick_callback(player->tick_userdata, player->cur_ticks);
2188             player->last_callback_ticks = player->cur_ticks;
2189         }
2190     }
2191     while(loadnextfile);
2192 
2193     /* do not update the status if the player has been stopped already */
2194     fluid_atomic_int_compare_and_exchange(&player->status, FLUID_PLAYER_PLAYING, status);
2195 
2196     return 1;
2197 }
2198 
2199 /**
2200  * Activates play mode for a MIDI player if not already playing.
2201  * @param player MIDI player instance
2202  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
2203  *
2204  * If the list of files added to the player has completed its requested number of loops,
2205  * the playlist will be restarted from the beginning with a loop count of 1.
2206  */
2207 int
fluid_player_play(fluid_player_t * player)2208 fluid_player_play(fluid_player_t *player)
2209 {
2210     if(fluid_player_get_status(player) == FLUID_PLAYER_PLAYING ||
2211        player->playlist == NULL)
2212     {
2213         return FLUID_OK;
2214     }
2215 
2216     if(!player->use_system_timer)
2217     {
2218         fluid_sample_timer_reset(player->synth, player->sample_timer);
2219     }
2220 
2221 	/* If we're at the end of the playlist and there are no loops left, loop once */
2222 	if(player->currentfile == NULL && player->loop == 0)
2223 	{
2224 		player->loop = 1;
2225 	}
2226 
2227     fluid_atomic_int_set(&player->status, FLUID_PLAYER_PLAYING);
2228 
2229     return FLUID_OK;
2230 }
2231 
2232 /**
2233  * Pauses the MIDI playback.
2234  *
2235  * @param player MIDI player instance
2236  * @return Always returns #FLUID_OK
2237  *
2238  * It will not rewind to the beginning of the file, use fluid_player_seek() for this purpose.
2239  */
2240 int
fluid_player_stop(fluid_player_t * player)2241 fluid_player_stop(fluid_player_t *player)
2242 {
2243     fluid_atomic_int_set(&player->status, FLUID_PLAYER_DONE);
2244     fluid_atomic_int_set(&player->stopping, 1);
2245     fluid_player_seek(player, fluid_player_get_current_tick(player));
2246     return FLUID_OK;
2247 }
2248 
2249 /**
2250  * Get MIDI player status.
2251  * @param player MIDI player instance
2252  * @return Player status (#fluid_player_status)
2253  * @since 1.1.0
2254  */
2255 int
fluid_player_get_status(fluid_player_t * player)2256 fluid_player_get_status(fluid_player_t *player)
2257 {
2258     return fluid_atomic_int_get(&player->status);
2259 }
2260 
2261 /**
2262  * Seek in the currently playing file.
2263  *
2264  * @param player MIDI player instance
2265  * @param ticks the position to seek to in the current file
2266  * @return #FLUID_FAILED if ticks is negative or after the latest tick of the file
2267  * [or, since 2.1.3, if another seek operation is currently in progress],
2268  * #FLUID_OK otherwise.
2269  *
2270  * The actual seek will be performed when the synth calls back the player (i.e. a few
2271  * levels above the player's callback set with fluid_player_set_playback_callback()).
2272  * If the player's status is #FLUID_PLAYER_PLAYING and a previous seek operation has
2273  * not been completed yet, #FLUID_FAILED is returned.
2274  *
2275  * @since 2.0.0
2276  */
fluid_player_seek(fluid_player_t * player,int ticks)2277 int fluid_player_seek(fluid_player_t *player, int ticks)
2278 {
2279     if(ticks < 0 || (fluid_player_get_status(player) != FLUID_PLAYER_READY && ticks > fluid_player_get_total_ticks(player)))
2280     {
2281         return FLUID_FAILED;
2282     }
2283 
2284     if(fluid_player_get_status(player) == FLUID_PLAYER_PLAYING)
2285     {
2286         if(fluid_atomic_int_compare_and_exchange(&player->seek_ticks, -1, ticks))
2287         {
2288             // new seek position has been set, as no previous seek was in progress
2289             return FLUID_OK;
2290         }
2291     }
2292     else
2293     {
2294         // If the player is not currently playing, a new seek position can be set at any time. This allows
2295         // the user to do:
2296         // fluid_player_stop();
2297         // fluid_player_seek(0); // to beginning
2298         fluid_atomic_int_set(&player->seek_ticks, ticks);
2299         return FLUID_OK;
2300     }
2301 
2302     // a previous seek is still in progress or hasn't been processed yet
2303     return FLUID_FAILED;
2304 }
2305 
2306 
2307 /**
2308  * Enable looping of a MIDI player
2309  *
2310  * @param player MIDI player instance
2311  * @param loop Times left to loop the playlist. -1 means loop infinitely.
2312  * @return Always returns #FLUID_OK
2313  *
2314  * For example, if you want to loop the playlist twice, set loop to 2
2315  * and call this function before you start the player.
2316  *
2317  * @since 1.1.0
2318  */
fluid_player_set_loop(fluid_player_t * player,int loop)2319 int fluid_player_set_loop(fluid_player_t *player, int loop)
2320 {
2321     player->loop = loop;
2322     return FLUID_OK;
2323 }
2324 
2325 /**
2326  * update the MIDI player internal deltatime dependent of actual tempo.
2327  * @param player MIDI player instance
2328  */
fluid_player_update_tempo(fluid_player_t * player)2329 static void fluid_player_update_tempo(fluid_player_t *player)
2330 {
2331     int tempo; /* tempo in micro seconds by quarter note */
2332     float deltatime;
2333 
2334     if(fluid_atomic_int_get(&player->sync_mode))
2335     {
2336         /* take internal tempo from MIDI file */
2337         tempo = fluid_atomic_int_get(&player->miditempo);
2338         /* compute deltattime (in ms) from current tempo and apply tempo multiplier */
2339         deltatime = (float)tempo / (float)player->division / (float)1000.0;
2340         deltatime /= fluid_atomic_float_get(&player->multempo); /* multiply tempo */
2341     }
2342     else
2343     {
2344         /* take  external tempo */
2345         tempo = fluid_atomic_int_get(&player->exttempo);
2346         /* compute deltattime (in ms) from current tempo */
2347         deltatime = (float)tempo / (float)player->division / (float)1000.0;
2348     }
2349 
2350     fluid_atomic_float_set(&player->deltatime, deltatime);
2351 
2352     player->start_msec = player->cur_msec;
2353     player->start_ticks = player->cur_ticks;
2354 
2355     FLUID_LOG(FLUID_DBG,
2356               "tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d",
2357               tempo, player->deltatime, player->cur_msec, player->cur_ticks);
2358 
2359 }
2360 
2361 /**
2362  * Set the tempo of a MIDI player.
2363  * The player can be controlled by internal tempo coming from MIDI file tempo
2364  * change or controlled by external tempo expressed in BPM or in micro seconds
2365  * per quarter note.
2366  *
2367  * @param player MIDI player instance. Must be a valid pointer.
2368  * @param tempo_type Must a be value of #fluid_player_set_tempo_type and indicates the
2369  *  meaning of tempo value and how the player will be controlled, see below.
2370  * @param tempo Tempo value or multiplier.
2371  *
2372  *  #FLUID_PLAYER_TEMPO_INTERNAL, the player will be controlled by internal
2373  *  MIDI file tempo changes. If there are no tempo change in the MIDI file a default
2374  *  value of 120 bpm is used. The @c tempo parameter is used as a multiplier factor
2375  *  that must be in the range (0.001 to 1000).
2376  *  For example, if the current MIDI file tempo is 120 bpm and the multiplier
2377  *  value is 0.5 then this tempo will be slowed down to 60 bpm.
2378  *  At creation, the player is set to be controlled by internal tempo with a
2379  *  multiplier factor set to 1.0.
2380  *
2381  *  #FLUID_PLAYER_TEMPO_EXTERNAL_BPM, the player will be controlled by the
2382  *  external tempo value provided  by the tempo parameter in bpm
2383  *  (i.e in quarter notes per minute) which must be in the range (1 to 60000000).
2384  *
2385  *  #FLUID_PLAYER_TEMPO_EXTERNAL_MIDI, similar as FLUID_PLAYER_TEMPO_EXTERNAL_BPM,
2386  *  but the tempo parameter value is in  micro seconds per quarter note which
2387  *  must be in the range (1 to 60000000).
2388  *  Using micro seconds per quarter note is convenient when the tempo value is
2389  *  derived from MIDI clock realtime messages.
2390  *
2391  * @note When the player is controlled by an external tempo
2392  * (#FLUID_PLAYER_TEMPO_EXTERNAL_BPM or #FLUID_PLAYER_TEMPO_EXTERNAL_MIDI) it
2393  * continues to memorize the most recent internal tempo change coming from the
2394  * MIDI file so that next call to fluid_player_set_tempo() with
2395  * #FLUID_PLAYER_TEMPO_INTERNAL will set the player to follow this internal
2396  * tempo.
2397  *
2398  * @return #FLUID_OK if success or #FLUID_FAILED otherwise (incorrect parameters).
2399  * @since 2.2.0
2400  */
fluid_player_set_tempo(fluid_player_t * player,int tempo_type,double tempo)2401 int fluid_player_set_tempo(fluid_player_t *player, int tempo_type, double tempo)
2402 {
2403     fluid_return_val_if_fail(player != NULL, FLUID_FAILED);
2404     fluid_return_val_if_fail(tempo_type >= FLUID_PLAYER_TEMPO_INTERNAL, FLUID_FAILED);
2405     fluid_return_val_if_fail(tempo_type < FLUID_PLAYER_TEMPO_NBR, FLUID_FAILED);
2406 
2407     switch(tempo_type)
2408     {
2409         /* set the player to be driven by internal tempo coming from MIDI file */
2410         case FLUID_PLAYER_TEMPO_INTERNAL:
2411             /* check if the multiplier is in correct range */
2412             fluid_return_val_if_fail(tempo >= MIN_TEMPO_MULTIPLIER, FLUID_FAILED);
2413             fluid_return_val_if_fail(tempo <= MAX_TEMPO_MULTIPLIER, FLUID_FAILED);
2414 
2415             /* set the tempo multiplier */
2416             fluid_atomic_float_set(&player->multempo, (float)tempo);
2417             fluid_atomic_int_set(&player->sync_mode, 1); /* set internal mode */
2418             break;
2419 
2420         /* set the player to be driven by external tempo */
2421         case FLUID_PLAYER_TEMPO_EXTERNAL_BPM:  /* value in bpm */
2422         case FLUID_PLAYER_TEMPO_EXTERNAL_MIDI: /* value in us/quarter note */
2423             /* check if tempo is in correct range */
2424             fluid_return_val_if_fail(tempo >= MIN_TEMPO_VALUE, FLUID_FAILED);
2425             fluid_return_val_if_fail(tempo <= MAX_TEMPO_VALUE, FLUID_FAILED);
2426 
2427             /* set the tempo value */
2428             if(tempo_type == FLUID_PLAYER_TEMPO_EXTERNAL_BPM)
2429             {
2430                 tempo = 60000000L / tempo; /* convert tempo in us/quarter note */
2431             }
2432             fluid_atomic_int_set(&player->exttempo, (int)tempo);
2433             fluid_atomic_int_set(&player->sync_mode, 0); /* set external mode */
2434             break;
2435 
2436         default: /* shouldn't happen */
2437             break;
2438     }
2439 
2440     /* update deltatime depending of current tempo */
2441     fluid_player_update_tempo(player);
2442 
2443     return FLUID_OK;
2444 }
2445 
2446 /**
2447  * Set the tempo of a MIDI player.
2448  * @param player MIDI player instance
2449  * @param tempo Tempo to set playback speed to (in microseconds per quarter note, as per MIDI file spec)
2450  * @return Always returns #FLUID_OK
2451  * @note Tempo change events contained in the MIDI file can override the specified tempo at any time!
2452  * @deprecated Use fluid_player_set_tempo() instead.
2453  */
fluid_player_set_midi_tempo(fluid_player_t * player,int tempo)2454 int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo)
2455 {
2456     player->miditempo = tempo;
2457 
2458     fluid_player_update_tempo(player);
2459     return FLUID_OK;
2460 }
2461 
2462 /**
2463  * Set the tempo of a MIDI player in beats per minute.
2464  * @param player MIDI player instance
2465  * @param bpm Tempo in beats per minute
2466  * @return Always returns #FLUID_OK
2467  * @note Tempo change events contained in the MIDI file can override the specified BPM at any time!
2468  * @deprecated Use fluid_player_set_tempo() instead.
2469  */
fluid_player_set_bpm(fluid_player_t * player,int bpm)2470 int fluid_player_set_bpm(fluid_player_t *player, int bpm)
2471 {
2472     if(bpm <= 0)
2473     {
2474         return FLUID_FAILED; /* to avoid a division by 0 */
2475     }
2476 
2477     return fluid_player_set_midi_tempo(player, 60000000L / bpm);
2478 }
2479 
2480 /**
2481  * Wait for a MIDI player until the playback has been stopped.
2482  * @param player MIDI player instance
2483  * @return Always #FLUID_OK
2484  *
2485  * @warning The player may still be used by a concurrently running synth context. Hence it is
2486  * not safe to immediately delete the player afterwards. Also refer to delete_fluid_player().
2487  */
2488 int
fluid_player_join(fluid_player_t * player)2489 fluid_player_join(fluid_player_t *player)
2490 {
2491     while(fluid_player_get_status(player) != FLUID_PLAYER_DONE)
2492     {
2493         fluid_msleep(10);
2494     }
2495     return FLUID_OK;
2496 }
2497 
2498 /**
2499  * Get the number of tempo ticks passed.
2500  * @param player MIDI player instance
2501  * @return The number of tempo ticks passed
2502  * @since 1.1.7
2503  */
fluid_player_get_current_tick(fluid_player_t * player)2504 int fluid_player_get_current_tick(fluid_player_t *player)
2505 {
2506     return player->cur_ticks;
2507 }
2508 
2509 /**
2510  * Looks through all available MIDI tracks and gets the absolute tick of the very last event to play.
2511  * @param player MIDI player instance
2512  * @return Total tick count of the sequence
2513  * @since 1.1.7
2514  */
fluid_player_get_total_ticks(fluid_player_t * player)2515 int fluid_player_get_total_ticks(fluid_player_t *player)
2516 {
2517     int i;
2518     int maxTicks = 0;
2519 
2520     for(i = 0; i < player->ntracks; i++)
2521     {
2522         if(player->track[i] != NULL)
2523         {
2524             int ticks = fluid_track_get_duration(player->track[i]);
2525 
2526             if(ticks > maxTicks)
2527             {
2528                 maxTicks = ticks;
2529             }
2530         }
2531     }
2532 
2533     return maxTicks;
2534 }
2535 
2536 /**
2537  * Get the tempo currently used by a MIDI player.
2538  * The player can be controlled by internal tempo coming from MIDI file tempo
2539  * change or controlled by external tempo see fluid_player_set_tempo().
2540  * @param player MIDI player instance. Must be a valid pointer.
2541  * @return MIDI player tempo in BPM or FLUID_FAILED if error.
2542  * @since 1.1.7
2543  */
fluid_player_get_bpm(fluid_player_t * player)2544 int fluid_player_get_bpm(fluid_player_t *player)
2545 {
2546 
2547     int midi_tempo = fluid_player_get_midi_tempo(player);
2548 
2549     if(midi_tempo > 0)
2550     {
2551         midi_tempo = 60000000L / midi_tempo; /* convert in bpm */
2552     }
2553 
2554     return midi_tempo;
2555 }
2556 
2557 /**
2558  * Get the tempo currently used by a MIDI player.
2559  * The player can be controlled by internal tempo coming from MIDI file tempo
2560  * change or controlled by external tempo see fluid_player_set_tempo().
2561 
2562  * @param player MIDI player instance. Must be a valid pointer.
2563  * @return Tempo of the MIDI player (in microseconds per quarter note, as per
2564  * MIDI file spec) or FLUID_FAILED if error.
2565  * @since 1.1.7
2566  */
fluid_player_get_midi_tempo(fluid_player_t * player)2567 int fluid_player_get_midi_tempo(fluid_player_t *player)
2568 {
2569     int midi_tempo; /* value to return */
2570 
2571     fluid_return_val_if_fail(player != NULL, FLUID_FAILED);
2572 
2573     midi_tempo = fluid_atomic_int_get(&player->exttempo);
2574     /* look if the player is internally synced */
2575     if(fluid_atomic_int_get(&player->sync_mode))
2576     {
2577         midi_tempo = (int)((float)fluid_atomic_int_get(&player->miditempo)/
2578                            fluid_atomic_float_get(&player->multempo));
2579     }
2580 
2581     return midi_tempo;
2582 }
2583 
2584 /************************************************************************
2585  *       MIDI PARSER
2586  *
2587  */
2588 
2589 /*
2590  * new_fluid_midi_parser
2591  */
2592 fluid_midi_parser_t *
new_fluid_midi_parser()2593 new_fluid_midi_parser()
2594 {
2595     fluid_midi_parser_t *parser;
2596     parser = FLUID_NEW(fluid_midi_parser_t);
2597 
2598     if(parser == NULL)
2599     {
2600         FLUID_LOG(FLUID_ERR, "Out of memory");
2601         return NULL;
2602     }
2603 
2604     parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */
2605     return parser;
2606 }
2607 
2608 /*
2609  * delete_fluid_midi_parser
2610  */
2611 void
delete_fluid_midi_parser(fluid_midi_parser_t * parser)2612 delete_fluid_midi_parser(fluid_midi_parser_t *parser)
2613 {
2614     fluid_return_if_fail(parser != NULL);
2615 
2616     FLUID_FREE(parser);
2617 }
2618 
2619 /**
2620  * Parse a MIDI stream one character at a time.
2621  * @param parser Parser instance
2622  * @param c Next character in MIDI stream
2623  * @return A parsed MIDI event or NULL if none.  Event is internal and should
2624  *   not be modified or freed and is only valid until next call to this function.
2625  * @internal Do not expose this function to the public API. It would allow downstream
2626  * apps to abuse fluidsynth as midi parser, e.g. feeding it with rawmidi and pull out
2627  * the needed midi information using the getter functions of fluid_midi_event_t.
2628  * This parser however is incomplete as it e.g. only provides a limited buffer to
2629  * store and process SYSEX data (i.e. doesn't allow arbitrary lengths)
2630  */
2631 fluid_midi_event_t *
fluid_midi_parser_parse(fluid_midi_parser_t * parser,unsigned char c)2632 fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c)
2633 {
2634     fluid_midi_event_t *event;
2635 
2636     /* Real-time messages (0xF8-0xFF) can occur anywhere, even in the middle
2637      * of another message. */
2638     if(c >= 0xF8)
2639     {
2640         if(c == MIDI_SYSTEM_RESET)
2641         {
2642             parser->event.type = c;
2643             parser->status = 0; /* clear the status */
2644             return &parser->event;
2645         }
2646 
2647         return NULL;
2648     }
2649 
2650     /* Status byte? - If previous message not yet complete, it is discarded (re-sync). */
2651     if(c & 0x80)
2652     {
2653         /* Any status byte terminates SYSEX messages (not just 0xF7) */
2654         if(parser->status == MIDI_SYSEX && parser->nr_bytes > 0)
2655         {
2656             event = &parser->event;
2657             fluid_midi_event_set_sysex(event, parser->data, parser->nr_bytes,
2658                                        FALSE);
2659         }
2660         else
2661         {
2662             event = NULL;
2663         }
2664 
2665         if(c < 0xF0)  /* Voice category message? */
2666         {
2667             parser->channel = c & 0x0F;
2668             parser->status = c & 0xF0;
2669 
2670             /* The event consumes x bytes of data... (subtract 1 for the status byte) */
2671             parser->nr_bytes_total = fluid_midi_event_length(parser->status)
2672                                      - 1;
2673 
2674             parser->nr_bytes = 0; /* 0  bytes read so far */
2675         }
2676         else if(c == MIDI_SYSEX)
2677         {
2678             parser->status = MIDI_SYSEX;
2679             parser->nr_bytes = 0;
2680         }
2681         else
2682         {
2683             parser->status = 0;    /* Discard other system messages (0xF1-0xF7) */
2684         }
2685 
2686         return event; /* Return SYSEX event or NULL */
2687     }
2688 
2689     /* Data/parameter byte */
2690 
2691     /* Discard data bytes for events we don't care about */
2692     if(parser->status == 0)
2693     {
2694         return NULL;
2695     }
2696 
2697     /* Max data size exceeded? (SYSEX messages only really) */
2698     if(parser->nr_bytes == FLUID_MIDI_PARSER_MAX_DATA_SIZE)
2699     {
2700         parser->status = 0; /* Discard the rest of the message */
2701         return NULL;
2702     }
2703 
2704     /* Store next byte */
2705     parser->data[parser->nr_bytes++] = c;
2706 
2707     /* Do we still need more data to get this event complete? */
2708     if(parser->status == MIDI_SYSEX || parser->nr_bytes < parser->nr_bytes_total)
2709     {
2710         return NULL;
2711     }
2712 
2713     /* Event is complete, return it.
2714      * Running status byte MIDI feature is also handled here. */
2715     parser->event.type = parser->status;
2716     parser->event.channel = parser->channel;
2717     parser->nr_bytes = 0; /* Reset data size, in case there are additional running status messages */
2718 
2719     switch(parser->status)
2720     {
2721     case NOTE_OFF:
2722     case NOTE_ON:
2723     case KEY_PRESSURE:
2724     case CONTROL_CHANGE:
2725     case PROGRAM_CHANGE:
2726     case CHANNEL_PRESSURE:
2727         parser->event.param1 = parser->data[0]; /* For example key number */
2728         parser->event.param2 = parser->data[1]; /* For example velocity */
2729         break;
2730 
2731     case PITCH_BEND:
2732         /* Pitch-bend is transmitted with 14-bit precision. */
2733         parser->event.param1 = (parser->data[1] << 7) | parser->data[0];
2734         break;
2735 
2736     default: /* Unlikely */
2737         return NULL;
2738     }
2739 
2740     return &parser->event;
2741 }
2742 
2743 /* Purpose:
2744  * Returns the length of a MIDI message. */
2745 static int
fluid_midi_event_length(unsigned char event)2746 fluid_midi_event_length(unsigned char event)
2747 {
2748     switch(event & 0xF0)
2749     {
2750     case NOTE_OFF:
2751     case NOTE_ON:
2752     case KEY_PRESSURE:
2753     case CONTROL_CHANGE:
2754     case PITCH_BEND:
2755         return 3;
2756 
2757     case PROGRAM_CHANGE:
2758     case CHANNEL_PRESSURE:
2759         return 2;
2760     }
2761 
2762     switch(event)
2763     {
2764     case MIDI_TIME_CODE:
2765     case MIDI_SONG_SELECT:
2766     case 0xF4:
2767     case 0xF5:
2768         return 2;
2769 
2770     case MIDI_TUNE_REQUEST:
2771         return 1;
2772 
2773     case MIDI_SONG_POSITION:
2774         return 3;
2775     }
2776 
2777     return 1;
2778 }
2779