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