diff --git a/fluidsynth/ChangeLog b/fluidsynth/ChangeLog index b3e3f5be..7a9e8a8b 100644 --- a/fluidsynth/ChangeLog +++ b/fluidsynth/ChangeLog @@ -1,3 +1,19 @@ +2004-03-22 Peter Hanappe + + * src/fluid_midi.c (fluid_player_callback): Fixed the timing in + the MIDI playback. The current MIDI tick in every timer callback + was calculated as an increment to the previous number of + ticks. This introduces a growing error due to rounding errors and + timer variations. The current tick is now calculated according to + the absolute time at the beginning of the file. (Beginners error + ...) + + * doc/FluidSynth-LADSPA.pdf: Added Markus' LADSPA design document. + + * doc/xtrafluid.txt: Added Antoine's Xtra API documentation. + + * doc/midi_time.txt: Added a memo on midi timing. + 2004-03-19 Peter Hanappe * src/fluid_midishare.c: Applied Stephane Letz patch: MidiShare is diff --git a/fluidsynth/TODO b/fluidsynth/TODO index 85024adb..cca25d4a 100644 --- a/fluidsynth/TODO +++ b/fluidsynth/TODO @@ -47,6 +47,24 @@ JG: - Remove dependency of settings on audio driver and other (see fluid_settings_init()) +- MIDI tempo + fluidsynth: real 2m23.312s + timidity: real 2m04.304s + + +- Validation tests +- Validate reverb +- Validate chorus +- Documentation +- Web site +- Linux + Win + MacOS X + fluid~ + fluidsynth~ + old distributions +- Documentation and announcement Virtools and Director + +- Component for MacOS X (Core Audio?) +- Component for DirectMusic +- Multi-channel output +- DirectSound 3D and EAX + Synthesis related ----------------- diff --git a/fluidsynth/include/fluidsynth/sfont.h b/fluidsynth/include/fluidsynth/sfont.h index 13d7fb5d..edf06719 100644 --- a/fluidsynth/include/fluidsynth/sfont.h +++ b/fluidsynth/include/fluidsynth/sfont.h @@ -36,10 +36,10 @@ extern "C" { * with callback functions): fluid_sfloader_t, fluid_sfont_t, and * fluid_preset_t. * - * To add a new SoundFont loader to the synthesizer, you call + * To add a new SoundFont loader to the synthesizer, call * fluid_synth_add_sfloader() and pass a pointer to an * fluid_sfloader_t structure. The important callback function in - * this structure os "load", which should try to load a file and + * this structure is "load", which should try to load a file and * returns a fluid_sfont_t structure, or NULL if it fails. * * The fluid_sfont_t structure contains a callback to obtain the @@ -72,8 +72,15 @@ extern "C" { */ struct _fluid_sfloader_t { + /** Private data */ void* data; + + /** The free must free the memory allocated for the loader in + * addition to any private data. It should return 0 if no error + * occured, non-zero otherwise.*/ int (*free)(fluid_sfloader_t* loader); + + /** Load a file. Returns NULL if an error occured. */ fluid_sfont_t* (*load)(fluid_sfloader_t* loader, const char* filename); }; @@ -91,8 +98,14 @@ struct _fluid_sfont_t { the samples could not be freed because they are still in use. */ int (*free)(fluid_sfont_t* sfont); + /** Return the name of the sfont */ char* (*get_name)(fluid_sfont_t* sfont); + + /** Return the preset with the specified bank and preset number. All + * the fields, including the 'sfont' field, should * be filled + * in. If the preset cannot be found, the function returns NULL. */ fluid_preset_t* (*get_preset)(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum); + void (*iteration_start)(fluid_sfont_t* sfont); /* return 0 when no more presets are available, 1 otherwise */ @@ -114,7 +127,7 @@ struct _fluid_preset_t { int (*get_banknum)(fluid_preset_t* preset); int (*get_num)(fluid_preset_t* preset); - /** handle a noteon event. */ + /** handle a noteon event. Returns 0 if no error occured. */ int (*noteon)(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel); /** Implement this function if the preset needs to be notified about @@ -142,7 +155,7 @@ struct _fluid_sample_t short* data; /** The amplitude, that will lower the level of the sample's loop to - the noise floor Needed for note turnoff optimization, will be + the noise floor. Needed for note turnoff optimization, will be filled out automatically */ /* Set this to zero, when submitting a new sample. */ int amplitude_that_reaches_noise_floor_is_valid; diff --git a/fluidsynth/src/fluid_midi.c b/fluidsynth/src/fluid_midi.c index f056545a..ca358ec8 100644 --- a/fluidsynth/src/fluid_midi.c +++ b/fluidsynth/src/fluid_midi.c @@ -60,30 +60,30 @@ static int remains_80e0[] = { */ fluid_midi_file* new_fluid_midi_file(char* filename) { - fluid_midi_file* mf; + fluid_midi_file* mf; - mf = FLUID_NEW(fluid_midi_file); - if (mf == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file)); + mf = FLUID_NEW(fluid_midi_file); + if (mf == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file)); - mf->c = -1; - mf->running_status = -1; - mf->fp = FLUID_FOPEN(filename, "rb"); + mf->c = -1; + mf->running_status = -1; + mf->fp = FLUID_FOPEN(filename, "rb"); - if (mf->fp == NULL) { - FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file"); - FLUID_FREE(mf); - return NULL; - } + if (mf->fp == NULL) { + FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file"); + FLUID_FREE(mf); + return NULL; + } - if (fluid_midi_file_read_mthd(mf) != FLUID_OK) { - FLUID_FREE(mf); - return NULL; - } - return mf; + if (fluid_midi_file_read_mthd(mf) != FLUID_OK) { + FLUID_FREE(mf); + return NULL; + } + return mf; } /* @@ -91,14 +91,14 @@ fluid_midi_file* new_fluid_midi_file(char* filename) */ void delete_fluid_midi_file(fluid_midi_file* mf) { - if (mf == NULL) { - return; - } - if (mf->fp != NULL) { - FLUID_FCLOSE(mf->fp); - } - FLUID_FREE(mf); - return; + if (mf == NULL) { + return; + } + if (mf->fp != NULL) { + FLUID_FCLOSE(mf->fp); + } + FLUID_FREE(mf); + return; } /* @@ -106,16 +106,16 @@ void delete_fluid_midi_file(fluid_midi_file* mf) */ int fluid_midi_file_getc(fluid_midi_file* mf) { - unsigned char c; - int n; - if (mf->c >= 0) { - c = mf->c; - mf->c = -1; - } else { - n = FLUID_FREAD(&c, 1, 1, mf->fp); - mf->trackpos++; - } - return (int) c; + unsigned char c; + int n; + if (mf->c >= 0) { + c = mf->c; + mf->c = -1; + } else { + n = FLUID_FREAD(&c, 1, 1, mf->fp); + mf->trackpos++; + } + return (int) c; } /* @@ -123,8 +123,8 @@ int fluid_midi_file_getc(fluid_midi_file* mf) */ int fluid_midi_file_push(fluid_midi_file* mf, int c) { - mf->c = c; - return FLUID_OK; + mf->c = c; + return FLUID_OK; } /* @@ -132,14 +132,14 @@ int fluid_midi_file_push(fluid_midi_file* mf, int c) */ int fluid_midi_file_read(fluid_midi_file* mf, void* buf, int len) { - int num = FLUID_FREAD(buf, 1, len, mf->fp); - mf->trackpos += num; + int num = FLUID_FREAD(buf, 1, len, mf->fp); + mf->trackpos += num; #if DEBUG - if (num != len) { - FLUID_LOG(FLUID_DBG, "Coulnd't read the requested number of bytes"); - } + if (num != len) { + FLUID_LOG(FLUID_DBG, "Coulnd't read the requested number of bytes"); + } #endif - return (num != len)? FLUID_FAILED : FLUID_OK; + return (num != len)? FLUID_FAILED : FLUID_OK; } /* @@ -147,12 +147,12 @@ int fluid_midi_file_read(fluid_midi_file* mf, void* buf, int len) */ int fluid_midi_file_skip(fluid_midi_file* mf, int skip) { - int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR); - if (err) { - FLUID_LOG(FLUID_ERR, "Failed to seek position in file"); - return FLUID_FAILED; - } - return FLUID_OK; + int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR); + if (err) { + FLUID_LOG(FLUID_ERR, "Failed to seek position in file"); + return FLUID_FAILED; + } + return FLUID_OK; } /* @@ -160,28 +160,29 @@ int fluid_midi_file_skip(fluid_midi_file* mf, int skip) */ int fluid_midi_file_read_mthd(fluid_midi_file* mf) { - char mthd[15]; - if (fluid_midi_file_read(mf, mthd, 14) != FLUID_OK) { - return FLUID_FAILED; - } - if ((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6) || (mthd[9] > 2)) { - FLUID_LOG(FLUID_ERR, "Doesn't look like a MIDI file: invalid MThd header"); - return FLUID_FAILED; - } - mf->type = mthd[9]; - mf->ntracks = (unsigned) mthd[11]; - mf->ntracks += (unsigned int) (mthd[10]) << 16; - if((mthd[12]) < 0){ - mf->uses_smpte = 1; - mf->smpte_fps = -mthd[12]; - mf->smpte_res = (unsigned) mthd[13]; - FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet"); - return FLUID_FAILED; - } else { - mf->uses_smpte = 0; - mf->division = (mthd[12] << 8) | (mthd[13] & 0xff); - } - return FLUID_OK; + char mthd[15]; + if (fluid_midi_file_read(mf, mthd, 14) != FLUID_OK) { + return FLUID_FAILED; + } + if ((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6) || (mthd[9] > 2)) { + FLUID_LOG(FLUID_ERR, "Doesn't look like a MIDI file: invalid MThd header"); + return FLUID_FAILED; + } + mf->type = mthd[9]; + mf->ntracks = (unsigned) mthd[11]; + mf->ntracks += (unsigned int) (mthd[10]) << 16; + if((mthd[12]) < 0){ + mf->uses_smpte = 1; + mf->smpte_fps = -mthd[12]; + mf->smpte_res = (unsigned) mthd[13]; + FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet"); + return FLUID_FAILED; + } else { + mf->uses_smpte = 0; + mf->division = (mthd[12] << 8) | (mthd[13] & 0xff); + FLUID_LOG(FLUID_DBG, "Division=%d", mf->division); + } + return FLUID_OK; } /* @@ -189,13 +190,13 @@ int fluid_midi_file_read_mthd(fluid_midi_file* mf) */ int fluid_midi_file_load_tracks(fluid_midi_file* mf, fluid_player_t* player) { - int i; - for (i = 0; i < mf->ntracks; i++) { - if (fluid_midi_file_read_track(mf, player, i) != FLUID_OK) { - return FLUID_FAILED; - } - } - return FLUID_OK; + int i; + for (i = 0; i < mf->ntracks; i++) { + if (fluid_midi_file_read_track(mf, player, i) != FLUID_OK) { + return FLUID_FAILED; + } + } + return FLUID_OK; } /* @@ -203,14 +204,14 @@ int fluid_midi_file_load_tracks(fluid_midi_file* mf, fluid_player_t* player) */ int fluid_isasciistring(char* s) { - int i; - int len = (int) FLUID_STRLEN(s); - for (i = 0; i < len; i++) { - if (!fluid_isascii(s[i])) { - return 0; - } - } - return 1; + int i; + int len = (int) FLUID_STRLEN(s); + for (i = 0; i < len; i++) { + if (!fluid_isascii(s[i])) { + return 0; + } + } + return 1; } /* @@ -218,9 +219,9 @@ int fluid_isasciistring(char* s) */ long fluid_getlength(unsigned char *s) { - long i = 0; - i = s[3] | (s[2]<<8) | (s[1]<<16) | (s[0]<<24); - return i; + long i = 0; + i = s[3] | (s[2]<<8) | (s[1]<<16) | (s[0]<<24); + return i; } /* @@ -228,14 +229,14 @@ long fluid_getlength(unsigned char *s) */ int fluid_midi_file_read_tracklen(fluid_midi_file* mf) { - unsigned char length[5]; - if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) { - return FLUID_FAILED; - } - mf->tracklen = fluid_getlength(length); - mf->trackpos = 0; - mf->eot = 0; - return FLUID_OK; + unsigned char length[5]; + if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) { + return FLUID_FAILED; + } + mf->tracklen = fluid_getlength(length); + mf->trackpos = 0; + mf->eot = 0; + return FLUID_OK; } /* @@ -244,11 +245,11 @@ int fluid_midi_file_read_tracklen(fluid_midi_file* mf) int fluid_midi_file_eot(fluid_midi_file* mf) { #if DEBUG - if (mf->trackpos > mf->tracklen) { - printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen); - } + if (mf->trackpos > mf->tracklen) { + printf("track overrun: %d > %d\n", mf->trackpos, mf->tracklen); + } #endif - return mf->eot || (mf->trackpos >= mf->tracklen); + return mf->eot || (mf->trackpos >= mf->tracklen); } /* @@ -256,61 +257,61 @@ int fluid_midi_file_eot(fluid_midi_file* mf) */ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int num) { - fluid_track_t* track; - unsigned char id[5], length[5]; - int found_track = 0; - int skip; + fluid_track_t* track; + unsigned char id[5], length[5]; + int found_track = 0; + int skip; - if (fluid_midi_file_read(mf, id, 4) != FLUID_OK) { - return FLUID_FAILED; - } - id[4]='\0'; - - while (!found_track){ - - if (fluid_isasciistring((char*) id) == 0) { - FLUID_LOG(FLUID_ERR, "An non-ascii track header found, currupt file"); - return FLUID_FAILED; - - } else if (strcmp((char*) id, "MTrk") == 0) { - - found_track = 1; - - if (fluid_midi_file_read_tracklen(mf) != FLUID_OK) { - return FLUID_FAILED; - } - - track = new_fluid_track(num); - if (track == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } - - while (!fluid_midi_file_eot(mf)) { - if (fluid_midi_file_read_event(mf, track) != FLUID_OK) { - return FLUID_FAILED; + if (fluid_midi_file_read(mf, id, 4) != FLUID_OK) { + return FLUID_FAILED; } - } + id[4]='\0'; - fluid_player_add_track(player, track); + while (!found_track){ - } else { - found_track = 0; - if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) { - return FLUID_FAILED; - } - skip = fluid_getlength(length); + if (fluid_isasciistring((char*) id) == 0) { + FLUID_LOG(FLUID_ERR, "An non-ascii track header found, currupt file"); + return FLUID_FAILED; + + } else if (strcmp((char*) id, "MTrk") == 0) { + + found_track = 1; + + if (fluid_midi_file_read_tracklen(mf) != FLUID_OK) { + return FLUID_FAILED; + } + + track = new_fluid_track(num); + if (track == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } + + while (!fluid_midi_file_eot(mf)) { + if (fluid_midi_file_read_event(mf, track) != FLUID_OK) { + return FLUID_FAILED; + } + } + + fluid_player_add_track(player, track); + + } else { + found_track = 0; + if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) { + return FLUID_FAILED; + } + skip = fluid_getlength(length); /* fseek(mf->fp, skip, SEEK_CUR); */ - if (fluid_midi_file_skip(mf, skip) != FLUID_OK) { - return FLUID_FAILED; - } - } - } - if (feof(mf->fp)) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } - return FLUID_OK; + if (fluid_midi_file_skip(mf, skip) != FLUID_OK) { + return FLUID_FAILED; + } + } + } + if (feof(mf->fp)) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } + return FLUID_OK; } /* @@ -318,28 +319,28 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int */ int fluid_midi_file_read_varlen(fluid_midi_file* mf) { - int i; - int c; - mf->varlen = 0; - for (i = 0;;i++) { - if (i == 4) { - FLUID_LOG(FLUID_ERR, "Invalid variable length number"); - return FLUID_FAILED; - } - c = fluid_midi_file_getc(mf); - if (c < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } - if (c & 0x80){ - mf->varlen |= (int) (c & 0x7F); - mf->varlen <<= 7; - } else { - mf->varlen += c; - break; - } - } - return FLUID_OK; + int i; + int c; + mf->varlen = 0; + for (i = 0;;i++) { + if (i == 4) { + FLUID_LOG(FLUID_ERR, "Invalid variable length number"); + return FLUID_FAILED; + } + c = fluid_midi_file_getc(mf); + if (c < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } + if (c & 0x80){ + mf->varlen |= (int) (c & 0x7F); + mf->varlen <<= 7; + } else { + mf->varlen += c; + break; + } + } + return FLUID_OK; } /* @@ -347,303 +348,303 @@ int fluid_midi_file_read_varlen(fluid_midi_file* mf) */ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) { - int dtime; - int status; - int type; - int tempo; - unsigned char* metadata = NULL; - unsigned char* dyn_buf = NULL; - unsigned char static_buf[256]; - int nominator, denominator, clocks, notes, sf, mi; - fluid_midi_event_t* evt; - int channel = 0; - int param1 = 0; - int param2 = 0; + int dtime; + int status; + int type; + int tempo; + unsigned char* metadata = NULL; + unsigned char* dyn_buf = NULL; + unsigned char static_buf[256]; + int nominator, denominator, clocks, notes, sf, mi; + fluid_midi_event_t* evt; + int channel = 0; + int param1 = 0; + int param2 = 0; - /* read the delta-time of the event */ - if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { - return FLUID_FAILED; - } - dtime = mf->varlen; + /* read the delta-time of the event */ + if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { + return FLUID_FAILED; + } + dtime = mf->varlen; - /* read the status byte */ - status = fluid_midi_file_getc(mf); - if (status < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } - - /* not a valid status byte: use the running status instead */ - if ((status & 0x80) == 0) { - if ((mf->running_status & 0x80) == 0) { - FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status"); - return FLUID_FAILED; - } - fluid_midi_file_push(mf, status); - status = mf->running_status; - } - - /* check what message we have */ - if (status & 0x80) { - mf->running_status = status; - - if ((status == MIDI_SYSEX) || (status == MIDI_EOX)) { /* system exclusif */ - /* - * Sysex messages are not handled yet - */ - /* read the length of the message */ - if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { - return FLUID_FAILED; - } - - if (mf->varlen) { - - if (mf->varlen < 255) { - metadata = &static_buf[0]; - } else { - FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); - dyn_buf = FLUID_MALLOC(mf->varlen + 1); - if (dyn_buf == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; - } - metadata = dyn_buf; + /* read the status byte */ + status = fluid_midi_file_getc(mf); + if (status < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; } - /* read the data of the message */ - if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) { - if (dyn_buf) { - FLUID_FREE(dyn_buf); - } - return FLUID_FAILED; - } + /* not a valid status byte: use the running status instead */ + if ((status & 0x80) == 0) { + if ((mf->running_status & 0x80) == 0) { + FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status"); + return FLUID_FAILED; + } + fluid_midi_file_push(mf, status); + status = mf->running_status; + } - if (dyn_buf) { - FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__); - FLUID_FREE(dyn_buf); - } - } + /* check what message we have */ + if (status & 0x80) { + mf->running_status = status; - return FLUID_OK; + if ((status == MIDI_SYSEX) || (status == MIDI_EOX)) { /* system exclusif */ + /* + * Sysex messages are not handled yet + */ + /* read the length of the message */ + if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { + return FLUID_FAILED; + } + + if (mf->varlen) { + + if (mf->varlen < 255) { + metadata = &static_buf[0]; + } else { + FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); + dyn_buf = FLUID_MALLOC(mf->varlen + 1); + if (dyn_buf == NULL) { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + metadata = dyn_buf; + } + + /* read the data of the message */ + if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) { + if (dyn_buf) { + FLUID_FREE(dyn_buf); + } + return FLUID_FAILED; + } + + if (dyn_buf) { + FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__); + FLUID_FREE(dyn_buf); + } + } + + return FLUID_OK; - } else if (status == MIDI_META_EVENT) { /* meta events */ + } else if (status == MIDI_META_EVENT) { /* meta events */ - int result = FLUID_OK; + int result = FLUID_OK; - /* get the type of the meta message */ - type = fluid_midi_file_getc(mf); - if (type < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } + /* get the type of the meta message */ + type = fluid_midi_file_getc(mf); + if (type < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } - /* get the length of the data part */ - if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { - return FLUID_FAILED; - } + /* get the length of the data part */ + if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { + return FLUID_FAILED; + } - if (mf->varlen < 255) { - metadata = &static_buf[0]; - } else { - FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); - dyn_buf = FLUID_MALLOC(mf->varlen + 1); - if (dyn_buf == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; - } - metadata = dyn_buf; - } + if (mf->varlen < 255) { + metadata = &static_buf[0]; + } else { + FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, __LINE__, mf->varlen); + dyn_buf = FLUID_MALLOC(mf->varlen + 1); + if (dyn_buf == NULL) { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + metadata = dyn_buf; + } - /* read the data */ - if (mf->varlen) - { - if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) { - if (dyn_buf) { - FLUID_FREE(dyn_buf); - } - return FLUID_FAILED; - } - } + /* read the data */ + if (mf->varlen) + { + if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) { + if (dyn_buf) { + FLUID_FREE(dyn_buf); + } + return FLUID_FAILED; + } + } - /* handle meta data */ - switch (type) { + /* handle meta data */ + switch (type) { - case MIDI_COPYRIGHT: - metadata[mf->varlen] = 0; - break; + case MIDI_COPYRIGHT: + metadata[mf->varlen] = 0; + break; - case MIDI_TRACK_NAME: - metadata[mf->varlen] = 0; - fluid_track_set_name(track, (char*) metadata); - break; + case MIDI_TRACK_NAME: + metadata[mf->varlen] = 0; + fluid_track_set_name(track, (char*) metadata); + break; - case MIDI_INST_NAME: - metadata[mf->varlen] = 0; - break; + case MIDI_INST_NAME: + metadata[mf->varlen] = 0; + break; - case MIDI_LYRIC: - break; + case MIDI_LYRIC: + break; - case MIDI_MARKER: - break; + case MIDI_MARKER: + break; - case MIDI_CUE_POINT: - break; /* don't care much for text events */ + case MIDI_CUE_POINT: + break; /* don't care much for text events */ - case MIDI_EOT: - if (mf->varlen != 0) { - FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event"); - result = FLUID_FAILED; - break; - } - mf->eot = 1; - break; + case MIDI_EOT: + if (mf->varlen != 0) { + FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event"); + result = FLUID_FAILED; + break; + } + mf->eot = 1; + break; - case MIDI_SET_TEMPO: - if (mf->varlen != 3) { - FLUID_LOG(FLUID_ERR, "Invalid length for SetTempo meta event"); - result = FLUID_FAILED; - break; - } - tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2]; - evt = new_fluid_midi_event(); - if (evt == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - result = FLUID_FAILED; - break; - } - evt->dtime = dtime; - evt->type = MIDI_SET_TEMPO; - evt->channel = 0; - evt->param1 = tempo; - evt->param2 = 0; - fluid_track_add_event(track, evt); - break; + case MIDI_SET_TEMPO: + if (mf->varlen != 3) { + FLUID_LOG(FLUID_ERR, "Invalid length for SetTempo meta event"); + result = FLUID_FAILED; + break; + } + tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2]; + evt = new_fluid_midi_event(); + if (evt == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + result = FLUID_FAILED; + break; + } + evt->dtime = dtime; + evt->type = MIDI_SET_TEMPO; + evt->channel = 0; + evt->param1 = tempo; + evt->param2 = 0; + fluid_track_add_event(track, evt); + break; - case MIDI_SMPTE_OFFSET: - if (mf->varlen != 5) { - FLUID_LOG(FLUID_ERR, "Invalid length for SMPTE Offset meta event"); - result = FLUID_FAILED; - break; - } - break; /* we don't use smtp */ + case MIDI_SMPTE_OFFSET: + if (mf->varlen != 5) { + FLUID_LOG(FLUID_ERR, "Invalid length for SMPTE Offset meta event"); + result = FLUID_FAILED; + break; + } + break; /* we don't use smtp */ - case MIDI_TIME_SIGNATURE: - if (mf->varlen != 4) { - FLUID_LOG(FLUID_ERR, "Invalid length for TimeSignature meta event"); - result = FLUID_FAILED; - break; - } - nominator = metadata[0]; - denominator = pow(2.0, (double) metadata[1]); - clocks = metadata[2]; - notes = metadata[3]; + case MIDI_TIME_SIGNATURE: + if (mf->varlen != 4) { + FLUID_LOG(FLUID_ERR, "Invalid length for TimeSignature meta event"); + result = FLUID_FAILED; + break; + } + nominator = metadata[0]; + denominator = pow(2.0, (double) metadata[1]); + clocks = metadata[2]; + notes = metadata[3]; - FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d\n", - nominator, denominator, clocks, notes); + FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d", + nominator, denominator, clocks, notes); - break; + break; - case MIDI_KEY_SIGNATURE: - if (mf->varlen != 2) { - FLUID_LOG(FLUID_ERR, "Invalid length for KeySignature meta event"); - result = FLUID_FAILED; - break; - } - sf = metadata[0]; - mi = metadata[1]; - break; + case MIDI_KEY_SIGNATURE: + if (mf->varlen != 2) { + FLUID_LOG(FLUID_ERR, "Invalid length for KeySignature meta event"); + result = FLUID_FAILED; + break; + } + sf = metadata[0]; + mi = metadata[1]; + break; - case MIDI_SEQUENCER_EVENT: - break; + case MIDI_SEQUENCER_EVENT: + break; - default: - break; - } + default: + break; + } - if (dyn_buf) { - FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__); - FLUID_FREE(dyn_buf); - } + if (dyn_buf) { + FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__); + FLUID_FREE(dyn_buf); + } - return result; + return result; - } else { /* channel messages */ + } else { /* channel messages */ - type = status & 0xf0; - channel = status & 0x0f; + type = status & 0xf0; + channel = status & 0x0f; - /* all channel message have at least 1 byte of associated data */ - if ((param1 = fluid_midi_file_getc(mf)) < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } + /* all channel message have at least 1 byte of associated data */ + if ((param1 = fluid_midi_file_getc(mf)) < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } - switch (type) { + switch (type) { - case NOTE_ON: - if ((param2 = fluid_midi_file_getc(mf)) < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; + case NOTE_ON: + if ((param2 = fluid_midi_file_getc(mf)) < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } + break; + + case NOTE_OFF: + if ((param2 = fluid_midi_file_getc(mf)) < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } + break; + + case KEY_PRESSURE: + if ((param2 = fluid_midi_file_getc(mf)) < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } + break; + + case CONTROL_CHANGE: + if ((param2 = fluid_midi_file_getc(mf)) < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } + break; + + case PROGRAM_CHANGE: + break; + + case CHANNEL_PRESSURE: + break; + + case PITCH_BEND: + if ((param2 = fluid_midi_file_getc(mf)) < 0) { + FLUID_LOG(FLUID_ERR, "Unexpected end of file"); + return FLUID_FAILED; + } + + param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f); + param2 = 0; + break; + + default: + /* Can't possibly happen !? */ + FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event"); + return FLUID_FAILED; + } + evt = new_fluid_midi_event(); + if (evt == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } + evt->dtime = dtime; + evt->type = type; + evt->channel = channel; + evt->param1 = param1; + evt->param2 = param2; + fluid_track_add_event(track, evt); + } } - break; - - case NOTE_OFF: - if ((param2 = fluid_midi_file_getc(mf)) < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } - break; - - case KEY_PRESSURE: - if ((param2 = fluid_midi_file_getc(mf)) < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } - break; - - case CONTROL_CHANGE: - if ((param2 = fluid_midi_file_getc(mf)) < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } - break; - - case PROGRAM_CHANGE: - break; - - case CHANNEL_PRESSURE: - break; - - case PITCH_BEND: - if ((param2 = fluid_midi_file_getc(mf)) < 0) { - FLUID_LOG(FLUID_ERR, "Unexpected end of file"); - return FLUID_FAILED; - } - - param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f); - param2 = 0; - break; - - default: - /* Can't possibly happen !? */ - FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event"); - return FLUID_FAILED; - } - evt = new_fluid_midi_event(); - if (evt == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } - evt->dtime = dtime; - evt->type = type; - evt->channel = channel; - evt->param1 = param1; - evt->param2 = param2; - fluid_track_add_event(track, evt); - } - } - return FLUID_OK; + return FLUID_OK; } /* @@ -651,7 +652,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) */ int fluid_midi_file_get_division(fluid_midi_file* midifile) { - return midifile->division; + return midifile->division; } /****************************************************** @@ -664,19 +665,19 @@ int fluid_midi_file_get_division(fluid_midi_file* midifile) */ fluid_midi_event_t* new_fluid_midi_event() { - fluid_midi_event_t* evt; - evt = FLUID_NEW(fluid_midi_event_t); - if (evt == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - evt->dtime = 0; - evt->type = 0; - evt->channel = 0; - evt->param1 = 0; - evt->param2 = 0; - evt->next = NULL; - return evt; + fluid_midi_event_t* evt; + evt = FLUID_NEW(fluid_midi_event_t); + if (evt == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + evt->dtime = 0; + evt->type = 0; + evt->channel = 0; + evt->param1 = 0; + evt->param2 = 0; + evt->next = NULL; + return evt; } /* @@ -684,15 +685,15 @@ fluid_midi_event_t* new_fluid_midi_event() */ int delete_fluid_midi_event(fluid_midi_event_t* evt) { - fluid_midi_event_t *temp; + fluid_midi_event_t *temp; - while (evt) - { - temp = evt->next; - FLUID_FREE(evt); - evt = temp; - } - return FLUID_OK; + while (evt) + { + temp = evt->next; + FLUID_FREE(evt); + evt = temp; + } + return FLUID_OK; } /* @@ -700,7 +701,7 @@ int delete_fluid_midi_event(fluid_midi_event_t* evt) */ int fluid_midi_event_get_type(fluid_midi_event_t* evt) { - return evt->type; + return evt->type; } /* @@ -708,8 +709,8 @@ int fluid_midi_event_get_type(fluid_midi_event_t* evt) */ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type) { - evt->type = type; - return FLUID_OK; + evt->type = type; + return FLUID_OK; } /* @@ -717,7 +718,7 @@ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type) */ int fluid_midi_event_get_channel(fluid_midi_event_t* evt) { - return evt->channel; + return evt->channel; } /* @@ -725,8 +726,8 @@ int fluid_midi_event_get_channel(fluid_midi_event_t* evt) */ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan) { - evt->channel = chan; - return FLUID_OK; + evt->channel = chan; + return FLUID_OK; } /* @@ -734,7 +735,7 @@ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan) */ int fluid_midi_event_get_key(fluid_midi_event_t* evt) { - return evt->param1; + return evt->param1; } /* @@ -742,8 +743,8 @@ int fluid_midi_event_get_key(fluid_midi_event_t* evt) */ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v) { - evt->param1 = v; - return FLUID_OK; + evt->param1 = v; + return FLUID_OK; } /* @@ -751,7 +752,7 @@ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v) */ int fluid_midi_event_get_velocity(fluid_midi_event_t* evt) { - return evt->param2; + return evt->param2; } /* @@ -759,8 +760,8 @@ int fluid_midi_event_get_velocity(fluid_midi_event_t* evt) */ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v) { - evt->param2 = v; - return FLUID_OK; + evt->param2 = v; + return FLUID_OK; } /* @@ -768,7 +769,7 @@ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v) */ int fluid_midi_event_get_control(fluid_midi_event_t* evt) { - return evt->param1; + return evt->param1; } /* @@ -776,8 +777,8 @@ int fluid_midi_event_get_control(fluid_midi_event_t* evt) */ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v) { - evt->param1 = v; - return FLUID_OK; + evt->param1 = v; + return FLUID_OK; } /* @@ -785,7 +786,7 @@ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v) */ int fluid_midi_event_get_value(fluid_midi_event_t* evt) { - return evt->param2; + return evt->param2; } /* @@ -793,30 +794,30 @@ int fluid_midi_event_get_value(fluid_midi_event_t* evt) */ int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v) { - evt->param2 = v; - return FLUID_OK; + evt->param2 = v; + return FLUID_OK; } int fluid_midi_event_get_program(fluid_midi_event_t* evt) { - return evt->param1; + return evt->param1; } int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val) { - evt->param1 = val; - return FLUID_OK; + evt->param1 = val; + return FLUID_OK; } int fluid_midi_event_get_pitch(fluid_midi_event_t* evt) { - return evt->param1; + return evt->param1; } int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val) { - evt->param1 = val; - return FLUID_OK; + evt->param1 = val; + return FLUID_OK; } /* @@ -863,18 +864,18 @@ int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val) */ fluid_track_t* new_fluid_track(int num) { - fluid_track_t* track; - track = FLUID_NEW(fluid_track_t); - if (track == NULL) { - return NULL; - } - track->name = NULL; - track->num = num; - track->first = NULL; - track->cur = NULL; - track->last = NULL; - track->ticks = 0; - return track; + fluid_track_t* track; + track = FLUID_NEW(fluid_track_t); + if (track == NULL) { + return NULL; + } + track->name = NULL; + track->num = num; + track->first = NULL; + track->cur = NULL; + track->last = NULL; + track->ticks = 0; + return track; } /* @@ -882,14 +883,14 @@ fluid_track_t* new_fluid_track(int num) */ int delete_fluid_track(fluid_track_t* track) { - if (track->name != NULL) { - FLUID_FREE(track->name); - } - if (track->first != NULL) { - delete_fluid_midi_event(track->first); - } - FLUID_FREE(track); - return FLUID_OK; + if (track->name != NULL) { + FLUID_FREE(track->name); + } + if (track->first != NULL) { + delete_fluid_midi_event(track->first); + } + FLUID_FREE(track); + return FLUID_OK; } /* @@ -897,22 +898,22 @@ int delete_fluid_track(fluid_track_t* track) */ int fluid_track_set_name(fluid_track_t* track, char* name) { - int len; - if (track->name != NULL) { - FLUID_FREE(track->name); - } - if (name == NULL) { - track->name = NULL; - return FLUID_OK; - } - len = FLUID_STRLEN(name); - track->name = FLUID_MALLOC(len + 1); - if (track->name == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } - FLUID_STRCPY(track->name, name); - return FLUID_OK; + int len; + if (track->name != NULL) { + FLUID_FREE(track->name); + } + if (name == NULL) { + track->name = NULL; + return FLUID_OK; + } + len = FLUID_STRLEN(name); + track->name = FLUID_MALLOC(len + 1); + if (track->name == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } + FLUID_STRCPY(track->name, name); + return FLUID_OK; } /* @@ -920,7 +921,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name) */ char* fluid_track_get_name(fluid_track_t* track) { - return track->name; + return track->name; } /* @@ -928,13 +929,13 @@ char* fluid_track_get_name(fluid_track_t* track) */ int fluid_track_get_duration(fluid_track_t* track) { - int time = 0; - fluid_midi_event_t* evt = track->first; - while (evt != NULL) { - time += evt->dtime; - evt = evt->next; - } - return time; + int time = 0; + fluid_midi_event_t* evt = track->first; + while (evt != NULL) { + time += evt->dtime; + evt = evt->next; + } + return time; } /* @@ -942,16 +943,16 @@ int fluid_track_get_duration(fluid_track_t* track) */ int fluid_track_count_events(fluid_track_t* track, int* on, int* off) { - fluid_midi_event_t* evt = track->first; - while (evt != NULL) { - if (evt->type == NOTE_ON) { - (*on)++; - } else if (evt->type == NOTE_OFF) { - (*off)++; - } - evt = evt->next; - } - return FLUID_OK; + fluid_midi_event_t* evt = track->first; + while (evt != NULL) { + if (evt->type == NOTE_ON) { + (*on)++; + } else if (evt->type == NOTE_OFF) { + (*off)++; + } + evt = evt->next; + } + return FLUID_OK; } /* @@ -959,16 +960,16 @@ int fluid_track_count_events(fluid_track_t* track, int* on, int* off) */ int fluid_track_add_event(fluid_track_t* track, fluid_midi_event_t* evt) { - evt->next = NULL; - if (track->first == NULL) { - track->first = evt; - track->cur = evt; - track->last = evt; - } else { - track->last->next = evt; - track->last = evt; - } - return FLUID_OK; + evt->next = NULL; + if (track->first == NULL) { + track->first = evt; + track->cur = evt; + track->last = evt; + } else { + track->last->next = evt; + track->last = evt; + } + return FLUID_OK; } /* @@ -976,8 +977,8 @@ int fluid_track_add_event(fluid_track_t* track, fluid_midi_event_t* evt) */ fluid_midi_event_t* fluid_track_first_event(fluid_track_t* track) { - track->cur = track->first; - return track->cur; + track->cur = track->first; + return track->cur; } /* @@ -985,10 +986,10 @@ fluid_midi_event_t* fluid_track_first_event(fluid_track_t* track) */ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track) { - if (track->cur != NULL) { - track->cur = track->cur->next; - } - return track->cur; + if (track->cur != NULL) { + track->cur = track->cur->next; + } + return track->cur; } /* @@ -997,9 +998,9 @@ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track) int fluid_track_reset(fluid_track_t* track) { - track->ticks = 0; - track->cur = track->first; - return FLUID_OK; + track->ticks = 0; + track->cur = track->first; + return FLUID_OK; } /* @@ -1007,38 +1008,38 @@ fluid_track_reset(fluid_track_t* track) */ int fluid_track_send_events(fluid_track_t* track, - fluid_synth_t* synth, - fluid_player_t* player, - unsigned int ticks) + fluid_synth_t* synth, + fluid_player_t* player, + unsigned int ticks) { - int status = FLUID_OK; - fluid_midi_event_t* event; + int status = FLUID_OK; + fluid_midi_event_t* event; - while (1) { + while (1) { - event = track->cur; - if (event == NULL) { - return status; - } + event = track->cur; + if (event == NULL) { + return status; + } -/* printf("track=%d\tticks=%u\ttrack=%u\tdtime=%u\tnext=%u\n", */ -/* track->num, */ -/* ticks, */ -/* track->ticks, */ -/* event->dtime, */ -/* track->ticks + event->dtime); */ +/* printf("track=%02d\tticks=%05u\ttrack=%05u\tdtime=%05u\tnext=%05u\n", */ +/* track->num, */ +/* ticks, */ +/* track->ticks, */ +/* event->dtime, */ +/* track->ticks + event->dtime); */ - if (track->ticks + event->dtime > ticks) { - return status; - } + if (track->ticks + event->dtime > ticks) { + return status; + } - track->ticks += event->dtime; - status = fluid_midi_send_event(synth, player, event); - fluid_track_next_event(track); + track->ticks += event->dtime; + status = fluid_midi_send_event(synth, player, event); + fluid_track_next_event(track); - } - return status; + } + return status; } /****************************************************** @@ -1050,30 +1051,28 @@ fluid_track_send_events(fluid_track_t* track, */ fluid_player_t* new_fluid_player(fluid_synth_t* synth) { - int i; - fluid_player_t* player; - player = FLUID_NEW(fluid_player_t); - if (player == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - player->status = FLUID_PLAYER_READY; - player->loop = 0; - player->ntracks = 0; - for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) { - player->track[i] = NULL; - } - player->synth = synth; - player->timer = NULL; - player->playlist = NULL; - player->current_file = NULL; - player->division = 0; - player->send_program_change = 1; - player->ticks_passed = 0; - player->msec_passed = 0; - player->miditempo = 480000; - player->deltatime = 4.0; - return player; + int i; + fluid_player_t* player; + player = FLUID_NEW(fluid_player_t); + if (player == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + player->status = FLUID_PLAYER_READY; + player->loop = 0; + player->ntracks = 0; + for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) { + player->track[i] = NULL; + } + player->synth = synth; + player->timer = NULL; + player->playlist = NULL; + player->current_file = NULL; + player->division = 0; + player->send_program_change = 1; + player->miditempo = 480000; + player->deltatime = 4.0; + return player; } /* @@ -1081,36 +1080,34 @@ fluid_player_t* new_fluid_player(fluid_synth_t* synth) */ int delete_fluid_player(fluid_player_t* player) { - if (player == NULL) { - return FLUID_OK; - } - fluid_player_stop(player); - fluid_player_reset(player); - FLUID_FREE(player); - return FLUID_OK; + if (player == NULL) { + return FLUID_OK; + } + fluid_player_stop(player); + fluid_player_reset(player); + FLUID_FREE(player); + return FLUID_OK; } int fluid_player_reset(fluid_player_t* player) { - int i; + int i; - for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) { - if (player->track[i] != NULL) { - delete_fluid_track(player->track[i]); - player->track[i] = NULL; - } - } - player->current_file = NULL; - player->status = FLUID_PLAYER_READY; - player->loop = 0; - player->ntracks = 0; - player->division = 0; - player->send_program_change = 1; - player->ticks_passed = 0; - player->msec_passed = 0; - player->miditempo = 480000; - player->deltatime = 4.0; - return 0; + for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) { + if (player->track[i] != NULL) { + delete_fluid_track(player->track[i]); + player->track[i] = NULL; + } + } + player->current_file = NULL; + player->status = FLUID_PLAYER_READY; + player->loop = 0; + player->ntracks = 0; + player->division = 0; + player->send_program_change = 1; + player->miditempo = 480000; + player->deltatime = 4.0; + return 0; } /* @@ -1118,12 +1115,12 @@ int fluid_player_reset(fluid_player_t* player) */ int fluid_player_add_track(fluid_player_t* player, fluid_track_t* track) { - if (player->ntracks < MAX_NUMBER_OF_TRACKS) { - player->track[player->ntracks++] = track; - return FLUID_OK; - } else { - return FLUID_FAILED; - } + if (player->ntracks < MAX_NUMBER_OF_TRACKS) { + player->track[player->ntracks++] = track; + return FLUID_OK; + } else { + return FLUID_FAILED; + } } /* @@ -1131,7 +1128,7 @@ int fluid_player_add_track(fluid_player_t* player, fluid_track_t* track) */ int fluid_player_count_tracks(fluid_player_t* player) { - return player->ntracks; + return player->ntracks; } /* @@ -1139,18 +1136,18 @@ int fluid_player_count_tracks(fluid_player_t* player) */ fluid_track_t* fluid_player_get_track(fluid_player_t* player, int i) { - if ((i >= 0) && (i < MAX_NUMBER_OF_TRACKS)) { - return player->track[i]; - } else { - return NULL; - } + if ((i >= 0) && (i < MAX_NUMBER_OF_TRACKS)) { + return player->track[i]; + } else { + return NULL; + } } int fluid_player_add(fluid_player_t* player, char* midifile) { - char *s = FLUID_STRDUP(midifile); - player->playlist = fluid_list_append(player->playlist, s); - return 0; + char *s = FLUID_STRDUP(midifile); + player->playlist = fluid_list_append(player->playlist, s); + return 0; } /* @@ -1158,21 +1155,21 @@ int fluid_player_add(fluid_player_t* player, char* midifile) */ int fluid_player_load(fluid_player_t* player, char *filename) { - fluid_midi_file* midifile; + fluid_midi_file* midifile; - midifile = new_fluid_midi_file(filename); - if (midifile == NULL) { - return FLUID_FAILED; - } - player->division = fluid_midi_file_get_division(midifile); + midifile = new_fluid_midi_file(filename); + if (midifile == NULL) { + return FLUID_FAILED; + } + player->division = fluid_midi_file_get_division(midifile); - /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */ + /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */ - if (fluid_midi_file_load_tracks(midifile, player) != FLUID_OK){ - return FLUID_FAILED; - } - delete_fluid_midi_file(midifile); - return FLUID_OK; + if (fluid_midi_file_load_tracks(midifile, player) != FLUID_OK){ + return FLUID_FAILED; + } + delete_fluid_midi_file(midifile); + return FLUID_OK; } /* @@ -1180,68 +1177,64 @@ int fluid_player_load(fluid_player_t* player, char *filename) */ int fluid_player_callback(void* data, unsigned int msec) { - int i; - unsigned int ticks; - unsigned int delta_ticks; - int status = FLUID_PLAYER_DONE; - fluid_player_t* player; - fluid_synth_t* synth; - player = (fluid_player_t*) data; - synth = player->synth; + int i; + unsigned int ticks; + unsigned int delta_ticks; + int status = FLUID_PLAYER_DONE; + fluid_player_t* player; + fluid_synth_t* synth; + player = (fluid_player_t*) data; + synth = player->synth; - /* Load the next file if necessary */ - while (player->current_file == NULL) { + /* Load the next file if necessary */ + while (player->current_file == NULL) { - if (player->playlist == NULL) { - return 0; - } + if (player->playlist == NULL) { + return 0; + } - fluid_player_reset(player); + fluid_player_reset(player); - player->current_file = fluid_list_get(player->playlist); - player->playlist = fluid_list_next(player->playlist); + player->current_file = fluid_list_get(player->playlist); + player->playlist = fluid_list_next(player->playlist); - FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__, player->current_file); + FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__, player->current_file); - if (fluid_player_load(player, player->current_file) == FLUID_OK) { + if (fluid_player_load(player, player->current_file) == FLUID_OK) { - player->ticks_passed = 0; - player->msec_passed = 0; + player->start_msec = msec; - for (i = 0; i < player->ntracks; i++) { - if (player->track[i] != NULL) { - fluid_track_reset(player->track[i]); + for (i = 0; i < player->ntracks; i++) { + if (player->track[i] != NULL) { + fluid_track_reset(player->track[i]); + } + } + + } else { + player->current_file = NULL; + } } - } - } else { - player->current_file = NULL; - } - } + ticks = (unsigned int) (((double) msec - (double) player->start_msec) / player->deltatime); + + for (i = 0; i < player->ntracks; i++) { + if (!fluid_track_eot(player->track[i])) { + status = FLUID_PLAYER_PLAYING; + if (fluid_track_send_events(player->track[i], synth, player, ticks) != FLUID_OK) { + /* */ + } + } + } - delta_ticks = (unsigned int) (((double) msec - (double) player->msec_passed) - / player->deltatime); + player->status = status; - ticks = player->ticks_passed + delta_ticks; + if (player->status == FLUID_PLAYER_DONE) { + FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", + __FILE__, __LINE__, (msec - player->start_msec) / 1000.0); + player->current_file = NULL; + } - for (i = 0; i < player->ntracks; i++) { - if (!fluid_track_eot(player->track[i])) { - status = FLUID_PLAYER_PLAYING; - if (fluid_track_send_events(player->track[i], synth, player, ticks) != FLUID_OK) { - /* */ - } - } - } - - player->status = status; - player->ticks_passed = ticks; - player->msec_passed = msec; - - if (player->status == FLUID_PLAYER_DONE) { - player->current_file = NULL; - } - - return 1; + return 1; } /* @@ -1249,22 +1242,22 @@ int fluid_player_callback(void* data, unsigned int msec) */ int fluid_player_play(fluid_player_t* player) { - if (player->status == FLUID_PLAYER_PLAYING) { - return FLUID_OK; - } + if (player->status == FLUID_PLAYER_PLAYING) { + return FLUID_OK; + } - if (player->playlist == NULL) { - return FLUID_OK; - } + if (player->playlist == NULL) { + return FLUID_OK; + } - player->status = FLUID_PLAYER_PLAYING; + player->status = FLUID_PLAYER_PLAYING; - player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback, - (void*) player, 1, 0); - if (player->timer == NULL) { - return FLUID_FAILED; - } - return FLUID_OK; + player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback, + (void*) player, 1, 0); + if (player->timer == NULL) { + return FLUID_FAILED; + } + return FLUID_OK; } /* @@ -1272,12 +1265,12 @@ int fluid_player_play(fluid_player_t* player) */ int fluid_player_stop(fluid_player_t* player) { - if (player->timer != NULL) { - delete_fluid_timer(player->timer); - } - player->status = FLUID_PLAYER_DONE; - player->timer = NULL; - return FLUID_OK; + if (player->timer != NULL) { + delete_fluid_timer(player->timer); + } + player->status = FLUID_PLAYER_DONE; + player->timer = NULL; + return FLUID_OK; } /* @@ -1285,8 +1278,8 @@ int fluid_player_stop(fluid_player_t* player) */ int fluid_player_set_loop(fluid_player_t* player, int loop) { - player->loop = loop; - return FLUID_OK; + player->loop = loop; + return FLUID_OK; } /* @@ -1294,13 +1287,13 @@ int fluid_player_set_loop(fluid_player_t* player, int loop) */ int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo) { - player->miditempo = tempo; - player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */ + player->miditempo = tempo; + player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */ - FLUID_LOG(FLUID_DBG,"tempo=%d\n", tempo); - FLUID_LOG(FLUID_DBG,"tick time=%f msec\n", player->deltatime); + FLUID_LOG(FLUID_DBG,"tempo=%d", tempo); + FLUID_LOG(FLUID_DBG,"tick time=%f msec", player->deltatime); - return FLUID_OK; + return FLUID_OK; } /* @@ -1308,7 +1301,7 @@ int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo) */ int fluid_player_set_bpm(fluid_player_t* player, int bpm) { - return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm)); + return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm)); } /* @@ -1316,7 +1309,7 @@ int fluid_player_set_bpm(fluid_player_t* player, int bpm) */ int fluid_player_join(fluid_player_t* player) { - return player->timer? fluid_timer_join(player->timer) : FLUID_OK; + return player->timer? fluid_timer_join(player->timer) : FLUID_OK; } /************************************************************************ @@ -1329,14 +1322,14 @@ int fluid_player_join(fluid_player_t* player) */ fluid_midi_parser_t* new_fluid_midi_parser() { - fluid_midi_parser_t* parser; - parser = FLUID_NEW(fluid_midi_parser_t); - if (parser == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */ - return parser; + fluid_midi_parser_t* parser; + parser = FLUID_NEW(fluid_midi_parser_t); + if (parser == NULL) { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + parser->status = 0; /* As long as the status is 0, the parser won't do anything -> no need to initialize all the fields. */ + return parser; } /* @@ -1344,8 +1337,8 @@ fluid_midi_parser_t* new_fluid_midi_parser() */ int delete_fluid_midi_parser(fluid_midi_parser_t* parser) { - FLUID_FREE(parser); - return FLUID_OK; + FLUID_FREE(parser); + return FLUID_OK; } /* @@ -1358,127 +1351,127 @@ int delete_fluid_midi_parser(fluid_midi_parser_t* parser) */ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigned char c) { - /*********************************************************************/ - /* 'Process' system real-time messages */ - /*********************************************************************/ - /* There are not too many real-time messages that are of interest here. - * They can occur anywhere, even in the middle of a noteon message! - * Real-time range: 0xF8 .. 0xFF - * Note: Real-time does not affect (running) status. - */ - if (c >= 0xF8){ - if (c == MIDI_SYSTEM_RESET){ - parser->event.type = c; - parser->status = 0; /* clear the status */ - return &parser->event; - }; - return NULL; - }; + /*********************************************************************/ + /* 'Process' system real-time messages */ + /*********************************************************************/ + /* There are not too many real-time messages that are of interest here. + * They can occur anywhere, even in the middle of a noteon message! + * Real-time range: 0xF8 .. 0xFF + * Note: Real-time does not affect (running) status. + */ + if (c >= 0xF8){ + if (c == MIDI_SYSTEM_RESET){ + parser->event.type = c; + parser->status = 0; /* clear the status */ + return &parser->event; + }; + return NULL; + }; - /*********************************************************************/ - /* 'Process' system common messages (again, just skip them) */ - /*********************************************************************/ - /* There are no system common messages that are of interest here. - * System common range: 0xF0 .. 0xF7 - */ + /*********************************************************************/ + /* 'Process' system common messages (again, just skip them) */ + /*********************************************************************/ + /* There are no system common messages that are of interest here. + * System common range: 0xF0 .. 0xF7 + */ - if (c > 0xF0){ - /* MIDI specs say: To ignore a non-real-time message, just discard all data up to - * the next status byte. - * And our parser will ignore data that is received without a valid status. - * Note: system common cancels running status. */ - parser->status = 0; - return NULL; - }; + if (c > 0xF0){ + /* MIDI specs say: To ignore a non-real-time message, just discard all data up to + * the next status byte. + * And our parser will ignore data that is received without a valid status. + * Note: system common cancels running status. */ + parser->status = 0; + return NULL; + }; - /*********************************************************************/ - /* Process voice category messages: */ - /*********************************************************************/ - /* Now that we have handled realtime and system common messages, only - * voice messages are left. - * Only a status byte has bit # 7 set. - * So no matter the status of the parser (in case we have lost sync), - * as soon as a byte >= 0x80 comes in, we are dealing with a status byte - * and start a new event. - */ + /*********************************************************************/ + /* Process voice category messages: */ + /*********************************************************************/ + /* Now that we have handled realtime and system common messages, only + * voice messages are left. + * Only a status byte has bit # 7 set. + * So no matter the status of the parser (in case we have lost sync), + * as soon as a byte >= 0x80 comes in, we are dealing with a status byte + * and start a new event. + */ - if (c & 0x80){ - parser->channel = c & 0x0F; - parser->status = c & 0xF0; - /* The event consumes x bytes of data... (subtract 1 for the status byte) */ - parser->nr_bytes_total=fluid_midi_event_length(parser->status)-1; - /* of which we have read 0 at this time. */ - parser->nr_bytes = 0; - return NULL; - }; + if (c & 0x80){ + parser->channel = c & 0x0F; + parser->status = c & 0xF0; + /* The event consumes x bytes of data... (subtract 1 for the status byte) */ + parser->nr_bytes_total=fluid_midi_event_length(parser->status)-1; + /* of which we have read 0 at this time. */ + parser->nr_bytes = 0; + return NULL; + }; - /*********************************************************************/ - /* Process data */ - /*********************************************************************/ - /* If we made it this far, then the received char belongs to the data - * of the last event. */ - if (parser->status == 0){ - /* We are not interested in the event currently received. - * Discard the data. */ - return NULL; - }; + /*********************************************************************/ + /* Process data */ + /*********************************************************************/ + /* If we made it this far, then the received char belongs to the data + * of the last event. */ + if (parser->status == 0){ + /* We are not interested in the event currently received. + * Discard the data. */ + return NULL; + }; - /* Store the first couple of bytes */ - if (parser->nr_bytes < FLUID_MIDI_PARSER_MAX_PAR){ - parser->p[parser->nr_bytes]=c; - }; - parser->nr_bytes++; + /* Store the first couple of bytes */ + if (parser->nr_bytes < FLUID_MIDI_PARSER_MAX_PAR){ + parser->p[parser->nr_bytes]=c; + }; + parser->nr_bytes++; - /* Do we still need more data to get this event complete? */ - if (parser->nr_bytes < parser->nr_bytes_total){ - return NULL; - }; + /* Do we still need more data to get this event complete? */ + if (parser->nr_bytes < parser->nr_bytes_total){ + return NULL; + }; - /*********************************************************************/ - /* Send the event */ - /*********************************************************************/ - /* The event is ready-to-go. - * About 'running status': - * The MIDI protocol has a built-in compression mechanism. If several similar events are sent - * in-a-row, for example note-ons, then the event type is only sent once. For this case, - * the last event type (status) is remembered. - * We simply keep the status as it is, just reset - * the parameter counter. If another status byte comes in, it will overwrite the status. */ - parser->event.type = parser->status; - parser->event.channel = parser->channel; - parser->nr_bytes = 0; /* Related to running status! */ - switch (parser->status){ - case NOTE_OFF: - case NOTE_ON: - case KEY_PRESSURE: - case CONTROL_CHANGE: - case PROGRAM_CHANGE: - case CHANNEL_PRESSURE: - parser->event.param1 = parser->p[0]; /* For example key number */ - parser->event.param2 = parser->p[1]; /* For example velocity */ - break; - case PITCH_BEND: - /* Pitch-bend is transmitted with 14-bit precision. */ - parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */ - break; - default: - /* Unlikely */ - return NULL; - }; - return &parser->event; + /*********************************************************************/ + /* Send the event */ + /*********************************************************************/ + /* The event is ready-to-go. + * About 'running status': + * The MIDI protocol has a built-in compression mechanism. If several similar events are sent + * in-a-row, for example note-ons, then the event type is only sent once. For this case, + * the last event type (status) is remembered. + * We simply keep the status as it is, just reset + * the parameter counter. If another status byte comes in, it will overwrite the status. */ + parser->event.type = parser->status; + parser->event.channel = parser->channel; + parser->nr_bytes = 0; /* Related to running status! */ + switch (parser->status){ + case NOTE_OFF: + case NOTE_ON: + case KEY_PRESSURE: + case CONTROL_CHANGE: + case PROGRAM_CHANGE: + case CHANNEL_PRESSURE: + parser->event.param1 = parser->p[0]; /* For example key number */ + parser->event.param2 = parser->p[1]; /* For example velocity */ + break; + case PITCH_BEND: + /* Pitch-bend is transmitted with 14-bit precision. */ + parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */ + break; + default: + /* Unlikely */ + return NULL; + }; + return &parser->event; }; /* Purpose: * Returns the length of the MIDI message starting with c. * Taken from Nagano Daisuke's USB-MIDI driver */ int fluid_midi_event_length(unsigned char event){ - if ( event < 0xf0 ) { - return remains_80e0[((event-0x80)>>4)&0x0f]; - } else if ( event < 0xf7 ) { - return remains_f0f6[event-0xf0]; - } else { - return 1; - } + if ( event < 0xf0 ) { + return remains_80e0[((event-0x80)>>4)&0x0f]; + } else if ( event < 0xf7 ) { + return remains_f0f6[event-0xf0]; + } else { + return 1; + } } /************************************************************************ @@ -1489,43 +1482,43 @@ int fluid_midi_event_length(unsigned char event){ */ int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, fluid_midi_event_t* event) { - switch (event->type) { - case NOTE_ON: - if (fluid_synth_noteon(synth, event->channel, event->param1, event->param2) != FLUID_OK) { - return FLUID_FAILED; - } - break; - case NOTE_OFF: - if (fluid_synth_noteoff(synth, event->channel, event->param1) != FLUID_OK) { - return FLUID_FAILED; - } - break; - case CONTROL_CHANGE: - if (fluid_synth_cc(synth, event->channel, event->param1, event->param2) != FLUID_OK) { - return FLUID_FAILED; - } - break; - case MIDI_SET_TEMPO: - if (player != NULL) { - if (fluid_player_set_midi_tempo(player, event->param1) != FLUID_OK) { - return FLUID_FAILED; - } - } - break; - case PROGRAM_CHANGE: - if (fluid_synth_program_change(synth, event->channel, event->param1) != FLUID_OK) { - return FLUID_FAILED; - } - break; - case PITCH_BEND: - if (fluid_synth_pitch_bend(synth, event->channel, event->param1) != FLUID_OK) { - return FLUID_FAILED; - } - break; - default: - break; - } - return FLUID_OK; + switch (event->type) { + case NOTE_ON: + if (fluid_synth_noteon(synth, event->channel, event->param1, event->param2) != FLUID_OK) { + return FLUID_FAILED; + } + break; + case NOTE_OFF: + if (fluid_synth_noteoff(synth, event->channel, event->param1) != FLUID_OK) { + return FLUID_FAILED; + } + break; + case CONTROL_CHANGE: + if (fluid_synth_cc(synth, event->channel, event->param1, event->param2) != FLUID_OK) { + return FLUID_FAILED; + } + break; + case MIDI_SET_TEMPO: + if (player != NULL) { + if (fluid_player_set_midi_tempo(player, event->param1) != FLUID_OK) { + return FLUID_FAILED; + } + } + break; + case PROGRAM_CHANGE: + if (fluid_synth_program_change(synth, event->channel, event->param1) != FLUID_OK) { + return FLUID_FAILED; + } + break; + case PITCH_BEND: + if (fluid_synth_pitch_bend(synth, event->channel, event->param1) != FLUID_OK) { + return FLUID_FAILED; + } + break; + default: + break; + } + return FLUID_OK; } diff --git a/fluidsynth/src/fluid_midi.h b/fluidsynth/src/fluid_midi.h index 923301e2..47edda7f 100644 --- a/fluidsynth/src/fluid_midi.h +++ b/fluidsynth/src/fluid_midi.h @@ -243,8 +243,7 @@ struct _fluid_player_t { fluid_list_t* playlist; char* current_file; char send_program_change; /* should we ignore the program changes? */ - int ticks_passed; /* number of midi ticks that have passed */ - int msec_passed; /* number of milliseconds that have passed */ + int start_msec; /* the start of the file */ int miditempo; /* as indicated by MIDI SetTempo: n 24th of a usec per midi-clock. bravo! */ double deltatime; /* milliseconds per midi tick. depends on set-tempo */ unsigned int division; diff --git a/fluidsynth/src/fluidsynth.c b/fluidsynth/src/fluidsynth.c index 5fa90a30..6379a418 100644 --- a/fluidsynth/src/fluidsynth.c +++ b/fluidsynth/src/fluidsynth.c @@ -92,20 +92,6 @@ extern int optind, opterr, optopt; #endif -/* is_number - * - * don't shoot me - */ -int is_number(char *a) -{ - for (; *a != 0; a++) { - if (((*a < '0') || (*a > '9')) && (*a != '-') && (*a != '+') && (*a != '.')) { - return 0; - } - } - return 1; -} - /* process_o_cmd_line_option * * Purpose: