diff --git a/fluidsynth/AUTHORS b/fluidsynth/AUTHORS index d41e0312..dc70cc3e 100644 --- a/fluidsynth/AUTHORS +++ b/fluidsynth/AUTHORS @@ -11,7 +11,8 @@ fixes. The project was started by Peter Hanappe who is the main author. Below you'll find a summery of contributions. -* Peter Hanappe. files: sticked it's hand in all files. +* Peter Hanappe. Initiated the project. files: sticked his nose in all + files. * Josh Green contributed a lot of code directly or indirectly through the Swami and Smurf code base. The soundfont loader is @@ -46,7 +47,7 @@ author. Below you'll find a summery of contributions. * Tim Goetze sent many patches and implemented the all_notes_off. He also sent his code for the new ALSA driver. files: iiwu_synth.c, -iiwu_chan.c, iiwu_voice.c, iiwu_alsa.c + iiwu_chan.c, iiwu_voice.c, iiwu_alsa.c * Norbert Schnell from Ircam's jMax Team wrote most of the jMax/FTS interface in a record time. He also pointed me to the technique of @@ -82,6 +83,10 @@ iiwu_chan.c, iiwu_voice.c, iiwu_alsa.c the iiwu_midi file. Martin Uddén file: iiwu_midi.c +* Ken Ellinwood send in a patch to add bank offsets to SoundFonts. An + adapted version was integrated in the source code. files: + fluid_cmd.c, fluidsynth/synth.h, fluid_synth.c. + * I copied some interpolation algorihms that I found in the music-dsp archives (http://www.smartelectronix.com/musicdsp). They were written by Joshua Scholar and others. file: iiwu_synth.c diff --git a/fluidsynth/ChangeLog b/fluidsynth/ChangeLog index 5fd410e9..b8d975f3 100644 --- a/fluidsynth/ChangeLog +++ b/fluidsynth/ChangeLog @@ -1,3 +1,9 @@ +2004-08-18 + + * src/fluid_synth.c (fluid_synth_set_bank_offset): + (fluid_synth_get_bank_offset): New API to set + a bank offset in a SoundFont (proposition made by Ken Ellinwood). + 2004-08-06 * src/fluid_synth.c (fluid_synth_noteon): @@ -9,7 +15,7 @@ * src/fluid_chan.c (fluid_channel_cc): Applied Ken Ellinwood's fix for the bank select (MSB) message. - + * src/fluid_jack.c (fluid_jack_audio_driver_settings): Applied Rui Nuno Capela's patch diff --git a/fluidsynth/THANKS b/fluidsynth/THANKS index 01129529..a9db234e 100644 --- a/fluidsynth/THANKS +++ b/fluidsynth/THANKS @@ -15,7 +15,7 @@ Raoul Bonisch Rui Nuno Capela Jake Commander Francois Dechelle -Ken Ellinwood +Ken Ellinwood Tim Goetze Anthony Green Josh Green @@ -29,7 +29,7 @@ Ebrahim Mayat Juergen Mueller Markus Nentwig David Olofson -Sergey Pavlishin +Sergey Pavlishin Dave Phillips Daniel Pressnitzer Gerald Pye diff --git a/fluidsynth/configure.ac b/fluidsynth/configure.ac index 371f666d..357e0d1d 100644 --- a/fluidsynth/configure.ac +++ b/fluidsynth/configure.ac @@ -6,9 +6,8 @@ AC_INIT(src/fluidsynth.c) FLUIDSYNTH_VERSION_MAJOR=1 FLUIDSYNTH_VERSION_MINOR=0 -FLUIDSYNTH_VERSION_MICRO=4 -FLUIDSYNTH_VERSION_PL=2 -FLUIDSYNTH_VERSION=$FLUIDSYNTH_VERSION_MAJOR.$FLUIDSYNTH_VERSION_MINOR.$FLUIDSYNTH_VERSION_MICRO-$FLUIDSYNTH_VERSION_PL +FLUIDSYNTH_VERSION_MICRO=5 +FLUIDSYNTH_VERSION=$FLUIDSYNTH_VERSION_MAJOR.$FLUIDSYNTH_VERSION_MINOR.$FLUIDSYNTH_VERSION_MICRO AC_SUBST(FLUIDSYNTH_VERSION_MAJOR) AC_SUBST(FLUIDSYNTH_VERSION_MINOR) diff --git a/fluidsynth/include/fluidsynth/synth.h b/fluidsynth/include/fluidsynth/synth.h index 0e77861d..1eddc93b 100644 --- a/fluidsynth/include/fluidsynth/synth.h +++ b/fluidsynth/include/fluidsynth/synth.h @@ -258,6 +258,12 @@ FLUIDSYNTH_API fluid_sfont_t* fluid_synth_get_sfont_by_id(fluid_synth_t* synth, /** Get the preset of a channel */ FLUIDSYNTH_API fluid_preset_t* fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan); + /** Offset the bank numbers in a SoundFont. Returns -1 if an error + * occured (out of memory or negative offset) */ +FLUIDSYNTH_API int fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset); + + /** Get the offset of the bank numbers in a SoundFont. */ +FLUIDSYNTH_API int fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id); diff --git a/fluidsynth/src/fluid_cmd.c b/fluidsynth/src/fluid_cmd.c index ea0b5fc5..57ed1263 100644 --- a/fluidsynth/src/fluid_cmd.c +++ b/fluidsynth/src/fluid_cmd.c @@ -63,9 +63,9 @@ fluid_cmd_t fluid_commands[] = { { "select", "event", (fluid_cmd_func_t) fluid_handle_select, NULL, "select chan sfont bank prog Combination of bank-select and program-change" }, { "load", "general", (fluid_cmd_func_t) fluid_handle_load, NULL, - "load file [reset] Load a SoundFont (reset=0|1, optional, default=1)" }, + "load file [reset] [bank_offset] Load a SoundFont (reset=0|1, default 1; bank_offset=n, default 0)" }, { "unload", "general", (fluid_cmd_func_t) fluid_handle_unload, NULL, - "unload id [reset] Unload the SoundFont with the specified ID (reset=0|1, def=1)"}, + "unload id [reset] Unload the SoundFont with the specified ID (reset=0|1, default 1)"}, { "reload", "general", (fluid_cmd_func_t) fluid_handle_reload, NULL, "reload id Reload the SoundFont with the specified ID" }, { "fonts", "general", (fluid_cmd_func_t) fluid_handle_fonts, NULL, @@ -430,6 +430,11 @@ fluid_handle_prog(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) int fluid_handle_select(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { + int sfont_id; + int chan; + int bank; + int prog; + if (ac < 4) { fluid_ostream_printf(out, "preset: too few arguments\n"); return -1; @@ -439,7 +444,20 @@ fluid_handle_select(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out fluid_ostream_printf(out, "preset: invalid argument\n"); return -1; } - return fluid_synth_program_select(synth, atoi(av[0]), atoi(av[1]), atoi(av[2]), atoi(av[3])); + + chan = atoi(av[0]); + sfont_id = atoi(av[1]); + bank = atoi(av[2]); + prog = atoi(av[3]); + + if (sfont_id != 0) { + return fluid_synth_program_select(synth, chan, sfont_id, bank, prog); + } else { + if (fluid_synth_bank_select(synth, chan, bank) == FLUID_OK) { + return fluid_synth_program_change(synth, chan, prog); + } + return FLUID_FAILED; + } } int @@ -448,6 +466,7 @@ fluid_handle_inst(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) int font; fluid_sfont_t* sfont; fluid_preset_t preset; + int offset; if (ac < 1) { fluid_ostream_printf(out, "inst: too few arguments\n"); @@ -462,6 +481,7 @@ fluid_handle_inst(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) font = atoi(av[0]); sfont = fluid_synth_get_sfont_by_id(synth, font); + offset = fluid_synth_get_bank_offset(synth, font); if (sfont == NULL) { fluid_ostream_printf(out, "inst: invalid font number\n"); @@ -472,7 +492,7 @@ fluid_handle_inst(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) while (fluid_sfont_iteration_next(sfont, &preset)) { fluid_ostream_printf(out, "%03d-%03d %s\n", - fluid_preset_get_banknum(&preset), + fluid_preset_get_banknum(&preset) + offset, fluid_preset_get_num(&preset), fluid_preset_get_name(&preset)); } @@ -509,6 +529,8 @@ fluid_handle_load(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) char buf[1024]; int id; int reset = 1; + int offset = 0; + if (ac < 1) { fluid_ostream_printf(out, "load: too few arguments\n"); return -1; @@ -516,13 +538,30 @@ fluid_handle_load(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) if (ac == 2) { reset = atoi(av[1]); } - id = fluid_synth_sfload(synth, fluid_expand_path(av[0], buf, 1024), reset); + if (ac == 3) { + offset = atoi(av[2]); + } + + /* Load the SoundFont without resetting the programs. The reset will + * be done later (if requested). */ + id = fluid_synth_sfload(synth, fluid_expand_path(av[0], buf, 1024), 0); + if (id == -1) { fluid_ostream_printf(out, "failed to load the SoundFont\n"); return -1; } else { fluid_ostream_printf(out, "loaded SoundFont has ID %d\n", id); } + + if (offset) { + fluid_synth_set_bank_offset(synth, id, offset); + } + + /* The reset should be done after the offset is set. */ + if (reset) { + fluid_synth_program_reset(synth); + } + return 0; } diff --git a/fluidsynth/src/fluid_synth.c b/fluidsynth/src/fluid_synth.c index 7b8e7ce6..6f9cdfe6 100644 --- a/fluidsynth/src/fluid_synth.c +++ b/fluidsynth/src/fluid_synth.c @@ -589,6 +589,7 @@ delete_fluid_synth(fluid_synth_t* synth) int i, k; fluid_list_t *list; fluid_sfont_t* sfont; + fluid_bank_offset_t* bank_offset; fluid_sfloader_t* loader; if (synth == NULL) { @@ -600,13 +601,21 @@ delete_fluid_synth(fluid_synth_t* synth) synth->state = FLUID_SYNTH_STOPPED; /* delete all the SoundFonts */ - for (list = synth->sfont; list; list = fluid_list_next(list)) { sfont = (fluid_sfont_t*) fluid_list_get(list); delete_fluid_sfont(sfont); } delete_fluid_list(synth->sfont); + + /* and the SoundFont offsets */ + for (list = synth->bank_offsets; list; list = fluid_list_next(list)) { + bank_offset = (fluid_bank_offset_t*) fluid_list_get(list); + FLUID_FREE(bank_offset); + } + + delete_fluid_list(synth->bank_offsets); + /* delete all the SoundFont loaders */ @@ -626,6 +635,7 @@ delete_fluid_synth(fluid_synth_t* synth) } FLUID_FREE(synth->channel); } + if (synth->voice != NULL) { for (i = 0; i < synth->nvoice; i++) { if (synth->voice[i] != NULL) { @@ -644,6 +654,7 @@ delete_fluid_synth(fluid_synth_t* synth) } FLUID_FREE(synth->left_ubuf); } + if (synth->right_ubuf != NULL) { for (i = 0; i < synth->nbuf; i++) { if (synth->right_ubuf[i] != NULL) { @@ -652,6 +663,7 @@ delete_fluid_synth(fluid_synth_t* synth) } FLUID_FREE(synth->right_ubuf); } + if (synth->fx_left_ubuf != NULL) { for (i = 0; i < 2; i++) { if (synth->fx_left_ubuf[i] != NULL) { @@ -1082,11 +1094,13 @@ fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum, fluid_preset_t* preset = NULL; fluid_sfont_t* sfont = NULL; fluid_list_t* list = synth->sfont; + int offset; sfont = fluid_synth_get_sfont_by_id(synth, sfontnum); if (sfont != NULL) { - preset = fluid_sfont_get_preset(sfont, banknum, prognum); + offset = fluid_synth_get_bank_offset(synth, sfontnum); + preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum); if (preset != NULL) { return preset; } @@ -1103,11 +1117,13 @@ fluid_synth_get_preset2(fluid_synth_t* synth, char* sfont_name, { fluid_preset_t* preset = NULL; fluid_sfont_t* sfont = NULL; + int offset; sfont = fluid_synth_get_sfont_by_name(synth, sfont_name); if (sfont != NULL) { - preset = fluid_sfont_get_preset(sfont, banknum, prognum); + offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont)); + preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum); if (preset != NULL) { return preset; } @@ -1122,11 +1138,13 @@ fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, fluid_preset_t* preset = NULL; fluid_sfont_t* sfont = NULL; fluid_list_t* list = synth->sfont; + int offset; while (list) { sfont = (fluid_sfont_t*) fluid_list_get(list); - preset = fluid_sfont_get_preset(sfont, banknum, prognum); + offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont)); + preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum); if (preset != NULL) { preset->sfont = sfont; /* FIXME */ @@ -1285,6 +1303,7 @@ int fluid_synth_program_select2(fluid_synth_t* synth, fluid_preset_t* preset = NULL; fluid_channel_t* channel; fluid_sfont_t* sfont = NULL; + int offset; if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_ERR, "Channel number out of range (chan=%d)", chan); @@ -1298,7 +1317,8 @@ int fluid_synth_program_select2(fluid_synth_t* synth, return FLUID_FAILED; } - preset = fluid_sfont_get_preset(sfont, bank_num, preset_num); + offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont)); + preset = fluid_sfont_get_preset(sfont, bank_num - offset, preset_num); if (preset == NULL) { FLUID_LOG(FLUID_ERR, "There is no preset with bank number %d and preset number %d in SoundFont %s", @@ -2104,7 +2124,7 @@ fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets if (sfont != NULL) { - sfont->id = synth->sfont_id++; + sfont->id = ++synth->sfont_id; /* insert the sfont as the first one on the list */ synth->sfont = fluid_list_prepend(synth->sfont, sfont); @@ -2259,7 +2279,7 @@ int fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id) */ int fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) { - sfont->id = synth->sfont_id++; + sfont->id = ++synth->sfont_id; /* insert the sfont as the first one on the list */ synth->sfont = fluid_list_prepend(synth->sfont, sfont); @@ -2276,7 +2296,12 @@ int fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) */ void fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) { + int sfont_id = fluid_sfont_get_id(sfont); + synth->sfont = fluid_list_remove(synth->sfont, sfont); + + /* remove a possible bank offset */ + fluid_synth_remove_bank_offset(synth, sfont_id); /* reset the presets for all channels */ fluid_synth_program_reset(synth); @@ -2954,3 +2979,64 @@ int fluid_synth_stop(fluid_synth_t* synth, unsigned int id) return status; } + +fluid_bank_offset_t* +fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id) +{ + fluid_list_t* list = synth->bank_offsets; + fluid_bank_offset_t* offset; + + while (list) { + + offset = (fluid_bank_offset_t*) fluid_list_get(list); + if (offset->sfont_id == sfont_id) { + return offset; + } + + list = fluid_list_next(list); + } + + return NULL; +} + +int +fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset) +{ + fluid_bank_offset_t* bank_offset; + + bank_offset = fluid_synth_get_bank_offset0(synth, sfont_id); + + if (bank_offset == NULL) { + bank_offset = FLUID_NEW(fluid_bank_offset_t); + if (bank_offset == NULL) { + return -1; + } + bank_offset->sfont_id = sfont_id; + bank_offset->offset = offset; + synth->bank_offsets = fluid_list_prepend(synth->bank_offsets, bank_offset); + } else { + bank_offset->offset = offset; + } + + return 0; +} + +int +fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id) +{ + fluid_bank_offset_t* bank_offset; + + bank_offset = fluid_synth_get_bank_offset0(synth, sfont_id); + return (bank_offset == NULL)? 0 : bank_offset->offset; +} + +void +fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id) +{ + fluid_bank_offset_t* bank_offset; + + bank_offset = fluid_synth_get_bank_offset0(synth, sfont_id); + if (bank_offset != NULL) { + synth->bank_offsets = fluid_list_remove(synth->bank_offsets, bank_offset); + } +} diff --git a/fluidsynth/src/fluid_synth.h b/fluidsynth/src/fluid_synth.h index 3e09ecd3..48c8950c 100644 --- a/fluidsynth/src/fluid_synth.h +++ b/fluidsynth/src/fluid_synth.h @@ -73,6 +73,15 @@ enum fluid_synth_status FLUID_SYNTH_STOPPED }; + +typedef struct _fluid_bank_offset_t fluid_bank_offset_t; + +struct _fluid_bank_offset_t { + int sfont_id; + int offset; +}; + + /* * fluid_synth_t */ @@ -99,6 +108,8 @@ struct _fluid_synth_t fluid_list_t *loaders; /** the soundfont loaders */ fluid_list_t* sfont; /** the loaded soundfont */ unsigned int sfont_id; + fluid_list_t* bank_offsets; /** the offsets of the soundfont banks */ + #if defined(MACOS9) fluid_list_t* unloading; /** the soundfonts that need to be unloaded */ #endif @@ -195,6 +206,11 @@ void fluid_synth_update_presets(fluid_synth_t* synth); int fluid_synth_update_gain(fluid_synth_t* synth, char* name, double value); +fluid_bank_offset_t* fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id); +void fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id); + + + /* * misc */