mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-07 08:14:11 +00:00
Added bank offsets for SoundFonts (proposition by Ken Ellinwood)
This commit is contained in:
parent
08d0adca72
commit
d5983ca43f
8 changed files with 177 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue