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