Added bank offsets for SoundFonts (proposition by Ken Ellinwood)

This commit is contained in:
Peter Hanappe 2004-08-18 15:11:47 +00:00
parent 08d0adca72
commit d5983ca43f
8 changed files with 177 additions and 20 deletions

View file

@ -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 <nanook@lysator.liu.se> 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

View file

@ -1,3 +1,9 @@
2004-08-18 <peter@hanappe.com>
* 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 <peter@hanappe.com>
* 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

View file

@ -15,7 +15,7 @@ Raoul Bonisch <jkl345 at gmx dot net>
Rui Nuno Capela <rncbc at rncbc dot org>
Jake Commander <jakec at ukfirst dot co dot uk>
Francois Dechelle <Francois dot Dechelle at ircam dot fr>
Ken Ellinwood <kellinwood@yahoo.com>
Ken Ellinwood <kellinwood at yahoo dot com>
Tim Goetze <tim at quitte dot de>
Anthony Green <green at redhat dot com>
Josh Green <jgreen at users dot sourceforge dot net>
@ -29,7 +29,7 @@ Ebrahim Mayat <ebmayat at mac dot com>
Juergen Mueller
Markus Nentwig <nentwig at users dot sourceforge dot net>
David Olofson <david at olofson dot net>
Sergey Pavlishin <xlogo@mail.ru>
Sergey Pavlishin <xlogo at mail dot ru>
Dave Phillips
Daniel Pressnitzer <pressnit at ircam dot fr>
Gerald Pye <mail at edenyard dot co dot uk>

View file

@ -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)

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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
*/