diff --git a/bindings/fluidmax/fluidmax.c b/bindings/fluidmax/fluidmax.c index fc6b3929..5980c45d 100644 --- a/bindings/fluidmax/fluidmax.c +++ b/bindings/fluidmax/fluidmax.c @@ -13,20 +13,20 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. - * + * * See file COPYING.LIB for further informations on licensing terms. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. * */ - + /************************************************************************ * * versions: @@ -40,7 +40,7 @@ * (7): added names for soundfonts (== file name without path and postfix) * (6): added message 'info' * (5): fixed bogus path translation at file loading - * + * */ #define FLUIDMAX_VERSION "01/2009 (14)" @@ -53,14 +53,14 @@ typedef struct { - ftmax_dsp_object_t obj; - - fluid_synth_t *synth; - fluid_settings_t *settings; - int reverb; - int chorus; - int mute; - void *outlet; + ftmax_dsp_object_t obj; + + fluid_synth_t *synth; + fluid_settings_t *settings; + int reverb; + int chorus; + int mute; + void *outlet; } fluidmax_t; static t_messlist *fluidmax_class; @@ -90,77 +90,77 @@ static ftmax_symbol_t sym_sinc = NULL; */ typedef struct { - int index; - const char *name; - const char *unit; -} fluidmax_gen_descr_t; + int index; + const char *name; + const char *unit; +} fluidmax_gen_descr_t; static fluidmax_gen_descr_t fluidmax_gen_info[] = { - {0, "startAddrsOffset", "samples"}, - {1, "endAddrsOffset", "samples"}, - {2, "startloopAddrsOffset", "samples"}, - {3, "endloopAddrsOffset", "samples"}, - {4, "startAddrsCoarseOffset", "32k samples"}, - {5, "modLfoToPitch", "cent fs"}, - {6, "vibLfoToPitch", "cent fs"}, - {7, "modEnvToPitch", "cent fs"}, - {8, "initialFilterFc", "cent 8.176 Hz"}, - {9, "initialFilterQ", "cB"}, - {10, "modLfoToFilterFc", "cent fs"}, - {11, "modEnvToFilterFc", "cent fs "}, - {12, "endAddrsCoarseOffset", "32k samples"}, - {13, "modLfoToVolume", "cB fs"}, - {14, "unused1", ""}, - {15, "chorusEffectsSend", "0.1%"}, - {16, "reverbEffectsSend", "0.1% "}, - {17, "pan", "0.1%"}, - {18, "unused2", ""}, - {19, "unused3", ""}, - {20, "unused4", ""}, - {21, "delayModLFO", "timecent"}, - {22, "freqModLFO", "cent 8.176 "}, - {23, "delayVibLFO", "timecent "}, - {24, "freqVibLFO", "cent 8.176"}, - {25, "delayModEnv", "timecent"}, - {26, "attackModEnv", "timecent "}, - {27, "holdModEnv", "timecent"}, - {28, "decayModEnv", "timecent"}, - {29, "sustainModEnv", "-0.1%"}, - {30, "releaseModEnv", "timecent"}, - {31, "keynumToModEnvHold", "tcent/key"}, - {32, "keynumToModEnvDecay", "tcent/key"}, - {33, "delayVolEnv", "timecent"}, - {34, "attackVolEnv", "timecent"}, - {35, "holdVolEnv", "timecent"}, - {36, "decayVolEnv", "timecent"}, - {37, "sustainVolEnv", "cB"}, - {38, "releaseVolEnv", "timecent "}, - {39, "keynumToVolEnvHold", "tcent/key"}, - {40, "keynumToVolEnvDecay", "tcent/key "}, - {41, "instrument", ""}, - {42, "reserved1", ""}, - {43, "keyRange MIDI", ""}, - {44, "velRange MIDI", ""}, - {45, "startloopAddrsCoarseOffset", "samples"}, - {46, "keynum MIDI", ""}, - {47, "velocity MIDI", ""}, - {48, "initialAttenuation", "cB"}, - {49, "reserved2", ""}, - {50, "endloopAddrsCoarseOffset", "samples"}, - {51, "coarseTune", "semitone"}, - {52, "fineTune", "cent"}, - {53, "sampleId", ""}, - {54, "sampleModes", "Bit Flags"}, - {55, "reserved3", ""}, - {56, "scaleTuning", "cent/key"}, - {57, "exclusiveClass", "arbitrary#"}, - {58, "unused5", ""}, - {59, "unused6", ""}, - {60, "unused7", ""}, - {61, "unused8", ""}, - {62, "unused9", ""}, - {63, "unused10", ""} + {0, "startAddrsOffset", "samples"}, + {1, "endAddrsOffset", "samples"}, + {2, "startloopAddrsOffset", "samples"}, + {3, "endloopAddrsOffset", "samples"}, + {4, "startAddrsCoarseOffset", "32k samples"}, + {5, "modLfoToPitch", "cent fs"}, + {6, "vibLfoToPitch", "cent fs"}, + {7, "modEnvToPitch", "cent fs"}, + {8, "initialFilterFc", "cent 8.176 Hz"}, + {9, "initialFilterQ", "cB"}, + {10, "modLfoToFilterFc", "cent fs"}, + {11, "modEnvToFilterFc", "cent fs "}, + {12, "endAddrsCoarseOffset", "32k samples"}, + {13, "modLfoToVolume", "cB fs"}, + {14, "unused1", ""}, + {15, "chorusEffectsSend", "0.1%"}, + {16, "reverbEffectsSend", "0.1% "}, + {17, "pan", "0.1%"}, + {18, "unused2", ""}, + {19, "unused3", ""}, + {20, "unused4", ""}, + {21, "delayModLFO", "timecent"}, + {22, "freqModLFO", "cent 8.176 "}, + {23, "delayVibLFO", "timecent "}, + {24, "freqVibLFO", "cent 8.176"}, + {25, "delayModEnv", "timecent"}, + {26, "attackModEnv", "timecent "}, + {27, "holdModEnv", "timecent"}, + {28, "decayModEnv", "timecent"}, + {29, "sustainModEnv", "-0.1%"}, + {30, "releaseModEnv", "timecent"}, + {31, "keynumToModEnvHold", "tcent/key"}, + {32, "keynumToModEnvDecay", "tcent/key"}, + {33, "delayVolEnv", "timecent"}, + {34, "attackVolEnv", "timecent"}, + {35, "holdVolEnv", "timecent"}, + {36, "decayVolEnv", "timecent"}, + {37, "sustainVolEnv", "cB"}, + {38, "releaseVolEnv", "timecent "}, + {39, "keynumToVolEnvHold", "tcent/key"}, + {40, "keynumToVolEnvDecay", "tcent/key "}, + {41, "instrument", ""}, + {42, "reserved1", ""}, + {43, "keyRange MIDI", ""}, + {44, "velRange MIDI", ""}, + {45, "startloopAddrsCoarseOffset", "samples"}, + {46, "keynum MIDI", ""}, + {47, "velocity MIDI", ""}, + {48, "initialAttenuation", "cB"}, + {49, "reserved2", ""}, + {50, "endloopAddrsCoarseOffset", "samples"}, + {51, "coarseTune", "semitone"}, + {52, "fineTune", "cent"}, + {53, "sampleId", ""}, + {54, "sampleModes", "Bit Flags"}, + {55, "reserved3", ""}, + {56, "scaleTuning", "cent/key"}, + {57, "exclusiveClass", "arbitrary#"}, + {58, "unused5", ""}, + {59, "unused6", ""}, + {60, "unused7", ""}, + {61, "unused8", ""}, + {62, "unused9", ""}, + {63, "unused10", ""} }; /*************************************************************** @@ -171,30 +171,34 @@ static fluidmax_gen_descr_t fluidmax_gen_info[] = static t_int * fluidmax_perform(t_int *w) { - fluidmax_t *self = (fluidmax_t *)(w[1]); - t_float *left = (t_float *)(w[2]); - t_float *right = (t_float *)(w[3]); - int n_tick = (int)(w[4]); + fluidmax_t *self = (fluidmax_t *)(w[1]); + t_float *left = (t_float *)(w[2]); + t_float *right = (t_float *)(w[3]); + int n_tick = (int)(w[4]); - if(self->mute == 0) - fluid_synth_write_float(self->synth, n_tick, left, 0, 1, right, 0, 1); - else - { - int i; - - for(i=0; imute == 0) + { + fluid_synth_write_float(self->synth, n_tick, left, 0, 1, right, 0, 1); + } + else + { + int i; + + for(i = 0; i < n_tick; i++) + { + left[i] = right[i] = 0.0; + } + } + + return (w + 5); } -static void +static void fluidmax_dsp(fluidmax_t *self, t_signal **sp, short *count) { - int n_tick = sp[0]->s_n; - - dsp_add(fluidmax_perform, 4, self, sp[0]->s_vec, sp[1]->s_vec, n_tick); + int n_tick = sp[0]->s_n; + + dsp_add(fluidmax_perform, 4, self, sp[0]->s_vec, sp[1]->s_vec, n_tick); } /*************************************************************** @@ -205,848 +209,1003 @@ fluidmax_dsp(fluidmax_t *self, t_signal **sp, short *count) static char * fluidmax_translate_fullpath(char *maxpath, char *fullpath) { - int i; + int i; - strcpy(fullpath, "/Volumes/"); - - for(i=0; maxpath[i] != ':'; i++) - fullpath[i + 9] = maxpath[i]; - - /* skip ':' */ - i++; - - strcpy(fullpath + i + 8, maxpath + i); - - return fullpath; + strcpy(fullpath, "/Volumes/"); + + for(i = 0; maxpath[i] != ':'; i++) + { + fullpath[i + 9] = maxpath[i]; + } + + /* skip ':' */ + i++; + + strcpy(fullpath + i + 8, maxpath + i); + + return fullpath; } - + static ftmax_symbol_t fluidmax_get_stripped_name(const char *fullpath) { - char stripped[1024]; - int i; - - for(i=strlen(fullpath)-1; i>=0; i--) - { - if(fullpath[i] == '/') - break; - } - - if(i != 0) - i++; - - strcpy(stripped, fullpath + i); - - for(i=0; stripped[i] != '\0'; i++) - { - if((stripped[i] == '.') && - (stripped[i + 1] == 's' || stripped[i + 1] == 'S') && - (stripped[i + 2] == 'f' || stripped[i + 2] == 'F') && - (stripped[i + 3] == '2')) + char stripped[1024]; + int i; + + for(i = strlen(fullpath) - 1; i >= 0; i--) { - stripped[i] = '\0'; - break; + if(fullpath[i] == '/') + { + break; + } } - } - - return ftmax_new_symbol(stripped); + + if(i != 0) + { + i++; + } + + strcpy(stripped, fullpath + i); + + for(i = 0; stripped[i] != '\0'; i++) + { + if((stripped[i] == '.') && + (stripped[i + 1] == 's' || stripped[i + 1] == 'S') && + (stripped[i + 2] == 'f' || stripped[i + 2] == 'F') && + (stripped[i + 3] == '2')) + { + stripped[i] = '\0'; + break; + } + } + + return ftmax_new_symbol(stripped); } - + static ftmax_symbol_t fluidmax_sfont_get_name(fluid_sfont_t *sfont) { - return fluidmax_get_stripped_name(fluid_sfont_get_name(sfont)); + return fluidmax_get_stripped_name(fluid_sfont_get_name(sfont)); } - + static fluid_sfont_t * fluidmax_sfont_get_by_name(fluidmax_t *self, ftmax_symbol_t name) { - int n = fluid_synth_sfcount(self->synth); - int i; - - for(i=0; isynth, i); + int n = fluid_synth_sfcount(self->synth); + int i; - if(fluidmax_sfont_get_name(sfont) == name) - return sfont; - } + for(i = 0; i < n; i++) + { + fluid_sfont_t *sfont = fluid_synth_get_sfont(self->synth, i); - return NULL; + if(fluidmax_sfont_get_name(sfont) == name) + { + return sfont; + } + } + + return NULL; } -static void +static void fluidmax_do_load(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_symbol(at)) - { - const char *filename = ftmax_symbol_name(ftmax_get_symbol(at)); - ftmax_symbol_t name = fluidmax_get_stripped_name(filename); - fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, name); - - if(sf == NULL) - { - int id = fluid_synth_sfload(self->synth, filename, 0); - - if(id >= 0) - { - post("fluidsynth~: loaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + fluidmax_t *self = (fluidmax_t *)o; - fluid_synth_program_reset(self->synth); - - outlet_bang(self->outlet); - } - else - error("fluidsynth~: cannot load soundfont from file '%s'", filename); - } - else + if(ac > 0 && ftmax_is_symbol(at)) { - error("fluidsynth~: soundfont named '%s' is already loaded", ftmax_symbol_name(name)); - return; + const char *filename = ftmax_symbol_name(ftmax_get_symbol(at)); + ftmax_symbol_t name = fluidmax_get_stripped_name(filename); + fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, name); + + if(sf == NULL) + { + int id = fluid_synth_sfload(self->synth, filename, 0); + + if(id >= 0) + { + post("fluidsynth~: loaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + + fluid_synth_program_reset(self->synth); + + outlet_bang(self->outlet); + } + else + { + error("fluidsynth~: cannot load soundfont from file '%s'", filename); + } + } + else + { + error("fluidsynth~: soundfont named '%s' is already loaded", ftmax_symbol_name(name)); + return; + } } - } } static void fluidmax_load_with_dialog(t_object *o, t_symbol *s, short argc, t_atom *argv) { - char filename[256]; - char maxpath[1024]; - char fullpath[1024]; - long type; - short path; - - open_promptset("open SoundFont 2 file"); - - if(open_dialog(filename, &path, &type, 0, 0)) - return; - - if(path_topotentialname(path, filename, maxpath, 0) == 0) - { - ftmax_atom_t a; - - ftmax_set_symbol(&a, ftmax_new_symbol(fluidmax_translate_fullpath(maxpath, fullpath))); - fluidmax_do_load(o, NULL, 1, &a); - } -} + char filename[256]; + char maxpath[1024]; + char fullpath[1024]; + long type; + short path; + + open_promptset("open SoundFont 2 file"); + + if(open_dialog(filename, &path, &type, 0, 0)) + { + return; + } + + if(path_topotentialname(path, filename, maxpath, 0) == 0) + { + ftmax_atom_t a; + + ftmax_set_symbol(&a, ftmax_new_symbol(fluidmax_translate_fullpath(maxpath, fullpath))); + fluidmax_do_load(o, NULL, 1, &a); + } +} /*************************************************************** * * user methods * */ -static void +static void fluidmax_load(t_object *o, Symbol *s, short ac, Atom *at) -{ - if(ac == 0) - defer(o, (method)fluidmax_load_with_dialog, NULL, 0, 0); - else - { - if(ftmax_is_symbol(at)) +{ + if(ac == 0) { - ftmax_symbol_t name = ftmax_get_symbol(at); - char *string = (char *)ftmax_symbol_name(name); - - if(string[0] == '/') - defer(o, (method)fluidmax_do_load, NULL, ac, at); - else - { - char maxpath[1024]; - char fullpath[1024]; - short path; - long type; - ftmax_atom_t a; - - if(locatefile_extended(string, &path, &type, 0, 0) || path_topotentialname(path, string, maxpath, 0) != 0) - { - error("fluidsynth~: cannot find file '%s'", string); - return; - } - - ftmax_set_symbol(&a, ftmax_new_symbol(fluidmax_translate_fullpath(maxpath, fullpath))); - defer(o, (method)fluidmax_do_load, NULL, 1, &a); - } + defer(o, (method)fluidmax_load_with_dialog, NULL, 0, 0); + } + else + { + if(ftmax_is_symbol(at)) + { + ftmax_symbol_t name = ftmax_get_symbol(at); + char *string = (char *)ftmax_symbol_name(name); + + if(string[0] == '/') + { + defer(o, (method)fluidmax_do_load, NULL, ac, at); + } + else + { + char maxpath[1024]; + char fullpath[1024]; + short path; + long type; + ftmax_atom_t a; + + if(locatefile_extended(string, &path, &type, 0, 0) || path_topotentialname(path, string, maxpath, 0) != 0) + { + error("fluidsynth~: cannot find file '%s'", string); + return; + } + + ftmax_set_symbol(&a, ftmax_new_symbol(fluidmax_translate_fullpath(maxpath, fullpath))); + defer(o, (method)fluidmax_do_load, NULL, 1, &a); + } + } } - } } -static void +static void fluidmax_unload(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0) - { - if(ftmax_is_number(at)) - { - int id = ftmax_get_number_int(at); - fluid_sfont_t *sf = fluid_synth_get_sfont_by_id(self->synth, id); - - if(sf != NULL) - { - ftmax_symbol_t name = fluidmax_sfont_get_name(sf); - - if(fluid_synth_sfunload(self->synth, id, 0) >= 0) - { - post("fluidsynth~: unloaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); - return; - } - } - - error("fluidsynth~: cannot unload soundfont %d", id); - } - else if (ftmax_is_symbol(at)) - { - ftmax_symbol_t sym = ftmax_get_symbol(at); - - if(sym == ftmax_new_symbol("all")) - { - fluid_sfont_t *sf = fluid_synth_get_sfont(self->synth, 0); - - fluid_synth_system_reset(self->synth); + fluidmax_t *self = (fluidmax_t *)o; - while(sf != NULL) + if(ac > 0) + { + if(ftmax_is_number(at)) { - ftmax_symbol_t name = fluidmax_sfont_get_name(sf); - unsigned int id = fluid_sfont_get_id(sf); - - if(fluid_synth_sfunload(self->synth, id, 0) >= 0) - post("fluidsynth~: unloaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); - else - error("fluidsynth~: cannot unload soundfont '%s' (id %d)", ftmax_symbol_name(name), id); - - sf = fluid_synth_get_sfont(self->synth, 0); + int id = ftmax_get_number_int(at); + fluid_sfont_t *sf = fluid_synth_get_sfont_by_id(self->synth, id); + + if(sf != NULL) + { + ftmax_symbol_t name = fluidmax_sfont_get_name(sf); + + if(fluid_synth_sfunload(self->synth, id, 0) >= 0) + { + post("fluidsynth~: unloaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + return; + } + } + + error("fluidsynth~: cannot unload soundfont %d", id); } - } - else - { - fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, sym); - - if(sf != NULL) + else if(ftmax_is_symbol(at)) { - unsigned int id = fluid_sfont_get_id(sf); - - if(fluid_synth_sfunload(self->synth, id, 0) >= 0) - { - post("fluidsynth~: unloaded soundfont '%s' (id %d)", ftmax_symbol_name(sym), id); - return; - } + ftmax_symbol_t sym = ftmax_get_symbol(at); + + if(sym == ftmax_new_symbol("all")) + { + fluid_sfont_t *sf = fluid_synth_get_sfont(self->synth, 0); + + fluid_synth_system_reset(self->synth); + + while(sf != NULL) + { + ftmax_symbol_t name = fluidmax_sfont_get_name(sf); + unsigned int id = fluid_sfont_get_id(sf); + + if(fluid_synth_sfunload(self->synth, id, 0) >= 0) + { + post("fluidsynth~: unloaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + } + else + { + error("fluidsynth~: cannot unload soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + } + + sf = fluid_synth_get_sfont(self->synth, 0); + } + } + else + { + fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, sym); + + if(sf != NULL) + { + unsigned int id = fluid_sfont_get_id(sf); + + if(fluid_synth_sfunload(self->synth, id, 0) >= 0) + { + post("fluidsynth~: unloaded soundfont '%s' (id %d)", ftmax_symbol_name(sym), id); + return; + } + } + + error("fluidsynth~: cannot unload soundfont '%s'", ftmax_symbol_name(sym)); + } } - - error("fluidsynth~: cannot unload soundfont '%s'", ftmax_symbol_name(sym)); - } } - } } -static void +static void fluidmax_reload(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0) - { - if(ftmax_is_number(at)) - { - int id = ftmax_get_number_int(at); - fluid_sfont_t *sf = fluid_synth_get_sfont_by_id(self->synth, id); - - if(sf != NULL) - { - if (fluid_synth_sfreload(self->synth, id) >= 0) - { - post("fluidsynth~: reloaded soundfont '%s' (id %d)", id); - return; - } + fluidmax_t *self = (fluidmax_t *)o; - error("fluidsynth~: cannot reload soundfont %d", id); - } - } - else if (ftmax_is_symbol(at)) + if(ac > 0) { - ftmax_symbol_t sym = ftmax_get_symbol(at); - - if(sym == ftmax_new_symbol("all")) - { - int n = fluid_synth_sfcount(self->synth); - int i; - - fluid_synth_system_reset(self->synth); + if(ftmax_is_number(at)) + { + int id = ftmax_get_number_int(at); + fluid_sfont_t *sf = fluid_synth_get_sfont_by_id(self->synth, id); - for(i=0; isynth, i); - ftmax_symbol_t name = fluidmax_sfont_get_name(sf); - unsigned int id = fluid_sfont_get_id(sf); - - - if (fluid_synth_sfreload(self->synth, id) >= 0) - post("fluidsynth~: reloaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); - else - error("fluidsynth~: cannot reload soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + if(sf != NULL) + { + if(fluid_synth_sfreload(self->synth, id) >= 0) + { + post("fluidsynth~: reloaded soundfont '%s' (id %d)", id); + return; + } + + error("fluidsynth~: cannot reload soundfont %d", id); + } } - } - else - { - fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, sym); - - if(sf != NULL) + else if(ftmax_is_symbol(at)) { - unsigned int id = fluid_sfont_get_id(sf); - - if(fluid_synth_sfreload(self->synth, id) >= 0) - { - post("fluidsynth~: reloaded soundfont '%s' (id %d)", ftmax_symbol_name(sym), id); - return; - } + ftmax_symbol_t sym = ftmax_get_symbol(at); + + if(sym == ftmax_new_symbol("all")) + { + int n = fluid_synth_sfcount(self->synth); + int i; + + fluid_synth_system_reset(self->synth); + + for(i = 0; i < n; i++) + { + fluid_sfont_t *sf = fluid_synth_get_sfont(self->synth, i); + ftmax_symbol_t name = fluidmax_sfont_get_name(sf); + unsigned int id = fluid_sfont_get_id(sf); + + + if(fluid_synth_sfreload(self->synth, id) >= 0) + { + post("fluidsynth~: reloaded soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + } + else + { + error("fluidsynth~: cannot reload soundfont '%s' (id %d)", ftmax_symbol_name(name), id); + } + } + } + else + { + fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, sym); + + if(sf != NULL) + { + unsigned int id = fluid_sfont_get_id(sf); + + if(fluid_synth_sfreload(self->synth, id) >= 0) + { + post("fluidsynth~: reloaded soundfont '%s' (id %d)", ftmax_symbol_name(sym), id); + return; + } + } + + error("fluidsynth~: cannot reload soundfont '%s'", ftmax_symbol_name(sym)); + } } - - error("fluidsynth~: cannot reload soundfont '%s'", ftmax_symbol_name(sym)); - } } - } } -static void +static void fluidmax_note(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_number(at)) - { - int velocity = 64; - int channel = 1; - - switch(ac) + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0 && ftmax_is_number(at)) { - default: - case 3: - if(ftmax_is_number(at + 2)) + int velocity = 64; + int channel = 1; + + switch(ac) { - channel = ftmax_get_number_int(at + 2); - - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); + default: + case 3: + if(ftmax_is_number(at + 2)) + { + channel = ftmax_get_number_int(at + 2); + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + } + + case 2: + if(ftmax_is_number(at + 1)) + { + velocity = ftmax_get_number_int(at + 1); + } + + case 1: + fluid_synth_noteon(self->synth, channel - 1, ftmax_get_number_int(at), velocity); + + case 0: + break; } - case 2: - if(ftmax_is_number(at + 1)) - velocity = ftmax_get_number_int(at + 1); - case 1: - fluid_synth_noteon(self->synth, channel - 1, ftmax_get_number_int(at), velocity); - case 0: - break; } - } } -static void +static void fluidmax_list(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_note(o, NULL, ac, at); + fluidmax_note(o, NULL, ac, at); } -static void +static void fluidmax_control_change(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_number(at)) - { - int value = 64; - int channel = 1; - - switch(ac) + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0 && ftmax_is_number(at)) { - default: - case 3: - if(ftmax_is_number(at + 2)) + int value = 64; + int channel = 1; + + switch(ac) { - channel = ftmax_get_number_int(at + 2); - - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); + default: + case 3: + if(ftmax_is_number(at + 2)) + { + channel = ftmax_get_number_int(at + 2); + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + } + + case 2: + if(ftmax_is_number(at + 1)) + { + value = ftmax_get_number_int(at + 1); + } + + case 1: + fluid_synth_cc(self->synth, channel - 1, ftmax_get_number_int(at), value); + + case 0: + break; } - case 2: - if(ftmax_is_number(at + 1)) - value = ftmax_get_number_int(at + 1); - case 1: - fluid_synth_cc(self->synth, channel - 1, ftmax_get_number_int(at), value); - case 0: - break; } - } } -static void +static void fluidmax_mod(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 1 && ftmax_is_number(at) && ftmax_is_number(at + 1)) - { - int param = ftmax_get_number_int(at); - float value = ftmax_get_number_float(at + 1); - int channel = 1; - - if(ac > 2 && ftmax_is_number(at + 2)) - { - channel = ftmax_get_number_int(at + 2); - - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); - } + fluidmax_t *self = (fluidmax_t *)o; - fluid_synth_set_gen(self->synth, channel - 1, param, value); - } + if(ac > 1 && ftmax_is_number(at) && ftmax_is_number(at + 1)) + { + int param = ftmax_get_number_int(at); + float value = ftmax_get_number_float(at + 1); + int channel = 1; + + if(ac > 2 && ftmax_is_number(at + 2)) + { + channel = ftmax_get_number_int(at + 2); + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + } + + fluid_synth_set_gen(self->synth, channel - 1, param, value); + } } -static void +static void fluidmax_pitch_bend(t_object *o, Symbol *s, short ac, Atom *at) -{ - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_number(at)) - { - int channel = 1; - double bend = 0.0; - - if(ac > 1 && ftmax_is_number(at + 1)) +{ + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0 && ftmax_is_number(at)) { - channel = ftmax_get_number_int(at + 1); - - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); + int channel = 1; + double bend = 0.0; + + if(ac > 1 && ftmax_is_number(at + 1)) + { + channel = ftmax_get_number_int(at + 1); + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + } + + bend = ftmax_get_number_float(at); + + if(bend < 0.0) + { + bend = 0.0; + } + else if(bend > 127.0) + { + bend = 127.0; + } + + fluid_synth_pitch_bend(self->synth, channel - 1, (int)(bend * 128.0)); } - - bend = ftmax_get_number_float(at); - - if(bend < 0.0) - bend = 0.0; - else if(bend > 127.0) - bend = 127.0; - - fluid_synth_pitch_bend(self->synth, channel - 1, (int)(bend * 128.0)); - } } -static void +static void fluidmax_pitch_bend_wheel(t_object *o, Symbol *s, short ac, Atom *at) -{ - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_number(at)) - { - int channel = 1; - - if(ac > 1 && ftmax_is_number(at + 1)) - channel = ftmax_get_number_int(at + 1); - - fluid_synth_pitch_wheel_sens(self->synth, channel - 1, ftmax_get_number_int(at)); - } -} +{ + fluidmax_t *self = (fluidmax_t *)o; -static void -fluidmax_program_change(t_object *o, Symbol *s, short ac, Atom *at) -{ - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_number(at)) - { - int channel = 1; - - if(ac > 1 && ftmax_is_number(at + 1)) + if(ac > 0 && ftmax_is_number(at)) { - channel = ftmax_get_number_int(at + 1); - - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); + int channel = 1; + + if(ac > 1 && ftmax_is_number(at + 1)) + { + channel = ftmax_get_number_int(at + 1); + } + + fluid_synth_pitch_wheel_sens(self->synth, channel - 1, ftmax_get_number_int(at)); } - - fluid_synth_program_change(self->synth, channel - 1, ftmax_get_number_int(at)); - } } -static void +static void +fluidmax_program_change(t_object *o, Symbol *s, short ac, Atom *at) +{ + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0 && ftmax_is_number(at)) + { + int channel = 1; + + if(ac > 1 && ftmax_is_number(at + 1)) + { + channel = ftmax_get_number_int(at + 1); + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + } + + fluid_synth_program_change(self->synth, channel - 1, ftmax_get_number_int(at)); + } +} + +static void fluidmax_bank_select(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_number(at)) - { - int channel = 1; - unsigned int sf_id; - unsigned int bank_num; - unsigned int prog_num; - - if(ac > 1 && ftmax_is_number(at + 1)) + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0 && ftmax_is_number(at)) { - channel = ftmax_get_number_int(at + 1); - - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); + int channel = 1; + unsigned int sf_id; + unsigned int bank_num; + unsigned int prog_num; + + if(ac > 1 && ftmax_is_number(at + 1)) + { + channel = ftmax_get_number_int(at + 1); + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + } + + fluid_synth_bank_select(self->synth, channel - 1, ftmax_get_number_int(at)); + fluid_synth_get_program(self->synth, channel - 1, &sf_id, &bank_num, &prog_num); + fluid_synth_program_change(self->synth, channel - 1, prog_num); } - - fluid_synth_bank_select(self->synth, channel - 1, ftmax_get_number_int(at)); - fluid_synth_get_program(self->synth, channel - 1, &sf_id, &bank_num, &prog_num); - fluid_synth_program_change(self->synth, channel - 1, prog_num); - } } -static void +static void fluidmax_select(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - unsigned int bank = 0; - unsigned int preset = 0; - int channel = 1; - - switch(ac) - { + fluidmax_t *self = (fluidmax_t *)o; + unsigned int bank = 0; + unsigned int preset = 0; + int channel = 1; + + switch(ac) + { default: case 4: - if(ftmax_is_number(at + 3)) - channel = ftmax_get_number_int(at + 3); + if(ftmax_is_number(at + 3)) + { + channel = ftmax_get_number_int(at + 3); + } + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); - case 3: - if(ftmax_is_number(at + 2)) - preset = ftmax_get_number_int(at + 2); - + if(ftmax_is_number(at + 2)) + { + preset = ftmax_get_number_int(at + 2); + } + case 2: - if(ftmax_is_number(at + 1)) - bank = ftmax_get_number_int(at + 1); - + if(ftmax_is_number(at + 1)) + { + bank = ftmax_get_number_int(at + 1); + } + case 1: - if(ftmax_is_number(at)) - fluid_synth_program_select(self->synth, channel - 1, ftmax_get_number_int(at), bank, preset); - else if(ftmax_is_symbol(at)) - { - ftmax_symbol_t name = ftmax_get_symbol(at); - fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, name); - - if(sf != NULL) - fluid_synth_program_select(self->synth, channel - 1, fluid_sfont_get_id(sf), bank, preset); - else - error("fluidsynth~ select: cannot find soundfont named '%s'", ftmax_symbol_name(name)); - } + if(ftmax_is_number(at)) + { + fluid_synth_program_select(self->synth, channel - 1, ftmax_get_number_int(at), bank, preset); + } + else if(ftmax_is_symbol(at)) + { + ftmax_symbol_t name = ftmax_get_symbol(at); + fluid_sfont_t *sf = fluidmax_sfont_get_by_name(self, name); + + if(sf != NULL) + { + fluid_synth_program_select(self->synth, channel - 1, fluid_sfont_get_id(sf), bank, preset); + } + else + { + error("fluidsynth~ select: cannot find soundfont named '%s'", ftmax_symbol_name(name)); + } + } + case 0: - break; - } + break; + } } -static void +static void fluidmax_reverb(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac == 0) - { - fluid_synth_set_reverb_on(self->synth, 1); - fluid_synth_reset_reverb(self->synth); - self->reverb = 1; - } - else if(ftmax_is_number(at)) - { - double room = fluid_synth_get_reverb_roomsize(self->synth); - double damping = fluid_synth_get_reverb_damp(self->synth); - double width = fluid_synth_get_reverb_width(self->synth); + fluidmax_t *self = (fluidmax_t *)o; - fluid_synth_set_reverb_on(self->synth, 1); - self->reverb = 1; - - switch(ac) + if(ac == 0) { - default: - case 4: - if(ftmax_is_number(at + 3)) - width = ftmax_get_number_float(at + 3); - case 3: - if(ftmax_is_number(at + 2)) - damping = ftmax_get_number_float(at + 2); - case 2: - if(ftmax_is_number(at + 1)) - room = ftmax_get_number_float(at + 1); - case 1: - fluid_synth_set_reverb(self->synth, room, damping, width, ftmax_get_number_float(at)); - case 0: - break; + fluid_synth_set_reverb_on(self->synth, 1); + fluid_synth_reset_reverb(self->synth); + self->reverb = 1; } - } - else if(ftmax_is_symbol(at)) - { - ftmax_symbol_t sym = ftmax_get_symbol(at); - - if(sym == sym_on) + else if(ftmax_is_number(at)) { - fluid_synth_set_reverb_on(self->synth, 1); - self->reverb = 1; - } - else if(sym == sym_off) - { - fluid_synth_set_reverb_on(self->synth, 0); - self->reverb = 0; - } - } -} + double room = fluid_synth_get_reverb_roomsize(self->synth); + double damping = fluid_synth_get_reverb_damp(self->synth); + double width = fluid_synth_get_reverb_width(self->synth); -static void -fluidmax_chorus(t_object *o, Symbol *s, short ac, Atom *at) -{ - fluidmax_t *self = (fluidmax_t *)o; - - if(ac == 0) - { - fluid_synth_set_chorus_on(self->synth, 1); - fluid_synth_reset_chorus(self->synth); - self->chorus = 1; - } - else if(ftmax_is_number(at)) - { - double speed = fluid_synth_get_chorus_speed(self->synth); - double depth = fluid_synth_get_chorus_depth(self->synth); - int type = fluid_synth_get_chorus_type(self->synth); - int nr = fluid_synth_get_chorus_nr(self->synth); + fluid_synth_set_reverb_on(self->synth, 1); + self->reverb = 1; - fluid_synth_set_chorus_on(self->synth, 1); - self->chorus = 1; + switch(ac) + { + default: + case 4: + if(ftmax_is_number(at + 3)) + { + width = ftmax_get_number_float(at + 3); + } - switch(ac) - { - default: - case 5: - if(ftmax_is_number(at + 4)) - nr = ftmax_get_number_int(at + 4); - case 4: - if(ftmax_is_number(at + 3)) - type = ftmax_get_number_int(at + 3); - case 3: - if(ftmax_is_number(at + 2)) - depth = ftmax_get_number_float(at + 2); - case 2: - if(ftmax_is_number(at + 1)) - speed = ftmax_get_number_float(at + 1); - case 1: - fluid_synth_set_chorus(self->synth, nr, ftmax_get_number_float(at), speed, depth, type); - case 0: - break; - } - } - else if(ftmax_is_symbol(at)) - { - ftmax_symbol_t sym = ftmax_get_symbol(at); - - if(sym == sym_on) - { - fluid_synth_set_chorus_on(self->synth, 1); - self->chorus = 1; - } - else if(sym == sym_off) - { - fluid_synth_set_chorus_on(self->synth, 0); - self->chorus = 0; - } - } -} + case 3: + if(ftmax_is_number(at + 2)) + { + damping = ftmax_get_number_float(at + 2); + } -static void -fluidmax_set_gain(t_object *o, Symbol *s, short ac, Atom *at) -{ - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0 && ftmax_is_number(at)) - { - float gain = ftmax_get_number_float(at); - - fluid_synth_set_gain(self->synth, gain); - } -} + case 2: + if(ftmax_is_number(at + 1)) + { + room = ftmax_get_number_float(at + 1); + } -static void -fluidmax_set_resampling_method(t_object *o, Symbol *s, short ac, Atom *at) -{ - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0) - { - if(ftmax_is_number(at)) - { - int ip = ftmax_get_int(at); - - if(ip == 0) - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_NONE); - else if(ip < 3) - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_LINEAR); - else if(ip < 6) - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_4THORDER); - else - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_7THORDER); + case 1: + fluid_synth_set_reverb(self->synth, room, damping, width, ftmax_get_number_float(at)); + + case 0: + break; + } } else if(ftmax_is_symbol(at)) { - ftmax_symbol_t sym = ftmax_get_symbol(at); - - if(sym == sym_nearest) - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_NONE); - else if(sym == sym_linear) - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_LINEAR); - else if(sym == sym_cubic) - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_4THORDER); - else if(sym == sym_sinc) - fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_7THORDER); - else - error("fluidsynth~: undefined resampling method: %s", ftmax_symbol_name(sym)); + ftmax_symbol_t sym = ftmax_get_symbol(at); + + if(sym == sym_on) + { + fluid_synth_set_reverb_on(self->synth, 1); + self->reverb = 1; + } + else if(sym == sym_off) + { + fluid_synth_set_reverb_on(self->synth, 0); + self->reverb = 0; + } } - } } -static void +static void +fluidmax_chorus(t_object *o, Symbol *s, short ac, Atom *at) +{ + fluidmax_t *self = (fluidmax_t *)o; + + if(ac == 0) + { + fluid_synth_set_chorus_on(self->synth, 1); + fluid_synth_reset_chorus(self->synth); + self->chorus = 1; + } + else if(ftmax_is_number(at)) + { + double speed = fluid_synth_get_chorus_speed(self->synth); + double depth = fluid_synth_get_chorus_depth(self->synth); + int type = fluid_synth_get_chorus_type(self->synth); + int nr = fluid_synth_get_chorus_nr(self->synth); + + fluid_synth_set_chorus_on(self->synth, 1); + self->chorus = 1; + + switch(ac) + { + default: + case 5: + if(ftmax_is_number(at + 4)) + { + nr = ftmax_get_number_int(at + 4); + } + + case 4: + if(ftmax_is_number(at + 3)) + { + type = ftmax_get_number_int(at + 3); + } + + case 3: + if(ftmax_is_number(at + 2)) + { + depth = ftmax_get_number_float(at + 2); + } + + case 2: + if(ftmax_is_number(at + 1)) + { + speed = ftmax_get_number_float(at + 1); + } + + case 1: + fluid_synth_set_chorus(self->synth, nr, ftmax_get_number_float(at), speed, depth, type); + + case 0: + break; + } + } + else if(ftmax_is_symbol(at)) + { + ftmax_symbol_t sym = ftmax_get_symbol(at); + + if(sym == sym_on) + { + fluid_synth_set_chorus_on(self->synth, 1); + self->chorus = 1; + } + else if(sym == sym_off) + { + fluid_synth_set_chorus_on(self->synth, 0); + self->chorus = 0; + } + } +} + +static void +fluidmax_set_gain(t_object *o, Symbol *s, short ac, Atom *at) +{ + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0 && ftmax_is_number(at)) + { + float gain = ftmax_get_number_float(at); + + fluid_synth_set_gain(self->synth, gain); + } +} + +static void +fluidmax_set_resampling_method(t_object *o, Symbol *s, short ac, Atom *at) +{ + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0) + { + if(ftmax_is_number(at)) + { + int ip = ftmax_get_int(at); + + if(ip == 0) + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_NONE); + } + else if(ip < 3) + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_LINEAR); + } + else if(ip < 6) + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_4THORDER); + } + else + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_7THORDER); + } + } + else if(ftmax_is_symbol(at)) + { + ftmax_symbol_t sym = ftmax_get_symbol(at); + + if(sym == sym_nearest) + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_NONE); + } + else if(sym == sym_linear) + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_LINEAR); + } + else if(sym == sym_cubic) + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_4THORDER); + } + else if(sym == sym_sinc) + { + fluid_synth_set_interp_method(self->synth, -1, FLUID_INTERP_7THORDER); + } + else + { + error("fluidsynth~: undefined resampling method: %s", ftmax_symbol_name(sym)); + } + } + } +} + +static void fluidmax_panic(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; + fluidmax_t *self = (fluidmax_t *)o; - fluid_synth_system_reset(self->synth); + fluid_synth_system_reset(self->synth); } -static void +static void fluidmax_reset(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - int n = fluid_synth_count_midi_channels(self->synth); - int i; + fluidmax_t *self = (fluidmax_t *)o; + int n = fluid_synth_count_midi_channels(self->synth); + int i; - for (i=0; isynth->channel[i]); + for(i = 0; i < n; i++) + { + fluid_channel_reset(self->synth->channel[i]); + } } -static void +static void fluidmax_mute(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - int mute = 1; - - if(ac > 0 && ftmax_is_number(at)) - mute = (ftmax_get_number_int(at) != 0); - - fluid_synth_system_reset(self->synth); - - self->mute = mute; + fluidmax_t *self = (fluidmax_t *)o; + int mute = 1; + + if(ac > 0 && ftmax_is_number(at)) + { + mute = (ftmax_get_number_int(at) != 0); + } + + fluid_synth_system_reset(self->synth); + + self->mute = mute; } -static void +static void fluidmax_unmute(t_object *o) { - ftmax_atom_t a; - - ftmax_set_int(&a, 0); - fluidmax_mute(o, NULL, 1, &a); + ftmax_atom_t a; + + ftmax_set_int(&a, 0); + fluidmax_mute(o, NULL, 1, &a); } -/* +/* int fluid_synth_count_audio_channels (fluid_synth_t *synth) int fluid_synth_count_audio_groups (fluid_synth_t *synth) int fluid_synth_count_effects_channels (fluid_synth_t *synth) */ -static void +static void fluidmax_tuning_octave(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - ftmax_symbol_t name; - int tuning_bank = 0; - int tuning_prog = 0; - double pitch[12]; - int i, n; - - if(ac > 0 && ftmax_is_symbol(at)) - { - name = ftmax_get_symbol(at); - at++; - ac--; - } - - n = ac - 2; - if(n > 12) - n = 12; + fluidmax_t *self = (fluidmax_t *)o; + ftmax_symbol_t name; + int tuning_bank = 0; + int tuning_prog = 0; + double pitch[12]; + int i, n; - if(ac > 0 && ftmax_is_number(at)) - tuning_bank = ftmax_get_number_int(at) % 128; - - if(ac > 1 && ftmax_is_number(at + 1)) - tuning_prog = ftmax_get_number_int(at) % 128; - - for(i=0; i 0 && ftmax_is_symbol(at)) + { + name = ftmax_get_symbol(at); + at++; + ac--; + } - fluid_synth_create_octave_tuning(self->synth, tuning_bank, tuning_prog, ftmax_symbol_name(name), pitch); + n = ac - 2; + + if(n > 12) + { + n = 12; + } + + if(ac > 0 && ftmax_is_number(at)) + { + tuning_bank = ftmax_get_number_int(at) % 128; + } + + if(ac > 1 && ftmax_is_number(at + 1)) + { + tuning_prog = ftmax_get_number_int(at) % 128; + } + + for(i = 0; i < n; i++) + { + if(ftmax_is_number(at + i + 2)) + { + pitch[i] = ftmax_get_number_float(at + i + 2); + } + else + { + pitch[i] = 0.0; + } + } + + for(; i < 12; n++) + { + pitch[i] = 0.0; + } + + fluid_synth_create_octave_tuning(self->synth, tuning_bank, tuning_prog, ftmax_symbol_name(name), pitch); } -static void +static void fluidmax_tuning_select(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - int tuning_bank = 0; - int tuning_prog = 0; - int channel = 1; - - if(ac > 0 && ftmax_is_number(at)) - tuning_bank = ftmax_get_number_int(at) % 128; - - if(ac > 1 && ftmax_is_number(at + 1)) - tuning_prog = ftmax_get_number_int(at + 1) % 128; - - if(ac > 2 && ftmax_is_number(at + 2)) - channel = ftmax_get_number_int(at + 2); - - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); - - fluid_synth_select_tuning(self->synth, channel - 1, tuning_bank, tuning_prog); + fluidmax_t *self = (fluidmax_t *)o; + int tuning_bank = 0; + int tuning_prog = 0; + int channel = 1; + + if(ac > 0 && ftmax_is_number(at)) + { + tuning_bank = ftmax_get_number_int(at) % 128; + } + + if(ac > 1 && ftmax_is_number(at + 1)) + { + tuning_prog = ftmax_get_number_int(at + 1) % 128; + } + + if(ac > 2 && ftmax_is_number(at + 2)) + { + channel = ftmax_get_number_int(at + 2); + } + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + + fluid_synth_select_tuning(self->synth, channel - 1, tuning_bank, tuning_prog); } -static void +static void fluidmax_tuning_reset(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - int channel = 0; - - if(ac > 0 && ftmax_is_number(at)) - channel = ftmax_get_number_int(at); + fluidmax_t *self = (fluidmax_t *)o; + int channel = 0; - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); - - fluid_synth_reset_tuning(self->synth, channel - 1); + if(ac > 0 && ftmax_is_number(at)) + { + channel = ftmax_get_number_int(at); + } + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + + fluid_synth_reset_tuning(self->synth, channel - 1); } /* more tuning ?? @@ -1060,454 +1219,478 @@ fluid_synth_tuning_dump (fluid_synth_t *synth, int bank, int prog, char *name, i static void fluidmax_version(t_object *o) { - post("fluidsynth~, version %s (based on FluidSynth %s)", FLUIDMAX_VERSION, FLUIDSYNTH_VERSION); - post(" FluidSynth is written by Peter Hanappe et al. (see fluidsynth.org)"); - post(" Max/MSP integration by Norbert Schnell IMTR IRCAM - Centre Pompidou"); + post("fluidsynth~, version %s (based on FluidSynth %s)", FLUIDMAX_VERSION, FLUIDSYNTH_VERSION); + post(" FluidSynth is written by Peter Hanappe et al. (see fluidsynth.org)"); + post(" Max/MSP integration by Norbert Schnell IMTR IRCAM - Centre Pompidou"); } extern const fluid_gen_info_t fluid_gen_info[]; -static void +static void fluidmax_print(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0) - { - if(ftmax_is_symbol(at)) + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0) { - ftmax_symbol_t sym = ftmax_get_symbol(at); - - if(sym == sym_soundfonts) - { - int n = fluid_synth_sfcount(self->synth); - int i; - - if(n > 0) - post("fluidsynth~ soundfonts:"); - else - post("fluidsynth~: no soundfonts loaded"); - - for(i=0; isynth, i); - ftmax_symbol_t name = fluidmax_sfont_get_name(sf); - unsigned int id = fluid_sfont_get_id(sf); - - post(" %d: '%s' (id %d)", i, ftmax_symbol_name(name), id); - } - } - else if(sym == sym_presets) - { - int n = fluid_synth_sfcount(self->synth); - - if(n > 0) - { - if(ac > 1) - { - fluid_sfont_t *sf = NULL; - ftmax_symbol_t name; - - if(ftmax_is_symbol(at + 1)) - { - name = ftmax_get_symbol(at + 1); - sf = fluidmax_sfont_get_by_name(self, name); - } - else if(ftmax_is_int(at + 1)) - { - int id = ftmax_get_int(at + 1); - - sf = fluid_synth_get_sfont_by_id(self->synth, id); - name = fluidmax_sfont_get_name(sf); - } - - if(sf != NULL) - { - fluid_preset_t *preset; - - fluid_sfont_iteration_start(sf); - - post("fluidsynth~ presets of soundfont '%s':", ftmax_symbol_name(name)); - - while((preset = fluid_sfont_iteration_next(sf)) != NULL) - { - char *preset_str = fluid_preset_get_name(preset); - ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); - int bank_num = fluid_preset_get_banknum(preset); - int prog_num = fluid_preset_get_num(preset); - - post(" '%s': bank %d, program %d", ftmax_symbol_name(preset_name), bank_num, prog_num); - } - } - } - else - { - int i; + ftmax_symbol_t sym = ftmax_get_symbol(at); - post("fluidsynth~ presets:"); - - for(i=0; i<128; i++) + if(sym == sym_soundfonts) { - int j; - - for(j=0; j<128; j++) - { - fluid_preset_t *preset = NULL; - fluid_sfont_t *sf = NULL; - int k; - - for(k=0; ksynth); + int i; + + if(n > 0) { - sf = fluid_synth_get_sfont(self->synth, k); - preset = fluid_sfont_get_preset(sf, i, j); - - if(preset != NULL) - break; + post("fluidsynth~ soundfonts:"); } - - if(preset != NULL) + else { - ftmax_symbol_t sf_name = fluidmax_sfont_get_name(sf); - char *preset_str = fluid_preset_get_name(preset); - ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); - - post(" '%s': soundfont '%s', bank %d, program %d", - ftmax_symbol_name(preset_name), ftmax_symbol_name(sf_name), i, j); + post("fluidsynth~: no soundfonts loaded"); + } + + for(i = 0; i < n; i++) + { + fluid_sfont_t *sf = fluid_synth_get_sfont(self->synth, i); + ftmax_symbol_t name = fluidmax_sfont_get_name(sf); + unsigned int id = fluid_sfont_get_id(sf); + + post(" %d: '%s' (id %d)", i, ftmax_symbol_name(name), id); } - } } - } - } - else - error("fluidsynth~: no soundfonts loaded"); - } - else if(sym == sym_channels) - { - int n = fluid_synth_count_midi_channels(self->synth); - int i; - - post("fluidsynth~ channels:"); - - for(i=0; isynth, i); - - if(preset != NULL) - { - char *preset_str = fluid_preset_get_name(preset); - ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); - unsigned int sf_id; - unsigned int bank_num; - unsigned int prog_num; - fluid_sfont_t *sf; - - fluid_synth_get_program(self->synth, i, &sf_id, &bank_num, &prog_num); - sf = fluid_synth_get_sfont_by_id(self->synth, sf_id); - - post(" %d: soundfont '%s', bank %d, program %d: '%s'", - i + 1, ftmax_symbol_name(fluidmax_sfont_get_name(sf)), bank_num, prog_num, ftmax_symbol_name(preset_name)); - } - else - post(" channel %d: no preset", i + 1); - } - } - else if(sym == ftmax_new_symbol("generators")) - { - int channel = 1; - int n = GEN_LAST; - int i; - - if(ac > 1 && ftmax_is_number(at + 1)) - channel = ftmax_get_number_int(at + 1); + else if(sym == sym_presets) + { + int n = fluid_synth_sfcount(self->synth); - if(channel < 1) - channel = 1; - else if(channel > fluid_synth_count_midi_channels(self->synth)) - channel = fluid_synth_count_midi_channels(self->synth); - - post("fluidsynth~ generators of channel %d:", channel); - - for(i=0; isynth, channel - 1, i); - double min = fluid_gen_info[i].min; - double max = fluid_gen_info[i].max; - - post(" %d '%s': %s %g [%g ... %g] (%s)", i, name, (incr >= 0)? "": "-" , fabs(incr), min, max, unit); - } - } - else if(sym == sym_gain) - { - double gain = fluid_synth_get_gain(self->synth); + if(n > 0) + { + if(ac > 1) + { + fluid_sfont_t *sf = NULL; + ftmax_symbol_t name; - post("gain: %g", gain); - } - else if(sym == sym_reverb) - { - double level = fluid_synth_get_reverb_level(self->synth); - double room = fluid_synth_get_reverb_roomsize(self->synth); - double damping = fluid_synth_get_reverb_damp(self->synth); - double width = fluid_synth_get_reverb_width(self->synth); - - if(self->reverb != 0) - { - post("fluidsynth~ current reverb parameters:"); - post(" level: %f", level); - post(" room size: %f", room); - post(" damping: %f", damping); - post(" width: %f", width); + if(ftmax_is_symbol(at + 1)) + { + name = ftmax_get_symbol(at + 1); + sf = fluidmax_sfont_get_by_name(self, name); + } + else if(ftmax_is_int(at + 1)) + { + int id = ftmax_get_int(at + 1); + + sf = fluid_synth_get_sfont_by_id(self->synth, id); + name = fluidmax_sfont_get_name(sf); + } + + if(sf != NULL) + { + fluid_preset_t *preset; + + fluid_sfont_iteration_start(sf); + + post("fluidsynth~ presets of soundfont '%s':", ftmax_symbol_name(name)); + + while((preset = fluid_sfont_iteration_next(sf)) != NULL) + { + char *preset_str = fluid_preset_get_name(preset); + ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); + int bank_num = fluid_preset_get_banknum(preset); + int prog_num = fluid_preset_get_num(preset); + + post(" '%s': bank %d, program %d", ftmax_symbol_name(preset_name), bank_num, prog_num); + } + } + } + else + { + int i; + + post("fluidsynth~ presets:"); + + for(i = 0; i < 128; i++) + { + int j; + + for(j = 0; j < 128; j++) + { + fluid_preset_t *preset = NULL; + fluid_sfont_t *sf = NULL; + int k; + + for(k = 0; k < n; k++) + { + sf = fluid_synth_get_sfont(self->synth, k); + preset = fluid_sfont_get_preset(sf, i, j); + + if(preset != NULL) + { + break; + } + } + + if(preset != NULL) + { + ftmax_symbol_t sf_name = fluidmax_sfont_get_name(sf); + char *preset_str = fluid_preset_get_name(preset); + ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); + + post(" '%s': soundfont '%s', bank %d, program %d", + ftmax_symbol_name(preset_name), ftmax_symbol_name(sf_name), i, j); + } + } + } + } + } + else + { + error("fluidsynth~: no soundfonts loaded"); + } + } + else if(sym == sym_channels) + { + int n = fluid_synth_count_midi_channels(self->synth); + int i; + + post("fluidsynth~ channels:"); + + for(i = 0; i < n; i++) + { + fluid_preset_t *preset = fluid_synth_get_channel_preset(self->synth, i); + + if(preset != NULL) + { + char *preset_str = fluid_preset_get_name(preset); + ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); + unsigned int sf_id; + unsigned int bank_num; + unsigned int prog_num; + fluid_sfont_t *sf; + + fluid_synth_get_program(self->synth, i, &sf_id, &bank_num, &prog_num); + sf = fluid_synth_get_sfont_by_id(self->synth, sf_id); + + post(" %d: soundfont '%s', bank %d, program %d: '%s'", + i + 1, ftmax_symbol_name(fluidmax_sfont_get_name(sf)), bank_num, prog_num, ftmax_symbol_name(preset_name)); + } + else + { + post(" channel %d: no preset", i + 1); + } + } + } + else if(sym == ftmax_new_symbol("generators")) + { + int channel = 1; + int n = GEN_LAST; + int i; + + if(ac > 1 && ftmax_is_number(at + 1)) + { + channel = ftmax_get_number_int(at + 1); + } + + if(channel < 1) + { + channel = 1; + } + else if(channel > fluid_synth_count_midi_channels(self->synth)) + { + channel = fluid_synth_count_midi_channels(self->synth); + } + + post("fluidsynth~ generators of channel %d:", channel); + + for(i = 0; i < n; i++) + { + const char *name = fluidmax_gen_info[i].name; + const char *unit = fluidmax_gen_info[i].unit; + double incr = fluid_synth_get_gen(self->synth, channel - 1, i); + double min = fluid_gen_info[i].min; + double max = fluid_gen_info[i].max; + + post(" %d '%s': %s %g [%g ... %g] (%s)", i, name, (incr >= 0) ? "" : "-", fabs(incr), min, max, unit); + } + } + else if(sym == sym_gain) + { + double gain = fluid_synth_get_gain(self->synth); + + post("gain: %g", gain); + } + else if(sym == sym_reverb) + { + double level = fluid_synth_get_reverb_level(self->synth); + double room = fluid_synth_get_reverb_roomsize(self->synth); + double damping = fluid_synth_get_reverb_damp(self->synth); + double width = fluid_synth_get_reverb_width(self->synth); + + if(self->reverb != 0) + { + post("fluidsynth~ current reverb parameters:"); + post(" level: %f", level); + post(" room size: %f", room); + post(" damping: %f", damping); + post(" width: %f", width); + } + else + { + post("fluidsynth~: reverb off"); + } + } + else if(sym == sym_chorus) + { + if(self->chorus != 0) + { + double level = fluid_synth_get_chorus_level(self->synth); + double speed = fluid_synth_get_chorus_speed(self->synth); + double depth = fluid_synth_get_chorus_depth(self->synth); + int type = fluid_synth_get_chorus_type(self->synth); + int nr = fluid_synth_get_chorus_nr(self->synth); + + post("fluidsynth~ current chorus parameters:"); + post(" level: %f", level); + post(" speed: %f Hz", speed); + post(" depth: %f msec", depth); + post(" type: %d (%s)", type, type ? "triangle" : "sine"); + post(" %d units", nr); + } + else + { + post("fluidsynth~: chorus off"); + } + } } - else - post("fluidsynth~: reverb off"); - } - else if(sym == sym_chorus) - { - if(self->chorus != 0) - { - double level = fluid_synth_get_chorus_level(self->synth); - double speed = fluid_synth_get_chorus_speed(self->synth); - double depth = fluid_synth_get_chorus_depth(self->synth); - int type = fluid_synth_get_chorus_type(self->synth); - int nr = fluid_synth_get_chorus_nr(self->synth); - - post("fluidsynth~ current chorus parameters:"); - post(" level: %f", level); - post(" speed: %f Hz", speed); - post(" depth: %f msec", depth); - post(" type: %d (%s)", type, type? "triangle": "sine"); - post(" %d units", nr); - } - else - post("fluidsynth~: chorus off"); - } } - } } -static void +static void fluidmax_info(t_object *o, Symbol *s, short ac, Atom *at) { - fluidmax_t *self = (fluidmax_t *)o; - - if(ac > 0) - { - if(ftmax_is_symbol(at)) + fluidmax_t *self = (fluidmax_t *)o; + + if(ac > 0) { - ftmax_symbol_t sym = ftmax_get_symbol(at); - - if(sym == sym_soundfonts) - { - int n = fluid_synth_sfcount(self->synth); - int i; - - for(i=0; isynth, i); - unsigned int id = fluid_sfont_get_id(sf); - ftmax_atom_t a[2]; - - ftmax_set_int(a, i); - ftmax_set_symbol(a + 1, fluidmax_sfont_get_name(sf)); - ftmax_set_int(a + 2, id); - outlet_anything(self->outlet, sym_soundfont, 3, a); - } - } - else if(sym == sym_presets) - { - int n = fluid_synth_sfcount(self->synth); - - if(n > 0) - { - if(ac > 1) - { - fluid_sfont_t *sf = NULL; - ftmax_symbol_t sf_name; - - if(ftmax_is_symbol(at + 1)) - { - sf_name = ftmax_get_symbol(at + 1); - sf = fluidmax_sfont_get_by_name(self, sf_name); - } - else if(ftmax_is_int(at + 1)) - { - int id = ftmax_get_int(at + 1); - - sf = fluid_synth_get_sfont_by_id(self->synth, id); - sf_name = fluidmax_sfont_get_name(sf); - } - - if(sf != NULL) - { - fluid_preset_t *preset; - - fluid_sfont_iteration_start(sf); - - while((preset = fluid_sfont_iteration_next(sf)) != NULL) - { - char *preset_str = fluid_preset_get_name(preset); - ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); - int bank_num = fluid_preset_get_banknum(preset); - int prog_num = fluid_preset_get_num(preset); - ftmax_atom_t a[4]; - - ftmax_set_symbol(a , preset_name); - ftmax_set_symbol(a + 1, sf_name); - ftmax_set_int(a + 2, bank_num); - ftmax_set_int(a + 3, prog_num); - outlet_anything(self->outlet, sym_preset, 4, a); - } - } - } - else - { - int i; + ftmax_symbol_t sym = ftmax_get_symbol(at); - for(i=0; i<128; i++) + if(sym == sym_soundfonts) { - int j; - - for(j=0; j<128; j++) - { - fluid_preset_t *preset = NULL; - fluid_sfont_t *sf = NULL; - int k; - - for(k=0; ksynth); + int i; + + for(i = 0; i < n; i++) { - sf = fluid_synth_get_sfont(self->synth, k); - preset = fluid_sfont_get_preset(sf, i, j); - - if(preset != NULL) - break; + fluid_sfont_t *sf = fluid_synth_get_sfont(self->synth, i); + unsigned int id = fluid_sfont_get_id(sf); + ftmax_atom_t a[2]; + + ftmax_set_int(a, i); + ftmax_set_symbol(a + 1, fluidmax_sfont_get_name(sf)); + ftmax_set_int(a + 2, id); + outlet_anything(self->outlet, sym_soundfont, 3, a); } - - if(preset != NULL) - { - ftmax_symbol_t sf_name = fluidmax_sfont_get_name(sf); - char *preset_str = fluid_preset_get_name(preset); - ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); - ftmax_atom_t a[4]; - - ftmax_set_symbol(a , preset_name); - ftmax_set_symbol(a + 1, sf_name); - ftmax_set_int(a + 2, i); - ftmax_set_int(a + 3, j); - outlet_anything(self->outlet, sym_preset, 4, a); - } - } } - } - } - else - error("fluidsynth~ info: no soundfonts loaded"); - } - else if(sym == sym_channels) - { - int n = fluid_synth_count_midi_channels(self->synth); - int i; - - for(i=0; isynth, i); - - if(preset != NULL) - { - char *preset_str = fluid_preset_get_name(preset); - ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); - unsigned int sf_id, bank_num, prog_num; - fluid_sfont_t *sf; - ftmax_atom_t a[5]; - - fluid_synth_get_program(self->synth, i, &sf_id, &bank_num, &prog_num); - sf = fluid_synth_get_sfont_by_id(self->synth, sf_id); + else if(sym == sym_presets) + { + int n = fluid_synth_sfcount(self->synth); - ftmax_set_int(a, i + 1); - ftmax_set_symbol(a + 1, fluidmax_sfont_get_name(sf)); - ftmax_set_int(a + 2, bank_num); - ftmax_set_int(a + 3, prog_num); - ftmax_set_symbol(a + 4, preset_name); - outlet_anything(self->outlet, sym_channel, 5, a); - } - else - { - ftmax_atom_t a[2]; - - ftmax_set_int(a, i + 1); - ftmax_set_symbol(a + 1, sym_undefined); - outlet_anything(self->outlet, sym_channel, 2, a); - } - } - } - else if(sym == sym_gain) - { - ftmax_atom_t a; - double gain = fluid_synth_get_gain(self->synth); + if(n > 0) + { + if(ac > 1) + { + fluid_sfont_t *sf = NULL; + ftmax_symbol_t sf_name; - ftmax_set_float(&a, gain); - outlet_anything(self->outlet, sym_channel, 1, &a); - } - else if(sym == sym_reverb) - { - if(self->reverb != 0) - { - double level = fluid_synth_get_reverb_level(self->synth); - double room = fluid_synth_get_reverb_roomsize(self->synth); - double damping = fluid_synth_get_reverb_damp(self->synth); - double width = fluid_synth_get_reverb_width(self->synth); - ftmax_atom_t a[4]; - - ftmax_set_float(a, level); - ftmax_set_float(a + 1, room); - ftmax_set_float(a + 2, damping); - ftmax_set_float(a + 3, width); - outlet_anything(self->outlet, sym_reverb, 4, a); + if(ftmax_is_symbol(at + 1)) + { + sf_name = ftmax_get_symbol(at + 1); + sf = fluidmax_sfont_get_by_name(self, sf_name); + } + else if(ftmax_is_int(at + 1)) + { + int id = ftmax_get_int(at + 1); + + sf = fluid_synth_get_sfont_by_id(self->synth, id); + sf_name = fluidmax_sfont_get_name(sf); + } + + if(sf != NULL) + { + fluid_preset_t *preset; + + fluid_sfont_iteration_start(sf); + + while((preset = fluid_sfont_iteration_next(sf)) != NULL) + { + char *preset_str = fluid_preset_get_name(preset); + ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); + int bank_num = fluid_preset_get_banknum(preset); + int prog_num = fluid_preset_get_num(preset); + ftmax_atom_t a[4]; + + ftmax_set_symbol(a, preset_name); + ftmax_set_symbol(a + 1, sf_name); + ftmax_set_int(a + 2, bank_num); + ftmax_set_int(a + 3, prog_num); + outlet_anything(self->outlet, sym_preset, 4, a); + } + } + } + else + { + int i; + + for(i = 0; i < 128; i++) + { + int j; + + for(j = 0; j < 128; j++) + { + fluid_preset_t *preset = NULL; + fluid_sfont_t *sf = NULL; + int k; + + for(k = 0; k < n; k++) + { + sf = fluid_synth_get_sfont(self->synth, k); + preset = fluid_sfont_get_preset(sf, i, j); + + if(preset != NULL) + { + break; + } + } + + if(preset != NULL) + { + ftmax_symbol_t sf_name = fluidmax_sfont_get_name(sf); + char *preset_str = fluid_preset_get_name(preset); + ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); + ftmax_atom_t a[4]; + + ftmax_set_symbol(a, preset_name); + ftmax_set_symbol(a + 1, sf_name); + ftmax_set_int(a + 2, i); + ftmax_set_int(a + 3, j); + outlet_anything(self->outlet, sym_preset, 4, a); + } + } + } + } + } + else + { + error("fluidsynth~ info: no soundfonts loaded"); + } + } + else if(sym == sym_channels) + { + int n = fluid_synth_count_midi_channels(self->synth); + int i; + + for(i = 0; i < n; i++) + { + fluid_preset_t *preset = fluid_synth_get_channel_preset(self->synth, i); + + if(preset != NULL) + { + char *preset_str = fluid_preset_get_name(preset); + ftmax_symbol_t preset_name = ftmax_new_symbol(preset_str); + unsigned int sf_id, bank_num, prog_num; + fluid_sfont_t *sf; + ftmax_atom_t a[5]; + + fluid_synth_get_program(self->synth, i, &sf_id, &bank_num, &prog_num); + sf = fluid_synth_get_sfont_by_id(self->synth, sf_id); + + ftmax_set_int(a, i + 1); + ftmax_set_symbol(a + 1, fluidmax_sfont_get_name(sf)); + ftmax_set_int(a + 2, bank_num); + ftmax_set_int(a + 3, prog_num); + ftmax_set_symbol(a + 4, preset_name); + outlet_anything(self->outlet, sym_channel, 5, a); + } + else + { + ftmax_atom_t a[2]; + + ftmax_set_int(a, i + 1); + ftmax_set_symbol(a + 1, sym_undefined); + outlet_anything(self->outlet, sym_channel, 2, a); + } + } + } + else if(sym == sym_gain) + { + ftmax_atom_t a; + double gain = fluid_synth_get_gain(self->synth); + + ftmax_set_float(&a, gain); + outlet_anything(self->outlet, sym_channel, 1, &a); + } + else if(sym == sym_reverb) + { + if(self->reverb != 0) + { + double level = fluid_synth_get_reverb_level(self->synth); + double room = fluid_synth_get_reverb_roomsize(self->synth); + double damping = fluid_synth_get_reverb_damp(self->synth); + double width = fluid_synth_get_reverb_width(self->synth); + ftmax_atom_t a[4]; + + ftmax_set_float(a, level); + ftmax_set_float(a + 1, room); + ftmax_set_float(a + 2, damping); + ftmax_set_float(a + 3, width); + outlet_anything(self->outlet, sym_reverb, 4, a); + } + else + { + ftmax_atom_t a; + + ftmax_set_symbol(&a, sym_off); + outlet_anything(self->outlet, sym_reverb, 1, &a); + } + } + else if(sym == sym_chorus) + { + if(self->chorus != 0) + { + double level = fluid_synth_get_chorus_level(self->synth); + double speed = fluid_synth_get_chorus_speed(self->synth); + double depth = fluid_synth_get_chorus_depth(self->synth); + int type = fluid_synth_get_chorus_type(self->synth); + int nr = fluid_synth_get_chorus_nr(self->synth); + ftmax_atom_t a[5]; + + ftmax_set_float(a, level); + ftmax_set_float(a + 1, speed); + ftmax_set_float(a + 2, depth); + ftmax_set_int(a + 3, type); + ftmax_set_int(a + 4, nr); + outlet_anything(self->outlet, sym_chorus, 5, a); + } + else + { + ftmax_atom_t a; + + ftmax_set_symbol(&a, sym_off); + outlet_anything(self->outlet, sym_chorus, 1, &a); + } + } + else if(sym == sym_polyphony) + { + int polyphony = fluid_synth_get_polyphony(self->synth); + ftmax_atom_t a; + + ftmax_set_int(&a, polyphony); + outlet_anything(self->outlet, sym_polyphony, 1, &a); + } } - else - { - ftmax_atom_t a; - - ftmax_set_symbol(&a, sym_off); - outlet_anything(self->outlet, sym_reverb, 1, &a); - } - } - else if(sym == sym_chorus) - { - if(self->chorus != 0) - { - double level = fluid_synth_get_chorus_level(self->synth); - double speed = fluid_synth_get_chorus_speed(self->synth); - double depth = fluid_synth_get_chorus_depth(self->synth); - int type = fluid_synth_get_chorus_type(self->synth); - int nr = fluid_synth_get_chorus_nr(self->synth); - ftmax_atom_t a[5]; - - ftmax_set_float(a, level); - ftmax_set_float(a + 1, speed); - ftmax_set_float(a + 2, depth); - ftmax_set_int(a + 3, type); - ftmax_set_int(a + 4, nr); - outlet_anything(self->outlet, sym_chorus, 5, a); - } - else - { - ftmax_atom_t a; - - ftmax_set_symbol(&a, sym_off); - outlet_anything(self->outlet, sym_chorus, 1, &a); - } - } - else if(sym == sym_polyphony) - { - int polyphony = fluid_synth_get_polyphony(self->synth); - ftmax_atom_t a; - - ftmax_set_int(&a, polyphony); - outlet_anything(self->outlet, sym_polyphony, 1, &a); - } } - } } /*************************************************************** @@ -1517,148 +1700,154 @@ fluidmax_info(t_object *o, Symbol *s, short ac, Atom *at) */ static void * fluidmax_new(Symbol *s, short ac, Atom *at) -{ - fluidmax_t *self = (fluidmax_t *)newobject(fluidmax_class); - int polyphony = 256; - int midi_channels = 16; +{ + fluidmax_t *self = (fluidmax_t *)newobject(fluidmax_class); + int polyphony = 256; + int midi_channels = 16; - self->outlet = outlet_new(self, "anything"); + self->outlet = outlet_new(self, "anything"); - dsp_setup((t_pxobject *)self, 0); - outlet_new(self, "signal"); - outlet_new(self, "signal"); + dsp_setup((t_pxobject *)self, 0); + outlet_new(self, "signal"); + outlet_new(self, "signal"); - self->synth = NULL; - self->settings = new_fluid_settings(); - self->reverb = 0; - self->chorus = 0; - self->mute = 0; - - if(ac > 0 && ftmax_is_number(at)) - { - polyphony = ftmax_get_number_int(at); - ac--; - at++; - } - - if(ac > 0 && ftmax_is_number(at)) - { - midi_channels = ftmax_get_number_int(at); - ac--; - at++; - } - - if(ac > 0 && ftmax_is_symbol(at)) - { - fluidmax_load((t_object *)self, NULL, 1, at); - } - - if(self->settings != NULL) - { - fluid_settings_setint(self->settings, "synth.midi-channels", midi_channels); - fluid_settings_setint(self->settings, "synth.polyphony", polyphony); - fluid_settings_setnum(self->settings, "synth.gain", 0.600000); - fluid_settings_setnum(self->settings, "synth.sample-rate", sys_getsr()); - - self->synth = new_fluid_synth(self->settings); - - if(self->synth != NULL) + self->synth = NULL; + self->settings = new_fluid_settings(); + self->reverb = 0; + self->chorus = 0; + self->mute = 0; + + if(ac > 0 && ftmax_is_number(at)) { - fluid_synth_set_reverb_on(self->synth, 0); - fluid_synth_set_chorus_on(self->synth, 0); - - if(ac > 0 && ftmax_is_symbol(at)) - fluidmax_load((t_object *)self, NULL, ac, at); - - return self; + polyphony = ftmax_get_number_int(at); + ac--; + at++; } - delete_fluid_settings(self->settings); - } + if(ac > 0 && ftmax_is_number(at)) + { + midi_channels = ftmax_get_number_int(at); + ac--; + at++; + } - error("fluidsynth~: cannot create FluidSynth core"); - - return NULL; + if(ac > 0 && ftmax_is_symbol(at)) + { + fluidmax_load((t_object *)self, NULL, 1, at); + } + + if(self->settings != NULL) + { + fluid_settings_setint(self->settings, "synth.midi-channels", midi_channels); + fluid_settings_setint(self->settings, "synth.polyphony", polyphony); + fluid_settings_setnum(self->settings, "synth.gain", 0.600000); + fluid_settings_setnum(self->settings, "synth.sample-rate", sys_getsr()); + + self->synth = new_fluid_synth(self->settings); + + if(self->synth != NULL) + { + fluid_synth_set_reverb_on(self->synth, 0); + fluid_synth_set_chorus_on(self->synth, 0); + + if(ac > 0 && ftmax_is_symbol(at)) + { + fluidmax_load((t_object *)self, NULL, ac, at); + } + + return self; + } + + delete_fluid_settings(self->settings); + } + + error("fluidsynth~: cannot create FluidSynth core"); + + return NULL; } static void fluidmax_free(t_pxobject *o) { - fluidmax_t *self = (fluidmax_t *)o; + fluidmax_t *self = (fluidmax_t *)o; - if(self->settings != NULL ) - delete_fluid_settings(self->settings); + if(self->settings != NULL) + { + delete_fluid_settings(self->settings); + } - if(self->synth != NULL ) - delete_fluid_synth(self->synth); + if(self->synth != NULL) + { + delete_fluid_synth(self->synth); + } - dsp_free(o); + dsp_free(o); } -int +int main(void) { - setup(&fluidmax_class, (method)fluidmax_new, (method)fluidmax_free, (short)sizeof(fluidmax_t), 0, A_GIMME, 0); - dsp_initclass(); + setup(&fluidmax_class, (method)fluidmax_new, (method)fluidmax_free, (short)sizeof(fluidmax_t), 0, A_GIMME, 0); + dsp_initclass(); - addmess((method)fluidmax_dsp, "dsp", A_CANT, 0); + addmess((method)fluidmax_dsp, "dsp", A_CANT, 0); - addmess((method)fluidmax_version, "version", 0); - addmess((method)fluidmax_print, "print", A_GIMME, 0); + addmess((method)fluidmax_version, "version", 0); + addmess((method)fluidmax_print, "print", A_GIMME, 0); - addmess((method)fluidmax_load, "load", A_GIMME, 0); - addmess((method)fluidmax_unload, "unload", A_GIMME, 0); - addmess((method)fluidmax_reload, "reload", A_GIMME, 0); - addmess((method)fluidmax_info, "info", A_GIMME, 0); - - addmess((method)fluidmax_panic, "panic", A_GIMME, 0); - addmess((method)fluidmax_reset, "reset", A_GIMME, 0); - addmess((method)fluidmax_mute, "mute", A_GIMME, 0); - addmess((method)fluidmax_unmute, "unmute", 0); + addmess((method)fluidmax_load, "load", A_GIMME, 0); + addmess((method)fluidmax_unload, "unload", A_GIMME, 0); + addmess((method)fluidmax_reload, "reload", A_GIMME, 0); + addmess((method)fluidmax_info, "info", A_GIMME, 0); - /*addmess((method)fluidmax_tuning_keys, "tuning-keys", A_GIMME, 0);*/ - addmess((method)fluidmax_tuning_octave, "tuning-octave", A_GIMME, 0); - addmess((method)fluidmax_tuning_select, "tuning-select", A_GIMME, 0); - addmess((method)fluidmax_tuning_reset, "tuning-reset", A_GIMME, 0); + addmess((method)fluidmax_panic, "panic", A_GIMME, 0); + addmess((method)fluidmax_reset, "reset", A_GIMME, 0); + addmess((method)fluidmax_mute, "mute", A_GIMME, 0); + addmess((method)fluidmax_unmute, "unmute", 0); - addmess((method)fluidmax_reverb, "reverb", A_GIMME, 0); - addmess((method)fluidmax_chorus, "chorus", A_GIMME, 0); - addmess((method)fluidmax_set_gain, "gain", A_GIMME, 0); - addmess((method)fluidmax_set_resampling_method, "resample", A_GIMME, 0); - - addmess((method)fluidmax_note, "note", A_GIMME, 0); - addmess((method)fluidmax_list, "list", A_GIMME, 0); + /*addmess((method)fluidmax_tuning_keys, "tuning-keys", A_GIMME, 0);*/ + addmess((method)fluidmax_tuning_octave, "tuning-octave", A_GIMME, 0); + addmess((method)fluidmax_tuning_select, "tuning-select", A_GIMME, 0); + addmess((method)fluidmax_tuning_reset, "tuning-reset", A_GIMME, 0); - addmess((method)fluidmax_control_change, "control", A_GIMME, 0); - addmess((method)fluidmax_mod, "mod", A_GIMME, 0); - - addmess((method)fluidmax_pitch_bend, "bend", A_GIMME, 0); - addmess((method)fluidmax_pitch_bend_wheel, "wheel", A_GIMME, 0); + addmess((method)fluidmax_reverb, "reverb", A_GIMME, 0); + addmess((method)fluidmax_chorus, "chorus", A_GIMME, 0); + addmess((method)fluidmax_set_gain, "gain", A_GIMME, 0); + addmess((method)fluidmax_set_resampling_method, "resample", A_GIMME, 0); - addmess((method)fluidmax_program_change, "program", A_GIMME, 0); - addmess((method)fluidmax_bank_select, "bank", A_GIMME, 0); - addmess((method)fluidmax_select, "select", A_GIMME, 0); + addmess((method)fluidmax_note, "note", A_GIMME, 0); + addmess((method)fluidmax_list, "list", A_GIMME, 0); - sym_on = ftmax_new_symbol("on"); - sym_off = ftmax_new_symbol("off"); - sym_undefined = ftmax_new_symbol("undefined"); - sym_gain = ftmax_new_symbol("gain"); - sym_channels = ftmax_new_symbol("channels"); - sym_channel = ftmax_new_symbol("channel"); - sym_soundfonts = ftmax_new_symbol("soundfonts"); - sym_soundfont = ftmax_new_symbol("soundfont"); - sym_presets = ftmax_new_symbol("presets"); - sym_preset = ftmax_new_symbol("preset"); - sym_reverb = ftmax_new_symbol("reverb"); - sym_chorus = ftmax_new_symbol("chorus"); - sym_polyphony = ftmax_new_symbol("polyphony"); - sym_nearest = ftmax_new_symbol("nearest"); - sym_linear = ftmax_new_symbol("linear"); - sym_cubic = ftmax_new_symbol("cubic"); - sym_sinc = ftmax_new_symbol("sinc"); + addmess((method)fluidmax_control_change, "control", A_GIMME, 0); + addmess((method)fluidmax_mod, "mod", A_GIMME, 0); - - fluidmax_version(NULL); - - return 0; + addmess((method)fluidmax_pitch_bend, "bend", A_GIMME, 0); + addmess((method)fluidmax_pitch_bend_wheel, "wheel", A_GIMME, 0); + + addmess((method)fluidmax_program_change, "program", A_GIMME, 0); + addmess((method)fluidmax_bank_select, "bank", A_GIMME, 0); + addmess((method)fluidmax_select, "select", A_GIMME, 0); + + sym_on = ftmax_new_symbol("on"); + sym_off = ftmax_new_symbol("off"); + sym_undefined = ftmax_new_symbol("undefined"); + sym_gain = ftmax_new_symbol("gain"); + sym_channels = ftmax_new_symbol("channels"); + sym_channel = ftmax_new_symbol("channel"); + sym_soundfonts = ftmax_new_symbol("soundfonts"); + sym_soundfont = ftmax_new_symbol("soundfont"); + sym_presets = ftmax_new_symbol("presets"); + sym_preset = ftmax_new_symbol("preset"); + sym_reverb = ftmax_new_symbol("reverb"); + sym_chorus = ftmax_new_symbol("chorus"); + sym_polyphony = ftmax_new_symbol("polyphony"); + sym_nearest = ftmax_new_symbol("nearest"); + sym_linear = ftmax_new_symbol("linear"); + sym_cubic = ftmax_new_symbol("cubic"); + sym_sinc = ftmax_new_symbol("sinc"); + + + fluidmax_version(NULL); + + return 0; } diff --git a/bindings/fluidmax/fluidmax_fakefuns.c b/bindings/fluidmax/fluidmax_fakefuns.c index 9cd800a0..b1fa41f1 100644 --- a/bindings/fluidmax/fluidmax_fakefuns.c +++ b/bindings/fluidmax/fluidmax_fakefuns.c @@ -13,143 +13,151 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. - * + * * See file COPYING.LIB for further informations on licensing terms. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. * */ /* - * This file contains the (mostly empty) implementation of some functions without + * This file contains the (mostly empty) implementation of some functions without * which Fluidsynth wouldn't compile. * - * The Max/MSP version of FluidSynth tries to link only with a minimum of needed + * The Max/MSP version of FluidSynth tries to link only with a minimum of needed * files. Some of the linked files depend on functions that are not necessary * and that are implemnted in files we don't want to include. So, alternate or empty * implemntations of these functions are provided here. - * + * */ #include "ftmax.h" #include "fluidsynth.h" #include "fluidsynth_priv.h" #include "fluid_settings.h" -unsigned int +unsigned int fluid_curtime() { - return (unsigned int)gettime(); + return (unsigned int)gettime(); } double fluid_utime(void) { - return 0.0; + return 0.0; } typedef void fluid_timer_t; -typedef int(*fluid_timer_callback_t)(void* data, unsigned int msec); +typedef int(*fluid_timer_callback_t)(void *data, unsigned int msec); -fluid_timer_t * -new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, int new_thread, int auto_destroy) +fluid_timer_t * +new_fluid_timer(int msec, fluid_timer_callback_t callback, void *data, int new_thread, int auto_destroy) { - /* just call it right away */ - (*callback)(data, msec); - - return NULL; + /* just call it right away */ + (*callback)(data, msec); + + return NULL; } -void +void fluid_sys_config() { } -char* +char * fluid_error() { - return NULL; + return NULL; } -/* This code is (unelegantly) copied from fluid_sys.c since other parts of fluid_sys.c +/* This code is (unelegantly) copied from fluid_sys.c since other parts of fluid_sys.c * that we don't need here depend on many other things that we don't want here. */ char * -fluid_strtok (char **str, char *delim) +fluid_strtok(char **str, char *delim) { - char *s, *d, *token; - char c; - - if (str == NULL || delim == NULL || !*delim) - { - FLUID_LOG(FLUID_ERR, "Null pointer"); - return NULL; - } - - s = *str; - if (!s) return NULL; /* str points to a NULL pointer? (tokenize already ended) */ - - /* skip delimiter chars at beginning of token */ - do - { - c = *s; - if (!c) /* end of source string? */ + char *s, *d, *token; + char c; + + if(str == NULL || delim == NULL || !*delim) { - *str = NULL; - return NULL; + FLUID_LOG(FLUID_ERR, "Null pointer"); + return NULL; } - - for (d = delim; *d; d++) /* is source char a token char? */ + + s = *str; + + if(!s) { - if (c == *d) /* token char match? */ - { - s++; /* advance to next source char */ - break; - } + return NULL; /* str points to a NULL pointer? (tokenize already ended) */ } - } while (*d); /* while token char match */ - - token = s; /* start of token found */ - - /* search for next token char or end of source string */ - for (s = s+1; *s; s++) - { - c = *s; - - for (d = delim; *d; d++) /* is source char a token char? */ + + /* skip delimiter chars at beginning of token */ + do { - if (c == *d) /* token char match? */ - { - *s = '\0'; /* overwrite token char with zero byte to terminate token */ - *str = s+1; /* update str to point to beginning of next token */ - return token; - } + c = *s; + + if(!c) /* end of source string? */ + { + *str = NULL; + return NULL; + } + + for(d = delim; *d; d++) /* is source char a token char? */ + { + if(c == *d) /* token char match? */ + { + s++; /* advance to next source char */ + break; + } + } } - } - - /* we get here only if source string ended */ - *str = NULL; - return token; + while(*d); /* while token char match */ + + token = s; /* start of token found */ + + /* search for next token char or end of source string */ + for(s = s + 1; *s; s++) + { + c = *s; + + for(d = delim; *d; d++) /* is source char a token char? */ + { + if(c == *d) /* token char match? */ + { + *s = '\0'; /* overwrite token char with zero byte to terminate token */ + *str = s + 1; /* update str to point to beginning of next token */ + return token; + } + } + } + + /* we get here only if source string ended */ + *str = NULL; + return token; } -int -fluid_log(int level, char* fmt, ...) +int +fluid_log(int level, char *fmt, ...) { - char buf[1024]; - - va_list args; - va_start (args, fmt); - vsprintf(buf, fmt, args); - va_end (args); + char buf[1024]; - if ((level > 0) && (level < LAST_LOG_LEVEL)) - post("fluidsynth~ core (level %d): %s", level, buf); + va_list args; + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); - return -1; + if((level > 0) && (level < LAST_LOG_LEVEL)) + { + post("fluidsynth~ core (level %d): %s", level, buf); + } + + return -1; } void @@ -160,93 +168,93 @@ fluid_shell_settings(fluid_settings_t *settings) void fluid_audio_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "audio.driver", "", 0, NULL, NULL); + fluid_settings_register_str(settings, "audio.driver", "", 0, NULL, NULL); } void fluid_midi_driver_settings(fluid_settings_t *settings) -{ - fluid_settings_register_str(settings, "midi.driver", "", 0, NULL, NULL); -} - -int fluid_midi_event_get_type(fluid_midi_event_t* evt) { - return 0; + fluid_settings_register_str(settings, "midi.driver", "", 0, NULL, NULL); } -int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type) +int fluid_midi_event_get_type(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; } -int fluid_midi_event_get_channel(fluid_midi_event_t* evt) +int fluid_midi_event_set_type(fluid_midi_event_t *evt, int type) { - return 0; + return FLUID_OK; } -int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan) +int fluid_midi_event_get_channel(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; } -int fluid_midi_event_get_key(fluid_midi_event_t* evt) +int fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan) { - return 0; + return FLUID_OK; } -int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v) +int fluid_midi_event_get_key(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; } -int fluid_midi_event_get_velocity(fluid_midi_event_t* evt) +int fluid_midi_event_set_key(fluid_midi_event_t *evt, int v) { - return 0; + return FLUID_OK; } -int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v) +int fluid_midi_event_get_velocity(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; } -int fluid_midi_event_get_control(fluid_midi_event_t* evt) +int fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int v) { - return 0; + return FLUID_OK; } -int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v) +int fluid_midi_event_get_control(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; } -int fluid_midi_event_get_value(fluid_midi_event_t* evt) +int fluid_midi_event_set_control(fluid_midi_event_t *evt, int v) { - return 0; + return FLUID_OK; } -int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v) +int fluid_midi_event_get_value(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; } -int fluid_midi_event_get_program(fluid_midi_event_t* evt) +int fluid_midi_event_set_value(fluid_midi_event_t *evt, int v) { - return 0; + return FLUID_OK; } -int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val) +int fluid_midi_event_get_program(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; } -int fluid_midi_event_get_pitch(fluid_midi_event_t* evt) +int fluid_midi_event_set_program(fluid_midi_event_t *evt, int val) { - return 0; + return FLUID_OK; } -int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val) +int fluid_midi_event_get_pitch(fluid_midi_event_t *evt) { - return FLUID_OK; + return 0; +} + +int fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val) +{ + return FLUID_OK; } diff --git a/bindings/fluidmax/fluidsynth/version.h b/bindings/fluidmax/fluidsynth/version.h index ec195a95..7521515d 100644 --- a/bindings/fluidmax/fluidsynth/version.h +++ b/bindings/fluidmax/fluidsynth/version.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -34,7 +34,7 @@ extern "C" { FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro); -FLUIDSYNTH_API char* fluid_version_str(void); +FLUIDSYNTH_API char *fluid_version_str(void); #ifdef __cplusplus diff --git a/bindings/fluidmax/ftmax.h b/bindings/fluidmax/ftmax.h index e6c85dbd..7be7dcb6 100644 --- a/bindings/fluidmax/ftmax.h +++ b/bindings/fluidmax/ftmax.h @@ -12,14 +12,14 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. - * + * * See file COPYING.LIB for further informations on licensing terms. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. diff --git a/bindings/fluidsynth_jni/include/sndfile.h b/bindings/fluidsynth_jni/include/sndfile.h index 9fd62db6..4c3d9af0 100644 --- a/bindings/fluidsynth_jni/include/sndfile.h +++ b/bindings/fluidsynth_jni/include/sndfile.h @@ -52,66 +52,67 @@ extern "C" { */ enum -{ /* Major formats. */ - SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian). */ - SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ - SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ - SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ - SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ - SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ - SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ - SF_FORMAT_VOC = 0x080000, /* VOC files. */ - SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ - SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ - SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ - SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ - SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ - SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ - SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ - - /* Subtypes from here on. */ +{ + /* Major formats. */ + SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian). */ + SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ + SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ + SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ + SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ + SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ + SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ + SF_FORMAT_VOC = 0x080000, /* VOC files. */ + SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ + SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ + SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ + SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ + SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ + SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ + SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ - SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ - SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ - SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ - SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ + /* Subtypes from here on. */ - SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ + SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ + SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ + SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ + SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ - SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ - SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ + SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ - SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ - SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ - SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ - SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ + SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ + SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ - SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ - SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ + SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ + SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ + SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ + SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ - SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ - SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ - SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ + SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ + SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ - SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ - SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ + SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ + SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ + SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ - SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ - SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ - + SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ - /* Endian-ness options. */ + SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ + SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ - SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ - SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ - SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ - SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ - SF_FORMAT_SUBMASK = 0x0000FFFF, - SF_FORMAT_TYPEMASK = 0x0FFF0000, - SF_FORMAT_ENDMASK = 0x30000000 + /* Endian-ness options. */ + + SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ + SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ + SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ + SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ + + SF_FORMAT_SUBMASK = 0x0000FFFF, + SF_FORMAT_TYPEMASK = 0x0FFF0000, + SF_FORMAT_ENDMASK = 0x30000000 } ; /* @@ -121,57 +122,58 @@ enum */ enum -{ SFC_GET_LIB_VERSION = 0x1000, - SFC_GET_LOG_INFO = 0x1001, +{ + SFC_GET_LIB_VERSION = 0x1000, + SFC_GET_LOG_INFO = 0x1001, - SFC_GET_NORM_DOUBLE = 0x1010, - SFC_GET_NORM_FLOAT = 0x1011, - SFC_SET_NORM_DOUBLE = 0x1012, - SFC_SET_NORM_FLOAT = 0x1013, + SFC_GET_NORM_DOUBLE = 0x1010, + SFC_GET_NORM_FLOAT = 0x1011, + SFC_SET_NORM_DOUBLE = 0x1012, + SFC_SET_NORM_FLOAT = 0x1013, - SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, - SFC_GET_SIMPLE_FORMAT = 0x1021, + SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, + SFC_GET_SIMPLE_FORMAT = 0x1021, - SFC_GET_FORMAT_INFO = 0x1028, + SFC_GET_FORMAT_INFO = 0x1028, - SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, - SFC_GET_FORMAT_MAJOR = 0x1031, - SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, - SFC_GET_FORMAT_SUBTYPE = 0x1033, + SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, + SFC_GET_FORMAT_MAJOR = 0x1031, + SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, + SFC_GET_FORMAT_SUBTYPE = 0x1033, - SFC_CALC_SIGNAL_MAX = 0x1040, - SFC_CALC_NORM_SIGNAL_MAX = 0x1041, - SFC_CALC_MAX_ALL_CHANNELS = 0x1042, - SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, + SFC_CALC_SIGNAL_MAX = 0x1040, + SFC_CALC_NORM_SIGNAL_MAX = 0x1041, + SFC_CALC_MAX_ALL_CHANNELS = 0x1042, + SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, - SFC_SET_ADD_PEAK_CHUNK = 0x1050, + SFC_SET_ADD_PEAK_CHUNK = 0x1050, - SFC_UPDATE_HEADER_NOW = 0x1060, - SFC_SET_UPDATE_HEADER_AUTO = 0x1061, + SFC_UPDATE_HEADER_NOW = 0x1060, + SFC_SET_UPDATE_HEADER_AUTO = 0x1061, - SFC_FILE_TRUNCATE = 0x1080, - - SFC_SET_RAW_START_OFFSET = 0x1090, + SFC_FILE_TRUNCATE = 0x1080, - SFC_SET_DITHER_ON_WRITE = 0x10A0, - SFC_SET_DITHER_ON_READ = 0x10A1, + SFC_SET_RAW_START_OFFSET = 0x1090, - SFC_GET_DITHER_INFO_COUNT = 0x10A2, - SFC_GET_DITHER_INFO = 0x10A3, + SFC_SET_DITHER_ON_WRITE = 0x10A0, + SFC_SET_DITHER_ON_READ = 0x10A1, - SFC_GET_EMBED_FILE_INFO = 0x10B0, - - /* Following commands for testing only. */ - SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, + SFC_GET_DITHER_INFO_COUNT = 0x10A2, + SFC_GET_DITHER_INFO = 0x10A3, - /* - ** SFC_SET_ADD_* values are deprecated and will disappear at some - ** time in the future. They are guaranteed to be here up to and - ** including version 1.0.8 to avoid breakage of existng software. - ** They currently do nothing and will continue to do nothing. - */ - SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, - SFC_SET_ADD_DITHER_ON_READ = 0x1071 + SFC_GET_EMBED_FILE_INFO = 0x10B0, + + /* Following commands for testing only. */ + SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, + + /* + ** SFC_SET_ADD_* values are deprecated and will disappear at some + ** time in the future. They are guaranteed to be here up to and + ** including version 1.0.8 to avoid breakage of existng software. + ** They currently do nothing and will continue to do nothing. + */ + SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, + SFC_SET_ADD_DITHER_ON_READ = 0x1071 } ; @@ -182,35 +184,38 @@ enum */ enum -{ SF_STR_TITLE = 0x01, - SF_STR_COPYRIGHT = 0x02, - SF_STR_SOFTWARE = 0x03, - SF_STR_ARTIST = 0x04, - SF_STR_COMMENT = 0x05, - SF_STR_DATE = 0x06 +{ + SF_STR_TITLE = 0x01, + SF_STR_COPYRIGHT = 0x02, + SF_STR_SOFTWARE = 0x03, + SF_STR_ARTIST = 0x04, + SF_STR_COMMENT = 0x05, + SF_STR_DATE = 0x06 } ; enum -{ /* True and false */ - SF_FALSE = 0, - SF_TRUE = 1, +{ + /* True and false */ + SF_FALSE = 0, + SF_TRUE = 1, - /* Modes for opening files. */ - SFM_READ = 0x10, - SFM_WRITE = 0x20, - SFM_RDWR = 0x30 + /* Modes for opening files. */ + SFM_READ = 0x10, + SFM_WRITE = 0x20, + SFM_RDWR = 0x30 } ; /* Pubic error values. These are guaranteed to remain unchanged for the duration -** of the library major version number. +** of the library major version number. ** There are also a large number of private error numbers which are internal to ** the library which can change at any time. */ enum -{ SF_ERR_NO_ERROR = 0, - SF_ERR_UNRECOGNISED_FORMAT = 1, - SF_ERR_SYSTEM = 2 +{ + SF_ERR_NO_ERROR = 0, + SF_ERR_UNRECOGNISED_FORMAT = 1, + SF_ERR_SYSTEM = 2 } ; /* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ @@ -225,12 +230,13 @@ typedef __int64 sf_count_t ; */ struct SF_INFO -{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ - int samplerate ; - int channels ; - int format ; - int sections ; - int seekable ; +{ + sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ + int samplerate ; + int channels ; + int format ; + int sections ; + int seekable ; } ; typedef struct SF_INFO SF_INFO ; @@ -247,30 +253,33 @@ typedef struct SF_INFO SF_INFO ; */ typedef struct -{ int format ; - const char *name ; - const char *extension ; +{ + int format ; + const char *name ; + const char *extension ; } SF_FORMAT_INFO ; /* -** Enums and typedefs for adding dither on read and write. -** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE +** Enums and typedefs for adding dither on read and write. +** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE ** and SFC_SET_DITHER_ON_READ. */ enum -{ SFD_DEFAULT_LEVEL = 0, - SFD_CUSTOM_LEVEL = 0x40000000, +{ + SFD_DEFAULT_LEVEL = 0, + SFD_CUSTOM_LEVEL = 0x40000000, - SFD_NO_DITHER = 500, - SFD_WHITE = 501, - SFD_TRIANGULAR_PDF = 502 + SFD_NO_DITHER = 500, + SFD_WHITE = 501, + SFD_TRIANGULAR_PDF = 502 } ; typedef struct -{ int type ; - double level ; - const char *name ; +{ + int type ; + double level ; + const char *name ; } SF_DITHER_INFO ; /* Struct used to retrieve information about a file embedded within a @@ -278,8 +287,9 @@ typedef struct */ typedef struct -{ sf_count_t offset ; - sf_count_t length ; +{ + sf_count_t offset ; + sf_count_t length ; } SF_EMBED_FILE_INFO ; @@ -289,7 +299,7 @@ typedef struct ** All calls to sf_open() should be matched with a call to sf_close(). */ -SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; +SNDFILE *sf_open(const char *path, int mode, SF_INFO *sfinfo) ; /* Use the existing file descriptor to create a SNDFILE object. If close_desc ** is TRUE, the file descriptor will be closed when sf_close() is called. If @@ -297,49 +307,49 @@ SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; ** When passed a descriptor like this, the library will assume that the start ** of file header is at the current file offset. This allows sound files within ** larger container files to be read and/or written. -** On error, this will return a NULL pointer. To find the error number, pass a +** On error, this will return a NULL pointer. To find the error number, pass a ** NULL SNDFILE to sf_perror () or sf_error_str (). ** All calls to sf_open_fd() should be matched with a call to sf_close(). */ -SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; +SNDFILE *sf_open_fd(int fd, int mode, SF_INFO *sfinfo, int close_desc) ; -/* sf_error () returns a error number which can be translated to a text +/* sf_error () returns a error number which can be translated to a text ** string using sf_error_number(). */ -int sf_error (SNDFILE *sndfile) ; +int sf_error(SNDFILE *sndfile) ; -/* sf_strerror () returns to the caller a pointer to the current error message for +/* sf_strerror () returns to the caller a pointer to the current error message for ** the given SNDFILE. */ -const char* sf_strerror (SNDFILE *sndfile) ; +const char *sf_strerror(SNDFILE *sndfile) ; /* sf_error_number () allows the retrieval of the error string for each internal -** error number. +** error number. ** */ -const char* sf_error_number (int errnum) ; +const char *sf_error_number(int errnum) ; /* The following three error functions are deprecated but they will remain in the ** library for the forseeable future. The function sf_strerror() should be used ** in their place. */ -int sf_perror (SNDFILE *sndfile) ; -int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; +int sf_perror(SNDFILE *sndfile) ; +int sf_error_str(SNDFILE *sndfile, char *str, size_t len) ; /* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ -int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; +int sf_command(SNDFILE *sndfile, int command, void *data, int datasize) ; /* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ -int sf_format_check (const SF_INFO *info) ; +int sf_format_check(const SF_INFO *info) ; /* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses ** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as @@ -353,7 +363,7 @@ int sf_format_check (const SF_INFO *info) ; ** On error all of these functions return -1. */ -sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; +sf_count_t sf_seek(SNDFILE *sndfile, sf_count_t frames, int whence) ; /* Functions for retrieving and setting string data within sound files. ** Not all file types support this features; AIFF and WAV do. For both @@ -363,15 +373,15 @@ sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; ** returns NULL. */ -int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; +int sf_set_string(SNDFILE *sndfile, int str_type, const char *str) ; -const char* sf_get_string (SNDFILE *sndfile, int str_type) ; +const char *sf_get_string(SNDFILE *sndfile, int str_type) ; /* Functions for reading/writing the waveform data of a sound file. */ -sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; -sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; +sf_count_t sf_read_raw(SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; +sf_count_t sf_write_raw(SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; /* Functions for reading and writing the data chunk in terms of frames. ** The number of items actually read/written = frames * number of channels. @@ -383,16 +393,16 @@ sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; ** All of these read/write function return number of frames read/written. */ -sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; -sf_count_t sf_writef_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; +sf_count_t sf_readf_short(SNDFILE *sndfile, short *ptr, sf_count_t frames) ; +sf_count_t sf_writef_short(SNDFILE *sndfile, short *ptr, sf_count_t frames) ; -sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; -sf_count_t sf_writef_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; +sf_count_t sf_readf_int(SNDFILE *sndfile, int *ptr, sf_count_t frames) ; +sf_count_t sf_writef_int(SNDFILE *sndfile, int *ptr, sf_count_t frames) ; -sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; -sf_count_t sf_writef_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; +sf_count_t sf_readf_float(SNDFILE *sndfile, float *ptr, sf_count_t frames) ; +sf_count_t sf_writef_float(SNDFILE *sndfile, float *ptr, sf_count_t frames) ; -sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; +sf_count_t sf_readf_double(SNDFILE *sndfile, double *ptr, sf_count_t frames) ; sf_count_t sf_writef_double(SNDFILE *sndfile, double *ptr, sf_count_t frames) ; /* Functions for reading and writing the data chunk in terms of items. @@ -400,24 +410,24 @@ sf_count_t sf_writef_double(SNDFILE *sndfile, double *ptr, sf_count_t frames) ; ** All of these read/write function return number of items read/written. */ -sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; -sf_count_t sf_write_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_read_short(SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_write_short(SNDFILE *sndfile, short *ptr, sf_count_t items) ; -sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; -sf_count_t sf_write_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_read_int(SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_write_int(SNDFILE *sndfile, int *ptr, sf_count_t items) ; -sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; -sf_count_t sf_write_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_read_float(SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_write_float(SNDFILE *sndfile, float *ptr, sf_count_t items) ; -sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; -sf_count_t sf_write_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; +sf_count_t sf_read_double(SNDFILE *sndfile, double *ptr, sf_count_t items) ; +sf_count_t sf_write_double(SNDFILE *sndfile, double *ptr, sf_count_t items) ; /* Close the SNDFILE and clean up all memory allocations associated with this -** file. -** Returns 0 on success, or an error number. +** file. +** Returns 0 on success, or an error number. */ -int sf_close (SNDFILE *sndfile) ; +int sf_close(SNDFILE *sndfile) ; #ifdef __cplusplus } /* extern "C" */ diff --git a/bindings/fluidsynth_jni/src/fluidsynth_Sample.cpp b/bindings/fluidsynth_jni/src/fluidsynth_Sample.cpp index 5321a699..a81f1abe 100644 --- a/bindings/fluidsynth_jni/src/fluidsynth_Sample.cpp +++ b/bindings/fluidsynth_jni/src/fluidsynth_Sample.cpp @@ -1,17 +1,17 @@ #include "fluidsynth_Sample.h" #include "fluidsynth_jni.h" -JNIEXPORT jint JNICALL +JNIEXPORT jint JNICALL Java_fluidsynth_Sample_newSample(JNIEnv *env, jobject obj, jstring filename, jint rootkey) { - const char *cfilename = env->GetStringUTFChars(filename, 0); - int err = fluid_jni_new_sample(cfilename, rootkey); - env->ReleaseStringUTFChars(filename, cfilename); - return err; + const char *cfilename = env->GetStringUTFChars(filename, 0); + int err = fluid_jni_new_sample(cfilename, rootkey); + env->ReleaseStringUTFChars(filename, cfilename); + return err; } -JNIEXPORT void JNICALL +JNIEXPORT void JNICALL Java_fluidsynth_Sample_deleteSample(JNIEnv *env, jobject obj, jint samplenum) { - fluid_jni_delete_sample(samplenum); + fluid_jni_delete_sample(samplenum); } diff --git a/bindings/fluidsynth_jni/src/fluidsynth_Sample.h b/bindings/fluidsynth_jni/src/fluidsynth_Sample.h index cfa55271..fab30005 100644 --- a/bindings/fluidsynth_jni/src/fluidsynth_Sample.h +++ b/bindings/fluidsynth_jni/src/fluidsynth_Sample.h @@ -13,7 +13,7 @@ extern "C" { * Signature: (Ljava/lang/String;I)I */ JNIEXPORT jint JNICALL Java_fluidsynth_Sample_newSample - (JNIEnv *, jobject, jstring, jint); +(JNIEnv *, jobject, jstring, jint); /* * Class: fluidsynth_Sample @@ -21,7 +21,7 @@ JNIEXPORT jint JNICALL Java_fluidsynth_Sample_newSample * Signature: (I)V */ JNIEXPORT void JNICALL Java_fluidsynth_Sample_deleteSample - (JNIEnv *, jobject, jint); +(JNIEnv *, jobject, jint); #ifdef __cplusplus } diff --git a/bindings/fluidsynth_jni/src/fluidsynth_Synth.cpp b/bindings/fluidsynth_jni/src/fluidsynth_Synth.cpp index 325e8ea1..a1e70ef0 100644 --- a/bindings/fluidsynth_jni/src/fluidsynth_Synth.cpp +++ b/bindings/fluidsynth_jni/src/fluidsynth_Synth.cpp @@ -1,38 +1,38 @@ #include "fluidsynth_Synth.h" #include "fluidsynth_jni.h" -JNIEXPORT jint JNICALL +JNIEXPORT jint JNICALL Java_fluidsynth_Synth_newSynth(JNIEnv *env, jobject obj) { - return fluid_jni_new_synth(); + return fluid_jni_new_synth(); } -JNIEXPORT void JNICALL +JNIEXPORT void JNICALL Java_fluidsynth_Synth_deleteSynth(JNIEnv *env, jobject obj, jint synth) { - fluid_jni_delete_synth(synth); + fluid_jni_delete_synth(synth); } -JNIEXPORT jint JNICALL +JNIEXPORT jint JNICALL Java_fluidsynth_Synth_add(JNIEnv *env, jobject obj, jint synth, jint samplenum, - jint bank, jint preset, jint lokey, jint hikey) + jint bank, jint preset, jint lokey, jint hikey) { - return fluid_jni_add(samplenum, bank, preset, lokey, hikey); + return fluid_jni_add(samplenum, bank, preset, lokey, hikey); } -JNIEXPORT jint JNICALL -Java_fluidsynth_Synth_remove(JNIEnv *env, jobject obj, jint synth, - jint samplenum, jint bank, jint preset) +JNIEXPORT jint JNICALL +Java_fluidsynth_Synth_remove(JNIEnv *env, jobject obj, jint synth, + jint samplenum, jint bank, jint preset) { - return fluid_jni_remove(samplenum, bank, preset); + return fluid_jni_remove(samplenum, bank, preset); } -JNIEXPORT jint JNICALL +JNIEXPORT jint JNICALL Java_fluidsynth_Synth_loadSoundFont(JNIEnv *env, jobject obj, jint synth, jstring filename) { - const char *cfilename = env->GetStringUTFChars(filename, 0); - int err = fluid_jni_sfload(cfilename); - env->ReleaseStringUTFChars(filename, cfilename); - return err; + const char *cfilename = env->GetStringUTFChars(filename, 0); + int err = fluid_jni_sfload(cfilename); + env->ReleaseStringUTFChars(filename, cfilename); + return err; } diff --git a/bindings/fluidsynth_jni/src/fluidsynth_Synth.h b/bindings/fluidsynth_jni/src/fluidsynth_Synth.h index e67f0719..a586cc27 100644 --- a/bindings/fluidsynth_jni/src/fluidsynth_Synth.h +++ b/bindings/fluidsynth_jni/src/fluidsynth_Synth.h @@ -13,7 +13,7 @@ extern "C" { * Signature: ()I */ JNIEXPORT jint JNICALL Java_fluidsynth_Synth_newSynth - (JNIEnv *, jobject); +(JNIEnv *, jobject); /* * Class: fluidsynth_Synth @@ -21,7 +21,7 @@ JNIEXPORT jint JNICALL Java_fluidsynth_Synth_newSynth * Signature: (I)V */ JNIEXPORT void JNICALL Java_fluidsynth_Synth_deleteSynth - (JNIEnv *, jobject, jint); +(JNIEnv *, jobject, jint); /* * Class: fluidsynth_Synth @@ -29,7 +29,7 @@ JNIEXPORT void JNICALL Java_fluidsynth_Synth_deleteSynth * Signature: (IIIIII)I */ JNIEXPORT jint JNICALL Java_fluidsynth_Synth_add - (JNIEnv *, jobject, jint, jint, jint, jint, jint, jint); +(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint); /* * Class: fluidsynth_Synth @@ -37,7 +37,7 @@ JNIEXPORT jint JNICALL Java_fluidsynth_Synth_add * Signature: (IIII)I */ JNIEXPORT jint JNICALL Java_fluidsynth_Synth_remove - (JNIEnv *, jobject, jint, jint, jint, jint); +(JNIEnv *, jobject, jint, jint, jint, jint); JNIEXPORT jint JNICALL Java_fluidsynth_Synth_loadSoundFont (JNIEnv *env, jobject obj, jint synth, jstring filename); diff --git a/bindings/fluidsynth_jni/src/fluidsynth_jni.cpp b/bindings/fluidsynth_jni/src/fluidsynth_jni.cpp index 156f2a7a..9789426a 100644 --- a/bindings/fluidsynth_jni/src/fluidsynth_jni.cpp +++ b/bindings/fluidsynth_jni/src/fluidsynth_jni.cpp @@ -4,264 +4,331 @@ const int fluid_jni_maxsamples = 1024; static int _initialized = 0; -static fluid_settings_t* _settings = 0; -static fluid_synth_t* _synth = 0; -static fluid_audio_driver_t* _adriver = 0; -static fluid_midi_driver_t* _mdriver = 0; -static fluid_sfont_t* _sfloader = 0; -static fluid_sample_t* _sample[fluid_jni_maxsamples]; +static fluid_settings_t *_settings = 0; +static fluid_synth_t *_synth = 0; +static fluid_audio_driver_t *_adriver = 0; +static fluid_midi_driver_t *_mdriver = 0; +static fluid_sfont_t *_sfloader = 0; +static fluid_sample_t *_sample[fluid_jni_maxsamples]; void fluid_jni_init() { - if (_initialized == 0) { - _initialized++; - for (int i = 0; i < fluid_jni_maxsamples; i++) { - _sample[i] = 0; + if(_initialized == 0) + { + _initialized++; + + for(int i = 0; i < fluid_jni_maxsamples; i++) + { + _sample[i] = 0; + } } - } } int fluid_jni_new_synth() { - if (_synth != 0) { + if(_synth != 0) + { + return -1; + } + + fluid_jni_init(); + + _settings = new_fluid_settings(); + + if(_settings == 0) + { + goto error_recovery; + } + + fluid_settings_setstr(_settings, "midi.driver", "midishare"); + + _synth = new_fluid_synth(_settings); + + if(_synth == 0) + { + goto error_recovery; + } + + _adriver = new_fluid_audio_driver(_settings, _synth); + + if(_adriver == 0) + { + goto error_recovery; + } + + _mdriver = new_fluid_midi_driver(_settings, fluid_synth_handle_midi_event, _synth); + + if(_mdriver == 0) + { + goto error_recovery; + } + + + _sfloader = fluid_ramsfont_create_sfont(); + + if(_sfloader == 0) + { + goto error_recovery; + } + + fluid_ramsfont_set_name((fluid_ramsfont_t *) _sfloader->data, "Tada"); + + fluid_synth_add_sfont(_synth, _sfloader); + + return 0; + +error_recovery: + fluid_jni_delete_synth(0); return -1; - } - - fluid_jni_init(); - - _settings = new_fluid_settings(); - if (_settings == 0) { - goto error_recovery; - } - - fluid_settings_setstr(_settings, "midi.driver", "midishare"); - - _synth = new_fluid_synth(_settings); - if (_synth == 0) { - goto error_recovery; - } - - _adriver = new_fluid_audio_driver(_settings, _synth); - if (_adriver == 0) { - goto error_recovery; - } - - _mdriver = new_fluid_midi_driver(_settings, fluid_synth_handle_midi_event, _synth); - if (_mdriver == 0) { - goto error_recovery; - } - - - _sfloader = fluid_ramsfont_create_sfont(); - if (_sfloader == 0) { - goto error_recovery; - } - fluid_ramsfont_set_name((fluid_ramsfont_t*) _sfloader->data, "Tada"); - - fluid_synth_add_sfont(_synth, _sfloader); - - return 0; - - error_recovery: - fluid_jni_delete_synth(0); - return -1; } int fluid_jni_delete_synth(int num) { - if (_mdriver) { + if(_mdriver) + { - delete_fluid_midi_driver(_mdriver); - - _mdriver = 0; - } - if (_adriver) { + delete_fluid_midi_driver(_mdriver); - delete_fluid_audio_driver(_adriver); + _mdriver = 0; + } - _adriver = 0; - } - if (_synth) { - - delete_fluid_synth(_synth); + if(_adriver) + { - _synth = 0; - } - if (_settings) { - delete_fluid_settings(_settings); - _settings = 0; - } - return 0; + delete_fluid_audio_driver(_adriver); + + _adriver = 0; + } + + if(_synth) + { + + delete_fluid_synth(_synth); + + _synth = 0; + } + + if(_settings) + { + delete_fluid_settings(_settings); + _settings = 0; + } + + return 0; } -int fluid_jni_sfload(const char* filename) +int fluid_jni_sfload(const char *filename) { - if (_synth == 0) { - return -1; - } - fluid_synth_sfload(_synth, filename, 1); - return 0; + if(_synth == 0) + { + return -1; + } + + fluid_synth_sfload(_synth, filename, 1); + return 0; } int fluid_jni_add(int samplenum, int bank, int preset, int lokey, int hikey) { - if (_synth == 0) { - return -1; - } - if (_sfloader == 0) { - return -1; - } - fluid_sample_t* sample = fluid_jni_get_sample(samplenum); - if (sample == 0) { - return -2; - } - - - - if (fluid_ramsfont_add_izone((fluid_ramsfont_t*) _sfloader->data, bank, - preset, sample, lokey, hikey) != 0) { - - - return -3; - } - - - - fluid_synth_program_select(_synth, 0, _sfloader->id, bank, preset); - return 0; + if(_synth == 0) + { + return -1; + } + + if(_sfloader == 0) + { + return -1; + } + + fluid_sample_t *sample = fluid_jni_get_sample(samplenum); + + if(sample == 0) + { + return -2; + } + + + + if(fluid_ramsfont_add_izone((fluid_ramsfont_t *) _sfloader->data, bank, + preset, sample, lokey, hikey) != 0) + { + + + return -3; + } + + + + fluid_synth_program_select(_synth, 0, _sfloader->id, bank, preset); + return 0; } int fluid_jni_remove(int samplenum, int bank, int preset) { - if (_synth == 0) { - return -1; - } - fluid_sample_t* sample = fluid_jni_get_sample(samplenum); - if (sample == 0) { - return -2; - } - if (fluid_ramsfont_remove_izone((fluid_ramsfont_t*) _sfloader->data, - bank, preset, sample) != 0) { - return -3; - } - + if(_synth == 0) + { + return -1; + } - return 0; + fluid_sample_t *sample = fluid_jni_get_sample(samplenum); + + if(sample == 0) + { + return -2; + } + + if(fluid_ramsfont_remove_izone((fluid_ramsfont_t *) _sfloader->data, + bank, preset, sample) != 0) + { + return -3; + } + + + return 0; } int fluid_jni_get_sample_num() { - for (int i = 0; i < fluid_jni_maxsamples; i++) { - if (_sample[i] == 0) { - return i; + for(int i = 0; i < fluid_jni_maxsamples; i++) + { + if(_sample[i] == 0) + { + return i; + } } - } - return -1; -} -int fluid_jni_new_sample(const char* filename, int rootkey) -{ - SF_INFO sfinfo; - SNDFILE* sndfile = 0; - fluid_sample_t* sample = 0; - short *data = 0; - sf_count_t count; - int err; - - int num = fluid_jni_get_sample_num(); - if (num < 0) { return -1; - } - - - - - sndfile = sf_open(filename, SFM_READ, &sfinfo) ; - if (sndfile == 0) { - return -2; - } - - //printf("fluid_jni_new_sample: channels=%i, srate=%i, frames=%i\n", -// sfinfo.channels, sfinfo.samplerate, sfinfo.frames); - - - if (sfinfo.channels != 1) { - err = -3; - goto error_recovery; - } - if (sfinfo.samplerate != 44100) { - err = -4; - goto error_recovery; - } - sample = new_fluid_ramsample(); - if (sample == 0) { - err = -5; - goto error_recovery; - } - data = new short[sfinfo.frames]; - if (data == 0) { - err = -6; - goto error_recovery; - } - - // printf("fluid_jni_new_sample 2\n"); - - count = sf_readf_short(sndfile, data, sfinfo.frames); - if (count != sfinfo.frames) { - err = -7; - goto error_recovery; - } - - //printf("fluid_jni_new_sample 3\n"); - - if (fluid_sample_set_sound_data(sample, data, sfinfo.frames, 1, rootkey) != 0) { - err = -8; - goto error_recovery; - } - - //printf("fluid_jni_new_sample 4: sample=%p\n", sample); - - _sample[num] = sample; - - sf_close(sndfile); - delete data; - - return num; - - error_recovery: - - if (sndfile) { - sf_close(sndfile); - } - if (sample) { - delete_fluid_ramsample(sample); - } - if (data) { - delete data; - } - return err; } -fluid_sample_t* fluid_jni_get_sample(int num) +int fluid_jni_new_sample(const char *filename, int rootkey) { - if ((num >= 0) - && (num < fluid_jni_maxsamples) - && (_sample[num] != 0)) { - return _sample[num]; - } - return 0; + SF_INFO sfinfo; + SNDFILE *sndfile = 0; + fluid_sample_t *sample = 0; + short *data = 0; + sf_count_t count; + int err; + + int num = fluid_jni_get_sample_num(); + + if(num < 0) + { + return -1; + } + + + + + sndfile = sf_open(filename, SFM_READ, &sfinfo) ; + + if(sndfile == 0) + { + return -2; + } + + //printf("fluid_jni_new_sample: channels=%i, srate=%i, frames=%i\n", +// sfinfo.channels, sfinfo.samplerate, sfinfo.frames); + + + if(sfinfo.channels != 1) + { + err = -3; + goto error_recovery; + } + + if(sfinfo.samplerate != 44100) + { + err = -4; + goto error_recovery; + } + + sample = new_fluid_ramsample(); + + if(sample == 0) + { + err = -5; + goto error_recovery; + } + + data = new short[sfinfo.frames]; + + if(data == 0) + { + err = -6; + goto error_recovery; + } + +// printf("fluid_jni_new_sample 2\n"); + + count = sf_readf_short(sndfile, data, sfinfo.frames); + + if(count != sfinfo.frames) + { + err = -7; + goto error_recovery; + } + + //printf("fluid_jni_new_sample 3\n"); + + if(fluid_sample_set_sound_data(sample, data, sfinfo.frames, 1, rootkey) != 0) + { + err = -8; + goto error_recovery; + } + + //printf("fluid_jni_new_sample 4: sample=%p\n", sample); + + _sample[num] = sample; + + sf_close(sndfile); + delete data; + + return num; + +error_recovery: + + if(sndfile) + { + sf_close(sndfile); + } + + if(sample) + { + delete_fluid_ramsample(sample); + } + + if(data) + { + delete data; + } + + return err; +} + +fluid_sample_t *fluid_jni_get_sample(int num) +{ + if((num >= 0) + && (num < fluid_jni_maxsamples) + && (_sample[num] != 0)) + { + return _sample[num]; + } + + return 0; } int fluid_jni_delete_sample(int num) { - if ((num >= 0) - && (num < fluid_jni_maxsamples) - && (_sample[num] != 0)) { - delete_fluid_ramsample(_sample[num]); - _sample[num] = 0; - } - return 0; + if((num >= 0) + && (num < fluid_jni_maxsamples) + && (_sample[num] != 0)) + { + delete_fluid_ramsample(_sample[num]); + _sample[num] = 0; + } + + return 0; } diff --git a/bindings/fluidsynth_jni/src/fluidsynth_jni.h b/bindings/fluidsynth_jni/src/fluidsynth_jni.h index e96254ff..28b94e01 100644 --- a/bindings/fluidsynth_jni/src/fluidsynth_jni.h +++ b/bindings/fluidsynth_jni/src/fluidsynth_jni.h @@ -8,11 +8,11 @@ int fluid_jni_new_synth(void); int fluid_jni_delete_synth(int num); int fluid_jni_add(int samplenum, int bank, int preset, int lokey, int hikey); int fluid_jni_remove(int samplenum, int bank, int preset); -int fluid_jni_sfload(const char* filename); +int fluid_jni_sfload(const char *filename); -int fluid_jni_new_sample(const char* filename, int rootkey); +int fluid_jni_new_sample(const char *filename, int rootkey); int fluid_jni_delete_sample(int num); int fluid_jni_get_sample_num(void); -fluid_sample_t* fluid_jni_get_sample(int num); +fluid_sample_t *fluid_jni_get_sample(int num); #endif /* _FLUID_JNI_H */ diff --git a/doc/example.c b/doc/example.c index 4ff1f07b..a15d15d9 100644 --- a/doc/example.c +++ b/doc/example.c @@ -6,7 +6,7 @@ $ gcc -o example example.c `pkg-config fluidsynth --libs` To compile it on Windows: - ... + ... Author: Peter Hanappe. @@ -23,52 +23,53 @@ #include #endif -int main(int argc, char** argv) +int main(int argc, char **argv) { - fluid_settings_t* settings; - fluid_synth_t* synth; - fluid_audio_driver_t* adriver; - int sfont_id; - int i, key; + fluid_settings_t *settings; + fluid_synth_t *synth; + fluid_audio_driver_t *adriver; + int sfont_id; + int i, key; - /* Create the settings. */ - settings = new_fluid_settings(); + /* Create the settings. */ + settings = new_fluid_settings(); - /* Change the settings if necessary*/ + /* Change the settings if necessary*/ - /* Create the synthesizer. */ - synth = new_fluid_synth(settings); + /* Create the synthesizer. */ + synth = new_fluid_synth(settings); - /* Create the audio driver. The synthesizer starts playing as soon - as the driver is created. */ - adriver = new_fluid_audio_driver(settings, synth); + /* Create the audio driver. The synthesizer starts playing as soon + as the driver is created. */ + adriver = new_fluid_audio_driver(settings, synth); - /* Load a SoundFont and reset presets (so that new instruments - * get used from the SoundFont) */ - sfont_id = fluid_synth_sfload(synth, "example.sf2", 1); + /* Load a SoundFont and reset presets (so that new instruments + * get used from the SoundFont) */ + sfont_id = fluid_synth_sfload(synth, "example.sf2", 1); - /* Initialize the random number generator */ - srand(getpid()); + /* Initialize the random number generator */ + srand(getpid()); - for (i = 0; i < 12; i++) { + for(i = 0; i < 12; i++) + { - /* Generate a random key */ - key = 60 + (int) (12.0f * rand() / (float) RAND_MAX); + /* Generate a random key */ + key = 60 + (int)(12.0f * rand() / (float) RAND_MAX); - /* Play a note */ - fluid_synth_noteon(synth, 0, key, 80); + /* Play a note */ + fluid_synth_noteon(synth, 0, key, 80); - /* Sleep for 1 second */ - sleep(1); + /* Sleep for 1 second */ + sleep(1); - /* Stop the note */ - fluid_synth_noteoff(synth, 0, key); - } + /* Stop the note */ + fluid_synth_noteoff(synth, 0, key); + } - /* Clean up */ - delete_fluid_audio_driver(adriver); - delete_fluid_synth(synth); - delete_fluid_settings(settings); + /* Clean up */ + delete_fluid_audio_driver(adriver); + delete_fluid_synth(synth); + delete_fluid_settings(settings); - return 0; + return 0; } diff --git a/doc/fluidsynth_arpeggio.c b/doc/fluidsynth_arpeggio.c index 71f004a4..1955acc8 100644 --- a/doc/fluidsynth_arpeggio.c +++ b/doc/fluidsynth_arpeggio.c @@ -28,124 +28,147 @@ unsigned int notes[] = { 60, 64, 67, 72, 76, 79, 84, 79, 76, 72, 67, 64 }; unsigned int pattern_size; /* prototype */ void -sequencer_callback (unsigned int time, fluid_event_t *event, - fluid_sequencer_t *seq, void *data); +sequencer_callback(unsigned int time, fluid_event_t *event, + fluid_sequencer_t *seq, void *data); /* schedule a note on message */ void -schedule_noteon (int chan, short key, unsigned int ticks) +schedule_noteon(int chan, short key, unsigned int ticks) { - fluid_event_t *ev = new_fluid_event (); - fluid_event_set_source (ev, -1); - fluid_event_set_dest (ev, synth_destination); - fluid_event_noteon (ev, chan, key, 127); - fluid_sequencer_send_at (sequencer, ev, ticks, 1); - delete_fluid_event (ev); + fluid_event_t *ev = new_fluid_event(); + fluid_event_set_source(ev, -1); + fluid_event_set_dest(ev, synth_destination); + fluid_event_noteon(ev, chan, key, 127); + fluid_sequencer_send_at(sequencer, ev, ticks, 1); + delete_fluid_event(ev); } /* schedule a note off message */ void -schedule_noteoff (int chan, short key, unsigned int ticks) +schedule_noteoff(int chan, short key, unsigned int ticks) { - fluid_event_t *ev = new_fluid_event (); - fluid_event_set_source (ev, -1); - fluid_event_set_dest (ev, synth_destination); - fluid_event_noteoff (ev, chan, key); - fluid_sequencer_send_at (sequencer, ev, ticks, 1); - delete_fluid_event (ev); + fluid_event_t *ev = new_fluid_event(); + fluid_event_set_source(ev, -1); + fluid_event_set_dest(ev, synth_destination); + fluid_event_noteoff(ev, chan, key); + fluid_sequencer_send_at(sequencer, ev, ticks, 1); + delete_fluid_event(ev); } /* schedule a timer event (shall trigger the callback) */ void -schedule_timer_event () +schedule_timer_event() { - fluid_event_t *ev = new_fluid_event (); - fluid_event_set_source (ev, -1); - fluid_event_set_dest (ev, client_destination); - fluid_event_timer (ev, NULL); - fluid_sequencer_send_at (sequencer, ev, time_marker, 1); - delete_fluid_event (ev); + fluid_event_t *ev = new_fluid_event(); + fluid_event_set_source(ev, -1); + fluid_event_set_dest(ev, client_destination); + fluid_event_timer(ev, NULL); + fluid_sequencer_send_at(sequencer, ev, time_marker, 1); + delete_fluid_event(ev); } /* schedule the arpeggio's notes */ void -schedule_pattern () +schedule_pattern() { int i, note_time, note_duration; note_time = time_marker; note_duration = duration / pattern_size; - for (i = 0; i < pattern_size; ++i) { - schedule_noteon (0, notes[i], note_time); + + for(i = 0; i < pattern_size; ++i) + { + schedule_noteon(0, notes[i], note_time); note_time += note_duration; - schedule_noteoff (0, notes[i], note_time); + schedule_noteoff(0, notes[i], note_time); } + time_marker += duration; } void -sequencer_callback (unsigned int time, fluid_event_t *event, - fluid_sequencer_t *seq, void *data) +sequencer_callback(unsigned int time, fluid_event_t *event, + fluid_sequencer_t *seq, void *data) { - schedule_timer_event (); - schedule_pattern (); + schedule_timer_event(); + schedule_pattern(); } void -usage (char* prog_name) +usage(char *prog_name) { - printf ("Usage: %s soundfont.sf2 [steps [duration]]\n", prog_name); - printf ("\t(optional) steps: number of pattern notes, from 2 to %d\n", - pattern_size); - printf ("\t(optional) duration: of the pattern in ticks, default %d\n", - duration); + printf("Usage: %s soundfont.sf2 [steps [duration]]\n", prog_name); + printf("\t(optional) steps: number of pattern notes, from 2 to %d\n", + pattern_size); + printf("\t(optional) duration: of the pattern in ticks, default %d\n", + duration); } int -main (int argc, char* argv[]) +main(int argc, char *argv[]) { int n; fluid_settings_t *settings; - settings = new_fluid_settings (); + settings = new_fluid_settings(); pattern_size = sizeof(notes) / sizeof(int); - if (argc < 2) { - usage (argv[0]); - } else { - /* create the synth, driver and sequencer instances */ - synth = new_fluid_synth (settings); - audiodriver = new_fluid_audio_driver (settings, synth); - sequencer = new_fluid_sequencer (); - /* register the synth with the sequencer */ - synth_destination = fluid_sequencer_register_fluidsynth (sequencer, - synth); - /* register the client name and callback */ - client_destination = fluid_sequencer_register_client (sequencer, - "arpeggio", sequencer_callback, NULL); - /* load a SoundFont */ - n = fluid_synth_sfload (synth, argv[1], 1); - if (n != -1) { - if (argc > 2) { - n = atoi (argv[2]); - if ((n > 1) && (n <= pattern_size)) pattern_size = n; - } - if (argc > 3) { - n = atoi (argv[3]); - if (n > 0) duration = n; - } - /* get the current time in ticks */ - time_marker = fluid_sequencer_get_tick (sequencer); - /* schedule patterns */ - schedule_pattern (); - schedule_timer_event (); - schedule_pattern (); - /* wait for user input */ - printf ("press to stop\n"); - n = getchar (); - } - /* clean and exit */ - delete_fluid_sequencer (sequencer); - delete_fluid_audio_driver (audiodriver); - delete_fluid_synth (synth); + + if(argc < 2) + { + usage(argv[0]); } - delete_fluid_settings (settings); + else + { + /* create the synth, driver and sequencer instances */ + synth = new_fluid_synth(settings); + audiodriver = new_fluid_audio_driver(settings, synth); + sequencer = new_fluid_sequencer(); + /* register the synth with the sequencer */ + synth_destination = fluid_sequencer_register_fluidsynth(sequencer, + synth); + /* register the client name and callback */ + client_destination = fluid_sequencer_register_client(sequencer, + "arpeggio", sequencer_callback, NULL); + /* load a SoundFont */ + n = fluid_synth_sfload(synth, argv[1], 1); + + if(n != -1) + { + if(argc > 2) + { + n = atoi(argv[2]); + + if((n > 1) && (n <= pattern_size)) + { + pattern_size = n; + } + } + + if(argc > 3) + { + n = atoi(argv[3]); + + if(n > 0) + { + duration = n; + } + } + + /* get the current time in ticks */ + time_marker = fluid_sequencer_get_tick(sequencer); + /* schedule patterns */ + schedule_pattern(); + schedule_timer_event(); + schedule_pattern(); + /* wait for user input */ + printf("press to stop\n"); + n = getchar(); + } + + /* clean and exit */ + delete_fluid_sequencer(sequencer); + delete_fluid_audio_driver(audiodriver); + delete_fluid_synth(synth); + } + + delete_fluid_settings(settings); return 0; } diff --git a/doc/fluidsynth_fx.c b/doc/fluidsynth_fx.c index 2add2b39..6e9a7441 100644 --- a/doc/fluidsynth_fx.c +++ b/doc/fluidsynth_fx.c @@ -19,9 +19,10 @@ /* The structure with the effects data. This example simply applies a * linear gain the to synthesizer output. */ -struct fx_data_t { - fluid_synth_t* synth; - float gain; +struct fx_data_t +{ + fluid_synth_t *synth; + float gain; } fx_data_t; /* This function implements the callback function of the audio driver @@ -37,103 +38,120 @@ struct fx_data_t { * audio drivers currently handles audio input. Either 'nin' will be * zero, or the buffers will be filled with zero samples. */ -int fx_function(void* data, int len, - int nin, float** in, - int nout, float** out) +int fx_function(void *data, int len, + int nin, float **in, + int nout, float **out) { - struct fx_data_t* fx_data = (struct fx_data_t*) data; - int i, k; - float* out_i; + struct fx_data_t *fx_data = (struct fx_data_t *) data; + int i, k; + float *out_i; - /* Call the synthesizer to fill the output buffers with its - * audio output. */ - if (fluid_synth_process(fx_data->synth, len, nin, in, nout, out) != 0) { - /* Some error occured. Very unlikely to happen, though. */ - return -1; - } + /* Call the synthesizer to fill the output buffers with its + * audio output. */ + if(fluid_synth_process(fx_data->synth, len, nin, in, nout, out) != 0) + { + /* Some error occured. Very unlikely to happen, though. */ + return -1; + } - /* Apply your effects here. In this example, the gain is - * applied to all the output buffers. */ - for (i = 0; i < nout; i++) { - out_i = out[i]; - for (k = 0; k < len; k++) { - out_i[k] *= fx_data->gain; - } - } + /* Apply your effects here. In this example, the gain is + * applied to all the output buffers. */ + for(i = 0; i < nout; i++) + { + out_i = out[i]; - return 0; + for(k = 0; k < len; k++) + { + out_i[k] *= fx_data->gain; + } + } + + return 0; } -int main(int argc, char** argv) +int main(int argc, char **argv) { - fluid_settings_t* settings; - fluid_synth_t* synth = NULL; - fluid_audio_driver_t* adriver = NULL; - int err = 0; - struct fx_data_t fx_data; + fluid_settings_t *settings; + fluid_synth_t *synth = NULL; + fluid_audio_driver_t *adriver = NULL; + int err = 0; + struct fx_data_t fx_data; - if (argc != 3) { - fprintf(stderr, "Usage: fluidsynth_simple [soundfont] [gain]\n"); - return 1; - } + if(argc != 3) + { + fprintf(stderr, "Usage: fluidsynth_simple [soundfont] [gain]\n"); + return 1; + } - /* Create the settings object. This example uses the default - * values for the settings. */ - settings = new_fluid_settings(); - if (settings == NULL) { - fprintf(stderr, "Failed to create the settings\n"); - err = 2; - goto cleanup; - } - - /* Create the synthesizer */ - synth = new_fluid_synth(settings); - if (synth == NULL) { - fprintf(stderr, "Failed to create the synthesizer\n"); - err = 3; - goto cleanup; - } + /* Create the settings object. This example uses the default + * values for the settings. */ + settings = new_fluid_settings(); - /* Load the soundfont */ - if (fluid_synth_sfload(synth, argv[1], 1) == -1) { - fprintf(stderr, "Failed to load the SoundFont\n"); - err = 4; - goto cleanup; - } + if(settings == NULL) + { + fprintf(stderr, "Failed to create the settings\n"); + err = 2; + goto cleanup; + } - /* Fill in the data of the effects unit */ - fx_data.synth = synth; - fx_data.gain = atof(argv[2]); + /* Create the synthesizer */ + synth = new_fluid_synth(settings); - /* Create the audio driver. As soon as the audio driver is - * created, the synthesizer can be played. */ - adriver = new_fluid_audio_driver2(settings, fx_function, (void*) &fx_data); - if (adriver == NULL) { - fprintf(stderr, "Failed to create the audio driver\n"); - err = 5; - goto cleanup; - } + if(synth == NULL) + { + fprintf(stderr, "Failed to create the synthesizer\n"); + err = 3; + goto cleanup; + } - /* Play a note */ - fluid_synth_noteon(synth, 0, 60, 100); + /* Load the soundfont */ + if(fluid_synth_sfload(synth, argv[1], 1) == -1) + { + fprintf(stderr, "Failed to load the SoundFont\n"); + err = 4; + goto cleanup; + } - printf("Press \"Enter\" to stop: "); - fgetc(stdin); - printf("done\n"); + /* Fill in the data of the effects unit */ + fx_data.synth = synth; + fx_data.gain = atof(argv[2]); - - cleanup: - - if (adriver) { - delete_fluid_audio_driver(adriver); - } - if (synth) { - delete_fluid_synth(synth); - } - if (settings) { - delete_fluid_settings(settings); - } - - return err; + /* Create the audio driver. As soon as the audio driver is + * created, the synthesizer can be played. */ + adriver = new_fluid_audio_driver2(settings, fx_function, (void *) &fx_data); + + if(adriver == NULL) + { + fprintf(stderr, "Failed to create the audio driver\n"); + err = 5; + goto cleanup; + } + + /* Play a note */ + fluid_synth_noteon(synth, 0, 60, 100); + + printf("Press \"Enter\" to stop: "); + fgetc(stdin); + printf("done\n"); + + +cleanup: + + if(adriver) + { + delete_fluid_audio_driver(adriver); + } + + if(synth) + { + delete_fluid_synth(synth); + } + + if(settings) + { + delete_fluid_settings(settings); + } + + return err; } diff --git a/doc/fluidsynth_metronome.c b/doc/fluidsynth_metronome.c index af00bfd4..72f508b4 100644 --- a/doc/fluidsynth_metronome.c +++ b/doc/fluidsynth_metronome.c @@ -30,108 +30,131 @@ unsigned int strong_note = 34; unsigned int pattern_size = 4; /* prototype */ void -sequencer_callback (unsigned int time, fluid_event_t *event, - fluid_sequencer_t *seq, void *data); +sequencer_callback(unsigned int time, fluid_event_t *event, + fluid_sequencer_t *seq, void *data); /* schedule a note on message */ void -schedule_noteon (int chan, short key, unsigned int ticks) +schedule_noteon(int chan, short key, unsigned int ticks) { - fluid_event_t *ev = new_fluid_event (); - fluid_event_set_source (ev, -1); - fluid_event_set_dest (ev, synth_destination); - fluid_event_noteon (ev, chan, key, 127); - fluid_sequencer_send_at (sequencer, ev, ticks, 1); - delete_fluid_event (ev); + fluid_event_t *ev = new_fluid_event(); + fluid_event_set_source(ev, -1); + fluid_event_set_dest(ev, synth_destination); + fluid_event_noteon(ev, chan, key, 127); + fluid_sequencer_send_at(sequencer, ev, ticks, 1); + delete_fluid_event(ev); } /* schedule a timer event (shall trigger the callback) */ void -schedule_timer_event () +schedule_timer_event() { - fluid_event_t *ev = new_fluid_event (); - fluid_event_set_source (ev, -1); - fluid_event_set_dest (ev, client_destination); - fluid_event_timer (ev, NULL); - fluid_sequencer_send_at (sequencer, ev, time_marker, 1); - delete_fluid_event (ev); + fluid_event_t *ev = new_fluid_event(); + fluid_event_set_source(ev, -1); + fluid_event_set_dest(ev, client_destination); + fluid_event_timer(ev, NULL); + fluid_sequencer_send_at(sequencer, ev, time_marker, 1); + delete_fluid_event(ev); } /* schedule the metronome pattern */ void -schedule_pattern () +schedule_pattern() { int i, note_time; note_time = time_marker; - for (i = 0; i < pattern_size; ++i) { - schedule_noteon (9, i ? weak_note : strong_note, note_time); + + for(i = 0; i < pattern_size; ++i) + { + schedule_noteon(9, i ? weak_note : strong_note, note_time); note_time += note_duration; } + time_marker = note_time; } void -sequencer_callback (unsigned int time, fluid_event_t *event, - fluid_sequencer_t *seq, void *data) +sequencer_callback(unsigned int time, fluid_event_t *event, + fluid_sequencer_t *seq, void *data) { - schedule_timer_event (); - schedule_pattern (); + schedule_timer_event(); + schedule_pattern(); } void -usage (char* prog_name) +usage(char *prog_name) { - printf ("Usage: %s soundfont.sf2 [beats [tempo]]\n", prog_name); - printf ("\t(optional) beats: number of pattern beats, default %d\n", - pattern_size); - printf ("\t(optional) tempo: BPM (Beats Per Minute), default %d\n", TEMPO); + printf("Usage: %s soundfont.sf2 [beats [tempo]]\n", prog_name); + printf("\t(optional) beats: number of pattern beats, default %d\n", + pattern_size); + printf("\t(optional) tempo: BPM (Beats Per Minute), default %d\n", TEMPO); } int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { int n; fluid_settings_t *settings; - settings = new_fluid_settings (); - if (argc < 2) { - usage (argv[0]); - } else { - /* create the synth, driver and sequencer instances */ - synth = new_fluid_synth (settings); - audiodriver = new_fluid_audio_driver (settings, synth); - sequencer = new_fluid_sequencer (); - /* register the synth with the sequencer */ - synth_destination = fluid_sequencer_register_fluidsynth (sequencer, - synth); - /* register the client name and callback */ - client_destination = fluid_sequencer_register_client (sequencer, - "fluidsynth_metronome", sequencer_callback, NULL); - /* load a SoundFont */ - n = fluid_synth_sfload (synth, argv[1], 1); - if (n != -1) { - if (argc > 2) { - n = atoi (argv[2]); - if (n > 0) pattern_size = n; - } - if (argc > 3) { - n = atoi (argv[3]); - if (n > 0) note_duration = 60000 / n; - } - /* get the current time in ticks */ - time_marker = fluid_sequencer_get_tick (sequencer); - /* schedule patterns */ - schedule_pattern (); - schedule_timer_event (); - schedule_pattern (); - /* wait for user input */ - printf ("press to stop\n"); - n = getchar (); - } - /* clean and exit */ - delete_fluid_sequencer (sequencer); - delete_fluid_audio_driver (audiodriver); - delete_fluid_synth (synth); + settings = new_fluid_settings(); + + if(argc < 2) + { + usage(argv[0]); } - delete_fluid_settings (settings); + else + { + /* create the synth, driver and sequencer instances */ + synth = new_fluid_synth(settings); + audiodriver = new_fluid_audio_driver(settings, synth); + sequencer = new_fluid_sequencer(); + /* register the synth with the sequencer */ + synth_destination = fluid_sequencer_register_fluidsynth(sequencer, + synth); + /* register the client name and callback */ + client_destination = fluid_sequencer_register_client(sequencer, + "fluidsynth_metronome", sequencer_callback, NULL); + /* load a SoundFont */ + n = fluid_synth_sfload(synth, argv[1], 1); + + if(n != -1) + { + if(argc > 2) + { + n = atoi(argv[2]); + + if(n > 0) + { + pattern_size = n; + } + } + + if(argc > 3) + { + n = atoi(argv[3]); + + if(n > 0) + { + note_duration = 60000 / n; + } + } + + /* get the current time in ticks */ + time_marker = fluid_sequencer_get_tick(sequencer); + /* schedule patterns */ + schedule_pattern(); + schedule_timer_event(); + schedule_pattern(); + /* wait for user input */ + printf("press to stop\n"); + n = getchar(); + } + + /* clean and exit */ + delete_fluid_sequencer(sequencer); + delete_fluid_audio_driver(audiodriver); + delete_fluid_synth(synth); + } + + delete_fluid_settings(settings); return 0; } diff --git a/doc/fluidsynth_process.c b/doc/fluidsynth_process.c index 9436d667..d9b1688e 100644 --- a/doc/fluidsynth_process.c +++ b/doc/fluidsynth_process.c @@ -19,7 +19,7 @@ int main() float left[SAMPLES], right[SAMPLES]; // array of buffers used to setup channel mapping - float *dry[1*2], *fx[1*2]; + float *dry[1 * 2], *fx[1 * 2]; // first make sure to zero out the sample buffers memset(left, 0, sizeof(left)); @@ -31,32 +31,41 @@ int main() // Setup channel mapping for a single stereo channel to which to render effects to. // Just using the same sample buffers as for dry audio is fine here, as it will cause the effects to be mixed with dry output. - // Note: reverb and chorus together make up two stereo channels. Setting up only one stereo channel is sufficient + // Note: reverb and chorus together make up two stereo channels. Setting up only one stereo channel is sufficient // as the channels warp around (i.e. chorus will be mixed with reverb channel). fx[0] = left; fx[1] = right; int err = fluid_synth_process(synth, SAMPLES, 2, fx, 2, dry); + if(err == FLUID_FAILED) + { puts(„oops“); + } // USECASE2: only render dry audio and discard effects // same as above, but call fluid_synth_process() like: int err = fluid_synth_process(synth, SAMPLES, 0, NULL, 2, dry); + if(err == FLUID_FAILED) + { puts(„oops“); + } } - + // USECASE3: render audio and discard all samples { int err = fluid_synth_process(synth, SAMPLES, 0, NULL, 0, NULL); + if(err == FLUID_FAILED) + { puts(„oops“); + } } - + // USECASE4: multi-channel rendering, i.e. render all audio and effects channels to dedicated audio buffers // ofc it‘s not a good idea to allocate all the arrays on the stack { @@ -79,7 +88,7 @@ int main() // ... // dry[i*2 + 0] = i‘th audio channel left // dry[i*2 + 1] = i‘th audio channel right - for(int i=0; i= 2 + if(res != FLUID_OK) #else if(res == 0) @@ -51,18 +53,19 @@ int main() return -1; } - fluid_synth_t* synth = new_fluid_synth(settings); - fluid_audio_driver_t* ad = new_fluid_audio_driver(settings, synth); + fluid_synth_t *synth = new_fluid_synth(settings); + fluid_audio_driver_t *ad = new_fluid_audio_driver(settings, synth); /* * ~~~ Do your daily business here ~~~ */ - + delete_fluid_audio_driver(ad); delete_fluid_synth(synth); delete_fluid_settings(settings); - + /* everything cleaned up, fluid_audio_driver_register() can be called again if needed */ } + return 0; } diff --git a/doc/fluidsynth_sfload_mem.c b/doc/fluidsynth_sfload_mem.c index caa2a674..3b9bcef2 100644 --- a/doc/fluidsynth_sfload_mem.c +++ b/doc/fluidsynth_sfload_mem.c @@ -1,6 +1,6 @@ /* * This is a C99 program that demonstrates how to load a soundfont from memory. - * + * * It only gives a brief overview on how to achieve this with fluidsynth's API. * Although it should compile, it's highly incomplete, as the details of it's * implementation depend on the users needs. @@ -10,37 +10,39 @@ #include #include -void * my_open(const char * filename) +void *my_open(const char *filename) { - void* p; + void *p; + if(filename[0] != '&') { return NULL; } + scanf("&%p", &p); return p; } -int my_read(void *buf, int count, void * handle) +int my_read(void *buf, int count, void *handle) { // not yet implemented memset(buf, 0, count); return FLUID_OK; } -int my_seek(void * handle, long offset, int origin) +int my_seek(void *handle, long offset, int origin) { // NYI return FLUID_OK; } -int my_close(void * handle) +int my_close(void *handle) { // NYI return FLUID_OK; } -long my_tell(void * handle) +long my_tell(void *handle) { // NYI return 0; @@ -50,10 +52,10 @@ int main() { int err = 0; - fluid_settings_t* settings = new_fluid_settings(); - fluid_synth_t* synth = new_fluid_synth(settings); - - fluid_sfloader_t* my_sfloader = new_fluid_defsfloader(settings); + fluid_settings_t *settings = new_fluid_settings(); + fluid_synth_t *synth = new_fluid_synth(settings); + + fluid_sfloader_t *my_sfloader = new_fluid_defsfloader(settings); fluid_sfloader_set_callbacks(my_sfloader, my_open, my_read, @@ -61,15 +63,15 @@ int main() my_tell, my_close); fluid_synth_add_sfloader(synth, my_sfloader); - - + + char abused_filename[64]; - const void* pointer_to_sf2_in_mem = 0x1234Beef; // some pointer to where the soundfont shall be loaded from + const void *pointer_to_sf2_in_mem = 0x1234Beef; // some pointer to where the soundfont shall be loaded from sprintf(abused_filename, "&%p", pointer_to_sf2_in_mem); - + int id = fluid_synth_sfload(synth, abused_filename, 0); /* now my_open() will be called with abused_filename and should have opened the memory region */ - + if(id == FLUID_FAILED) { puts("oops"); @@ -80,12 +82,12 @@ int main() /* * ~~~ Do your daily business here ~~~ */ - -cleanup: + +cleanup: /* deleting the synth also deletes my_sfloader */ delete_fluid_synth(synth); - + delete_fluid_settings(settings); - + return err; } diff --git a/doc/fluidsynth_simple.c b/doc/fluidsynth_simple.c index 0614ca1e..23bfff3b 100644 --- a/doc/fluidsynth_simple.c +++ b/doc/fluidsynth_simple.c @@ -15,70 +15,83 @@ #include #include -int main(int argc, char** argv) +int main(int argc, char **argv) { - fluid_settings_t* settings; - fluid_synth_t* synth = NULL; - fluid_audio_driver_t* adriver = NULL; - int err = 0; + fluid_settings_t *settings; + fluid_synth_t *synth = NULL; + fluid_audio_driver_t *adriver = NULL; + int err = 0; - if (argc != 2) { - fprintf(stderr, "Usage: fluidsynth_simple [soundfont]\n"); - return 1; - } + if(argc != 2) + { + fprintf(stderr, "Usage: fluidsynth_simple [soundfont]\n"); + return 1; + } - /* Create the settings object. This example uses the default - * values for the settings. */ - settings = new_fluid_settings(); - if (settings == NULL) { - fprintf(stderr, "Failed to create the settings\n"); - err = 2; - goto cleanup; - } - - /* Create the synthesizer */ - synth = new_fluid_synth(settings); - if (synth == NULL) { - fprintf(stderr, "Failed to create the synthesizer\n"); - err = 3; - goto cleanup; - } + /* Create the settings object. This example uses the default + * values for the settings. */ + settings = new_fluid_settings(); - /* Load the soundfont */ - if (fluid_synth_sfload(synth, argv[1], 1) == -1) { - fprintf(stderr, "Failed to load the SoundFont\n"); - err = 4; - goto cleanup; - } + if(settings == NULL) + { + fprintf(stderr, "Failed to create the settings\n"); + err = 2; + goto cleanup; + } - /* Create the audio driver. As soon as the audio driver is - * created, the synthesizer can be played. */ - adriver = new_fluid_audio_driver(settings, synth); - if (adriver == NULL) { - fprintf(stderr, "Failed to create the audio driver\n"); - err = 5; - goto cleanup; - } + /* Create the synthesizer */ + synth = new_fluid_synth(settings); - /* Play a note */ - fluid_synth_noteon(synth, 0, 60, 100); + if(synth == NULL) + { + fprintf(stderr, "Failed to create the synthesizer\n"); + err = 3; + goto cleanup; + } - printf("Press \"Enter\" to stop: "); - fgetc(stdin); - printf("done\n"); + /* Load the soundfont */ + if(fluid_synth_sfload(synth, argv[1], 1) == -1) + { + fprintf(stderr, "Failed to load the SoundFont\n"); + err = 4; + goto cleanup; + } - - cleanup: - - if (adriver) { - delete_fluid_audio_driver(adriver); - } - if (synth) { - delete_fluid_synth(synth); - } - if (settings) { - delete_fluid_settings(settings); - } - - return err; + /* Create the audio driver. As soon as the audio driver is + * created, the synthesizer can be played. */ + adriver = new_fluid_audio_driver(settings, synth); + + if(adriver == NULL) + { + fprintf(stderr, "Failed to create the audio driver\n"); + err = 5; + goto cleanup; + } + + /* Play a note */ + fluid_synth_noteon(synth, 0, 60, 100); + + printf("Press \"Enter\" to stop: "); + fgetc(stdin); + printf("done\n"); + + +cleanup: + + if(adriver) + { + delete_fluid_audio_driver(adriver); + } + + if(synth) + { + delete_fluid_synth(synth); + } + + if(settings) + { + delete_fluid_settings(settings); + } + + return err; } diff --git a/include/fluidsynth/audio.h b/include/fluidsynth/audio.h index 8341b81d..c9b8c580 100644 --- a/include/fluidsynth/audio.h +++ b/include/fluidsynth/audio.h @@ -52,25 +52,25 @@ extern "C" { * @param out Array of buffers to store (dry) audio to. Buffers may alias with buffers of \c fx. * @return Should return #FLUID_OK on success, #FLUID_FAILED if an error occured. */ -typedef int (*fluid_audio_func_t)(void* data, int len, - int nfx, float* fx[], - int nout, float* out[]); +typedef int (*fluid_audio_func_t)(void *data, int len, + int nfx, float *fx[], + int nout, float *out[]); -FLUIDSYNTH_API fluid_audio_driver_t* new_fluid_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); +FLUIDSYNTH_API fluid_audio_driver_t *new_fluid_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); -FLUIDSYNTH_API fluid_audio_driver_t* new_fluid_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, - void* data); +FLUIDSYNTH_API fluid_audio_driver_t *new_fluid_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, + void *data); -FLUIDSYNTH_API void delete_fluid_audio_driver(fluid_audio_driver_t* driver); +FLUIDSYNTH_API void delete_fluid_audio_driver(fluid_audio_driver_t *driver); -FLUIDSYNTH_API fluid_file_renderer_t *new_fluid_file_renderer(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_file_renderer_process_block(fluid_file_renderer_t* dev); -FLUIDSYNTH_API void delete_fluid_file_renderer(fluid_file_renderer_t* dev); -FLUIDSYNTH_API int fluid_file_set_encoding_quality(fluid_file_renderer_t* dev, double q); +FLUIDSYNTH_API fluid_file_renderer_t *new_fluid_file_renderer(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_file_renderer_process_block(fluid_file_renderer_t *dev); +FLUIDSYNTH_API void delete_fluid_file_renderer(fluid_file_renderer_t *dev); +FLUIDSYNTH_API int fluid_file_set_encoding_quality(fluid_file_renderer_t *dev, double q); -FLUIDSYNTH_API int fluid_audio_driver_register(const char** adrivers); +FLUIDSYNTH_API int fluid_audio_driver_register(const char **adrivers); #ifdef __cplusplus } diff --git a/include/fluidsynth/event.h b/include/fluidsynth/event.h index 1f601074..cbd1fa6a 100644 --- a/include/fluidsynth/event.h +++ b/include/fluidsynth/event.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -35,101 +35,102 @@ extern "C" { /** * Sequencer event type enumeration. */ -enum fluid_seq_event_type { - FLUID_SEQ_NOTE = 0, /**< Note event with duration */ - FLUID_SEQ_NOTEON, /**< Note on event */ - FLUID_SEQ_NOTEOFF, /**< Note off event */ - FLUID_SEQ_ALLSOUNDSOFF, /**< All sounds off event */ - FLUID_SEQ_ALLNOTESOFF, /**< All notes off event */ - FLUID_SEQ_BANKSELECT, /**< Bank select message */ - FLUID_SEQ_PROGRAMCHANGE, /**< Program change message */ - FLUID_SEQ_PROGRAMSELECT, /**< Program select message */ - FLUID_SEQ_PITCHBEND, /**< Pitch bend message */ - FLUID_SEQ_PITCHWHEELSENS, /**< Pitch wheel sensitivity set message @since 1.1.0 was mispelled previously */ - FLUID_SEQ_MODULATION, /**< Modulation controller event */ - FLUID_SEQ_SUSTAIN, /**< Sustain controller event */ - FLUID_SEQ_CONTROLCHANGE, /**< MIDI control change event */ - FLUID_SEQ_PAN, /**< Stereo pan set event */ - FLUID_SEQ_VOLUME, /**< Volume set event */ - FLUID_SEQ_REVERBSEND, /**< Reverb send set event */ - FLUID_SEQ_CHORUSSEND, /**< Chorus send set event */ - FLUID_SEQ_TIMER, /**< Timer event (useful for giving a callback at a certain time) */ - FLUID_SEQ_ANYCONTROLCHANGE, /**< Any control change message (only internally used for remove_events) */ - FLUID_SEQ_CHANNELPRESSURE, /**< Channel aftertouch event @since 1.1.0 */ - FLUID_SEQ_KEYPRESSURE, /**< Polyphonic aftertouch event @since 2.0.0 */ - FLUID_SEQ_SYSTEMRESET, /**< System reset event @since 1.1.0 */ - FLUID_SEQ_UNREGISTERING, /**< Called when a sequencer client is being unregistered. @since 1.1.0 */ +enum fluid_seq_event_type +{ + FLUID_SEQ_NOTE = 0, /**< Note event with duration */ + FLUID_SEQ_NOTEON, /**< Note on event */ + FLUID_SEQ_NOTEOFF, /**< Note off event */ + FLUID_SEQ_ALLSOUNDSOFF, /**< All sounds off event */ + FLUID_SEQ_ALLNOTESOFF, /**< All notes off event */ + FLUID_SEQ_BANKSELECT, /**< Bank select message */ + FLUID_SEQ_PROGRAMCHANGE, /**< Program change message */ + FLUID_SEQ_PROGRAMSELECT, /**< Program select message */ + FLUID_SEQ_PITCHBEND, /**< Pitch bend message */ + FLUID_SEQ_PITCHWHEELSENS, /**< Pitch wheel sensitivity set message @since 1.1.0 was mispelled previously */ + FLUID_SEQ_MODULATION, /**< Modulation controller event */ + FLUID_SEQ_SUSTAIN, /**< Sustain controller event */ + FLUID_SEQ_CONTROLCHANGE, /**< MIDI control change event */ + FLUID_SEQ_PAN, /**< Stereo pan set event */ + FLUID_SEQ_VOLUME, /**< Volume set event */ + FLUID_SEQ_REVERBSEND, /**< Reverb send set event */ + FLUID_SEQ_CHORUSSEND, /**< Chorus send set event */ + FLUID_SEQ_TIMER, /**< Timer event (useful for giving a callback at a certain time) */ + FLUID_SEQ_ANYCONTROLCHANGE, /**< Any control change message (only internally used for remove_events) */ + FLUID_SEQ_CHANNELPRESSURE, /**< Channel aftertouch event @since 1.1.0 */ + FLUID_SEQ_KEYPRESSURE, /**< Polyphonic aftertouch event @since 2.0.0 */ + FLUID_SEQ_SYSTEMRESET, /**< System reset event @since 1.1.0 */ + FLUID_SEQ_UNREGISTERING, /**< Called when a sequencer client is being unregistered. @since 1.1.0 */ #ifndef __DOXYGEN__ - FLUID_SEQ_LASTEVENT /**< @internal Defines the count of events enums @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ + FLUID_SEQ_LASTEVENT /**< @internal Defines the count of events enums @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ #endif }; /* Event alloc/free */ -FLUIDSYNTH_API fluid_event_t* new_fluid_event(void); -FLUIDSYNTH_API void delete_fluid_event(fluid_event_t* evt); +FLUIDSYNTH_API fluid_event_t *new_fluid_event(void); +FLUIDSYNTH_API void delete_fluid_event(fluid_event_t *evt); /* Initializing events */ -FLUIDSYNTH_API void fluid_event_set_source(fluid_event_t* evt, fluid_seq_id_t src); -FLUIDSYNTH_API void fluid_event_set_dest(fluid_event_t* evt, fluid_seq_id_t dest); +FLUIDSYNTH_API void fluid_event_set_source(fluid_event_t *evt, fluid_seq_id_t src); +FLUIDSYNTH_API void fluid_event_set_dest(fluid_event_t *evt, fluid_seq_id_t dest); /* Timer events */ -FLUIDSYNTH_API void fluid_event_timer(fluid_event_t* evt, void* data); +FLUIDSYNTH_API void fluid_event_timer(fluid_event_t *evt, void *data); /* Note events */ -FLUIDSYNTH_API void fluid_event_note(fluid_event_t* evt, int channel, - short key, short vel, - unsigned int duration); +FLUIDSYNTH_API void fluid_event_note(fluid_event_t *evt, int channel, + short key, short vel, + unsigned int duration); -FLUIDSYNTH_API void fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel); -FLUIDSYNTH_API void fluid_event_noteoff(fluid_event_t* evt, int channel, short key); -FLUIDSYNTH_API void fluid_event_all_sounds_off(fluid_event_t* evt, int channel); -FLUIDSYNTH_API void fluid_event_all_notes_off(fluid_event_t* evt, int channel); +FLUIDSYNTH_API void fluid_event_noteon(fluid_event_t *evt, int channel, short key, short vel); +FLUIDSYNTH_API void fluid_event_noteoff(fluid_event_t *evt, int channel, short key); +FLUIDSYNTH_API void fluid_event_all_sounds_off(fluid_event_t *evt, int channel); +FLUIDSYNTH_API void fluid_event_all_notes_off(fluid_event_t *evt, int channel); /* Instrument selection */ -FLUIDSYNTH_API void fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num); -FLUIDSYNTH_API void fluid_event_program_change(fluid_event_t* evt, int channel, short preset_num); -FLUIDSYNTH_API void fluid_event_program_select(fluid_event_t* evt, int channel, unsigned int sfont_id, short bank_num, short preset_num); +FLUIDSYNTH_API void fluid_event_bank_select(fluid_event_t *evt, int channel, short bank_num); +FLUIDSYNTH_API void fluid_event_program_change(fluid_event_t *evt, int channel, short preset_num); +FLUIDSYNTH_API void fluid_event_program_select(fluid_event_t *evt, int channel, unsigned int sfont_id, short bank_num, short preset_num); /* Real-time generic instrument controllers */ -FLUIDSYNTH_API -void fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val); +FLUIDSYNTH_API +void fluid_event_control_change(fluid_event_t *evt, int channel, short control, short val); /* Real-time instrument controllers shortcuts */ -FLUIDSYNTH_API void fluid_event_pitch_bend(fluid_event_t* evt, int channel, int val); -FLUIDSYNTH_API void fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_modulation(fluid_event_t* evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_sustain(fluid_event_t* evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_pan(fluid_event_t* evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_volume(fluid_event_t* evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_reverb_send(fluid_event_t* evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_chorus_send(fluid_event_t* evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_pitch_bend(fluid_event_t *evt, int channel, int val); +FLUIDSYNTH_API void fluid_event_pitch_wheelsens(fluid_event_t *evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_modulation(fluid_event_t *evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_sustain(fluid_event_t *evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_pan(fluid_event_t *evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_volume(fluid_event_t *evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_reverb_send(fluid_event_t *evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_chorus_send(fluid_event_t *evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_key_pressure(fluid_event_t* evt, int channel, short key, short val); -FLUIDSYNTH_API void fluid_event_channel_pressure(fluid_event_t* evt, int channel, short val); -FLUIDSYNTH_API void fluid_event_system_reset(fluid_event_t* evt); +FLUIDSYNTH_API void fluid_event_key_pressure(fluid_event_t *evt, int channel, short key, short val); +FLUIDSYNTH_API void fluid_event_channel_pressure(fluid_event_t *evt, int channel, short val); +FLUIDSYNTH_API void fluid_event_system_reset(fluid_event_t *evt); /* Only for removing events */ -FLUIDSYNTH_API void fluid_event_any_control_change(fluid_event_t* evt, int channel); +FLUIDSYNTH_API void fluid_event_any_control_change(fluid_event_t *evt, int channel); /* Only when unregistering clients */ -FLUIDSYNTH_API void fluid_event_unregistering(fluid_event_t* evt); +FLUIDSYNTH_API void fluid_event_unregistering(fluid_event_t *evt); /* Accessing event data */ -FLUIDSYNTH_API int fluid_event_get_type(fluid_event_t* evt); -FLUIDSYNTH_API fluid_seq_id_t fluid_event_get_source(fluid_event_t* evt); -FLUIDSYNTH_API fluid_seq_id_t fluid_event_get_dest(fluid_event_t* evt); -FLUIDSYNTH_API int fluid_event_get_channel(fluid_event_t* evt); -FLUIDSYNTH_API short fluid_event_get_key(fluid_event_t* evt); -FLUIDSYNTH_API short fluid_event_get_velocity(fluid_event_t* evt); -FLUIDSYNTH_API short fluid_event_get_control(fluid_event_t* evt); -FLUIDSYNTH_API short fluid_event_get_value(fluid_event_t* evt); -FLUIDSYNTH_API short fluid_event_get_program(fluid_event_t* evt); -FLUIDSYNTH_API void* fluid_event_get_data(fluid_event_t* evt); -FLUIDSYNTH_API unsigned int fluid_event_get_duration(fluid_event_t* evt); -FLUIDSYNTH_API short fluid_event_get_bank(fluid_event_t* evt); -FLUIDSYNTH_API int fluid_event_get_pitch(fluid_event_t* evt); -FLUIDSYNTH_API unsigned int fluid_event_get_sfont_id(fluid_event_t* evt); +FLUIDSYNTH_API int fluid_event_get_type(fluid_event_t *evt); +FLUIDSYNTH_API fluid_seq_id_t fluid_event_get_source(fluid_event_t *evt); +FLUIDSYNTH_API fluid_seq_id_t fluid_event_get_dest(fluid_event_t *evt); +FLUIDSYNTH_API int fluid_event_get_channel(fluid_event_t *evt); +FLUIDSYNTH_API short fluid_event_get_key(fluid_event_t *evt); +FLUIDSYNTH_API short fluid_event_get_velocity(fluid_event_t *evt); +FLUIDSYNTH_API short fluid_event_get_control(fluid_event_t *evt); +FLUIDSYNTH_API short fluid_event_get_value(fluid_event_t *evt); +FLUIDSYNTH_API short fluid_event_get_program(fluid_event_t *evt); +FLUIDSYNTH_API void *fluid_event_get_data(fluid_event_t *evt); +FLUIDSYNTH_API unsigned int fluid_event_get_duration(fluid_event_t *evt); +FLUIDSYNTH_API short fluid_event_get_bank(fluid_event_t *evt); +FLUIDSYNTH_API int fluid_event_get_pitch(fluid_event_t *evt); +FLUIDSYNTH_API unsigned int fluid_event_get_sfont_id(fluid_event_t *evt); #ifdef __cplusplus } diff --git a/include/fluidsynth/gen.h b/include/fluidsynth/gen.h index 74ccd213..4b625831 100644 --- a/include/fluidsynth/gen.h +++ b/include/fluidsynth/gen.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -33,80 +33,81 @@ extern "C" { /** * Generator (effect) numbers (Soundfont 2.01 specifications section 8.1.3) */ -enum fluid_gen_type { - GEN_STARTADDROFS, /**< Sample start address offset (0-32767) */ - GEN_ENDADDROFS, /**< Sample end address offset (-32767-0) */ - GEN_STARTLOOPADDROFS, /**< Sample loop start address offset (-32767-32767) */ - GEN_ENDLOOPADDROFS, /**< Sample loop end address offset (-32767-32767) */ - GEN_STARTADDRCOARSEOFS, /**< Sample start address coarse offset (X 32768) */ - GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */ - GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */ - GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */ - GEN_FILTERFC, /**< Filter cutoff */ - GEN_FILTERQ, /**< Filter Q */ - GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */ - GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */ - GEN_ENDADDRCOARSEOFS, /**< Sample end address coarse offset (X 32768) */ - GEN_MODLFOTOVOL, /**< Modulation LFO to volume */ - GEN_UNUSED1, /**< Unused */ - GEN_CHORUSSEND, /**< Chorus send amount */ - GEN_REVERBSEND, /**< Reverb send amount */ - GEN_PAN, /**< Stereo panning */ - GEN_UNUSED2, /**< Unused */ - GEN_UNUSED3, /**< Unused */ - GEN_UNUSED4, /**< Unused */ - GEN_MODLFODELAY, /**< Modulation LFO delay */ - GEN_MODLFOFREQ, /**< Modulation LFO frequency */ - GEN_VIBLFODELAY, /**< Vibrato LFO delay */ - GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */ - GEN_MODENVDELAY, /**< Modulation envelope delay */ - GEN_MODENVATTACK, /**< Modulation envelope attack */ - GEN_MODENVHOLD, /**< Modulation envelope hold */ - GEN_MODENVDECAY, /**< Modulation envelope decay */ - GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */ - GEN_MODENVRELEASE, /**< Modulation envelope release */ - GEN_KEYTOMODENVHOLD, /**< Key to modulation envelope hold */ - GEN_KEYTOMODENVDECAY, /**< Key to modulation envelope decay */ - GEN_VOLENVDELAY, /**< Volume envelope delay */ - GEN_VOLENVATTACK, /**< Volume envelope attack */ - GEN_VOLENVHOLD, /**< Volume envelope hold */ - GEN_VOLENVDECAY, /**< Volume envelope decay */ - GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */ - GEN_VOLENVRELEASE, /**< Volume envelope release */ - GEN_KEYTOVOLENVHOLD, /**< Key to volume envelope hold */ - GEN_KEYTOVOLENVDECAY, /**< Key to volume envelope decay */ - GEN_INSTRUMENT, /**< Instrument ID (shouldn't be set by user) */ - GEN_RESERVED1, /**< Reserved */ - GEN_KEYRANGE, /**< MIDI note range */ - GEN_VELRANGE, /**< MIDI velocity range */ - GEN_STARTLOOPADDRCOARSEOFS, /**< Sample start loop address coarse offset (X 32768) */ - GEN_KEYNUM, /**< Fixed MIDI note number */ - GEN_VELOCITY, /**< Fixed MIDI velocity value */ - GEN_ATTENUATION, /**< Initial volume attenuation */ - GEN_RESERVED2, /**< Reserved */ - GEN_ENDLOOPADDRCOARSEOFS, /**< Sample end loop address coarse offset (X 32768) */ - GEN_COARSETUNE, /**< Coarse tuning */ - GEN_FINETUNE, /**< Fine tuning */ - GEN_SAMPLEID, /**< Sample ID (shouldn't be set by user) */ - GEN_SAMPLEMODE, /**< Sample mode flags */ - GEN_RESERVED3, /**< Reserved */ - GEN_SCALETUNE, /**< Scale tuning */ - GEN_EXCLUSIVECLASS, /**< Exclusive class number */ - GEN_OVERRIDEROOTKEY, /**< Sample root note override */ +enum fluid_gen_type +{ + GEN_STARTADDROFS, /**< Sample start address offset (0-32767) */ + GEN_ENDADDROFS, /**< Sample end address offset (-32767-0) */ + GEN_STARTLOOPADDROFS, /**< Sample loop start address offset (-32767-32767) */ + GEN_ENDLOOPADDROFS, /**< Sample loop end address offset (-32767-32767) */ + GEN_STARTADDRCOARSEOFS, /**< Sample start address coarse offset (X 32768) */ + GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */ + GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */ + GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */ + GEN_FILTERFC, /**< Filter cutoff */ + GEN_FILTERQ, /**< Filter Q */ + GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */ + GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */ + GEN_ENDADDRCOARSEOFS, /**< Sample end address coarse offset (X 32768) */ + GEN_MODLFOTOVOL, /**< Modulation LFO to volume */ + GEN_UNUSED1, /**< Unused */ + GEN_CHORUSSEND, /**< Chorus send amount */ + GEN_REVERBSEND, /**< Reverb send amount */ + GEN_PAN, /**< Stereo panning */ + GEN_UNUSED2, /**< Unused */ + GEN_UNUSED3, /**< Unused */ + GEN_UNUSED4, /**< Unused */ + GEN_MODLFODELAY, /**< Modulation LFO delay */ + GEN_MODLFOFREQ, /**< Modulation LFO frequency */ + GEN_VIBLFODELAY, /**< Vibrato LFO delay */ + GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */ + GEN_MODENVDELAY, /**< Modulation envelope delay */ + GEN_MODENVATTACK, /**< Modulation envelope attack */ + GEN_MODENVHOLD, /**< Modulation envelope hold */ + GEN_MODENVDECAY, /**< Modulation envelope decay */ + GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */ + GEN_MODENVRELEASE, /**< Modulation envelope release */ + GEN_KEYTOMODENVHOLD, /**< Key to modulation envelope hold */ + GEN_KEYTOMODENVDECAY, /**< Key to modulation envelope decay */ + GEN_VOLENVDELAY, /**< Volume envelope delay */ + GEN_VOLENVATTACK, /**< Volume envelope attack */ + GEN_VOLENVHOLD, /**< Volume envelope hold */ + GEN_VOLENVDECAY, /**< Volume envelope decay */ + GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */ + GEN_VOLENVRELEASE, /**< Volume envelope release */ + GEN_KEYTOVOLENVHOLD, /**< Key to volume envelope hold */ + GEN_KEYTOVOLENVDECAY, /**< Key to volume envelope decay */ + GEN_INSTRUMENT, /**< Instrument ID (shouldn't be set by user) */ + GEN_RESERVED1, /**< Reserved */ + GEN_KEYRANGE, /**< MIDI note range */ + GEN_VELRANGE, /**< MIDI velocity range */ + GEN_STARTLOOPADDRCOARSEOFS, /**< Sample start loop address coarse offset (X 32768) */ + GEN_KEYNUM, /**< Fixed MIDI note number */ + GEN_VELOCITY, /**< Fixed MIDI velocity value */ + GEN_ATTENUATION, /**< Initial volume attenuation */ + GEN_RESERVED2, /**< Reserved */ + GEN_ENDLOOPADDRCOARSEOFS, /**< Sample end loop address coarse offset (X 32768) */ + GEN_COARSETUNE, /**< Coarse tuning */ + GEN_FINETUNE, /**< Fine tuning */ + GEN_SAMPLEID, /**< Sample ID (shouldn't be set by user) */ + GEN_SAMPLEMODE, /**< Sample mode flags */ + GEN_RESERVED3, /**< Reserved */ + GEN_SCALETUNE, /**< Scale tuning */ + GEN_EXCLUSIVECLASS, /**< Exclusive class number */ + GEN_OVERRIDEROOTKEY, /**< Sample root note override */ - /* the initial pitch is not a "standard" generator. It is not - * mentioned in the list of generator in the SF2 specifications. It - * is used, however, as the destination for the default pitch wheel - * modulator. */ - GEN_PITCH, /**< Pitch @note Not a real SoundFont generator */ + /* the initial pitch is not a "standard" generator. It is not + * mentioned in the list of generator in the SF2 specifications. It + * is used, however, as the destination for the default pitch wheel + * modulator. */ + GEN_PITCH, /**< Pitch @note Not a real SoundFont generator */ + + GEN_CUSTOM_BALANCE, /**< Balance @note Not a real SoundFont generator */ + /* non-standard generator for an additional custom high- or low-pass filter */ + GEN_CUSTOM_FILTERFC, /**< Custom filter cutoff frequency */ + GEN_CUSTOM_FILTERQ, /**< Custom filter Q */ - GEN_CUSTOM_BALANCE, /**< Balance @note Not a real SoundFont generator */ - /* non-standard generator for an additional custom high- or low-pass filter */ - GEN_CUSTOM_FILTERFC, /**< Custom filter cutoff frequency */ - GEN_CUSTOM_FILTERQ, /**< Custom filter Q */ - #ifndef __DOXYGEN__ - GEN_LAST /**< @internal Value defines the count of generators (#fluid_gen_type) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ + GEN_LAST /**< @internal Value defines the count of generators (#fluid_gen_type) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ #endif }; diff --git a/include/fluidsynth/ladspa.h b/include/fluidsynth/ladspa.h index f12bb33e..978ce6d3 100644 --- a/include/fluidsynth/ladspa.h +++ b/include/fluidsynth/ladspa.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -28,10 +28,10 @@ extern "C" { /** * @file ladspa.h * @brief Functions for manipulating the ladspa effects unit - * - * This header defines useful functions for programatically manipulating the ladspa + * + * This header defines useful functions for programatically manipulating the ladspa * effects unit of the synth that can be retrieved via fluid_synth_get_ladspa_fx(). - * + * * Using any of those functions requires fluidsynth to be compiled with ladspa support. * Else all of those functions are useless dummies. */ @@ -56,7 +56,7 @@ FLUIDSYNTH_API int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const const char *port_name, float val); FLUIDSYNTH_API int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name, const char *port_name, const char *name); - + #ifdef __cplusplus } #endif diff --git a/include/fluidsynth/log.h b/include/fluidsynth/log.h index 61bbef21..eca44200 100644 --- a/include/fluidsynth/log.h +++ b/include/fluidsynth/log.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -52,14 +52,15 @@ extern "C" { /** * FluidSynth log levels. */ -enum fluid_log_level { - FLUID_PANIC, /**< The synth can't function correctly any more */ - FLUID_ERR, /**< Serious error occurred */ - FLUID_WARN, /**< Warning */ - FLUID_INFO, /**< Verbose informational messages */ - FLUID_DBG, /**< Debugging messages */ +enum fluid_log_level +{ + FLUID_PANIC, /**< The synth can't function correctly any more */ + FLUID_ERR, /**< Serious error occurred */ + FLUID_WARN, /**< Warning */ + FLUID_INFO, /**< Verbose informational messages */ + FLUID_DBG, /**< Debugging messages */ #ifndef __DOXYGEN__ - LAST_LOG_LEVEL /**< @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ + LAST_LOG_LEVEL /**< @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ #endif }; @@ -69,12 +70,12 @@ enum fluid_log_level { * @param message Log message text * @param data User data pointer supplied to fluid_set_log_function(). */ -typedef void (*fluid_log_function_t)(int level, char* message, void* data); +typedef void (*fluid_log_function_t)(int level, char *message, void *data); -FLUIDSYNTH_API -fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data); +FLUIDSYNTH_API +fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void *data); -FLUIDSYNTH_API void fluid_default_log_function(int level, char* message, void* data); +FLUIDSYNTH_API void fluid_default_log_function(int level, char *message, void *data); FLUIDSYNTH_API int fluid_log(int level, const char *fmt, ...); diff --git a/include/fluidsynth/midi.h b/include/fluidsynth/midi.h index dafc034d..cd30e208 100644 --- a/include/fluidsynth/midi.h +++ b/include/fluidsynth/midi.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -30,31 +30,31 @@ extern "C" { * @brief Functions for MIDI events, drivers and MIDI file playback. */ -FLUIDSYNTH_API fluid_midi_event_t* new_fluid_midi_event(void); -FLUIDSYNTH_API void delete_fluid_midi_event(fluid_midi_event_t* event); +FLUIDSYNTH_API fluid_midi_event_t *new_fluid_midi_event(void); +FLUIDSYNTH_API void delete_fluid_midi_event(fluid_midi_event_t *event); -FLUIDSYNTH_API int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type); -FLUIDSYNTH_API int fluid_midi_event_get_type(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan); -FLUIDSYNTH_API int fluid_midi_event_get_channel(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_get_key(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_set_key(fluid_midi_event_t* evt, int key); -FLUIDSYNTH_API int fluid_midi_event_get_velocity(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int vel); -FLUIDSYNTH_API int fluid_midi_event_get_control(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_set_control(fluid_midi_event_t* evt, int ctrl); -FLUIDSYNTH_API int fluid_midi_event_get_value(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_set_value(fluid_midi_event_t* evt, int val); -FLUIDSYNTH_API int fluid_midi_event_get_program(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val); -FLUIDSYNTH_API int fluid_midi_event_get_pitch(fluid_midi_event_t* evt); -FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val); -FLUIDSYNTH_API int fluid_midi_event_set_sysex(fluid_midi_event_t* evt, void *data, - int size, int dynamic); +FLUIDSYNTH_API int fluid_midi_event_set_type(fluid_midi_event_t *evt, int type); +FLUIDSYNTH_API int fluid_midi_event_get_type(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan); +FLUIDSYNTH_API int fluid_midi_event_get_channel(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_get_key(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_set_key(fluid_midi_event_t *evt, int key); +FLUIDSYNTH_API int fluid_midi_event_get_velocity(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int vel); +FLUIDSYNTH_API int fluid_midi_event_get_control(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_set_control(fluid_midi_event_t *evt, int ctrl); +FLUIDSYNTH_API int fluid_midi_event_get_value(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_set_value(fluid_midi_event_t *evt, int val); +FLUIDSYNTH_API int fluid_midi_event_get_program(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_set_program(fluid_midi_event_t *evt, int val); +FLUIDSYNTH_API int fluid_midi_event_get_pitch(fluid_midi_event_t *evt); +FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val); +FLUIDSYNTH_API int fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, + int size, int dynamic); FLUIDSYNTH_API int fluid_midi_event_set_text(fluid_midi_event_t *evt, - void *data, int size, int dynamic); + void *data, int size, int dynamic); FLUIDSYNTH_API int fluid_midi_event_set_lyrics(fluid_midi_event_t *evt, - void *data, int size, int dynamic); + void *data, int size, int dynamic); /** * MIDI router rule type. @@ -62,14 +62,14 @@ FLUIDSYNTH_API int fluid_midi_event_set_lyrics(fluid_midi_event_t *evt, */ typedef enum { - FLUID_MIDI_ROUTER_RULE_NOTE, /**< MIDI note rule */ - FLUID_MIDI_ROUTER_RULE_CC, /**< MIDI controller rule */ - FLUID_MIDI_ROUTER_RULE_PROG_CHANGE, /**< MIDI program change rule */ - FLUID_MIDI_ROUTER_RULE_PITCH_BEND, /**< MIDI pitch bend rule */ - FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE, /**< MIDI channel pressure rule */ - FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE, /**< MIDI key pressure rule */ + FLUID_MIDI_ROUTER_RULE_NOTE, /**< MIDI note rule */ + FLUID_MIDI_ROUTER_RULE_CC, /**< MIDI controller rule */ + FLUID_MIDI_ROUTER_RULE_PROG_CHANGE, /**< MIDI program change rule */ + FLUID_MIDI_ROUTER_RULE_PITCH_BEND, /**< MIDI pitch bend rule */ + FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE, /**< MIDI channel pressure rule */ + FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE, /**< MIDI key pressure rule */ #ifndef __DOXYGEN__ - FLUID_MIDI_ROUTER_RULE_COUNT /**< @internal Total count of rule types @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time!*/ + FLUID_MIDI_ROUTER_RULE_COUNT /**< @internal Total count of rule types @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time!*/ #endif } fluid_midi_router_rule_type; @@ -85,35 +85,35 @@ typedef enum * to communicate events. * In the not-so-far future... */ -typedef int (*handle_midi_event_func_t)(void* data, fluid_midi_event_t* event); +typedef int (*handle_midi_event_func_t)(void *data, fluid_midi_event_t *event); -FLUIDSYNTH_API fluid_midi_router_t* new_fluid_midi_router(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -FLUIDSYNTH_API void delete_fluid_midi_router(fluid_midi_router_t* handler); -FLUIDSYNTH_API int fluid_midi_router_set_default_rules (fluid_midi_router_t *router); -FLUIDSYNTH_API int fluid_midi_router_clear_rules (fluid_midi_router_t *router); -FLUIDSYNTH_API int fluid_midi_router_add_rule (fluid_midi_router_t *router, - fluid_midi_router_rule_t *rule, int type); -FLUIDSYNTH_API fluid_midi_router_rule_t *new_fluid_midi_router_rule (void); -FLUIDSYNTH_API void delete_fluid_midi_router_rule (fluid_midi_router_rule_t *rule); -FLUIDSYNTH_API void fluid_midi_router_rule_set_chan (fluid_midi_router_rule_t *rule, - int min, int max, float mul, int add); -FLUIDSYNTH_API void fluid_midi_router_rule_set_param1 (fluid_midi_router_rule_t *rule, - int min, int max, float mul, int add); -FLUIDSYNTH_API void fluid_midi_router_rule_set_param2 (fluid_midi_router_rule_t *rule, - int min, int max, float mul, int add); -FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event); -FLUIDSYNTH_API int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event); -FLUIDSYNTH_API int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event); +FLUIDSYNTH_API fluid_midi_router_t *new_fluid_midi_router(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); +FLUIDSYNTH_API void delete_fluid_midi_router(fluid_midi_router_t *handler); +FLUIDSYNTH_API int fluid_midi_router_set_default_rules(fluid_midi_router_t *router); +FLUIDSYNTH_API int fluid_midi_router_clear_rules(fluid_midi_router_t *router); +FLUIDSYNTH_API int fluid_midi_router_add_rule(fluid_midi_router_t *router, + fluid_midi_router_rule_t *rule, int type); +FLUIDSYNTH_API fluid_midi_router_rule_t *new_fluid_midi_router_rule(void); +FLUIDSYNTH_API void delete_fluid_midi_router_rule(fluid_midi_router_rule_t *rule); +FLUIDSYNTH_API void fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t *rule, + int min, int max, float mul, int add); +FLUIDSYNTH_API void fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t *rule, + int min, int max, float mul, int add); +FLUIDSYNTH_API void fluid_midi_router_rule_set_param2(fluid_midi_router_rule_t *rule, + int min, int max, float mul, int add); +FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void *data, fluid_midi_event_t *event); +FLUIDSYNTH_API int fluid_midi_dump_prerouter(void *data, fluid_midi_event_t *event); +FLUIDSYNTH_API int fluid_midi_dump_postrouter(void *data, fluid_midi_event_t *event); -FLUIDSYNTH_API -fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); +FLUIDSYNTH_API +fluid_midi_driver_t *new_fluid_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); -FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t* driver); +FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t *driver); /** @@ -122,32 +122,32 @@ FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t* driver); */ enum fluid_player_status { - FLUID_PLAYER_READY, /**< Player is ready */ - FLUID_PLAYER_PLAYING, /**< Player is currently playing */ - FLUID_PLAYER_DONE /**< Player is finished playing */ + FLUID_PLAYER_READY, /**< Player is ready */ + FLUID_PLAYER_PLAYING, /**< Player is currently playing */ + FLUID_PLAYER_DONE /**< Player is finished playing */ }; -FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth); -FLUIDSYNTH_API void delete_fluid_player(fluid_player_t* player); -FLUIDSYNTH_API int fluid_player_add(fluid_player_t* player, const char *midifile); -FLUIDSYNTH_API int fluid_player_add_mem(fluid_player_t* player, const void *buffer, size_t len); -FLUIDSYNTH_API int fluid_player_play(fluid_player_t* player); -FLUIDSYNTH_API int fluid_player_stop(fluid_player_t* player); -FLUIDSYNTH_API int fluid_player_join(fluid_player_t* player); -FLUIDSYNTH_API int fluid_player_set_loop(fluid_player_t* player, int loop); -FLUIDSYNTH_API int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo); -FLUIDSYNTH_API int fluid_player_set_bpm(fluid_player_t* player, int bpm); -FLUIDSYNTH_API int fluid_player_set_playback_callback(fluid_player_t* player, handle_midi_event_func_t handler, void* handler_data); +FLUIDSYNTH_API fluid_player_t *new_fluid_player(fluid_synth_t *synth); +FLUIDSYNTH_API void delete_fluid_player(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_add(fluid_player_t *player, const char *midifile); +FLUIDSYNTH_API int fluid_player_add_mem(fluid_player_t *player, const void *buffer, size_t len); +FLUIDSYNTH_API int fluid_player_play(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_stop(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_join(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_set_loop(fluid_player_t *player, int loop); +FLUIDSYNTH_API int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo); +FLUIDSYNTH_API int fluid_player_set_bpm(fluid_player_t *player, int bpm); +FLUIDSYNTH_API int fluid_player_set_playback_callback(fluid_player_t *player, handle_midi_event_func_t handler, void *handler_data); -FLUIDSYNTH_API int fluid_player_get_status(fluid_player_t* player); -FLUIDSYNTH_API int fluid_player_get_current_tick(fluid_player_t * player); -FLUIDSYNTH_API int fluid_player_get_total_ticks(fluid_player_t * player); -FLUIDSYNTH_API int fluid_player_get_bpm(fluid_player_t * player); -FLUIDSYNTH_API int fluid_player_get_midi_tempo(fluid_player_t * player); +FLUIDSYNTH_API int fluid_player_get_status(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_get_current_tick(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_get_total_ticks(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_get_bpm(fluid_player_t *player); +FLUIDSYNTH_API int fluid_player_get_midi_tempo(fluid_player_t *player); FLUIDSYNTH_API int fluid_player_seek(fluid_player_t *player, int ticks); /// - + #ifdef __cplusplus } #endif diff --git a/include/fluidsynth/misc.h b/include/fluidsynth/misc.h index 6e0bf653..7a2b457b 100644 --- a/include/fluidsynth/misc.h +++ b/include/fluidsynth/misc.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -60,8 +60,8 @@ extern "C" { #define FLUID_FAILED (-1) -FLUIDSYNTH_API int fluid_is_soundfont (const char *filename); -FLUIDSYNTH_API int fluid_is_midifile (const char *filename); +FLUIDSYNTH_API int fluid_is_soundfont(const char *filename); +FLUIDSYNTH_API int fluid_is_midifile(const char *filename); #ifdef __cplusplus diff --git a/include/fluidsynth/mod.h b/include/fluidsynth/mod.h index 2449fdb1..5ea5f89d 100644 --- a/include/fluidsynth/mod.h +++ b/include/fluidsynth/mod.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -40,18 +40,18 @@ extern "C" { */ enum fluid_mod_flags { - FLUID_MOD_POSITIVE = 0, /**< Mapping function is positive */ - FLUID_MOD_NEGATIVE = 1, /**< Mapping function is negative */ - FLUID_MOD_UNIPOLAR = 0, /**< Mapping function is unipolar */ - FLUID_MOD_BIPOLAR = 2, /**< Mapping function is bipolar */ - FLUID_MOD_LINEAR = 0, /**< Linear mapping function */ - FLUID_MOD_CONCAVE = 4, /**< Concave mapping function */ - FLUID_MOD_CONVEX = 8, /**< Convex mapping function */ - FLUID_MOD_SWITCH = 12, /**< Switch (on/off) mapping function */ - FLUID_MOD_GC = 0, /**< General controller source type (#fluid_mod_src) */ - FLUID_MOD_CC = 16, /**< MIDI CC controller (source will be a MIDI CC number) */ - - FLUID_MOD_SIN = 0x80, /**< Custom non-standard sinus mapping function */ + FLUID_MOD_POSITIVE = 0, /**< Mapping function is positive */ + FLUID_MOD_NEGATIVE = 1, /**< Mapping function is negative */ + FLUID_MOD_UNIPOLAR = 0, /**< Mapping function is unipolar */ + FLUID_MOD_BIPOLAR = 2, /**< Mapping function is bipolar */ + FLUID_MOD_LINEAR = 0, /**< Linear mapping function */ + FLUID_MOD_CONCAVE = 4, /**< Concave mapping function */ + FLUID_MOD_CONVEX = 8, /**< Convex mapping function */ + FLUID_MOD_SWITCH = 12, /**< Switch (on/off) mapping function */ + FLUID_MOD_GC = 0, /**< General controller source type (#fluid_mod_src) */ + FLUID_MOD_CC = 16, /**< MIDI CC controller (source will be a MIDI CC number) */ + + FLUID_MOD_SIN = 0x80, /**< Custom non-standard sinus mapping function */ }; /** @@ -60,36 +60,36 @@ enum fluid_mod_flags */ enum fluid_mod_src { - FLUID_MOD_NONE = 0, /**< No source controller */ - FLUID_MOD_VELOCITY = 2, /**< MIDI note-on velocity */ - FLUID_MOD_KEY = 3, /**< MIDI note-on note number */ - FLUID_MOD_KEYPRESSURE = 10, /**< MIDI key pressure */ - FLUID_MOD_CHANNELPRESSURE = 13, /**< MIDI channel pressure */ - FLUID_MOD_PITCHWHEEL = 14, /**< Pitch wheel */ - FLUID_MOD_PITCHWHEELSENS = 16 /**< Pitch wheel sensitivity */ + FLUID_MOD_NONE = 0, /**< No source controller */ + FLUID_MOD_VELOCITY = 2, /**< MIDI note-on velocity */ + FLUID_MOD_KEY = 3, /**< MIDI note-on note number */ + FLUID_MOD_KEYPRESSURE = 10, /**< MIDI key pressure */ + FLUID_MOD_CHANNELPRESSURE = 13, /**< MIDI channel pressure */ + FLUID_MOD_PITCHWHEEL = 14, /**< Pitch wheel */ + FLUID_MOD_PITCHWHEELSENS = 16 /**< Pitch wheel sensitivity */ }; -FLUIDSYNTH_API fluid_mod_t* new_fluid_mod(void); -FLUIDSYNTH_API void delete_fluid_mod(fluid_mod_t * mod); +FLUIDSYNTH_API fluid_mod_t *new_fluid_mod(void); +FLUIDSYNTH_API void delete_fluid_mod(fluid_mod_t *mod); FLUIDSYNTH_API size_t fluid_mod_sizeof(void); -FLUIDSYNTH_API void fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags); -FLUIDSYNTH_API void fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags); -FLUIDSYNTH_API void fluid_mod_set_dest(fluid_mod_t* mod, int dst); -FLUIDSYNTH_API void fluid_mod_set_amount(fluid_mod_t* mod, double amount); +FLUIDSYNTH_API void fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags); +FLUIDSYNTH_API void fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags); +FLUIDSYNTH_API void fluid_mod_set_dest(fluid_mod_t *mod, int dst); +FLUIDSYNTH_API void fluid_mod_set_amount(fluid_mod_t *mod, double amount); -FLUIDSYNTH_API int fluid_mod_get_source1(const fluid_mod_t* mod); -FLUIDSYNTH_API int fluid_mod_get_flags1(const fluid_mod_t* mod); -FLUIDSYNTH_API int fluid_mod_get_source2(const fluid_mod_t* mod); -FLUIDSYNTH_API int fluid_mod_get_flags2(const fluid_mod_t* mod); -FLUIDSYNTH_API int fluid_mod_get_dest(const fluid_mod_t* mod); -FLUIDSYNTH_API double fluid_mod_get_amount(const fluid_mod_t* mod); +FLUIDSYNTH_API int fluid_mod_get_source1(const fluid_mod_t *mod); +FLUIDSYNTH_API int fluid_mod_get_flags1(const fluid_mod_t *mod); +FLUIDSYNTH_API int fluid_mod_get_source2(const fluid_mod_t *mod); +FLUIDSYNTH_API int fluid_mod_get_flags2(const fluid_mod_t *mod); +FLUIDSYNTH_API int fluid_mod_get_dest(const fluid_mod_t *mod); +FLUIDSYNTH_API double fluid_mod_get_amount(const fluid_mod_t *mod); -FLUIDSYNTH_API int fluid_mod_test_identity(const fluid_mod_t * mod1, const fluid_mod_t * mod2); -FLUIDSYNTH_API int fluid_mod_has_source(const fluid_mod_t * mod, int cc, int ctrl); -FLUIDSYNTH_API int fluid_mod_has_dest(const fluid_mod_t * mod, int gen); +FLUIDSYNTH_API int fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2); +FLUIDSYNTH_API int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl); +FLUIDSYNTH_API int fluid_mod_has_dest(const fluid_mod_t *mod, int gen); -FLUIDSYNTH_API void fluid_mod_clone(fluid_mod_t* mod, const fluid_mod_t* src); +FLUIDSYNTH_API void fluid_mod_clone(fluid_mod_t *mod, const fluid_mod_t *src); #ifdef __cplusplus } diff --git a/include/fluidsynth/ramsfont.h b/include/fluidsynth/ramsfont.h index 7d3d1eb9..52faef8e 100644 --- a/include/fluidsynth/ramsfont.h +++ b/include/fluidsynth/ramsfont.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -39,23 +39,23 @@ extern "C" { * ones are permitted. This may be extensible in the future. */ -FLUIDSYNTH_API fluid_sfont_t* fluid_ramsfont_create_sfont(void); -FLUIDSYNTH_API int fluid_ramsfont_set_name(fluid_ramsfont_t* sfont, const char *name); -FLUIDSYNTH_API -int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont, - int bank, int num, fluid_sample_t* sample, - int lokey, int hikey); +FLUIDSYNTH_API fluid_sfont_t *fluid_ramsfont_create_sfont(void); +FLUIDSYNTH_API int fluid_ramsfont_set_name(fluid_ramsfont_t *sfont, const char *name); FLUIDSYNTH_API -int fluid_ramsfont_remove_izone(fluid_ramsfont_t* sfont, - int bank, int num, fluid_sample_t* sample); +int fluid_ramsfont_add_izone(fluid_ramsfont_t *sfont, + int bank, int num, fluid_sample_t *sample, + int lokey, int hikey); FLUIDSYNTH_API -int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont, - int bank, int num, fluid_sample_t* sample, - int gen_type, float value); +int fluid_ramsfont_remove_izone(fluid_ramsfont_t *sfont, + int bank, int num, fluid_sample_t *sample); FLUIDSYNTH_API -int fluid_ramsfont_izone_set_loop(fluid_ramsfont_t* sfont, - int bank, int num, fluid_sample_t* sample, - int on, float loopstart, float loopend); +int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t *sfont, + int bank, int num, fluid_sample_t *sample, + int gen_type, float value); +FLUIDSYNTH_API +int fluid_ramsfont_izone_set_loop(fluid_ramsfont_t *sfont, + int bank, int num, fluid_sample_t *sample, + int on, float loopstart, float loopend); diff --git a/include/fluidsynth/seq.h b/include/fluidsynth/seq.h index 69056fc9..c0e6b555 100644 --- a/include/fluidsynth/seq.h +++ b/include/fluidsynth/seq.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -37,39 +37,39 @@ extern "C" { * @param seq The sequencer instance * @param data User defined data registered with the client */ -typedef void (*fluid_event_callback_t)(unsigned int time, fluid_event_t* event, - fluid_sequencer_t* seq, void* data); +typedef void (*fluid_event_callback_t)(unsigned int time, fluid_event_t *event, + fluid_sequencer_t *seq, void *data); -FLUIDSYNTH_API fluid_sequencer_t* new_fluid_sequencer(void); -FLUIDSYNTH_API fluid_sequencer_t* new_fluid_sequencer2(int use_system_timer); -FLUIDSYNTH_API void delete_fluid_sequencer(fluid_sequencer_t* seq); -FLUIDSYNTH_API int fluid_sequencer_get_use_system_timer(fluid_sequencer_t* seq); -FLUIDSYNTH_API -fluid_seq_id_t fluid_sequencer_register_client(fluid_sequencer_t* seq, const char *name, - fluid_event_callback_t callback, void* data); -FLUIDSYNTH_API void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, fluid_seq_id_t id); -FLUIDSYNTH_API int fluid_sequencer_count_clients(fluid_sequencer_t* seq); -FLUIDSYNTH_API fluid_seq_id_t fluid_sequencer_get_client_id(fluid_sequencer_t* seq, int index); -FLUIDSYNTH_API char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, fluid_seq_id_t id); -FLUIDSYNTH_API int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, fluid_seq_id_t id); -FLUIDSYNTH_API void fluid_sequencer_process(fluid_sequencer_t* seq, unsigned int msec); -FLUIDSYNTH_API void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt); -FLUIDSYNTH_API -int fluid_sequencer_send_at(fluid_sequencer_t* seq, fluid_event_t* evt, - unsigned int time, int absolute); -FLUIDSYNTH_API -void fluid_sequencer_remove_events(fluid_sequencer_t* seq, fluid_seq_id_t source, fluid_seq_id_t dest, int type); -FLUIDSYNTH_API unsigned int fluid_sequencer_get_tick(fluid_sequencer_t* seq); -FLUIDSYNTH_API void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale); -FLUIDSYNTH_API double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq); +FLUIDSYNTH_API fluid_sequencer_t *new_fluid_sequencer(void); +FLUIDSYNTH_API fluid_sequencer_t *new_fluid_sequencer2(int use_system_timer); +FLUIDSYNTH_API void delete_fluid_sequencer(fluid_sequencer_t *seq); +FLUIDSYNTH_API int fluid_sequencer_get_use_system_timer(fluid_sequencer_t *seq); +FLUIDSYNTH_API +fluid_seq_id_t fluid_sequencer_register_client(fluid_sequencer_t *seq, const char *name, + fluid_event_callback_t callback, void *data); +FLUIDSYNTH_API void fluid_sequencer_unregister_client(fluid_sequencer_t *seq, fluid_seq_id_t id); +FLUIDSYNTH_API int fluid_sequencer_count_clients(fluid_sequencer_t *seq); +FLUIDSYNTH_API fluid_seq_id_t fluid_sequencer_get_client_id(fluid_sequencer_t *seq, int index); +FLUIDSYNTH_API char *fluid_sequencer_get_client_name(fluid_sequencer_t *seq, fluid_seq_id_t id); +FLUIDSYNTH_API int fluid_sequencer_client_is_dest(fluid_sequencer_t *seq, fluid_seq_id_t id); +FLUIDSYNTH_API void fluid_sequencer_process(fluid_sequencer_t *seq, unsigned int msec); +FLUIDSYNTH_API void fluid_sequencer_send_now(fluid_sequencer_t *seq, fluid_event_t *evt); +FLUIDSYNTH_API +int fluid_sequencer_send_at(fluid_sequencer_t *seq, fluid_event_t *evt, + unsigned int time, int absolute); +FLUIDSYNTH_API +void fluid_sequencer_remove_events(fluid_sequencer_t *seq, fluid_seq_id_t source, fluid_seq_id_t dest, int type); +FLUIDSYNTH_API unsigned int fluid_sequencer_get_tick(fluid_sequencer_t *seq); +FLUIDSYNTH_API void fluid_sequencer_set_time_scale(fluid_sequencer_t *seq, double scale); +FLUIDSYNTH_API double fluid_sequencer_get_time_scale(fluid_sequencer_t *seq); // Compile in internal traceing functions #define FLUID_SEQ_WITH_TRACE 0 #if FLUID_SEQ_WITH_TRACE -FLUIDSYNTH_API char * fluid_seq_gettrace(fluid_sequencer_t* seq); -FLUIDSYNTH_API void fluid_seq_cleartrace(fluid_sequencer_t* seq); +FLUIDSYNTH_API char *fluid_seq_gettrace(fluid_sequencer_t *seq); +FLUIDSYNTH_API void fluid_seq_cleartrace(fluid_sequencer_t *seq); #endif #ifdef __cplusplus diff --git a/include/fluidsynth/seqbind.h b/include/fluidsynth/seqbind.h index 1fa707c7..63859566 100644 --- a/include/fluidsynth/seqbind.h +++ b/include/fluidsynth/seqbind.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -32,10 +32,10 @@ extern "C" { * @brief Functions for binding sequencer objects to other subsystems. */ -FLUIDSYNTH_API -fluid_seq_id_t fluid_sequencer_register_fluidsynth(fluid_sequencer_t* seq, fluid_synth_t* synth); +FLUIDSYNTH_API +fluid_seq_id_t fluid_sequencer_register_fluidsynth(fluid_sequencer_t *seq, fluid_synth_t *synth); FLUIDSYNTH_API int -fluid_sequencer_add_midi_event_to_buffer(void* data, fluid_midi_event_t* event); +fluid_sequencer_add_midi_event_to_buffer(void *data, fluid_midi_event_t *event); #ifdef __cplusplus diff --git a/include/fluidsynth/settings.h b/include/fluidsynth/settings.h index 0784d993..aa7f0831 100644 --- a/include/fluidsynth/settings.h +++ b/include/fluidsynth/settings.h @@ -88,67 +88,68 @@ extern "C" { * set of values. The type of each setting can be retrieved using the * function fluid_settings_get_type() */ -enum fluid_types_enum { - FLUID_NO_TYPE = -1, /**< Undefined type */ - FLUID_NUM_TYPE, /**< Numeric (double) */ - FLUID_INT_TYPE, /**< Integer */ - FLUID_STR_TYPE, /**< String */ - FLUID_SET_TYPE /**< Set of values */ +enum fluid_types_enum +{ + FLUID_NO_TYPE = -1, /**< Undefined type */ + FLUID_NUM_TYPE, /**< Numeric (double) */ + FLUID_INT_TYPE, /**< Integer */ + FLUID_STR_TYPE, /**< String */ + FLUID_SET_TYPE /**< Set of values */ }; -FLUIDSYNTH_API fluid_settings_t* new_fluid_settings(void); -FLUIDSYNTH_API void delete_fluid_settings(fluid_settings_t* settings); +FLUIDSYNTH_API fluid_settings_t *new_fluid_settings(void); +FLUIDSYNTH_API void delete_fluid_settings(fluid_settings_t *settings); FLUIDSYNTH_API -int fluid_settings_get_type(fluid_settings_t* settings, const char *name); +int fluid_settings_get_type(fluid_settings_t *settings, const char *name); FLUIDSYNTH_API -int fluid_settings_get_hints(fluid_settings_t* settings, const char *name, int* val); +int fluid_settings_get_hints(fluid_settings_t *settings, const char *name, int *val); FLUIDSYNTH_API -int fluid_settings_is_realtime(fluid_settings_t* settings, const char *name); +int fluid_settings_is_realtime(fluid_settings_t *settings, const char *name); FLUIDSYNTH_API -int fluid_settings_setstr(fluid_settings_t* settings, const char *name, const char *str); +int fluid_settings_setstr(fluid_settings_t *settings, const char *name, const char *str); FLUIDSYNTH_API -int fluid_settings_copystr(fluid_settings_t* settings, const char *name, char *str, int len); +int fluid_settings_copystr(fluid_settings_t *settings, const char *name, char *str, int len); FLUIDSYNTH_API -int fluid_settings_dupstr(fluid_settings_t* settings, const char *name, char** str); +int fluid_settings_dupstr(fluid_settings_t *settings, const char *name, char **str); FLUIDSYNTH_API -int fluid_settings_getstr_default(fluid_settings_t* settings, const char *name, char** def); +int fluid_settings_getstr_default(fluid_settings_t *settings, const char *name, char **def); FLUIDSYNTH_API -int fluid_settings_str_equal(fluid_settings_t* settings, const char *name, const char *value); +int fluid_settings_str_equal(fluid_settings_t *settings, const char *name, const char *value); FLUIDSYNTH_API -int fluid_settings_setnum(fluid_settings_t* settings, const char *name, double val); +int fluid_settings_setnum(fluid_settings_t *settings, const char *name, double val); FLUIDSYNTH_API -int fluid_settings_getnum(fluid_settings_t* settings, const char *name, double* val); +int fluid_settings_getnum(fluid_settings_t *settings, const char *name, double *val); FLUIDSYNTH_API -int fluid_settings_getnum_default(fluid_settings_t* settings, const char *name, double* val); +int fluid_settings_getnum_default(fluid_settings_t *settings, const char *name, double *val); FLUIDSYNTH_API -int fluid_settings_getnum_range(fluid_settings_t* settings, const char *name, - double* min, double* max); +int fluid_settings_getnum_range(fluid_settings_t *settings, const char *name, + double *min, double *max); FLUIDSYNTH_API -int fluid_settings_setint(fluid_settings_t* settings, const char *name, int val); +int fluid_settings_setint(fluid_settings_t *settings, const char *name, int val); FLUIDSYNTH_API -int fluid_settings_getint(fluid_settings_t* settings, const char *name, int* val); +int fluid_settings_getint(fluid_settings_t *settings, const char *name, int *val); FLUIDSYNTH_API -int fluid_settings_getint_default(fluid_settings_t* settings, const char *name, int* val); +int fluid_settings_getint_default(fluid_settings_t *settings, const char *name, int *val); FLUIDSYNTH_API -int fluid_settings_getint_range(fluid_settings_t* settings, const char *name, - int* min, int* max); +int fluid_settings_getint_range(fluid_settings_t *settings, const char *name, + int *min, int *max); /** * Callback function type used with fluid_settings_foreach_option() @@ -159,14 +160,14 @@ int fluid_settings_getint_range(fluid_settings_t* settings, const char *name, typedef void (*fluid_settings_foreach_option_t)(void *data, const char *name, const char *option); FLUIDSYNTH_API -void fluid_settings_foreach_option(fluid_settings_t* settings, - const char* name, void* data, - fluid_settings_foreach_option_t func); +void fluid_settings_foreach_option(fluid_settings_t *settings, + const char *name, void *data, + fluid_settings_foreach_option_t func); FLUIDSYNTH_API -int fluid_settings_option_count (fluid_settings_t* settings, const char* name); -FLUIDSYNTH_API char *fluid_settings_option_concat (fluid_settings_t* settings, - const char* name, - const char* separator); +int fluid_settings_option_count(fluid_settings_t *settings, const char *name); +FLUIDSYNTH_API char *fluid_settings_option_concat(fluid_settings_t *settings, + const char *name, + const char *separator); /** * Callback function type used with fluid_settings_foreach() @@ -177,8 +178,8 @@ FLUIDSYNTH_API char *fluid_settings_option_concat (fluid_settings_t* settings, typedef void (*fluid_settings_foreach_t)(void *data, const char *name, int type); FLUIDSYNTH_API -void fluid_settings_foreach(fluid_settings_t* settings, void* data, - fluid_settings_foreach_t func); +void fluid_settings_foreach(fluid_settings_t *settings, void *data, + fluid_settings_foreach_t func); #ifdef __cplusplus } diff --git a/include/fluidsynth/sfont.h b/include/fluidsynth/sfont.h index 658ef8fd..55413a9e 100644 --- a/include/fluidsynth/sfont.h +++ b/include/fluidsynth/sfont.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -38,7 +38,7 @@ extern "C" { * To add a new SoundFont loader to the synthesizer, call * fluid_synth_add_sfloader() and pass a pointer to an * #fluid_sfloader_t instance created by new_fluid_sfloader(). - * On creation, you must specify a callback function \p load + * On creation, you must specify a callback function \p load * that will be called for every file attempting to load it and * if successful returns a #fluid_sfont_t instance, or NULL if it fails. * @@ -51,7 +51,7 @@ extern "C" { * The #fluid_preset_t instance contains some functions to obtain * information from the preset (name, bank, number). The most * important callback is the noteon function. The noteon function - * is called by fluidsynth internally and + * is called by fluidsynth internally and * should call fluid_synth_alloc_voice() for every sample that has * to be played. fluid_synth_alloc_voice() expects a pointer to a * #fluid_sample_t instance and returns a pointer to the opaque @@ -64,10 +64,11 @@ extern "C" { /** * Some notification enums for presets and samples. */ -enum { - FLUID_PRESET_SELECTED, /**< Preset selected notify */ - FLUID_PRESET_UNSELECTED, /**< Preset unselected notify */ - FLUID_SAMPLE_DONE /**< Sample no longer needed notify */ +enum +{ + FLUID_PRESET_SELECTED, /**< Preset selected notify */ + FLUID_PRESET_UNSELECTED, /**< Preset unselected notify */ + FLUID_SAMPLE_DONE /**< Sample no longer needed notify */ }; /** @@ -91,7 +92,7 @@ enum fluid_sample_type * @param filename File name or other string identifier * @return The loaded instrument file (SoundFont) or NULL if an error occured. */ -typedef fluid_sfont_t* (*fluid_sfloader_load_t)(fluid_sfloader_t* loader, const char* filename); +typedef fluid_sfont_t *(*fluid_sfloader_load_t)(fluid_sfloader_t *loader, const char *filename); /** * The free method should free the memory allocated for a fluid_sfloader_t instance in @@ -100,13 +101,13 @@ typedef fluid_sfont_t* (*fluid_sfloader_load_t)(fluid_sfloader_t* loader, const * needs to be freed, setting this to delete_fluid_sfloader() is sufficient. * @param loader SoundFont loader */ -typedef void (*fluid_sfloader_free_t)(fluid_sfloader_t* loader); +typedef void (*fluid_sfloader_free_t)(fluid_sfloader_t *loader); -FLUIDSYNTH_API fluid_sfloader_t* new_fluid_sfloader(fluid_sfloader_load_t load, fluid_sfloader_free_t free); -FLUIDSYNTH_API void delete_fluid_sfloader(fluid_sfloader_t* loader); +FLUIDSYNTH_API fluid_sfloader_t *new_fluid_sfloader(fluid_sfloader_load_t load, fluid_sfloader_free_t free); +FLUIDSYNTH_API void delete_fluid_sfloader(fluid_sfloader_t *loader); -FLUIDSYNTH_API fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings); +FLUIDSYNTH_API fluid_sfloader_t *new_fluid_defsfloader(fluid_settings_t *settings); /** * Opens the file or memory indicated by \c filename in binary read mode. @@ -114,44 +115,44 @@ FLUIDSYNTH_API fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* setting * * @return returns a file handle on success, NULL otherwise */ -typedef void * (* fluid_sfloader_callback_open_t )(const char * filename); +typedef void *(* fluid_sfloader_callback_open_t)(const char *filename); /** * Reads \c count bytes to the specified buffer \c buf. - * + * * @return returns #FLUID_OK if exactly \c count bytes were successfully read, else returns #FLUID_FAILED and leaves \a buf unmodified. */ -typedef int (* fluid_sfloader_callback_read_t )(void *buf, int count, void * handle); +typedef int (* fluid_sfloader_callback_read_t)(void *buf, int count, void *handle); /** * Same purpose and behaviour as fseek. - * + * * @param origin either \c SEEK_SET, \c SEEK_CUR or \c SEEK_END - * + * * @return returns #FLUID_OK if the seek was successfully performed while not seeking beyond a buffer or file, #FLUID_FAILED otherwise */ -typedef int (* fluid_sfloader_callback_seek_t )(void * handle, long offset, int origin); +typedef int (* fluid_sfloader_callback_seek_t)(void *handle, long offset, int origin); -/** +/** * Closes the handle returned by #fluid_sfloader_callback_open_t and frees used ressources. - * + * * @return returns #FLUID_OK on success, #FLUID_FAILED on error */ -typedef int (* fluid_sfloader_callback_close_t )(void * handle); +typedef int (* fluid_sfloader_callback_close_t)(void *handle); /** @return returns current file offset or #FLUID_FAILED on error */ -typedef long (* fluid_sfloader_callback_tell_t )(void * handle); +typedef long (* fluid_sfloader_callback_tell_t)(void *handle); -FLUIDSYNTH_API int fluid_sfloader_set_callbacks(fluid_sfloader_t* loader, - fluid_sfloader_callback_open_t open, - fluid_sfloader_callback_read_t read, - fluid_sfloader_callback_seek_t seek, - fluid_sfloader_callback_tell_t tell, - fluid_sfloader_callback_close_t close); +FLUIDSYNTH_API int fluid_sfloader_set_callbacks(fluid_sfloader_t *loader, + fluid_sfloader_callback_open_t open, + fluid_sfloader_callback_read_t read, + fluid_sfloader_callback_seek_t seek, + fluid_sfloader_callback_tell_t tell, + fluid_sfloader_callback_close_t close); -FLUIDSYNTH_API int fluid_sfloader_set_data(fluid_sfloader_t* loader, void* data); -FLUIDSYNTH_API void* fluid_sfloader_get_data(fluid_sfloader_t* loader); +FLUIDSYNTH_API int fluid_sfloader_set_data(fluid_sfloader_t *loader, void *data); +FLUIDSYNTH_API void *fluid_sfloader_get_data(fluid_sfloader_t *loader); @@ -160,8 +161,8 @@ FLUIDSYNTH_API void* fluid_sfloader_get_data(fluid_sfloader_t* loader); * @param sfont Virtual SoundFont * @return The name of the virtual SoundFont. */ -typedef const char* (*fluid_sfont_get_name_t)(fluid_sfont_t* sfont); - +typedef const char *(*fluid_sfont_get_name_t)(fluid_sfont_t *sfont); + /** * Get a virtual SoundFont preset by bank and program numbers. * @param sfont Virtual SoundFont @@ -170,7 +171,7 @@ typedef const char* (*fluid_sfont_get_name_t)(fluid_sfont_t* sfont); * @return Should return an allocated virtual preset or NULL if it could not * be found. */ -typedef fluid_preset_t* (*fluid_sfont_get_preset_t)(fluid_sfont_t* sfont, int bank, int prenum); +typedef fluid_preset_t *(*fluid_sfont_get_preset_t)(fluid_sfont_t *sfont, int bank, int prenum); /** * Start virtual SoundFont preset iteration method. @@ -178,7 +179,7 @@ typedef fluid_preset_t* (*fluid_sfont_get_preset_t)(fluid_sfont_t* sfont, int ba * * Starts/re-starts virtual preset iteration in a SoundFont. */ -typedef void (*fluid_sfont_iteration_start_t)(fluid_sfont_t* sfont); +typedef void (*fluid_sfont_iteration_start_t)(fluid_sfont_t *sfont); /** * Virtual SoundFont preset iteration function. @@ -190,7 +191,7 @@ typedef void (*fluid_sfont_iteration_start_t)(fluid_sfont_t* sfont); * and advance the internal iteration state to the next preset for subsequent * calls. */ -typedef fluid_preset_t* (*fluid_sfont_iteration_next_t)(fluid_sfont_t* sfont); +typedef fluid_preset_t *(*fluid_sfont_iteration_next_t)(fluid_sfont_t *sfont); /** * Method to free a virtual SoundFont bank. Any custom user provided cleanup function must ultimately call @@ -201,25 +202,25 @@ typedef fluid_preset_t* (*fluid_sfont_iteration_next_t)(fluid_sfont_t* sfont); * if some of the samples could not be freed because they are still in use, * in which case the free will be tried again later, until success. */ -typedef int (*fluid_sfont_free_t)(fluid_sfont_t* sfont); +typedef int (*fluid_sfont_free_t)(fluid_sfont_t *sfont); -FLUIDSYNTH_API fluid_sfont_t* new_fluid_sfont(fluid_sfont_get_name_t get_name, - fluid_sfont_get_preset_t get_preset, - fluid_sfont_iteration_start_t iter_start, - fluid_sfont_iteration_next_t iter_next, - fluid_sfont_free_t free); +FLUIDSYNTH_API fluid_sfont_t *new_fluid_sfont(fluid_sfont_get_name_t get_name, + fluid_sfont_get_preset_t get_preset, + fluid_sfont_iteration_start_t iter_start, + fluid_sfont_iteration_next_t iter_next, + fluid_sfont_free_t free); -FLUIDSYNTH_API int delete_fluid_sfont(fluid_sfont_t* sfont); +FLUIDSYNTH_API int delete_fluid_sfont(fluid_sfont_t *sfont); -FLUIDSYNTH_API int fluid_sfont_set_data(fluid_sfont_t* sfont, void* data); -FLUIDSYNTH_API void* fluid_sfont_get_data(fluid_sfont_t* sfont); +FLUIDSYNTH_API int fluid_sfont_set_data(fluid_sfont_t *sfont, void *data); +FLUIDSYNTH_API void *fluid_sfont_get_data(fluid_sfont_t *sfont); -FLUIDSYNTH_API int fluid_sfont_get_id(fluid_sfont_t* sfont); -FLUIDSYNTH_API const char* fluid_sfont_get_name(fluid_sfont_t* sfont); -FLUIDSYNTH_API fluid_preset_t* fluid_sfont_get_preset(fluid_sfont_t* sfont, int bank, int prenum); -FLUIDSYNTH_API void fluid_sfont_iteration_start(fluid_sfont_t* sfont); -FLUIDSYNTH_API fluid_preset_t* fluid_sfont_iteration_next(fluid_sfont_t* sfont); +FLUIDSYNTH_API int fluid_sfont_get_id(fluid_sfont_t *sfont); +FLUIDSYNTH_API const char *fluid_sfont_get_name(fluid_sfont_t *sfont); +FLUIDSYNTH_API fluid_preset_t *fluid_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum); +FLUIDSYNTH_API void fluid_sfont_iteration_start(fluid_sfont_t *sfont); +FLUIDSYNTH_API fluid_preset_t *fluid_sfont_iteration_next(fluid_sfont_t *sfont); /** * Method to get a virtual SoundFont preset name. @@ -228,21 +229,21 @@ FLUIDSYNTH_API fluid_preset_t* fluid_sfont_iteration_next(fluid_sfont_t* sfont); * valid for the duration of the virtual preset (or the duration of the * SoundFont, in the case of preset iteration). */ -typedef const char* (*fluid_preset_get_name_t)(fluid_preset_t* preset); +typedef const char *(*fluid_preset_get_name_t)(fluid_preset_t *preset); /** * Method to get a virtual SoundFont preset MIDI bank number. * @param preset Virtual SoundFont preset * @param return The bank number of the preset */ -typedef int (*fluid_preset_get_banknum_t)(fluid_preset_t* preset); +typedef int (*fluid_preset_get_banknum_t)(fluid_preset_t *preset); /** * Method to get a virtual SoundFont preset MIDI program number. * @param preset Virtual SoundFont preset * @param return The program number of the preset */ -typedef int (*fluid_preset_get_num_t)(fluid_preset_t* preset); +typedef int (*fluid_preset_get_num_t)(fluid_preset_t *preset); /** * Method to handle a noteon event (synthesize the instrument). @@ -266,7 +267,7 @@ typedef int (*fluid_preset_get_num_t)(fluid_preset_t* preset); * start playing the synthesis voice. Starting with FluidSynth 1.1.0 all voices * created will be started at the same time. */ -typedef int (*fluid_preset_noteon_t)(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel); +typedef int (*fluid_preset_noteon_t)(fluid_preset_t *preset, fluid_synth_t *synth, int chan, int key, int vel); /** * Method to free a virtual SoundFont preset. Any custom user provided cleanup function must ultimately call @@ -275,38 +276,38 @@ typedef int (*fluid_preset_noteon_t)(fluid_preset_t* preset, fluid_synth_t* synt * @param preset Virtual SoundFont preset * @return Should return 0 */ -typedef void (*fluid_preset_free_t)(fluid_preset_t* preset); +typedef void (*fluid_preset_free_t)(fluid_preset_t *preset); -FLUIDSYNTH_API fluid_preset_t* new_fluid_preset(fluid_sfont_t* parent_sfont, - fluid_preset_get_name_t get_name, - fluid_preset_get_banknum_t get_bank, - fluid_preset_get_num_t get_num, - fluid_preset_noteon_t noteon, - fluid_preset_free_t free); -FLUIDSYNTH_API void delete_fluid_preset(fluid_preset_t* preset); +FLUIDSYNTH_API fluid_preset_t *new_fluid_preset(fluid_sfont_t *parent_sfont, + fluid_preset_get_name_t get_name, + fluid_preset_get_banknum_t get_bank, + fluid_preset_get_num_t get_num, + fluid_preset_noteon_t noteon, + fluid_preset_free_t free); +FLUIDSYNTH_API void delete_fluid_preset(fluid_preset_t *preset); -FLUIDSYNTH_API int fluid_preset_set_data(fluid_preset_t* preset, void* data); -FLUIDSYNTH_API void* fluid_preset_get_data(fluid_preset_t* preset); +FLUIDSYNTH_API int fluid_preset_set_data(fluid_preset_t *preset, void *data); +FLUIDSYNTH_API void *fluid_preset_get_data(fluid_preset_t *preset); -FLUIDSYNTH_API const char* fluid_preset_get_name(fluid_preset_t* preset); -FLUIDSYNTH_API int fluid_preset_get_banknum(fluid_preset_t* preset); -FLUIDSYNTH_API int fluid_preset_get_num(fluid_preset_t* preset); -FLUIDSYNTH_API fluid_sfont_t* fluid_preset_get_sfont(fluid_preset_t* preset); +FLUIDSYNTH_API const char *fluid_preset_get_name(fluid_preset_t *preset); +FLUIDSYNTH_API int fluid_preset_get_banknum(fluid_preset_t *preset); +FLUIDSYNTH_API int fluid_preset_get_num(fluid_preset_t *preset); +FLUIDSYNTH_API fluid_sfont_t *fluid_preset_get_sfont(fluid_preset_t *preset); -FLUIDSYNTH_API fluid_sample_t* new_fluid_sample(void); -FLUIDSYNTH_API void delete_fluid_sample(fluid_sample_t* sample); +FLUIDSYNTH_API fluid_sample_t *new_fluid_sample(void); +FLUIDSYNTH_API void delete_fluid_sample(fluid_sample_t *sample); FLUIDSYNTH_API size_t fluid_sample_sizeof(void); -FLUIDSYNTH_API int fluid_sample_set_name(fluid_sample_t* sample, const char *name); -FLUIDSYNTH_API int fluid_sample_set_sound_data (fluid_sample_t* sample, - short *data, - char *data24, - unsigned int nbframes, - unsigned int sample_rate, - short copy_data); +FLUIDSYNTH_API int fluid_sample_set_name(fluid_sample_t *sample, const char *name); +FLUIDSYNTH_API int fluid_sample_set_sound_data(fluid_sample_t *sample, + short *data, + char *data24, + unsigned int nbframes, + unsigned int sample_rate, + short copy_data); -FLUIDSYNTH_API int fluid_sample_set_loop(fluid_sample_t* sample, unsigned int loop_start, unsigned int loop_end); -FLUIDSYNTH_API int fluid_sample_set_pitch(fluid_sample_t* sample, int root_key, int fine_tune); +FLUIDSYNTH_API int fluid_sample_set_loop(fluid_sample_t *sample, unsigned int loop_start, unsigned int loop_end); +FLUIDSYNTH_API int fluid_sample_set_pitch(fluid_sample_t *sample, int root_key, int fine_tune); #ifdef __cplusplus } diff --git a/include/fluidsynth/shell.h b/include/fluidsynth/shell.h index c20b2e25..f9c17e0f 100644 --- a/include/fluidsynth/shell.h +++ b/include/fluidsynth/shell.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -39,55 +39,55 @@ extern "C" { FLUIDSYNTH_API fluid_istream_t fluid_get_stdin(void); FLUIDSYNTH_API fluid_ostream_t fluid_get_stdout(void); -FLUIDSYNTH_API char* fluid_get_userconf(char* buf, int len); -FLUIDSYNTH_API char* fluid_get_sysconf(char* buf, int len); +FLUIDSYNTH_API char *fluid_get_userconf(char *buf, int len); +FLUIDSYNTH_API char *fluid_get_sysconf(char *buf, int len); /* The command handler */ -FLUIDSYNTH_API -fluid_cmd_handler_t* new_fluid_cmd_handler(fluid_synth_t* synth, fluid_midi_router_t* router); +FLUIDSYNTH_API +fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_router_t *router); -FLUIDSYNTH_API -void delete_fluid_cmd_handler(fluid_cmd_handler_t* handler); +FLUIDSYNTH_API +void delete_fluid_cmd_handler(fluid_cmd_handler_t *handler); -FLUIDSYNTH_API -void fluid_cmd_handler_set_synth(fluid_cmd_handler_t* handler, fluid_synth_t* synth); +FLUIDSYNTH_API +void fluid_cmd_handler_set_synth(fluid_cmd_handler_t *handler, fluid_synth_t *synth); /* Command function */ -FLUIDSYNTH_API -int fluid_command(fluid_cmd_handler_t* handler, const char *cmd, fluid_ostream_t out); +FLUIDSYNTH_API +int fluid_command(fluid_cmd_handler_t *handler, const char *cmd, fluid_ostream_t out); -FLUIDSYNTH_API -int fluid_source(fluid_cmd_handler_t* handler, const char *filename); +FLUIDSYNTH_API +int fluid_source(fluid_cmd_handler_t *handler, const char *filename); -FLUIDSYNTH_API -void fluid_usershell(fluid_settings_t* settings, fluid_cmd_handler_t* handler); +FLUIDSYNTH_API +void fluid_usershell(fluid_settings_t *settings, fluid_cmd_handler_t *handler); /* Shell */ -FLUIDSYNTH_API -fluid_shell_t* new_fluid_shell(fluid_settings_t* settings, fluid_cmd_handler_t* handler, - fluid_istream_t in, fluid_ostream_t out, int thread); +FLUIDSYNTH_API +fluid_shell_t *new_fluid_shell(fluid_settings_t *settings, fluid_cmd_handler_t *handler, + fluid_istream_t in, fluid_ostream_t out, int thread); -FLUIDSYNTH_API void delete_fluid_shell(fluid_shell_t* shell); +FLUIDSYNTH_API void delete_fluid_shell(fluid_shell_t *shell); /* TCP/IP server */ -FLUIDSYNTH_API -fluid_server_t* new_fluid_server(fluid_settings_t* settings, - fluid_synth_t* synth, fluid_midi_router_t* router); +FLUIDSYNTH_API +fluid_server_t *new_fluid_server(fluid_settings_t *settings, + fluid_synth_t *synth, fluid_midi_router_t *router); -FLUIDSYNTH_API void delete_fluid_server(fluid_server_t* server); +FLUIDSYNTH_API void delete_fluid_server(fluid_server_t *server); -FLUIDSYNTH_API int fluid_server_join(fluid_server_t* server); +FLUIDSYNTH_API int fluid_server_join(fluid_server_t *server); #ifdef __cplusplus diff --git a/include/fluidsynth/synth.h b/include/fluidsynth/synth.h index 72940d42..9fc131c7 100644 --- a/include/fluidsynth/synth.h +++ b/include/fluidsynth/synth.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -30,112 +30,112 @@ extern "C" { /** * @file synth.h * @brief Embeddable SoundFont synthesizer - * + * * You create a new synthesizer with new_fluid_synth() and you destroy * if with delete_fluid_synth(). Use the settings structure to specify - * the synthesizer characteristics. + * the synthesizer characteristics. * * You have to load a SoundFont in order to hear any sound. For that * you use the fluid_synth_sfload() function. * * You can use the audio driver functions described below to open * the audio device and create a background audio thread. - * + * * The API for sending MIDI events is probably what you expect: * fluid_synth_noteon(), fluid_synth_noteoff(), ... */ -FLUIDSYNTH_API fluid_synth_t* new_fluid_synth(fluid_settings_t* settings); -FLUIDSYNTH_API void delete_fluid_synth(fluid_synth_t* synth); -FLUIDSYNTH_API fluid_settings_t* fluid_synth_get_settings(fluid_synth_t* synth); +FLUIDSYNTH_API fluid_synth_t *new_fluid_synth(fluid_settings_t *settings); +FLUIDSYNTH_API void delete_fluid_synth(fluid_synth_t *synth); +FLUIDSYNTH_API fluid_settings_t *fluid_synth_get_settings(fluid_synth_t *synth); /* MIDI channel messages */ -FLUIDSYNTH_API int fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel); -FLUIDSYNTH_API int fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key); -FLUIDSYNTH_API int fluid_synth_cc(fluid_synth_t* synth, int chan, int ctrl, int val); -FLUIDSYNTH_API int fluid_synth_get_cc(fluid_synth_t* synth, int chan, int ctrl, int* pval); +FLUIDSYNTH_API int fluid_synth_noteon(fluid_synth_t *synth, int chan, int key, int vel); +FLUIDSYNTH_API int fluid_synth_noteoff(fluid_synth_t *synth, int chan, int key); +FLUIDSYNTH_API int fluid_synth_cc(fluid_synth_t *synth, int chan, int ctrl, int val); +FLUIDSYNTH_API int fluid_synth_get_cc(fluid_synth_t *synth, int chan, int ctrl, int *pval); FLUIDSYNTH_API int fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len, char *response, int *response_len, int *handled, int dryrun); -FLUIDSYNTH_API int fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val); -FLUIDSYNTH_API int fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend); -FLUIDSYNTH_API int fluid_synth_pitch_wheel_sens(fluid_synth_t* synth, int chan, int val); -FLUIDSYNTH_API int fluid_synth_get_pitch_wheel_sens(fluid_synth_t* synth, int chan, int* pval); -FLUIDSYNTH_API int fluid_synth_program_change(fluid_synth_t* synth, int chan, int program); -FLUIDSYNTH_API int fluid_synth_channel_pressure(fluid_synth_t* synth, int chan, int val); -FLUIDSYNTH_API int fluid_synth_key_pressure(fluid_synth_t* synth, int chan, int key, int val); -FLUIDSYNTH_API int fluid_synth_bank_select(fluid_synth_t* synth, int chan, int bank); -FLUIDSYNTH_API int fluid_synth_sfont_select(fluid_synth_t* synth, int chan, int sfont_id); +FLUIDSYNTH_API int fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val); +FLUIDSYNTH_API int fluid_synth_get_pitch_bend(fluid_synth_t *synth, int chan, int *ppitch_bend); +FLUIDSYNTH_API int fluid_synth_pitch_wheel_sens(fluid_synth_t *synth, int chan, int val); +FLUIDSYNTH_API int fluid_synth_get_pitch_wheel_sens(fluid_synth_t *synth, int chan, int *pval); +FLUIDSYNTH_API int fluid_synth_program_change(fluid_synth_t *synth, int chan, int program); +FLUIDSYNTH_API int fluid_synth_channel_pressure(fluid_synth_t *synth, int chan, int val); +FLUIDSYNTH_API int fluid_synth_key_pressure(fluid_synth_t *synth, int chan, int key, int val); +FLUIDSYNTH_API int fluid_synth_bank_select(fluid_synth_t *synth, int chan, int bank); +FLUIDSYNTH_API int fluid_synth_sfont_select(fluid_synth_t *synth, int chan, int sfont_id); FLUIDSYNTH_API -int fluid_synth_program_select(fluid_synth_t* synth, int chan, int sfont_id, +int fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id, int bank_num, int preset_num); FLUIDSYNTH_API int -fluid_synth_program_select_by_sfont_name (fluid_synth_t* synth, int chan, - const char *sfont_name, int bank_num, - int preset_num); -FLUIDSYNTH_API -int fluid_synth_get_program(fluid_synth_t* synth, int chan, int* sfont_id, - int* bank_num, int* preset_num); -FLUIDSYNTH_API int fluid_synth_unset_program (fluid_synth_t *synth, int chan); -FLUIDSYNTH_API int fluid_synth_program_reset(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_system_reset(fluid_synth_t* synth); +fluid_synth_program_select_by_sfont_name(fluid_synth_t *synth, int chan, + const char *sfont_name, int bank_num, + int preset_num); +FLUIDSYNTH_API +int fluid_synth_get_program(fluid_synth_t *synth, int chan, int *sfont_id, + int *bank_num, int *preset_num); +FLUIDSYNTH_API int fluid_synth_unset_program(fluid_synth_t *synth, int chan); +FLUIDSYNTH_API int fluid_synth_program_reset(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_system_reset(fluid_synth_t *synth); -FLUIDSYNTH_API int fluid_synth_all_notes_off(fluid_synth_t* synth, int chan); -FLUIDSYNTH_API int fluid_synth_all_sounds_off(fluid_synth_t* synth, int chan); +FLUIDSYNTH_API int fluid_synth_all_notes_off(fluid_synth_t *synth, int chan); +FLUIDSYNTH_API int fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan); /** * The midi channel type used by fluid_synth_set_channel_type() */ enum fluid_midi_channel_type { - CHANNEL_TYPE_MELODIC = 0, /**< Melodic midi channel */ - CHANNEL_TYPE_DRUM = 1 /**< Drum midi channel */ + CHANNEL_TYPE_MELODIC = 0, /**< Melodic midi channel */ + CHANNEL_TYPE_DRUM = 1 /**< Drum midi channel */ }; -FLUIDSYNTH_API int fluid_synth_set_channel_type(fluid_synth_t* synth, int chan, int type); +FLUIDSYNTH_API int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type); /* Low level access */ -FLUIDSYNTH_API fluid_preset_t* fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan); -FLUIDSYNTH_API int fluid_synth_start(fluid_synth_t* synth, unsigned int id, - fluid_preset_t* preset, int audio_chan, - int midi_chan, int key, int vel); -FLUIDSYNTH_API int fluid_synth_stop(fluid_synth_t* synth, unsigned int id); +FLUIDSYNTH_API fluid_preset_t *fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan); +FLUIDSYNTH_API int fluid_synth_start(fluid_synth_t *synth, unsigned int id, + fluid_preset_t *preset, int audio_chan, + int midi_chan, int key, int vel); +FLUIDSYNTH_API int fluid_synth_stop(fluid_synth_t *synth, unsigned int id); /* SoundFont management */ -FLUIDSYNTH_API -int fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets); -FLUIDSYNTH_API int fluid_synth_sfreload(fluid_synth_t* synth, int id); -FLUIDSYNTH_API int fluid_synth_sfunload(fluid_synth_t* synth, int id, int reset_presets); -FLUIDSYNTH_API int fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont); -FLUIDSYNTH_API int fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont); -FLUIDSYNTH_API int fluid_synth_sfcount(fluid_synth_t* synth); -FLUIDSYNTH_API fluid_sfont_t* fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num); -FLUIDSYNTH_API fluid_sfont_t* fluid_synth_get_sfont_by_id(fluid_synth_t* synth, int id); -FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont_by_name (fluid_synth_t* synth, - const char *name); -FLUIDSYNTH_API int fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset); -FLUIDSYNTH_API int fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id); +FLUIDSYNTH_API +int fluid_synth_sfload(fluid_synth_t *synth, const char *filename, int reset_presets); +FLUIDSYNTH_API int fluid_synth_sfreload(fluid_synth_t *synth, int id); +FLUIDSYNTH_API int fluid_synth_sfunload(fluid_synth_t *synth, int id, int reset_presets); +FLUIDSYNTH_API int fluid_synth_add_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont); +FLUIDSYNTH_API int fluid_synth_remove_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont); +FLUIDSYNTH_API int fluid_synth_sfcount(fluid_synth_t *synth); +FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont(fluid_synth_t *synth, unsigned int num); +FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont_by_id(fluid_synth_t *synth, int id); +FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont_by_name(fluid_synth_t *synth, + const char *name); +FLUIDSYNTH_API int fluid_synth_set_bank_offset(fluid_synth_t *synth, int sfont_id, int offset); +FLUIDSYNTH_API int fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_id); /* Reverb */ -FLUIDSYNTH_API int fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize, - double damping, double width, double level); -FLUIDSYNTH_API int fluid_synth_set_reverb_roomsize(fluid_synth_t* synth, double roomsize); -FLUIDSYNTH_API int fluid_synth_set_reverb_damp(fluid_synth_t* synth, double damping); -FLUIDSYNTH_API int fluid_synth_set_reverb_width(fluid_synth_t* synth, double width); -FLUIDSYNTH_API int fluid_synth_set_reverb_level(fluid_synth_t* synth, double level); +FLUIDSYNTH_API int fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, + double damping, double width, double level); +FLUIDSYNTH_API int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize); +FLUIDSYNTH_API int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping); +FLUIDSYNTH_API int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width); +FLUIDSYNTH_API int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level); -FLUIDSYNTH_API void fluid_synth_set_reverb_on(fluid_synth_t* synth, int on); -FLUIDSYNTH_API double fluid_synth_get_reverb_roomsize(fluid_synth_t* synth); -FLUIDSYNTH_API double fluid_synth_get_reverb_damp(fluid_synth_t* synth); -FLUIDSYNTH_API double fluid_synth_get_reverb_level(fluid_synth_t* synth); -FLUIDSYNTH_API double fluid_synth_get_reverb_width(fluid_synth_t* synth); +FLUIDSYNTH_API void fluid_synth_set_reverb_on(fluid_synth_t *synth, int on); +FLUIDSYNTH_API double fluid_synth_get_reverb_roomsize(fluid_synth_t *synth); +FLUIDSYNTH_API double fluid_synth_get_reverb_damp(fluid_synth_t *synth); +FLUIDSYNTH_API double fluid_synth_get_reverb_level(fluid_synth_t *synth); +FLUIDSYNTH_API double fluid_synth_get_reverb_width(fluid_synth_t *synth); /* Chorus */ @@ -143,94 +143,96 @@ FLUIDSYNTH_API double fluid_synth_get_reverb_width(fluid_synth_t* synth); /** * Chorus modulation waveform type. */ -enum fluid_chorus_mod { - FLUID_CHORUS_MOD_SINE = 0, /**< Sine wave chorus modulation */ - FLUID_CHORUS_MOD_TRIANGLE = 1 /**< Triangle wave chorus modulation */ +enum fluid_chorus_mod +{ + FLUID_CHORUS_MOD_SINE = 0, /**< Sine wave chorus modulation */ + FLUID_CHORUS_MOD_TRIANGLE = 1 /**< Triangle wave chorus modulation */ }; -FLUIDSYNTH_API int fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level, - double speed, double depth_ms, int type); -FLUIDSYNTH_API int fluid_synth_set_chorus_nr(fluid_synth_t* synth, int nr); -FLUIDSYNTH_API int fluid_synth_set_chorus_level(fluid_synth_t* synth, double level); -FLUIDSYNTH_API int fluid_synth_set_chorus_speed(fluid_synth_t* synth, double speed); -FLUIDSYNTH_API int fluid_synth_set_chorus_depth(fluid_synth_t* synth, double depth_ms); -FLUIDSYNTH_API int fluid_synth_set_chorus_type(fluid_synth_t* synth, int type); +FLUIDSYNTH_API int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level, + double speed, double depth_ms, int type); +FLUIDSYNTH_API int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr); +FLUIDSYNTH_API int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level); +FLUIDSYNTH_API int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed); +FLUIDSYNTH_API int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms); +FLUIDSYNTH_API int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type); -FLUIDSYNTH_API void fluid_synth_set_chorus_on(fluid_synth_t* synth, int on); -FLUIDSYNTH_API int fluid_synth_get_chorus_nr(fluid_synth_t* synth); -FLUIDSYNTH_API double fluid_synth_get_chorus_level(fluid_synth_t* synth); -FLUIDSYNTH_API double fluid_synth_get_chorus_speed(fluid_synth_t* synth); -FLUIDSYNTH_API double fluid_synth_get_chorus_depth(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_get_chorus_type(fluid_synth_t* synth); /* see fluid_chorus_mod */ +FLUIDSYNTH_API void fluid_synth_set_chorus_on(fluid_synth_t *synth, int on); +FLUIDSYNTH_API int fluid_synth_get_chorus_nr(fluid_synth_t *synth); +FLUIDSYNTH_API double fluid_synth_get_chorus_level(fluid_synth_t *synth); +FLUIDSYNTH_API double fluid_synth_get_chorus_speed(fluid_synth_t *synth); +FLUIDSYNTH_API double fluid_synth_get_chorus_depth(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_get_chorus_type(fluid_synth_t *synth); /* see fluid_chorus_mod */ /* Audio and MIDI channels */ -FLUIDSYNTH_API int fluid_synth_count_midi_channels(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_count_audio_channels(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_count_audio_groups(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_count_effects_channels(fluid_synth_t* synth); +FLUIDSYNTH_API int fluid_synth_count_midi_channels(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_count_audio_channels(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_count_audio_groups(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_count_effects_channels(fluid_synth_t *synth); /* Synthesis parameters */ -FLUIDSYNTH_API void fluid_synth_set_sample_rate(fluid_synth_t* synth, float sample_rate); -FLUIDSYNTH_API void fluid_synth_set_gain(fluid_synth_t* synth, float gain); -FLUIDSYNTH_API float fluid_synth_get_gain(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony); -FLUIDSYNTH_API int fluid_synth_get_polyphony(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_get_active_voice_count(fluid_synth_t* synth); -FLUIDSYNTH_API int fluid_synth_get_internal_bufsize(fluid_synth_t* synth); +FLUIDSYNTH_API void fluid_synth_set_sample_rate(fluid_synth_t *synth, float sample_rate); +FLUIDSYNTH_API void fluid_synth_set_gain(fluid_synth_t *synth, float gain); +FLUIDSYNTH_API float fluid_synth_get_gain(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_set_polyphony(fluid_synth_t *synth, int polyphony); +FLUIDSYNTH_API int fluid_synth_get_polyphony(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_get_active_voice_count(fluid_synth_t *synth); +FLUIDSYNTH_API int fluid_synth_get_internal_bufsize(fluid_synth_t *synth); -FLUIDSYNTH_API -int fluid_synth_set_interp_method(fluid_synth_t* synth, int chan, int interp_method); +FLUIDSYNTH_API +int fluid_synth_set_interp_method(fluid_synth_t *synth, int chan, int interp_method); /** * Synthesis interpolation method. */ -enum fluid_interp { - FLUID_INTERP_NONE = 0, /**< No interpolation: Fastest, but questionable audio quality */ - FLUID_INTERP_LINEAR = 1, /**< Straight-line interpolation: A bit slower, reasonable audio quality */ - FLUID_INTERP_4THORDER = 4, /**< Fourth-order interpolation, good quality, the default */ - FLUID_INTERP_7THORDER = 7, /**< Seventh-order interpolation */ - - FLUID_INTERP_DEFAULT = FLUID_INTERP_4THORDER, /**< Default interpolation method */ - FLUID_INTERP_HIGHEST = FLUID_INTERP_7THORDER, /**< Highest interpolation method */ +enum fluid_interp +{ + FLUID_INTERP_NONE = 0, /**< No interpolation: Fastest, but questionable audio quality */ + FLUID_INTERP_LINEAR = 1, /**< Straight-line interpolation: A bit slower, reasonable audio quality */ + FLUID_INTERP_4THORDER = 4, /**< Fourth-order interpolation, good quality, the default */ + FLUID_INTERP_7THORDER = 7, /**< Seventh-order interpolation */ + + FLUID_INTERP_DEFAULT = FLUID_INTERP_4THORDER, /**< Default interpolation method */ + FLUID_INTERP_HIGHEST = FLUID_INTERP_7THORDER, /**< Highest interpolation method */ }; /* Generator interface */ -FLUIDSYNTH_API int fluid_synth_set_gen (fluid_synth_t* synth, int chan, - int param, float value); -FLUIDSYNTH_API float fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param); +FLUIDSYNTH_API int fluid_synth_set_gen(fluid_synth_t *synth, int chan, + int param, float value); +FLUIDSYNTH_API float fluid_synth_get_gen(fluid_synth_t *synth, int chan, int param); /* Tuning */ FLUIDSYNTH_API -int fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog, - const char* name, const double* pitch, int apply); +int fluid_synth_activate_key_tuning(fluid_synth_t *synth, int bank, int prog, + const char *name, const double *pitch, int apply); FLUIDSYNTH_API -int fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog, - const char* name, const double* pitch, int apply); -FLUIDSYNTH_API -int fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog, - int len, const int *keys, const double* pitch, int apply); +int fluid_synth_activate_octave_tuning(fluid_synth_t *synth, int bank, int prog, + const char *name, const double *pitch, int apply); FLUIDSYNTH_API -int fluid_synth_activate_tuning(fluid_synth_t* synth, int chan, int bank, int prog, +int fluid_synth_tune_notes(fluid_synth_t *synth, int bank, int prog, + int len, const int *keys, const double *pitch, int apply); +FLUIDSYNTH_API +int fluid_synth_activate_tuning(fluid_synth_t *synth, int chan, int bank, int prog, int apply); FLUIDSYNTH_API -int fluid_synth_deactivate_tuning(fluid_synth_t* synth, int chan, int apply); -FLUIDSYNTH_API void fluid_synth_tuning_iteration_start(fluid_synth_t* synth); -FLUIDSYNTH_API -int fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog); -FLUIDSYNTH_API int fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog, - char* name, int len, double* pitch); +int fluid_synth_deactivate_tuning(fluid_synth_t *synth, int chan, int apply); +FLUIDSYNTH_API void fluid_synth_tuning_iteration_start(fluid_synth_t *synth); +FLUIDSYNTH_API +int fluid_synth_tuning_iteration_next(fluid_synth_t *synth, int *bank, int *prog); +FLUIDSYNTH_API int fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int prog, + char *name, int len, double *pitch); /* Misc */ -FLUIDSYNTH_API double fluid_synth_get_cpu_load(fluid_synth_t* synth); -FLUIDSYNTH_API const char* fluid_synth_error(fluid_synth_t* synth); +FLUIDSYNTH_API double fluid_synth_get_cpu_load(fluid_synth_t *synth); +FLUIDSYNTH_API const char *fluid_synth_error(fluid_synth_t *synth); /* Default modulators */ @@ -238,13 +240,14 @@ FLUIDSYNTH_API const char* fluid_synth_error(fluid_synth_t* synth); /** * Enum used with fluid_synth_add_default_mod() to specify how to handle duplicate modulators. */ -enum fluid_synth_add_mod { - FLUID_SYNTH_OVERWRITE, /**< Overwrite any existing matching modulator */ - FLUID_SYNTH_ADD, /**< Add (sum) modulator amounts */ +enum fluid_synth_add_mod +{ + FLUID_SYNTH_OVERWRITE, /**< Overwrite any existing matching modulator */ + FLUID_SYNTH_ADD, /**< Add (sum) modulator amounts */ }; -FLUIDSYNTH_API int fluid_synth_add_default_mod(fluid_synth_t* synth, fluid_mod_t* mod, int mode); -FLUIDSYNTH_API int fluid_synth_remove_default_mod(fluid_synth_t* synth, const fluid_mod_t* mod); +FLUIDSYNTH_API int fluid_synth_add_default_mod(fluid_synth_t *synth, fluid_mod_t *mod, int mode); +FLUIDSYNTH_API int fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod); /* @@ -252,38 +255,39 @@ FLUIDSYNTH_API int fluid_synth_remove_default_mod(fluid_synth_t* synth, const fl * * To create a synthesizer plugin, create the synthesizer as * explained above. Once the synthesizer is created you can call - * any of the functions below to get the audio. + * any of the functions below to get the audio. */ -FLUIDSYNTH_API int fluid_synth_write_s16(fluid_synth_t* synth, int len, - void* lout, int loff, int lincr, - void* rout, int roff, int rincr); -FLUIDSYNTH_API int fluid_synth_write_float(fluid_synth_t* synth, int len, - void* lout, int loff, int lincr, - void* rout, int roff, int rincr); -FLUIDSYNTH_API int fluid_synth_nwrite_float(fluid_synth_t* synth, int len, - float** left, float** right, - float** fx_left, float** fx_right); -FLUIDSYNTH_API int fluid_synth_process(fluid_synth_t* synth, int len, - int nfx, float* fx[], - int nout, float* out[]); +FLUIDSYNTH_API int fluid_synth_write_s16(fluid_synth_t *synth, int len, + void *lout, int loff, int lincr, + void *rout, int roff, int rincr); +FLUIDSYNTH_API int fluid_synth_write_float(fluid_synth_t *synth, int len, + void *lout, int loff, int lincr, + void *rout, int roff, int rincr); +FLUIDSYNTH_API int fluid_synth_nwrite_float(fluid_synth_t *synth, int len, + float **left, float **right, + float **fx_left, float **fx_right); +FLUIDSYNTH_API int fluid_synth_process(fluid_synth_t *synth, int len, + int nfx, float *fx[], + int nout, float *out[]); /* Synthesizer's interface to handle SoundFont loaders */ -FLUIDSYNTH_API void fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader); -FLUIDSYNTH_API fluid_voice_t* fluid_synth_alloc_voice(fluid_synth_t* synth, - fluid_sample_t* sample, - int channum, int key, int vel); -FLUIDSYNTH_API void fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* voice); -FLUIDSYNTH_API void fluid_synth_get_voicelist(fluid_synth_t* synth, - fluid_voice_t* buf[], int bufsize, int ID); -FLUIDSYNTH_API int fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event); +FLUIDSYNTH_API void fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader); +FLUIDSYNTH_API fluid_voice_t *fluid_synth_alloc_voice(fluid_synth_t *synth, + fluid_sample_t *sample, + int channum, int key, int vel); +FLUIDSYNTH_API void fluid_synth_start_voice(fluid_synth_t *synth, fluid_voice_t *voice); +FLUIDSYNTH_API void fluid_synth_get_voicelist(fluid_synth_t *synth, + fluid_voice_t *buf[], int bufsize, int ID); +FLUIDSYNTH_API int fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event); /** * Specifies the type of filter to use for the custom IIR filter */ -enum fluid_iir_filter_type { +enum fluid_iir_filter_type +{ FLUID_IIR_DISABLED = 0, /**< Custom IIR filter is not operating */ FLUID_IIR_LOWPASS, /**< Custom IIR filter is operating as low-pass filter */ FLUID_IIR_HIGHPASS, /**< Custom IIR filter is operating as high-pass filter */ @@ -293,13 +297,14 @@ enum fluid_iir_filter_type { /** * Specifies optional settings to use for the custom IIR filter */ -enum fluid_iir_filter_flags { +enum fluid_iir_filter_flags +{ FLUID_IIR_Q_LINEAR = 1 << 0, /**< The Soundfont spec requires the filter Q to be interpreted in dB. If this flag is set the filter Q is instead assumed to be in a linear range */ FLUID_IIR_Q_ZERO_OFF = 1 << 1, /**< If this flag the filter is switched off if Q == 0 (prior to any transformation) */ FLUID_IIR_NO_GAIN_AMP = 1 << 2 /**< The Soundfont spec requires to correct the gain of the filter depending on the filter's Q. If this flag is set the filter gain will not be corrected. */ }; -FLUIDSYNTH_API int fluid_synth_set_custom_filter(fluid_synth_t*, int type, int flags); +FLUIDSYNTH_API int fluid_synth_set_custom_filter(fluid_synth_t *, int type, int flags); /* LADSPA */ @@ -310,7 +315,7 @@ FLUIDSYNTH_API fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth /* API: Poly mono mode */ /** Interface to poly/mono mode variables - * + * * Channel mode bits OR-ed together so that it matches with the midi spec: poly omnion (0), mono omnion (1), poly omnioff (2), mono omnioff (3) */ enum fluid_channel_mode_flags @@ -329,7 +334,7 @@ enum fluid_channel_breath_flags /** Indicates the mode a basic channel is set to */ enum fluid_basic_channel_modes -{ +{ FLUID_CHANNEL_MODE_MASK = (FLUID_CHANNEL_OMNI_OFF | FLUID_CHANNEL_POLY_OFF), /**< Mask Poly and Omni bits of #fluid_channel_mode_flags, usually only used internally */ FLUID_CHANNEL_MODE_OMNION_POLY = FLUID_CHANNEL_MODE_MASK & (~FLUID_CHANNEL_OMNI_OFF & ~FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 0 */ FLUID_CHANNEL_MODE_OMNION_MONO = FLUID_CHANNEL_MODE_MASK & (~FLUID_CHANNEL_OMNI_OFF & FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 1 */ @@ -338,27 +343,27 @@ enum fluid_basic_channel_modes FLUID_CHANNEL_MODE_LAST /**< @internal Value defines the count of basic channel modes (#fluid_basic_channel_modes) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ }; -FLUIDSYNTH_API int fluid_synth_reset_basic_channel(fluid_synth_t* synth, int chan); +FLUIDSYNTH_API int fluid_synth_reset_basic_channel(fluid_synth_t *synth, int chan); -FLUIDSYNTH_API int fluid_synth_get_basic_channel(fluid_synth_t* synth, int chan, - int *basic_chan_out, - int *mode_chan_out, - int *basic_val_out ); -FLUIDSYNTH_API int fluid_synth_set_basic_channel(fluid_synth_t* synth, int chan, int mode, int val); +FLUIDSYNTH_API int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan, + int *basic_chan_out, + int *mode_chan_out, + int *basic_val_out); +FLUIDSYNTH_API int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val); /** Interface to mono legato mode - * + * * Indicates the legato mode a channel is set to * n1,n2,n3,.. is a legato passage. n1 is the first note, and n2,n3,n4 are played legato with previous note. */ enum fluid_channel_legato_mode { - FLUID_CHANNEL_LEGATO_MODE_RETRIGGER, /**< Mode 0 - Release previous note, start a new note */ - FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER, /**< Mode 1 - On contiguous notes retrigger in attack section using current value, shape attack using current dynamic and make use of previous voices if any */ - FLUID_CHANNEL_LEGATO_MODE_LAST /**< @internal Value defines the count of legato modes (#fluid_channel_legato_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ + FLUID_CHANNEL_LEGATO_MODE_RETRIGGER, /**< Mode 0 - Release previous note, start a new note */ + FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER, /**< Mode 1 - On contiguous notes retrigger in attack section using current value, shape attack using current dynamic and make use of previous voices if any */ + FLUID_CHANNEL_LEGATO_MODE_LAST /**< @internal Value defines the count of legato modes (#fluid_channel_legato_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ }; -FLUIDSYNTH_API int fluid_synth_set_legato_mode(fluid_synth_t* synth, int chan, int legatomode); -FLUIDSYNTH_API int fluid_synth_get_legato_mode(fluid_synth_t* synth, int chan, int *legatomode); +FLUIDSYNTH_API int fluid_synth_set_legato_mode(fluid_synth_t *synth, int chan, int legatomode); +FLUIDSYNTH_API int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode); /** Interface to portamento mode * @@ -366,22 +371,22 @@ FLUIDSYNTH_API int fluid_synth_get_legato_mode(fluid_synth_t* synth, int chan, i */ enum fluid_channel_portamento_mode { - FLUID_CHANNEL_PORTAMENTO_MODE_EACH_NOTE, /**< Mode 0 - Portamento on each note (staccato or legato) */ - FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY, /**< Mode 1 - Portamento only on legato note */ - FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY, /**< Mode 2 - Portamento only on staccato note */ - FLUID_CHANNEL_PORTAMENTO_MODE_LAST /**< @internal Value defines the count of portamento modes (#fluid_channel_portamento_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ + FLUID_CHANNEL_PORTAMENTO_MODE_EACH_NOTE, /**< Mode 0 - Portamento on each note (staccato or legato) */ + FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY, /**< Mode 1 - Portamento only on legato note */ + FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY, /**< Mode 2 - Portamento only on staccato note */ + FLUID_CHANNEL_PORTAMENTO_MODE_LAST /**< @internal Value defines the count of portamento modes (#fluid_channel_portamento_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */ }; -FLUIDSYNTH_API int fluid_synth_set_portamento_mode(fluid_synth_t* synth, - int chan, int portamentomode); -FLUIDSYNTH_API int fluid_synth_get_portamento_mode(fluid_synth_t* synth, - int chan, int * portamentomode); +FLUIDSYNTH_API int fluid_synth_set_portamento_mode(fluid_synth_t *synth, + int chan, int portamentomode); +FLUIDSYNTH_API int fluid_synth_get_portamento_mode(fluid_synth_t *synth, + int chan, int *portamentomode); /* Interface to breath mode */ -FLUIDSYNTH_API int fluid_synth_set_breath_mode(fluid_synth_t* synth, - int chan, int breathmode); -FLUIDSYNTH_API int fluid_synth_get_breath_mode(fluid_synth_t* synth, - int chan, int *breathmode); +FLUIDSYNTH_API int fluid_synth_set_breath_mode(fluid_synth_t *synth, + int chan, int breathmode); +FLUIDSYNTH_API int fluid_synth_get_breath_mode(fluid_synth_t *synth, + int chan, int *breathmode); #ifdef __cplusplus diff --git a/include/fluidsynth/types.h b/include/fluidsynth/types.h index dd5bfa8f..47ef1833 100644 --- a/include/fluidsynth/types.h +++ b/include/fluidsynth/types.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA diff --git a/include/fluidsynth/voice.h b/include/fluidsynth/voice.h index ed3f869a..f0644718 100644 --- a/include/fluidsynth/voice.h +++ b/include/fluidsynth/voice.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -39,30 +39,31 @@ extern "C" { /** * Enum used with fluid_voice_add_mod() to specify how to handle duplicate modulators. */ -enum fluid_voice_add_mod { - FLUID_VOICE_OVERWRITE, /**< Overwrite any existing matching modulator */ - FLUID_VOICE_ADD, /**< Add (sum) modulator amounts */ - FLUID_VOICE_DEFAULT /**< For default modulators only, no need to check for duplicates */ +enum fluid_voice_add_mod +{ + FLUID_VOICE_OVERWRITE, /**< Overwrite any existing matching modulator */ + FLUID_VOICE_ADD, /**< Add (sum) modulator amounts */ + FLUID_VOICE_DEFAULT /**< For default modulators only, no need to check for duplicates */ }; -FLUIDSYNTH_API void fluid_voice_add_mod(fluid_voice_t* voice, fluid_mod_t* mod, int mode); -FLUIDSYNTH_API float fluid_voice_gen_get(fluid_voice_t* voice, int gen); -FLUIDSYNTH_API void fluid_voice_gen_set(fluid_voice_t* voice, int gen, float val); -FLUIDSYNTH_API void fluid_voice_gen_incr(fluid_voice_t* voice, int gen, float val); +FLUIDSYNTH_API void fluid_voice_add_mod(fluid_voice_t *voice, fluid_mod_t *mod, int mode); +FLUIDSYNTH_API float fluid_voice_gen_get(fluid_voice_t *voice, int gen); +FLUIDSYNTH_API void fluid_voice_gen_set(fluid_voice_t *voice, int gen, float val); +FLUIDSYNTH_API void fluid_voice_gen_incr(fluid_voice_t *voice, int gen, float val); + +FLUIDSYNTH_API unsigned int fluid_voice_get_id(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_get_channel(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_get_key(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_get_actual_key(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_get_velocity(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_get_actual_velocity(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_is_playing(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_is_on(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_is_sustained(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_is_sostenuto(const fluid_voice_t *voice); +FLUIDSYNTH_API int fluid_voice_optimize_sample(fluid_sample_t *s); +FLUIDSYNTH_API void fluid_voice_update_param(fluid_voice_t *voice, int gen); -FLUIDSYNTH_API unsigned int fluid_voice_get_id(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_get_channel(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_get_key(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_get_actual_key(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_get_velocity(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_get_actual_velocity(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_is_playing(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_is_on(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_is_sustained(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_is_sostenuto(const fluid_voice_t* voice); -FLUIDSYNTH_API int fluid_voice_optimize_sample(fluid_sample_t* s); -FLUIDSYNTH_API void fluid_voice_update_param(fluid_voice_t* voice, int gen); - #ifdef __cplusplus } diff --git a/src/bindings/fluid_cmd.c b/src/bindings/fluid_cmd.c index b28b0608..93ac9126 100644 --- a/src/bindings/fluid_cmd.c +++ b/src/bindings/fluid_cmd.c @@ -42,203 +42,352 @@ #define FLUID_ENTRY_COMMAND(data) fluid_cmd_handler_t* handler=(fluid_cmd_handler_t*)(data) /* the shell cmd handler struct */ -struct _fluid_cmd_handler_t { - fluid_synth_t* synth; - fluid_midi_router_t* router; - fluid_cmd_hash_t* commands; - - fluid_midi_router_rule_t *cmd_rule; /* Rule currently being processed by shell command handler */ - int cmd_rule_type; /* Type of the rule (#fluid_midi_router_rule_type) */ -}; - - -struct _fluid_shell_t { - fluid_settings_t* settings; - fluid_cmd_handler_t* handler; - fluid_thread_t* thread; - fluid_istream_t in; - fluid_ostream_t out; -}; - - -static fluid_thread_return_t fluid_shell_run(void* data); -static void fluid_shell_init(fluid_shell_t* shell, - fluid_settings_t* settings, fluid_cmd_handler_t* handler, - fluid_istream_t in, fluid_ostream_t out); -static int fluid_handle_voice_count (void* data, int ac, char **av, - fluid_ostream_t out); - -void fluid_shell_settings(fluid_settings_t* settings) +struct _fluid_cmd_handler_t { - fluid_settings_register_str(settings, "shell.prompt", "", 0); - fluid_settings_register_int(settings, "shell.port", 9800, 1, 65535, 0); + fluid_synth_t *synth; + fluid_midi_router_t *router; + fluid_cmd_hash_t *commands; + + fluid_midi_router_rule_t *cmd_rule; /* Rule currently being processed by shell command handler */ + int cmd_rule_type; /* Type of the rule (#fluid_midi_router_rule_type) */ +}; + + +struct _fluid_shell_t +{ + fluid_settings_t *settings; + fluid_cmd_handler_t *handler; + fluid_thread_t *thread; + fluid_istream_t in; + fluid_ostream_t out; +}; + + +static fluid_thread_return_t fluid_shell_run(void *data); +static void fluid_shell_init(fluid_shell_t *shell, + fluid_settings_t *settings, fluid_cmd_handler_t *handler, + fluid_istream_t in, fluid_ostream_t out); +static int fluid_handle_voice_count(void *data, int ac, char **av, + fluid_ostream_t out); + +void fluid_shell_settings(fluid_settings_t *settings) +{ + fluid_settings_register_str(settings, "shell.prompt", "", 0); + fluid_settings_register_int(settings, "shell.port", 9800, 1, 65535, 0); } /** the table of all handled commands */ -static const fluid_cmd_t fluid_commands[] = { +static const fluid_cmd_t fluid_commands[] = +{ /* general commands */ - { "help", "general", fluid_handle_help, - "help Shows help topics ('help TOPIC' for more info)" }, - { "quit", "general", fluid_handle_quit, - "quit Quit the synthesizer" }, - { "source", "general", fluid_handle_source, - "source filename Loads a file and parse every line as a command" }, + { + "help", "general", fluid_handle_help, + "help Shows help topics ('help TOPIC' for more info)" + }, + { + "quit", "general", fluid_handle_quit, + "quit Quit the synthesizer" + }, + { + "source", "general", fluid_handle_source, + "source filename Loads a file and parse every line as a command" + }, /* event commands */ - { "noteon", "event", fluid_handle_noteon, - "noteon chan key vel Sends noteon" }, - { "noteoff", "event", fluid_handle_noteoff, - "noteoff chan key Sends noteoff" }, - { "pitch_bend", "event", fluid_handle_pitch_bend, - "pitch_bend chan offset Bends pitch" }, - { "pitch_bend_range", "event", fluid_handle_pitch_bend_range, - "pitch_bend chan range Sets bend pitch range" }, - { "cc", "event", fluid_handle_cc, - "cc chan ctrl value Sends control-change message" }, - { "prog", "event", fluid_handle_prog, - "prog chan num Sends program-change message" }, - { "select", "event", fluid_handle_select, - "select chan sfont bank prog Combination of bank-select and program-change" }, - { "load", "general", fluid_handle_load, - "load file [reset] [bankofs] Loads SoundFont (reset=0|1, def 1; bankofs=n, def 0)" }, - { "unload", "general", fluid_handle_unload, - "unload id [reset] Unloads SoundFont by ID (reset=0|1, default 1)"}, - { "reload", "general", fluid_handle_reload, - "reload id Reload the SoundFont with the specified ID" }, - { "fonts", "general", fluid_handle_fonts, - "fonts Display the list of loaded SoundFonts" }, - { "inst", "general", fluid_handle_inst, - "inst font Print out the available instruments for the font" }, - { "channels", "general", fluid_handle_channels, - "channels [-verbose] Print out preset of all channels" }, - { "interp", "general", fluid_handle_interp, - "interp num Choose interpolation method for all channels" }, - { "interpc", "general", fluid_handle_interpc, - "interpc chan num Choose interpolation method for one channel" }, + { + "noteon", "event", fluid_handle_noteon, + "noteon chan key vel Sends noteon" + }, + { + "noteoff", "event", fluid_handle_noteoff, + "noteoff chan key Sends noteoff" + }, + { + "pitch_bend", "event", fluid_handle_pitch_bend, + "pitch_bend chan offset Bends pitch" + }, + { + "pitch_bend_range", "event", fluid_handle_pitch_bend_range, + "pitch_bend chan range Sets bend pitch range" + }, + { + "cc", "event", fluid_handle_cc, + "cc chan ctrl value Sends control-change message" + }, + { + "prog", "event", fluid_handle_prog, + "prog chan num Sends program-change message" + }, + { + "select", "event", fluid_handle_select, + "select chan sfont bank prog Combination of bank-select and program-change" + }, + { + "load", "general", fluid_handle_load, + "load file [reset] [bankofs] Loads SoundFont (reset=0|1, def 1; bankofs=n, def 0)" + }, + { + "unload", "general", fluid_handle_unload, + "unload id [reset] Unloads SoundFont by ID (reset=0|1, default 1)" + }, + { + "reload", "general", fluid_handle_reload, + "reload id Reload the SoundFont with the specified ID" + }, + { + "fonts", "general", fluid_handle_fonts, + "fonts Display the list of loaded SoundFonts" + }, + { + "inst", "general", fluid_handle_inst, + "inst font Print out the available instruments for the font" + }, + { + "channels", "general", fluid_handle_channels, + "channels [-verbose] Print out preset of all channels" + }, + { + "interp", "general", fluid_handle_interp, + "interp num Choose interpolation method for all channels" + }, + { + "interpc", "general", fluid_handle_interpc, + "interpc chan num Choose interpolation method for one channel" + }, /* polymono commands */ - { "basicchannels", "polymono", fluid_handle_basicchannels, - "basicchannels Prints the list of basic channels"}, - { "resetbasicchannels", "polymono", fluid_handle_resetbasicchannels, - "resetbasicchannels [chan1 chan2..] Resets all or some basic channels"}, - { "setbasicchannels", "polymono", fluid_handle_setbasicchannels, - "setbasicchannels [chan mode val...] Sets default, adds basic channels"}, - { "channelsmode", "polymono", fluid_handle_channelsmode, - "channelsmode [chan1 chan2..] Prints channels mode"}, - { "legatomode", "polymono", fluid_handle_legatomode, - "legatomode [chan1 chan2..] Prints channels legato mode"}, - { "setlegatomode", "polymono", fluid_handle_setlegatomode, - "setlegatomode chan mode [chan mode..] Sets legato mode"}, - { "portamentomode", "polymono", fluid_handle_portamentomode, - "portamentomode [chan1 chan2..] Prints channels portamento mode"}, - { "setportamentomode", "polymono", fluid_handle_setportamentomode, - "setportamentomode chan mode [chan mode..] Sets portamento mode"}, - { "breathmode", "polymono", fluid_handle_breathmode, - "breathmode [chan1 chan2..] Prints channels breath mode"}, - { "setbreathmode", "polymono", fluid_handle_setbreathmode, - "setbreathmode chan poly(1/0) mono(1/0) breath_sync(1/0) [..] Sets breath mode"}, + { + "basicchannels", "polymono", fluid_handle_basicchannels, + "basicchannels Prints the list of basic channels" + }, + { + "resetbasicchannels", "polymono", fluid_handle_resetbasicchannels, + "resetbasicchannels [chan1 chan2..] Resets all or some basic channels" + }, + { + "setbasicchannels", "polymono", fluid_handle_setbasicchannels, + "setbasicchannels [chan mode val...] Sets default, adds basic channels" + }, + { + "channelsmode", "polymono", fluid_handle_channelsmode, + "channelsmode [chan1 chan2..] Prints channels mode" + }, + { + "legatomode", "polymono", fluid_handle_legatomode, + "legatomode [chan1 chan2..] Prints channels legato mode" + }, + { + "setlegatomode", "polymono", fluid_handle_setlegatomode, + "setlegatomode chan mode [chan mode..] Sets legato mode" + }, + { + "portamentomode", "polymono", fluid_handle_portamentomode, + "portamentomode [chan1 chan2..] Prints channels portamento mode" + }, + { + "setportamentomode", "polymono", fluid_handle_setportamentomode, + "setportamentomode chan mode [chan mode..] Sets portamento mode" + }, + { + "breathmode", "polymono", fluid_handle_breathmode, + "breathmode [chan1 chan2..] Prints channels breath mode" + }, + { + "setbreathmode", "polymono", fluid_handle_setbreathmode, + "setbreathmode chan poly(1/0) mono(1/0) breath_sync(1/0) [..] Sets breath mode" + }, /* reverb commands */ - { "rev_preset", "reverb", fluid_handle_reverbpreset, - "rev_preset num Load preset num into the reverb unit" }, - { "rev_setroomsize", "reverb", fluid_handle_reverbsetroomsize, - "rev_setroomsize num Change reverb room size" }, - { "rev_setdamp", "reverb", fluid_handle_reverbsetdamp, - "rev_setdamp num Change reverb damping" }, - { "rev_setwidth", "reverb", fluid_handle_reverbsetwidth, - "rev_setwidth num Change reverb width" }, - { "rev_setlevel", "reverb", fluid_handle_reverbsetlevel, - "rev_setlevel num Change reverb level" }, - { "reverb", "reverb", fluid_handle_reverb, - "reverb [0|1|on|off] Turn the reverb on or off" }, + { + "rev_preset", "reverb", fluid_handle_reverbpreset, + "rev_preset num Load preset num into the reverb unit" + }, + { + "rev_setroomsize", "reverb", fluid_handle_reverbsetroomsize, + "rev_setroomsize num Change reverb room size" + }, + { + "rev_setdamp", "reverb", fluid_handle_reverbsetdamp, + "rev_setdamp num Change reverb damping" + }, + { + "rev_setwidth", "reverb", fluid_handle_reverbsetwidth, + "rev_setwidth num Change reverb width" + }, + { + "rev_setlevel", "reverb", fluid_handle_reverbsetlevel, + "rev_setlevel num Change reverb level" + }, + { + "reverb", "reverb", fluid_handle_reverb, + "reverb [0|1|on|off] Turn the reverb on or off" + }, /* chorus commands */ - { "cho_set_nr", "chorus", fluid_handle_chorusnr, - "cho_set_nr n Use n delay lines (default 3)" }, - { "cho_set_level", "chorus", fluid_handle_choruslevel, - "cho_set_level num Set output level of each chorus line to num" }, - { "cho_set_speed", "chorus", fluid_handle_chorusspeed, - "cho_set_speed num Set mod speed of chorus to num (Hz)" }, - { "cho_set_depth", "chorus", fluid_handle_chorusdepth, - "cho_set_depth num Set chorus modulation depth to num (ms)" }, - { "chorus", "chorus", fluid_handle_chorus, - "chorus [0|1|on|off] Turn the chorus on or off" }, - { "gain", "general", fluid_handle_gain, - "gain value Set the master gain (0 < gain < 5)" }, - { "voice_count", "general", fluid_handle_voice_count, - "voice_count Get number of active synthesis voices" }, + { + "cho_set_nr", "chorus", fluid_handle_chorusnr, + "cho_set_nr n Use n delay lines (default 3)" + }, + { + "cho_set_level", "chorus", fluid_handle_choruslevel, + "cho_set_level num Set output level of each chorus line to num" + }, + { + "cho_set_speed", "chorus", fluid_handle_chorusspeed, + "cho_set_speed num Set mod speed of chorus to num (Hz)" + }, + { + "cho_set_depth", "chorus", fluid_handle_chorusdepth, + "cho_set_depth num Set chorus modulation depth to num (ms)" + }, + { + "chorus", "chorus", fluid_handle_chorus, + "chorus [0|1|on|off] Turn the chorus on or off" + }, + { + "gain", "general", fluid_handle_gain, + "gain value Set the master gain (0 < gain < 5)" + }, + { + "voice_count", "general", fluid_handle_voice_count, + "voice_count Get number of active synthesis voices" + }, /* tuning commands */ - { "tuning", "tuning", fluid_handle_tuning, - "tuning name bank prog Create a tuning with name, bank number, \n" - " and program number (0 <= bank,prog <= 127)" }, - { "tune", "tuning", fluid_handle_tune, - "tune bank prog key pitch Tune a key" }, - { "settuning", "tuning", fluid_handle_settuning, - "settuning chan bank prog Set the tuning for a MIDI channel" }, - { "resettuning", "tuning", fluid_handle_resettuning, - "resettuning chan Restore the default tuning of a MIDI channel" }, - { "tunings", "tuning", fluid_handle_tunings, - "tunings Print the list of available tunings" }, - { "dumptuning", "tuning", fluid_handle_dumptuning, - "dumptuning bank prog Print the pitch details of the tuning" }, - { "reset", "general", fluid_handle_reset, - "reset System reset (all notes off, reset controllers)" }, + { + "tuning", "tuning", fluid_handle_tuning, + "tuning name bank prog Create a tuning with name, bank number, \n" + " and program number (0 <= bank,prog <= 127)" + }, + { + "tune", "tuning", fluid_handle_tune, + "tune bank prog key pitch Tune a key" + }, + { + "settuning", "tuning", fluid_handle_settuning, + "settuning chan bank prog Set the tuning for a MIDI channel" + }, + { + "resettuning", "tuning", fluid_handle_resettuning, + "resettuning chan Restore the default tuning of a MIDI channel" + }, + { + "tunings", "tuning", fluid_handle_tunings, + "tunings Print the list of available tunings" + }, + { + "dumptuning", "tuning", fluid_handle_dumptuning, + "dumptuning bank prog Print the pitch details of the tuning" + }, + { + "reset", "general", fluid_handle_reset, + "reset System reset (all notes off, reset controllers)" + }, /* settings commands */ - { "set", "settings", fluid_handle_set, - "set name value Set the value of a controller or settings" }, - { "get", "settings", fluid_handle_get, - "get name Get the value of a controller or settings" }, - { "info", "settings", fluid_handle_info, - "info name Get information about a controller or settings" }, - { "settings", "settings", fluid_handle_settings, - "settings Print out all settings" }, - { "echo", "general", fluid_handle_echo, - "echo arg Print arg" }, - /* Sleep command, useful to insert a delay between commands */ - { "sleep", "general", fluid_handle_sleep, - "sleep duration sleep duration(in ms)" }, - /* LADSPA-related commands */ + { + "set", "settings", fluid_handle_set, + "set name value Set the value of a controller or settings" + }, + { + "get", "settings", fluid_handle_get, + "get name Get the value of a controller or settings" + }, + { + "info", "settings", fluid_handle_info, + "info name Get information about a controller or settings" + }, + { + "settings", "settings", fluid_handle_settings, + "settings Print out all settings" + }, + { + "echo", "general", fluid_handle_echo, + "echo arg Print arg" + }, + /* Sleep command, useful to insert a delay between commands */ + { + "sleep", "general", fluid_handle_sleep, + "sleep duration sleep duration(in ms)" + }, + /* LADSPA-related commands */ #ifdef LADSPA - { "ladspa_effect", "ladspa", fluid_handle_ladspa_effect, - "ladspa_effect Create a new effect from a LADSPA plugin"}, - { "ladspa_link", "ladspa", fluid_handle_ladspa_link, - "ladspa_link Connect an effect port to a host port or buffer"}, - { "ladspa_buffer", "ladspa", fluid_handle_ladspa_buffer, - "ladspa_buffer Create a LADSPA buffer"}, - { "ladspa_set", "ladspa", fluid_handle_ladspa_set, - "ladspa_set Set the value of an effect control port"}, - { "ladspa_check", "ladspa", fluid_handle_ladspa_check, - "ladspa_check Check LADSPA configuration"}, - { "ladspa_start", "ladspa", fluid_handle_ladspa_start, - "ladspa_start Start LADSPA effects"}, - { "ladspa_stop", "ladspa", fluid_handle_ladspa_stop, - "ladspa_stop Stop LADSPA effect unit"}, - { "ladspa_reset", "ladspa", fluid_handle_ladspa_reset, - "ladspa_reset Stop and reset LADSPA effects"}, + { + "ladspa_effect", "ladspa", fluid_handle_ladspa_effect, + "ladspa_effect Create a new effect from a LADSPA plugin" + }, + { + "ladspa_link", "ladspa", fluid_handle_ladspa_link, + "ladspa_link Connect an effect port to a host port or buffer" + }, + { + "ladspa_buffer", "ladspa", fluid_handle_ladspa_buffer, + "ladspa_buffer Create a LADSPA buffer" + }, + { + "ladspa_set", "ladspa", fluid_handle_ladspa_set, + "ladspa_set Set the value of an effect control port" + }, + { + "ladspa_check", "ladspa", fluid_handle_ladspa_check, + "ladspa_check Check LADSPA configuration" + }, + { + "ladspa_start", "ladspa", fluid_handle_ladspa_start, + "ladspa_start Start LADSPA effects" + }, + { + "ladspa_stop", "ladspa", fluid_handle_ladspa_stop, + "ladspa_stop Stop LADSPA effect unit" + }, + { + "ladspa_reset", "ladspa", fluid_handle_ladspa_reset, + "ladspa_reset Stop and reset LADSPA effects" + }, #endif /* router commands */ - { "router_clear", "router", fluid_handle_router_clear, - "router_clear Clears all routing rules from the midi router"}, - { "router_default", "router", fluid_handle_router_default, - "router_default Resets the midi router to default state"}, - { "router_begin", "router", fluid_handle_router_begin, - "router_begin [note|cc|prog|pbend|cpress|kpress]: Starts a new routing rule"}, - { "router_chan", "router", fluid_handle_router_chan, - "router_chan min max mul add filters and maps midi channels on current rule"}, - { "router_par1", "router", fluid_handle_router_par1, - "router_par1 min max mul add filters and maps parameter 1 (key/ctrl nr)"}, - { "router_par2", "router", fluid_handle_router_par2, - "router_par2 min max mul add filters and maps parameter 2 (vel/cc val)"}, - { "router_end", "router", fluid_handle_router_end, - "router_end closes and commits the current routing rule"}, + { + "router_clear", "router", fluid_handle_router_clear, + "router_clear Clears all routing rules from the midi router" + }, + { + "router_default", "router", fluid_handle_router_default, + "router_default Resets the midi router to default state" + }, + { + "router_begin", "router", fluid_handle_router_begin, + "router_begin [note|cc|prog|pbend|cpress|kpress]: Starts a new routing rule" + }, + { + "router_chan", "router", fluid_handle_router_chan, + "router_chan min max mul add filters and maps midi channels on current rule" + }, + { + "router_par1", "router", fluid_handle_router_par1, + "router_par1 min max mul add filters and maps parameter 1 (key/ctrl nr)" + }, + { + "router_par2", "router", fluid_handle_router_par2, + "router_par2 min max mul add filters and maps parameter 2 (vel/cc val)" + }, + { + "router_end", "router", fluid_handle_router_end, + "router_end closes and commits the current routing rule" + }, #if WITH_PROFILING /* Profiling commands */ - { "profile", "profile", fluid_handle_profile, - "profile Prints default parameters used by prof_start"}, - { "prof_set_notes", "profile", fluid_handle_prof_set_notes, - "prof_set_notes nbr [bank prog] Sets notes number generated by prof_start"}, - { "prof_set_print", "profile", fluid_handle_prof_set_print, - "prof_set_print mode Sets print mode (0:simple, 1:full infos)"}, - { "prof_start", "profile", fluid_handle_prof_start, - "prof_start [n_prof [dur]] Starts n_prof measures of duration(ms) each"} + { + "profile", "profile", fluid_handle_profile, + "profile Prints default parameters used by prof_start" + }, + { + "prof_set_notes", "profile", fluid_handle_prof_set_notes, + "prof_set_notes nbr [bank prog] Sets notes number generated by prof_start" + }, + { + "prof_set_print", "profile", fluid_handle_prof_set_print, + "prof_set_print mode Sets print mode (0:simple, 1:full infos)" + }, + { + "prof_start", "profile", fluid_handle_prof_start, + "prof_start [n_prof [dur]] Starts n_prof measures of duration(ms) each" + } #endif }; @@ -252,24 +401,26 @@ static const fluid_cmd_t fluid_commands[] = { * 1 if 'cmd' is a comment or is empty and -2 if quit was issued */ int -fluid_command(fluid_cmd_handler_t* handler, const char *cmd, fluid_ostream_t out) +fluid_command(fluid_cmd_handler_t *handler, const char *cmd, fluid_ostream_t out) { - int result, num_tokens = 0; - char** tokens = NULL; + int result, num_tokens = 0; + char **tokens = NULL; - if (cmd[0] == '#' || cmd[0] == '\0') { - return 1; - } + if(cmd[0] == '#' || cmd[0] == '\0') + { + return 1; + } - if (!g_shell_parse_argv(cmd, &num_tokens, &tokens, NULL)) { - fluid_ostream_printf(out, "Error parsing command\n"); - return FLUID_FAILED; - } + if(!g_shell_parse_argv(cmd, &num_tokens, &tokens, NULL)) + { + fluid_ostream_printf(out, "Error parsing command\n"); + return FLUID_FAILED; + } - result = fluid_cmd_handler_handle(handler, num_tokens, &tokens[0], out); - g_strfreev(tokens); + result = fluid_cmd_handler_handle(handler, num_tokens, &tokens[0], out); + g_strfreev(tokens); - return result; + return result; } /** @@ -283,42 +434,49 @@ fluid_command(fluid_cmd_handler_t* handler, const char *cmd, fluid_ostream_t out * @return New shell instance or NULL on error */ fluid_shell_t * -new_fluid_shell(fluid_settings_t* settings, fluid_cmd_handler_t* handler, +new_fluid_shell(fluid_settings_t *settings, fluid_cmd_handler_t *handler, fluid_istream_t in, fluid_ostream_t out, int thread) { - fluid_shell_t* shell = FLUID_NEW(fluid_shell_t); - if (shell == NULL) { - FLUID_LOG (FLUID_PANIC, "Out of memory"); - return NULL; - } + fluid_shell_t *shell = FLUID_NEW(fluid_shell_t); - - fluid_shell_init(shell, settings, handler, in, out); - - if (thread) { - shell->thread = new_fluid_thread("shell", fluid_shell_run, shell, - 0, TRUE); - if (shell->thread == NULL) { - delete_fluid_shell(shell); - return NULL; + if(shell == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return NULL; } - } else { - shell->thread = NULL; - fluid_shell_run(shell); - } - return shell; + + fluid_shell_init(shell, settings, handler, in, out); + + if(thread) + { + shell->thread = new_fluid_thread("shell", fluid_shell_run, shell, + 0, TRUE); + + if(shell->thread == NULL) + { + delete_fluid_shell(shell); + return NULL; + } + } + else + { + shell->thread = NULL; + fluid_shell_run(shell); + } + + return shell; } static void -fluid_shell_init(fluid_shell_t* shell, - fluid_settings_t* settings, fluid_cmd_handler_t* handler, - fluid_istream_t in, fluid_ostream_t out) +fluid_shell_init(fluid_shell_t *shell, + fluid_settings_t *settings, fluid_cmd_handler_t *handler, + fluid_istream_t in, fluid_ostream_t out) { - shell->settings = settings; - shell->handler = handler; - shell->in = in; - shell->out = out; + shell->settings = settings; + shell->handler = handler; + shell->in = in; + shell->out = out; } /** @@ -326,70 +484,84 @@ fluid_shell_init(fluid_shell_t* shell, * @param shell Command shell instance */ void -delete_fluid_shell(fluid_shell_t* shell) +delete_fluid_shell(fluid_shell_t *shell) { fluid_return_if_fail(shell != NULL); - - if (shell->thread != NULL) { - delete_fluid_thread(shell->thread); - } - FLUID_FREE(shell); + if(shell->thread != NULL) + { + delete_fluid_thread(shell->thread); + } + + FLUID_FREE(shell); } static fluid_thread_return_t -fluid_shell_run(void* data) +fluid_shell_run(void *data) { - fluid_shell_t* shell = (fluid_shell_t*)data; - char workline[FLUID_WORKLINELENGTH]; - char* prompt = NULL; - int cont = 1; - int errors = FALSE; - int n; + fluid_shell_t *shell = (fluid_shell_t *)data; + char workline[FLUID_WORKLINELENGTH]; + char *prompt = NULL; + int cont = 1; + int errors = FALSE; + int n; - if (shell->settings) - fluid_settings_dupstr(shell->settings, "shell.prompt", &prompt); /* ++ alloc prompt */ - - /* handle user input */ - while (cont) { - - n = fluid_istream_readline(shell->in, shell->out, prompt ? prompt : "", workline, FLUID_WORKLINELENGTH); - - if (n < 0) { - break; + if(shell->settings) + { + fluid_settings_dupstr(shell->settings, "shell.prompt", &prompt); /* ++ alloc prompt */ } + /* handle user input */ + while(cont) + { + + n = fluid_istream_readline(shell->in, shell->out, prompt ? prompt : "", workline, FLUID_WORKLINELENGTH); + + if(n < 0) + { + break; + } + #if WITH_READLINE - if (shell->in == fluid_get_stdin()) { - add_history(workline); - } + + if(shell->in == fluid_get_stdin()) + { + add_history(workline); + } + #endif - /* handle the command */ - switch (fluid_command(shell->handler, workline, shell->out)) { + /* handle the command */ + switch(fluid_command(shell->handler, workline, shell->out)) + { - case 1: /* empty line or comment */ - break; + case 1: /* empty line or comment */ + break; - case FLUID_FAILED: /* erronous command */ - errors = TRUE; - case FLUID_OK: /* valid command */ - break; + case FLUID_FAILED: /* erronous command */ + errors = TRUE; - case -2: /* quit */ - cont = 0; - break; + case FLUID_OK: /* valid command */ + break; + + case -2: /* quit */ + cont = 0; + break; + } + + if(n == 0) + { + break; + } } - if (n == 0) { - break; + if(prompt) + { + FLUID_FREE(prompt); /* -- free prompt */ } - } - if (prompt) FLUID_FREE (prompt); /* -- free prompt */ - - /* return FLUID_THREAD_RETURN_VALUE on success, something else on failure */ - return errors ? (fluid_thread_return_t)(-1) : FLUID_THREAD_RETURN_VALUE; + /* return FLUID_THREAD_RETURN_VALUE on success, something else on failure */ + return errors ? (fluid_thread_return_t)(-1) : FLUID_THREAD_RETURN_VALUE; } /** @@ -399,11 +571,11 @@ fluid_shell_run(void* data) * @param handler Command handler callback */ void -fluid_usershell(fluid_settings_t* settings, fluid_cmd_handler_t* handler) +fluid_usershell(fluid_settings_t *settings, fluid_cmd_handler_t *handler) { - fluid_shell_t shell; - fluid_shell_init(&shell, settings, handler, fluid_get_stdin(), fluid_get_stdout()); - fluid_shell_run(&shell); + fluid_shell_t shell; + fluid_shell_init(&shell, settings, handler, fluid_get_stdin(), fluid_get_stdout()); + fluid_shell_run(&shell); } /** @@ -413,30 +585,33 @@ fluid_usershell(fluid_settings_t* settings, fluid_cmd_handler_t* handler) * @return 0 on success, a negative value on error */ int -fluid_source(fluid_cmd_handler_t* handler, const char *filename) +fluid_source(fluid_cmd_handler_t *handler, const char *filename) { - int file; - fluid_shell_t shell; - int result; + int file; + fluid_shell_t shell; + int result; #ifdef WIN32 - file = _open(filename, _O_RDONLY); + file = _open(filename, _O_RDONLY); #else - file = open(filename, O_RDONLY); + file = open(filename, O_RDONLY); #endif - if (file < 0) { - return file; - } - fluid_shell_init(&shell, NULL, handler, file, fluid_get_stdout()); - result = (fluid_shell_run(&shell) == FLUID_THREAD_RETURN_VALUE) ? 0 : -1; + + if(file < 0) + { + return file; + } + + fluid_shell_init(&shell, NULL, handler, file, fluid_get_stdout()); + result = (fluid_shell_run(&shell) == FLUID_THREAD_RETURN_VALUE) ? 0 : -1; #ifdef WIN32 - _close(file); + _close(file); #else - close(file); + close(file); #endif - return result; + return result; } /** @@ -445,19 +620,24 @@ fluid_source(fluid_cmd_handler_t* handler, const char *filename) * @param len Length of \a buf * @return Returns \a buf pointer or NULL if no user command file for this system type. */ -char* -fluid_get_userconf(char* buf, int len) +char * +fluid_get_userconf(char *buf, int len) { #if defined(WIN32) || defined(MACOS9) - return NULL; -#else - char* home = getenv("HOME"); - if (home == NULL) { return NULL; - } else { - FLUID_SNPRINTF (buf, len, "%s/.fluidsynth", home); - return buf; - } +#else + char *home = getenv("HOME"); + + if(home == NULL) + { + return NULL; + } + else + { + FLUID_SNPRINTF(buf, len, "%s/.fluidsynth", home); + return buf; + } + #endif } @@ -467,14 +647,14 @@ fluid_get_userconf(char* buf, int len) * @param len Length of \a buf * @return Returns \a buf pointer or NULL if no system command file for this system type. */ -char* -fluid_get_sysconf(char* buf, int len) +char * +fluid_get_sysconf(char *buf, int len) { #if defined(WIN32) || defined(MACOS9) - return NULL; + return NULL; #else - FLUID_SNPRINTF (buf, len, "/etc/fluidsynth.conf"); - return buf; + FLUID_SNPRINTF(buf, len, "/etc/fluidsynth.conf"); + return buf; #endif } @@ -483,567 +663,704 @@ fluid_get_sysconf(char* buf, int len) * handlers */ int -fluid_handle_noteon(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_noteon(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - if (ac < 3) { - fluid_ostream_printf(out, "noteon: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1]) || !fluid_is_number(av[2])) { - fluid_ostream_printf(out, "noteon: invalid argument\n"); - return FLUID_FAILED; - } - return fluid_synth_noteon(handler->synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); -} + FLUID_ENTRY_COMMAND(data); -int -fluid_handle_noteoff(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - if (ac < 2) { - fluid_ostream_printf(out, "noteoff: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1])) { - fluid_ostream_printf(out, "noteon: invalid argument\n"); - return FLUID_FAILED; - } - return fluid_synth_noteoff(handler->synth, atoi(av[0]), atoi(av[1])); -} - -int -fluid_handle_pitch_bend(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - if (ac < 2) { - fluid_ostream_printf(out, "pitch_bend: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1])) { - fluid_ostream_printf(out, "pitch_bend: invalid argument\n"); - return FLUID_FAILED; - } - return fluid_synth_pitch_bend(handler->synth, atoi(av[0]), atoi(av[1])); -} - -int -fluid_handle_pitch_bend_range(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - int channum; - int value; - if (ac < 2) { - fluid_ostream_printf(out, "pitch_bend_range: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1])) { - fluid_ostream_printf(out, "pitch_bend_range: invalid argument\n"); - return FLUID_FAILED; - } - channum = atoi(av[0]); - value = atoi(av[1]); - fluid_channel_set_pitch_wheel_sensitivity(handler->synth->channel[channum], value); - return FLUID_OK; -} - -int -fluid_handle_cc(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - if (ac < 3) { - fluid_ostream_printf(out, "cc: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1]) || !fluid_is_number(av[2])) { - fluid_ostream_printf(out, "cc: invalid argument\n"); - return FLUID_FAILED; - } - return fluid_synth_cc(handler->synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); -} - -int -fluid_handle_prog(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - if (ac < 2) { - fluid_ostream_printf(out, "prog: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1])) { - fluid_ostream_printf(out, "prog: invalid argument\n"); - return FLUID_FAILED; - } - return fluid_synth_program_change(handler->synth, atoi(av[0]), atoi(av[1])); -} - -int -fluid_handle_select(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - int sfont_id; - int chan; - int bank; - int prog; - - if (ac < 4) { - fluid_ostream_printf(out, "preset: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1]) - || !fluid_is_number(av[2]) || !fluid_is_number(av[3])) { - fluid_ostream_printf(out, "preset: invalid argument\n"); - return FLUID_FAILED; - } - - 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(handler->synth, chan, sfont_id, bank, prog); - } else { - if (fluid_synth_bank_select(handler->synth, chan, bank) == FLUID_OK) { - return fluid_synth_program_change(handler->synth, chan, prog); + if(ac < 3) + { + fluid_ostream_printf(out, "noteon: too few arguments\n"); + return FLUID_FAILED; } - return FLUID_FAILED; - } + + if(!fluid_is_number(av[0]) || !fluid_is_number(av[1]) || !fluid_is_number(av[2])) + { + fluid_ostream_printf(out, "noteon: invalid argument\n"); + return FLUID_FAILED; + } + + return fluid_synth_noteon(handler->synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); } int -fluid_handle_inst(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_noteoff(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int font; - fluid_sfont_t* sfont; - fluid_preset_t* preset; - int offset; + FLUID_ENTRY_COMMAND(data); - if (ac < 1) { - fluid_ostream_printf(out, "inst: too few arguments\n"); - return FLUID_FAILED; - } + if(ac < 2) + { + fluid_ostream_printf(out, "noteoff: too few arguments\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "inst: invalid argument\n"); - return FLUID_FAILED; - } + if(!fluid_is_number(av[0]) || !fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "noteon: invalid argument\n"); + return FLUID_FAILED; + } - font = atoi(av[0]); - - sfont = fluid_synth_get_sfont_by_id(handler->synth, font); - offset = fluid_synth_get_bank_offset(handler->synth, font); - - if (sfont == NULL) { - fluid_ostream_printf(out, "inst: invalid font number\n"); - return FLUID_FAILED; - } - - fluid_sfont_iteration_start(sfont); - - while ((preset = fluid_sfont_iteration_next(sfont)) != NULL) { - fluid_ostream_printf(out, "%03d-%03d %s\n", - fluid_preset_get_banknum(preset) + offset, - fluid_preset_get_num(preset), - fluid_preset_get_name(preset)); - } - - return FLUID_OK; -} - - -int -fluid_handle_channels(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - fluid_preset_t* preset; - int verbose = 0; - int i; - - if (ac > 0 && FLUID_STRCMP( av[0], "-verbose") == 0) verbose = 1; - - for (i = 0; i < fluid_synth_count_midi_channels(handler->synth); i++) { - preset = fluid_synth_get_channel_preset(handler->synth, i); - if (preset == NULL) fluid_ostream_printf(out, "chan %d, no preset\n", i); - else if (!verbose) fluid_ostream_printf(out, "chan %d, %s\n", i, fluid_preset_get_name(preset)); - else fluid_ostream_printf(out, "chan %d, sfont %d, bank %d, preset %d, %s\n", i, - fluid_sfont_get_id( preset->sfont), - fluid_preset_get_banknum(preset), - fluid_preset_get_num(preset), - fluid_preset_get_name(preset)); - } - - return FLUID_OK; + return fluid_synth_noteoff(handler->synth, atoi(av[0]), atoi(av[1])); } int -fluid_handle_load(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_pitch_bend(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - char buf[1024]; - int id; - int reset = 1; - int offset = 0; + FLUID_ENTRY_COMMAND(data); - if (ac < 1) { - fluid_ostream_printf(out, "load: too few arguments\n"); - return FLUID_FAILED; - } - if (ac == 2) { - reset = atoi(av[1]); - } - if (ac == 3) { - offset = atoi(av[2]); - } + if(ac < 2) + { + fluid_ostream_printf(out, "pitch_bend: too few arguments\n"); + return FLUID_FAILED; + } - /* Load the SoundFont without resetting the programs. The reset will - * be done later (if requested). */ - id = fluid_synth_sfload(handler->synth, fluid_expand_path(av[0], buf, 1024), 0); + if(!fluid_is_number(av[0]) || !fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "pitch_bend: invalid argument\n"); + return FLUID_FAILED; + } - if (id == -1) { - fluid_ostream_printf(out, "failed to load the SoundFont\n"); - return FLUID_FAILED; - } else { - fluid_ostream_printf(out, "loaded SoundFont has ID %d\n", id); - } - - if (offset) { - fluid_synth_set_bank_offset(handler->synth, id, offset); - } - - /* The reset should be done after the offset is set. */ - if (reset) { - fluid_synth_program_reset(handler->synth); - } - - return FLUID_OK; + return fluid_synth_pitch_bend(handler->synth, atoi(av[0]), atoi(av[1])); } int -fluid_handle_unload(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_pitch_bend_range(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int reset = 1; - if (ac < 1) { - fluid_ostream_printf(out, "unload: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "unload: expected a number as argument\n"); - return FLUID_FAILED; - } - if (ac == 2) { - reset = atoi(av[1]); - } - if (fluid_synth_sfunload(handler->synth, atoi(av[0]), reset) != 0) { - fluid_ostream_printf(out, "failed to unload the SoundFont\n"); - return FLUID_FAILED; - } - return FLUID_OK; -} + FLUID_ENTRY_COMMAND(data); + int channum; + int value; -int -fluid_handle_reload(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - if (ac < 1) { - fluid_ostream_printf(out, "reload: too few arguments\n"); - return FLUID_FAILED; - } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "reload: expected a number as argument\n"); - return FLUID_FAILED; - } - if (fluid_synth_sfreload(handler->synth, atoi(av[0])) == -1) { - fluid_ostream_printf(out, "failed to reload the SoundFont\n"); - return FLUID_FAILED; - } - return FLUID_OK; -} + if(ac < 2) + { + fluid_ostream_printf(out, "pitch_bend_range: too few arguments\n"); + return FLUID_FAILED; + } + if(!fluid_is_number(av[0]) || !fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "pitch_bend_range: invalid argument\n"); + return FLUID_FAILED; + } -int -fluid_handle_fonts(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - int i; - fluid_sfont_t* sfont; - int num; - - num = fluid_synth_sfcount(handler->synth); - - if (num == 0) { - fluid_ostream_printf(out, "no SoundFont loaded (try load)\n"); + channum = atoi(av[0]); + value = atoi(av[1]); + fluid_channel_set_pitch_wheel_sensitivity(handler->synth->channel[channum], value); return FLUID_OK; - } +} - fluid_ostream_printf(out, "ID Name\n"); +int +fluid_handle_cc(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); - for (i = 0; i < num; i++) { - sfont = fluid_synth_get_sfont(handler->synth, i); - if (sfont) { - fluid_ostream_printf(out, "%2d %s\n", - fluid_sfont_get_id(sfont), - fluid_sfont_get_name(sfont)); + if(ac < 3) + { + fluid_ostream_printf(out, "cc: too few arguments\n"); + return FLUID_FAILED; } - else { - fluid_ostream_printf(out, "sfont is \"NULL\" for index %d\n", i); - } - } - return FLUID_OK; + if(!fluid_is_number(av[0]) || !fluid_is_number(av[1]) || !fluid_is_number(av[2])) + { + fluid_ostream_printf(out, "cc: invalid argument\n"); + return FLUID_FAILED; + } + + return fluid_synth_cc(handler->synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); +} + +int +fluid_handle_prog(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + + if(ac < 2) + { + fluid_ostream_printf(out, "prog: too few arguments\n"); + return FLUID_FAILED; + } + + if(!fluid_is_number(av[0]) || !fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "prog: invalid argument\n"); + return FLUID_FAILED; + } + + return fluid_synth_program_change(handler->synth, atoi(av[0]), atoi(av[1])); +} + +int +fluid_handle_select(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + int sfont_id; + int chan; + int bank; + int prog; + + if(ac < 4) + { + fluid_ostream_printf(out, "preset: too few arguments\n"); + return FLUID_FAILED; + } + + if(!fluid_is_number(av[0]) || !fluid_is_number(av[1]) + || !fluid_is_number(av[2]) || !fluid_is_number(av[3])) + { + fluid_ostream_printf(out, "preset: invalid argument\n"); + return FLUID_FAILED; + } + + 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(handler->synth, chan, sfont_id, bank, prog); + } + else + { + if(fluid_synth_bank_select(handler->synth, chan, bank) == FLUID_OK) + { + return fluid_synth_program_change(handler->synth, chan, prog); + } + + return FLUID_FAILED; + } +} + +int +fluid_handle_inst(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + int font; + fluid_sfont_t *sfont; + fluid_preset_t *preset; + int offset; + + if(ac < 1) + { + fluid_ostream_printf(out, "inst: too few arguments\n"); + return FLUID_FAILED; + } + + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "inst: invalid argument\n"); + return FLUID_FAILED; + } + + font = atoi(av[0]); + + sfont = fluid_synth_get_sfont_by_id(handler->synth, font); + offset = fluid_synth_get_bank_offset(handler->synth, font); + + if(sfont == NULL) + { + fluid_ostream_printf(out, "inst: invalid font number\n"); + return FLUID_FAILED; + } + + fluid_sfont_iteration_start(sfont); + + while((preset = fluid_sfont_iteration_next(sfont)) != NULL) + { + fluid_ostream_printf(out, "%03d-%03d %s\n", + fluid_preset_get_banknum(preset) + offset, + fluid_preset_get_num(preset), + fluid_preset_get_name(preset)); + } + + return FLUID_OK; +} + + +int +fluid_handle_channels(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + fluid_preset_t *preset; + int verbose = 0; + int i; + + if(ac > 0 && FLUID_STRCMP(av[0], "-verbose") == 0) + { + verbose = 1; + } + + for(i = 0; i < fluid_synth_count_midi_channels(handler->synth); i++) + { + preset = fluid_synth_get_channel_preset(handler->synth, i); + + if(preset == NULL) + { + fluid_ostream_printf(out, "chan %d, no preset\n", i); + } + else if(!verbose) + { + fluid_ostream_printf(out, "chan %d, %s\n", i, fluid_preset_get_name(preset)); + } + else + { + fluid_ostream_printf(out, + "chan %d, sfont %d, bank %d, preset %d, %s\n", + i, + fluid_sfont_get_id(preset->sfont), + fluid_preset_get_banknum(preset), + fluid_preset_get_num(preset), + fluid_preset_get_name(preset)); + } + } + + return FLUID_OK; +} + +int +fluid_handle_load(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + char buf[1024]; + int id; + int reset = 1; + int offset = 0; + + if(ac < 1) + { + fluid_ostream_printf(out, "load: too few arguments\n"); + return FLUID_FAILED; + } + + if(ac == 2) + { + reset = atoi(av[1]); + } + + 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(handler->synth, fluid_expand_path(av[0], buf, 1024), 0); + + if(id == -1) + { + fluid_ostream_printf(out, "failed to load the SoundFont\n"); + return FLUID_FAILED; + } + else + { + fluid_ostream_printf(out, "loaded SoundFont has ID %d\n", id); + } + + if(offset) + { + fluid_synth_set_bank_offset(handler->synth, id, offset); + } + + /* The reset should be done after the offset is set. */ + if(reset) + { + fluid_synth_program_reset(handler->synth); + } + + return FLUID_OK; +} + +int +fluid_handle_unload(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + int reset = 1; + + if(ac < 1) + { + fluid_ostream_printf(out, "unload: too few arguments\n"); + return FLUID_FAILED; + } + + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "unload: expected a number as argument\n"); + return FLUID_FAILED; + } + + if(ac == 2) + { + reset = atoi(av[1]); + } + + if(fluid_synth_sfunload(handler->synth, atoi(av[0]), reset) != 0) + { + fluid_ostream_printf(out, "failed to unload the SoundFont\n"); + return FLUID_FAILED; + } + + return FLUID_OK; +} + +int +fluid_handle_reload(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + + if(ac < 1) + { + fluid_ostream_printf(out, "reload: too few arguments\n"); + return FLUID_FAILED; + } + + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "reload: expected a number as argument\n"); + return FLUID_FAILED; + } + + if(fluid_synth_sfreload(handler->synth, atoi(av[0])) == -1) + { + fluid_ostream_printf(out, "failed to reload the SoundFont\n"); + return FLUID_FAILED; + } + + return FLUID_OK; +} + + +int +fluid_handle_fonts(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + int i; + fluid_sfont_t *sfont; + int num; + + num = fluid_synth_sfcount(handler->synth); + + if(num == 0) + { + fluid_ostream_printf(out, "no SoundFont loaded (try load)\n"); + return FLUID_OK; + } + + fluid_ostream_printf(out, "ID Name\n"); + + for(i = 0; i < num; i++) + { + sfont = fluid_synth_get_sfont(handler->synth, i); + + if(sfont) + { + fluid_ostream_printf(out, "%2d %s\n", + fluid_sfont_get_id(sfont), + fluid_sfont_get_name(sfont)); + } + else + { + fluid_ostream_printf(out, "sfont is \"NULL\" for index %d\n", i); + } + } + + return FLUID_OK; } /* Purpose: * Response to 'rev_preset' command. * Load the values from a reverb preset into the reverb unit. */ int -fluid_handle_reverbpreset(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_reverbpreset(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int reverb_preset_number; - - fluid_ostream_printf(out, "rev_preset is deprecated and will be removed in a future release!\n"); - - if (ac < 1) { - fluid_ostream_printf(out, "rev_preset: too few arguments\n"); - return FLUID_FAILED; - } - reverb_preset_number = atoi(av[0]); - if (fluid_synth_set_reverb_preset(handler->synth, reverb_preset_number)!=FLUID_OK){ - fluid_ostream_printf(out, "rev_preset: Failed. Parameter out of range?\n"); - return FLUID_FAILED; - }; - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + int reverb_preset_number; + + fluid_ostream_printf(out, "rev_preset is deprecated and will be removed in a future release!\n"); + + if(ac < 1) + { + fluid_ostream_printf(out, "rev_preset: too few arguments\n"); + return FLUID_FAILED; + } + + reverb_preset_number = atoi(av[0]); + + if(fluid_synth_set_reverb_preset(handler->synth, reverb_preset_number) != FLUID_OK) + { + fluid_ostream_printf(out, "rev_preset: Failed. Parameter out of range?\n"); + return FLUID_FAILED; + }; + + return FLUID_OK; } /* Purpose: * Response to 'rev_setroomsize' command. * Load the new room size into the reverb unit. */ int -fluid_handle_reverbsetroomsize(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_reverbsetroomsize(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_real_t room_size; - - if (ac < 1) { - fluid_ostream_printf(out, "rev_setroomsize: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "rev_setroomsize is deprecated! Use 'set synth.reverb.room-size %s' instead.\n", av[0]); - - room_size = atof(av[0]); - if (room_size < 0){ - fluid_ostream_printf(out, "rev_setroomsize: Room size must be positive!\n"); - return FLUID_FAILED; - } - if (room_size > 1.0){ - fluid_ostream_printf(out, "rev_setroomsize: Room size too big!\n"); - return FLUID_FAILED; - } - fluid_synth_set_reverb_roomsize(handler->synth, room_size); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_real_t room_size; + + if(ac < 1) + { + fluid_ostream_printf(out, "rev_setroomsize: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "rev_setroomsize is deprecated! Use 'set synth.reverb.room-size %s' instead.\n", av[0]); + + room_size = atof(av[0]); + + if(room_size < 0) + { + fluid_ostream_printf(out, "rev_setroomsize: Room size must be positive!\n"); + return FLUID_FAILED; + } + + if(room_size > 1.0) + { + fluid_ostream_printf(out, "rev_setroomsize: Room size too big!\n"); + return FLUID_FAILED; + } + + fluid_synth_set_reverb_roomsize(handler->synth, room_size); + return FLUID_OK; } /* Purpose: * Response to 'rev_setdamp' command. * Load the new damp factor into the reverb unit. */ int -fluid_handle_reverbsetdamp(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_reverbsetdamp(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_real_t damp; - if (ac < 1) { - fluid_ostream_printf(out, "rev_setdamp: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "rev_setdamp is deprecated! Use 'set synth.reverb.damp %s' instead.\n", av[0]); - - damp = atof(av[0]); - if ((damp < 0.0f) || (damp > 1)){ - fluid_ostream_printf(out, "rev_setdamp: damp must be between 0 and 1!\n"); - return FLUID_FAILED; - } - fluid_synth_set_reverb_damp(handler->synth, damp); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_real_t damp; + + if(ac < 1) + { + fluid_ostream_printf(out, "rev_setdamp: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "rev_setdamp is deprecated! Use 'set synth.reverb.damp %s' instead.\n", av[0]); + + damp = atof(av[0]); + + if((damp < 0.0f) || (damp > 1)) + { + fluid_ostream_printf(out, "rev_setdamp: damp must be between 0 and 1!\n"); + return FLUID_FAILED; + } + + fluid_synth_set_reverb_damp(handler->synth, damp); + return FLUID_OK; } /* Purpose: * Response to 'rev_setwidth' command. * Load the new width into the reverb unit. */ int -fluid_handle_reverbsetwidth(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_reverbsetwidth(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_real_t width; - if (ac < 1) { - fluid_ostream_printf(out, "rev_setwidth: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "rev_setroomsize is deprecated! Use 'set synth.reverb.width %s' instead.\n", av[0]); - - width = atof(av[0]); - if ((width < 0) || (width > 100)){ - fluid_ostream_printf(out, "rev_setroomsize: Too wide! (0..100)\n"); - return FLUID_FAILED; - } - fluid_synth_set_reverb_width(handler->synth, width); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_real_t width; + + if(ac < 1) + { + fluid_ostream_printf(out, "rev_setwidth: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "rev_setroomsize is deprecated! Use 'set synth.reverb.width %s' instead.\n", av[0]); + + width = atof(av[0]); + + if((width < 0) || (width > 100)) + { + fluid_ostream_printf(out, "rev_setroomsize: Too wide! (0..100)\n"); + return FLUID_FAILED; + } + + fluid_synth_set_reverb_width(handler->synth, width); + return FLUID_OK; } /* Purpose: * Response to 'rev_setlevel' command. * Load the new level into the reverb unit. */ int -fluid_handle_reverbsetlevel(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_reverbsetlevel(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_real_t level; - if (ac < 1) { - fluid_ostream_printf(out, "rev_setlevel: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "rev_setlevel is deprecated! Use 'set synth.reverb.level %s' instead.\n", av[0]); - - level = atof(av[0]); - if (fabs(level) > 30){ - fluid_ostream_printf(out, "rev_setlevel: Value too high! (Value of 10 =+20 dB)\n"); - return FLUID_FAILED; - } - fluid_synth_set_reverb_level(handler->synth, level); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_real_t level; + + if(ac < 1) + { + fluid_ostream_printf(out, "rev_setlevel: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "rev_setlevel is deprecated! Use 'set synth.reverb.level %s' instead.\n", av[0]); + + level = atof(av[0]); + + if(fabs(level) > 30) + { + fluid_ostream_printf(out, "rev_setlevel: Value too high! (Value of 10 =+20 dB)\n"); + return FLUID_FAILED; + } + + fluid_synth_set_reverb_level(handler->synth, level); + return FLUID_OK; } /* Purpose: * Response to 'reverb' command. * Change the FLUID_REVERB flag in the synth */ int -fluid_handle_reverb(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_reverb(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - if (ac < 1) { - fluid_ostream_printf(out, "reverb: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "reverb is deprecated! Use 'set synth.reverb.active %s' instead.\n", av[0]); - - if ((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0)) { - fluid_synth_set_reverb_on(handler->synth,0); - } else if ((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0)) { - fluid_synth_set_reverb_on(handler->synth,1); - } else { - fluid_ostream_printf(out, "reverb: invalid arguments %s [0|1|on|off]", av[0]); - return FLUID_FAILED; - } + FLUID_ENTRY_COMMAND(data); - return FLUID_OK; + if(ac < 1) + { + fluid_ostream_printf(out, "reverb: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "reverb is deprecated! Use 'set synth.reverb.active %s' instead.\n", av[0]); + + if((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0)) + { + fluid_synth_set_reverb_on(handler->synth, 0); + } + else if((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0)) + { + fluid_synth_set_reverb_on(handler->synth, 1); + } + else + { + fluid_ostream_printf(out, "reverb: invalid arguments %s [0|1|on|off]", av[0]); + return FLUID_FAILED; + } + + return FLUID_OK; } /* Purpose: * Response to 'chorus_setnr' command */ int -fluid_handle_chorusnr(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_chorusnr(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int nr; - if (ac < 1) { - fluid_ostream_printf(out, "cho_set_nr: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "cho_set_nr is deprecated! Use 'set synth.chorus.nr %s' instead.\n", av[0]); - - nr = atoi(av[0]); - fluid_synth_set_chorus_nr(handler->synth, nr); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + int nr; + + if(ac < 1) + { + fluid_ostream_printf(out, "cho_set_nr: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "cho_set_nr is deprecated! Use 'set synth.chorus.nr %s' instead.\n", av[0]); + + nr = atoi(av[0]); + fluid_synth_set_chorus_nr(handler->synth, nr); + return FLUID_OK; } /* Purpose: * Response to 'chorus_setlevel' command */ int -fluid_handle_choruslevel(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_choruslevel(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_real_t level; - if (ac < 1) { - fluid_ostream_printf(out, "cho_set_level: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "cho_set_level is deprecated! Use 'set synth.chorus.level %s' instead.\n", av[0]); - - level = atof(av[0]); - fluid_synth_set_chorus_level(handler->synth, level); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_real_t level; + + if(ac < 1) + { + fluid_ostream_printf(out, "cho_set_level: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "cho_set_level is deprecated! Use 'set synth.chorus.level %s' instead.\n", av[0]); + + level = atof(av[0]); + fluid_synth_set_chorus_level(handler->synth, level); + return FLUID_OK; } /* Purpose: * Response to 'chorus_setspeed' command */ int -fluid_handle_chorusspeed(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_chorusspeed(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_real_t speed; - if (ac < 1) { - fluid_ostream_printf(out, "cho_set_speed: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "cho_set_speed is deprecated! Use 'set synth.chorus.speed %s' instead.\n", av[0]); - - speed = atof(av[0]); - fluid_synth_set_chorus_speed(handler->synth, speed); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_real_t speed; + + if(ac < 1) + { + fluid_ostream_printf(out, "cho_set_speed: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "cho_set_speed is deprecated! Use 'set synth.chorus.speed %s' instead.\n", av[0]); + + speed = atof(av[0]); + fluid_synth_set_chorus_speed(handler->synth, speed); + return FLUID_OK; } /* Purpose: * Response to 'chorus_setdepth' command */ int -fluid_handle_chorusdepth(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_chorusdepth(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_real_t depth; - if (ac < 1) { - fluid_ostream_printf(out, "cho_set_depth: too few arguments.\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "cho_set_depth is deprecated! Use 'set synth.chorus.depth %s' instead.\n", av[0]); - - depth = atof(av[0]); - fluid_synth_set_chorus_depth(handler->synth, depth); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_real_t depth; + + if(ac < 1) + { + fluid_ostream_printf(out, "cho_set_depth: too few arguments.\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "cho_set_depth is deprecated! Use 'set synth.chorus.depth %s' instead.\n", av[0]); + + depth = atof(av[0]); + fluid_synth_set_chorus_depth(handler->synth, depth); + return FLUID_OK; } int -fluid_handle_chorus(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_chorus(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - if (ac < 1) { - fluid_ostream_printf(out, "chorus: too few arguments\n"); - return FLUID_FAILED; - } - - fluid_ostream_printf(out, "chorus is deprecated! Use 'set synth.chorus.active %s' instead.\n", av[0]); - - if ((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0)) { - fluid_synth_set_chorus_on(handler->synth,0); - } else if ((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0)) { - fluid_synth_set_chorus_on(handler->synth,1); - } else { - fluid_ostream_printf(out, "chorus: invalid arguments %s [0|1|on|off]", av[0]); - return FLUID_FAILED; - } + FLUID_ENTRY_COMMAND(data); - return FLUID_OK; + if(ac < 1) + { + fluid_ostream_printf(out, "chorus: too few arguments\n"); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "chorus is deprecated! Use 'set synth.chorus.active %s' instead.\n", av[0]); + + if((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0)) + { + fluid_synth_set_chorus_on(handler->synth, 0); + } + else if((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0)) + { + fluid_synth_set_chorus_on(handler->synth, 1); + } + else + { + fluid_ostream_printf(out, "chorus: invalid arguments %s [0|1|on|off]", av[0]); + return FLUID_FAILED; + } + + return FLUID_OK; } /* Purpose: @@ -1052,16 +1369,17 @@ fluid_handle_chorus(void* data, int ac, char** av, fluid_ostream_t out) * It can signal for example, that a list of commands has been processed. */ int -fluid_handle_echo(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_echo(void *data, int ac, char **av, fluid_ostream_t out) { - if (ac < 1) { - fluid_ostream_printf(out, "echo: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 1) + { + fluid_ostream_printf(out, "echo: too few arguments.\n"); + return FLUID_FAILED; + } - fluid_ostream_printf(out, "%s\n",av[0]); + fluid_ostream_printf(out, "%s\n", av[0]); - return FLUID_OK; + return FLUID_OK; } /* Purpose: @@ -1071,718 +1389,869 @@ fluid_handle_echo(void* data, int ac, char** av, fluid_ostream_t out) * in a command file. */ int -fluid_handle_sleep(void *data, int ac, char** av, fluid_ostream_t out) +fluid_handle_sleep(void *data, int ac, char **av, fluid_ostream_t out) { - if (ac < 1) { - fluid_ostream_printf(out, "sleep: too few arguments.\n"); - return -1; - } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "sleep: argument should be a number in ms.\n"); - return -1; - } - fluid_msleep(atoi(av[0])); /* delay in milliseconds */ + if(ac < 1) + { + fluid_ostream_printf(out, "sleep: too few arguments.\n"); + return -1; + } - return 0; + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "sleep: argument should be a number in ms.\n"); + return -1; + } + + fluid_msleep(atoi(av[0])); /* delay in milliseconds */ + + return 0; } int -fluid_handle_source(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_source(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - if (ac < 1) { - fluid_ostream_printf(out, "source: too few arguments.\n"); - return FLUID_FAILED; - } + FLUID_ENTRY_COMMAND(data); - fluid_source(handler, av[0]); + if(ac < 1) + { + fluid_ostream_printf(out, "source: too few arguments.\n"); + return FLUID_FAILED; + } - return FLUID_OK; + fluid_source(handler, av[0]); + + return FLUID_OK; } /* Purpose: * Response to 'gain' command. */ int -fluid_handle_gain(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_gain(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - float gain; + FLUID_ENTRY_COMMAND(data); + float gain; - if (ac < 1) { - fluid_ostream_printf(out, "gain: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 1) + { + fluid_ostream_printf(out, "gain: too few arguments.\n"); + return FLUID_FAILED; + } - gain = atof(av[0]); + gain = atof(av[0]); - if ((gain < 0.0f) || (gain > 5.0f)) { - fluid_ostream_printf(out, "gain: value should be between '0' and '5'.\n"); - return FLUID_FAILED; - }; + if((gain < 0.0f) || (gain > 5.0f)) + { + fluid_ostream_printf(out, "gain: value should be between '0' and '5'.\n"); + return FLUID_FAILED; + }; - fluid_synth_set_gain(handler->synth, gain); + fluid_synth_set_gain(handler->synth, gain); - return FLUID_OK; + return FLUID_OK; } /* Response to voice_count command */ static int -fluid_handle_voice_count (void* data, int ac, char **av, - fluid_ostream_t out) +fluid_handle_voice_count(void *data, int ac, char **av, + fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_ostream_printf (out, "voice_count: %d\n", - fluid_synth_get_active_voice_count (handler->synth)); - return FLUID_OK; + FLUID_ENTRY_COMMAND(data); + fluid_ostream_printf(out, "voice_count: %d\n", + fluid_synth_get_active_voice_count(handler->synth)); + return FLUID_OK; } /* Purpose: * Response to 'interp' command. */ int -fluid_handle_interp(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_interp(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int interp; - int chan=-1; /* -1: Set all channels */ + FLUID_ENTRY_COMMAND(data); + int interp; + int chan = -1; /* -1: Set all channels */ - if (ac < 1) { - fluid_ostream_printf(out, "interp: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 1) + { + fluid_ostream_printf(out, "interp: too few arguments.\n"); + return FLUID_FAILED; + } - interp = atoi(av[0]); + interp = atoi(av[0]); - if ((interp < 0) || (interp > FLUID_INTERP_HIGHEST)) { - fluid_ostream_printf(out, "interp: Bad value\n"); - return FLUID_FAILED; - }; + if((interp < 0) || (interp > FLUID_INTERP_HIGHEST)) + { + fluid_ostream_printf(out, "interp: Bad value\n"); + return FLUID_FAILED; + }; - fluid_synth_set_interp_method(handler->synth, chan, interp); + fluid_synth_set_interp_method(handler->synth, chan, interp); - return FLUID_OK; + return FLUID_OK; } /* Purpose: * Response to 'interp' command. */ int -fluid_handle_interpc(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_interpc(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int interp; - int chan; + FLUID_ENTRY_COMMAND(data); + int interp; + int chan; - if (ac < 2) { - fluid_ostream_printf(out, "interpc: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 2) + { + fluid_ostream_printf(out, "interpc: too few arguments.\n"); + return FLUID_FAILED; + } - chan = atoi(av[0]); - interp = atoi(av[1]); + chan = atoi(av[0]); + interp = atoi(av[1]); - if ((chan < 0) || (chan >= fluid_synth_count_midi_channels(handler->synth))){ - fluid_ostream_printf(out, "interp: Bad value for channel number.\n"); - return FLUID_FAILED; - }; - if ((interp < 0) || (interp > FLUID_INTERP_HIGHEST)) { - fluid_ostream_printf(out, "interp: Bad value for interpolation method.\n"); - return FLUID_FAILED; - }; + if((chan < 0) || (chan >= fluid_synth_count_midi_channels(handler->synth))) + { + fluid_ostream_printf(out, "interp: Bad value for channel number.\n"); + return FLUID_FAILED; + }; - fluid_synth_set_interp_method(handler->synth, chan, interp); + if((interp < 0) || (interp > FLUID_INTERP_HIGHEST)) + { + fluid_ostream_printf(out, "interp: Bad value for interpolation method.\n"); + return FLUID_FAILED; + }; - return FLUID_OK; + fluid_synth_set_interp_method(handler->synth, chan, interp); + + return FLUID_OK; } int -fluid_handle_tuning(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_tuning(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - char *name; - int bank, prog; + FLUID_ENTRY_COMMAND(data); + char *name; + int bank, prog; - if (ac < 3) { - fluid_ostream_printf(out, "tuning: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 3) + { + fluid_ostream_printf(out, "tuning: too few arguments.\n"); + return FLUID_FAILED; + } - name = av[0]; + name = av[0]; - if (!fluid_is_number(av[1])) { - fluid_ostream_printf(out, "tuning: 2nd argument should be a number.\n"); - return FLUID_FAILED; - } - bank = atoi(av[1]); - if ((bank < 0) || (bank >= 128)){ - fluid_ostream_printf(out, "tuning: invalid bank number.\n"); - return FLUID_FAILED; - }; + if(!fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "tuning: 2nd argument should be a number.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[2])) { - fluid_ostream_printf(out, "tuning: 3rd argument should be a number.\n"); - return FLUID_FAILED; - } - prog = atoi(av[2]); - if ((prog < 0) || (prog >= 128)){ - fluid_ostream_printf(out, "tuning: invalid program number.\n"); - return FLUID_FAILED; - }; + bank = atoi(av[1]); - fluid_synth_activate_key_tuning(handler->synth, bank, prog, name, NULL, FALSE); + if((bank < 0) || (bank >= 128)) + { + fluid_ostream_printf(out, "tuning: invalid bank number.\n"); + return FLUID_FAILED; + }; - return FLUID_OK; + if(!fluid_is_number(av[2])) + { + fluid_ostream_printf(out, "tuning: 3rd argument should be a number.\n"); + return FLUID_FAILED; + } + + prog = atoi(av[2]); + + if((prog < 0) || (prog >= 128)) + { + fluid_ostream_printf(out, "tuning: invalid program number.\n"); + return FLUID_FAILED; + }; + + fluid_synth_activate_key_tuning(handler->synth, bank, prog, name, NULL, FALSE); + + return FLUID_OK; } int -fluid_handle_tune(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_tune(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int bank, prog, key; - double pitch; + FLUID_ENTRY_COMMAND(data); + int bank, prog, key; + double pitch; - if (ac < 4) { - fluid_ostream_printf(out, "tune: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 4) + { + fluid_ostream_printf(out, "tune: too few arguments.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); - return FLUID_FAILED; - } - bank = atoi(av[0]); - if ((bank < 0) || (bank >= 128)){ - fluid_ostream_printf(out, "tune: invalid bank number.\n"); - return FLUID_FAILED; - }; + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[1])) { - fluid_ostream_printf(out, "tune: 2nd argument should be a number.\n"); - return FLUID_FAILED; - } - prog = atoi(av[1]); - if ((prog < 0) || (prog >= 128)){ - fluid_ostream_printf(out, "tune: invalid program number.\n"); - return FLUID_FAILED; - }; + bank = atoi(av[0]); - if (!fluid_is_number(av[2])) { - fluid_ostream_printf(out, "tune: 3rd argument should be a number.\n"); - return FLUID_FAILED; - } - key = atoi(av[2]); - if ((key < 0) || (key >= 128)){ - fluid_ostream_printf(out, "tune: invalid key number.\n"); - return FLUID_FAILED; - }; + if((bank < 0) || (bank >= 128)) + { + fluid_ostream_printf(out, "tune: invalid bank number.\n"); + return FLUID_FAILED; + }; - pitch = atof(av[3]); - if (pitch < 0.0f) { - fluid_ostream_printf(out, "tune: invalid pitch.\n"); - return FLUID_FAILED; - }; + if(!fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "tune: 2nd argument should be a number.\n"); + return FLUID_FAILED; + } - fluid_synth_tune_notes(handler->synth, bank, prog, 1, &key, &pitch, 0); + prog = atoi(av[1]); - return FLUID_OK; + if((prog < 0) || (prog >= 128)) + { + fluid_ostream_printf(out, "tune: invalid program number.\n"); + return FLUID_FAILED; + }; + + if(!fluid_is_number(av[2])) + { + fluid_ostream_printf(out, "tune: 3rd argument should be a number.\n"); + return FLUID_FAILED; + } + + key = atoi(av[2]); + + if((key < 0) || (key >= 128)) + { + fluid_ostream_printf(out, "tune: invalid key number.\n"); + return FLUID_FAILED; + }; + + pitch = atof(av[3]); + + if(pitch < 0.0f) + { + fluid_ostream_printf(out, "tune: invalid pitch.\n"); + return FLUID_FAILED; + }; + + fluid_synth_tune_notes(handler->synth, bank, prog, 1, &key, &pitch, 0); + + return FLUID_OK; } int -fluid_handle_settuning(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_settuning(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int chan, bank, prog; + FLUID_ENTRY_COMMAND(data); + int chan, bank, prog; - if (ac < 3) { - fluid_ostream_printf(out, "settuning: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 3) + { + fluid_ostream_printf(out, "settuning: too few arguments.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); - return FLUID_FAILED; - } - chan = atoi(av[0]); - if ((chan < 0) || (chan >= fluid_synth_count_midi_channels(handler->synth))){ - fluid_ostream_printf(out, "tune: invalid channel number.\n"); - return FLUID_FAILED; - }; + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[1])) { - fluid_ostream_printf(out, "tuning: 2nd argument should be a number.\n"); - return FLUID_FAILED; - } - bank = atoi(av[1]); - if ((bank < 0) || (bank >= 128)){ - fluid_ostream_printf(out, "tuning: invalid bank number.\n"); - return FLUID_FAILED; - }; + chan = atoi(av[0]); - if (!fluid_is_number(av[2])) { - fluid_ostream_printf(out, "tuning: 3rd argument should be a number.\n"); - return FLUID_FAILED; - } - prog = atoi(av[2]); - if ((prog < 0) || (prog >= 128)){ - fluid_ostream_printf(out, "tuning: invalid program number.\n"); - return FLUID_FAILED; - }; + if((chan < 0) || (chan >= fluid_synth_count_midi_channels(handler->synth))) + { + fluid_ostream_printf(out, "tune: invalid channel number.\n"); + return FLUID_FAILED; + }; - fluid_synth_activate_tuning(handler->synth, chan, bank, prog, FALSE); + if(!fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "tuning: 2nd argument should be a number.\n"); + return FLUID_FAILED; + } - return FLUID_OK; + bank = atoi(av[1]); + + if((bank < 0) || (bank >= 128)) + { + fluid_ostream_printf(out, "tuning: invalid bank number.\n"); + return FLUID_FAILED; + }; + + if(!fluid_is_number(av[2])) + { + fluid_ostream_printf(out, "tuning: 3rd argument should be a number.\n"); + return FLUID_FAILED; + } + + prog = atoi(av[2]); + + if((prog < 0) || (prog >= 128)) + { + fluid_ostream_printf(out, "tuning: invalid program number.\n"); + return FLUID_FAILED; + }; + + fluid_synth_activate_tuning(handler->synth, chan, bank, prog, FALSE); + + return FLUID_OK; } int -fluid_handle_resettuning(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_resettuning(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int chan; + FLUID_ENTRY_COMMAND(data); + int chan; - if (ac < 1) { - fluid_ostream_printf(out, "resettuning: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 1) + { + fluid_ostream_printf(out, "resettuning: too few arguments.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); - return FLUID_FAILED; - } - chan = atoi(av[0]); - if ((chan < 0) || (chan >= fluid_synth_count_midi_channels(handler->synth))){ - fluid_ostream_printf(out, "tune: invalid channel number.\n"); - return FLUID_FAILED; - }; + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); + return FLUID_FAILED; + } - fluid_synth_deactivate_tuning(handler->synth, chan, FALSE); + chan = atoi(av[0]); - return FLUID_OK; + if((chan < 0) || (chan >= fluid_synth_count_midi_channels(handler->synth))) + { + fluid_ostream_printf(out, "tune: invalid channel number.\n"); + return FLUID_FAILED; + }; + + fluid_synth_deactivate_tuning(handler->synth, chan, FALSE); + + return FLUID_OK; } int -fluid_handle_tunings(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_tunings(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int bank, prog; - char name[256]; - int count = 0; + FLUID_ENTRY_COMMAND(data); + int bank, prog; + char name[256]; + int count = 0; - fluid_synth_tuning_iteration_start(handler->synth); + fluid_synth_tuning_iteration_start(handler->synth); - while (fluid_synth_tuning_iteration_next(handler->synth, &bank, &prog)) { - fluid_synth_tuning_dump(handler->synth, bank, prog, name, 256, NULL); - fluid_ostream_printf(out, "%03d-%03d %s\n", bank, prog, name); - count++; - } + while(fluid_synth_tuning_iteration_next(handler->synth, &bank, &prog)) + { + fluid_synth_tuning_dump(handler->synth, bank, prog, name, 256, NULL); + fluid_ostream_printf(out, "%03d-%03d %s\n", bank, prog, name); + count++; + } - if (count == 0) { - fluid_ostream_printf(out, "No tunings available\n"); - } + if(count == 0) + { + fluid_ostream_printf(out, "No tunings available\n"); + } - return FLUID_OK; + return FLUID_OK; } int -fluid_handle_dumptuning(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_dumptuning(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int bank, prog, i, res; - double pitch[128]; - char name[256]; + FLUID_ENTRY_COMMAND(data); + int bank, prog, i, res; + double pitch[128]; + char name[256]; - if (ac < 2) { - fluid_ostream_printf(out, "dumptuning: too few arguments.\n"); - return FLUID_FAILED; - } + if(ac < 2) + { + fluid_ostream_printf(out, "dumptuning: too few arguments.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[0])) { - fluid_ostream_printf(out, "dumptuning: 1st argument should be a number.\n"); - return FLUID_FAILED; - } - bank = atoi(av[0]); - if ((bank < 0) || (bank >= 128)){ - fluid_ostream_printf(out, "dumptuning: invalid bank number.\n"); - return FLUID_FAILED; - }; + if(!fluid_is_number(av[0])) + { + fluid_ostream_printf(out, "dumptuning: 1st argument should be a number.\n"); + return FLUID_FAILED; + } - if (!fluid_is_number(av[1])) { - fluid_ostream_printf(out, "dumptuning: 2nd argument should be a number.\n"); - return FLUID_FAILED; - } - prog = atoi(av[1]); - if ((prog < 0) || (prog >= 128)){ - fluid_ostream_printf(out, "dumptuning: invalid program number.\n"); - return FLUID_FAILED; - }; + bank = atoi(av[0]); - res = fluid_synth_tuning_dump(handler->synth, bank, prog, name, 256, pitch); - if (FLUID_OK != res) { - fluid_ostream_printf(out, "Tuning %03d-%03d does not exist.\n", bank, prog); - return FLUID_FAILED; - } + if((bank < 0) || (bank >= 128)) + { + fluid_ostream_printf(out, "dumptuning: invalid bank number.\n"); + return FLUID_FAILED; + }; - fluid_ostream_printf(out, "%03d-%03d %s:\n", bank, prog, name); + if(!fluid_is_number(av[1])) + { + fluid_ostream_printf(out, "dumptuning: 2nd argument should be a number.\n"); + return FLUID_FAILED; + } - for (i = 0; i < 128; i++) { - fluid_ostream_printf(out, "key %03d, pitch %5.2f\n", i, pitch[i]); - } + prog = atoi(av[1]); - return FLUID_OK; + if((prog < 0) || (prog >= 128)) + { + fluid_ostream_printf(out, "dumptuning: invalid program number.\n"); + return FLUID_FAILED; + }; + + res = fluid_synth_tuning_dump(handler->synth, bank, prog, name, 256, pitch); + + if(FLUID_OK != res) + { + fluid_ostream_printf(out, "Tuning %03d-%03d does not exist.\n", bank, prog); + return FLUID_FAILED; + } + + fluid_ostream_printf(out, "%03d-%03d %s:\n", bank, prog, name); + + for(i = 0; i < 128; i++) + { + fluid_ostream_printf(out, "key %03d, pitch %5.2f\n", i, pitch[i]); + } + + return FLUID_OK; } int -fluid_handle_set(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - int hints; - int ival; - int ret = FLUID_FAILED; + FLUID_ENTRY_COMMAND(data); + int hints; + int ival; + int ret = FLUID_FAILED; - if (ac < 2) { - fluid_ostream_printf(out, "set: Too few arguments.\n"); - return ret; - } + if(ac < 2) + { + fluid_ostream_printf(out, "set: Too few arguments.\n"); + return ret; + } - switch (fluid_settings_get_type (handler->synth->settings, av[0])) - { + switch(fluid_settings_get_type(handler->synth->settings, av[0])) + { case FLUID_NO_TYPE: - fluid_ostream_printf (out, "set: Parameter '%s' not found.\n", av[0]); - break; + fluid_ostream_printf(out, "set: Parameter '%s' not found.\n", av[0]); + break; + case FLUID_INT_TYPE: - if (fluid_settings_get_hints (handler->synth->settings, av[0], &hints) == FLUID_OK - && hints & FLUID_HINT_TOGGLED) - { - if (FLUID_STRCASECMP (av[1], "yes") == 0 - || FLUID_STRCASECMP (av[1], "true") == 0 - || FLUID_STRCASECMP (av[1], "t") == 0) - ival = 1; - else ival = atoi (av[1]); - } - else ival = atoi (av[1]); - - ret = fluid_settings_setint (handler->synth->settings, av[0], ival); - break; - case FLUID_NUM_TYPE: - ret = fluid_settings_setnum (handler->synth->settings, av[0], atof (av[1])); - break; - case FLUID_STR_TYPE: - ret = fluid_settings_setstr(handler->synth->settings, av[0], av[1]); - break; - case FLUID_SET_TYPE: - fluid_ostream_printf (out, "set: Parameter '%s' is a node.\n", av[0]); - return FLUID_FAILED; - } - - if(ret == FLUID_FAILED) - fluid_ostream_printf(out, "set: Value out of range.\n"); - - return ret; -} - -int -fluid_handle_get(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - if (ac < 1) { - fluid_ostream_printf(out, "get: too few arguments.\n"); - return FLUID_FAILED; - } - - switch (fluid_settings_get_type(fluid_synth_get_settings(handler->synth), av[0])) { - case FLUID_NO_TYPE: - fluid_ostream_printf(out, "get: no such setting '%s'.\n", av[0]); - return FLUID_FAILED; - - case FLUID_NUM_TYPE: { - double value; - fluid_settings_getnum(handler->synth->settings, av[0], &value); - fluid_ostream_printf(out, "%.3f\n", value); - break; - } - - case FLUID_INT_TYPE: { - int value; - fluid_settings_getint(handler->synth->settings, av[0], &value); - fluid_ostream_printf(out, "%d\n", value); - break; - } - - case FLUID_STR_TYPE: { - char* s; - fluid_settings_dupstr(handler->synth->settings, av[0], &s); /* ++ alloc string */ - fluid_ostream_printf(out, "%s\n", s ? s : "NULL"); - if (s) FLUID_FREE (s); /* -- free string */ - break; - } - - case FLUID_SET_TYPE: - fluid_ostream_printf(out, "%s is a node\n", av[0]); - break; - } - - return FLUID_OK; -} - -struct _fluid_handle_settings_data_t { - int len; - fluid_synth_t* synth; - fluid_ostream_t out; -}; - -static void fluid_handle_settings_iter1(void* data, const char* name, int type) -{ - struct _fluid_handle_settings_data_t* d = (struct _fluid_handle_settings_data_t*) data; - - int len = FLUID_STRLEN(name); - if (len > d->len) { - d->len = len; - } -} - -static void fluid_handle_settings_iter2(void* data, const char* name, int type) -{ - struct _fluid_handle_settings_data_t* d = (struct _fluid_handle_settings_data_t*) data; - - int len = FLUID_STRLEN(name); - fluid_ostream_printf(d->out, "%s", name); - while (len++ < d->len) { - fluid_ostream_printf(d->out, " "); - } - fluid_ostream_printf(d->out, " "); - - switch (fluid_settings_get_type(fluid_synth_get_settings(d->synth), name)) { - case FLUID_NUM_TYPE: { - double value; - fluid_settings_getnum(d->synth->settings, name, &value); - fluid_ostream_printf(d->out, "%.3f\n", value); - break; - } - - case FLUID_INT_TYPE: { - int value, hints; - fluid_settings_getint(d->synth->settings, name, &value); - - if(fluid_settings_get_hints (d->synth->settings, name, &hints) == FLUID_OK) - { - if (!(hints & FLUID_HINT_TOGGLED)) - fluid_ostream_printf(d->out, "%d\n", value); - else fluid_ostream_printf(d->out, "%s\n", value ? "True" : "False"); - } - break; - } - - case FLUID_STR_TYPE: { - char* s; - fluid_settings_dupstr(d->synth->settings, name, &s); /* ++ alloc string */ - fluid_ostream_printf(d->out, "%s\n", s ? s : "NULL"); - if (s) FLUID_FREE (s); /* -- free string */ - break; - } - } -} - -int -fluid_handle_settings(void* d, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(d); - struct _fluid_handle_settings_data_t data; - - data.len = 0; - data.synth = handler->synth; - data.out = out; - - fluid_settings_foreach(fluid_synth_get_settings(handler->synth), &data, fluid_handle_settings_iter1); - fluid_settings_foreach(fluid_synth_get_settings(handler->synth), &data, fluid_handle_settings_iter2); - return FLUID_OK; -} - - -struct _fluid_handle_option_data_t { - int first; - fluid_ostream_t out; -}; - -void fluid_handle_print_option(void* data, const char* name, const char* option) -{ - struct _fluid_handle_option_data_t* d = (struct _fluid_handle_option_data_t*) data; - - if (d->first) { - fluid_ostream_printf(d->out, "%s", option); - d->first = 0; - } else { - fluid_ostream_printf(d->out, ", %s", option); - } -} - -int -fluid_handle_info(void* d, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(d); - fluid_settings_t* settings = fluid_synth_get_settings(handler->synth); - struct _fluid_handle_option_data_t data; - - if (ac < 1) { - fluid_ostream_printf(out, "info: too few arguments.\n"); - return FLUID_FAILED; - } - - switch (fluid_settings_get_type(settings, av[0])) { - case FLUID_NO_TYPE: - fluid_ostream_printf(out, "info: no such setting '%s'.\n", av[0]); - return FLUID_FAILED; - - case FLUID_NUM_TYPE: { - double value, min, max, def; - if(fluid_settings_getnum_range(settings, av[0], &min, &max) == FLUID_OK - && fluid_settings_getnum(settings, av[0], &value) == FLUID_OK - && fluid_settings_getnum_default(settings, av[0], &def) == FLUID_OK) - { - fluid_ostream_printf(out, "%s:\n", av[0]); - fluid_ostream_printf(out, "Type: number\n"); - fluid_ostream_printf(out, "Value: %.3f\n", value); - fluid_ostream_printf(out, "Minimum value: %.3f\n", min); - fluid_ostream_printf(out, "Maximum value: %.3f\n", max); - fluid_ostream_printf(out, "Default value: %.3f\n", def); - fluid_ostream_printf(out, "Real-time: %s\n", - fluid_settings_is_realtime(settings, av[0])? "yes" : "no"); - } - else - { - fluid_ostream_printf(out, "An error occurred when processing %s\n", av[0]); - } - break; - } - - case FLUID_INT_TYPE: { - int value, min, max, def, hints; - - if(fluid_settings_getint_range(settings, av[0], &min, &max) == FLUID_OK - && fluid_settings_getint(settings, av[0], &value) == FLUID_OK - && fluid_settings_get_hints(settings, av[0], &hints) == FLUID_OK - && fluid_settings_getint_default (settings, av[0], &def) == FLUID_OK) - { - fluid_ostream_printf(out, "%s:\n", av[0]); - - if (!(hints & FLUID_HINT_TOGGLED)) + if(fluid_settings_get_hints(handler->synth->settings, av[0], &hints) == FLUID_OK + && hints & FLUID_HINT_TOGGLED) { - fluid_ostream_printf(out, "Type: integer\n"); - fluid_ostream_printf(out, "Value: %d\n", value); - fluid_ostream_printf(out, "Minimum value: %d\n", min); - fluid_ostream_printf(out, "Maximum value: %d\n", max); - fluid_ostream_printf(out, "Default value: %d\n", def); + if(FLUID_STRCASECMP(av[1], "yes") == 0 + || FLUID_STRCASECMP(av[1], "true") == 0 + || FLUID_STRCASECMP(av[1], "t") == 0) + { + ival = 1; + } + else + { + ival = atoi(av[1]); + } } else { - fluid_ostream_printf(out, "Type: boolean\n"); - fluid_ostream_printf(out, "Value: %s\n", value ? "True" : "False"); - fluid_ostream_printf(out, "Default value: %s\n", def ? "True" : "False"); + ival = atoi(av[1]); } - fluid_ostream_printf(out, "Real-time: %s\n", - fluid_settings_is_realtime(settings, av[0])? "yes" : "no"); + ret = fluid_settings_setint(handler->synth->settings, av[0], ival); + break; + + case FLUID_NUM_TYPE: + ret = fluid_settings_setnum(handler->synth->settings, av[0], atof(av[1])); + break; + + case FLUID_STR_TYPE: + ret = fluid_settings_setstr(handler->synth->settings, av[0], av[1]); + break; + + case FLUID_SET_TYPE: + fluid_ostream_printf(out, "set: Parameter '%s' is a node.\n", av[0]); + return FLUID_FAILED; + } + + if(ret == FLUID_FAILED) + { + fluid_ostream_printf(out, "set: Value out of range.\n"); + } + + return ret; +} + +int +fluid_handle_get(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + + if(ac < 1) + { + fluid_ostream_printf(out, "get: too few arguments.\n"); + return FLUID_FAILED; + } + + switch(fluid_settings_get_type(fluid_synth_get_settings(handler->synth), av[0])) + { + case FLUID_NO_TYPE: + fluid_ostream_printf(out, "get: no such setting '%s'.\n", av[0]); + return FLUID_FAILED; + + case FLUID_NUM_TYPE: + { + double value; + fluid_settings_getnum(handler->synth->settings, av[0], &value); + fluid_ostream_printf(out, "%.3f\n", value); + break; + } + + case FLUID_INT_TYPE: + { + int value; + fluid_settings_getint(handler->synth->settings, av[0], &value); + fluid_ostream_printf(out, "%d\n", value); + break; + } + + case FLUID_STR_TYPE: + { + char *s; + fluid_settings_dupstr(handler->synth->settings, av[0], &s); /* ++ alloc string */ + fluid_ostream_printf(out, "%s\n", s ? s : "NULL"); + + if(s) + { + FLUID_FREE(s); /* -- free string */ + } + + break; + } + + case FLUID_SET_TYPE: + fluid_ostream_printf(out, "%s is a node\n", av[0]); + break; + } + + return FLUID_OK; +} + +struct _fluid_handle_settings_data_t +{ + int len; + fluid_synth_t *synth; + fluid_ostream_t out; +}; + +static void fluid_handle_settings_iter1(void *data, const char *name, int type) +{ + struct _fluid_handle_settings_data_t *d = (struct _fluid_handle_settings_data_t *) data; + + int len = FLUID_STRLEN(name); + + if(len > d->len) + { + d->len = len; + } +} + +static void fluid_handle_settings_iter2(void *data, const char *name, int type) +{ + struct _fluid_handle_settings_data_t *d = (struct _fluid_handle_settings_data_t *) data; + + int len = FLUID_STRLEN(name); + fluid_ostream_printf(d->out, "%s", name); + + while(len++ < d->len) + { + fluid_ostream_printf(d->out, " "); + } + + fluid_ostream_printf(d->out, " "); + + switch(fluid_settings_get_type(fluid_synth_get_settings(d->synth), name)) + { + case FLUID_NUM_TYPE: + { + double value; + fluid_settings_getnum(d->synth->settings, name, &value); + fluid_ostream_printf(d->out, "%.3f\n", value); + break; + } + + case FLUID_INT_TYPE: + { + int value, hints; + fluid_settings_getint(d->synth->settings, name, &value); + + if(fluid_settings_get_hints(d->synth->settings, name, &hints) == FLUID_OK) + { + if(!(hints & FLUID_HINT_TOGGLED)) + { + fluid_ostream_printf(d->out, "%d\n", value); + } + else + { + fluid_ostream_printf(d->out, "%s\n", value ? "True" : "False"); + } + } + + break; + } + + case FLUID_STR_TYPE: + { + char *s; + fluid_settings_dupstr(d->synth->settings, name, &s); /* ++ alloc string */ + fluid_ostream_printf(d->out, "%s\n", s ? s : "NULL"); + + if(s) + { + FLUID_FREE(s); /* -- free string */ + } + + break; + } + } +} + +int +fluid_handle_settings(void *d, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(d); + struct _fluid_handle_settings_data_t data; + + data.len = 0; + data.synth = handler->synth; + data.out = out; + + fluid_settings_foreach(fluid_synth_get_settings(handler->synth), &data, fluid_handle_settings_iter1); + fluid_settings_foreach(fluid_synth_get_settings(handler->synth), &data, fluid_handle_settings_iter2); + return FLUID_OK; +} + + +struct _fluid_handle_option_data_t +{ + int first; + fluid_ostream_t out; +}; + +void fluid_handle_print_option(void *data, const char *name, const char *option) +{ + struct _fluid_handle_option_data_t *d = (struct _fluid_handle_option_data_t *) data; + + if(d->first) + { + fluid_ostream_printf(d->out, "%s", option); + d->first = 0; } else { - fluid_ostream_printf(out, "An error occurred when processing %s\n", av[0]); + fluid_ostream_printf(d->out, ", %s", option); } - break; - } +} - case FLUID_STR_TYPE: { - char *s; - fluid_settings_dupstr(settings, av[0], &s); /* ++ alloc string */ - fluid_ostream_printf(out, "%s:\n", av[0]); - fluid_ostream_printf(out, "Type: string\n"); - fluid_ostream_printf(out, "Value: %s\n", s ? s : "NULL"); - fluid_settings_getstr_default(settings, av[0], &s); - fluid_ostream_printf(out, "Default value: %s\n", s); +int +fluid_handle_info(void *d, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(d); + fluid_settings_t *settings = fluid_synth_get_settings(handler->synth); + struct _fluid_handle_option_data_t data; - if (s) FLUID_FREE (s); + if(ac < 1) + { + fluid_ostream_printf(out, "info: too few arguments.\n"); + return FLUID_FAILED; + } + + switch(fluid_settings_get_type(settings, av[0])) + { + case FLUID_NO_TYPE: + fluid_ostream_printf(out, "info: no such setting '%s'.\n", av[0]); + return FLUID_FAILED; + + case FLUID_NUM_TYPE: + { + double value, min, max, def; + + if(fluid_settings_getnum_range(settings, av[0], &min, &max) == FLUID_OK + && fluid_settings_getnum(settings, av[0], &value) == FLUID_OK + && fluid_settings_getnum_default(settings, av[0], &def) == FLUID_OK) + { + fluid_ostream_printf(out, "%s:\n", av[0]); + fluid_ostream_printf(out, "Type: number\n"); + fluid_ostream_printf(out, "Value: %.3f\n", value); + fluid_ostream_printf(out, "Minimum value: %.3f\n", min); + fluid_ostream_printf(out, "Maximum value: %.3f\n", max); + fluid_ostream_printf(out, "Default value: %.3f\n", def); + fluid_ostream_printf(out, "Real-time: %s\n", + fluid_settings_is_realtime(settings, av[0]) ? "yes" : "no"); + } + else + { + fluid_ostream_printf(out, "An error occurred when processing %s\n", av[0]); + } + + break; + } + + case FLUID_INT_TYPE: + { + int value, min, max, def, hints; + + if(fluid_settings_getint_range(settings, av[0], &min, &max) == FLUID_OK + && fluid_settings_getint(settings, av[0], &value) == FLUID_OK + && fluid_settings_get_hints(settings, av[0], &hints) == FLUID_OK + && fluid_settings_getint_default(settings, av[0], &def) == FLUID_OK) + { + fluid_ostream_printf(out, "%s:\n", av[0]); + + if(!(hints & FLUID_HINT_TOGGLED)) + { + fluid_ostream_printf(out, "Type: integer\n"); + fluid_ostream_printf(out, "Value: %d\n", value); + fluid_ostream_printf(out, "Minimum value: %d\n", min); + fluid_ostream_printf(out, "Maximum value: %d\n", max); + fluid_ostream_printf(out, "Default value: %d\n", def); + } + else + { + fluid_ostream_printf(out, "Type: boolean\n"); + fluid_ostream_printf(out, "Value: %s\n", value ? "True" : "False"); + fluid_ostream_printf(out, "Default value: %s\n", def ? "True" : "False"); + } + + fluid_ostream_printf(out, "Real-time: %s\n", + fluid_settings_is_realtime(settings, av[0]) ? "yes" : "no"); + } + else + { + fluid_ostream_printf(out, "An error occurred when processing %s\n", av[0]); + } + + break; + } + + case FLUID_STR_TYPE: + { + char *s; + fluid_settings_dupstr(settings, av[0], &s); /* ++ alloc string */ + fluid_ostream_printf(out, "%s:\n", av[0]); + fluid_ostream_printf(out, "Type: string\n"); + fluid_ostream_printf(out, "Value: %s\n", s ? s : "NULL"); + fluid_settings_getstr_default(settings, av[0], &s); + fluid_ostream_printf(out, "Default value: %s\n", s); + + if(s) + { + FLUID_FREE(s); + } + + data.out = out; + data.first = 1; + fluid_ostream_printf(out, "Options: "); + fluid_settings_foreach_option(settings, av[0], &data, fluid_handle_print_option); + fluid_ostream_printf(out, "\n"); + + fluid_ostream_printf(out, "Real-time: %s\n", + fluid_settings_is_realtime(settings, av[0]) ? "yes" : "no"); + break; + } + + case FLUID_SET_TYPE: + fluid_ostream_printf(out, "%s:\n", av[0]); + fluid_ostream_printf(out, "Type: node\n"); + break; + } + + return FLUID_OK; +} + +int +fluid_handle_reset(void *data, int ac, char **av, fluid_ostream_t out) +{ + FLUID_ENTRY_COMMAND(data); + fluid_synth_system_reset(handler->synth); + return FLUID_OK; +} + +int +fluid_handle_quit(void *data, int ac, char **av, fluid_ostream_t out) +{ + fluid_ostream_printf(out, "cheers!\n"); + return -2; +} + +int +fluid_handle_help(void *data, int ac, char **av, fluid_ostream_t out) +{ + /* Purpose: + * Prints the help text for the command line commands. + * Can be used as follows: + * - help + * - help (topic), where (topic) is 'general', 'chorus', etc. + * - help all + */ + char *topic = "help"; /* default, if no topic is given */ + int count = 0; + unsigned int i; - data.out = out; - data.first = 1; - fluid_ostream_printf(out, "Options: "); - fluid_settings_foreach_option (settings, av[0], &data, fluid_handle_print_option); fluid_ostream_printf(out, "\n"); - fluid_ostream_printf(out, "Real-time: %s\n", - fluid_settings_is_realtime(settings, av[0])? "yes" : "no"); - break; - } + /* 1st argument (optional): help topic */ + if(ac >= 1) + { + topic = av[0]; + } - case FLUID_SET_TYPE: - fluid_ostream_printf(out, "%s:\n", av[0]); - fluid_ostream_printf(out, "Type: node\n"); - break; - } + if(FLUID_STRCMP(topic, "help") == 0) + { + /* "help help": Print a list of all topics */ + fluid_ostream_printf(out, + "*** Help topics:***\n" + "help all (prints all topics)\n"); - return FLUID_OK; -} + for(i = 0; i < FLUID_N_ELEMENTS(fluid_commands); i++) + { + int listed_first_time = 1; + unsigned int ii; -int -fluid_handle_reset(void* data, int ac, char** av, fluid_ostream_t out) -{ - FLUID_ENTRY_COMMAND(data); - fluid_synth_system_reset(handler->synth); - return FLUID_OK; -} + for(ii = 0; ii < i; ii++) + { + if(FLUID_STRCMP(fluid_commands[i].topic, fluid_commands[ii].topic) == 0) + { + listed_first_time = 0; + }; /* if topic has already been listed */ + }; /* for all topics (inner loop) */ -int -fluid_handle_quit(void* data, int ac, char** av, fluid_ostream_t out) -{ - fluid_ostream_printf(out, "cheers!\n"); - return -2; -} + if(listed_first_time) + { + fluid_ostream_printf(out, "help %s\n", fluid_commands[i].topic); + }; + }; /* for all topics (outer loop) */ + } + else + { + /* help (arbitrary topic or "all") */ + for(i = 0; i < FLUID_N_ELEMENTS(fluid_commands); i++) + { + if(fluid_commands[i].help != NULL) + { + if(FLUID_STRCMP(topic, "all") == 0 || FLUID_STRCMP(topic, fluid_commands[i].topic) == 0) + { + fluid_ostream_printf(out, "%s\n", fluid_commands[i].help); + count++; + }; /* if it matches the topic */ + }; /* if help text exists */ + }; /* foreach command */ -int -fluid_handle_help(void* data, int ac, char** av, fluid_ostream_t out) -{ - /* Purpose: - * Prints the help text for the command line commands. - * Can be used as follows: - * - help - * - help (topic), where (topic) is 'general', 'chorus', etc. - * - help all - */ - char* topic = "help"; /* default, if no topic is given */ - int count = 0; - unsigned int i; - - fluid_ostream_printf(out, "\n"); - /* 1st argument (optional): help topic */ - if (ac >= 1) { - topic = av[0]; - } - if (FLUID_STRCMP(topic,"help") == 0){ - /* "help help": Print a list of all topics */ - fluid_ostream_printf(out, - "*** Help topics:***\n" - "help all (prints all topics)\n"); - for (i = 0; i < FLUID_N_ELEMENTS(fluid_commands); i++) { - int listed_first_time = 1; - unsigned int ii; - for (ii = 0; ii < i; ii++){ - if (FLUID_STRCMP(fluid_commands[i].topic, fluid_commands[ii].topic) == 0){ - listed_first_time = 0; - }; /* if topic has already been listed */ - }; /* for all topics (inner loop) */ - if (listed_first_time){ - fluid_ostream_printf(out, "help %s\n",fluid_commands[i].topic); - }; - }; /* for all topics (outer loop) */ - } else { - /* help (arbitrary topic or "all") */ - for (i = 0; i < FLUID_N_ELEMENTS(fluid_commands); i++) { - if (fluid_commands[i].help != NULL) { - if (FLUID_STRCMP(topic,"all") == 0 || FLUID_STRCMP(topic,fluid_commands[i].topic) == 0){ - fluid_ostream_printf(out, "%s\n", fluid_commands[i].help); - count++; - }; /* if it matches the topic */ - }; /* if help text exists */ - }; /* foreach command */ - if (count == 0){ - fluid_ostream_printf(out, "Unknown help topic. Try 'help help'.\n"); + if(count == 0) + { + fluid_ostream_printf(out, "Unknown help topic. Try 'help help'.\n"); + }; }; - }; - return FLUID_OK; + + return FLUID_OK; } #define CHECK_VALID_ROUTER(_router, _out) \ @@ -1792,187 +2261,213 @@ fluid_handle_help(void* data, int ac, char** av, fluid_ostream_t out) } /* Command handler for "router_clear" command */ -int fluid_handle_router_clear(void* data, int ac, char** av, fluid_ostream_t out) +int fluid_handle_router_clear(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_midi_router_t *router = handler->router; + FLUID_ENTRY_COMMAND(data); + fluid_midi_router_t *router = handler->router; - if (ac != 0) { - fluid_ostream_printf (out, "router_clear needs no arguments.\n"); - return FLUID_FAILED; - } + if(ac != 0) + { + fluid_ostream_printf(out, "router_clear needs no arguments.\n"); + return FLUID_FAILED; + } - CHECK_VALID_ROUTER (router, out); + CHECK_VALID_ROUTER(router, out); - fluid_midi_router_clear_rules (router); + fluid_midi_router_clear_rules(router); - return FLUID_OK; + return FLUID_OK; } /* Command handler for "router_default" command */ -int fluid_handle_router_default(void* data, int ac, char** av, fluid_ostream_t out) +int fluid_handle_router_default(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_midi_router_t *router = handler->router; + FLUID_ENTRY_COMMAND(data); + fluid_midi_router_t *router = handler->router; - if (ac != 0) { - fluid_ostream_printf(out, "router_default needs no arguments.\n"); - return FLUID_FAILED; - } + if(ac != 0) + { + fluid_ostream_printf(out, "router_default needs no arguments.\n"); + return FLUID_FAILED; + } - CHECK_VALID_ROUTER (router, out); + CHECK_VALID_ROUTER(router, out); - fluid_midi_router_set_default_rules (router); + fluid_midi_router_set_default_rules(router); - return FLUID_OK; + return FLUID_OK; } /* Command handler for "router_begin" command */ -int fluid_handle_router_begin(void* data, int ac, char** av, fluid_ostream_t out) +int fluid_handle_router_begin(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_midi_router_t* router = handler->router; + FLUID_ENTRY_COMMAND(data); + fluid_midi_router_t *router = handler->router; - if (ac != 1) { - fluid_ostream_printf (out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n"); - return FLUID_FAILED; - } + if(ac != 1) + { + fluid_ostream_printf(out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n"); + return FLUID_FAILED; + } - CHECK_VALID_ROUTER (router, out); + CHECK_VALID_ROUTER(router, out); - if (FLUID_STRCMP (av[0], "note") == 0) - handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_NOTE; - else if (FLUID_STRCMP (av[0], "cc") == 0) - handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CC; - else if (FLUID_STRCMP (av[0], "prog") == 0) - handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PROG_CHANGE; - else if (FLUID_STRCMP (av[0], "pbend") == 0) - handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PITCH_BEND; - else if (FLUID_STRCMP (av[0], "cpress") == 0) - handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE; - else if (FLUID_STRCMP (av[0], "kpress") == 0) - handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE; - else - { - fluid_ostream_printf (out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n"); - return FLUID_FAILED; - } + if(FLUID_STRCMP(av[0], "note") == 0) + { + handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_NOTE; + } + else if(FLUID_STRCMP(av[0], "cc") == 0) + { + handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CC; + } + else if(FLUID_STRCMP(av[0], "prog") == 0) + { + handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PROG_CHANGE; + } + else if(FLUID_STRCMP(av[0], "pbend") == 0) + { + handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PITCH_BEND; + } + else if(FLUID_STRCMP(av[0], "cpress") == 0) + { + handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE; + } + else if(FLUID_STRCMP(av[0], "kpress") == 0) + { + handler->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE; + } + else + { + fluid_ostream_printf(out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n"); + return FLUID_FAILED; + } - if (handler->cmd_rule) - delete_fluid_midi_router_rule (handler->cmd_rule); + if(handler->cmd_rule) + { + delete_fluid_midi_router_rule(handler->cmd_rule); + } - handler->cmd_rule = new_fluid_midi_router_rule (); + handler->cmd_rule = new_fluid_midi_router_rule(); - if (!handler->cmd_rule) - return FLUID_FAILED; + if(!handler->cmd_rule) + { + return FLUID_FAILED; + } - return FLUID_OK; + return FLUID_OK; } /* Command handler for "router_end" command */ -int fluid_handle_router_end(void* data, int ac, char** av, fluid_ostream_t out) +int fluid_handle_router_end(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_midi_router_t* router = handler->router; + FLUID_ENTRY_COMMAND(data); + fluid_midi_router_t *router = handler->router; - if (ac != 0) { - fluid_ostream_printf (out, "router_end needs no arguments.\n"); - return FLUID_FAILED; - } + if(ac != 0) + { + fluid_ostream_printf(out, "router_end needs no arguments.\n"); + return FLUID_FAILED; + } - CHECK_VALID_ROUTER (router, out); + CHECK_VALID_ROUTER(router, out); - if (!handler->cmd_rule) - { - fluid_ostream_printf (out, "No active router_begin command.\n"); - return FLUID_FAILED; - } + if(!handler->cmd_rule) + { + fluid_ostream_printf(out, "No active router_begin command.\n"); + return FLUID_FAILED; + } - /* Add the rule */ - if (fluid_midi_router_add_rule (router, handler->cmd_rule, handler->cmd_rule_type) != FLUID_OK) - delete_fluid_midi_router_rule (handler->cmd_rule); /* Free on failure */ + /* Add the rule */ + if(fluid_midi_router_add_rule(router, handler->cmd_rule, handler->cmd_rule_type) != FLUID_OK) + { + delete_fluid_midi_router_rule(handler->cmd_rule); /* Free on failure */ + } - handler->cmd_rule = NULL; + handler->cmd_rule = NULL; - return FLUID_OK; + return FLUID_OK; } /* Command handler for "router_chan" command */ -int fluid_handle_router_chan(void* data, int ac, char** av, fluid_ostream_t out) +int fluid_handle_router_chan(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_midi_router_t* router = handler->router; + FLUID_ENTRY_COMMAND(data); + fluid_midi_router_t *router = handler->router; - if (ac != 4) { - fluid_ostream_printf(out, "router_chan needs four args: min, max, mul, add."); - return FLUID_FAILED; - } + if(ac != 4) + { + fluid_ostream_printf(out, "router_chan needs four args: min, max, mul, add."); + return FLUID_FAILED; + } - CHECK_VALID_ROUTER (router, out); + CHECK_VALID_ROUTER(router, out); - if (!handler->cmd_rule) - { - fluid_ostream_printf (out, "No active router_begin command.\n"); - return FLUID_FAILED; - } + if(!handler->cmd_rule) + { + fluid_ostream_printf(out, "No active router_begin command.\n"); + return FLUID_FAILED; + } - fluid_midi_router_rule_set_chan (handler->cmd_rule, atoi (av[0]), atoi (av[1]), - atof (av[2]), atoi (av[3])); - return FLUID_OK; + fluid_midi_router_rule_set_chan(handler->cmd_rule, atoi(av[0]), atoi(av[1]), + atof(av[2]), atoi(av[3])); + return FLUID_OK; } /* Command handler for "router_par1" command */ -int fluid_handle_router_par1(void* data, int ac, char** av, fluid_ostream_t out) +int fluid_handle_router_par1(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_midi_router_t* router = handler->router; + FLUID_ENTRY_COMMAND(data); + fluid_midi_router_t *router = handler->router; - if (ac != 4) { - fluid_ostream_printf(out, "router_par1 needs four args: min, max, mul, add."); - return FLUID_FAILED; - } + if(ac != 4) + { + fluid_ostream_printf(out, "router_par1 needs four args: min, max, mul, add."); + return FLUID_FAILED; + } - CHECK_VALID_ROUTER (router, out); + CHECK_VALID_ROUTER(router, out); - if (!handler->cmd_rule) - { - fluid_ostream_printf (out, "No active router_begin command.\n"); - return FLUID_FAILED; - } + if(!handler->cmd_rule) + { + fluid_ostream_printf(out, "No active router_begin command.\n"); + return FLUID_FAILED; + } - fluid_midi_router_rule_set_param1 (handler->cmd_rule, atoi (av[0]), atoi (av[1]), - atof (av[2]), atoi (av[3])); - return FLUID_OK; + fluid_midi_router_rule_set_param1(handler->cmd_rule, atoi(av[0]), atoi(av[1]), + atof(av[2]), atoi(av[3])); + return FLUID_OK; } /* Command handler for "router_par2" command */ -int fluid_handle_router_par2(void* data, int ac, char** av, fluid_ostream_t out) +int fluid_handle_router_par2(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_midi_router_t* router = handler->router; + FLUID_ENTRY_COMMAND(data); + fluid_midi_router_t *router = handler->router; - if (ac != 4) { - fluid_ostream_printf(out, "router_par2 needs four args: min, max, mul, add."); - return FLUID_FAILED; - } + if(ac != 4) + { + fluid_ostream_printf(out, "router_par2 needs four args: min, max, mul, add."); + return FLUID_FAILED; + } - CHECK_VALID_ROUTER (router, out); + CHECK_VALID_ROUTER(router, out); - if (!handler->cmd_rule) - { - fluid_ostream_printf (out, "No active router_begin command.\n"); - return FLUID_FAILED; - } + if(!handler->cmd_rule) + { + fluid_ostream_printf(out, "No active router_begin command.\n"); + return FLUID_FAILED; + } - fluid_midi_router_rule_set_param2 (handler->cmd_rule, atoi (av[0]), atoi (av[1]), - atof (av[2]), atoi (av[3])); - return FLUID_OK; + fluid_midi_router_rule_set_param2(handler->cmd_rule, atoi(av[0]), atoi(av[1]), + atof(av[2]), atoi(av[3])); + return FLUID_OK; } /** commands Poly/mono mode *************************************************/ -static const char * mode_name[]={"poly omni on (0)","mono omni on (1)", - "poly omni off(2)","mono omni off(3)"}; +static const char *mode_name[] = {"poly omni on (0)", "mono omni on (1)", + "poly omni off(2)", "mono omni off(3)" + }; /* Prints result message for commands: basicchannels, resetbasicchannels. Prints all basic channels and print a warning if there is no basic channel. @@ -1980,43 +2475,47 @@ static const char * mode_name[]={"poly omni on (0)","mono omni on (1)", @param synth the synth instance. @param out output stream. */ -static int print_basic_channels(fluid_synth_t* synth, fluid_ostream_t out) +static int print_basic_channels(fluid_synth_t *synth, fluid_ostream_t out) { - static const char * warning_msg = "Warning: no basic channels. All MIDI channels are disabled.\n" - "Make use of setbasicchannels to set at least a default basic channel.\n"; - - int n_chan= synth->midi_channels; - int i , n= 0; - /* prints all basic channels */ - for (i =0; i< n_chan; i++) - { - int basic_chan, mode_chan,val; - if( fluid_synth_get_basic_channel(synth, i, &basic_chan, &mode_chan, &val) == FLUID_OK) - { - if (basic_chan == i) - { - n++; - fluid_ostream_printf(out,"Basic channel:%3d, %s, nbr:%3d\n", i, - mode_name[mode_chan & FLUID_CHANNEL_MODE_MASK ], - val); - } - } - else - { - return FLUID_FAILED; /* error */ - } - } - /* prints a warning if there is no basic channel */ - if (n == 0) - { - fluid_ostream_printf(out, warning_msg); - } - return FLUID_OK; + static const char *warning_msg = "Warning: no basic channels. All MIDI channels are disabled.\n" + "Make use of setbasicchannels to set at least a default basic channel.\n"; + + int n_chan = synth->midi_channels; + int i, n = 0; + + /* prints all basic channels */ + for(i = 0; i < n_chan; i++) + { + int basic_chan, mode_chan, val; + + if(fluid_synth_get_basic_channel(synth, i, &basic_chan, &mode_chan, &val) == FLUID_OK) + { + if(basic_chan == i) + { + n++; + fluid_ostream_printf(out, "Basic channel:%3d, %s, nbr:%3d\n", i, + mode_name[mode_chan & FLUID_CHANNEL_MODE_MASK ], + val); + } + } + else + { + return FLUID_FAILED; /* error */ + } + } + + /* prints a warning if there is no basic channel */ + if(n == 0) + { + fluid_ostream_printf(out, warning_msg); + } + + return FLUID_OK; } /*----------------------------------------------------------------------------- - basicchannels - Prints the list of all MIDI basic channels informations + basicchannels + Prints the list of all MIDI basic channels informations example: Basic channel: 0, poly omni on (0), nbr: 3 @@ -2024,12 +2523,12 @@ static int print_basic_channels(fluid_synth_t* synth, fluid_ostream_t out) Basic channel: 8, mono omni off(3), nbr: 2 Basic channel: 13, mono omni on (1), nbr: 3 */ -int fluid_handle_basicchannels (void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_basicchannels(void *data, int ac, char **av, + fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - return print_basic_channels(synth, out); + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + return print_basic_channels(synth, out); } /* @@ -2038,24 +2537,26 @@ int fluid_handle_basicchannels (void* data, int ac, char** av, @param name to search. @return channel mode number (0 to 3) if name is valid, -1 otherwise. */ -static int get_channel_mode_num(char * name) +static int get_channel_mode_num(char *name) { - /* argument names for channel mode parameter (see resetbasicchannels and - setbasicchannels commands*/ - static const char * name_channel_mode [FLUID_CHANNEL_MODE_LAST]= - {"poly_omnion","mono_omnion","poly_omnioff","mono_omnioff"}; - int i; - for (i = 0 ; i < FLUID_CHANNEL_MODE_LAST;i++) - { - if ( ! FLUID_STRCMP (name, name_channel_mode[i])) - { - return i; - } - } - return -1; + /* argument names for channel mode parameter (see resetbasicchannels and + setbasicchannels commands*/ + static const char *name_channel_mode [FLUID_CHANNEL_MODE_LAST] = + {"poly_omnion", "mono_omnion", "poly_omnioff", "mono_omnioff"}; + int i; + + for(i = 0 ; i < FLUID_CHANNEL_MODE_LAST; i++) + { + if(! FLUID_STRCMP(name, name_channel_mode[i])) + { + return i; + } + } + + return -1; } -static const char *invalid_arg_msg ="invalid argument\n"; +static const char *invalid_arg_msg = "invalid argument\n"; /* checks basic channels arguments: chan1 mode1 val chan2 mode2 val2 ... All arguments can be numeric. mode parameter can be a name. @@ -2067,29 +2568,33 @@ static const char *invalid_arg_msg ="invalid argument\n"; @param name_cde command name prefix. @return 0 if arguments are valid, -1 otherwise. */ -static int check_basicchannels_arguments(int ac, char** av, - fluid_ostream_t out, char const * name_cde) +static int check_basicchannels_arguments(int ac, char **av, + fluid_ostream_t out, char const *name_cde) { - static const char *too_few_arg_msg = "too few argument, chan mode val [chan mode val]...\n"; - int i; - for (i = 0; i < ac; i++) - { - /* checks parameters for list entries: chan1 mode1 val chan2 mode2 val2 ...*/ - /* all parameters can be numeric. mode parameter can be a name. */ - if (!fluid_is_number(av[i]) && - ( (i % 3 != 1) || get_channel_mode_num(av[i]) < 0 )) - { - fluid_ostream_printf(out, "%s: %s",name_cde, invalid_arg_msg); - return -1; - } - } - if (ac % 3) - { /* each group entry needs 3 parameters: basicchan,mode,val */ - fluid_ostream_printf(out, "%s: channel %d, %s\n",name_cde, - atoi(av[((ac/3) * 3)]),too_few_arg_msg); - return -1; - } - return 0; + static const char *too_few_arg_msg = "too few argument, chan mode val [chan mode val]...\n"; + int i; + + for(i = 0; i < ac; i++) + { + /* checks parameters for list entries: chan1 mode1 val chan2 mode2 val2 ...*/ + /* all parameters can be numeric. mode parameter can be a name. */ + if(!fluid_is_number(av[i]) && + ((i % 3 != 1) || get_channel_mode_num(av[i]) < 0)) + { + fluid_ostream_printf(out, "%s: %s", name_cde, invalid_arg_msg); + return -1; + } + } + + if(ac % 3) + { + /* each group entry needs 3 parameters: basicchan,mode,val */ + fluid_ostream_printf(out, "%s: channel %d, %s\n", name_cde, + atoi(av[((ac / 3) * 3)]), too_few_arg_msg); + return -1; + } + + return 0; } /* @@ -2102,132 +2607,146 @@ static int check_basicchannels_arguments(int ac, char** av, @param name_cde command name prefix. @return 0 if arguments are valid, -1 otherwise. */ -static int check_channels_arguments(int ac, char** av, - fluid_ostream_t out, char const * name_cde) +static int check_channels_arguments(int ac, char **av, + fluid_ostream_t out, char const *name_cde) { - int i; - for (i = 0; i < ac; i++) - { - if (!fluid_is_number(av[i])) - { - fluid_ostream_printf(out, "%s: %s",name_cde, invalid_arg_msg); - return -1; - } - } - return 0; + int i; + + for(i = 0; i < ac; i++) + { + if(!fluid_is_number(av[i])) + { + fluid_ostream_printf(out, "%s: %s", name_cde, invalid_arg_msg); + return -1; + } + } + + return 0; } /*----------------------------------------------------------------------------- resetbasicchannels - + With no parameters the command resets all basic channels. - Note: Be aware than when a synth instance has no basic channels, all channels + Note: Be aware than when a synth instance has no basic channels, all channels are disabled. In the intend to get some MIDI channels enabled, use the command setbasicchannels. resetbasicchannels chan1 [chan2 . . .] Resets basic channel group chan1, basic channel group chan2 . . . */ -int fluid_handle_resetbasicchannels (void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_resetbasicchannels(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="resetbasicchannels"; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; + static const char *name_cde = "resetbasicchannels"; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; - /* checks channels arguments: chan1 chan2 .... */ - if (check_channels_arguments(ac,av,out,name_cde ) < 0) - { - return -1; - } + /* checks channels arguments: chan1 chan2 .... */ + if(check_channels_arguments(ac, av, out, name_cde) < 0) + { + return -1; + } - if (ac ) - { /* resetbasicchannels chan1 [chan2 . . .] */ - int i; - for (i = 0; i < ac; i++) - { - int chan = atoi(av[i]); - int result = fluid_synth_reset_basic_channel(synth, chan); - if (result == FLUID_FAILED) - { - fluid_ostream_printf(out,"%s: channel %3d, %s", name_cde, chan,invalid_arg_msg); - } - } - } - else - { - /* resets all basic channels */ - fluid_synth_reset_basic_channel(synth, -1); - } - /* prints result */ - return print_basic_channels(synth, out); + if(ac) + { + /* resetbasicchannels chan1 [chan2 . . .] */ + int i; + + for(i = 0; i < ac; i++) + { + int chan = atoi(av[i]); + int result = fluid_synth_reset_basic_channel(synth, chan); + + if(result == FLUID_FAILED) + { + fluid_ostream_printf(out, "%s: channel %3d, %s", name_cde, chan, invalid_arg_msg); + } + } + } + else + { + /* resets all basic channels */ + fluid_synth_reset_basic_channel(synth, -1); + } + + /* prints result */ + return print_basic_channels(synth, out); } /*----------------------------------------------------------------------------- setbasicchannels - + With no parameters the command sets one channel basic at basic channel 0 in Omni On Poly (i.e all the MIDI channels are polyphonic). setbasicchannels chan1 mode1 nbr1 [chan2 mode2 nbr2] ... ... - + Adds basic channel 1 and 2 - + The command fails if any channels overlaps any existing basic channel groups. To make room if necessary, existing basic channel groups can be cleared using resetbasicchannels command. - Mode can be a numeric value or a name: + Mode can be a numeric value or a name: numeric: 0 to 3 or name: poly_omnion , mono_omnion, poly_omnioff, mono_omnioff. */ -int fluid_handle_setbasicchannels (void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_setbasicchannels(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="setbasicchannels"; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - int result; - int i,n ; + static const char *name_cde = "setbasicchannels"; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + int result; + int i, n ; - if(!ac) - { - /* sets one default basic channel */ - fluid_synth_reset_basic_channel(synth, -1); /* reset all basic channels */ - /* sets one basic channel Omni On Poly (i.e all the MIDI channels are polyphonic) */ - fluid_synth_set_basic_channel( synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,0); - return 0; - } - /* checks parameters: chan1 mode1 val1 chan2 mode2 val2 */ - if (check_basicchannels_arguments(ac,av,out,name_cde) < 0) - { - return -1; - } + if(!ac) + { + /* sets one default basic channel */ + fluid_synth_reset_basic_channel(synth, -1); /* reset all basic channels */ + /* sets one basic channel Omni On Poly (i.e all the MIDI channels are polyphonic) */ + fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY, 0); + return 0; + } - n = ac / 3; /* number of basic channel information */ - for (i = 0; i < n; i++) - { - int basicchan, mode, val; + /* checks parameters: chan1 mode1 val1 chan2 mode2 val2 */ + if(check_basicchannels_arguments(ac, av, out, name_cde) < 0) + { + return -1; + } - basicchan = atoi(av[(i * 3)]); /* chan is numeric */ - if (fluid_is_number(av[(i * 3)+1])) - { /* chan is numeric */ - mode = atoi(av[(i * 3)+1]); - } - else - { /* mode is a name */ - mode = get_channel_mode_num(av[(i * 3)+1]); - } - val = atoi(av[(i * 3)+2]); /* val is numeric */ + n = ac / 3; /* number of basic channel information */ - /* changes or sets basic channels */ - result = fluid_synth_set_basic_channel(synth, basicchan, mode, val); - if (result == FLUID_FAILED) - { - fluid_ostream_printf(out,"%s: channel %3d, mode %3d, nbr %3d, %s", - name_cde, basicchan, mode, val, invalid_arg_msg); - } - } - return 0; + for(i = 0; i < n; i++) + { + int basicchan, mode, val; + + basicchan = atoi(av[(i * 3)]); /* chan is numeric */ + + if(fluid_is_number(av[(i * 3) + 1])) + { + /* chan is numeric */ + mode = atoi(av[(i * 3) + 1]); + } + else + { + /* mode is a name */ + mode = get_channel_mode_num(av[(i * 3) + 1]); + } + + val = atoi(av[(i * 3) + 2]); /* val is numeric */ + + /* changes or sets basic channels */ + result = fluid_synth_set_basic_channel(synth, basicchan, mode, val); + + if(result == FLUID_FAILED) + { + fluid_ostream_printf(out, "%s: channel %3d, mode %3d, nbr %3d, %s", + name_cde, basicchan, mode, val, invalid_arg_msg); + } + } + + return 0; } /* @@ -2238,18 +2757,18 @@ int fluid_handle_setbasicchannels (void* data, int ac, char** av, @param chan, MIDI channel number x. @param n_chan, number of MIDI channels y. */ -static void print_channel_is_outside_count(fluid_ostream_t out, char const * name_cde, - int chan, int n_chan) +static void print_channel_is_outside_count(fluid_ostream_t out, char const *name_cde, + int chan, int n_chan) { - fluid_ostream_printf(out,"%s: channel %3d is outside MIDI channel count(%d)\n", - name_cde, chan, n_chan); + fluid_ostream_printf(out, "%s: channel %3d is outside MIDI channel count(%d)\n", + name_cde, chan, n_chan); } /*----------------------------------------------------------------------------- channelsmode Prints channel mode of all MIDI channels (Poly/mono, Enabled, Basic Channel) - example + example Channel , Status , Type , Mode , Nbr of channels channel: 0, disabled @@ -2268,86 +2787,105 @@ static void print_channel_is_outside_count(fluid_ostream_t out, char const * nam channel: 13, enabled, -- , mono , -- channel: 14, disabled channel: 15, disabled - + channelsmode chan1 chan2 Prints only channel mode of MIDI channels chan1, chan2 */ -int fluid_handle_channelsmode (void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_channelsmode(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * header = - "Channel , Status , Type , Mode , Nbr of channels\n"; - static const char * name_cde="channelsmode"; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - - int i, n, n_chan= synth->midi_channels; - - /* checks parameters: chan1 chan2 .... */ - if (check_channels_arguments(ac,av,out,name_cde) < 0) - { - return -1; - } - if (ac ) - { - n = ac; /* prints ac MIDI channels number */ - } - else - { - n= n_chan; /* prints all MIDI channels number */ - } - /* prints header */ - fluid_ostream_printf(out, header); - for (i = 0; i < n; i++) - { - int basic_chan, mode, val; - int chan = ac ? atoi(av[i]): i; - int result = fluid_synth_get_basic_channel(synth, chan, &basic_chan, &mode, &val); - if (result == FLUID_OK) - { - if(basic_chan != FLUID_FAILED) - { /* This channel is enabled */ - const char * p_basicchan; /* field basic channel */ - const char * p_mode; /* field mode */ - const char *p_nbr; /* field Nbr */ - static const char * blank="--"; /* field empty */ - if (chan == basic_chan) - { /* This channel is a basic channel */ - char nbr[10]; /* field Nbr */ - FLUID_SNPRINTF(nbr,sizeof(nbr),"nbr:%3d",val); - p_nbr = nbr; - p_mode = mode_name[mode]; - p_basicchan = "basic channel"; - } - else - { /* This channel is member of a basic channel group */ - p_basicchan = blank; - if(mode & FLUID_CHANNEL_POLY_OFF) p_mode = "mono"; - else p_mode = "poly"; - p_nbr = blank; - } - fluid_ostream_printf(out, - "channel:%3d, enabled, %-13s, %-16s, %s\n", - chan, - p_basicchan, - p_mode, - p_nbr); - } - else - { - fluid_ostream_printf(out, "channel:%3d, disabled\n", chan); - } - } - else - { - print_channel_is_outside_count(out, name_cde, chan, n_chan); - if(i < n-1) - { - fluid_ostream_printf(out, header); - } - } - } - return 0; + static const char *header = + "Channel , Status , Type , Mode , Nbr of channels\n"; + static const char *name_cde = "channelsmode"; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + + int i, n, n_chan = synth->midi_channels; + + /* checks parameters: chan1 chan2 .... */ + if(check_channels_arguments(ac, av, out, name_cde) < 0) + { + return -1; + } + + if(ac) + { + n = ac; /* prints ac MIDI channels number */ + } + else + { + n = n_chan; /* prints all MIDI channels number */ + } + + /* prints header */ + fluid_ostream_printf(out, header); + + for(i = 0; i < n; i++) + { + int basic_chan, mode, val; + int chan = ac ? atoi(av[i]) : i; + int result = fluid_synth_get_basic_channel(synth, chan, &basic_chan, &mode, &val); + + if(result == FLUID_OK) + { + if(basic_chan != FLUID_FAILED) + { + /* This channel is enabled */ + const char *p_basicchan; /* field basic channel */ + const char *p_mode; /* field mode */ + const char *p_nbr; /* field Nbr */ + static const char *blank = "--"; /* field empty */ + + if(chan == basic_chan) + { + /* This channel is a basic channel */ + char nbr[10]; /* field Nbr */ + FLUID_SNPRINTF(nbr, sizeof(nbr), "nbr:%3d", val); + p_nbr = nbr; + p_mode = mode_name[mode]; + p_basicchan = "basic channel"; + } + else + { + /* This channel is member of a basic channel group */ + p_basicchan = blank; + + if(mode & FLUID_CHANNEL_POLY_OFF) + { + p_mode = "mono"; + } + else + { + p_mode = "poly"; + } + + p_nbr = blank; + } + + fluid_ostream_printf(out, + "channel:%3d, enabled, %-13s, %-16s, %s\n", + chan, + p_basicchan, + p_mode, + p_nbr); + } + else + { + fluid_ostream_printf(out, "channel:%3d, disabled\n", chan); + } + } + else + { + print_channel_is_outside_count(out, name_cde, chan, n_chan); + + if(i < n - 1) + { + fluid_ostream_printf(out, header); + } + } + } + + return 0; } /** commands mono legato mode ***********************************************/ @@ -2361,67 +2899,70 @@ int fluid_handle_channelsmode (void* data, int ac, char** av, @param n_chan, number of MIDI channels. */ static void print_result_get_channel_mode(int result, fluid_ostream_t out, - char const * name_cde, int chan, - char const * name_mode, int n_chan ) + char const *name_cde, int chan, + char const *name_mode, int n_chan) { - if (result == FLUID_OK) - { - fluid_ostream_printf(out,"%s: channel %3d, %s\n", name_cde, chan, name_mode); - } - else - { - print_channel_is_outside_count(out, name_cde, chan, n_chan); - } + if(result == FLUID_OK) + { + fluid_ostream_printf(out, "%s: channel %3d, %s\n", name_cde, chan, name_mode); + } + else + { + print_channel_is_outside_count(out, name_cde, chan, n_chan); + } } /*----------------------------------------------------------------------------- legatomode Prints legato mode of all MIDI channels - example + example channel: 0, (1)multi-retrigger channel: 1, (0)retrigger channel: 2, (1)multi-retrigger ..... - + legatomode chan1 chan2 Prints only legato mode of MIDI channels chan1, chan2 */ -int fluid_handle_legatomode(void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_legatomode(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="legatomode"; - static const char * name_legato_mode[FLUID_CHANNEL_LEGATO_MODE_LAST]= - { "(0)retrigger","(1)multi-retrigger" }; + static const char *name_cde = "legatomode"; + static const char *name_legato_mode[FLUID_CHANNEL_LEGATO_MODE_LAST] = + { "(0)retrigger", "(1)multi-retrigger" }; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - int mode = 0; - int i, n, n_chan= synth->midi_channels; - - /* checks channels arguments: chan1 chan2 .... */ - if (check_channels_arguments(ac, av, out, name_cde) < 0) - { - return -1; - } + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + int mode = 0; + int i, n, n_chan = synth->midi_channels; - if (ac ) - { - n = ac; /* prints ac MIDI channels number */ - } - else - { - n= n_chan; /* prints all MIDI channels number */ - } - /* prints header */ - fluid_ostream_printf(out,"Channel , legato mode\n"); - for (i = 0; i < n; i++) - { - int chan = ac ? atoi(av[i]): i; - int result = fluid_synth_get_legato_mode(synth, chan, &mode); - print_result_get_channel_mode(result, out, name_cde, chan, name_legato_mode[mode], n_chan); - } - return 0; + /* checks channels arguments: chan1 chan2 .... */ + if(check_channels_arguments(ac, av, out, name_cde) < 0) + { + return -1; + } + + if(ac) + { + n = ac; /* prints ac MIDI channels number */ + } + else + { + n = n_chan; /* prints all MIDI channels number */ + } + + /* prints header */ + fluid_ostream_printf(out, "Channel , legato mode\n"); + + for(i = 0; i < n; i++) + { + int chan = ac ? atoi(av[i]) : i; + int result = fluid_synth_get_legato_mode(synth, chan, &mode); + print_result_get_channel_mode(result, out, name_cde, chan, name_legato_mode[mode], n_chan); + } + + return 0; } /* @@ -2439,33 +2980,36 @@ int fluid_handle_legatomode(void* data, int ac, char** av, @param nbr_arg_group_msg message when the number of argument by group is invalid. @return 0 if arguments are valid, -1 otherwise. */ -static int check_channels_group_arguments(int ac, char** av, int nbr_arg_group, - fluid_ostream_t out, - char const * name_cde, - char const * nbr_arg_group_msg - ) +static int check_channels_group_arguments(int ac, char **av, int nbr_arg_group, + fluid_ostream_t out, + char const *name_cde, + char const *nbr_arg_group_msg + ) { - if (ac) - { - /* checks channels numeric arguments */ - if (check_channels_arguments(ac, av, out, name_cde) < 0) - { - return -1; - } - if (ac % nbr_arg_group) - { /* each group entry needs nbr_arg_group parameters */ - fluid_ostream_printf(out, "%s: channel %d, %s\n",name_cde, - atoi(av[((ac/nbr_arg_group) * nbr_arg_group)]), - nbr_arg_group_msg); - return -1; - } - } - else - { - fluid_ostream_printf(out, "%s: %s",name_cde, nbr_arg_group_msg); - return -1; - } - return 0; + if(ac) + { + /* checks channels numeric arguments */ + if(check_channels_arguments(ac, av, out, name_cde) < 0) + { + return -1; + } + + if(ac % nbr_arg_group) + { + /* each group entry needs nbr_arg_group parameters */ + fluid_ostream_printf(out, "%s: channel %d, %s\n", name_cde, + atoi(av[((ac / nbr_arg_group) * nbr_arg_group)]), + nbr_arg_group_msg); + return -1; + } + } + else + { + fluid_ostream_printf(out, "%s: %s", name_cde, nbr_arg_group_msg); + return -1; + } + + return 0; } /* @@ -2476,47 +3020,49 @@ static int check_channels_group_arguments(int ac, char** av, int nbr_arg_group, @param chan, MIDI channel number to display. @param mode, mode value to display. */ -static void print_result_set_channel_mode(int result, fluid_ostream_t out, - char const * name_cde, - int chan, int mode) +static void print_result_set_channel_mode(int result, fluid_ostream_t out, + char const *name_cde, + int chan, int mode) { - if (result == FLUID_FAILED) - { - fluid_ostream_printf(out,"%s: channel %3d, mode %3d, %s", name_cde, chan, mode, invalid_arg_msg); - } + if(result == FLUID_FAILED) + { + fluid_ostream_printf(out, "%s: channel %3d, mode %3d, %s", name_cde, chan, mode, invalid_arg_msg); + } } static const char *too_few_arg_chan_mode_msg = "too few argument, chan mode [chan mode]...\n"; /*----------------------------------------------------------------------------- setlegatomode chan0 mode1 [chan1 mode0] .. .. - + Changes legato mode for channels chan0 and [chan1] */ -int fluid_handle_setlegatomode(void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_setlegatomode(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="setlegatomode"; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - int i,n ; + static const char *name_cde = "setlegatomode"; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + int i, n ; - /* checks channels arguments by group of 2: chan1 val1 chan2 val1 .. ..*/ - if (check_channels_group_arguments(ac, av, 2, out, name_cde, too_few_arg_chan_mode_msg) < 0) - { - return -1; - } + /* checks channels arguments by group of 2: chan1 val1 chan2 val1 .. ..*/ + if(check_channels_group_arguments(ac, av, 2, out, name_cde, too_few_arg_chan_mode_msg) < 0) + { + return -1; + } - n = ac / 2; /* number of legato groups informations */ - for (i = 0; i < n; i++) - { - int chan = atoi(av[(i * 2)]); - int mode = atoi(av[(i * 2)+1]); - /* changes legato mode */ - - int result = fluid_synth_set_legato_mode(synth,chan,mode); - print_result_set_channel_mode(result, out, name_cde, chan, mode); - } - return 0; + n = ac / 2; /* number of legato groups informations */ + + for(i = 0; i < n; i++) + { + int chan = atoi(av[(i * 2)]); + int mode = atoi(av[(i * 2) + 1]); + /* changes legato mode */ + + int result = fluid_synth_set_legato_mode(synth, chan, mode); + print_result_set_channel_mode(result, out, name_cde, chan, mode); + } + + return 0; } /** commands mono/poly portamento mode **************************************/ @@ -2524,83 +3070,89 @@ int fluid_handle_setlegatomode(void* data, int ac, char** av, /*----------------------------------------------------------------------------- portamentomode Prints portamento mode of all MIDI channels - example + example channel: 0, (2)staccato only channel: 1, (1)legato only channel: 2, (0)each note channel: 3, (1)legato only ..... - + portamentomode chan1 chan2 Prints only portamento mode of MIDI channels chan1, chan2 */ -int fluid_handle_portamentomode(void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_portamentomode(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="portamentomode"; - static const char * name_portamento_mode[FLUID_CHANNEL_PORTAMENTO_MODE_LAST]= - { "(0)each note", "(1)legato only", "(2)staccato only" }; + static const char *name_cde = "portamentomode"; + static const char *name_portamento_mode[FLUID_CHANNEL_PORTAMENTO_MODE_LAST] = + { "(0)each note", "(1)legato only", "(2)staccato only" }; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - int mode = 0; - int i, n, n_chan= synth->midi_channels; - - /* checks channels arguments: chan1 chan2 . . . */ - if (check_channels_arguments(ac, av, out, name_cde) < 0) - { - return -1; - } - if (ac ) - { - n = ac; /* prints ac MIDI channels number */ - } - else - { - n= n_chan; /* prints all MIDI channels number */ - } - /* prints header */ - fluid_ostream_printf(out,"Channel , portamento mode\n"); - for (i = 0; i < n; i++) - { - int chan = ac ? atoi(av[i]): i; - int result = fluid_synth_get_portamento_mode(synth, chan, &mode); - print_result_get_channel_mode(result, out, name_cde, chan, name_portamento_mode[mode], n_chan); - } - return 0; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + int mode = 0; + int i, n, n_chan = synth->midi_channels; + + /* checks channels arguments: chan1 chan2 . . . */ + if(check_channels_arguments(ac, av, out, name_cde) < 0) + { + return -1; + } + + if(ac) + { + n = ac; /* prints ac MIDI channels number */ + } + else + { + n = n_chan; /* prints all MIDI channels number */ + } + + /* prints header */ + fluid_ostream_printf(out, "Channel , portamento mode\n"); + + for(i = 0; i < n; i++) + { + int chan = ac ? atoi(av[i]) : i; + int result = fluid_synth_get_portamento_mode(synth, chan, &mode); + print_result_get_channel_mode(result, out, name_cde, chan, name_portamento_mode[mode], n_chan); + } + + return 0; } /*----------------------------------------------------------------------------- setportamentomode chan1 mode1 [chan2 mode2] .. .. - + Changes portamento mode for channels chan1 and [chan2] */ -int fluid_handle_setportamentomode(void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_setportamentomode(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="setportamentomode"; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - int i,n ; + static const char *name_cde = "setportamentomode"; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + int i, n ; - /* checks channels arguments by group of 2: chan1 val1 chan2 val1 .. .. */ - if (check_channels_group_arguments(ac, av, 2, out, name_cde, too_few_arg_chan_mode_msg) < 0) - { - return -1; - } + /* checks channels arguments by group of 2: chan1 val1 chan2 val1 .. .. */ + if(check_channels_group_arguments(ac, av, 2, out, name_cde, too_few_arg_chan_mode_msg) < 0) + { + return -1; + } - n = ac / 2; /* number of portamento groups informations */ - for (i = 0; i < n; i++) - { - int chan = atoi(av[(i * 2)]); - int mode = atoi(av[(i * 2)+1]); - /* changes portamento mode */ - - int result = fluid_synth_set_portamento_mode(synth,chan,mode); - print_result_set_channel_mode(result, out, name_cde, chan, mode); - } - return 0; + n = ac / 2; /* number of portamento groups informations */ + + for(i = 0; i < n; i++) + { + int chan = atoi(av[(i * 2)]); + int mode = atoi(av[(i * 2) + 1]); + /* changes portamento mode */ + + int result = fluid_synth_set_portamento_mode(synth, chan, mode); + print_result_set_channel_mode(result, out, name_cde, chan, mode); + } + + return 0; } /** commands mono/poly breath mode *******************************************/ @@ -2608,90 +3160,99 @@ int fluid_handle_setportamentomode(void* data, int ac, char** av, breathmode Prints breath options of all MIDI channels. poly breath on/off, mono breath on/off, breath sync on/off - - example + + example Channel , poly breath , mono breath , breath sync channel: 0, off , off , off channel: 1, off , off , off channel: 2, off , off , off ..... - + breathmode chan1 chan2 Prints only breath mode of MIDI channels chan1, chan2 */ -int fluid_handle_breathmode(void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_breathmode(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="breathmode"; - static const char * header="Channel , poly breath , mono breath , breath sync\n"; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - int breathmode; - int i, n, n_chan= synth->midi_channels; - - /* checks channels arguments: chan1 chan2 . . . */ - if (check_channels_arguments(ac, av, out, name_cde) < 0) - { - return -1; - } + static const char *name_cde = "breathmode"; + static const char *header = "Channel , poly breath , mono breath , breath sync\n"; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + int breathmode; + int i, n, n_chan = synth->midi_channels; - if (ac ) - { - n = ac; /* prints ac MIDI channels number */ - } - else - { - n= n_chan; /* prints all MIDI channels number */ - } - /* prints header */ - fluid_ostream_printf(out, header); - for (i = 0; i < n; i++) - { - int chan = ac ? atoi(av[i]): i; - int result = fluid_synth_get_breath_mode(synth, chan, &breathmode); - if (result == FLUID_OK) - { - static const char * on_msg ="on"; - static const char * off_msg ="off"; - const char * msg_poly_breath, * msg_mono_breath, * msg_breath_sync; - if (breathmode & FLUID_CHANNEL_BREATH_POLY) - { - msg_poly_breath =on_msg; - } - else - { - msg_poly_breath = off_msg; - } - if (breathmode & FLUID_CHANNEL_BREATH_MONO) - { - msg_mono_breath =on_msg; - } - else - { - msg_mono_breath = off_msg; - } - if (breathmode & FLUID_CHANNEL_BREATH_SYNC) - { - msg_breath_sync =on_msg; - } - else - { - msg_breath_sync = off_msg; - } - fluid_ostream_printf(out,"channel:%3d, %-12s, %-12s, %-11s\n",chan, - msg_poly_breath, msg_mono_breath, msg_breath_sync); - } - else - { - print_channel_is_outside_count(out, name_cde, chan, n_chan); - if(i < n-1) - { - fluid_ostream_printf(out, header); - } - } - } - return 0; + /* checks channels arguments: chan1 chan2 . . . */ + if(check_channels_arguments(ac, av, out, name_cde) < 0) + { + return -1; + } + + if(ac) + { + n = ac; /* prints ac MIDI channels number */ + } + else + { + n = n_chan; /* prints all MIDI channels number */ + } + + /* prints header */ + fluid_ostream_printf(out, header); + + for(i = 0; i < n; i++) + { + int chan = ac ? atoi(av[i]) : i; + int result = fluid_synth_get_breath_mode(synth, chan, &breathmode); + + if(result == FLUID_OK) + { + static const char *on_msg = "on"; + static const char *off_msg = "off"; + const char *msg_poly_breath, * msg_mono_breath, * msg_breath_sync; + + if(breathmode & FLUID_CHANNEL_BREATH_POLY) + { + msg_poly_breath = on_msg; + } + else + { + msg_poly_breath = off_msg; + } + + if(breathmode & FLUID_CHANNEL_BREATH_MONO) + { + msg_mono_breath = on_msg; + } + else + { + msg_mono_breath = off_msg; + } + + if(breathmode & FLUID_CHANNEL_BREATH_SYNC) + { + msg_breath_sync = on_msg; + } + else + { + msg_breath_sync = off_msg; + } + + fluid_ostream_printf(out, "channel:%3d, %-12s, %-12s, %-11s\n", chan, + msg_poly_breath, msg_mono_breath, msg_breath_sync); + } + else + { + print_channel_is_outside_count(out, name_cde, chan, n_chan); + + if(i < n - 1) + { + fluid_ostream_printf(out, header); + } + } + } + + return 0; } /*----------------------------------------------------------------------------- @@ -2700,51 +3261,67 @@ int fluid_handle_breathmode(void* data, int ac, char** av, Changes breath options for channels chan1 [chan2] .. .. Example: setbreathmode 4 0 1 1 - + Parameter 1 is the channel number (i.e 4). Parameter 2 is the " Breath modulator " enable/disable for poly mode (i.e disabled). Parameter 3 is the " Breath modulator " enabe/disable for mono mode (i.e enabled). Parameter 4 is "breath sync noteOn/Off" enable/disable for mono mode only (i.e enabled). */ -int fluid_handle_setbreathmode(void* data, int ac, char** av, - fluid_ostream_t out) +int fluid_handle_setbreathmode(void *data, int ac, char **av, + fluid_ostream_t out) { - static const char * name_cde="setbreathmode"; - static const char *too_few_arg_breath_msg = - "too few argument:\nchan 1/0(breath poly) 1/0(breath mono) 1/0(breath sync mono)[..]\n"; + static const char *name_cde = "setbreathmode"; + static const char *too_few_arg_breath_msg = + "too few argument:\nchan 1/0(breath poly) 1/0(breath mono) 1/0(breath sync mono)[..]\n"; - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; - int i,n, n_chan= synth->midi_channels; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; + int i, n, n_chan = synth->midi_channels; - /* checks channels arguments by group of 4: - chan1 val1 val2 val3 chan2 val1 val2 val3 .... ....*/ - if (check_channels_group_arguments(ac, av, 4, out, name_cde, too_few_arg_breath_msg) < 0) - { - return -1; - } + /* checks channels arguments by group of 4: + chan1 val1 val2 val3 chan2 val1 val2 val3 .... ....*/ + if(check_channels_group_arguments(ac, av, 4, out, name_cde, too_few_arg_breath_msg) < 0) + { + return -1; + } - n = ac / 4; /* number of breath groups informations */ - for (i = 0; i < n; i++) - { - int result; - int chan = atoi(av[(i * 4)]); - int poly_breath = atoi(av[(i * 4)+1]); - int mono_breath = atoi(av[(i * 4)+2]); - int breath_sync = atoi(av[(i * 4)+3]); - int breath_infos = 0; - /* changes breath infos */ - if(poly_breath) breath_infos |= FLUID_CHANNEL_BREATH_POLY; - if(mono_breath) breath_infos |= FLUID_CHANNEL_BREATH_MONO; - if(breath_sync) breath_infos |= FLUID_CHANNEL_BREATH_SYNC; - result = fluid_synth_set_breath_mode(synth,chan,breath_infos); - if (result == FLUID_FAILED) - { - print_channel_is_outside_count(out, name_cde, chan, n_chan); - } - } - return 0; + n = ac / 4; /* number of breath groups informations */ + + for(i = 0; i < n; i++) + { + int result; + int chan = atoi(av[(i * 4)]); + int poly_breath = atoi(av[(i * 4) + 1]); + int mono_breath = atoi(av[(i * 4) + 2]); + int breath_sync = atoi(av[(i * 4) + 3]); + int breath_infos = 0; + + /* changes breath infos */ + if(poly_breath) + { + breath_infos |= FLUID_CHANNEL_BREATH_POLY; + } + + if(mono_breath) + { + breath_infos |= FLUID_CHANNEL_BREATH_MONO; + } + + if(breath_sync) + { + breath_infos |= FLUID_CHANNEL_BREATH_SYNC; + } + + result = fluid_synth_set_breath_mode(synth, chan, breath_infos); + + if(result == FLUID_FAILED) + { + print_channel_is_outside_count(out, name_cde, chan, n_chan); + } + } + + return 0; } @@ -2769,13 +3346,13 @@ int fluid_handle_setbreathmode(void* data, int ac, char** av, /** * ladspa_start */ -int fluid_handle_ladspa_start(void* data, int ac, char **av, fluid_ostream_t out) +int fluid_handle_ladspa_start(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; char error[LADSPA_ERR_LEN]; - if (ac != 0) + if(ac != 0) { fluid_ostream_printf(out, "ladspa_start does not accept any arguments\n"); return FLUID_FAILED; @@ -2784,13 +3361,13 @@ int fluid_handle_ladspa_start(void* data, int ac, char **av, fluid_ostream_t out CHECK_LADSPA_ENABLED(fx, out); CHECK_LADSPA_INACTIVE(fx, out); - if (fluid_ladspa_check(fx, error, LADSPA_ERR_LEN) != FLUID_OK) + if(fluid_ladspa_check(fx, error, LADSPA_ERR_LEN) != FLUID_OK) { fluid_ostream_printf(out, "Unable to start LADSPA: %s", error); return FLUID_FAILED; } - if (fluid_ladspa_activate(fx) != FLUID_OK) + if(fluid_ladspa_activate(fx) != FLUID_OK) { fluid_ostream_printf(out, "Unable to start LADSPA.\n"); return FLUID_FAILED; @@ -2802,12 +3379,12 @@ int fluid_handle_ladspa_start(void* data, int ac, char **av, fluid_ostream_t out /** * ladspa_stop */ -int fluid_handle_ladspa_stop(void* data, int ac, char **av, fluid_ostream_t out) +int fluid_handle_ladspa_stop(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; - if (ac != 0) + if(ac != 0) { fluid_ostream_printf(out, "ladspa_stop does not accept any arguments\n"); return FLUID_FAILED; @@ -2815,12 +3392,12 @@ int fluid_handle_ladspa_stop(void* data, int ac, char **av, fluid_ostream_t out) CHECK_LADSPA_ENABLED(fx, out); - if (!fluid_ladspa_is_active(fx)) + if(!fluid_ladspa_is_active(fx)) { fluid_ostream_printf(out, "LADSPA has not been started.\n"); } - if (fluid_ladspa_deactivate(fx) != FLUID_OK) + if(fluid_ladspa_deactivate(fx) != FLUID_OK) { fluid_ostream_printf(out, "Unable to stop LADSPA.\n"); return FLUID_FAILED; @@ -2832,12 +3409,12 @@ int fluid_handle_ladspa_stop(void* data, int ac, char **av, fluid_ostream_t out) /** * ladspa_reset */ -int fluid_handle_ladspa_reset(void* data, int ac, char **av, fluid_ostream_t out) +int fluid_handle_ladspa_reset(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; - if (ac != 0) + if(ac != 0) { fluid_ostream_printf(out, "ladspa_reset does not accept any arguments\n"); return FLUID_FAILED; @@ -2853,13 +3430,13 @@ int fluid_handle_ladspa_reset(void* data, int ac, char **av, fluid_ostream_t out /** * ladspa_check */ -int fluid_handle_ladspa_check(void* data, int ac, char **av, fluid_ostream_t out) +int fluid_handle_ladspa_check(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; char error[LADSPA_ERR_LEN]; - if (ac != 0) + if(ac != 0) { fluid_ostream_printf(out, "ladspa_reset does not accept any arguments\n"); return FLUID_FAILED; @@ -2867,7 +3444,7 @@ int fluid_handle_ladspa_check(void* data, int ac, char **av, fluid_ostream_t out CHECK_LADSPA_ENABLED(fx, out); - if (fluid_ladspa_check(fx, error, LADSPA_ERR_LEN) != FLUID_OK) + if(fluid_ladspa_check(fx, error, LADSPA_ERR_LEN) != FLUID_OK) { fluid_ostream_printf(out, "LADSPA check failed: %s", error); return FLUID_FAILED; @@ -2883,10 +3460,10 @@ int fluid_handle_ladspa_check(void* data, int ac, char **av, fluid_ostream_t out */ int fluid_handle_ladspa_set(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; - if (ac != 3) + if(ac != 3) { fluid_ostream_printf(out, "ladspa_set needs three arguments: \n"); return FLUID_FAILED; @@ -2895,16 +3472,16 @@ int fluid_handle_ladspa_set(void *data, int ac, char **av, fluid_ostream_t out) CHECK_LADSPA_ENABLED(fx, out); /* Redundant check, just here to give a more detailed error message */ - if (!fluid_ladspa_effect_port_exists(fx, av[0], av[1])) + if(!fluid_ladspa_effect_port_exists(fx, av[0], av[1])) { fluid_ostream_printf(out, "Port '%s' not found on effect '%s'\n", av[1], av[0]); return FLUID_FAILED; } - if (fluid_ladspa_effect_set_control(fx, av[0], av[1], atof(av[2])) != FLUID_OK) + if(fluid_ladspa_effect_set_control(fx, av[0], av[1], atof(av[2])) != FLUID_OK) { fluid_ostream_printf(out, "Failed to set port '%s' on effect '%s', " - "maybe it is not a control port?\n", av[1], av[0]); + "maybe it is not a control port?\n", av[1], av[0]); return FLUID_FAILED; } @@ -2916,19 +3493,20 @@ int fluid_handle_ladspa_set(void *data, int ac, char **av, fluid_ostream_t out) */ int fluid_handle_ladspa_buffer(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; - if (ac != 1) + if(ac != 1) { fluid_ostream_printf(out, "ladspa_buffer needs one argument: \n"); return FLUID_FAILED; }; CHECK_LADSPA_ENABLED(fx, out); + CHECK_LADSPA_INACTIVE(fx, out); - if (fluid_ladspa_add_buffer(fx, av[0]) != FLUID_OK) + if(fluid_ladspa_add_buffer(fx, av[0]) != FLUID_OK) { fluid_ostream_printf(out, "Failed to add buffer\n"); return FLUID_FAILED; @@ -2940,25 +3518,26 @@ int fluid_handle_ladspa_buffer(void *data, int ac, char **av, fluid_ostream_t ou /** * ladspa_effect [plugin] [--mix [gain]] */ -int fluid_handle_ladspa_effect(void* data, int ac, char **av, fluid_ostream_t out) +int fluid_handle_ladspa_effect(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; char *plugin_name = NULL; int pos; int mix = FALSE; float gain = 1.0f; - if (ac < 2 || ac > 5) + if(ac < 2 || ac > 5) { fluid_ostream_printf(out, "ladspa_effect invalid arguments: " - " [plugin] [--mix [gain]]\n"); + " [plugin] [--mix [gain]]\n"); return FLUID_FAILED; } pos = 2; + /* If the first optional arg is not --mix, then it must be the plugin label */ - if ((pos < ac) && (FLUID_STRCMP(av[pos], "--mix") != 0)) + if((pos < ac) && (FLUID_STRCMP(av[pos], "--mix") != 0)) { plugin_name = av[pos]; pos++; @@ -2966,10 +3545,11 @@ int fluid_handle_ladspa_effect(void* data, int ac, char **av, fluid_ostream_t ou /* If this optional arg is --mix and there's an argument after it, that that * must be the gain */ - if ((pos < ac) && (FLUID_STRCMP(av[pos], "--mix") == 0)) + if((pos < ac) && (FLUID_STRCMP(av[pos], "--mix") == 0)) { mix = TRUE; - if (pos + 1 < ac) + + if(pos + 1 < ac) { gain = atof(av[pos + 1]); } @@ -2978,21 +3558,21 @@ int fluid_handle_ladspa_effect(void* data, int ac, char **av, fluid_ostream_t ou CHECK_LADSPA_ENABLED(fx, out); CHECK_LADSPA_INACTIVE(fx, out); - if (fluid_ladspa_add_effect(fx, av[0], av[1], plugin_name) != FLUID_OK) + if(fluid_ladspa_add_effect(fx, av[0], av[1], plugin_name) != FLUID_OK) { fluid_ostream_printf(out, "Failed to create effect\n"); return FLUID_FAILED; } - if (mix) + if(mix) { - if (!fluid_ladspa_effect_can_mix(fx, av[0])) + if(!fluid_ladspa_effect_can_mix(fx, av[0])) { fluid_ostream_printf(out, "Effect '%s' does not support --mix mode\n", av[0]); return FLUID_FAILED; } - if (fluid_ladspa_effect_set_mix(fx, av[0], mix, gain) != FLUID_OK) + if(fluid_ladspa_effect_set_mix(fx, av[0], mix, gain) != FLUID_OK) { fluid_ostream_printf(out, "Failed to set --mix mode\n"); return FLUID_FAILED; @@ -3005,34 +3585,34 @@ int fluid_handle_ladspa_effect(void* data, int ac, char **av, fluid_ostream_t ou /* * ladspa_link */ -int fluid_handle_ladspa_link(void* data, int ac, char **av, fluid_ostream_t out) +int fluid_handle_ladspa_link(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); + FLUID_ENTRY_COMMAND(data); fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx; - if (ac != 3) + if(ac != 3) { fluid_ostream_printf(out, "ladspa_link needs 3 arguments: " - " \n"); + " \n"); return FLUID_FAILED; } CHECK_LADSPA_ENABLED(fx, out); CHECK_LADSPA_INACTIVE(fx, out); - if (!fluid_ladspa_effect_port_exists(fx, av[0], av[1])) + if(!fluid_ladspa_effect_port_exists(fx, av[0], av[1])) { fluid_ostream_printf(out, "Port '%s' not found on effect '%s'\n", av[1], av[0]); return FLUID_FAILED; } - if (!fluid_ladspa_host_port_exists(fx, av[2]) && !fluid_ladspa_buffer_exists(fx, av[2])) + if(!fluid_ladspa_host_port_exists(fx, av[2]) && !fluid_ladspa_buffer_exists(fx, av[2])) { fluid_ostream_printf(out, "Host port or buffer '%s' not found.\n", av[2]); return FLUID_FAILED; } - if (fluid_ladspa_effect_link(fx, av[0], av[1], av[2]) != FLUID_OK) + if(fluid_ladspa_effect_link(fx, av[0], av[1], av[2]) != FLUID_OK) { fluid_ostream_printf(out, "Failed to link port\n"); return FLUID_FAILED; @@ -3052,13 +3632,14 @@ int fluid_handle_ladspa_link(void* data, int ac, char **av, fluid_ostream_t out) */ static int fluid_profile_lock_command(fluid_ostream_t out) { - if (! fluid_atomic_int_compare_and_exchange(&fluid_profile_lock,0,1)) - { - fluid_ostream_printf(out, - "profile command in use in another shell. Try later!\n"); - return FLUID_FAILED; - } - return FLUID_OK; + if(! fluid_atomic_int_compare_and_exchange(&fluid_profile_lock, 0, 1)) + { + fluid_ostream_printf(out, + "profile command in use in another shell. Try later!\n"); + return FLUID_FAILED; + } + + return FLUID_OK; } /* @@ -3066,38 +3647,38 @@ static int fluid_profile_lock_command(fluid_ostream_t out) */ static void fluid_profile_unlock_command(void) { - fluid_atomic_int_set(&fluid_profile_lock,0); + fluid_atomic_int_set(&fluid_profile_lock, 0); } /* * command: profile * * Prints default parameters used by prof_start command. -* +* * Notes:0, bank:0, prog:16, print:0, n_prof:1, dur:500 ms. * * @return FLUID_OK if success , otherwise FLUID_FAILED. */ int -fluid_handle_profile(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_profile(void *data, int ac, char **av, fluid_ostream_t out) { - /* locks to prevent simultaneous changes by an other shell */ - /* (may be a server shell (tcp)) */ - if ( fluid_profile_lock_command(out) == FLUID_FAILED ) - { - return FLUID_FAILED; - } + /* locks to prevent simultaneous changes by an other shell */ + /* (may be a server shell (tcp)) */ + if(fluid_profile_lock_command(out) == FLUID_FAILED) + { + return FLUID_FAILED; + } - /* prints default parameters */ - fluid_ostream_printf(out, - " Notes:%d, bank:%d, prog:%d, print:%d, n_prof:%d, dur:%d ms\n", - fluid_profile_notes, fluid_profile_bank, fluid_profile_prog, - fluid_profile_print, - fluid_profile_n_prof, fluid_profile_dur); + /* prints default parameters */ + fluid_ostream_printf(out, + " Notes:%d, bank:%d, prog:%d, print:%d, n_prof:%d, dur:%d ms\n", + fluid_profile_notes, fluid_profile_bank, fluid_profile_prog, + fluid_profile_print, + fluid_profile_n_prof, fluid_profile_dur); - /* unlocks */ - fluid_profile_unlock_command(); - return FLUID_OK; + /* unlocks */ + fluid_profile_unlock_command(); + return FLUID_OK; } /* @@ -3111,66 +3692,75 @@ fluid_handle_profile(void* data, int ac, char** av, fluid_ostream_t out) * @return FLUID_OK if success , otherwise FLUID_FAILED. */ int -fluid_handle_prof_set_notes(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_prof_set_notes(void *data, int ac, char **av, fluid_ostream_t out) { - unsigned short nbr; /* previous parameters */ - unsigned char bank, prog; /* previous parameters */ - int r; /* return */ - /* locks to prevent simultaneous changes by an other shell */ - if( fluid_profile_lock_command(out) == FLUID_FAILED ) - { - return FLUID_FAILED; - } + unsigned short nbr; /* previous parameters */ + unsigned char bank, prog; /* previous parameters */ + int r; /* return */ - /* checks parameters */ - if ( ac < 1 ) - { - fluid_ostream_printf(out, "profile_notes: too few arguments\n"); - fluid_profile_unlock_command(); - return FLUID_FAILED; - } + /* locks to prevent simultaneous changes by an other shell */ + if(fluid_profile_lock_command(out) == FLUID_FAILED) + { + return FLUID_FAILED; + } - /* gets default parameters */ - nbr = fluid_profile_notes, bank = fluid_profile_bank; - prog = fluid_profile_prog; + /* checks parameters */ + if(ac < 1) + { + fluid_ostream_printf(out, "profile_notes: too few arguments\n"); + fluid_profile_unlock_command(); + return FLUID_FAILED; + } - r = fluid_is_number(av[0]); - if ( r ) - { /* checks nbr */ - nbr= atoi(av[0]); /* get nbr parameter */ - if ( ac >= 2 ) - { /* [bank prog] are optional */ - if ( ac >= 3 ) - { - r = fluid_is_number(av[1]) && fluid_is_number(av[2]); - if( r ) - { - bank= atoi(av[1]); /* gets bank parameter */ - prog= atoi(av[2]); /* gets prog parameter */ - } - } - else - { /* prog is needed */ - fluid_ostream_printf(out, "profile_set_notes: too few arguments\n"); - fluid_profile_unlock_command(); - return FLUID_FAILED; - } - } - } + /* gets default parameters */ + nbr = fluid_profile_notes, bank = fluid_profile_bank; + prog = fluid_profile_prog; - if ( !r ) - { - fluid_ostream_printf(out, "profile_set_notes: invalid argument\n"); - fluid_profile_unlock_command(); - return FLUID_FAILED; - } + r = fluid_is_number(av[0]); - /* Saves new parameters */ - fluid_profile_notes = nbr; fluid_profile_bank = bank; fluid_profile_prog = prog; + if(r) + { + /* checks nbr */ + nbr = atoi(av[0]); /* get nbr parameter */ - /* unlocks */ - fluid_profile_unlock_command(); - return FLUID_OK; + if(ac >= 2) + { + /* [bank prog] are optional */ + if(ac >= 3) + { + r = fluid_is_number(av[1]) && fluid_is_number(av[2]); + + if(r) + { + bank = atoi(av[1]); /* gets bank parameter */ + prog = atoi(av[2]); /* gets prog parameter */ + } + } + else + { + /* prog is needed */ + fluid_ostream_printf(out, "profile_set_notes: too few arguments\n"); + fluid_profile_unlock_command(); + return FLUID_FAILED; + } + } + } + + if(!r) + { + fluid_ostream_printf(out, "profile_set_notes: invalid argument\n"); + fluid_profile_unlock_command(); + return FLUID_FAILED; + } + + /* Saves new parameters */ + fluid_profile_notes = nbr; + fluid_profile_bank = bank; + fluid_profile_prog = prog; + + /* unlocks */ + fluid_profile_unlock_command(); + return FLUID_OK; } /* @@ -3184,38 +3774,40 @@ fluid_handle_prof_set_notes(void* data, int ac, char** av, fluid_ostream_t out) * @return FLUID_OK if success , otherwise FLUID_FAILED. */ int -fluid_handle_prof_set_print(void* data, int ac, char** av, fluid_ostream_t out) +fluid_handle_prof_set_print(void *data, int ac, char **av, fluid_ostream_t out) { - int r; - /* locks to prevent simultaneous changes by an other shell */ - if ( fluid_profile_lock_command(out) == FLUID_FAILED ) - { - return FLUID_FAILED; - } + int r; - /* checks parameters */ - if ( ac < 1 ) - { - fluid_ostream_printf(out, "profile_set_print: too few arguments\n"); - fluid_profile_unlock_command(); - return FLUID_FAILED; - } + /* locks to prevent simultaneous changes by an other shell */ + if(fluid_profile_lock_command(out) == FLUID_FAILED) + { + return FLUID_FAILED; + } - /* gets parameters */ - if ( fluid_is_number(av[0]) ) - { /* checks and gets mode */ - fluid_profile_print = atoi(av[0]); /* gets and saves mode parameter */ - r = FLUID_OK; - } - else - { - fluid_ostream_printf(out, "profile_set_print: invalid argument\n"); - r = FLUID_FAILED; - } + /* checks parameters */ + if(ac < 1) + { + fluid_ostream_printf(out, "profile_set_print: too few arguments\n"); + fluid_profile_unlock_command(); + return FLUID_FAILED; + } - /* unlocks */ - fluid_profile_unlock_command(); - return r; + /* gets parameters */ + if(fluid_is_number(av[0])) + { + /* checks and gets mode */ + fluid_profile_print = atoi(av[0]); /* gets and saves mode parameter */ + r = FLUID_OK; + } + else + { + fluid_ostream_printf(out, "profile_set_print: invalid argument\n"); + r = FLUID_FAILED; + } + + /* unlocks */ + fluid_profile_unlock_command(); + return r; } /* @@ -3228,40 +3820,49 @@ fluid_handle_prof_set_print(void* data, int ac, char** av, fluid_ostream_t out) * @return the number of voices generated. It can be lower than notes number * when the preset have instrument only on few key range. */ -static unsigned short fluid_profile_send_notes(fluid_synth_t* synth, int notes, - int bank, int prog, - fluid_ostream_t out) +static unsigned short fluid_profile_send_notes(fluid_synth_t *synth, int notes, + int bank, int prog, + fluid_ostream_t out) { - int n; /* number of notes generated */ - int n_voices,n_actives=0; /* Maximum voices, voices generated */ - int n_chan, chan, key ; - /* MIDI channels count and maximum polyphony */ - n_chan = fluid_synth_count_midi_channels(synth); /* channels count */ - n_voices = fluid_synth_get_polyphony(synth); /* maximum voices */ - /* */ - fluid_ostream_printf(out,"Generating %d notes, ",notes); + int n; /* number of notes generated */ + int n_voices, n_actives = 0; /* Maximum voices, voices generated */ + int n_chan, chan, key ; + /* MIDI channels count and maximum polyphony */ + n_chan = fluid_synth_count_midi_channels(synth); /* channels count */ + n_voices = fluid_synth_get_polyphony(synth); /* maximum voices */ + /* */ + fluid_ostream_printf(out, "Generating %d notes, ", notes); - for (n = 0 , key = FLUID_PROFILE_LAST_KEY+1, chan = -1; n < notes; n++, key++) - { - if ( key > FLUID_PROFILE_LAST_KEY ) - { /* next channel */ - chan++; - if (chan >= n_chan) break; /* stops generation */ - /* select preset */ - fluid_synth_bank_select(synth,chan,bank); - fluid_synth_program_change(synth,chan,prog); - key = FLUID_PROFILE_FIRST_KEY; - } - fluid_synth_noteon(synth, chan, key, FLUID_PROFILE_DEFAULT_VEL); - n_actives = fluid_synth_get_active_voice_count(synth); /* running voices */ - if ( n_actives >= n_voices ) - { - fluid_ostream_printf(out,"max polyphony reached:%d, ", n_voices); - break; /* stops notes generation */ - } - } - fluid_ostream_printf(out,"generated voices:%d\n", n_actives); - return n_actives; + for(n = 0, key = FLUID_PROFILE_LAST_KEY + 1, chan = -1; n < notes; n++, key++) + { + if(key > FLUID_PROFILE_LAST_KEY) + { + /* next channel */ + chan++; + + if(chan >= n_chan) + { + break; /* stops generation */ + } + + /* select preset */ + fluid_synth_bank_select(synth, chan, bank); + fluid_synth_program_change(synth, chan, prog); + key = FLUID_PROFILE_FIRST_KEY; + } + + fluid_synth_noteon(synth, chan, key, FLUID_PROFILE_DEFAULT_VEL); + n_actives = fluid_synth_get_active_voice_count(synth); /* running voices */ + + if(n_actives >= n_voices) + { + fluid_ostream_printf(out, "max polyphony reached:%d, ", n_voices); + break; /* stops notes generation */ + } + } + + fluid_ostream_printf(out, "generated voices:%d\n", n_actives); + return n_actives; } /* @@ -3281,204 +3882,228 @@ static unsigned short fluid_profile_send_notes(fluid_synth_t* synth, int notes, * @return FLUID_OK if success , otherwise FLUID_FAILED. */ int -fluid_handle_prof_start(void *data, int ac, char** av, fluid_ostream_t out) +fluid_handle_prof_start(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_synth_t* synth = handler->synth; + FLUID_ENTRY_COMMAND(data); + fluid_synth_t *synth = handler->synth; - unsigned short n_prof,n, dur; /* previous parameters */ - unsigned int total_dur, rem_dur; /* total and remainder duration (ms) */ - unsigned short notes; /* notes number to generate */ - int n_actives = 0; /* actives voices */ - float gain; /* current gain */ - int r = 1; /* checking parameter result */ + unsigned short n_prof, n, dur; /* previous parameters */ + unsigned int total_dur, rem_dur; /* total and remainder duration (ms) */ + unsigned short notes; /* notes number to generate */ + int n_actives = 0; /* actives voices */ + float gain; /* current gain */ + int r = 1; /* checking parameter result */ - /* Locks to prevent simultaneous command by an other shell */ - if ( fluid_profile_lock_command(out) == FLUID_FAILED) - { - return FLUID_FAILED; - } + /* Locks to prevent simultaneous command by an other shell */ + if(fluid_profile_lock_command(out) == FLUID_FAILED) + { + return FLUID_FAILED; + } - /* Gets previous parameters values */ - n_prof = fluid_profile_n_prof; /* number of measuses */ - dur = fluid_profile_dur; /* duration of one measure (ms) */ - /* check parameters */ - if (ac >= 1 ) - { - r = fluid_is_number(av[0]); - if (r) - { - n_prof= atoi(av[0]); /* gets n_prof parameter */ - if (ac >= 2 ) - { - r = fluid_is_number(av[1]); - if (r) - { - dur = atoi(av[1]);/* gets dur parameter */ - } - } - } - } - if ( !r || n_prof < 1 || dur < 1 ) - { - fluid_ostream_printf(out, "profile_start: invalid argument\n"); - fluid_profile_unlock_command(); - return FLUID_FAILED; - } + /* Gets previous parameters values */ + n_prof = fluid_profile_n_prof; /* number of measuses */ + dur = fluid_profile_dur; /* duration of one measure (ms) */ - /* Saves new parameters */ - fluid_profile_n_prof = n_prof; - fluid_profile_dur = dur; + /* check parameters */ + if(ac >= 1) + { + r = fluid_is_number(av[0]); - /* Saves current gain */ - gain = fluid_synth_get_gain(synth); + if(r) + { + n_prof = atoi(av[0]); /* gets n_prof parameter */ - /* Generates notes if any */ - notes = fluid_profile_notes; - if (notes ) - { - /* checks if the synth is playing */ - /* Warn the user */ - if (fluid_synth_get_active_voice_count(synth)) - { - fluid_ostream_printf(out, - "Warning: can't generate notes, please stop any playing\n"); - } - else - { - float send_gain; - /* sets low gain before sending notes */ - fluid_synth_set_gain(synth, 0.01); - /* sends notes */ - n_actives = fluid_profile_send_notes(synth, notes, fluid_profile_bank, - fluid_profile_prog, out); - /* compensates gain to avoid a loud sound */ - send_gain = 1.0 * pow(10, (n_actives * FLUID_PROFILE_VOICE_ATTEN)/20 ); - fluid_synth_set_gain(synth, send_gain); - - /* Before starting profiling immediately we wait to ensures that voices are - currently synthesized by audio rendering API. This ensure that macro - probes will register the expected number of actives voices. - */ - fluid_msleep(200); /* wait 200 ms */ - } - } + if(ac >= 2) + { + r = fluid_is_number(av[1]); - /* Starts - waits - prints n_prof measures */ - fluid_ostream_printf(out,"Number of measures(n_prof):%d, duration of one mesure(dur):%dms\n", - n_prof,dur); + if(r) + { + dur = atoi(av[1]);/* gets dur parameter */ + } + } + } + } - /* Clears any previous pending key */ - fluid_profile_is_cancel_req(); + if(!r || n_prof < 1 || dur < 1) + { + fluid_ostream_printf(out, "profile_start: invalid argument\n"); + fluid_profile_unlock_command(); + return FLUID_FAILED; + } - total_dur = rem_dur = n_prof * dur; - for ( n = 0 ; n < n_prof; rem_dur -= dur, n++ ) - { - unsigned int end_ticks;/* ending position (in ticks) */ - unsigned int tm, ts, rm, rs; - int status; - ts = total_dur / 1000; - tm = ts / 60; ts = ts % 60; /* total minutes and seconds */ + /* Saves new parameters */ + fluid_profile_n_prof = n_prof; + fluid_profile_dur = dur; - rs = rem_dur / 1000; - rm = rs / 60; rs = rs % 60; /* remainder minutes and seconds */ + /* Saves current gain */ + gain = fluid_synth_get_gain(synth); - /* Prints total and remainder duration */ + /* Generates notes if any */ + notes = fluid_profile_notes; + + if(notes) + { + /* checks if the synth is playing */ + /* Warn the user */ + if(fluid_synth_get_active_voice_count(synth)) + { + fluid_ostream_printf(out, + "Warning: can't generate notes, please stop any playing\n"); + } + else + { + float send_gain; + /* sets low gain before sending notes */ + fluid_synth_set_gain(synth, 0.01); + /* sends notes */ + n_actives = fluid_profile_send_notes(synth, notes, fluid_profile_bank, + fluid_profile_prog, out); + /* compensates gain to avoid a loud sound */ + send_gain = 1.0 * pow(10, (n_actives * FLUID_PROFILE_VOICE_ATTEN) / 20); + fluid_synth_set_gain(synth, send_gain); + + /* Before starting profiling immediately we wait to ensures that voices are + currently synthesized by audio rendering API. This ensure that macro + probes will register the expected number of actives voices. + */ + fluid_msleep(200); /* wait 200 ms */ + } + } + + /* Starts - waits - prints n_prof measures */ + fluid_ostream_printf(out, "Number of measures(n_prof):%d, duration of one mesure(dur):%dms\n", + n_prof, dur); + + /* Clears any previous pending key */ + fluid_profile_is_cancel_req(); + + total_dur = rem_dur = n_prof * dur; + + for(n = 0 ; n < n_prof; rem_dur -= dur, n++) + { + unsigned int end_ticks;/* ending position (in ticks) */ + unsigned int tm, ts, rm, rs; + int status; + ts = total_dur / 1000; + tm = ts / 60; + ts = ts % 60; /* total minutes and seconds */ + + rs = rem_dur / 1000; + rm = rs / 60; + rs = rs % 60; /* remainder minutes and seconds */ + + /* Prints total and remainder duration */ #ifdef FLUID_PROFILE_CANCEL - fluid_ostream_printf(out, - "\nProfiling time(mm:ss): Total=%d:%d Remainder=%d:%d, press to cancel\n", - tm,ts,rm,rs); + fluid_ostream_printf(out, + "\nProfiling time(mm:ss): Total=%d:%d Remainder=%d:%d, press to cancel\n", + tm, ts, rm, rs); #else - fluid_ostream_printf(out, - "\nProfiling time(mm:ss): Total=%d:%d Remainder=%d:%d\n", - tm,ts,rm,rs); + fluid_ostream_printf(out, + "\nProfiling time(mm:ss): Total=%d:%d Remainder=%d:%d\n", + tm, ts, rm, rs); #endif - /* converts duration(ms) in end position in ticks. */ - end_ticks = fluid_atomic_int_get(&synth->ticks_since_start)+ - dur * synth->sample_rate / 1000; - /* requests to start the measurement in audio rendering API */ - fluid_profile_start_stop(end_ticks, n); + /* converts duration(ms) in end position in ticks. */ + end_ticks = fluid_atomic_int_get(&synth->ticks_since_start) + + dur * synth->sample_rate / 1000; + /* requests to start the measurement in audio rendering API */ + fluid_profile_start_stop(end_ticks, n); - /* waits while running */ - do - { - /* passive waiting */ - fluid_msleep(500); /* wait 500 ms */ - status = fluid_profile_get_status(); - } - while ( status == PROFILE_RUNNING ); + /* waits while running */ + do + { + /* passive waiting */ + fluid_msleep(500); /* wait 500 ms */ + status = fluid_profile_get_status(); + } + while(status == PROFILE_RUNNING); - /* checks if data are ready */ - if( status == PROFILE_READY) - { - /* profiling data are ready, prints profile data */ - fluid_profiling_print_data(synth->sample_rate,out); - } - /* checks if the measurement has been cancelled */ - else if( status == PROFILE_CANCELED || status == PROFILE_STOP ) - { - fluid_ostream_printf(out, "Profiling cancelled.\n"); - break; /* cancel the command */ - } - } + /* checks if data are ready */ + if(status == PROFILE_READY) + { + /* profiling data are ready, prints profile data */ + fluid_profiling_print_data(synth->sample_rate, out); + } + /* checks if the measurement has been cancelled */ + else if(status == PROFILE_CANCELED || status == PROFILE_STOP) + { + fluid_ostream_printf(out, "Profiling cancelled.\n"); + break; /* cancel the command */ + } + } - /* Stops voices if any had been generated */ - if ( n_actives ) - { - fluid_ostream_printf(out, "Stopping %d voices...", n_actives); - fluid_synth_system_reset(synth); - /* waits until all voices become inactives */ - do - { - fluid_msleep( 10 ); /* wait 10 ms */ - n_actives = fluid_synth_get_active_voice_count(synth); - } - while ( n_actives ); - fluid_ostream_printf(out, "voices stopped.\n"); - } + /* Stops voices if any had been generated */ + if(n_actives) + { + fluid_ostream_printf(out, "Stopping %d voices...", n_actives); + fluid_synth_system_reset(synth); - /* Restores initial gain */ - fluid_synth_set_gain(synth, gain); + /* waits until all voices become inactives */ + do + { + fluid_msleep(10); /* wait 10 ms */ + n_actives = fluid_synth_get_active_voice_count(synth); + } + while(n_actives); - /* Unlocks */ - fluid_profile_unlock_command(); - return FLUID_OK; + fluid_ostream_printf(out, "voices stopped.\n"); + } + + /* Restores initial gain */ + fluid_synth_set_gain(synth, gain); + + /* Unlocks */ + fluid_profile_unlock_command(); + return FLUID_OK; } #endif /* WITH_PROFILING */ int -fluid_is_number(char* a) +fluid_is_number(char *a) { - while (*a != 0) { - if (((*a < '0') || (*a > '9')) && (*a != '-') && (*a != '+') && (*a != '.')) { - return FALSE; + while(*a != 0) + { + if(((*a < '0') || (*a > '9')) && (*a != '-') && (*a != '+') && (*a != '.')) + { + return FALSE; + } + + a++; } - a++; - } - return TRUE; + + return TRUE; } -char* -fluid_expand_path(char* path, char* new_path, int len) +char * +fluid_expand_path(char *path, char *new_path, int len) { #if defined(WIN32) || defined(MACOS9) - FLUID_SNPRINTF (new_path, len - 1, "%s", path); + FLUID_SNPRINTF(new_path, len - 1, "%s", path); #else - if ((path[0] == '~') && (path[1] == '/')) { - char* home = getenv("HOME"); - if (home == NULL) { - FLUID_SNPRINTF (new_path, len - 1, "%s", path); - } else { - FLUID_SNPRINTF (new_path, len - 1, "%s%s", home, &path[1]); + + if((path[0] == '~') && (path[1] == '/')) + { + char *home = getenv("HOME"); + + if(home == NULL) + { + FLUID_SNPRINTF(new_path, len - 1, "%s", path); + } + else + { + FLUID_SNPRINTF(new_path, len - 1, "%s%s", home, &path[1]); + } } - } else { - FLUID_SNPRINTF (new_path, len - 1, "%s", path); - } + else + { + FLUID_SNPRINTF(new_path, len - 1, "%s", path); + } + #endif - new_path[len - 1] = 0; - return new_path; + new_path[len - 1] = 0; + return new_path; } @@ -3487,22 +4112,24 @@ fluid_expand_path(char* path, char* new_path, int len) * Command */ -fluid_cmd_t* fluid_cmd_copy(const fluid_cmd_t* cmd) +fluid_cmd_t *fluid_cmd_copy(const fluid_cmd_t *cmd) { - fluid_cmd_t* copy = FLUID_NEW(fluid_cmd_t); - if (copy == NULL) { - FLUID_LOG (FLUID_PANIC, "Out of memory"); - return NULL; - } + fluid_cmd_t *copy = FLUID_NEW(fluid_cmd_t); - copy->name = FLUID_STRDUP(cmd->name); - copy->topic = FLUID_STRDUP(cmd->topic); - copy->help = FLUID_STRDUP(cmd->help); - copy->handler = cmd->handler; - return copy; + if(copy == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return NULL; + } + + copy->name = FLUID_STRDUP(cmd->name); + copy->topic = FLUID_STRDUP(cmd->topic); + copy->help = FLUID_STRDUP(cmd->help); + copy->handler = cmd->handler; + return copy; } -void delete_fluid_cmd(fluid_cmd_t* cmd) +void delete_fluid_cmd(fluid_cmd_t *cmd) { fluid_return_if_fail(cmd != NULL); FLUID_FREE(cmd->name); @@ -3516,9 +4143,9 @@ void delete_fluid_cmd(fluid_cmd_t* cmd) */ static void -fluid_cmd_handler_destroy_hash_value (void *value) +fluid_cmd_handler_destroy_hash_value(void *value) { - delete_fluid_cmd ((fluid_cmd_t *)value); + delete_fluid_cmd((fluid_cmd_t *)value); } /** @@ -3527,42 +4154,47 @@ fluid_cmd_handler_destroy_hash_value (void *value) * @param router If not NULL, all the default midi_router commands will be added to the new handler. * @return New command handler, or NULL if alloc failed */ -fluid_cmd_handler_t* new_fluid_cmd_handler(fluid_synth_t* synth, fluid_midi_router_t* router) +fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_router_t *router) { - unsigned int i; - fluid_cmd_handler_t* handler; + unsigned int i; + fluid_cmd_handler_t *handler; - handler = FLUID_NEW(fluid_cmd_handler_t); - if (handler == NULL) { - return NULL; - } - FLUID_MEMSET(handler, 0, sizeof(*handler)); + handler = FLUID_NEW(fluid_cmd_handler_t); - handler->commands = new_fluid_hashtable_full (fluid_str_hash, fluid_str_equal, - NULL, fluid_cmd_handler_destroy_hash_value); - if (handler->commands == NULL) { - FLUID_FREE(handler); - return NULL; - } - - handler->synth = synth; - handler->router = router; - - for (i = 0; i < FLUID_N_ELEMENTS(fluid_commands); i++) + if(handler == NULL) { - const fluid_cmd_t* cmd = &fluid_commands[i]; + return NULL; + } + + FLUID_MEMSET(handler, 0, sizeof(*handler)); + + handler->commands = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal, + NULL, fluid_cmd_handler_destroy_hash_value); + + if(handler->commands == NULL) + { + FLUID_FREE(handler); + return NULL; + } + + handler->synth = synth; + handler->router = router; + + for(i = 0; i < FLUID_N_ELEMENTS(fluid_commands); i++) + { + const fluid_cmd_t *cmd = &fluid_commands[i]; int is_router_cmd = FLUID_STRCMP(cmd->topic, "router") == 0; - + if((is_router_cmd && router == NULL) || (!is_router_cmd && synth == NULL)) { /* omit registering router and synth commands if they were not requested */ continue; } - + fluid_cmd_handler_register(handler, &fluid_commands[i]); } - return handler; + return handler; } /** @@ -3570,12 +4202,12 @@ fluid_cmd_handler_t* new_fluid_cmd_handler(fluid_synth_t* synth, fluid_midi_rout * @param handler Command handler to delete */ void -delete_fluid_cmd_handler(fluid_cmd_handler_t* handler) +delete_fluid_cmd_handler(fluid_cmd_handler_t *handler) { fluid_return_if_fail(handler != NULL); - - delete_fluid_hashtable(handler->commands); - FLUID_FREE(handler); + + delete_fluid_hashtable(handler->commands); + FLUID_FREE(handler); } /** @@ -3585,11 +4217,11 @@ delete_fluid_cmd_handler(fluid_cmd_handler_t* handler) * @return #FLUID_OK if command was inserted, #FLUID_FAILED otherwise */ int -fluid_cmd_handler_register(fluid_cmd_handler_t* handler, const fluid_cmd_t* cmd) +fluid_cmd_handler_register(fluid_cmd_handler_t *handler, const fluid_cmd_t *cmd) { - fluid_cmd_t* copy = fluid_cmd_copy(cmd); - fluid_hashtable_insert(handler->commands, copy->name, copy); - return FLUID_OK; + fluid_cmd_t *copy = fluid_cmd_copy(cmd); + fluid_hashtable_insert(handler->commands, copy->name, copy); + return FLUID_OK; } /** @@ -3599,171 +4231,183 @@ fluid_cmd_handler_register(fluid_cmd_handler_t* handler, const fluid_cmd_t* cmd) * @return TRUE if command was found and unregistered, FALSE otherwise */ int -fluid_cmd_handler_unregister(fluid_cmd_handler_t* handler, const char *cmd) +fluid_cmd_handler_unregister(fluid_cmd_handler_t *handler, const char *cmd) { - return fluid_hashtable_remove(handler->commands, cmd); + return fluid_hashtable_remove(handler->commands, cmd); } int -fluid_cmd_handler_handle(void* data, int ac, char** av, fluid_ostream_t out) +fluid_cmd_handler_handle(void *data, int ac, char **av, fluid_ostream_t out) { - FLUID_ENTRY_COMMAND(data); - fluid_cmd_t* cmd; + FLUID_ENTRY_COMMAND(data); + fluid_cmd_t *cmd; - cmd = fluid_hashtable_lookup(handler->commands, av[0]); + cmd = fluid_hashtable_lookup(handler->commands, av[0]); - if (cmd && cmd->handler) - return (*cmd->handler)(handler, ac - 1, av + 1, out); + if(cmd && cmd->handler) + { + return (*cmd->handler)(handler, ac - 1, av + 1, out); + } - fluid_ostream_printf(out, "unknown command: %s (try help)\n", av[0]); - return FLUID_FAILED; + fluid_ostream_printf(out, "unknown command: %s (try help)\n", av[0]); + return FLUID_FAILED; } #ifdef NETWORK_SUPPORT -struct _fluid_server_t { - fluid_server_socket_t* socket; - fluid_settings_t* settings; - fluid_synth_t* synth; - fluid_midi_router_t* router; - fluid_list_t* clients; - fluid_mutex_t mutex; +struct _fluid_server_t +{ + fluid_server_socket_t *socket; + fluid_settings_t *settings; + fluid_synth_t *synth; + fluid_midi_router_t *router; + fluid_list_t *clients; + fluid_mutex_t mutex; }; -static void fluid_server_close(fluid_server_t* server) +static void fluid_server_close(fluid_server_t *server) { - fluid_list_t* list; - fluid_list_t* clients; - fluid_client_t* client; + fluid_list_t *list; + fluid_list_t *clients; + fluid_client_t *client; - fluid_return_if_fail(server != NULL); + fluid_return_if_fail(server != NULL); - fluid_mutex_lock(server->mutex); - clients = server->clients; - server->clients = NULL; - fluid_mutex_unlock(server->mutex); + fluid_mutex_lock(server->mutex); + clients = server->clients; + server->clients = NULL; + fluid_mutex_unlock(server->mutex); - list = clients; + list = clients; - while (list) { - client = fluid_list_get(list); - fluid_client_quit(client); - list = fluid_list_next(list); - } + while(list) + { + client = fluid_list_get(list); + fluid_client_quit(client); + list = fluid_list_next(list); + } - delete_fluid_list(clients); + delete_fluid_list(clients); - if (server->socket) { - delete_fluid_server_socket(server->socket); - server->socket = NULL; - } + if(server->socket) + { + delete_fluid_server_socket(server->socket); + server->socket = NULL; + } } static int -fluid_server_handle_connection(fluid_server_t* server, fluid_socket_t client_socket, char* addr) +fluid_server_handle_connection(fluid_server_t *server, fluid_socket_t client_socket, char *addr) { - fluid_client_t* client; + fluid_client_t *client; - client = new_fluid_client(server, server->settings, client_socket); - if (client == NULL) { - return -1; - } - fluid_server_add_client(server, client); + client = new_fluid_client(server, server->settings, client_socket); - return 0; + if(client == NULL) + { + return -1; + } + + fluid_server_add_client(server, client); + + return 0; } -void fluid_server_add_client(fluid_server_t* server, fluid_client_t* client) +void fluid_server_add_client(fluid_server_t *server, fluid_client_t *client) { - fluid_mutex_lock(server->mutex); - server->clients = fluid_list_append(server->clients, client); - fluid_mutex_unlock(server->mutex); + fluid_mutex_lock(server->mutex); + server->clients = fluid_list_append(server->clients, client); + fluid_mutex_unlock(server->mutex); } -void fluid_server_remove_client(fluid_server_t* server, fluid_client_t* client) +void fluid_server_remove_client(fluid_server_t *server, fluid_client_t *client) { - fluid_mutex_lock(server->mutex); - server->clients = fluid_list_remove(server->clients, client); - fluid_mutex_unlock(server->mutex); + fluid_mutex_lock(server->mutex); + server->clients = fluid_list_remove(server->clients, client); + fluid_mutex_unlock(server->mutex); } -struct _fluid_client_t { - fluid_server_t* server; - fluid_settings_t* settings; - fluid_cmd_handler_t* handler; - fluid_socket_t socket; - fluid_thread_t* thread; +struct _fluid_client_t +{ + fluid_server_t *server; + fluid_settings_t *settings; + fluid_cmd_handler_t *handler; + fluid_socket_t socket; + fluid_thread_t *thread; }; -static fluid_thread_return_t fluid_client_run(void* data) +static fluid_thread_return_t fluid_client_run(void *data) { - fluid_shell_t shell; - fluid_client_t* client = (fluid_client_t*)data; - - fluid_shell_init(&shell, - client->settings, - client->handler, - fluid_socket_get_istream(client->socket), - fluid_socket_get_ostream(client->socket)); - fluid_shell_run(&shell); - fluid_server_remove_client(client->server, client); - delete_fluid_client(client); - - return FLUID_THREAD_RETURN_VALUE; + fluid_shell_t shell; + fluid_client_t *client = (fluid_client_t *)data; + + fluid_shell_init(&shell, + client->settings, + client->handler, + fluid_socket_get_istream(client->socket), + fluid_socket_get_ostream(client->socket)); + fluid_shell_run(&shell); + fluid_server_remove_client(client->server, client); + delete_fluid_client(client); + + return FLUID_THREAD_RETURN_VALUE; } -fluid_client_t* -new_fluid_client(fluid_server_t* server, fluid_settings_t* settings, fluid_socket_t sock) +fluid_client_t * +new_fluid_client(fluid_server_t *server, fluid_settings_t *settings, fluid_socket_t sock) { - fluid_client_t* client; + fluid_client_t *client; - client = FLUID_NEW(fluid_client_t); - if (client == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + client = FLUID_NEW(fluid_client_t); - client->server = server; - client->socket = sock; - client->settings = settings; - client->handler = new_fluid_cmd_handler(server->synth, server->router); - client->thread = new_fluid_thread("client", fluid_client_run, client, - 0, FALSE); + if(client == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - if (client->handler == NULL || client->thread == NULL) { - goto error_recovery; - } + client->server = server; + client->socket = sock; + client->settings = settings; + client->handler = new_fluid_cmd_handler(server->synth, server->router); + client->thread = new_fluid_thread("client", fluid_client_run, client, + 0, FALSE); - return client; + if(client->handler == NULL || client->thread == NULL) + { + goto error_recovery; + } + + return client; error_recovery: - FLUID_LOG(FLUID_ERR, "Out of memory"); - delete_fluid_client(client); - return NULL; + FLUID_LOG(FLUID_ERR, "Out of memory"); + delete_fluid_client(client); + return NULL; } -void fluid_client_quit(fluid_client_t* client) +void fluid_client_quit(fluid_client_t *client) { fluid_socket_close(client->socket); - - FLUID_LOG(FLUID_DBG, "fluid_client_quit: joining"); - fluid_thread_join(client->thread); - FLUID_LOG(FLUID_DBG, "fluid_client_quit: done"); + + FLUID_LOG(FLUID_DBG, "fluid_client_quit: joining"); + fluid_thread_join(client->thread); + FLUID_LOG(FLUID_DBG, "fluid_client_quit: done"); } -void delete_fluid_client(fluid_client_t* client) +void delete_fluid_client(fluid_client_t *client) { fluid_return_if_fail(client != NULL); - + delete_fluid_cmd_handler(client->handler); fluid_socket_close(client->socket); delete_fluid_thread(client->thread); - - FLUID_FREE(client); + + FLUID_FREE(client); } #endif /* NETWORK_SUPPORT */ @@ -3775,41 +4419,45 @@ void delete_fluid_client(fluid_client_t* client) * @param router If not NULL, the midi_router instance for the command handler to be used by the client * @return New shell server instance or NULL on error */ -fluid_server_t* -new_fluid_server(fluid_settings_t* settings, - fluid_synth_t* synth, fluid_midi_router_t* router) +fluid_server_t * +new_fluid_server(fluid_settings_t *settings, + fluid_synth_t *synth, fluid_midi_router_t *router) { #ifdef NETWORK_SUPPORT - fluid_server_t* server; - int port; + fluid_server_t *server; + int port; - server = FLUID_NEW(fluid_server_t); - if (server == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + server = FLUID_NEW(fluid_server_t); - server->settings = settings; - server->clients = NULL; - server->synth = synth; - server->router = router; + if(server == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - fluid_mutex_init(server->mutex); + server->settings = settings; + server->clients = NULL; + server->synth = synth; + server->router = router; - fluid_settings_getint(settings, "shell.port", &port); + fluid_mutex_init(server->mutex); - server->socket = new_fluid_server_socket(port, - (fluid_server_func_t) fluid_server_handle_connection, - server); - if (server->socket == NULL) { - FLUID_FREE(server); - return NULL; - } + fluid_settings_getint(settings, "shell.port", &port); - return server; + server->socket = new_fluid_server_socket(port, + (fluid_server_func_t) fluid_server_handle_connection, + server); + + if(server->socket == NULL) + { + FLUID_FREE(server); + return NULL; + } + + return server; #else - FLUID_LOG(FLUID_WARN, "Network support disabled on this platform."); - return NULL; + FLUID_LOG(FLUID_WARN, "Network support disabled on this platform."); + return NULL; #endif } @@ -3818,14 +4466,14 @@ new_fluid_server(fluid_settings_t* settings, * @param server Shell server instance */ void -delete_fluid_server(fluid_server_t* server) +delete_fluid_server(fluid_server_t *server) { #ifdef NETWORK_SUPPORT - fluid_return_if_fail(server != NULL); + fluid_return_if_fail(server != NULL); - fluid_server_close(server); + fluid_server_close(server); - FLUID_FREE(server); + FLUID_FREE(server); #endif } @@ -3834,11 +4482,11 @@ delete_fluid_server(fluid_server_t* server) * @param server Shell server instance * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_server_join(fluid_server_t* server) +int fluid_server_join(fluid_server_t *server) { #ifdef NETWORK_SUPPORT - return fluid_server_socket_join(server->socket); + return fluid_server_socket_join(server->socket); #else - return FLUID_FAILED; + return FLUID_FAILED; #endif } diff --git a/src/bindings/fluid_cmd.h b/src/bindings/fluid_cmd.h index 624cc28f..7e81ab08 100644 --- a/src/bindings/fluid_cmd.h +++ b/src/bindings/fluid_cmd.h @@ -24,84 +24,84 @@ #include "fluidsynth_priv.h" -void fluid_shell_settings(fluid_settings_t* settings); +void fluid_shell_settings(fluid_settings_t *settings); /** some help functions */ -int fluid_is_number(char* a); -char* fluid_expand_path(char* path, char* new_path, int len); +int fluid_is_number(char *a); +char *fluid_expand_path(char *path, char *new_path, int len); /** the handlers for the command lines */ -int fluid_handle_help(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_quit(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_noteon(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_noteoff(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_pitch_bend(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_pitch_bend_range(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_cc(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_prog(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_select(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_inst(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_channels(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_load(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_unload(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reload(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_fonts(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reverbpreset(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reverbsetroomsize(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reverbsetdamp(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reverbsetwidth(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reverbsetlevel(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_chorusnr(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_choruslevel(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_chorusspeed(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_chorusdepth(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_chorus(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reverb(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_gain(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_interp(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_interpc(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_tuning(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_tune(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_settuning(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_resettuning(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_tunings(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_dumptuning(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_reset(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_source(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_echo(void* data, int ac, char** av, fluid_ostream_t out); +int fluid_handle_help(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_quit(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_noteon(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_noteoff(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_pitch_bend(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_pitch_bend_range(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_cc(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_prog(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_select(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_inst(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_channels(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_load(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_unload(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reload(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_fonts(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reverbpreset(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reverbsetroomsize(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reverbsetdamp(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reverbsetwidth(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reverbsetlevel(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_chorusnr(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_choruslevel(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_chorusspeed(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_chorusdepth(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_chorus(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reverb(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_gain(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_interp(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_interpc(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_tuning(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_tune(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_settuning(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_resettuning(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_tunings(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_dumptuning(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_reset(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_source(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_echo(void *data, int ac, char **av, fluid_ostream_t out); -int fluid_handle_set(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_get(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_info(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_settings(void* data, int ac, char** av, fluid_ostream_t out); +int fluid_handle_set(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_get(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_info(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_settings(void *data, int ac, char **av, fluid_ostream_t out); -int fluid_handle_router_clear(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_router_default(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_router_begin(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_router_end(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_router_chan(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_router_par1(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_router_par2(void* data, int ac, char** av, fluid_ostream_t out); +int fluid_handle_router_clear(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_router_default(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_router_begin(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_router_end(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_router_chan(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_router_par1(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_router_par2(void *data, int ac, char **av, fluid_ostream_t out); #if WITH_PROFILING -int fluid_handle_profile(void *data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_prof_set_notes(void *data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_prof_set_print(void *data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_prof_start(void *data, int ac, char** av, fluid_ostream_t out); +int fluid_handle_profile(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_prof_set_notes(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_prof_set_print(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_prof_start(void *data, int ac, char **av, fluid_ostream_t out); #endif -int fluid_handle_basicchannels (void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_resetbasicchannels (void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_setbasicchannels (void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_channelsmode (void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_legatomode(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_setlegatomode(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_portamentomode(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_setportamentomode(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_breathmode(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_setbreathmode(void* data, int ac, char** av, fluid_ostream_t out); -int fluid_handle_sleep(void *data, int ac, char** av, fluid_ostream_t out); +int fluid_handle_basicchannels(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_resetbasicchannels(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_setbasicchannels(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_channelsmode(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_legatomode(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_setlegatomode(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_portamentomode(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_setportamentomode(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_breathmode(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_setbreathmode(void *data, int ac, char **av, fluid_ostream_t out); +int fluid_handle_sleep(void *data, int ac, char **av, fluid_ostream_t out); #ifdef LADSPA int fluid_handle_ladspa_effect(void *data, int ac, char **av, fluid_ostream_t out); @@ -123,39 +123,40 @@ int fluid_handle_ladspa_reset(void *data, int ac, char **av, fluid_ostream_t out * @param out Output stream to send response to * @return Should return #FLUID_OK on success, #FLUID_FAILED otherwise */ -typedef int (*fluid_cmd_func_t)(void* data, int ac, char** av, fluid_ostream_t out); +typedef int (*fluid_cmd_func_t)(void *data, int ac, char **av, fluid_ostream_t out); /** * Shell command information structure. */ -typedef struct { - char* name; /**< The name of the command, as typed in the shell */ - char* topic; /**< The help topic group of this command */ - fluid_cmd_func_t handler; /**< Pointer to the handler for this command */ - char* help; /**< A help string */ +typedef struct +{ + char *name; /**< The name of the command, as typed in the shell */ + char *topic; /**< The help topic group of this command */ + fluid_cmd_func_t handler; /**< Pointer to the handler for this command */ + char *help; /**< A help string */ } fluid_cmd_t; -fluid_cmd_t* fluid_cmd_copy(const fluid_cmd_t* cmd); -void delete_fluid_cmd(fluid_cmd_t* cmd); +fluid_cmd_t *fluid_cmd_copy(const fluid_cmd_t *cmd); +void delete_fluid_cmd(fluid_cmd_t *cmd); -int fluid_cmd_handler_handle(void* data, - int ac, char** av, - fluid_ostream_t out); +int fluid_cmd_handler_handle(void *data, + int ac, char **av, + fluid_ostream_t out); -int fluid_cmd_handler_register(fluid_cmd_handler_t* handler, const fluid_cmd_t* cmd); -int fluid_cmd_handler_unregister(fluid_cmd_handler_t* handler, const char *cmd); +int fluid_cmd_handler_register(fluid_cmd_handler_t *handler, const fluid_cmd_t *cmd); +int fluid_cmd_handler_unregister(fluid_cmd_handler_t *handler, const char *cmd); -void fluid_server_remove_client(fluid_server_t* server, fluid_client_t* client); -void fluid_server_add_client(fluid_server_t* server, fluid_client_t* client); +void fluid_server_remove_client(fluid_server_t *server, fluid_client_t *client); +void fluid_server_add_client(fluid_server_t *server, fluid_client_t *client); -fluid_client_t* new_fluid_client(fluid_server_t* server, - fluid_settings_t* settings, - fluid_socket_t sock); +fluid_client_t *new_fluid_client(fluid_server_t *server, + fluid_settings_t *settings, + fluid_socket_t sock); -void delete_fluid_client(fluid_client_t* client); -void fluid_client_quit(fluid_client_t* client); +void delete_fluid_client(fluid_client_t *client); +void fluid_client_quit(fluid_client_t *client); #endif /* _FLUID_CMD_H */ diff --git a/src/bindings/fluid_filerenderer.c b/src/bindings/fluid_filerenderer.c index 7e779f64..6882a4b9 100644 --- a/src/bindings/fluid_filerenderer.c +++ b/src/bindings/fluid_filerenderer.c @@ -18,9 +18,9 @@ * 02110-1301, USA */ - /* - * Low-level routines for file output. - */ +/* + * Low-level routines for file output. + */ #include "fluid_sys.h" #include "fluid_synth.h" @@ -30,19 +30,20 @@ #include #endif -struct _fluid_file_renderer_t { - fluid_synth_t* synth; +struct _fluid_file_renderer_t +{ + fluid_synth_t *synth; #if LIBSNDFILE_SUPPORT - SNDFILE* sndfile; - float* buf; + SNDFILE *sndfile; + float *buf; #else - FILE* file; - short* buf; + FILE *file; + short *buf; #endif - int period_size; - int buf_size; + int period_size; + int buf_size; }; #if LIBSNDFILE_SUPPORT @@ -52,107 +53,119 @@ struct _fluid_file_renderer_t { /* File audio format names. * !! Keep in sync with format_ids[] */ -static const char * const format_names[] = { - "s8", - "s16", - "s24", - "s32", - "u8", - "float", - "double" +static const char *const format_names[] = +{ + "s8", + "s16", + "s24", + "s32", + "u8", + "float", + "double" }; - + /* File audio format IDs. * !! Keep in sync with format_names[] */ -static const int format_ids[] = { - SF_FORMAT_PCM_S8, - SF_FORMAT_PCM_16, - SF_FORMAT_PCM_24, - SF_FORMAT_PCM_32, - SF_FORMAT_PCM_U8, - SF_FORMAT_FLOAT, - SF_FORMAT_DOUBLE +static const int format_ids[] = +{ + SF_FORMAT_PCM_S8, + SF_FORMAT_PCM_16, + SF_FORMAT_PCM_24, + SF_FORMAT_PCM_32, + SF_FORMAT_PCM_U8, + SF_FORMAT_FLOAT, + SF_FORMAT_DOUBLE }; /* File endian byte order names. * !! Keep in sync with endian_ids[] */ -static const char * const endian_names[] = { - "auto", - "little", - "big", - "cpu" +static const char *const endian_names[] = +{ + "auto", + "little", + "big", + "cpu" }; /* File endian byte order ids. * !! Keep in sync with endian_names[] */ -static const int endian_ids[] = { - SF_ENDIAN_FILE, - SF_ENDIAN_LITTLE, - SF_ENDIAN_BIG, - SF_ENDIAN_CPU +static const int endian_ids[] = +{ + SF_ENDIAN_FILE, + SF_ENDIAN_LITTLE, + SF_ENDIAN_BIG, + SF_ENDIAN_CPU }; -static int fluid_file_renderer_parse_options (char *filetype, char *format, - char *endian, char *filename, SF_INFO *info); -static int fluid_file_renderer_find_file_type (char *extension, int *type); -static int fluid_file_renderer_find_valid_format (SF_INFO *info); +static int fluid_file_renderer_parse_options(char *filetype, char *format, + char *endian, char *filename, SF_INFO *info); +static int fluid_file_renderer_find_file_type(char *extension, int *type); +static int fluid_file_renderer_find_valid_format(SF_INFO *info); #endif void -fluid_file_renderer_settings (fluid_settings_t* settings) +fluid_file_renderer_settings(fluid_settings_t *settings) { #if LIBSNDFILE_SUPPORT - SF_FORMAT_INFO finfo, cmpinfo; - int major_count; - int i, i2; - unsigned int n; + SF_FORMAT_INFO finfo, cmpinfo; + int major_count; + int i, i2; + unsigned int n; - fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.wav", 0); - fluid_settings_register_str(settings, "audio.file.type", "auto", 0); - fluid_settings_register_str(settings, "audio.file.format", "s16", 0); - fluid_settings_register_str(settings, "audio.file.endian", "auto", 0); + fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.wav", 0); + fluid_settings_register_str(settings, "audio.file.type", "auto", 0); + fluid_settings_register_str(settings, "audio.file.format", "s16", 0); + fluid_settings_register_str(settings, "audio.file.endian", "auto", 0); - fluid_settings_add_option (settings, "audio.file.type", "auto"); + fluid_settings_add_option(settings, "audio.file.type", "auto"); - sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int)); + sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof(int)); - for (i = 0; i < major_count; i++) - { - finfo.format = i; - sf_command (NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof (finfo)); - - /* Check for duplicates */ - for (i2 = 0; i2 < i; i2++) + for(i = 0; i < major_count; i++) { - cmpinfo.format = i2; - sf_command (NULL, SFC_GET_FORMAT_MAJOR, &cmpinfo, sizeof (cmpinfo)); + finfo.format = i; + sf_command(NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof(finfo)); - if (FLUID_STRCMP (cmpinfo.extension, finfo.extension) == 0) - break; + /* Check for duplicates */ + for(i2 = 0; i2 < i; i2++) + { + cmpinfo.format = i2; + sf_command(NULL, SFC_GET_FORMAT_MAJOR, &cmpinfo, sizeof(cmpinfo)); + + if(FLUID_STRCMP(cmpinfo.extension, finfo.extension) == 0) + { + break; + } + } + + if(i2 == i) + { + fluid_settings_add_option(settings, "audio.file.type", finfo.extension); + } } - if (i2 == i) - fluid_settings_add_option (settings, "audio.file.type", finfo.extension); - } + for(n = 0; n < FLUID_N_ELEMENTS(format_names); n++) + { + fluid_settings_add_option(settings, "audio.file.format", format_names[n]); + } - for (n = 0; n < FLUID_N_ELEMENTS(format_names); n++) - fluid_settings_add_option (settings, "audio.file.format", format_names[n]); - - for (n = 0; n < FLUID_N_ELEMENTS(endian_names); n++) - fluid_settings_add_option (settings, "audio.file.endian", endian_names[n]); + for(n = 0; n < FLUID_N_ELEMENTS(endian_names); n++) + { + fluid_settings_add_option(settings, "audio.file.endian", endian_names[n]); + } #else - fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.raw", 0); - fluid_settings_register_str(settings, "audio.file.type", "raw", 0); - fluid_settings_add_option (settings, "audio.file.type", "raw"); - fluid_settings_register_str(settings, "audio.file.format", "s16", 0); - fluid_settings_add_option (settings, "audio.file.format", "s16"); - fluid_settings_register_str(settings, "audio.file.endian", "cpu", 0); - fluid_settings_add_option (settings, "audio.file.endian", "cpu"); + fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.raw", 0); + fluid_settings_register_str(settings, "audio.file.type", "raw", 0); + fluid_settings_add_option(settings, "audio.file.type", "raw"); + fluid_settings_register_str(settings, "audio.file.format", "s16", 0); + fluid_settings_add_option(settings, "audio.file.format", "s16"); + fluid_settings_register_str(settings, "audio.file.endian", "cpu", 0); + fluid_settings_add_option(settings, "audio.file.endian", "cpu"); #endif } @@ -176,108 +189,136 @@ fluid_file_renderer_settings (fluid_settings_t* settings) * - synth.sample-rate: Sample rate to use */ fluid_file_renderer_t * -new_fluid_file_renderer(fluid_synth_t* synth) +new_fluid_file_renderer(fluid_synth_t *synth) { #if LIBSNDFILE_SUPPORT - char *type, *format, *endian; - SF_INFO info; - double samplerate; - int retval; + char *type, *format, *endian; + SF_INFO info; + double samplerate; + int retval; #endif - char *filename = NULL; - fluid_file_renderer_t* dev; + char *filename = NULL; + fluid_file_renderer_t *dev; - fluid_return_val_if_fail (synth != NULL, NULL); - fluid_return_val_if_fail (synth->settings != NULL, NULL); + fluid_return_val_if_fail(synth != NULL, NULL); + fluid_return_val_if_fail(synth->settings != NULL, NULL); - dev = FLUID_NEW(fluid_file_renderer_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_file_renderer_t)); + dev = FLUID_NEW(fluid_file_renderer_t); - dev->synth = synth; - fluid_settings_getint (synth->settings, "audio.period-size", &dev->period_size); + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_file_renderer_t)); + + dev->synth = synth; + fluid_settings_getint(synth->settings, "audio.period-size", &dev->period_size); #if LIBSNDFILE_SUPPORT - dev->buf_size = 2 * dev->period_size * sizeof (float); - dev->buf = FLUID_ARRAY(float, 2 * dev->period_size); + dev->buf_size = 2 * dev->period_size * sizeof(float); + dev->buf = FLUID_ARRAY(float, 2 * dev->period_size); #else - dev->buf_size = 2 * dev->period_size * sizeof (short); - dev->buf = FLUID_ARRAY(short, 2 * dev->period_size); + dev->buf_size = 2 * dev->period_size * sizeof(short); + dev->buf = FLUID_ARRAY(short, 2 * dev->period_size); #endif - if (dev->buf == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } + if(dev->buf == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } - fluid_settings_dupstr (synth->settings, "audio.file.name", &filename); - if (filename == NULL) { - FLUID_LOG(FLUID_ERR, "No file name specified"); - goto error_recovery; - } + fluid_settings_dupstr(synth->settings, "audio.file.name", &filename); + + if(filename == NULL) + { + FLUID_LOG(FLUID_ERR, "No file name specified"); + goto error_recovery; + } #if LIBSNDFILE_SUPPORT - memset (&info, 0, sizeof (info)); + memset(&info, 0, sizeof(info)); - info.format = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE | SF_FORMAT_PCM_16; + info.format = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE | SF_FORMAT_PCM_16; - fluid_settings_dupstr (synth->settings, "audio.file.type", &type); - fluid_settings_dupstr (synth->settings, "audio.file.format", &format); - fluid_settings_dupstr (synth->settings, "audio.file.endian", &endian); + fluid_settings_dupstr(synth->settings, "audio.file.type", &type); + fluid_settings_dupstr(synth->settings, "audio.file.format", &format); + fluid_settings_dupstr(synth->settings, "audio.file.endian", &endian); - retval = fluid_file_renderer_parse_options (type, format, endian, filename, &info); + retval = fluid_file_renderer_parse_options(type, format, endian, filename, &info); - if (type) FLUID_FREE (type); - if (format) FLUID_FREE (format); - if (endian) FLUID_FREE (endian); + if(type) + { + FLUID_FREE(type); + } - if (!retval) goto error_recovery; + if(format) + { + FLUID_FREE(format); + } - fluid_settings_getnum (synth->settings, "synth.sample-rate", &samplerate); - info.samplerate = samplerate + 0.5; - info.channels = 2; + if(endian) + { + FLUID_FREE(endian); + } - /* Search for valid format for given file type, if invalid and no format was specified. - * To handle Ogg/Vorbis and possibly future file types with new formats. - * Checking if format is SF_FORMAT_PCM_16 isn't a fool proof way to check if - * format was specified or not (if user specifies "s16" itself), but should suffice. */ - if (!sf_format_check (&info) + if(!retval) + { + goto error_recovery; + } + + fluid_settings_getnum(synth->settings, "synth.sample-rate", &samplerate); + info.samplerate = samplerate + 0.5; + info.channels = 2; + + /* Search for valid format for given file type, if invalid and no format was specified. + * To handle Ogg/Vorbis and possibly future file types with new formats. + * Checking if format is SF_FORMAT_PCM_16 isn't a fool proof way to check if + * format was specified or not (if user specifies "s16" itself), but should suffice. */ + if(!sf_format_check(&info) && ((info.format & SF_FORMAT_SUBMASK) != SF_FORMAT_PCM_16 - || !fluid_file_renderer_find_valid_format (&info))) - { - FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file format settings"); - goto error_recovery; - } + || !fluid_file_renderer_find_valid_format(&info))) + { + FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file format settings"); + goto error_recovery; + } - dev->sndfile = sf_open (filename, SFM_WRITE, &info); + dev->sndfile = sf_open(filename, SFM_WRITE, &info); - if (!dev->sndfile) - { - FLUID_LOG(FLUID_ERR, "Failed to open audio file '%s' for writing", filename); - goto error_recovery; - } + if(!dev->sndfile) + { + FLUID_LOG(FLUID_ERR, "Failed to open audio file '%s' for writing", filename); + goto error_recovery; + } - /* Turn on clipping and normalization of floats (-1.0 - 1.0) */ - sf_command (dev->sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE); - sf_command (dev->sndfile, SFC_SET_NORM_FLOAT, NULL, SF_TRUE); + /* Turn on clipping and normalization of floats (-1.0 - 1.0) */ + sf_command(dev->sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE); + sf_command(dev->sndfile, SFC_SET_NORM_FLOAT, NULL, SF_TRUE); #else - dev->file = fopen(filename, "wb"); - if (dev->file == NULL) { - FLUID_LOG(FLUID_ERR, "Failed to open the file '%s'", filename); - goto error_recovery; - } + dev->file = fopen(filename, "wb"); + + if(dev->file == NULL) + { + FLUID_LOG(FLUID_ERR, "Failed to open the file '%s'", filename); + goto error_recovery; + } + #endif - return dev; + return dev; - error_recovery: - if (filename) FLUID_FREE (filename); - delete_fluid_file_renderer(dev); - return NULL; +error_recovery: + + if(filename) + { + FLUID_FREE(filename); + } + + delete_fluid_file_renderer(dev); + return NULL; } /** @@ -288,14 +329,19 @@ new_fluid_file_renderer(fluid_synth_t* synth) * @since 1.1.7 */ int -fluid_file_set_encoding_quality(fluid_file_renderer_t* dev, double q) +fluid_file_set_encoding_quality(fluid_file_renderer_t *dev, double q) { #if LIBSNDFILE_SUPPORT - if (sf_command (dev->sndfile, SFC_SET_VBR_ENCODING_QUALITY, &q, sizeof (double)) == SF_TRUE) - return FLUID_OK; - else + + if(sf_command(dev->sndfile, SFC_SET_VBR_ENCODING_QUALITY, &q, sizeof(double)) == SF_TRUE) + { + return FLUID_OK; + } + else #endif - return FLUID_FAILED; + { + return FLUID_FAILED; + } } /** @@ -303,24 +349,33 @@ fluid_file_set_encoding_quality(fluid_file_renderer_t* dev, double q) * @param dev File renderer object. * @since 1.1.0 */ -void delete_fluid_file_renderer(fluid_file_renderer_t* dev) +void delete_fluid_file_renderer(fluid_file_renderer_t *dev) { - fluid_return_if_fail(dev != NULL); + fluid_return_if_fail(dev != NULL); #if LIBSNDFILE_SUPPORT - if (dev->sndfile != NULL) { - int retval = sf_close (dev->sndfile); - if (retval != 0) FLUID_LOG (FLUID_WARN, "Error closing audio file: %s", - sf_error_number (retval)); + + if(dev->sndfile != NULL) + { + int retval = sf_close(dev->sndfile); + + if(retval != 0) + { + FLUID_LOG(FLUID_WARN, "Error closing audio file: %s", sf_error_number(retval)); } + } + #else - if (dev->file != NULL) { - fclose(dev->file); - } + + if(dev->file != NULL) + { + fclose(dev->file); + } + #endif FLUID_FREE(dev->buf); - FLUID_FREE(dev); + FLUID_FREE(dev); } /** @@ -330,36 +385,40 @@ void delete_fluid_file_renderer(fluid_file_renderer_t* dev) * @since 1.1.0 */ int -fluid_file_renderer_process_block(fluid_file_renderer_t* dev) +fluid_file_renderer_process_block(fluid_file_renderer_t *dev) { #if LIBSNDFILE_SUPPORT - int n; + int n; - fluid_synth_write_float(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2); + fluid_synth_write_float(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2); - n = sf_writef_float (dev->sndfile, dev->buf, dev->period_size); + n = sf_writef_float(dev->sndfile, dev->buf, dev->period_size); - if (n != dev->period_size) { - FLUID_LOG (FLUID_ERR, "Audio file write error: %s", - sf_strerror (dev->sndfile)); - return FLUID_FAILED; - } - return FLUID_OK; + if(n != dev->period_size) + { + FLUID_LOG(FLUID_ERR, "Audio file write error: %s", + sf_strerror(dev->sndfile)); + return FLUID_FAILED; + } + + return FLUID_OK; #else /* No libsndfile support */ - size_t res, nmemb = dev->buf_size; + size_t res, nmemb = dev->buf_size; - fluid_synth_write_s16(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2); + fluid_synth_write_s16(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2); - res = fwrite(dev->buf, 1, nmemb, dev->file); - if (res < nmemb) { - FLUID_LOG(FLUID_ERR, "Audio output file write error: %s", - strerror (errno)); - return FLUID_FAILED; - } + res = fwrite(dev->buf, 1, nmemb, dev->file); - return FLUID_OK; + if(res < nmemb) + { + FLUID_LOG(FLUID_ERR, "Audio output file write error: %s", + strerror(errno)); + return FLUID_FAILED; + } + + return FLUID_OK; #endif } @@ -378,74 +437,87 @@ fluid_file_renderer_process_block(fluid_file_renderer_t* dev) * @return TRUE on success, FALSE otherwise */ static int -fluid_file_renderer_parse_options (char *filetype, char *format, char *endian, - char *filename, SF_INFO *info) +fluid_file_renderer_parse_options(char *filetype, char *format, char *endian, + char *filename, SF_INFO *info) { - int type = -1; /* -1 indicates "auto" type */ - char *s; - unsigned int i; + int type = -1; /* -1 indicates "auto" type */ + char *s; + unsigned int i; - /* If "auto" type, then use extension to search for a match */ - if (!filetype || FLUID_STRCMP (filetype, "auto") == 0) - { - type = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE; - s = FLUID_STRRCHR (filename, '.'); - - if (s && s[1] != '\0') - { - if (!fluid_file_renderer_find_file_type (s + 1, &type)) - FLUID_LOG (FLUID_WARN, "Failed to determine audio file type from filename, defaulting to WAV"); - } - } - else if (!fluid_file_renderer_find_file_type (filetype, &type)) - { - FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file type '%s'", filetype); - return FALSE; - } - - - info->format = (info->format & ~SF_FORMAT_TYPEMASK) | type; - - /* Look for subtype */ - if (format) - { - for (i = 0; i < FLUID_N_ELEMENTS(format_names); i++) - if (FLUID_STRCMP (format, format_names[i]) == 0) - break; - - if (i >= FLUID_N_ELEMENTS(format_names)) + /* If "auto" type, then use extension to search for a match */ + if(!filetype || FLUID_STRCMP(filetype, "auto") == 0) { - FLUID_LOG (FLUID_ERR, "Invalid or unsupported file audio format '%s'", format); - return FALSE; + type = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE; + s = FLUID_STRRCHR(filename, '.'); + + if(s && s[1] != '\0') + { + if(!fluid_file_renderer_find_file_type(s + 1, &type)) + { + FLUID_LOG(FLUID_WARN, "Failed to determine audio file type from filename, defaulting to WAV"); + } + } + } + else if(!fluid_file_renderer_find_file_type(filetype, &type)) + { + FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file type '%s'", filetype); + return FALSE; } - info->format = (info->format & ~SF_FORMAT_SUBMASK) | format_ids[i]; - } + + info->format = (info->format & ~SF_FORMAT_TYPEMASK) | type; + + /* Look for subtype */ + if(format) + { + for(i = 0; i < FLUID_N_ELEMENTS(format_names); i++) + { + if(FLUID_STRCMP(format, format_names[i]) == 0) + { + break; + } + } + + if(i >= FLUID_N_ELEMENTS(format_names)) + { + FLUID_LOG(FLUID_ERR, "Invalid or unsupported file audio format '%s'", format); + return FALSE; + } + + info->format = (info->format & ~SF_FORMAT_SUBMASK) | format_ids[i]; + } #if LIBSNDFILE_HASVORBIS - /* Force subformat to vorbis as nothing else would make sense currently */ - if ((info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_OGG) { - info->format = (info->format & ~SF_FORMAT_SUBMASK) | SF_FORMAT_VORBIS; - } -#endif - /* Look for endian */ - if (endian) - { - for (i = 0; i < FLUID_N_ELEMENTS(endian_names); i++) - if (FLUID_STRCMP (endian, endian_names[i]) == 0) - break; - - if (i >= FLUID_N_ELEMENTS(endian_names)) + /* Force subformat to vorbis as nothing else would make sense currently */ + if((info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_OGG) { - FLUID_LOG (FLUID_ERR, "Invalid or unsupported endian byte order '%s'", endian); - return FALSE; + info->format = (info->format & ~SF_FORMAT_SUBMASK) | SF_FORMAT_VORBIS; } - info->format = (info->format & ~SF_FORMAT_ENDMASK) | endian_ids[i]; - } +#endif - return TRUE; + /* Look for endian */ + if(endian) + { + for(i = 0; i < FLUID_N_ELEMENTS(endian_names); i++) + { + if(FLUID_STRCMP(endian, endian_names[i]) == 0) + { + break; + } + } + + if(i >= FLUID_N_ELEMENTS(endian_names)) + { + FLUID_LOG(FLUID_ERR, "Invalid or unsupported endian byte order '%s'", endian); + return FALSE; + } + + info->format = (info->format & ~SF_FORMAT_ENDMASK) | endian_ids[i]; + } + + return TRUE; } /** @@ -455,53 +527,58 @@ fluid_file_renderer_parse_options (char *filetype, char *format, char *endian, * @return TRUE if found, FALSE otherwise */ static int -fluid_file_renderer_find_file_type (char *extension, int *type) +fluid_file_renderer_find_file_type(char *extension, int *type) { - SF_FORMAT_INFO finfo; - int major_count; - int i; + SF_FORMAT_INFO finfo; + int major_count; + int i; - sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof (int)); + sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof(int)); - for (i = 0; i < major_count; i++) - { - finfo.format = i; - sf_command (NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof (finfo)); + for(i = 0; i < major_count; i++) + { + finfo.format = i; + sf_command(NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof(finfo)); - if (FLUID_STRCMP (extension, finfo.extension) == 0) - break; - } + if(FLUID_STRCMP(extension, finfo.extension) == 0) + { + break; + } + } - if (i < major_count) - { - *type = finfo.format; - return TRUE; - } + if(i < major_count) + { + *type = finfo.format; + return TRUE; + } - return FALSE; + return FALSE; } /* Search for a valid audio format for a given file type */ static int -fluid_file_renderer_find_valid_format (SF_INFO *info) +fluid_file_renderer_find_valid_format(SF_INFO *info) { - SF_FORMAT_INFO format_info; - int count, i; + SF_FORMAT_INFO format_info; + int count, i; - sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)); + sf_command(NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof(int)); - for (i = 0; i < count; i++) - { - format_info.format = i; + for(i = 0; i < count; i++) + { + format_info.format = i; - sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)); + sf_command(NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof(format_info)); - info->format = (info->format & ~SF_FORMAT_SUBMASK) | format_info.format; + info->format = (info->format & ~SF_FORMAT_SUBMASK) | format_info.format; - if (sf_format_check (info)) return TRUE; - } + if(sf_format_check(info)) + { + return TRUE; + } + } - return FALSE; + return FALSE; } #endif diff --git a/src/bindings/fluid_ladspa.c b/src/bindings/fluid_ladspa.c index bb79ba56..5f68de4a 100644 --- a/src/bindings/fluid_ladspa.c +++ b/src/bindings/fluid_ladspa.c @@ -35,20 +35,23 @@ #define FLUID_LADSPA_MAX_EFFECTS 100 #define FLUID_LADSPA_MAX_NODES 100 -typedef enum _fluid_ladspa_state_t { +typedef enum _fluid_ladspa_state_t +{ FLUID_LADSPA_INACTIVE = 0, FLUID_LADSPA_ACTIVE, FLUID_LADSPA_RUNNING } fluid_ladspa_state_t; -typedef enum _fluid_ladspa_dir_t { +typedef enum _fluid_ladspa_dir_t +{ FLUID_LADSPA_INPUT, FLUID_LADSPA_OUTPUT, } fluid_ladspa_dir_t; -typedef enum _fluid_ladspa_node_type_t { +typedef enum _fluid_ladspa_node_type_t +{ FLUID_LADSPA_NODE_AUDIO = 1, FLUID_LADSPA_NODE_CONTROL = 2, FLUID_LADSPA_NODE_EFFECT = 4, @@ -155,7 +158,7 @@ static int get_effect_port_idx(const fluid_ladspa_effect_t *effect, const char * static LADSPA_Data get_default_port_value(fluid_ladspa_effect_t *effect, unsigned int port_idx, int sample_rate); static void connect_node_to_port(fluid_ladspa_node_t *node, fluid_ladspa_dir_t dir, - fluid_ladspa_effect_t *effect, int port_idx); + fluid_ladspa_effect_t *effect, int port_idx); static int create_control_port_nodes(fluid_ladspa_fx_t *fx, fluid_ladspa_effect_t *effect); /* Plugin helpers */ @@ -184,10 +187,12 @@ fluid_ladspa_fx_t *new_fluid_ladspa_fx(fluid_real_t sample_rate, int buffer_size fluid_ladspa_fx_t *fx; fx = FLUID_NEW(fluid_ladspa_fx_t); - if (fx == NULL) + + if(fx == NULL) { return NULL; } + FLUID_MEMSET(fx, 0, sizeof(fluid_ladspa_fx_t)); /* Setup recursive mutex to protect access to public API */ @@ -201,12 +206,15 @@ fluid_ladspa_fx_t *new_fluid_ladspa_fx(fluid_real_t sample_rate, int buffer_size /* Setup mutex and cond used to signal that fluid_ladspa_run has finished */ fx->run_finished_mutex = new_fluid_cond_mutex(); - if (fx->run_finished_mutex == NULL) + + if(fx->run_finished_mutex == NULL) { goto error_recovery; } + fx->run_finished_cond = new_fluid_cond(); - if (fx->run_finished_cond == NULL) + + if(fx->run_finished_cond == NULL) { goto error_recovery; } @@ -232,22 +240,22 @@ error_recovery: void delete_fluid_ladspa_fx(fluid_ladspa_fx_t *fx) { int i; - fluid_return_if_fail (fx != NULL); + fluid_return_if_fail(fx != NULL); clear_ladspa(fx); /* clear the remaining input or output nodes */ - for (i = 0; i < fx->num_nodes; i++) + for(i = 0; i < fx->num_nodes; i++) { delete_fluid_ladspa_node(fx->nodes[i]); } - if (fx->run_finished_cond != NULL) + if(fx->run_finished_cond != NULL) { delete_fluid_cond(fx->run_finished_cond); } - if (fx->run_finished_mutex != NULL) + if(fx->run_finished_mutex != NULL) { delete_fluid_cond_mutex(fx->run_finished_mutex); } @@ -271,23 +279,24 @@ void delete_fluid_ladspa_fx(fluid_ladspa_fx_t *fx) * @return FLUID_OK on success, otherwise FLUID_FAILED */ int fluid_ladspa_add_host_ports(fluid_ladspa_fx_t *fx, const char *prefix, - int num_buffers, fluid_real_t buffers[], int buf_stride) + int num_buffers, fluid_real_t buffers[], int buf_stride) { int i; char name[99]; LADSPA_API_ENTER(fx); - if (fluid_ladspa_is_active(fx)) + if(fluid_ladspa_is_active(fx)) { LADSPA_API_RETURN(fx, FLUID_FAILED); } /* Create nodes for all channels */ - for (i = 0; i < num_buffers; i++) + for(i = 0; i < num_buffers; i++) { /* If there is more than one buffer, then append a 1-based index to each node name */ - if (num_buffers > 1) { + if(num_buffers > 1) + { FLUID_SNPRINTF(name, sizeof(name), "%s%d", prefix, (i + 1)); } else @@ -295,9 +304,9 @@ int fluid_ladspa_add_host_ports(fluid_ladspa_fx_t *fx, const char *prefix, FLUID_STRNCPY(name, prefix, sizeof(name)); } - if (new_fluid_ladspa_node(fx, name, - FLUID_LADSPA_NODE_AUDIO | FLUID_LADSPA_NODE_HOST, - &buffers[i * buf_stride]) == NULL) + if(new_fluid_ladspa_node(fx, name, + FLUID_LADSPA_NODE_AUDIO | FLUID_LADSPA_NODE_HOST, + &buffers[i * buf_stride]) == NULL) { LADSPA_API_RETURN(fx, FLUID_FAILED); } @@ -326,14 +335,14 @@ int fluid_ladspa_set_sample_rate(fluid_ladspa_fx_t *fx, fluid_real_t sample_rate /* Add 0.5 to minimize rounding errors */ new_sample_rate = (unsigned long)(sample_rate + 0.5); - if (fx->sample_rate == new_sample_rate) + if(fx->sample_rate == new_sample_rate) { LADSPA_API_RETURN(fx, FLUID_OK); } - if (fluid_ladspa_is_active(fx)) + if(fluid_ladspa_is_active(fx)) { - if (fluid_ladspa_reset(fx) != FLUID_OK) + if(fluid_ladspa_reset(fx) != FLUID_OK) { FLUID_LOG(FLUID_ERR, "Failed to reset LADSPA, unable to change sample rate"); LADSPA_API_RETURN(fx, FLUID_FAILED); @@ -383,28 +392,29 @@ int fluid_ladspa_activate(fluid_ladspa_fx_t *fx) LADSPA_API_ENTER(fx); - if (fluid_ladspa_is_active(fx)) + if(fluid_ladspa_is_active(fx)) { LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (fluid_ladspa_check(fx, NULL, 0) != FLUID_OK) + if(fluid_ladspa_check(fx, NULL, 0) != FLUID_OK) { FLUID_LOG(FLUID_ERR, "LADSPA check failed, unable to activate effects"); LADSPA_API_RETURN(fx, FLUID_FAILED); } - for (i = 0; i < fx->num_effects; i++) + for(i = 0; i < fx->num_effects; i++) { activate_effect(fx->effects[i]); } - if (!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_INACTIVE, FLUID_LADSPA_ACTIVE)) + if(!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_INACTIVE, FLUID_LADSPA_ACTIVE)) { - for (i = 0; i < fx->num_effects; i++) + for(i = 0; i < fx->num_effects; i++) { deactivate_effect(fx->effects[i]); } + LADSPA_API_RETURN(fx, FLUID_FAILED); } @@ -428,7 +438,7 @@ int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx) LADSPA_API_ENTER(fx); /* If we are already inactive, then simply return success */ - if (fluid_atomic_int_get(&fx->state) == FLUID_LADSPA_INACTIVE) + if(fluid_atomic_int_get(&fx->state) == FLUID_LADSPA_INACTIVE) { LADSPA_API_RETURN(fx, FLUID_OK); } @@ -438,14 +448,16 @@ int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx) fx->pending_deactivation = 1; fluid_cond_mutex_lock(fx->run_finished_mutex); - while (!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_ACTIVE, FLUID_LADSPA_INACTIVE)) + + while(!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_ACTIVE, FLUID_LADSPA_INACTIVE)) { fluid_cond_wait(fx->run_finished_cond, fx->run_finished_mutex); } + fluid_cond_mutex_unlock(fx->run_finished_mutex); /* Now that we're inactive, deactivate all effects and return success */ - for (i = 0; i < fx->num_effects; i++) + for(i = 0; i < fx->num_effects; i++) { deactivate_effect(fx->effects[i]); } @@ -468,9 +480,9 @@ int fluid_ladspa_reset(fluid_ladspa_fx_t *fx) LADSPA_API_ENTER(fx); - if (fluid_ladspa_is_active(fx)) + if(fluid_ladspa_is_active(fx)) { - if (fluid_ladspa_deactivate(fx) != FLUID_OK) + if(fluid_ladspa_deactivate(fx) != FLUID_OK) { LADSPA_API_RETURN(fx, FLUID_FAILED); } @@ -503,13 +515,13 @@ void fluid_ladspa_run(fluid_ladspa_fx_t *fx, int block_count, int block_size) /* Somebody wants to deactivate the engine, so let's give them a chance to do that. * And check that there is at least one effect, to avoid the overhead of the * atomic compare and exchange on an unconfigured LADSPA engine. */ - if (fx->pending_deactivation || fx->num_effects == 0) + if(fx->pending_deactivation || fx->num_effects == 0) { return; } /* Inform the engine that we are now running pluings, and bail out if it's not active */ - if (!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_ACTIVE, FLUID_LADSPA_RUNNING)) + if(!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_ACTIVE, FLUID_LADSPA_RUNNING)) { return; } @@ -520,17 +532,17 @@ void fluid_ladspa_run(fluid_ladspa_fx_t *fx, int block_count, int block_size) copy_host_to_effect_buffers(fx, num_samples); #endif - for (i = 0; i < fx->num_audio_nodes; i++) + for(i = 0; i < fx->num_audio_nodes; i++) { FLUID_MEMSET(fx->audio_nodes[i]->effect_buffer, 0, fx->buffer_size * sizeof(LADSPA_Data)); } /* Run each effect in the order that they were added */ - for (i = 0; i < fx->num_effects; i++) + for(i = 0; i < fx->num_effects; i++) { effect = fx->effects[i]; - if (effect->mix) + if(effect->mix) { effect->desc->run_adding(effect->handle, num_samples); } @@ -544,14 +556,14 @@ void fluid_ladspa_run(fluid_ladspa_fx_t *fx, int block_count, int block_size) copy_effect_to_host_buffers(fx, num_samples); #endif - if (!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_RUNNING, FLUID_LADSPA_ACTIVE)) + if(!fluid_atomic_int_compare_and_exchange(&fx->state, FLUID_LADSPA_RUNNING, FLUID_LADSPA_ACTIVE)) { FLUID_LOG(FLUID_ERR, "Unable to reset LADSPA running state!"); } /* If deactivation was requested while in running state, notify that we've finished now * and deactivation can proceed */ - if (fx->pending_deactivation) + if(fx->pending_deactivation) { fluid_cond_mutex_lock(fx->run_finished_mutex); fluid_cond_broadcast(fx->run_finished_cond); @@ -578,13 +590,14 @@ int fluid_ladspa_effect_can_mix(fluid_ladspa_fx_t *fx, const char *name) LADSPA_API_ENTER(fx); effect = get_effect(fx, name); - if (effect == NULL) + + if(effect == NULL) { LADSPA_API_RETURN(fx, FALSE); } can_mix = (effect->desc->run_adding != NULL - && effect->desc->set_run_adding_gain != NULL); + && effect->desc->set_run_adding_gain != NULL); LADSPA_API_RETURN(fx, can_mix); } @@ -609,14 +622,15 @@ int fluid_ladspa_effect_set_mix(fluid_ladspa_fx_t *fx, const char *name, int mix LADSPA_API_ENTER(fx); effect = get_effect(fx, name); - if (effect == NULL) + + if(effect == NULL) { LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (mix) + if(mix) { - if (!fluid_ladspa_effect_can_mix(fx, name)) + if(!fluid_ladspa_effect_can_mix(fx, name)) { FLUID_LOG(FLUID_ERR, "Effect '%s' does not support mix mode", name); LADSPA_API_RETURN(fx, FLUID_FAILED); @@ -635,18 +649,19 @@ static void clear_ladspa(fluid_ladspa_fx_t *fx) int i; /* Deactivate and free all effects */ - for (i = 0; i < fx->num_effects; i++) + for(i = 0; i < fx->num_effects; i++) { deactivate_effect(fx->effects[i]); delete_fluid_ladspa_effect(fx->effects[i]); } + fx->num_effects = 0; /* Delete all nodes (but not the host audio nodes) */ - for (i = 0; i < fx->num_nodes; i++) + for(i = 0; i < fx->num_nodes; i++) { - if ((fx->nodes[i]->type & FLUID_LADSPA_NODE_HOST) && - (fx->nodes[i]->type & FLUID_LADSPA_NODE_AUDIO)) + if((fx->nodes[i]->type & FLUID_LADSPA_NODE_HOST) && + (fx->nodes[i]->type & FLUID_LADSPA_NODE_AUDIO)) { continue; } @@ -655,12 +670,13 @@ static void clear_ladspa(fluid_ladspa_fx_t *fx) } /* Fill the list with the host nodes and reset the connection counts */ - for (i = 0; i < fx->num_host_nodes; i++) + for(i = 0; i < fx->num_host_nodes; i++) { fx->host_nodes[i]->num_inputs = 0; fx->host_nodes[i]->num_outputs = 0; fx->nodes[i] = fx->host_nodes[i]; } + fx->num_nodes = fx->num_host_nodes; /* Reset list of user audio nodes */ @@ -684,12 +700,13 @@ int fluid_ladspa_host_port_exists(fluid_ladspa_fx_t *fx, const char *name) LADSPA_API_ENTER(fx); node = get_node(fx, name); - if (node == NULL) + + if(node == NULL) { LADSPA_API_RETURN(fx, FALSE); } - if (node->type & FLUID_LADSPA_NODE_HOST) + if(node->type & FLUID_LADSPA_NODE_HOST) { LADSPA_API_RETURN(fx, TRUE); } @@ -715,7 +732,8 @@ int fluid_ladspa_buffer_exists(fluid_ladspa_fx_t *fx, const char *name) LADSPA_API_ENTER(fx); node = get_node(fx, name); - if (node == NULL) + + if(node == NULL) { LADSPA_API_RETURN(fx, FALSE); } @@ -735,7 +753,7 @@ int fluid_ladspa_buffer_exists(fluid_ladspa_fx_t *fx, const char *name) * @return TRUE if port was found, otherwise FALSE */ int fluid_ladspa_effect_port_exists(fluid_ladspa_fx_t *fx, const char *effect_name, - const char *port_name) + const char *port_name) { fluid_ladspa_effect_t *effect; int port_exists; @@ -747,7 +765,8 @@ int fluid_ladspa_effect_port_exists(fluid_ladspa_fx_t *fx, const char *effect_na LADSPA_API_ENTER(fx); effect = get_effect(fx, effect_name); - if (effect == NULL) + + if(effect == NULL) { LADSPA_API_RETURN(fx, FALSE); } @@ -772,14 +791,16 @@ int fluid_ladspa_add_buffer(fluid_ladspa_fx_t *fx, const char *name) fluid_return_val_if_fail(name != NULL, FLUID_FAILED); LADSPA_API_ENTER(fx); - if (fluid_ladspa_is_active(fx)) + + if(fluid_ladspa_is_active(fx)) { LADSPA_API_RETURN(fx, FLUID_FAILED); } node = new_fluid_ladspa_node(fx, name, - FLUID_LADSPA_NODE_AUDIO | FLUID_LADSPA_NODE_USER, NULL); - if (node == NULL) + FLUID_LADSPA_NODE_AUDIO | FLUID_LADSPA_NODE_USER, NULL); + + if(node == NULL) { LADSPA_API_RETURN(fx, FLUID_FAILED); } @@ -797,7 +818,7 @@ int fluid_ladspa_add_buffer(fluid_ladspa_fx_t *fx, const char *name) * @return FLUID_OK on success, FLUID_FAILED on error */ int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const char *effect_name, - const char *port_name, float val) + const char *port_name, float val) { fluid_ladspa_node_t *node; fluid_ladspa_effect_t *effect; @@ -810,24 +831,27 @@ int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const char *effect_na LADSPA_API_ENTER(fx); effect = get_effect(fx, effect_name); - if (effect == NULL) + + if(effect == NULL) { LADSPA_API_RETURN(fx, FLUID_FAILED); } port_idx = get_effect_port_idx(effect, port_name); - if (port_idx < 0) + + if(port_idx < 0) { LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (!LADSPA_IS_PORT_CONTROL(effect->desc->PortDescriptors[port_idx])) + if(!LADSPA_IS_PORT_CONTROL(effect->desc->PortDescriptors[port_idx])) { LADSPA_API_RETURN(fx, FLUID_FAILED); } node = effect->port_nodes[port_idx]; - if (node == NULL) + + if(node == NULL) { LADSPA_API_RETURN(fx, FLUID_FAILED); } @@ -847,7 +871,7 @@ int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const char *effect_na * @return FLUID_OK on success, otherwise FLUID_FAILED */ int fluid_ladspa_add_effect(fluid_ladspa_fx_t *fx, const char *effect_name, - const char *lib_name, const char *plugin_name) + const char *lib_name, const char *plugin_name) { fluid_ladspa_effect_t *effect; @@ -856,32 +880,35 @@ int fluid_ladspa_add_effect(fluid_ladspa_fx_t *fx, const char *effect_name, fluid_return_val_if_fail(lib_name != NULL, FLUID_FAILED); LADSPA_API_ENTER(fx); - if (fluid_ladspa_is_active(fx)) + + if(fluid_ladspa_is_active(fx)) { LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (fx->num_effects >= FLUID_LADSPA_MAX_EFFECTS) + if(fx->num_effects >= FLUID_LADSPA_MAX_EFFECTS) { FLUID_LOG(FLUID_ERR, "Maximum number of LADSPA effects reached"); LADSPA_API_RETURN(fx, FLUID_FAILED); } effect = new_fluid_ladspa_effect(fx, lib_name, plugin_name); - if (effect == NULL) + + if(effect == NULL) { LADSPA_API_RETURN(fx, FLUID_FAILED); } effect->name = FLUID_STRDUP(effect_name); - if (effect->name == NULL) + + if(effect->name == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); delete_fluid_ladspa_effect(effect); LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (create_control_port_nodes(fx, effect) != FLUID_OK) + if(create_control_port_nodes(fx, effect) != FLUID_OK) { delete_fluid_ladspa_effect(effect); LADSPA_API_RETURN(fx, FLUID_FAILED); @@ -905,7 +932,7 @@ int fluid_ladspa_add_effect(fluid_ladspa_fx_t *fx, const char *effect_name, * @return FLUID_OK on success, otherwise FLUID_FAILED */ int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name, - const char *port_name, const char *name) + const char *port_name, const char *name) { fluid_ladspa_effect_t *effect; fluid_ladspa_node_t *node; @@ -920,27 +947,30 @@ int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name, LADSPA_API_ENTER(fx); - if (fluid_ladspa_is_active(fx)) + if(fluid_ladspa_is_active(fx)) { LADSPA_API_RETURN(fx, FLUID_FAILED); } effect = get_effect(fx, effect_name); - if (effect == NULL) + + if(effect == NULL) { FLUID_LOG(FLUID_ERR, "Effect '%s' not found", effect_name); LADSPA_API_RETURN(fx, FLUID_FAILED); } port_idx = get_effect_port_idx(effect, port_name); - if (port_idx < 0) + + if(port_idx < 0) { FLUID_LOG(FLUID_ERR, "Port '%s' not found on effect '%s'", port_name, effect_name); LADSPA_API_RETURN(fx, FLUID_FAILED); } node = get_node(fx, name); - if (node == NULL) + + if(node == NULL) { FLUID_LOG(FLUID_ERR, "Node '%s' not found", name); LADSPA_API_RETURN(fx, FLUID_FAILED); @@ -949,20 +979,20 @@ int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name, port_flags = effect->desc->PortDescriptors[port_idx]; /* Check that requested port type matches the node type */ - if (LADSPA_IS_PORT_CONTROL(port_flags) && !(node->type & FLUID_LADSPA_NODE_CONTROL)) + if(LADSPA_IS_PORT_CONTROL(port_flags) && !(node->type & FLUID_LADSPA_NODE_CONTROL)) { FLUID_LOG(FLUID_ERR, "Control port '%s' on effect '%s' can only connect to " - "other control ports", port_name, effect_name); + "other control ports", port_name, effect_name); LADSPA_API_RETURN(fx, FLUID_FAILED); } - else if (LADSPA_IS_PORT_AUDIO(port_flags) && !(node->type & FLUID_LADSPA_NODE_AUDIO)) + else if(LADSPA_IS_PORT_AUDIO(port_flags) && !(node->type & FLUID_LADSPA_NODE_AUDIO)) { FLUID_LOG(FLUID_ERR, "Audio port '%s' on effect '%s' can only connect to" - "other audio port or buffer", port_name, effect_name); + "other audio port or buffer", port_name, effect_name); LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (LADSPA_IS_PORT_INPUT(port_flags)) + if(LADSPA_IS_PORT_INPUT(port_flags)) { dir = FLUID_LADSPA_INPUT; } @@ -1000,53 +1030,57 @@ int fluid_ladspa_check(fluid_ladspa_fx_t *fx, char *err, int err_size) LADSPA_API_ENTER(fx); /* Check that there is at least one effect */ - if (fx->num_effects == 0) + if(fx->num_effects == 0) { FLUID_SNPRINTF(err, err_size, "No effects configured\n"); LADSPA_API_RETURN(fx, FLUID_FAILED); } - for (i = 0; i < fx->num_effects; i++) + for(i = 0; i < fx->num_effects; i++) { effect = fx->effects[i]; - if (check_all_ports_connected(effect, &str) == FLUID_FAILED) + if(check_all_ports_connected(effect, &str) == FLUID_FAILED) { - if (err != NULL) + if(err != NULL) { FLUID_SNPRINTF(err, err_size, "Port '%s' on effect '%s' is not connected\n", - str, effect->name); + str, effect->name); } + LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (check_no_inplace_broken(effect, &str, &str2) == FLUID_FAILED) + if(check_no_inplace_broken(effect, &str, &str2) == FLUID_FAILED) { - if (err != NULL) + if(err != NULL) { FLUID_SNPRINTF(err, err_size, - "effect '%s' is in-place broken, '%s' and '%s' are not allowed " - "to connect to the same node\n", effect->name, str, str2); + "effect '%s' is in-place broken, '%s' and '%s' are not allowed " + "to connect to the same node\n", effect->name, str, str2); } + LADSPA_API_RETURN(fx, FLUID_FAILED); } } - if (check_host_output_used(fx) == FLUID_FAILED) + if(check_host_output_used(fx) == FLUID_FAILED) { - if (err != NULL) + if(err != NULL) { FLUID_SNPRINTF(err, err_size, "No effect outputs to one the host nodes\n"); } + LADSPA_API_RETURN(fx, FLUID_FAILED); } - if (check_all_audio_nodes_connected(fx, &str) == FLUID_FAILED) + if(check_all_audio_nodes_connected(fx, &str) == FLUID_FAILED) { - if (err != NULL) + if(err != NULL) { FLUID_SNPRINTF(err, err_size, "Audio node '%s' is not fully connected\n", str); } + LADSPA_API_RETURN(fx, FLUID_FAILED); } @@ -1056,10 +1090,11 @@ int fluid_ladspa_check(fluid_ladspa_fx_t *fx, char *err, int err_size) static void activate_effect(fluid_ladspa_effect_t *effect) { - if (!effect->active) + if(!effect->active) { effect->active = TRUE; - if (effect->desc->activate != NULL) + + if(effect->desc->activate != NULL) { effect->desc->activate(effect->handle); } @@ -1068,10 +1103,11 @@ static void activate_effect(fluid_ladspa_effect_t *effect) static void deactivate_effect(fluid_ladspa_effect_t *effect) { - if (effect->active) + if(effect->active) { effect->active = FALSE; - if (effect->desc->deactivate != NULL) + + if(effect->desc->deactivate != NULL) { effect->desc->deactivate(effect->handle); } @@ -1089,9 +1125,9 @@ static fluid_ladspa_node_t *get_node(fluid_ladspa_fx_t *fx, const char *name) { int i; - for (i = 0; i < fx->num_nodes; i++) + for(i = 0; i < fx->num_nodes; i++) { - if (FLUID_STRCASECMP(fx->nodes[i]->name, name) == 0) + if(FLUID_STRCASECMP(fx->nodes[i]->name, name) == 0) { return fx->nodes[i]; } @@ -1116,18 +1152,18 @@ static int get_effect_port_idx(const fluid_ladspa_effect_t *effect, const char * unsigned int i; int port = -1; - for (i = 0; i < effect->desc->PortCount; i++) + for(i = 0; i < effect->desc->PortCount; i++) { - if (FLUID_STRNCASECMP(effect->desc->PortNames[i], name, FLUID_STRLEN(name)) == 0) + if(FLUID_STRNCASECMP(effect->desc->PortNames[i], name, FLUID_STRLEN(name)) == 0) { /* exact match, return immediately */ - if (FLUID_STRLEN(effect->desc->PortNames[i]) == FLUID_STRLEN(name)) + if(FLUID_STRLEN(effect->desc->PortNames[i]) == FLUID_STRLEN(name)) { return i; } /* more than one prefix match should be treated as not found */ - if (port != -1) + if(port != -1) { return -1; } @@ -1155,20 +1191,23 @@ static const LADSPA_Descriptor *get_plugin_descriptor(fluid_module_t *lib, const LADSPA_Descriptor_Function ladspa_descriptor; int i; - if (!fluid_module_symbol(lib, "ladspa_descriptor", (void *)&ladspa_descriptor)) + if(!fluid_module_symbol(lib, "ladspa_descriptor", (void *)&ladspa_descriptor)) { FLUID_LOG(FLUID_ERR, "Unable to find ladspa_descriptor in '%s'. " - "Is this really a LADSPA plugin?", fluid_module_name(lib)); + "Is this really a LADSPA plugin?", fluid_module_name(lib)); return NULL; } - for (i = 0; /* endless */; i++) + for(i = 0; /* endless */; i++) { desc = ladspa_descriptor(i); - if (desc == NULL) - break; - if (name != NULL && FLUID_STRCMP(desc->Label, name) == 0) + if(desc == NULL) + { + break; + } + + if(name != NULL && FLUID_STRCMP(desc->Label, name) == 0) { return desc; } @@ -1176,14 +1215,15 @@ static const LADSPA_Descriptor *get_plugin_descriptor(fluid_module_t *lib, const last_desc = desc; } - if (name == NULL) + if(name == NULL) { - if (i == 1) + if(i == 1) { return last_desc; } + FLUID_LOG(FLUID_ERR, "Library contains more than one plugin, please specify " - "the plugin label"); + "the plugin label"); } return NULL; @@ -1207,56 +1247,63 @@ new_fluid_ladspa_effect(fluid_ladspa_fx_t *fx, const char *lib_name, const char fluid_ladspa_effect_t *effect; effect = FLUID_NEW(fluid_ladspa_effect_t); - if (effect == NULL) + + if(effect == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(effect, 0, sizeof(fluid_ladspa_effect_t)); effect->lib = fluid_module_open(lib_name); - if (effect->lib == NULL) + + if(effect->lib == NULL) { FLUID_LOG(FLUID_ERR, "Unable to load LADSPA library '%s': %s", lib_name, - fluid_module_error()); + fluid_module_error()); delete_fluid_ladspa_effect(effect); return NULL; } effect->desc = get_plugin_descriptor(effect->lib, plugin_name); - if (effect->desc == NULL) + + if(effect->desc == NULL) { delete_fluid_ladspa_effect(effect); return NULL; } effect->handle = effect->desc->instantiate(effect->desc, fx->sample_rate); - if (effect->handle == NULL) + + if(effect->handle == NULL) { delete_fluid_ladspa_effect(effect); FLUID_LOG(FLUID_ERR, "Unable to instantiate plugin '%s' from '%s'", plugin_name, lib_name); return NULL; } - effect->port_nodes = FLUID_ARRAY(fluid_ladspa_node_t*, effect->desc->PortCount); - if (effect->port_nodes == NULL) + effect->port_nodes = FLUID_ARRAY(fluid_ladspa_node_t *, effect->desc->PortCount); + + if(effect->port_nodes == NULL) { delete_fluid_ladspa_effect(effect); FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } - FLUID_MEMSET(effect->port_nodes, 0, effect->desc->PortCount * sizeof(fluid_ladspa_node_t*)); + + FLUID_MEMSET(effect->port_nodes, 0, effect->desc->PortCount * sizeof(fluid_ladspa_node_t *)); return effect; } static void delete_fluid_ladspa_effect(fluid_ladspa_effect_t *effect) { - fluid_return_if_fail (effect != NULL); + fluid_return_if_fail(effect != NULL); FLUID_FREE(effect->port_nodes); - if (effect->handle != NULL && effect->desc != NULL && effect->desc->cleanup != NULL) + if(effect->handle != NULL && effect->desc != NULL && effect->desc->cleanup != NULL) { effect->desc->cleanup(effect->handle); } @@ -1277,27 +1324,30 @@ static fluid_ladspa_node_t *new_fluid_ladspa_node(fluid_ladspa_fx_t *fx, const c fluid_ladspa_node_t *node; /* For named nodes, make sure that the name is unique */ - if (FLUID_STRLEN(name) > 0 && get_node(fx, name) != NULL) + if(FLUID_STRLEN(name) > 0 && get_node(fx, name) != NULL) { return NULL; } - if (fx->num_nodes >= FLUID_LADSPA_MAX_NODES) + if(fx->num_nodes >= FLUID_LADSPA_MAX_NODES) { FLUID_LOG(FLUID_ERR, "Maximum number of nodes reached"); return NULL; } node = FLUID_NEW(fluid_ladspa_node_t); - if (node == NULL) + + if(node == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(node, 0, sizeof(fluid_ladspa_node_t)); node->name = FLUID_STRDUP(name); - if (node->name == NULL) + + if(node->name == NULL) { delete_fluid_ladspa_node(node); FLUID_LOG(FLUID_ERR, "Out of memory"); @@ -1308,9 +1358,9 @@ static fluid_ladspa_node_t *new_fluid_ladspa_node(fluid_ladspa_fx_t *fx, const c node->host_buffer = host_buffer; /* host audio nodes need a host buffer set */ - if ((type & FLUID_LADSPA_NODE_AUDIO) && (type & FLUID_LADSPA_NODE_HOST)) + if((type & FLUID_LADSPA_NODE_AUDIO) && (type & FLUID_LADSPA_NODE_HOST)) { - if (node->host_buffer == NULL) + if(node->host_buffer == NULL) { delete_fluid_ladspa_node(node); return NULL; @@ -1324,18 +1374,20 @@ static fluid_ladspa_node_t *new_fluid_ladspa_node(fluid_ladspa_fx_t *fx, const c #endif } - if (node->effect_buffer == NULL) + if(node->effect_buffer == NULL) { /* Control nodes only store a single floating-point value */ buffer_size = (type & FLUID_LADSPA_NODE_CONTROL) ? 1 : fx->buffer_size; node->effect_buffer = FLUID_ARRAY(LADSPA_Data, buffer_size); - if (node->effect_buffer == NULL) + + if(node->effect_buffer == NULL) { delete_fluid_ladspa_node(node); FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(node->effect_buffer, 0, buffer_size * sizeof(LADSPA_Data)); } @@ -1343,11 +1395,11 @@ static fluid_ladspa_node_t *new_fluid_ladspa_node(fluid_ladspa_fx_t *fx, const c /* Host and user audio nodes are also noted in separate lists to access them * quickly during fluid_ladspa_run */ - if ((type & FLUID_LADSPA_NODE_AUDIO) && (type & FLUID_LADSPA_NODE_HOST)) + if((type & FLUID_LADSPA_NODE_AUDIO) && (type & FLUID_LADSPA_NODE_HOST)) { fx->host_nodes[fx->num_host_nodes++] = node; } - else if ((type & FLUID_LADSPA_NODE_AUDIO) && (type & FLUID_LADSPA_NODE_USER)) + else if((type & FLUID_LADSPA_NODE_AUDIO) && (type & FLUID_LADSPA_NODE_USER)) { fx->audio_nodes[fx->num_audio_nodes++] = node; } @@ -1361,7 +1413,7 @@ static void delete_fluid_ladspa_node(fluid_ladspa_node_t *node) /* If effect_buffer the same as host_buffer, then the effect_buffer has been * provided externally, so don't free */ - if ((node->effect_buffer != NULL) && ((void *)node->effect_buffer != (void *)node->host_buffer)) + if((node->effect_buffer != NULL) && ((void *)node->effect_buffer != (void *)node->host_buffer)) { FLUID_FREE(node->effect_buffer); } @@ -1383,9 +1435,9 @@ static fluid_ladspa_effect_t *get_effect(fluid_ladspa_fx_t *fx, const char *name LADSPA_API_ENTER(fx); - for (i = 0; i < fx->num_effects; i++) + for(i = 0; i < fx->num_effects; i++) { - if (FLUID_STRNCASECMP(fx->effects[i]->name, name, FLUID_STRLEN(name)) == 0) + if(FLUID_STRNCASECMP(fx->effects[i]->name, name, FLUID_STRLEN(name)) == 0) { LADSPA_API_RETURN(fx, fx->effects[i]); } @@ -1416,7 +1468,7 @@ static LADSPA_Data get_default_port_value(fluid_ladspa_effect_t *effect, unsigne float low_factor = 0.0; float high_factor = 0.0; - if (port_idx >= effect->desc->PortCount) + if(port_idx >= effect->desc->PortCount) { return value; } @@ -1424,56 +1476,57 @@ static LADSPA_Data get_default_port_value(fluid_ladspa_effect_t *effect, unsigne hint = &effect->desc->PortRangeHints[port_idx]; flags = hint->HintDescriptor; - if (!LADSPA_IS_HINT_HAS_DEFAULT(flags)) + if(!LADSPA_IS_HINT_HAS_DEFAULT(flags)) { return value; } - if (LADSPA_IS_HINT_DEFAULT_0(flags)) + if(LADSPA_IS_HINT_DEFAULT_0(flags)) { value = 0.0; } - else if (LADSPA_IS_HINT_DEFAULT_1(flags)) + else if(LADSPA_IS_HINT_DEFAULT_1(flags)) { value = 1.0; } - else if (LADSPA_IS_HINT_DEFAULT_100(flags)) + else if(LADSPA_IS_HINT_DEFAULT_100(flags)) { value = 100.0; } - else if (LADSPA_IS_HINT_DEFAULT_440(flags)) + else if(LADSPA_IS_HINT_DEFAULT_440(flags)) { value = 440.0; } /* defaults based on lower or upper bounds must consider HINT_SAMPLE_RATE */ - else { - if (LADSPA_IS_HINT_DEFAULT_MINIMUM(flags)) + else + { + if(LADSPA_IS_HINT_DEFAULT_MINIMUM(flags)) { low_factor = 1.0; high_factor = 0.0; } - else if (LADSPA_IS_HINT_DEFAULT_LOW(flags)) + else if(LADSPA_IS_HINT_DEFAULT_LOW(flags)) { low_factor = 0.75; high_factor = 0.25; } - else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(flags)) + else if(LADSPA_IS_HINT_DEFAULT_MIDDLE(flags)) { low_factor = 0.5; high_factor = 0.5; } - else if (LADSPA_IS_HINT_DEFAULT_HIGH(flags)) + else if(LADSPA_IS_HINT_DEFAULT_HIGH(flags)) { low_factor = 0.25; high_factor = 0.75; } - else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(flags)) + else if(LADSPA_IS_HINT_DEFAULT_MAXIMUM(flags)) { low_factor = 0.0; high_factor = 1.0; } - if (LADSPA_IS_HINT_LOGARITHMIC(flags) && low_factor > 0 && high_factor > 0) + if(LADSPA_IS_HINT_LOGARITHMIC(flags) && low_factor > 0 && high_factor > 0) { value = exp(log(hint->LowerBound) * low_factor + log(hint->UpperBound) * high_factor); } @@ -1482,13 +1535,13 @@ static LADSPA_Data get_default_port_value(fluid_ladspa_effect_t *effect, unsigne value = (hint->LowerBound * low_factor + hint->UpperBound * high_factor); } - if (LADSPA_IS_HINT_SAMPLE_RATE(flags)) + if(LADSPA_IS_HINT_SAMPLE_RATE(flags)) { value *= sample_rate; } } - if (LADSPA_IS_HINT_INTEGER(flags)) + if(LADSPA_IS_HINT_INTEGER(flags)) { /* LADSPA doesn't specify which rounding method to use, so lets keep it simple... */ value = floor(value + 0.5); @@ -1513,16 +1566,19 @@ static int create_control_port_nodes(fluid_ladspa_fx_t *fx, fluid_ladspa_effect_ fluid_ladspa_dir_t dir; int port_flags; - for (i = 0; i < effect->desc->PortCount; i++) + for(i = 0; i < effect->desc->PortCount; i++) { port_flags = effect->desc->PortDescriptors[i]; - if (!LADSPA_IS_PORT_CONTROL(port_flags)) + if(!LADSPA_IS_PORT_CONTROL(port_flags)) + { continue; + } node = new_fluid_ladspa_node(fx, "", - FLUID_LADSPA_NODE_EFFECT | FLUID_LADSPA_NODE_CONTROL, NULL); - if (node == NULL) + FLUID_LADSPA_NODE_EFFECT | FLUID_LADSPA_NODE_CONTROL, NULL); + + if(node == NULL) { return FLUID_FAILED; } @@ -1538,13 +1594,13 @@ static int create_control_port_nodes(fluid_ladspa_fx_t *fx, fluid_ladspa_effect_ } static void connect_node_to_port(fluid_ladspa_node_t *node, fluid_ladspa_dir_t dir, - fluid_ladspa_effect_t *effect, int port_idx) + fluid_ladspa_effect_t *effect, int port_idx) { effect->desc->connect_port(effect->handle, port_idx, node->effect_buffer); effect->port_nodes[port_idx] = node; /* Mark node as connected in the respective direction */ - if (dir == FLUID_LADSPA_INPUT) + if(dir == FLUID_LADSPA_INPUT) { node->num_outputs++; } @@ -1566,14 +1622,15 @@ static int check_all_ports_connected(fluid_ladspa_effect_t *effect, const char * { unsigned int i; - for (i = 0; i < effect->desc->PortCount; i++) + for(i = 0; i < effect->desc->PortCount; i++) { - if (effect->port_nodes[i] == NULL) + if(effect->port_nodes[i] == NULL) { *name = effect->desc->PortNames[i]; return FLUID_FAILED; } } + return FLUID_OK; } @@ -1591,23 +1648,23 @@ static int check_no_inplace_broken(fluid_ladspa_effect_t *effect, const char **n unsigned int i, k; LADSPA_PortDescriptor flags1, flags2; - if (!LADSPA_IS_INPLACE_BROKEN(effect->desc->Properties)) + if(!LADSPA_IS_INPLACE_BROKEN(effect->desc->Properties)) { return FLUID_OK; } - for (i = 0; i < effect->desc->PortCount; i++) + for(i = 0; i < effect->desc->PortCount; i++) { flags1 = effect->desc->PortDescriptors[i]; - for (k = 0; k < effect->desc->PortCount; k++) + for(k = 0; k < effect->desc->PortCount; k++) { flags2 = effect->desc->PortDescriptors[k]; - if (i != k - && effect->port_nodes[i]->effect_buffer == effect->port_nodes[k]->effect_buffer - && (flags1 & 0x3) != (flags2 & 0x3) /* first two bits encode direction */ - && LADSPA_IS_PORT_AUDIO(flags1) && LADSPA_IS_PORT_AUDIO(flags2)) + if(i != k + && effect->port_nodes[i]->effect_buffer == effect->port_nodes[k]->effect_buffer + && (flags1 & 0x3) != (flags2 & 0x3) /* first two bits encode direction */ + && LADSPA_IS_PORT_AUDIO(flags1) && LADSPA_IS_PORT_AUDIO(flags2)) { *name1 = effect->desc->PortNames[i]; *name2 = effect->desc->PortNames[k]; @@ -1615,6 +1672,7 @@ static int check_no_inplace_broken(fluid_ladspa_effect_t *effect, const char **n } } } + return FLUID_OK; } @@ -1628,13 +1686,14 @@ static int check_host_output_used(fluid_ladspa_fx_t *fx) { int i; - for (i = 0; i < fx->num_host_nodes; i++) + for(i = 0; i < fx->num_host_nodes; i++) { - if (fx->host_nodes[i]->num_inputs) + if(fx->host_nodes[i]->num_inputs) { return FLUID_OK; } } + return FLUID_FAILED; } @@ -1649,14 +1708,15 @@ static int check_all_audio_nodes_connected(fluid_ladspa_fx_t *fx, const char **n { int i; - for (i = 0; i < fx->num_audio_nodes; i++) + for(i = 0; i < fx->num_audio_nodes; i++) { - if (fx->audio_nodes[i]->num_inputs == 0 || fx->audio_nodes[i]->num_outputs == 0) + if(fx->audio_nodes[i]->num_inputs == 0 || fx->audio_nodes[i]->num_outputs == 0) { *name = fx->audio_nodes[i]->name; return FLUID_FAILED; } } + return FLUID_OK; } @@ -1670,14 +1730,15 @@ static FLUID_INLINE void copy_host_to_effect_buffers(fluid_ladspa_fx_t *fx, int int i, n; fluid_ladspa_node_t *node; - for (n = 0; n < fx->num_host_nodes; n++) + for(n = 0; n < fx->num_host_nodes; n++) { node = fx->host_nodes[n]; + /* Only copy host nodes that have at least one output or output, i.e. * that are connected to at least one effect port. */ - if (node->num_inputs > 0 || node->num_outputs > 0) + if(node->num_inputs > 0 || node->num_outputs > 0) { - for (i = 0; i < num_samples; i++) + for(i = 0; i < num_samples; i++) { node->effect_buffer[i] = (LADSPA_Data)node->host_buffer[i]; } @@ -1694,14 +1755,15 @@ static FLUID_INLINE void copy_effect_to_host_buffers(fluid_ladspa_fx_t *fx, int int i, n; fluid_ladspa_node_t *node; - for (n = 0; n < fx->num_host_nodes; n++) + for(n = 0; n < fx->num_host_nodes; n++) { node = fx->host_nodes[n]; + /* Only copy effect nodes that have at least one input, i.e. that are connected to * at least one effect output */ - if (node->num_inputs > 0) + if(node->num_inputs > 0) { - for (i = 0; i < num_samples; i++) + for(i = 0; i < num_samples; i++) { node->host_buffer[i] = (fluid_real_t)node->effect_buffer[i]; } @@ -1756,7 +1818,7 @@ int fluid_ladspa_buffer_exists(fluid_ladspa_fx_t *fx, const char *name) } int fluid_ladspa_add_effect(fluid_ladspa_fx_t *fx, const char *effect_name, - const char *lib_name, const char *plugin_name) + const char *lib_name, const char *plugin_name) { return FLUID_FAILED; } @@ -1777,13 +1839,13 @@ int fluid_ladspa_effect_port_exists(fluid_ladspa_fx_t *fx, const char *effect_na } int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const char *effect_name, - const char *port_name, float val) + const char *port_name, float val) { return FLUID_FAILED; } int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name, - const char *port_name, const char *name) + const char *port_name, const char *name) { return FLUID_FAILED; } diff --git a/src/bindings/fluid_ladspa.h b/src/bindings/fluid_ladspa.h index be607a89..80952d51 100644 --- a/src/bindings/fluid_ladspa.h +++ b/src/bindings/fluid_ladspa.h @@ -31,6 +31,6 @@ int fluid_ladspa_set_sample_rate(fluid_ladspa_fx_t *fx, fluid_real_t sample_rate void fluid_ladspa_run(fluid_ladspa_fx_t *fx, int block_count, int block_size); int fluid_ladspa_add_host_ports(fluid_ladspa_fx_t *fx, const char *prefix, - int num_buffers, fluid_real_t buffers[], int buf_stride); + int num_buffers, fluid_real_t buffers[], int buf_stride); #endif /* _FLUID_LADSPA_H */ diff --git a/src/bindings/fluid_lash.c b/src/bindings/fluid_lash.c index 1178c271..652ccb26 100644 --- a/src/bindings/fluid_lash.c +++ b/src/bindings/fluid_lash.c @@ -21,140 +21,150 @@ #ifdef HAVE_LASH -static void fluid_lash_save (fluid_synth_t * synth); -static void fluid_lash_load (fluid_synth_t * synth, const char * filename); -static void *fluid_lash_run (void * data); +static void fluid_lash_save(fluid_synth_t *synth); +static void fluid_lash_load(fluid_synth_t *synth, const char *filename); +static void *fluid_lash_run(void *data); /* * lash client - this symbol needs to be in the library else * all clients would need a fluid_lash_client symbol. */ -lash_client_t * fluid_lash_client; +lash_client_t *fluid_lash_client; static pthread_t fluid_lash_thread; fluid_lash_args_t * -fluid_lash_extract_args (int * pargc, char *** pargv) +fluid_lash_extract_args(int *pargc, char ***pargv) { - return lash_extract_args (pargc, pargv); + return lash_extract_args(pargc, pargv); } int -fluid_lash_connect (fluid_lash_args_t * args) +fluid_lash_connect(fluid_lash_args_t *args) { - fluid_lash_client = lash_init (args, PACKAGE, LASH_Config_Data_Set | LASH_Terminal, LASH_PROTOCOL (2,0)); - return fluid_lash_client && lash_enabled (fluid_lash_client); + fluid_lash_client = lash_init(args, PACKAGE, LASH_Config_Data_Set | LASH_Terminal, LASH_PROTOCOL(2, 0)); + return fluid_lash_client && lash_enabled(fluid_lash_client); } void -fluid_lash_create_thread (fluid_synth_t * synth) +fluid_lash_create_thread(fluid_synth_t *synth) { - pthread_create (&fluid_lash_thread, NULL, fluid_lash_run, synth); + pthread_create(&fluid_lash_thread, NULL, fluid_lash_run, synth); } static void -fluid_lash_save (fluid_synth_t * synth) +fluid_lash_save(fluid_synth_t *synth) { - int i; - int sfcount; - fluid_sfont_t * sfont; - lash_config_t * config; - char num[32]; + int i; + int sfcount; + fluid_sfont_t *sfont; + lash_config_t *config; + char num[32]; - sfcount = fluid_synth_sfcount (synth); + sfcount = fluid_synth_sfcount(synth); - config = lash_config_new (); - lash_config_set_key (config, "soundfont count"); - lash_config_set_value_int (config, sfcount); - lash_send_config (fluid_lash_client, config); + config = lash_config_new(); + lash_config_set_key(config, "soundfont count"); + lash_config_set_value_int(config, sfcount); + lash_send_config(fluid_lash_client, config); - for (i = sfcount - 1; i >= 0; i--) + for(i = sfcount - 1; i >= 0; i--) { - sfont = fluid_synth_get_sfont (synth, i); - config = lash_config_new (); + sfont = fluid_synth_get_sfont(synth, i); + config = lash_config_new(); - sprintf (num, "%d", i); + sprintf(num, "%d", i); - lash_config_set_key (config, num); - lash_config_set_value_string (config, sfont->get_name (sfont)); + lash_config_set_key(config, num); + lash_config_set_value_string(config, sfont->get_name(sfont)); - lash_send_config (fluid_lash_client, config); + lash_send_config(fluid_lash_client, config); } } static void -fluid_lash_load (fluid_synth_t * synth, const char * filename) +fluid_lash_load(fluid_synth_t *synth, const char *filename) { - fluid_synth_sfload (synth, filename, 1); + fluid_synth_sfload(synth, filename, 1); } static void * -fluid_lash_run (void * data) +fluid_lash_run(void *data) { - lash_event_t * event; - lash_config_t * config; - fluid_synth_t * synth; - int done = 0; - int err; - int pending_restores = 0; + lash_event_t *event; + lash_config_t *config; + fluid_synth_t *synth; + int done = 0; + int err; + int pending_restores = 0; - synth = (fluid_synth_t *) data; + synth = (fluid_synth_t *) data; - while (!done) + while(!done) { - while ( (event = lash_get_event (fluid_lash_client)) ) + while((event = lash_get_event(fluid_lash_client))) { - switch (lash_event_get_type (event)) + switch(lash_event_get_type(event)) { case LASH_Save_Data_Set: - fluid_lash_save (synth); - lash_send_event (fluid_lash_client, event); - break; + fluid_lash_save(synth); + lash_send_event(fluid_lash_client, event); + break; + case LASH_Restore_Data_Set: - lash_event_destroy (event); - break; + lash_event_destroy(event); + break; + case LASH_Quit: - err = kill (getpid(), SIGQUIT); - if (err) - fprintf (stderr, "%s: error sending signal: %s", - __FUNCTION__, strerror (errno)); - lash_event_destroy (event); - done = 1; - break; - case LASH_Server_Lost: - lash_event_destroy (event); - done = 1; - break; + err = kill(getpid(), SIGQUIT); + + if(err) + { + fprintf(stderr, "%s: error sending signal: %s", __FUNCTION__, strerror(errno)); + } + + lash_event_destroy(event); + done = 1; + break; + + case LASH_Server_Lost: + lash_event_destroy(event); + done = 1; + break; + default: - fprintf (stderr, "Received unknown LASH event of type %d\n", lash_event_get_type (event)); - lash_event_destroy (event); - break; + fprintf(stderr, "Received unknown LASH event of type %d\n", lash_event_get_type(event)); + lash_event_destroy(event); + break; } } - while ( (config = lash_get_config (fluid_lash_client)) ) + while((config = lash_get_config(fluid_lash_client))) { - if (FLUID_STRCMP (lash_config_get_key (config), "soundfont count") == 0) - pending_restores = lash_config_get_value_int (config); - else - { - fluid_lash_load (synth, lash_config_get_value_string (config)); - pending_restores--; - } - lash_config_destroy (config); + if(FLUID_STRCMP(lash_config_get_key(config), "soundfont count") == 0) + { + pending_restores = lash_config_get_value_int(config); + } + else + { + fluid_lash_load(synth, lash_config_get_value_string(config)); + pending_restores--; + } - if (!pending_restores) - { - event = lash_event_new_with_type (LASH_Restore_Data_Set); - lash_send_event (fluid_lash_client, event); - } + lash_config_destroy(config); + + if(!pending_restores) + { + event = lash_event_new_with_type(LASH_Restore_Data_Set); + lash_send_event(fluid_lash_client, event); + } } - usleep (10000); + usleep(10000); } - return NULL; + return NULL; } #endif /* #if HAVE_LASH #else */ diff --git a/src/bindings/fluid_lash.h b/src/bindings/fluid_lash.h index 47c1c570..0dc8f290 100644 --- a/src/bindings/fluid_lash.h +++ b/src/bindings/fluid_lash.h @@ -28,7 +28,7 @@ #ifdef HAVE_LASH #include -extern lash_client_t * fluid_lash_client; +extern lash_client_t *fluid_lash_client; #define fluid_lash_args_t lash_args_t #define fluid_lash_alsa_client_id lash_alsa_client_id #define fluid_lash_jack_client_name lash_jack_client_name @@ -36,8 +36,8 @@ extern lash_client_t * fluid_lash_client; #endif -FLUIDSYNTH_API fluid_lash_args_t *fluid_lash_extract_args (int * pargc, char *** pargv); -FLUIDSYNTH_API int fluid_lash_connect (fluid_lash_args_t * args); -FLUIDSYNTH_API void fluid_lash_create_thread (fluid_synth_t * synth); +FLUIDSYNTH_API fluid_lash_args_t *fluid_lash_extract_args(int *pargc, char ***pargv); +FLUIDSYNTH_API int fluid_lash_connect(fluid_lash_args_t *args); +FLUIDSYNTH_API void fluid_lash_create_thread(fluid_synth_t *synth); #endif /* defined(HAVE_LASH) */ diff --git a/src/bindings/fluid_rtkit.c b/src/bindings/fluid_rtkit.c index b8d7207f..d0e96cfd 100644 --- a/src/bindings/fluid_rtkit.c +++ b/src/bindings/fluid_rtkit.c @@ -43,248 +43,303 @@ #include -static pid_t _gettid(void) { - return (pid_t) syscall(SYS_gettid); +static pid_t _gettid(void) +{ + return (pid_t) syscall(SYS_gettid); } -static int translate_error(const char *name) { - if (FLUID_STRCMP(name, DBUS_ERROR_NO_MEMORY) == 0) - return -ENOMEM; - if (FLUID_STRCMP(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 || +static int translate_error(const char *name) +{ + if(FLUID_STRCMP(name, DBUS_ERROR_NO_MEMORY) == 0) + { + return -ENOMEM; + } + + if(FLUID_STRCMP(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 || FLUID_STRCMP(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0) - return -ENOENT; - if (FLUID_STRCMP(name, DBUS_ERROR_ACCESS_DENIED) == 0 || + { + return -ENOENT; + } + + if(FLUID_STRCMP(name, DBUS_ERROR_ACCESS_DENIED) == 0 || FLUID_STRCMP(name, DBUS_ERROR_AUTH_FAILED) == 0) - return -EACCES; + { + return -EACCES; + } - return -EIO; + return -EIO; } -static long long rtkit_get_int_property(DBusConnection *connection, const char* propname, long long* propval) { - DBusMessage *m = NULL, *r = NULL; - DBusMessageIter iter, subiter; - dbus_int64_t i64; - dbus_int32_t i32; - DBusError error; - int current_type; - long long ret; - const char * interfacestr = "org.freedesktop.RealtimeKit1"; +static long long rtkit_get_int_property(DBusConnection *connection, const char *propname, long long *propval) +{ + DBusMessage *m = NULL, *r = NULL; + DBusMessageIter iter, subiter; + dbus_int64_t i64; + dbus_int32_t i32; + DBusError error; + int current_type; + long long ret; + const char *interfacestr = "org.freedesktop.RealtimeKit1"; - dbus_error_init(&error); + dbus_error_init(&error); - if (!(m = dbus_message_new_method_call( - RTKIT_SERVICE_NAME, - RTKIT_OBJECT_PATH, - "org.freedesktop.DBus.Properties", - "Get"))) { - ret = -ENOMEM; - goto finish; - } + if(!(m = dbus_message_new_method_call( + RTKIT_SERVICE_NAME, + RTKIT_OBJECT_PATH, + "org.freedesktop.DBus.Properties", + "Get"))) + { + ret = -ENOMEM; + goto finish; + } - if (!dbus_message_append_args( - m, - DBUS_TYPE_STRING, &interfacestr, - DBUS_TYPE_STRING, &propname, - DBUS_TYPE_INVALID)) { - ret = -ENOMEM; - goto finish; - } + if(!dbus_message_append_args( + m, + DBUS_TYPE_STRING, &interfacestr, + DBUS_TYPE_STRING, &propname, + DBUS_TYPE_INVALID)) + { + ret = -ENOMEM; + goto finish; + } - if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) { - ret = translate_error(error.name); - goto finish; - } + if(!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) + { + ret = translate_error(error.name); + goto finish; + } - if (dbus_set_error_from_message(&error, r)) { - ret = translate_error(error.name); - goto finish; - } + if(dbus_set_error_from_message(&error, r)) + { + ret = translate_error(error.name); + goto finish; + } - ret = -EBADMSG; - dbus_message_iter_init(r, &iter); - while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) { + ret = -EBADMSG; + dbus_message_iter_init(r, &iter); - if (current_type == DBUS_TYPE_VARIANT) { - dbus_message_iter_recurse(&iter, &subiter); + while((current_type = dbus_message_iter_get_arg_type(&iter)) != DBUS_TYPE_INVALID) + { - while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) { + if(current_type == DBUS_TYPE_VARIANT) + { + dbus_message_iter_recurse(&iter, &subiter); - if (current_type == DBUS_TYPE_INT32) { - dbus_message_iter_get_basic(&subiter, &i32); - *propval = i32; - ret = 0; - } + while((current_type = dbus_message_iter_get_arg_type(&subiter)) != DBUS_TYPE_INVALID) + { - if (current_type == DBUS_TYPE_INT64) { - dbus_message_iter_get_basic(&subiter, &i64); - *propval = i64; - ret = 0; - } - - dbus_message_iter_next (&subiter); - } + if(current_type == DBUS_TYPE_INT32) + { + dbus_message_iter_get_basic(&subiter, &i32); + *propval = i32; + ret = 0; } - dbus_message_iter_next (&iter); + + if(current_type == DBUS_TYPE_INT64) + { + dbus_message_iter_get_basic(&subiter, &i64); + *propval = i64; + ret = 0; + } + + dbus_message_iter_next(&subiter); + } } + dbus_message_iter_next(&iter); + } + finish: - if (m) - dbus_message_unref(m); + if(m) + { + dbus_message_unref(m); + } - if (r) - dbus_message_unref(r); + if(r) + { + dbus_message_unref(r); + } - dbus_error_free(&error); + dbus_error_free(&error); - return ret; + return ret; } -int rtkit_get_max_realtime_priority(DBusConnection *connection) { - long long retval = 0; - int err; +int rtkit_get_max_realtime_priority(DBusConnection *connection) +{ + long long retval = 0; + int err; - err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval); - return err < 0 ? err : retval; + err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval); + return err < 0 ? err : retval; } -int rtkit_get_min_nice_level(DBusConnection *connection, int* min_nice_level) { - long long retval = 0; - int err; +int rtkit_get_min_nice_level(DBusConnection *connection, int *min_nice_level) +{ + long long retval = 0; + int err; - err = rtkit_get_int_property(connection, "MinNiceLevel", &retval); - if (err >= 0) - *min_nice_level = retval; - return err; + err = rtkit_get_int_property(connection, "MinNiceLevel", &retval); + + if(err >= 0) + { + *min_nice_level = retval; + } + + return err; } -long long rtkit_get_rttime_nsec_max(DBusConnection *connection) { - long long retval = 0; - int err; +long long rtkit_get_rttime_nsec_max(DBusConnection *connection) +{ + long long retval = 0; + int err; - err = rtkit_get_int_property(connection, "RTTimeNSecMax", &retval); - return err < 0 ? err : retval; + err = rtkit_get_int_property(connection, "RTTimeNSecMax", &retval); + return err < 0 ? err : retval; } -int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) { - DBusMessage *m = NULL, *r = NULL; - dbus_uint64_t u64; - dbus_uint32_t u32; - DBusError error; - int ret; +int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) +{ + DBusMessage *m = NULL, *r = NULL; + dbus_uint64_t u64; + dbus_uint32_t u32; + DBusError error; + int ret; - dbus_error_init(&error); + dbus_error_init(&error); - if (thread == 0) - thread = _gettid(); + if(thread == 0) + { + thread = _gettid(); + } - if (!(m = dbus_message_new_method_call( - RTKIT_SERVICE_NAME, - RTKIT_OBJECT_PATH, - "org.freedesktop.RealtimeKit1", - "MakeThreadRealtime"))) { - ret = -ENOMEM; - goto finish; - } + if(!(m = dbus_message_new_method_call( + RTKIT_SERVICE_NAME, + RTKIT_OBJECT_PATH, + "org.freedesktop.RealtimeKit1", + "MakeThreadRealtime"))) + { + ret = -ENOMEM; + goto finish; + } - u64 = (dbus_uint64_t) thread; - u32 = (dbus_uint32_t) priority; + u64 = (dbus_uint64_t) thread; + u32 = (dbus_uint32_t) priority; - if (!dbus_message_append_args( - m, - DBUS_TYPE_UINT64, &u64, - DBUS_TYPE_UINT32, &u32, - DBUS_TYPE_INVALID)) { - ret = -ENOMEM; - goto finish; - } + if(!dbus_message_append_args( + m, + DBUS_TYPE_UINT64, &u64, + DBUS_TYPE_UINT32, &u32, + DBUS_TYPE_INVALID)) + { + ret = -ENOMEM; + goto finish; + } - if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) { - ret = translate_error(error.name); - goto finish; - } + if(!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) + { + ret = translate_error(error.name); + goto finish; + } - if (dbus_set_error_from_message(&error, r)) { - ret = translate_error(error.name); - goto finish; - } + if(dbus_set_error_from_message(&error, r)) + { + ret = translate_error(error.name); + goto finish; + } - ret = 0; + ret = 0; finish: - if (m) - dbus_message_unref(m); + if(m) + { + dbus_message_unref(m); + } - if (r) - dbus_message_unref(r); + if(r) + { + dbus_message_unref(r); + } - dbus_error_free(&error); + dbus_error_free(&error); - return ret; + return ret; } -int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) { - DBusMessage *m = NULL, *r = NULL; - dbus_uint64_t u64; - dbus_int32_t s32; - DBusError error; - int ret; +int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) +{ + DBusMessage *m = NULL, *r = NULL; + dbus_uint64_t u64; + dbus_int32_t s32; + DBusError error; + int ret; - dbus_error_init(&error); + dbus_error_init(&error); - if (thread == 0) - thread = _gettid(); + if(thread == 0) + { + thread = _gettid(); + } - if (!(m = dbus_message_new_method_call( - RTKIT_SERVICE_NAME, - RTKIT_OBJECT_PATH, - "org.freedesktop.RealtimeKit1", - "MakeThreadHighPriority"))) { - ret = -ENOMEM; - goto finish; - } + if(!(m = dbus_message_new_method_call( + RTKIT_SERVICE_NAME, + RTKIT_OBJECT_PATH, + "org.freedesktop.RealtimeKit1", + "MakeThreadHighPriority"))) + { + ret = -ENOMEM; + goto finish; + } - u64 = (dbus_uint64_t) thread; - s32 = (dbus_int32_t) nice_level; + u64 = (dbus_uint64_t) thread; + s32 = (dbus_int32_t) nice_level; - if (!dbus_message_append_args( - m, - DBUS_TYPE_UINT64, &u64, - DBUS_TYPE_INT32, &s32, - DBUS_TYPE_INVALID)) { - ret = -ENOMEM; - goto finish; - } + if(!dbus_message_append_args( + m, + DBUS_TYPE_UINT64, &u64, + DBUS_TYPE_INT32, &s32, + DBUS_TYPE_INVALID)) + { + ret = -ENOMEM; + goto finish; + } - if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) { - ret = translate_error(error.name); - goto finish; - } + if(!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) + { + ret = translate_error(error.name); + goto finish; + } - if (dbus_set_error_from_message(&error, r)) { - ret = translate_error(error.name); - goto finish; - } + if(dbus_set_error_from_message(&error, r)) + { + ret = translate_error(error.name); + goto finish; + } - ret = 0; + ret = 0; finish: - if (m) - dbus_message_unref(m); + if(m) + { + dbus_message_unref(m); + } - if (r) - dbus_message_unref(r); + if(r) + { + dbus_message_unref(r); + } - dbus_error_free(&error); + dbus_error_free(&error); - return ret; + return ret; } #ifndef RLIMIT_RTTIME @@ -297,80 +352,110 @@ finish: dbus_connection_unref(conn); \ return _value; \ } while (0) - -int fluid_rtkit_make_realtime(pid_t thread, int priority) { - DBusConnection *conn = NULL; - DBusError error; - int max_prio, res; - long long max_rttime; - struct rlimit old_limit, new_limit; - if (!dbus_threads_init_default()) - return -ENOMEM; +int fluid_rtkit_make_realtime(pid_t thread, int priority) +{ + DBusConnection *conn = NULL; + DBusError error; + int max_prio, res; + long long max_rttime; + struct rlimit old_limit, new_limit; - /* Initialize system bus connection */ - dbus_error_init(&error); - conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); - if (conn == NULL) { - res = translate_error(error.name); - dbus_error_free(&error); - return res; - } + if(!dbus_threads_init_default()) + { + return -ENOMEM; + } + + /* Initialize system bus connection */ + dbus_error_init(&error); + conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); + + if(conn == NULL) + { + res = translate_error(error.name); dbus_error_free(&error); - - /* Make sure we don't fail by wanting too much */ - max_prio = rtkit_get_max_realtime_priority(conn); - if (max_prio < 0) - MAKE_REALTIME_RETURN(max_prio); + return res; + } + + dbus_error_free(&error); + + /* Make sure we don't fail by wanting too much */ + max_prio = rtkit_get_max_realtime_priority(conn); + + if(max_prio < 0) + { + MAKE_REALTIME_RETURN(max_prio); + } + + if(priority >= max_prio) + { + priority = max_prio; + } + + /* Enforce RLIMIT_RTTIME, also a must for obtaining rt prio through rtkit */ + max_rttime = rtkit_get_rttime_nsec_max(conn); + + if(max_rttime < 0) + { + MAKE_REALTIME_RETURN(max_rttime); + } + + new_limit.rlim_cur = new_limit.rlim_max = max_rttime; + + if(getrlimit(RLIMIT_RTTIME, &old_limit) < 0) + { + MAKE_REALTIME_RETURN(-1); + } + + if(setrlimit(RLIMIT_RTTIME, &new_limit) < 0) + { + MAKE_REALTIME_RETURN(-1); + } + + /* Finally, let's try */ + res = rtkit_make_realtime(conn, thread, priority); + + if(res != 0) + { + setrlimit(RLIMIT_RTTIME, &old_limit); + } + + MAKE_REALTIME_RETURN(res); - if (priority >= max_prio) - priority = max_prio; - - /* Enforce RLIMIT_RTTIME, also a must for obtaining rt prio through rtkit */ - max_rttime = rtkit_get_rttime_nsec_max(conn); - if (max_rttime < 0) - MAKE_REALTIME_RETURN(max_rttime); - new_limit.rlim_cur = new_limit.rlim_max = max_rttime; - if (getrlimit(RLIMIT_RTTIME, &old_limit) < 0) - MAKE_REALTIME_RETURN(-1); - if (setrlimit(RLIMIT_RTTIME, &new_limit) < 0) - MAKE_REALTIME_RETURN(-1); - - /* Finally, let's try */ - res = rtkit_make_realtime(conn, thread, priority); - if (res != 0) { - setrlimit(RLIMIT_RTTIME, &old_limit); - } - MAKE_REALTIME_RETURN(res); - } #else -int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) { - return -ENOTSUP; +int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) +{ + return -ENOTSUP; } -int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) { - return -ENOTSUP; +int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) +{ + return -ENOTSUP; } -int rtkit_get_max_realtime_priority(DBusConnection *connection) { - return -ENOTSUP; +int rtkit_get_max_realtime_priority(DBusConnection *connection) +{ + return -ENOTSUP; } -int rtkit_get_min_nice_level(DBusConnection *connection, int* min_nice_level) { - return -ENOTSUP; +int rtkit_get_min_nice_level(DBusConnection *connection, int *min_nice_level) +{ + return -ENOTSUP; } -long long rtkit_get_rttime_nsec_max(DBusConnection *connection) { - return -ENOTSUP; +long long rtkit_get_rttime_nsec_max(DBusConnection *connection) +{ + return -ENOTSUP; } -int fluid_rtkit_make_realtime(pid_t thread, int priority) { - return -ENOTSUP; +int fluid_rtkit_make_realtime(pid_t thread, int priority) +{ + return -ENOTSUP; } #endif /* defined(__linux__) || defined(__APPLE__) */ diff --git a/src/drivers/fluid_adriver.c b/src/drivers/fluid_adriver.c index 8cf60b5d..a326bcac 100644 --- a/src/drivers/fluid_adriver.c +++ b/src/drivers/fluid_adriver.c @@ -27,95 +27,95 @@ typedef struct _fluid_audriver_definition_t { - const char* name; - fluid_audio_driver_t* (*new)(fluid_settings_t* settings, fluid_synth_t* synth); - fluid_audio_driver_t* (*new2)(fluid_settings_t* settings, - fluid_audio_func_t func, - void* data); - void (*free)(fluid_audio_driver_t* driver); - void (*settings)(fluid_settings_t* settings); + const char *name; + fluid_audio_driver_t *(*new)(fluid_settings_t *settings, fluid_synth_t *synth); + fluid_audio_driver_t *(*new2)(fluid_settings_t *settings, + fluid_audio_func_t func, + void *data); + void (*free)(fluid_audio_driver_t *driver); + void (*settings)(fluid_settings_t *settings); } fluid_audriver_definition_t; #if PULSE_SUPPORT -fluid_audio_driver_t* new_fluid_pulse_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_pulse_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data); -void delete_fluid_pulse_audio_driver(fluid_audio_driver_t* p); -void fluid_pulse_audio_driver_settings(fluid_settings_t* settings); +fluid_audio_driver_t *new_fluid_pulse_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_pulse_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data); +void delete_fluid_pulse_audio_driver(fluid_audio_driver_t *p); +void fluid_pulse_audio_driver_settings(fluid_settings_t *settings); #endif #if ALSA_SUPPORT -fluid_audio_driver_t* new_fluid_alsa_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_alsa_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data); -void delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p); -void fluid_alsa_audio_driver_settings(fluid_settings_t* settings); +fluid_audio_driver_t *new_fluid_alsa_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_alsa_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data); +void delete_fluid_alsa_audio_driver(fluid_audio_driver_t *p); +void fluid_alsa_audio_driver_settings(fluid_settings_t *settings); #endif #if OSS_SUPPORT -fluid_audio_driver_t* new_fluid_oss_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_oss_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data); -void delete_fluid_oss_audio_driver(fluid_audio_driver_t* p); -void fluid_oss_audio_driver_settings(fluid_settings_t* settings); +fluid_audio_driver_t *new_fluid_oss_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_oss_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data); +void delete_fluid_oss_audio_driver(fluid_audio_driver_t *p); +void fluid_oss_audio_driver_settings(fluid_settings_t *settings); #endif #if COREAUDIO_SUPPORT -fluid_audio_driver_t* new_fluid_core_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, - void* data); -void delete_fluid_core_audio_driver(fluid_audio_driver_t* p); -void fluid_core_audio_driver_settings(fluid_settings_t* settings); +fluid_audio_driver_t *new_fluid_core_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_core_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, + void *data); +void delete_fluid_core_audio_driver(fluid_audio_driver_t *p); +void fluid_core_audio_driver_settings(fluid_settings_t *settings); #endif #if DSOUND_SUPPORT -fluid_audio_driver_t* new_fluid_dsound_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -void delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p); -void fluid_dsound_audio_driver_settings(fluid_settings_t* settings); +fluid_audio_driver_t *new_fluid_dsound_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +void delete_fluid_dsound_audio_driver(fluid_audio_driver_t *p); +void fluid_dsound_audio_driver_settings(fluid_settings_t *settings); #endif #if PORTAUDIO_SUPPORT -void fluid_portaudio_driver_settings (fluid_settings_t *settings); -fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -void delete_fluid_portaudio_driver(fluid_audio_driver_t* p); +void fluid_portaudio_driver_settings(fluid_settings_t *settings); +fluid_audio_driver_t *new_fluid_portaudio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +void delete_fluid_portaudio_driver(fluid_audio_driver_t *p); #endif #if JACK_SUPPORT -fluid_audio_driver_t* new_fluid_jack_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_jack_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data); -void delete_fluid_jack_audio_driver(fluid_audio_driver_t* p); -void fluid_jack_audio_driver_settings(fluid_settings_t* settings); +fluid_audio_driver_t *new_fluid_jack_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_jack_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data); +void delete_fluid_jack_audio_driver(fluid_audio_driver_t *p); +void fluid_jack_audio_driver_settings(fluid_settings_t *settings); #endif #if SNDMAN_SUPPORT -fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, - void* data); -void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p); +fluid_audio_driver_t *new_fluid_sndmgr_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_sndmgr_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, + void *data); +void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t *p); #endif #if DART_SUPPORT -fluid_audio_driver_t* new_fluid_dart_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -void delete_fluid_dart_audio_driver(fluid_audio_driver_t* p); -void fluid_dart_audio_driver_settings(fluid_settings_t* settings); +fluid_audio_driver_t *new_fluid_dart_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +void delete_fluid_dart_audio_driver(fluid_audio_driver_t *p); +void fluid_dart_audio_driver_settings(fluid_settings_t *settings); #endif #if AUFILE_SUPPORT -fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -void delete_fluid_file_audio_driver(fluid_audio_driver_t* p); +fluid_audio_driver_t *new_fluid_file_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +void delete_fluid_file_audio_driver(fluid_audio_driver_t *p); #endif @@ -123,83 +123,103 @@ void delete_fluid_file_audio_driver(fluid_audio_driver_t* p); static const fluid_audriver_definition_t fluid_audio_drivers[] = { #if JACK_SUPPORT - { "jack", + { + "jack", new_fluid_jack_audio_driver, new_fluid_jack_audio_driver2, delete_fluid_jack_audio_driver, - fluid_jack_audio_driver_settings }, + fluid_jack_audio_driver_settings + }, #endif #if ALSA_SUPPORT - { "alsa", + { + "alsa", new_fluid_alsa_audio_driver, new_fluid_alsa_audio_driver2, delete_fluid_alsa_audio_driver, - fluid_alsa_audio_driver_settings }, + fluid_alsa_audio_driver_settings + }, #endif #if OSS_SUPPORT - { "oss", + { + "oss", new_fluid_oss_audio_driver, new_fluid_oss_audio_driver2, delete_fluid_oss_audio_driver, - fluid_oss_audio_driver_settings }, + fluid_oss_audio_driver_settings + }, #endif #if PULSE_SUPPORT - { "pulseaudio", + { + "pulseaudio", new_fluid_pulse_audio_driver, new_fluid_pulse_audio_driver2, delete_fluid_pulse_audio_driver, - fluid_pulse_audio_driver_settings }, + fluid_pulse_audio_driver_settings + }, #endif #if COREAUDIO_SUPPORT - { "coreaudio", + { + "coreaudio", new_fluid_core_audio_driver, new_fluid_core_audio_driver2, delete_fluid_core_audio_driver, - fluid_core_audio_driver_settings }, + fluid_core_audio_driver_settings + }, #endif #if DSOUND_SUPPORT - { "dsound", + { + "dsound", new_fluid_dsound_audio_driver, NULL, delete_fluid_dsound_audio_driver, - fluid_dsound_audio_driver_settings }, + fluid_dsound_audio_driver_settings + }, #endif #if PORTAUDIO_SUPPORT - { "portaudio", + { + "portaudio", new_fluid_portaudio_driver, NULL, delete_fluid_portaudio_driver, - fluid_portaudio_driver_settings }, + fluid_portaudio_driver_settings + }, #endif #if SNDMAN_SUPPORT - { "sndman", + { + "sndman", new_fluid_sndmgr_audio_driver, new_fluid_sndmgr_audio_driver2, delete_fluid_sndmgr_audio_driver, - NULL }, + NULL + }, #endif #if DART_SUPPORT - { "dart", + { + "dart", new_fluid_dart_audio_driver, NULL, delete_fluid_dart_audio_driver, - fluid_dart_audio_driver_settings }, + fluid_dart_audio_driver_settings + }, #endif #if AUFILE_SUPPORT - { "file", + { + "file", new_fluid_file_audio_driver, NULL, delete_fluid_file_audio_driver, - NULL }, + NULL + }, #endif }; @@ -209,121 +229,135 @@ static const fluid_audriver_definition_t fluid_audio_drivers[] = #define IS_AUDIO_DRIVER_ENABLED(_drv, _idx) \ (!(_drv[(_idx) / (sizeof(*(_drv))*8)] & (1 << ((_idx) % (sizeof((*_drv))*8))))) -static uint8_t fluid_adriver_disable_mask[(FLUID_N_ELEMENTS(fluid_audio_drivers)+7)/8] = {0}; +static uint8_t fluid_adriver_disable_mask[(FLUID_N_ELEMENTS(fluid_audio_drivers) + 7) / 8] = {0}; -void fluid_audio_driver_settings(fluid_settings_t* settings) +void fluid_audio_driver_settings(fluid_settings_t *settings) { - unsigned int i; + unsigned int i; - fluid_settings_register_str(settings, "audio.sample-format", "16bits", 0); - fluid_settings_add_option(settings, "audio.sample-format", "16bits"); - fluid_settings_add_option(settings, "audio.sample-format", "float"); + fluid_settings_register_str(settings, "audio.sample-format", "16bits", 0); + fluid_settings_add_option(settings, "audio.sample-format", "16bits"); + fluid_settings_add_option(settings, "audio.sample-format", "float"); #if defined(WIN32) - fluid_settings_register_int(settings, "audio.period-size", 512, 64, 8192, 0); - fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0); + fluid_settings_register_int(settings, "audio.period-size", 512, 64, 8192, 0); + fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0); #elif defined(MACOS9) - fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0); - fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0); + fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0); + fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0); #else - fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0); - fluid_settings_register_int(settings, "audio.periods", 16, 2, 64, 0); + fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0); + fluid_settings_register_int(settings, "audio.periods", 16, 2, 64, 0); #endif - fluid_settings_register_int (settings, "audio.realtime-prio", - FLUID_DEFAULT_AUDIO_RT_PRIO, 0, 99, 0); + fluid_settings_register_int(settings, "audio.realtime-prio", + FLUID_DEFAULT_AUDIO_RT_PRIO, 0, 99, 0); - /* Set the default driver */ + /* Set the default driver */ #if JACK_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "jack", 0); + fluid_settings_register_str(settings, "audio.driver", "jack", 0); #elif ALSA_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "alsa", 0); + fluid_settings_register_str(settings, "audio.driver", "alsa", 0); #elif PULSE_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "pulseaudio", 0); + fluid_settings_register_str(settings, "audio.driver", "pulseaudio", 0); #elif OSS_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "oss", 0); + fluid_settings_register_str(settings, "audio.driver", "oss", 0); #elif COREAUDIO_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "coreaudio", 0); + fluid_settings_register_str(settings, "audio.driver", "coreaudio", 0); #elif DSOUND_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "dsound", 0); + fluid_settings_register_str(settings, "audio.driver", "dsound", 0); #elif SNDMAN_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "sndman", 0); + fluid_settings_register_str(settings, "audio.driver", "sndman", 0); #elif PORTAUDIO_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "portaudio", 0); + fluid_settings_register_str(settings, "audio.driver", "portaudio", 0); #elif DART_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "dart", 0); + fluid_settings_register_str(settings, "audio.driver", "dart", 0); #elif AUFILE_SUPPORT - fluid_settings_register_str(settings, "audio.driver", "file", 0); + fluid_settings_register_str(settings, "audio.driver", "file", 0); #else - fluid_settings_register_str(settings, "audio.driver", "", 0); + fluid_settings_register_str(settings, "audio.driver", "", 0); #endif - /* Add all drivers to the list of options */ + /* Add all drivers to the list of options */ #if PULSE_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "pulseaudio"); + fluid_settings_add_option(settings, "audio.driver", "pulseaudio"); #endif #if ALSA_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "alsa"); + fluid_settings_add_option(settings, "audio.driver", "alsa"); #endif #if OSS_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "oss"); + fluid_settings_add_option(settings, "audio.driver", "oss"); #endif #if COREAUDIO_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "coreaudio"); + fluid_settings_add_option(settings, "audio.driver", "coreaudio"); #endif #if DSOUND_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "dsound"); + fluid_settings_add_option(settings, "audio.driver", "dsound"); #endif #if SNDMAN_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "sndman"); + fluid_settings_add_option(settings, "audio.driver", "sndman"); #endif #if PORTAUDIO_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "portaudio"); + fluid_settings_add_option(settings, "audio.driver", "portaudio"); #endif #if JACK_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "jack"); + fluid_settings_add_option(settings, "audio.driver", "jack"); #endif #if DART_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "dart"); + fluid_settings_add_option(settings, "audio.driver", "dart"); #endif #if AUFILE_SUPPORT - fluid_settings_add_option(settings, "audio.driver", "file"); + fluid_settings_add_option(settings, "audio.driver", "file"); #endif - for (i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers); i++) { - if (fluid_audio_drivers[i].settings != NULL && - IS_AUDIO_DRIVER_ENABLED(fluid_adriver_disable_mask, i)) { - fluid_audio_drivers[i].settings(settings); + for(i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers); i++) + { + if(fluid_audio_drivers[i].settings != NULL && + IS_AUDIO_DRIVER_ENABLED(fluid_adriver_disable_mask, i)) + { + fluid_audio_drivers[i].settings(settings); + } } - } } -static const fluid_audriver_definition_t* -find_fluid_audio_driver(fluid_settings_t* settings) +static const fluid_audriver_definition_t * +find_fluid_audio_driver(fluid_settings_t *settings) { - unsigned int i; - char* name; - char *allnames; + unsigned int i; + char *name; + char *allnames; - for (i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers); i++) { - /* If this driver is de-activated, just ignore it */ - if (!IS_AUDIO_DRIVER_ENABLED(fluid_adriver_disable_mask, i)) - continue; + for(i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers); i++) + { + /* If this driver is de-activated, just ignore it */ + if(!IS_AUDIO_DRIVER_ENABLED(fluid_adriver_disable_mask, i)) + { + continue; + } - if (fluid_settings_str_equal(settings, "audio.driver", fluid_audio_drivers[i].name)) { - FLUID_LOG(FLUID_DBG, "Using '%s' audio driver", fluid_audio_drivers[i].name); - return &fluid_audio_drivers[i]; + if(fluid_settings_str_equal(settings, "audio.driver", fluid_audio_drivers[i].name)) + { + FLUID_LOG(FLUID_DBG, "Using '%s' audio driver", fluid_audio_drivers[i].name); + return &fluid_audio_drivers[i]; + } } - } - allnames = fluid_settings_option_concat (settings, "audio.driver", NULL); - fluid_settings_dupstr (settings, "audio.driver", &name); /* ++ alloc name */ - FLUID_LOG(FLUID_ERR, "Couldn't find the requested audio driver %s. Valid drivers are: %s.", - name ? name : "NULL", allnames ? allnames : "ERROR"); - if (name) FLUID_FREE (name); - if (allnames) FLUID_FREE (allnames); + allnames = fluid_settings_option_concat(settings, "audio.driver", NULL); + fluid_settings_dupstr(settings, "audio.driver", &name); /* ++ alloc name */ + FLUID_LOG(FLUID_ERR, "Couldn't find the requested audio driver %s. Valid drivers are: %s.", + name ? name : "NULL", allnames ? allnames : "ERROR"); - return NULL; + if(name) + { + FLUID_FREE(name); + } + + if(allnames) + { + FLUID_FREE(allnames); + } + + return NULL; } /** @@ -336,21 +370,24 @@ find_fluid_audio_driver(fluid_settings_t* settings) * Creates a new audio driver for a given 'synth' instance with a defined set * of configuration 'settings'. */ -fluid_audio_driver_t* -new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) { - const fluid_audriver_definition_t *def = find_fluid_audio_driver(settings); + const fluid_audriver_definition_t *def = find_fluid_audio_driver(settings); - if (def) { - fluid_audio_driver_t *driver = (*def->new)(settings, synth); + if(def) + { + fluid_audio_driver_t *driver = (*def->new)(settings, synth); - if (driver) - driver->name = def->name; + if(driver) + { + driver->name = def->name; + } - return driver; - } + return driver; + } - return NULL; + return NULL; } /** @@ -367,26 +404,33 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) * * NOTE: Not as efficient as new_fluid_audio_driver(). */ -fluid_audio_driver_t* -new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data) +fluid_audio_driver_t * +new_fluid_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data) { - const fluid_audriver_definition_t *def = find_fluid_audio_driver(settings); + const fluid_audriver_definition_t *def = find_fluid_audio_driver(settings); - if (def) { - fluid_audio_driver_t *driver = NULL; + if(def) + { + fluid_audio_driver_t *driver = NULL; - if (def->new2 == NULL) - FLUID_LOG(FLUID_DBG, "Callback mode unsupported on '%s' audio driver", def->name); - else { - driver = (*def->new2)(settings, func, data); - if (driver) - driver->name = def->name; + if(def->new2 == NULL) + { + FLUID_LOG(FLUID_DBG, "Callback mode unsupported on '%s' audio driver", def->name); + } + else + { + driver = (*def->new2)(settings, func, data); + + if(driver) + { + driver->name = def->name; + } + } + + return driver; } - return driver; - } - - return NULL; + return NULL; } /** @@ -396,66 +440,70 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi * Shuts down an audio driver and deletes its instance. */ void -delete_fluid_audio_driver(fluid_audio_driver_t* driver) +delete_fluid_audio_driver(fluid_audio_driver_t *driver) { - unsigned int i; - fluid_return_if_fail(driver != NULL); + unsigned int i; + fluid_return_if_fail(driver != NULL); - /* iterate over fluid_audio_drivers_template to ensure deleting even drivers currently not registered */ - for (i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers); i++) { - if (fluid_audio_drivers[i].name == driver->name) { - fluid_audio_drivers[i].free(driver); - return; + /* iterate over fluid_audio_drivers_template to ensure deleting even drivers currently not registered */ + for(i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers); i++) + { + if(fluid_audio_drivers[i].name == driver->name) + { + fluid_audio_drivers[i].free(driver); + return; + } } - } } /** * @brief Registers audio drivers to use - * + * * When creating a settings instance with new_fluid_settings(), all audio drivers are initialized once. * In the past this has caused segfaults and application crashes due to buggy soundcard drivers. - * + * * This function enables the user to only initialize specific audio drivers when settings instances are created. * Therefore pass a NULL-terminated array of C-strings containing the \c names of audio drivers to register * for the usage with fluidsynth. * The \c names are the same as being used for the \c audio.driver setting. - * + * * By default all audio drivers fluidsynth has been compiled with are registered, so calling this function is optional. - * + * * @warning This function may only be called if no thread is residing in fluidsynth's API and no instances of any kind * are alive (e.g. as it would be the case right after fluidsynth's inital creation). Else the behaviour is undefined. * Furtermore any attempt of using audio drivers that have not been registered is undefined behaviour! - * + * * @param adrivers NULL-terminated array of audio drivers to register. Pass NULL to register all available drivers. * @return #FLUID_OK if all the audio drivers requested by the user are supported by fluidsynth and have been * successfully registered. Otherwise #FLUID_FAILED is returned and this function has no effect. - * + * * @note This function is not thread safe and will never be! * @since 1.1.9 */ -int fluid_audio_driver_register(const char** adrivers) +int fluid_audio_driver_register(const char **adrivers) { unsigned int i; uint8_t disable_mask[FLUID_N_ELEMENTS(fluid_adriver_disable_mask)]; - - if (adrivers == NULL) { - /* Pass NULL to register all available drivers. */ - FLUID_MEMSET(fluid_adriver_disable_mask, 0, sizeof(fluid_adriver_disable_mask)); - return FLUID_OK; + if(adrivers == NULL) + { + /* Pass NULL to register all available drivers. */ + FLUID_MEMSET(fluid_adriver_disable_mask, 0, sizeof(fluid_adriver_disable_mask)); + + return FLUID_OK; } FLUID_MEMSET(disable_mask, 0xFF, sizeof(disable_mask)); - for(i=0; adrivers[i] != NULL; i++) + for(i = 0; adrivers[i] != NULL; i++) { unsigned int j; + /* search the requested audio driver in the template and copy it over if found */ - for (j = 0; j < FLUID_N_ELEMENTS(fluid_audio_drivers); j++) + for(j = 0; j < FLUID_N_ELEMENTS(fluid_audio_drivers); j++) { - if (FLUID_STRCMP(adrivers[i], fluid_audio_drivers[j].name) == 0) + if(FLUID_STRCMP(adrivers[i], fluid_audio_drivers[j].name) == 0) { ENABLE_AUDIO_DRIVER(disable_mask, j); break; diff --git a/src/drivers/fluid_adriver.h b/src/drivers/fluid_adriver.h index ae12001c..c9172c32 100644 --- a/src/drivers/fluid_adriver.h +++ b/src/drivers/fluid_adriver.h @@ -23,7 +23,7 @@ #include "fluid_sys.h" -void fluid_audio_driver_settings(fluid_settings_t* settings); +void fluid_audio_driver_settings(fluid_settings_t *settings); /* @@ -32,7 +32,7 @@ void fluid_audio_driver_settings(fluid_settings_t* settings); struct _fluid_audio_driver_t { - const char* name; + const char *name; }; diff --git a/src/drivers/fluid_alsa.c b/src/drivers/fluid_alsa.c index 4d4d3004..0eed070d 100644 --- a/src/drivers/fluid_alsa.c +++ b/src/drivers/fluid_alsa.c @@ -48,45 +48,52 @@ * This structure should not be accessed directly. Use audio port * functions instead. */ -typedef struct { - fluid_audio_driver_t driver; - snd_pcm_t* pcm; - fluid_audio_func_t callback; - void* data; - int buffer_size; - fluid_thread_t *thread; - int cont; +typedef struct +{ + fluid_audio_driver_t driver; + snd_pcm_t *pcm; + fluid_audio_func_t callback; + void *data; + int buffer_size; + fluid_thread_t *thread; + int cont; } fluid_alsa_audio_driver_t; -fluid_audio_driver_t* new_fluid_alsa_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_alsa_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data); +fluid_audio_driver_t *new_fluid_alsa_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_alsa_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data); -void delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p); -void fluid_alsa_audio_driver_settings(fluid_settings_t* settings); -static fluid_thread_return_t fluid_alsa_audio_run_float(void* d); -static fluid_thread_return_t fluid_alsa_audio_run_s16(void* d); +void delete_fluid_alsa_audio_driver(fluid_audio_driver_t *p); +void fluid_alsa_audio_driver_settings(fluid_settings_t *settings); +static fluid_thread_return_t fluid_alsa_audio_run_float(void *d); +static fluid_thread_return_t fluid_alsa_audio_run_s16(void *d); -struct fluid_alsa_formats_t { - char* name; - snd_pcm_format_t format; - snd_pcm_access_t access; - fluid_thread_func_t run; +struct fluid_alsa_formats_t +{ + char *name; + snd_pcm_format_t format; + snd_pcm_access_t access; + fluid_thread_func_t run; }; -struct fluid_alsa_formats_t fluid_alsa_formats[] = { - { "s16, rw, interleaved", - SND_PCM_FORMAT_S16, - SND_PCM_ACCESS_RW_INTERLEAVED, - fluid_alsa_audio_run_s16 }, - { "float, rw, non interleaved", - SND_PCM_FORMAT_FLOAT, - SND_PCM_ACCESS_RW_NONINTERLEAVED, - fluid_alsa_audio_run_float }, - { NULL, 0, 0, NULL } +struct fluid_alsa_formats_t fluid_alsa_formats[] = +{ + { + "s16, rw, interleaved", + SND_PCM_FORMAT_S16, + SND_PCM_ACCESS_RW_INTERLEAVED, + fluid_alsa_audio_run_s16 + }, + { + "float, rw, non interleaved", + SND_PCM_FORMAT_FLOAT, + SND_PCM_ACCESS_RW_NONINTERLEAVED, + fluid_alsa_audio_run_float + }, + { NULL, 0, 0, NULL } }; @@ -95,47 +102,49 @@ struct fluid_alsa_formats_t fluid_alsa_formats[] = { * fluid_alsa_rawmidi_driver_t * */ -typedef struct { - fluid_midi_driver_t driver; - snd_rawmidi_t *rawmidi_in; - struct pollfd *pfd; - int npfd; - fluid_thread_t *thread; - fluid_atomic_int_t should_quit; - unsigned char buffer[BUFFER_LENGTH]; - fluid_midi_parser_t* parser; +typedef struct +{ + fluid_midi_driver_t driver; + snd_rawmidi_t *rawmidi_in; + struct pollfd *pfd; + int npfd; + fluid_thread_t *thread; + fluid_atomic_int_t should_quit; + unsigned char buffer[BUFFER_LENGTH]; + fluid_midi_parser_t *parser; } fluid_alsa_rawmidi_driver_t; -fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); +fluid_midi_driver_t *new_fluid_alsa_rawmidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); -void delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p); -static fluid_thread_return_t fluid_alsa_midi_run(void* d); +void delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t *p); +static fluid_thread_return_t fluid_alsa_midi_run(void *d); /* * fluid_alsa_seq_driver_t * */ -typedef struct { - fluid_midi_driver_t driver; - snd_seq_t *seq_handle; - struct pollfd *pfd; - int npfd; - fluid_thread_t *thread; - fluid_atomic_int_t should_quit; - int port_count; - int autoconn_inputs; - snd_seq_addr_t autoconn_dest; +typedef struct +{ + fluid_midi_driver_t driver; + snd_seq_t *seq_handle; + struct pollfd *pfd; + int npfd; + fluid_thread_t *thread; + fluid_atomic_int_t should_quit; + int port_count; + int autoconn_inputs; + snd_seq_addr_t autoconn_dest; } fluid_alsa_seq_driver_t; -fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* data); -void delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p); -static fluid_thread_return_t fluid_alsa_seq_run(void* d); +fluid_midi_driver_t *new_fluid_alsa_seq_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *data); +void delete_fluid_alsa_seq_driver(fluid_midi_driver_t *p); +static fluid_thread_return_t fluid_alsa_seq_run(void *d); /************************************************************** * @@ -143,393 +152,477 @@ static fluid_thread_return_t fluid_alsa_seq_run(void* d); * */ -void fluid_alsa_audio_driver_settings(fluid_settings_t* settings) +void fluid_alsa_audio_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "audio.alsa.device", "default", 0); + fluid_settings_register_str(settings, "audio.alsa.device", "default", 0); } -fluid_audio_driver_t* -new_fluid_alsa_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_alsa_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth) { - return new_fluid_alsa_audio_driver2(settings, NULL, synth); + return new_fluid_alsa_audio_driver2(settings, NULL, synth); } -fluid_audio_driver_t* -new_fluid_alsa_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data) +fluid_audio_driver_t * +new_fluid_alsa_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data) { - fluid_alsa_audio_driver_t* dev; - double sample_rate; - int periods, period_size; - char* device = NULL; - int realtime_prio = 0; - int i, err, dir = 0; - snd_pcm_hw_params_t* hwparams; - snd_pcm_sw_params_t* swparams = NULL; - snd_pcm_uframes_t uframes; - unsigned int tmp; + fluid_alsa_audio_driver_t *dev; + double sample_rate; + int periods, period_size; + char *device = NULL; + int realtime_prio = 0; + int i, err, dir = 0; + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams = NULL; + snd_pcm_uframes_t uframes; + unsigned int tmp; - dev = FLUID_NEW(fluid_alsa_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + dev = FLUID_NEW(fluid_alsa_audio_driver_t); + + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_alsa_audio_driver_t)); + + fluid_settings_getint(settings, "audio.periods", &periods); + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_dupstr(settings, "audio.alsa.device", &device); /* ++ dup device name */ + fluid_settings_getint(settings, "audio.realtime-prio", &realtime_prio); + + dev->data = data; + dev->callback = func; + dev->cont = 1; + dev->buffer_size = period_size; + + /* Open the PCM device */ + if((err = snd_pcm_open(&dev->pcm, device ? device : "default", + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) != 0) + { + if(err == -EBUSY) + { + FLUID_LOG(FLUID_ERR, "The \"%s\" audio device is used by another application", + device ? device : "default"); + goto error_recovery; + } + else + { + FLUID_LOG(FLUID_ERR, "Failed to open the \"%s\" audio device", + device ? device : "default"); + goto error_recovery; + } + } + + snd_pcm_hw_params_alloca(&hwparams); + snd_pcm_sw_params_alloca(&swparams); + + /* Set hardware parameters. We continue trying access methods and + sample formats until we have one that works. For example, if + memory mapped access fails we try regular IO methods. (not + finished, yet). */ + + for(i = 0; fluid_alsa_formats[i].name != NULL; i++) + { + + snd_pcm_hw_params_any(dev->pcm, hwparams); + + if(snd_pcm_hw_params_set_access(dev->pcm, hwparams, fluid_alsa_formats[i].access) < 0) + { + continue; + } + + if(snd_pcm_hw_params_set_format(dev->pcm, hwparams, fluid_alsa_formats[i].format) < 0) + { + continue; + } + + if((err = snd_pcm_hw_params_set_channels(dev->pcm, hwparams, 2)) < 0) + { + FLUID_LOG(FLUID_ERR, "Failed to set the channels: %s", + snd_strerror(err)); + goto error_recovery; + } + + tmp = (unsigned int) sample_rate; + + if((err = snd_pcm_hw_params_set_rate_near(dev->pcm, hwparams, &tmp, NULL)) < 0) + { + FLUID_LOG(FLUID_ERR, "Failed to set the sample rate: %s", + snd_strerror(err)); + goto error_recovery; + } + + if(tmp != sample_rate) + { + /* There's currently no way to change the sampling rate of the + synthesizer after it's been created. */ + FLUID_LOG(FLUID_WARN, "Requested sample rate of %u, got %u instead, " + "synthesizer likely out of tune!", (unsigned int) sample_rate, tmp); + } + + uframes = period_size; + + if(snd_pcm_hw_params_set_period_size_near(dev->pcm, hwparams, &uframes, &dir) < 0) + { + FLUID_LOG(FLUID_ERR, "Failed to set the period size"); + goto error_recovery; + } + + if(uframes != (unsigned long) period_size) + { + FLUID_LOG(FLUID_WARN, "Requested a period size of %d, got %d instead", + period_size, (int) uframes); + dev->buffer_size = (int) uframes; + period_size = uframes; /* period size is used below, so set it to the real value */ + } + + tmp = periods; + + if(snd_pcm_hw_params_set_periods_near(dev->pcm, hwparams, &tmp, &dir) < 0) + { + FLUID_LOG(FLUID_ERR, "Failed to set the number of periods"); + goto error_recovery; + } + + if(tmp != (unsigned int) periods) + { + FLUID_LOG(FLUID_WARN, "Requested %d periods, got %d instead", + periods, (int) tmp); + } + + if(snd_pcm_hw_params(dev->pcm, hwparams) < 0) + { + FLUID_LOG(FLUID_WARN, "Audio device hardware configuration failed"); + continue; + } + + break; + } + + if(fluid_alsa_formats[i].name == NULL) + { + FLUID_LOG(FLUID_ERR, "Failed to find a workable audio format"); + goto error_recovery; + } + + /* Set the software params */ + snd_pcm_sw_params_current(dev->pcm, swparams); + + if(snd_pcm_sw_params_set_start_threshold(dev->pcm, swparams, period_size) != 0) + { + FLUID_LOG(FLUID_ERR, "Failed to set start threshold."); + } + + if(snd_pcm_sw_params_set_avail_min(dev->pcm, swparams, period_size) != 0) + { + FLUID_LOG(FLUID_ERR, "Software setup for minimum available frames failed."); + } + + if(snd_pcm_sw_params(dev->pcm, swparams) != 0) + { + FLUID_LOG(FLUID_ERR, "Software setup failed."); + } + + if(snd_pcm_nonblock(dev->pcm, 0) != 0) + { + FLUID_LOG(FLUID_ERR, "Failed to set the audio device to blocking mode"); + goto error_recovery; + } + + /* Create the audio thread */ + dev->thread = new_fluid_thread("alsa-audio", fluid_alsa_formats[i].run, dev, realtime_prio, FALSE); + + if(!dev->thread) + { + goto error_recovery; + } + + if(device) + { + FLUID_FREE(device); /* -- free device name */ + } + + return (fluid_audio_driver_t *) dev; + +error_recovery: + + if(device) + { + FLUID_FREE(device); /* -- free device name */ + } + + delete_fluid_alsa_audio_driver((fluid_audio_driver_t *) dev); return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_alsa_audio_driver_t)); - - fluid_settings_getint(settings, "audio.periods", &periods); - fluid_settings_getint(settings, "audio.period-size", &period_size); - fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); - fluid_settings_dupstr(settings, "audio.alsa.device", &device); /* ++ dup device name */ - fluid_settings_getint (settings, "audio.realtime-prio", &realtime_prio); - - dev->data = data; - dev->callback = func; - dev->cont = 1; - dev->buffer_size = period_size; - - /* Open the PCM device */ - if ((err = snd_pcm_open(&dev->pcm, device ? device : "default", - SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) != 0) { - if (err == -EBUSY) { - FLUID_LOG(FLUID_ERR, "The \"%s\" audio device is used by another application", - device ? device : "default"); - goto error_recovery; - } else { - FLUID_LOG(FLUID_ERR, "Failed to open the \"%s\" audio device", - device ? device : "default"); - goto error_recovery; - } - } - - snd_pcm_hw_params_alloca(&hwparams); - snd_pcm_sw_params_alloca(&swparams); - - /* Set hardware parameters. We continue trying access methods and - sample formats until we have one that works. For example, if - memory mapped access fails we try regular IO methods. (not - finished, yet). */ - - for (i = 0; fluid_alsa_formats[i].name != NULL; i++) { - - snd_pcm_hw_params_any(dev->pcm, hwparams); - - if (snd_pcm_hw_params_set_access(dev->pcm, hwparams, fluid_alsa_formats[i].access) < 0) { - continue; - } - - if (snd_pcm_hw_params_set_format(dev->pcm, hwparams, fluid_alsa_formats[i].format) < 0) { - continue; - } - - if ((err = snd_pcm_hw_params_set_channels(dev->pcm, hwparams, 2)) < 0) { - FLUID_LOG(FLUID_ERR, "Failed to set the channels: %s", - snd_strerror (err)); - goto error_recovery; - } - - tmp = (unsigned int) sample_rate; - if ((err = snd_pcm_hw_params_set_rate_near(dev->pcm, hwparams, &tmp, NULL)) < 0) { - FLUID_LOG(FLUID_ERR, "Failed to set the sample rate: %s", - snd_strerror (err)); - goto error_recovery; - } - - if (tmp != sample_rate) { - /* There's currently no way to change the sampling rate of the - synthesizer after it's been created. */ - FLUID_LOG(FLUID_WARN, "Requested sample rate of %u, got %u instead, " - "synthesizer likely out of tune!", (unsigned int) sample_rate, tmp); - } - - uframes = period_size; - if (snd_pcm_hw_params_set_period_size_near(dev->pcm, hwparams, &uframes, &dir) < 0) { - FLUID_LOG(FLUID_ERR, "Failed to set the period size"); - goto error_recovery; - } - if (uframes != (unsigned long) period_size) { - FLUID_LOG(FLUID_WARN, "Requested a period size of %d, got %d instead", - period_size, (int) uframes); - dev->buffer_size = (int) uframes; - period_size = uframes; /* period size is used below, so set it to the real value */ - } - - tmp = periods; - if (snd_pcm_hw_params_set_periods_near(dev->pcm, hwparams, &tmp, &dir) < 0) { - FLUID_LOG(FLUID_ERR, "Failed to set the number of periods"); - goto error_recovery; - } - if (tmp != (unsigned int) periods) { - FLUID_LOG(FLUID_WARN, "Requested %d periods, got %d instead", - periods, (int) tmp); - } - - if (snd_pcm_hw_params(dev->pcm, hwparams) < 0) { - FLUID_LOG(FLUID_WARN, "Audio device hardware configuration failed"); - continue; - } - - break; - } - - if (fluid_alsa_formats[i].name == NULL) { - FLUID_LOG(FLUID_ERR, "Failed to find a workable audio format"); - goto error_recovery; - } - - /* Set the software params */ - snd_pcm_sw_params_current(dev->pcm, swparams); - - if (snd_pcm_sw_params_set_start_threshold(dev->pcm, swparams, period_size) != 0) { - FLUID_LOG(FLUID_ERR, "Failed to set start threshold."); - } - - if (snd_pcm_sw_params_set_avail_min(dev->pcm, swparams, period_size) != 0) { - FLUID_LOG(FLUID_ERR, "Software setup for minimum available frames failed."); - } - - if (snd_pcm_sw_params(dev->pcm, swparams) != 0) { - FLUID_LOG(FLUID_ERR, "Software setup failed."); - } - - if (snd_pcm_nonblock(dev->pcm, 0) != 0) { - FLUID_LOG(FLUID_ERR, "Failed to set the audio device to blocking mode"); - goto error_recovery; - } - - /* Create the audio thread */ - dev->thread = new_fluid_thread ("alsa-audio", fluid_alsa_formats[i].run, dev, realtime_prio, FALSE); - - if (!dev->thread) - goto error_recovery; - - if (device) FLUID_FREE (device); /* -- free device name */ - - return (fluid_audio_driver_t*) dev; - - error_recovery: - if (device) FLUID_FREE (device); /* -- free device name */ - delete_fluid_alsa_audio_driver((fluid_audio_driver_t*) dev); - return NULL; } -void delete_fluid_alsa_audio_driver(fluid_audio_driver_t* p) +void delete_fluid_alsa_audio_driver(fluid_audio_driver_t *p) { - fluid_alsa_audio_driver_t* dev = (fluid_alsa_audio_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_alsa_audio_driver_t *dev = (fluid_alsa_audio_driver_t *) p; + fluid_return_if_fail(dev != NULL); - dev->cont = 0; + dev->cont = 0; - if (dev->thread) - fluid_thread_join (dev->thread); + if(dev->thread) + { + fluid_thread_join(dev->thread); + } - if (dev->pcm) - snd_pcm_close (dev->pcm); + if(dev->pcm) + { + snd_pcm_close(dev->pcm); + } - FLUID_FREE(dev); + FLUID_FREE(dev); } /* handle error after an ALSA write call */ -static int fluid_alsa_handle_write_error (snd_pcm_t *pcm, int errval) +static int fluid_alsa_handle_write_error(snd_pcm_t *pcm, int errval) { - switch (errval) - { - case -EAGAIN: - snd_pcm_wait(pcm, 1); - break; + switch(errval) + { + case -EAGAIN: + snd_pcm_wait(pcm, 1); + break; // on some BSD variants ESTRPIPE is defined as EPIPE. // not sure why, maybe because this version of alsa doesnt support -// suspending pcm streams. anyway, since EPIPE seems to be more +// suspending pcm streams. anyway, since EPIPE seems to be more // likely than ESTRPIPE, so ifdef it out in case. #if ESTRPIPE == EPIPE - #warning "ESTRPIPE defined as EPIPE. This may cause trouble with ALSA playback." +#warning "ESTRPIPE defined as EPIPE. This may cause trouble with ALSA playback." #else - case -ESTRPIPE: - if (snd_pcm_resume(pcm) != 0) { - FLUID_LOG(FLUID_ERR, "Failed to resume the audio device"); - return FLUID_FAILED; - } + + case -ESTRPIPE: + if(snd_pcm_resume(pcm) != 0) + { + FLUID_LOG(FLUID_ERR, "Failed to resume the audio device"); + return FLUID_FAILED; + } + #endif - /* fall through ... */ - /* ... since the stream got resumed, but still has to be prepared */ - case -EPIPE: - case -EBADFD: - if (snd_pcm_prepare(pcm) != 0) { - FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); - return FLUID_FAILED; + + /* fall through ... */ + /* ... since the stream got resumed, but still has to be prepared */ + case -EPIPE: + case -EBADFD: + if(snd_pcm_prepare(pcm) != 0) + { + FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); + return FLUID_FAILED; + } + + break; + + default: + FLUID_LOG(FLUID_ERR, "The audio device error: %s", snd_strerror(errval)); + return FLUID_FAILED; } - break; - default: - FLUID_LOG(FLUID_ERR, "The audio device error: %s", snd_strerror(errval)); - return FLUID_FAILED; - } - return FLUID_OK; + return FLUID_OK; } -static fluid_thread_return_t fluid_alsa_audio_run_float (void *d) +static fluid_thread_return_t fluid_alsa_audio_run_float(void *d) { - fluid_alsa_audio_driver_t* dev = (fluid_alsa_audio_driver_t*) d; - fluid_synth_t *synth = (fluid_synth_t *)(dev->data); - float* left; - float* right; - float* handle[2]; - int n, buffer_size, offset; + fluid_alsa_audio_driver_t *dev = (fluid_alsa_audio_driver_t *) d; + fluid_synth_t *synth = (fluid_synth_t *)(dev->data); + float *left; + float *right; + float *handle[2]; + int n, buffer_size, offset; - buffer_size = dev->buffer_size; + buffer_size = dev->buffer_size; - left = FLUID_ARRAY(float, buffer_size); - right = FLUID_ARRAY(float, buffer_size); + left = FLUID_ARRAY(float, buffer_size); + right = FLUID_ARRAY(float, buffer_size); - if ((left == NULL) || (right == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory."); - goto error_recovery; - } + if((left == NULL) || (right == NULL)) + { + FLUID_LOG(FLUID_ERR, "Out of memory."); + goto error_recovery; + } - if (snd_pcm_prepare(dev->pcm) != 0) { - FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); - goto error_recovery; - } + if(snd_pcm_prepare(dev->pcm) != 0) + { + FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); + goto error_recovery; + } - /* use separate loops depending on if callback supplied or not (overkill?) */ - if (dev->callback) - { - while (dev->cont) { - handle[0] = left; - handle[1] = right; + /* use separate loops depending on if callback supplied or not (overkill?) */ + if(dev->callback) + { + while(dev->cont) + { + handle[0] = left; + handle[1] = right; - (*dev->callback)(synth, buffer_size, 0, NULL, 2, handle); + (*dev->callback)(synth, buffer_size, 0, NULL, 2, handle); - offset = 0; - while (offset < buffer_size) { - handle[0] = left + offset; - handle[1] = right + offset; + offset = 0; - n = snd_pcm_writen(dev->pcm, (void *)handle, buffer_size - offset); + while(offset < buffer_size) + { + handle[0] = left + offset; + handle[1] = right + offset; - if (n < 0) /* error occurred? */ - { - if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK) - goto error_recovery; - } else offset += n; /* no error occurred */ - } /* while (offset < buffer_size) */ - } /* while (dev->cont) */ - } - else /* no user audio callback (faster) */ - { - while (dev->cont) { - fluid_synth_write_float(dev->data, buffer_size, left, 0, 1, right, 0, 1); + n = snd_pcm_writen(dev->pcm, (void *)handle, buffer_size - offset); - offset = 0; - while (offset < buffer_size) { - handle[0] = left + offset; - handle[1] = right + offset; + if(n < 0) /* error occurred? */ + { + if(fluid_alsa_handle_write_error(dev->pcm, n) != FLUID_OK) + { + goto error_recovery; + } + } + else + { + offset += n; /* no error occurred */ + } + } /* while (offset < buffer_size) */ + } /* while (dev->cont) */ + } + else /* no user audio callback (faster) */ + { + while(dev->cont) + { + fluid_synth_write_float(dev->data, buffer_size, left, 0, 1, right, 0, 1); - n = snd_pcm_writen(dev->pcm, (void *)handle, buffer_size - offset); + offset = 0; - if (n < 0) /* error occurred? */ - { - if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK) - goto error_recovery; - } else offset += n; /* no error occurred */ - } /* while (offset < buffer_size) */ - } /* while (dev->cont) */ - } + while(offset < buffer_size) + { + handle[0] = left + offset; + handle[1] = right + offset; - error_recovery: + n = snd_pcm_writen(dev->pcm, (void *)handle, buffer_size - offset); - FLUID_FREE(left); - FLUID_FREE(right); + if(n < 0) /* error occurred? */ + { + if(fluid_alsa_handle_write_error(dev->pcm, n) != FLUID_OK) + { + goto error_recovery; + } + } + else + { + offset += n; /* no error occurred */ + } + } /* while (offset < buffer_size) */ + } /* while (dev->cont) */ + } - return FLUID_THREAD_RETURN_VALUE; +error_recovery: + + FLUID_FREE(left); + FLUID_FREE(right); + + return FLUID_THREAD_RETURN_VALUE; } -static fluid_thread_return_t fluid_alsa_audio_run_s16 (void *d) +static fluid_thread_return_t fluid_alsa_audio_run_s16(void *d) { - fluid_alsa_audio_driver_t* dev = (fluid_alsa_audio_driver_t*) d; - float* left; - float* right; - short* buf; - float* handle[2]; - int n, buffer_size, offset; + fluid_alsa_audio_driver_t *dev = (fluid_alsa_audio_driver_t *) d; + float *left; + float *right; + short *buf; + float *handle[2]; + int n, buffer_size, offset; - buffer_size = dev->buffer_size; + buffer_size = dev->buffer_size; - left = FLUID_ARRAY(float, buffer_size); - right = FLUID_ARRAY(float, buffer_size); - buf = FLUID_ARRAY(short, 2 * buffer_size); + left = FLUID_ARRAY(float, buffer_size); + right = FLUID_ARRAY(float, buffer_size); + buf = FLUID_ARRAY(short, 2 * buffer_size); - if ((left == NULL) || (right == NULL) || (buf == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory."); - goto error_recovery; - } - - handle[0] = left; - handle[1] = right; - - if (snd_pcm_prepare(dev->pcm) != 0) { - FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); - goto error_recovery; - } - - /* use separate loops depending on if callback supplied or not */ - if (dev->callback) - { - int dither_index = 0; - - while (dev->cont) + if((left == NULL) || (right == NULL) || (buf == NULL)) { - (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, handle); + FLUID_LOG(FLUID_ERR, "Out of memory."); + goto error_recovery; + } - /* convert floating point data to 16 bit (with dithering) */ - fluid_synth_dither_s16 (&dither_index, buffer_size, left, right, - buf, 0, 2, buf, 1, 2); - offset = 0; - while (offset < buffer_size) - { - n = snd_pcm_writei (dev->pcm, (void*) (buf + 2 * offset), - buffer_size - offset); - if (n < 0) /* error occurred? */ - { - if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK) - goto error_recovery; - } - else offset += n; /* no error occurred */ - } /* while (offset < buffer_size) */ - } /* while (dev->cont) */ - } - else /* no user audio callback, dev->data is the synth instance */ - { - fluid_synth_t* synth = (fluid_synth_t *)(dev->data); + handle[0] = left; + handle[1] = right; - while (dev->cont) + if(snd_pcm_prepare(dev->pcm) != 0) { - fluid_synth_write_s16 (synth, buffer_size, buf, 0, 2, buf, 1, 2); + FLUID_LOG(FLUID_ERR, "Failed to prepare the audio device"); + goto error_recovery; + } - offset = 0; - while (offset < buffer_size) - { - n = snd_pcm_writei (dev->pcm, (void*) (buf + 2 * offset), - buffer_size - offset); + /* use separate loops depending on if callback supplied or not */ + if(dev->callback) + { + int dither_index = 0; - if (n < 0) /* error occurred? */ - { - if (fluid_alsa_handle_write_error (dev->pcm, n) != FLUID_OK) - goto error_recovery; - } - else offset += n; /* no error occurred */ - } /* while (offset < buffer_size) */ - } /* while (dev->cont) */ - } + while(dev->cont) + { + (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, handle); - error_recovery: + /* convert floating point data to 16 bit (with dithering) */ + fluid_synth_dither_s16(&dither_index, buffer_size, left, right, + buf, 0, 2, buf, 1, 2); + offset = 0; - FLUID_FREE(left); - FLUID_FREE(right); - FLUID_FREE(buf); + while(offset < buffer_size) + { + n = snd_pcm_writei(dev->pcm, (void *)(buf + 2 * offset), + buffer_size - offset); - return FLUID_THREAD_RETURN_VALUE; + if(n < 0) /* error occurred? */ + { + if(fluid_alsa_handle_write_error(dev->pcm, n) != FLUID_OK) + { + goto error_recovery; + } + } + else + { + offset += n; /* no error occurred */ + } + } /* while (offset < buffer_size) */ + } /* while (dev->cont) */ + } + else /* no user audio callback, dev->data is the synth instance */ + { + fluid_synth_t *synth = (fluid_synth_t *)(dev->data); + + while(dev->cont) + { + fluid_synth_write_s16(synth, buffer_size, buf, 0, 2, buf, 1, 2); + + offset = 0; + + while(offset < buffer_size) + { + n = snd_pcm_writei(dev->pcm, (void *)(buf + 2 * offset), + buffer_size - offset); + + if(n < 0) /* error occurred? */ + { + if(fluid_alsa_handle_write_error(dev->pcm, n) != FLUID_OK) + { + goto error_recovery; + } + } + else + { + offset += n; /* no error occurred */ + } + } /* while (offset < buffer_size) */ + } /* while (dev->cont) */ + } + +error_recovery: + + FLUID_FREE(left); + FLUID_FREE(right); + FLUID_FREE(buf); + + return FLUID_THREAD_RETURN_VALUE; } @@ -540,100 +633,122 @@ static fluid_thread_return_t fluid_alsa_audio_run_s16 (void *d) */ -void fluid_alsa_rawmidi_driver_settings(fluid_settings_t* settings) +void fluid_alsa_rawmidi_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "midi.alsa.device", "default", 0); + fluid_settings_register_str(settings, "midi.alsa.device", "default", 0); } /* * new_fluid_alsa_rawmidi_driver */ -fluid_midi_driver_t* -new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* data) +fluid_midi_driver_t * +new_fluid_alsa_rawmidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *data) { - int i, err; - fluid_alsa_rawmidi_driver_t* dev; - int realtime_prio = 0; - int count; - struct pollfd *pfd = NULL; - char* device = NULL; + int i, err; + fluid_alsa_rawmidi_driver_t *dev; + int realtime_prio = 0; + int count; + struct pollfd *pfd = NULL; + char *device = NULL; - /* not much use doing anything */ - if (handler == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid argument"); - return NULL; - } - - /* allocate the device */ - dev = FLUID_NEW(fluid_alsa_rawmidi_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_alsa_rawmidi_driver_t)); - - dev->driver.handler = handler; - dev->driver.data = data; - - /* allocate one event to store the input data */ - dev->parser = new_fluid_midi_parser(); - if (dev->parser == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } - - fluid_settings_getint (settings, "midi.realtime-prio", &realtime_prio); - - /* get the device name. if none is specified, use the default device. */ - fluid_settings_dupstr(settings, "midi.alsa.device", &device); /* ++ alloc device name */ - - /* open the hardware device. only use midi in. */ - if ((err = snd_rawmidi_open(&dev->rawmidi_in, NULL, device ? device : "default", - SND_RAWMIDI_NONBLOCK)) < 0) { - FLUID_LOG(FLUID_ERR, "Error opening ALSA raw MIDI port"); - goto error_recovery; - } - - snd_rawmidi_nonblock(dev->rawmidi_in, 1); - - /* get # of MIDI file descriptors */ - count = snd_rawmidi_poll_descriptors_count(dev->rawmidi_in); - if (count > 0) { /* make sure there are some */ - pfd = FLUID_MALLOC(sizeof (struct pollfd) * count); - dev->pfd = FLUID_MALLOC(sizeof (struct pollfd) * count); - /* grab file descriptor POLL info structures */ - count = snd_rawmidi_poll_descriptors(dev->rawmidi_in, pfd, count); - } - - /* copy the input FDs */ - for (i = 0; i < count; i++) { /* loop over file descriptors */ - if (pfd[i].events & POLLIN) { /* use only the input FDs */ - dev->pfd[dev->npfd].fd = pfd[i].fd; - dev->pfd[dev->npfd].events = POLLIN; - dev->pfd[dev->npfd].revents = 0; - dev->npfd++; + /* not much use doing anything */ + if(handler == NULL) + { + FLUID_LOG(FLUID_ERR, "Invalid argument"); + return NULL; } - } - FLUID_FREE(pfd); - fluid_atomic_int_set(&dev->should_quit, 0); + /* allocate the device */ + dev = FLUID_NEW(fluid_alsa_rawmidi_driver_t); - /* create the MIDI thread */ - dev->thread = new_fluid_thread ("alsa-midi-raw", fluid_alsa_midi_run, dev, realtime_prio, FALSE); + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - if (!dev->thread) - goto error_recovery; + FLUID_MEMSET(dev, 0, sizeof(fluid_alsa_rawmidi_driver_t)); - if (device) FLUID_FREE (device); /* -- free device name */ + dev->driver.handler = handler; + dev->driver.data = data; - return (fluid_midi_driver_t*) dev; + /* allocate one event to store the input data */ + dev->parser = new_fluid_midi_parser(); - error_recovery: - if (device) FLUID_FREE (device); /* -- free device name */ - delete_fluid_alsa_rawmidi_driver((fluid_midi_driver_t*) dev); - return NULL; + if(dev->parser == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + fluid_settings_getint(settings, "midi.realtime-prio", &realtime_prio); + + /* get the device name. if none is specified, use the default device. */ + fluid_settings_dupstr(settings, "midi.alsa.device", &device); /* ++ alloc device name */ + + /* open the hardware device. only use midi in. */ + if((err = snd_rawmidi_open(&dev->rawmidi_in, NULL, device ? device : "default", + SND_RAWMIDI_NONBLOCK)) < 0) + { + FLUID_LOG(FLUID_ERR, "Error opening ALSA raw MIDI port"); + goto error_recovery; + } + + snd_rawmidi_nonblock(dev->rawmidi_in, 1); + + /* get # of MIDI file descriptors */ + count = snd_rawmidi_poll_descriptors_count(dev->rawmidi_in); + + if(count > 0) /* make sure there are some */ + { + pfd = FLUID_MALLOC(sizeof(struct pollfd) * count); + dev->pfd = FLUID_MALLOC(sizeof(struct pollfd) * count); + /* grab file descriptor POLL info structures */ + count = snd_rawmidi_poll_descriptors(dev->rawmidi_in, pfd, count); + } + + /* copy the input FDs */ + for(i = 0; i < count; i++) /* loop over file descriptors */ + { + if(pfd[i].events & POLLIN) /* use only the input FDs */ + { + dev->pfd[dev->npfd].fd = pfd[i].fd; + dev->pfd[dev->npfd].events = POLLIN; + dev->pfd[dev->npfd].revents = 0; + dev->npfd++; + } + } + + FLUID_FREE(pfd); + + fluid_atomic_int_set(&dev->should_quit, 0); + + /* create the MIDI thread */ + dev->thread = new_fluid_thread("alsa-midi-raw", fluid_alsa_midi_run, dev, realtime_prio, FALSE); + + if(!dev->thread) + { + goto error_recovery; + } + + if(device) + { + FLUID_FREE(device); /* -- free device name */ + } + + return (fluid_midi_driver_t *) dev; + +error_recovery: + + if(device) + { + FLUID_FREE(device); /* -- free device name */ + } + + delete_fluid_alsa_rawmidi_driver((fluid_midi_driver_t *) dev); + return NULL; } @@ -641,63 +756,79 @@ new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings, * delete_fluid_alsa_rawmidi_driver */ void -delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p) +delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t *p) { - fluid_alsa_rawmidi_driver_t* dev = (fluid_alsa_rawmidi_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_alsa_rawmidi_driver_t *dev = (fluid_alsa_rawmidi_driver_t *) p; + fluid_return_if_fail(dev != NULL); - /* cancel the thread and wait for it before cleaning up */ - fluid_atomic_int_set(&dev->should_quit, 1); + /* cancel the thread and wait for it before cleaning up */ + fluid_atomic_int_set(&dev->should_quit, 1); - if (dev->thread) - fluid_thread_join (dev->thread); + if(dev->thread) + { + fluid_thread_join(dev->thread); + } - if (dev->rawmidi_in) { - snd_rawmidi_close(dev->rawmidi_in); - } - if (dev->parser != NULL) { - delete_fluid_midi_parser(dev->parser); - } - FLUID_FREE(dev); + if(dev->rawmidi_in) + { + snd_rawmidi_close(dev->rawmidi_in); + } + + if(dev->parser != NULL) + { + delete_fluid_midi_parser(dev->parser); + } + + FLUID_FREE(dev); } /* * fluid_alsa_midi_run */ fluid_thread_return_t -fluid_alsa_midi_run(void* d) +fluid_alsa_midi_run(void *d) { - fluid_midi_event_t* evt; - fluid_alsa_rawmidi_driver_t* dev = (fluid_alsa_rawmidi_driver_t*) d; - int n, i; + fluid_midi_event_t *evt; + fluid_alsa_rawmidi_driver_t *dev = (fluid_alsa_rawmidi_driver_t *) d; + int n, i; - /* go into a loop until someone tells us to stop */ - while (!fluid_atomic_int_get(&dev->should_quit)) { + /* go into a loop until someone tells us to stop */ + while(!fluid_atomic_int_get(&dev->should_quit)) + { - /* is there something to read? */ - n = poll(dev->pfd, dev->npfd, 100); /* use a 100 milliseconds timeout */ - if (n < 0) { - perror("poll"); - } else if (n > 0) { + /* is there something to read? */ + n = poll(dev->pfd, dev->npfd, 100); /* use a 100 milliseconds timeout */ - /* read new data */ - n = snd_rawmidi_read(dev->rawmidi_in, dev->buffer, BUFFER_LENGTH); - if ((n < 0) && (n != -EAGAIN)) { - FLUID_LOG(FLUID_ERR, "Failed to read the midi input"); - fluid_atomic_int_set(&dev->should_quit, 1); - } + if(n < 0) + { + perror("poll"); + } + else if(n > 0) + { - /* let the parser convert the data into events */ - for (i = 0; i < n; i++) { - evt = fluid_midi_parser_parse(dev->parser, dev->buffer[i]); - if (evt != NULL) { - (*dev->driver.handler)(dev->driver.data, evt); - } - } + /* read new data */ + n = snd_rawmidi_read(dev->rawmidi_in, dev->buffer, BUFFER_LENGTH); + + if((n < 0) && (n != -EAGAIN)) + { + FLUID_LOG(FLUID_ERR, "Failed to read the midi input"); + fluid_atomic_int_set(&dev->should_quit, 1); + } + + /* let the parser convert the data into events */ + for(i = 0; i < n; i++) + { + evt = fluid_midi_parser_parse(dev->parser, dev->buffer[i]); + + if(evt != NULL) + { + (*dev->driver.handler)(dev->driver.data, evt); + } + } + } } - } - return FLUID_THREAD_RETURN_VALUE; + return FLUID_THREAD_RETURN_VALUE; } /************************************************************** @@ -707,416 +838,531 @@ fluid_alsa_midi_run(void* d) */ -void fluid_alsa_seq_driver_settings(fluid_settings_t* settings) +void fluid_alsa_seq_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "midi.alsa_seq.device", "default", 0); - fluid_settings_register_str(settings, "midi.alsa_seq.id", "pid", 0); + fluid_settings_register_str(settings, "midi.alsa_seq.device", "default", 0); + fluid_settings_register_str(settings, "midi.alsa_seq.id", "pid", 0); } -static char* fluid_alsa_seq_full_id(char* id, char* buf, int len) +static char *fluid_alsa_seq_full_id(char *id, char *buf, int len) { - if (id != NULL) { - if (FLUID_STRCMP(id, "pid") == 0) { - FLUID_SNPRINTF (buf, len, "FLUID Synth (%d)", getpid()); - } else { - FLUID_SNPRINTF (buf, len, "FLUID Synth (%s)", id); + if(id != NULL) + { + if(FLUID_STRCMP(id, "pid") == 0) + { + FLUID_SNPRINTF(buf, len, "FLUID Synth (%d)", getpid()); + } + else + { + FLUID_SNPRINTF(buf, len, "FLUID Synth (%s)", id); + } + } + else + { + FLUID_SNPRINTF(buf, len, "FLUID Synth"); } - } else { - FLUID_SNPRINTF (buf, len, "FLUID Synth"); - } - return buf; + return buf; } -static char* fluid_alsa_seq_full_name(char* id, int port, char* buf, int len) +static char *fluid_alsa_seq_full_name(char *id, int port, char *buf, int len) { - if (id != NULL) { - if (FLUID_STRCMP(id, "pid") == 0) { - FLUID_SNPRINTF (buf, len, "Synth input port (%d:%d)", getpid(), port); - } else { - FLUID_SNPRINTF (buf, len, "Synth input port (%s:%d)", id, port); + if(id != NULL) + { + if(FLUID_STRCMP(id, "pid") == 0) + { + FLUID_SNPRINTF(buf, len, "Synth input port (%d:%d)", getpid(), port); + } + else + { + FLUID_SNPRINTF(buf, len, "Synth input port (%s:%d)", id, port); + } } - } else { - FLUID_SNPRINTF (buf, len, "Synth input port"); - } - return buf; + else + { + FLUID_SNPRINTF(buf, len, "Synth input port"); + } + + return buf; } // Connect a single port_info to autoconnect_dest if it has right type/capabilities -static void fluid_alsa_seq_autoconnect_port_info(fluid_alsa_seq_driver_t* dev, snd_seq_port_info_t *pinfo) +static void fluid_alsa_seq_autoconnect_port_info(fluid_alsa_seq_driver_t *dev, snd_seq_port_info_t *pinfo) { - snd_seq_port_subscribe_t *subs; - snd_seq_t *seq = dev->seq_handle; - const unsigned int needed_type = SND_SEQ_PORT_TYPE_MIDI_GENERIC; - const unsigned int needed_cap = SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ; - const snd_seq_addr_t *sender = snd_seq_port_info_get_addr(pinfo); - const char *pname = snd_seq_port_info_get_name(pinfo); - if ((snd_seq_port_info_get_type(pinfo) & needed_type) != needed_type) - return; - if ((snd_seq_port_info_get_capability(pinfo) & needed_cap) != needed_cap) - return; - snd_seq_port_subscribe_alloca(&subs); - snd_seq_port_subscribe_set_sender(subs, sender); - snd_seq_port_subscribe_set_dest(subs, &dev->autoconn_dest); + snd_seq_port_subscribe_t *subs; + snd_seq_t *seq = dev->seq_handle; + const unsigned int needed_type = SND_SEQ_PORT_TYPE_MIDI_GENERIC; + const unsigned int needed_cap = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; + const snd_seq_addr_t *sender = snd_seq_port_info_get_addr(pinfo); + const char *pname = snd_seq_port_info_get_name(pinfo); - if (snd_seq_get_port_subscription(seq, subs) == 0) { - FLUID_LOG(FLUID_WARN, "Connection %s is already subscribed", pname); - return; - } - if (snd_seq_subscribe_port(seq, subs) < 0) { - FLUID_LOG(FLUID_ERR, "Connection of %s failed (%s)", pname, snd_strerror(errno)); - return; - } - FLUID_LOG(FLUID_INFO, "Connection of %s succeeded", pname); + if((snd_seq_port_info_get_type(pinfo) & needed_type) != needed_type) + { + return; + } + + if((snd_seq_port_info_get_capability(pinfo) & needed_cap) != needed_cap) + { + return; + } + + snd_seq_port_subscribe_alloca(&subs); + snd_seq_port_subscribe_set_sender(subs, sender); + snd_seq_port_subscribe_set_dest(subs, &dev->autoconn_dest); + + if(snd_seq_get_port_subscription(seq, subs) == 0) + { + FLUID_LOG(FLUID_WARN, "Connection %s is already subscribed", pname); + return; + } + + if(snd_seq_subscribe_port(seq, subs) < 0) + { + FLUID_LOG(FLUID_ERR, "Connection of %s failed (%s)", pname, snd_strerror(errno)); + return; + } + + FLUID_LOG(FLUID_INFO, "Connection of %s succeeded", pname); } // Autoconnect a single client port (by id) to autoconnect_dest if it has right type/capabilities -static void fluid_alsa_seq_autoconnect_port(fluid_alsa_seq_driver_t* dev, int client_id, int port_id) +static void fluid_alsa_seq_autoconnect_port(fluid_alsa_seq_driver_t *dev, int client_id, int port_id) { - int err; - snd_seq_t *seq = dev->seq_handle; - snd_seq_port_info_t *pinfo; + int err; + snd_seq_t *seq = dev->seq_handle; + snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca(&pinfo); + snd_seq_port_info_alloca(&pinfo); - if ((err = snd_seq_get_any_port_info(seq, client_id, port_id, pinfo)) < 0) { - FLUID_LOG(FLUID_ERR, "snd_seq_get_any_port_info() failed: %s", snd_strerror(err)); - return; - } - fluid_alsa_seq_autoconnect_port_info(dev, pinfo); + if((err = snd_seq_get_any_port_info(seq, client_id, port_id, pinfo)) < 0) + { + FLUID_LOG(FLUID_ERR, "snd_seq_get_any_port_info() failed: %s", snd_strerror(err)); + return; + } + + fluid_alsa_seq_autoconnect_port_info(dev, pinfo); } // Connect available ALSA MIDI inputs to the provided port_info -static void fluid_alsa_seq_autoconnect(fluid_alsa_seq_driver_t* dev, const snd_seq_port_info_t *dest_pinfo) +static void fluid_alsa_seq_autoconnect(fluid_alsa_seq_driver_t *dev, const snd_seq_port_info_t *dest_pinfo) { - int err; - snd_seq_t *seq = dev->seq_handle; - snd_seq_client_info_t *cinfo; - snd_seq_port_info_t *pinfo; + int err; + snd_seq_t *seq = dev->seq_handle; + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; - // subscribe to future new clients/ports showing up - if ((err = snd_seq_connect_from(seq, snd_seq_port_info_get_port(dest_pinfo), - SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE)) < 0) { - FLUID_LOG(FLUID_ERR, "snd_seq_connect_from() failed: %s", snd_strerror(err)); - } - - snd_seq_client_info_alloca(&cinfo); - snd_seq_port_info_alloca(&pinfo); - - dev->autoconn_dest = *snd_seq_port_info_get_addr(dest_pinfo); - - snd_seq_client_info_set_client(cinfo, -1); - while (snd_seq_query_next_client(seq, cinfo) >= 0) { - snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); - snd_seq_port_info_set_port(pinfo, -1); - while (snd_seq_query_next_port(seq, pinfo) >= 0) { - fluid_alsa_seq_autoconnect_port_info(dev, pinfo); + // subscribe to future new clients/ports showing up + if((err = snd_seq_connect_from(seq, snd_seq_port_info_get_port(dest_pinfo), + SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE)) < 0) + { + FLUID_LOG(FLUID_ERR, "snd_seq_connect_from() failed: %s", snd_strerror(err)); + } + + snd_seq_client_info_alloca(&cinfo); + snd_seq_port_info_alloca(&pinfo); + + dev->autoconn_dest = *snd_seq_port_info_get_addr(dest_pinfo); + + snd_seq_client_info_set_client(cinfo, -1); + + while(snd_seq_query_next_client(seq, cinfo) >= 0) + { + snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); + snd_seq_port_info_set_port(pinfo, -1); + + while(snd_seq_query_next_port(seq, pinfo) >= 0) + { + fluid_alsa_seq_autoconnect_port_info(dev, pinfo); + } } - } } /* * new_fluid_alsa_seq_driver */ -fluid_midi_driver_t* -new_fluid_alsa_seq_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, void* data) +fluid_midi_driver_t * +new_fluid_alsa_seq_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data) { - int i, err; - fluid_alsa_seq_driver_t* dev; - int realtime_prio = 0; - int count; - struct pollfd *pfd = NULL; - char *device = NULL; - char *id = NULL; - char *portname = NULL; - char full_id[64]; - char full_name[64]; - snd_seq_port_info_t *port_info = NULL; - int midi_channels; + int i, err; + fluid_alsa_seq_driver_t *dev; + int realtime_prio = 0; + int count; + struct pollfd *pfd = NULL; + char *device = NULL; + char *id = NULL; + char *portname = NULL; + char full_id[64]; + char full_name[64]; + snd_seq_port_info_t *port_info = NULL; + int midi_channels; - /* not much use doing anything */ - if (handler == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid argument"); - return NULL; - } - - /* allocate the device */ - dev = FLUID_NEW(fluid_alsa_seq_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_alsa_seq_driver_t)); - dev->driver.data = data; - dev->driver.handler = handler; - - fluid_settings_getint (settings, "midi.realtime-prio", &realtime_prio); - - /* get the device name. if none is specified, use the default device. */ - if (fluid_settings_dupstr(settings, "midi.alsa_seq.device", &device) != FLUID_OK) /* ++ alloc device name */ - goto error_recovery; - - if (fluid_settings_dupstr(settings, "midi.alsa_seq.id", &id) != FLUID_OK) /* ++ alloc id string */ - goto error_recovery; - - if (id == NULL) { - id = FLUID_MALLOC (32); - if (!id) + /* not much use doing anything */ + if(handler == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; + FLUID_LOG(FLUID_ERR, "Invalid argument"); + return NULL; } - sprintf(id, "%d", getpid()); - } + /* allocate the device */ + dev = FLUID_NEW(fluid_alsa_seq_driver_t); - /* get the midi portname */ - fluid_settings_dupstr(settings, "midi.portname", &portname); - if (portname && FLUID_STRLEN (portname) == 0) - { - FLUID_FREE (portname); /* -- free port name */ - portname = NULL; - } - - /* open the sequencer INPUT only */ - err = snd_seq_open(&dev->seq_handle, device ? device : "default", SND_SEQ_OPEN_INPUT, 0); - if (err < 0) { - FLUID_LOG(FLUID_ERR, "Error opening ALSA sequencer"); - goto error_recovery; - } - - snd_seq_nonblock (dev->seq_handle, 1); - - /* get # of MIDI file descriptors */ - count = snd_seq_poll_descriptors_count(dev->seq_handle, POLLIN); - if (count > 0) { /* make sure there are some */ - pfd = FLUID_MALLOC(sizeof (struct pollfd) * count); - dev->pfd = FLUID_MALLOC(sizeof (struct pollfd) * count); - /* grab file descriptor POLL info structures */ - count = snd_seq_poll_descriptors(dev->seq_handle, pfd, count, POLLIN); - } - - /* copy the input FDs */ - for (i = 0; i < count; i++) { /* loop over file descriptors */ - if (pfd[i].events & POLLIN) { /* use only the input FDs */ - dev->pfd[dev->npfd].fd = pfd[i].fd; - dev->pfd[dev->npfd].events = POLLIN; - dev->pfd[dev->npfd].revents = 0; - dev->npfd++; + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - } - FLUID_FREE(pfd); - /* set the client name */ - if (!portname) { - snd_seq_set_client_name(dev->seq_handle, fluid_alsa_seq_full_id(id, full_id, 64)); - } - else { - snd_seq_set_client_name(dev->seq_handle, portname); - } + FLUID_MEMSET(dev, 0, sizeof(fluid_alsa_seq_driver_t)); + dev->driver.data = data; + dev->driver.handler = handler; + fluid_settings_getint(settings, "midi.realtime-prio", &realtime_prio); - /* create the ports */ - snd_seq_port_info_alloca(&port_info); - FLUID_MEMSET(port_info, 0, snd_seq_port_info_sizeof()); - - fluid_settings_getint(settings, "synth.midi-channels", &midi_channels); - dev->port_count = midi_channels / 16; - - snd_seq_port_info_set_capability(port_info, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE); - snd_seq_port_info_set_type(port_info, - SND_SEQ_PORT_TYPE_MIDI_GM | - SND_SEQ_PORT_TYPE_SYNTHESIZER | - SND_SEQ_PORT_TYPE_APPLICATION | - SND_SEQ_PORT_TYPE_MIDI_GENERIC); - snd_seq_port_info_set_midi_channels(port_info, 16); - snd_seq_port_info_set_port_specified(port_info, 1); - - for (i = 0; i < dev->port_count; i++) { - - if (!portname) { - snd_seq_port_info_set_name(port_info, fluid_alsa_seq_full_name(id, i, full_name, 64)); + /* get the device name. if none is specified, use the default device. */ + if(fluid_settings_dupstr(settings, "midi.alsa_seq.device", &device) != FLUID_OK) /* ++ alloc device name */ + { + goto error_recovery; } - else { - snd_seq_port_info_set_name(port_info, portname); + + if(fluid_settings_dupstr(settings, "midi.alsa_seq.id", &id) != FLUID_OK) /* ++ alloc id string */ + { + goto error_recovery; } - snd_seq_port_info_set_port(port_info, i); - err = snd_seq_create_port(dev->seq_handle, port_info); - if (err < 0) { - FLUID_LOG(FLUID_ERR, "Error creating ALSA sequencer port"); - goto error_recovery; + if(id == NULL) + { + id = FLUID_MALLOC(32); + + if(!id) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + sprintf(id, "%d", getpid()); } - } - fluid_settings_getint(settings, "midi.autoconnect", &dev->autoconn_inputs); - if (dev->autoconn_inputs) - fluid_alsa_seq_autoconnect(dev, port_info); + /* get the midi portname */ + fluid_settings_dupstr(settings, "midi.portname", &portname); - /* tell the lash server our client id */ + if(portname && FLUID_STRLEN(portname) == 0) + { + FLUID_FREE(portname); /* -- free port name */ + portname = NULL; + } + + /* open the sequencer INPUT only */ + err = snd_seq_open(&dev->seq_handle, device ? device : "default", SND_SEQ_OPEN_INPUT, 0); + + if(err < 0) + { + FLUID_LOG(FLUID_ERR, "Error opening ALSA sequencer"); + goto error_recovery; + } + + snd_seq_nonblock(dev->seq_handle, 1); + + /* get # of MIDI file descriptors */ + count = snd_seq_poll_descriptors_count(dev->seq_handle, POLLIN); + + if(count > 0) /* make sure there are some */ + { + pfd = FLUID_MALLOC(sizeof(struct pollfd) * count); + dev->pfd = FLUID_MALLOC(sizeof(struct pollfd) * count); + /* grab file descriptor POLL info structures */ + count = snd_seq_poll_descriptors(dev->seq_handle, pfd, count, POLLIN); + } + + /* copy the input FDs */ + for(i = 0; i < count; i++) /* loop over file descriptors */ + { + if(pfd[i].events & POLLIN) /* use only the input FDs */ + { + dev->pfd[dev->npfd].fd = pfd[i].fd; + dev->pfd[dev->npfd].events = POLLIN; + dev->pfd[dev->npfd].revents = 0; + dev->npfd++; + } + } + + FLUID_FREE(pfd); + + /* set the client name */ + if(!portname) + { + snd_seq_set_client_name(dev->seq_handle, fluid_alsa_seq_full_id(id, full_id, 64)); + } + else + { + snd_seq_set_client_name(dev->seq_handle, portname); + } + + + /* create the ports */ + snd_seq_port_info_alloca(&port_info); + FLUID_MEMSET(port_info, 0, snd_seq_port_info_sizeof()); + + fluid_settings_getint(settings, "synth.midi-channels", &midi_channels); + dev->port_count = midi_channels / 16; + + snd_seq_port_info_set_capability(port_info, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE); + snd_seq_port_info_set_type(port_info, + SND_SEQ_PORT_TYPE_MIDI_GM | + SND_SEQ_PORT_TYPE_SYNTHESIZER | + SND_SEQ_PORT_TYPE_APPLICATION | + SND_SEQ_PORT_TYPE_MIDI_GENERIC); + snd_seq_port_info_set_midi_channels(port_info, 16); + snd_seq_port_info_set_port_specified(port_info, 1); + + for(i = 0; i < dev->port_count; i++) + { + + if(!portname) + { + snd_seq_port_info_set_name(port_info, fluid_alsa_seq_full_name(id, i, full_name, 64)); + } + else + { + snd_seq_port_info_set_name(port_info, portname); + } + + snd_seq_port_info_set_port(port_info, i); + + err = snd_seq_create_port(dev->seq_handle, port_info); + + if(err < 0) + { + FLUID_LOG(FLUID_ERR, "Error creating ALSA sequencer port"); + goto error_recovery; + } + } + + fluid_settings_getint(settings, "midi.autoconnect", &dev->autoconn_inputs); + + if(dev->autoconn_inputs) + { + fluid_alsa_seq_autoconnect(dev, port_info); + } + + /* tell the lash server our client id */ #ifdef LASH_ENABLED - { - int enable_lash = 0; - fluid_settings_getint (settings, "lash.enable", &enable_lash); - if (enable_lash) - fluid_lash_alsa_client_id (fluid_lash_client, snd_seq_client_id (dev->seq_handle)); - } + { + int enable_lash = 0; + fluid_settings_getint(settings, "lash.enable", &enable_lash); + + if(enable_lash) + { + fluid_lash_alsa_client_id(fluid_lash_client, snd_seq_client_id(dev->seq_handle)); + } + } #endif /* LASH_ENABLED */ - fluid_atomic_int_set(&dev->should_quit, 0); + fluid_atomic_int_set(&dev->should_quit, 0); - /* create the MIDI thread */ - dev->thread = new_fluid_thread ("alsa-midi-seq", fluid_alsa_seq_run, dev, realtime_prio, FALSE); + /* create the MIDI thread */ + dev->thread = new_fluid_thread("alsa-midi-seq", fluid_alsa_seq_run, dev, realtime_prio, FALSE); - if (portname) FLUID_FREE (portname); - if (id) FLUID_FREE (id); - if (device) FLUID_FREE (device); + if(portname) + { + FLUID_FREE(portname); + } - return (fluid_midi_driver_t*) dev; + if(id) + { + FLUID_FREE(id); + } - error_recovery: + if(device) + { + FLUID_FREE(device); + } - if (portname) FLUID_FREE (portname); - if (id) FLUID_FREE (id); - if (device) FLUID_FREE (device); + return (fluid_midi_driver_t *) dev; - delete_fluid_alsa_seq_driver((fluid_midi_driver_t*) dev); +error_recovery: - return NULL; + if(portname) + { + FLUID_FREE(portname); + } + + if(id) + { + FLUID_FREE(id); + } + + if(device) + { + FLUID_FREE(device); + } + + delete_fluid_alsa_seq_driver((fluid_midi_driver_t *) dev); + + return NULL; } /* * delete_fluid_alsa_seq_driver */ void -delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p) +delete_fluid_alsa_seq_driver(fluid_midi_driver_t *p) { - fluid_alsa_seq_driver_t* dev = (fluid_alsa_seq_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_alsa_seq_driver_t *dev = (fluid_alsa_seq_driver_t *) p; + fluid_return_if_fail(dev != NULL); - /* cancel the thread and wait for it before cleaning up */ - fluid_atomic_int_set(&dev->should_quit, 1); + /* cancel the thread and wait for it before cleaning up */ + fluid_atomic_int_set(&dev->should_quit, 1); - if (dev->thread) - fluid_thread_join (dev->thread); + if(dev->thread) + { + fluid_thread_join(dev->thread); + } - if (dev->seq_handle) { - snd_seq_close(dev->seq_handle); - } + if(dev->seq_handle) + { + snd_seq_close(dev->seq_handle); + } - if (dev->pfd) FLUID_FREE (dev->pfd); + if(dev->pfd) + { + FLUID_FREE(dev->pfd); + } - FLUID_FREE(dev); + FLUID_FREE(dev); } /* * fluid_alsa_seq_run */ fluid_thread_return_t -fluid_alsa_seq_run(void* d) +fluid_alsa_seq_run(void *d) { - int n, ev; - snd_seq_event_t *seq_ev; - fluid_midi_event_t evt; - fluid_alsa_seq_driver_t* dev = (fluid_alsa_seq_driver_t*) d; + int n, ev; + snd_seq_event_t *seq_ev; + fluid_midi_event_t evt; + fluid_alsa_seq_driver_t *dev = (fluid_alsa_seq_driver_t *) d; - /* go into a loop until someone tells us to stop */ - while (!fluid_atomic_int_get(&dev->should_quit)) { + /* go into a loop until someone tells us to stop */ + while(!fluid_atomic_int_get(&dev->should_quit)) + { - /* is there something to read? */ - n = poll(dev->pfd, dev->npfd, 100); /* use a 100 milliseconds timeout */ - if (n < 0) { - perror("poll"); - } else if (n > 0) { /* check for pending events */ - do - { - ev = snd_seq_event_input(dev->seq_handle, &seq_ev); /* read the events */ + /* is there something to read? */ + n = poll(dev->pfd, dev->npfd, 100); /* use a 100 milliseconds timeout */ - if (ev == -EAGAIN) break; + if(n < 0) + { + perror("poll"); + } + else if(n > 0) /* check for pending events */ + { + do + { + ev = snd_seq_event_input(dev->seq_handle, &seq_ev); /* read the events */ - /* Negative value indicates an error, ignore interrupted system call - * (-EPERM) and input event buffer overrun (-ENOSPC) */ - if (ev < 0) - { /* FIXME - report buffer overrun? */ - if (ev != -EPERM && ev != -ENOSPC) - { - FLUID_LOG(FLUID_ERR, "Error while reading ALSA sequencer (code=%d)", ev); - fluid_atomic_int_set(&dev->should_quit, 1); - } - break; - } + if(ev == -EAGAIN) + { + break; + } - switch (seq_ev->type) - { - case SND_SEQ_EVENT_NOTEON: - evt.type = NOTE_ON; - evt.channel = seq_ev->dest.port * 16 + seq_ev->data.note.channel; - evt.param1 = seq_ev->data.note.note; - evt.param2 = seq_ev->data.note.velocity; - break; - case SND_SEQ_EVENT_NOTEOFF: - evt.type = NOTE_OFF; - evt.channel = seq_ev->dest.port * 16 + seq_ev->data.note.channel; - evt.param1 = seq_ev->data.note.note; - evt.param2 = seq_ev->data.note.velocity; - break; - case SND_SEQ_EVENT_KEYPRESS: - evt.type = KEY_PRESSURE; - evt.channel = seq_ev->dest.port * 16 + seq_ev->data.note.channel; - evt.param1 = seq_ev->data.note.note; - evt.param2 = seq_ev->data.note.velocity; - break; - case SND_SEQ_EVENT_CONTROLLER: - evt.type = CONTROL_CHANGE; - evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; - evt.param1 = seq_ev->data.control.param; - evt.param2 = seq_ev->data.control.value; - break; - case SND_SEQ_EVENT_PITCHBEND: - evt.type = PITCH_BEND; - evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; + /* Negative value indicates an error, ignore interrupted system call + * (-EPERM) and input event buffer overrun (-ENOSPC) */ + if(ev < 0) + { + /* FIXME - report buffer overrun? */ + if(ev != -EPERM && ev != -ENOSPC) + { + FLUID_LOG(FLUID_ERR, "Error while reading ALSA sequencer (code=%d)", ev); + fluid_atomic_int_set(&dev->should_quit, 1); + } - /* ALSA pitch bend is -8192 - 8191, we adjust it here */ - evt.param1 = seq_ev->data.control.value + 8192; - break; - case SND_SEQ_EVENT_PGMCHANGE: - evt.type = PROGRAM_CHANGE; - evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; - evt.param1 = seq_ev->data.control.value; - break; - case SND_SEQ_EVENT_CHANPRESS: - evt.type = CHANNEL_PRESSURE; - evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; - evt.param1 = seq_ev->data.control.value; - break; - case SND_SEQ_EVENT_SYSEX: - if (seq_ev->data.ext.len < 2) continue; + break; + } - fluid_midi_event_set_sysex (&evt, (char *)(seq_ev->data.ext.ptr) + 1, - seq_ev->data.ext.len - 2, FALSE); - break; - case SND_SEQ_EVENT_PORT_START: { - if (dev->autoconn_inputs) { - fluid_alsa_seq_autoconnect_port(dev, seq_ev->data.addr.client, seq_ev->data.addr.port); - } - } - break; - default: - continue; /* unhandled event, next loop iteration */ - } + switch(seq_ev->type) + { + case SND_SEQ_EVENT_NOTEON: + evt.type = NOTE_ON; + evt.channel = seq_ev->dest.port * 16 + seq_ev->data.note.channel; + evt.param1 = seq_ev->data.note.note; + evt.param2 = seq_ev->data.note.velocity; + break; - /* send the events to the next link in the chain */ - (*dev->driver.handler)(dev->driver.data, &evt); - } - while (ev > 0); - } /* if poll() > 0 */ - } /* while (!dev->should_quit) */ + case SND_SEQ_EVENT_NOTEOFF: + evt.type = NOTE_OFF; + evt.channel = seq_ev->dest.port * 16 + seq_ev->data.note.channel; + evt.param1 = seq_ev->data.note.note; + evt.param2 = seq_ev->data.note.velocity; + break; - return FLUID_THREAD_RETURN_VALUE; + case SND_SEQ_EVENT_KEYPRESS: + evt.type = KEY_PRESSURE; + evt.channel = seq_ev->dest.port * 16 + seq_ev->data.note.channel; + evt.param1 = seq_ev->data.note.note; + evt.param2 = seq_ev->data.note.velocity; + break; + + case SND_SEQ_EVENT_CONTROLLER: + evt.type = CONTROL_CHANGE; + evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; + evt.param1 = seq_ev->data.control.param; + evt.param2 = seq_ev->data.control.value; + break; + + case SND_SEQ_EVENT_PITCHBEND: + evt.type = PITCH_BEND; + evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; + + /* ALSA pitch bend is -8192 - 8191, we adjust it here */ + evt.param1 = seq_ev->data.control.value + 8192; + break; + + case SND_SEQ_EVENT_PGMCHANGE: + evt.type = PROGRAM_CHANGE; + evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; + evt.param1 = seq_ev->data.control.value; + break; + + case SND_SEQ_EVENT_CHANPRESS: + evt.type = CHANNEL_PRESSURE; + evt.channel = seq_ev->dest.port * 16 + seq_ev->data.control.channel; + evt.param1 = seq_ev->data.control.value; + break; + + case SND_SEQ_EVENT_SYSEX: + if(seq_ev->data.ext.len < 2) + { + continue; + } + + fluid_midi_event_set_sysex(&evt, (char *)(seq_ev->data.ext.ptr) + 1, + seq_ev->data.ext.len - 2, FALSE); + break; + + case SND_SEQ_EVENT_PORT_START: + { + if(dev->autoconn_inputs) + { + fluid_alsa_seq_autoconnect_port(dev, seq_ev->data.addr.client, seq_ev->data.addr.port); + } + } + break; + + default: + continue; /* unhandled event, next loop iteration */ + } + + /* send the events to the next link in the chain */ + (*dev->driver.handler)(dev->driver.data, &evt); + } + while(ev > 0); + } /* if poll() > 0 */ + } /* while (!dev->should_quit) */ + + return FLUID_THREAD_RETURN_VALUE; } #endif /* #if ALSA_SUPPORT */ diff --git a/src/drivers/fluid_aufile.c b/src/drivers/fluid_aufile.c index 84cd03ed..3751de4b 100644 --- a/src/drivers/fluid_aufile.c +++ b/src/drivers/fluid_aufile.c @@ -34,92 +34,102 @@ * This structure should not be accessed directly. Use audio port * functions instead. */ -typedef struct { - fluid_audio_driver_t driver; - fluid_audio_func_t callback; - void* data; - fluid_file_renderer_t* renderer; - int period_size; - double sample_rate; - fluid_timer_t* timer; - unsigned int samples; +typedef struct +{ + fluid_audio_driver_t driver; + fluid_audio_func_t callback; + void *data; + fluid_file_renderer_t *renderer; + int period_size; + double sample_rate; + fluid_timer_t *timer; + unsigned int samples; } fluid_file_audio_driver_t; -fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); +fluid_audio_driver_t *new_fluid_file_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); -void delete_fluid_file_audio_driver(fluid_audio_driver_t* p); -static int fluid_file_audio_run_s16(void* d, unsigned int msec); +void delete_fluid_file_audio_driver(fluid_audio_driver_t *p); +static int fluid_file_audio_run_s16(void *d, unsigned int msec); /************************************************************** * * 'file' audio driver - * + * */ -fluid_audio_driver_t* -new_fluid_file_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_file_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth) { - fluid_file_audio_driver_t* dev; - int msec; + fluid_file_audio_driver_t *dev; + int msec; - dev = FLUID_NEW(fluid_file_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t)); + dev = FLUID_NEW(fluid_file_audio_driver_t); - fluid_settings_getint(settings, "audio.period-size", &dev->period_size); - fluid_settings_getnum(settings, "synth.sample-rate", &dev->sample_rate); + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - dev->data = synth; - dev->callback = (fluid_audio_func_t) fluid_synth_process; - dev->samples = 0; + FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t)); - dev->renderer = new_fluid_file_renderer(synth); + fluid_settings_getint(settings, "audio.period-size", &dev->period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &dev->sample_rate); - if (dev->renderer == NULL) - goto error_recovery; + dev->data = synth; + dev->callback = (fluid_audio_func_t) fluid_synth_process; + dev->samples = 0; - msec = (int) (0.5 + dev->period_size / dev->sample_rate * 1000.0); - dev->timer = new_fluid_timer(msec, fluid_file_audio_run_s16, (void*) dev, TRUE, FALSE, TRUE); - if (dev->timer == NULL) { - FLUID_LOG(FLUID_PANIC, "Couldn't create the audio thread."); - goto error_recovery; - } + dev->renderer = new_fluid_file_renderer(synth); - return (fluid_audio_driver_t*) dev; + if(dev->renderer == NULL) + { + goto error_recovery; + } - error_recovery: - delete_fluid_file_audio_driver((fluid_audio_driver_t*) dev); - return NULL; + msec = (int)(0.5 + dev->period_size / dev->sample_rate * 1000.0); + dev->timer = new_fluid_timer(msec, fluid_file_audio_run_s16, (void *) dev, TRUE, FALSE, TRUE); + + if(dev->timer == NULL) + { + FLUID_LOG(FLUID_PANIC, "Couldn't create the audio thread."); + goto error_recovery; + } + + return (fluid_audio_driver_t *) dev; + +error_recovery: + delete_fluid_file_audio_driver((fluid_audio_driver_t *) dev); + return NULL; } -void delete_fluid_file_audio_driver(fluid_audio_driver_t* p) +void delete_fluid_file_audio_driver(fluid_audio_driver_t *p) { - fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_file_audio_driver_t *dev = (fluid_file_audio_driver_t *) p; + fluid_return_if_fail(dev != NULL); - delete_fluid_timer(dev->timer); - delete_fluid_file_renderer(dev->renderer); - - FLUID_FREE(dev); + delete_fluid_timer(dev->timer); + delete_fluid_file_renderer(dev->renderer); + + FLUID_FREE(dev); } -static int fluid_file_audio_run_s16(void* d, unsigned int clock_time) +static int fluid_file_audio_run_s16(void *d, unsigned int clock_time) { - fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) d; - unsigned int sample_time; + fluid_file_audio_driver_t *dev = (fluid_file_audio_driver_t *) d; + unsigned int sample_time; - sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0); - if (sample_time > clock_time) { - return 1; - } + sample_time = (unsigned int)(dev->samples / dev->sample_rate * 1000.0); - dev->samples += dev->period_size; + if(sample_time > clock_time) + { + return 1; + } - return fluid_file_renderer_process_block(dev->renderer) == FLUID_OK ? 1 : 0; + dev->samples += dev->period_size; + + return fluid_file_renderer_process_block(dev->renderer) == FLUID_OK ? 1 : 0; } diff --git a/src/drivers/fluid_coreaudio.c b/src/drivers/fluid_coreaudio.c index 18257b91..341c08db 100644 --- a/src/drivers/fluid_coreaudio.c +++ b/src/drivers/fluid_coreaudio.c @@ -40,31 +40,32 @@ * fluid_core_audio_driver_t * */ -typedef struct { - fluid_audio_driver_t driver; - AudioUnit outputUnit; - AudioStreamBasicDescription format; - fluid_audio_func_t callback; - void* data; - unsigned int buffer_size; - float* buffers[2]; - double phase; +typedef struct +{ + fluid_audio_driver_t driver; + AudioUnit outputUnit; + AudioStreamBasicDescription format; + fluid_audio_func_t callback; + void *data; + unsigned int buffer_size; + float *buffers[2]; + double phase; } fluid_core_audio_driver_t; -fluid_audio_driver_t* new_fluid_core_audio_driver (fluid_settings_t* settings, fluid_synth_t* synth); +fluid_audio_driver_t *new_fluid_core_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth); -fluid_audio_driver_t* new_fluid_core_audio_driver2 (fluid_settings_t* settings, - fluid_audio_func_t func, - void* data); +fluid_audio_driver_t *new_fluid_core_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, + void *data); -OSStatus fluid_core_audio_callback (void *data, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData); +OSStatus fluid_core_audio_callback(void *data, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData); -void delete_fluid_core_audio_driver (fluid_audio_driver_t* p); +void delete_fluid_core_audio_driver(fluid_audio_driver_t *p); /************************************************************** @@ -76,289 +77,340 @@ void delete_fluid_core_audio_driver (fluid_audio_driver_t* p); #define OK(x) (x == noErr) int -get_num_outputs (AudioDeviceID deviceID) +get_num_outputs(AudioDeviceID deviceID) { - int i, total = 0; - UInt32 size; - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyStreamConfiguration; - pa.mScope = kAudioDevicePropertyScopeOutput; - pa.mElement = kAudioObjectPropertyElementMaster; + int i, total = 0; + UInt32 size; + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyStreamConfiguration; + pa.mScope = kAudioDevicePropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; - if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) { - int num = size / (int) sizeof (AudioBufferList); - AudioBufferList bufList[num]; - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) { - int numStreams = bufList->mNumberBuffers; - for (i = 0; i < numStreams; ++i) { - AudioBuffer b = bufList->mBuffers[i]; - total += b.mNumberChannels; - } + if(OK(AudioObjectGetPropertyDataSize(deviceID, &pa, 0, 0, &size))) + { + int num = size / (int) sizeof(AudioBufferList); + AudioBufferList bufList[num]; + + if(OK(AudioObjectGetPropertyData(deviceID, &pa, 0, 0, &size, bufList))) + { + int numStreams = bufList->mNumberBuffers; + + for(i = 0; i < numStreams; ++i) + { + AudioBuffer b = bufList->mBuffers[i]; + total += b.mNumberChannels; + } + } } - } - return total; + + return total; } void -fluid_core_audio_driver_settings(fluid_settings_t* settings) +fluid_core_audio_driver_settings(fluid_settings_t *settings) { - int i; - UInt32 size; - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioHardwarePropertyDevices; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; + int i; + UInt32 size; + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioHardwarePropertyDevices; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; - fluid_settings_register_str (settings, "audio.coreaudio.device", "default", 0); - fluid_settings_add_option (settings, "audio.coreaudio.device", "default"); - if (OK (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size))) { - int num = size / (int) sizeof (AudioDeviceID); - AudioDeviceID devs [num]; - if (OK (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, devs))) { - for (i = 0; i < num; ++i) { - char name [1024]; - size = sizeof (name); - pa.mSelector = kAudioDevicePropertyDeviceName; - if (OK (AudioObjectGetPropertyData (devs[i], &pa, 0, 0, &size, name))) { - if ( get_num_outputs (devs[i]) > 0) { - fluid_settings_add_option (settings, "audio.coreaudio.device", name); - } + fluid_settings_register_str(settings, "audio.coreaudio.device", "default", 0); + fluid_settings_add_option(settings, "audio.coreaudio.device", "default"); + + if(OK(AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa, 0, 0, &size))) + { + int num = size / (int) sizeof(AudioDeviceID); + AudioDeviceID devs [num]; + + if(OK(AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0, 0, &size, devs))) + { + for(i = 0; i < num; ++i) + { + char name [1024]; + size = sizeof(name); + pa.mSelector = kAudioDevicePropertyDeviceName; + + if(OK(AudioObjectGetPropertyData(devs[i], &pa, 0, 0, &size, name))) + { + if(get_num_outputs(devs[i]) > 0) + { + fluid_settings_add_option(settings, "audio.coreaudio.device", name); + } + } + } } - } } - } } /* * new_fluid_core_audio_driver */ -fluid_audio_driver_t* -new_fluid_core_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_core_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) { - return new_fluid_core_audio_driver2 ( settings, + return new_fluid_core_audio_driver2(settings, (fluid_audio_func_t) fluid_synth_process, - (void*) synth ); + (void *) synth); } /* * new_fluid_core_audio_driver2 */ -fluid_audio_driver_t* -new_fluid_core_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data) +fluid_audio_driver_t * +new_fluid_core_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data) { - char* devname = NULL; - fluid_core_audio_driver_t* dev = NULL; - int period_size, periods; - double sample_rate; - OSStatus status; - UInt32 size; - int i; + char *devname = NULL; + fluid_core_audio_driver_t *dev = NULL; + int period_size, periods; + double sample_rate; + OSStatus status; + UInt32 size; + int i; - dev = FLUID_NEW(fluid_core_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_core_audio_driver_t)); + dev = FLUID_NEW(fluid_core_audio_driver_t); - dev->callback = func; - dev->data = data; - - // Open the default output unit - ComponentDescription desc; - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_HALOutput; //kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - Component comp = FindNextComponent(NULL, &desc); - if (comp == NULL) { - FLUID_LOG(FLUID_ERR, "Failed to get the default audio device"); - goto error_recovery; - } - - status = OpenAComponent(comp, &dev->outputUnit); - if (status != noErr) { - FLUID_LOG(FLUID_ERR, "Failed to open the default audio device. Status=%ld\n", (long int)status); - goto error_recovery; - } - - // Set up a callback function to generate output - AURenderCallbackStruct render; - render.inputProc = fluid_core_audio_callback; - render.inputProcRefCon = (void *) dev; - status = AudioUnitSetProperty (dev->outputUnit, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, - 0, - &render, - sizeof(render)); - if (status != noErr) { - FLUID_LOG (FLUID_ERR, "Error setting the audio callback. Status=%ld\n", (long int)status); - goto error_recovery; - } - - fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); - fluid_settings_getint(settings, "audio.periods", &periods); - fluid_settings_getint(settings, "audio.period-size", &period_size); - - /* get the selected device name. if none is specified, use NULL for the default device. */ - if (fluid_settings_dupstr(settings, "audio.coreaudio.device", &devname) == FLUID_OK /* alloc device name */ - && devname && strlen (devname) > 0) { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioHardwarePropertyDevices; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; - if (OK (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size))) { - int num = size / (int) sizeof (AudioDeviceID); - AudioDeviceID devs [num]; - if (OK (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, devs))) { - for (i = 0; i < num; ++i) { - char name [1024]; - size = sizeof (name); - pa.mSelector = kAudioDevicePropertyDeviceName; - if (OK (AudioObjectGetPropertyData (devs[i], &pa, 0, 0, &size, name))) { - if (get_num_outputs (devs[i]) > 0 && FLUID_STRCASECMP(devname, name) == 0) { - AudioDeviceID selectedID = devs[i]; - status = AudioUnitSetProperty (dev->outputUnit, - kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, - 0, - &selectedID, - sizeof(AudioDeviceID)); - if (status != noErr) { - FLUID_LOG (FLUID_ERR, "Error setting the selected output device. Status=%ld\n", (long int)status); - goto error_recovery; - } - } - } - } - } + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - } - if (devname) - FLUID_FREE (devname); /* free device name */ + FLUID_MEMSET(dev, 0, sizeof(fluid_core_audio_driver_t)); - dev->buffer_size = period_size * periods; + dev->callback = func; + dev->data = data; - // The DefaultOutputUnit should do any format conversions - // necessary from our format to the device's format. - dev->format.mSampleRate = sample_rate; // sample rate of the audio stream - dev->format.mFormatID = kAudioFormatLinearPCM; // encoding type of the audio stream - dev->format.mFormatFlags = kLinearPCMFormatFlagIsFloat; - dev->format.mBytesPerPacket = 2*sizeof(float); - dev->format.mFramesPerPacket = 1; - dev->format.mBytesPerFrame = 2*sizeof(float); - dev->format.mChannelsPerFrame = 2; - dev->format.mBitsPerChannel = 8*sizeof(float); + // Open the default output unit + ComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_HALOutput; //kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; - FLUID_LOG (FLUID_DBG, "mSampleRate %g", dev->format.mSampleRate); - FLUID_LOG (FLUID_DBG, "mFormatFlags %08X", dev->format.mFormatFlags); - FLUID_LOG (FLUID_DBG, "mBytesPerPacket %d", dev->format.mBytesPerPacket); - FLUID_LOG (FLUID_DBG, "mFramesPerPacket %d", dev->format.mFramesPerPacket); - FLUID_LOG (FLUID_DBG, "mChannelsPerFrame %d", dev->format.mChannelsPerFrame); - FLUID_LOG (FLUID_DBG, "mBytesPerFrame %d", dev->format.mBytesPerFrame); - FLUID_LOG (FLUID_DBG, "mBitsPerChannel %d", dev->format.mBitsPerChannel); + Component comp = FindNextComponent(NULL, &desc); - status = AudioUnitSetProperty (dev->outputUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, - &dev->format, - sizeof(AudioStreamBasicDescription)); - if (status != noErr) { - FLUID_LOG (FLUID_ERR, "Error setting the audio format. Status=%ld\n", (long int)status); - goto error_recovery; - } + if(comp == NULL) + { + FLUID_LOG(FLUID_ERR, "Failed to get the default audio device"); + goto error_recovery; + } - status = AudioUnitSetProperty (dev->outputUnit, - kAudioUnitProperty_MaximumFramesPerSlice, - kAudioUnitScope_Input, - 0, - &dev->buffer_size, - sizeof(unsigned int)); - if (status != noErr) { - FLUID_LOG (FLUID_ERR, "Failed to set the MaximumFramesPerSlice. Status=%ld\n", (long int)status); - goto error_recovery; - } - FLUID_LOG (FLUID_DBG, "MaximumFramesPerSlice = %d", dev->buffer_size); + status = OpenAComponent(comp, &dev->outputUnit); - dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size); - dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size); + if(status != noErr) + { + FLUID_LOG(FLUID_ERR, "Failed to open the default audio device. Status=%ld\n", (long int)status); + goto error_recovery; + } - // Initialize the audio unit - status = AudioUnitInitialize(dev->outputUnit); - if (status != noErr) { - FLUID_LOG (FLUID_ERR, "Error calling AudioUnitInitialize(). Status=%ld\n", (long int)status); - goto error_recovery; - } + // Set up a callback function to generate output + AURenderCallbackStruct render; + render.inputProc = fluid_core_audio_callback; + render.inputProcRefCon = (void *) dev; + status = AudioUnitSetProperty(dev->outputUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &render, + sizeof(render)); - // Start the rendering - status = AudioOutputUnitStart (dev->outputUnit); - if (status != noErr) { - FLUID_LOG (FLUID_ERR, "Error calling AudioOutputUnitStart(). Status=%ld\n", (long int)status); - goto error_recovery; - } + if(status != noErr) + { + FLUID_LOG(FLUID_ERR, "Error setting the audio callback. Status=%ld\n", (long int)status); + goto error_recovery; + } - return (fluid_audio_driver_t*) dev; + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_getint(settings, "audio.periods", &periods); + fluid_settings_getint(settings, "audio.period-size", &period_size); + + /* get the selected device name. if none is specified, use NULL for the default device. */ + if(fluid_settings_dupstr(settings, "audio.coreaudio.device", &devname) == FLUID_OK /* alloc device name */ + && devname && strlen(devname) > 0) + { + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioHardwarePropertyDevices; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; + + if(OK(AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &pa, 0, 0, &size))) + { + int num = size / (int) sizeof(AudioDeviceID); + AudioDeviceID devs [num]; + + if(OK(AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0, 0, &size, devs))) + { + for(i = 0; i < num; ++i) + { + char name [1024]; + size = sizeof(name); + pa.mSelector = kAudioDevicePropertyDeviceName; + + if(OK(AudioObjectGetPropertyData(devs[i], &pa, 0, 0, &size, name))) + { + if(get_num_outputs(devs[i]) > 0 && FLUID_STRCASECMP(devname, name) == 0) + { + AudioDeviceID selectedID = devs[i]; + status = AudioUnitSetProperty(dev->outputUnit, + kAudioOutputUnitProperty_CurrentDevice, + kAudioUnitScope_Global, + 0, + &selectedID, + sizeof(AudioDeviceID)); + + if(status != noErr) + { + FLUID_LOG(FLUID_ERR, "Error setting the selected output device. Status=%ld\n", (long int)status); + goto error_recovery; + } + } + } + } + } + } + } + + if(devname) + { + FLUID_FREE(devname); /* free device name */ + } + + dev->buffer_size = period_size * periods; + + // The DefaultOutputUnit should do any format conversions + // necessary from our format to the device's format. + dev->format.mSampleRate = sample_rate; // sample rate of the audio stream + dev->format.mFormatID = kAudioFormatLinearPCM; // encoding type of the audio stream + dev->format.mFormatFlags = kLinearPCMFormatFlagIsFloat; + dev->format.mBytesPerPacket = 2 * sizeof(float); + dev->format.mFramesPerPacket = 1; + dev->format.mBytesPerFrame = 2 * sizeof(float); + dev->format.mChannelsPerFrame = 2; + dev->format.mBitsPerChannel = 8 * sizeof(float); + + FLUID_LOG(FLUID_DBG, "mSampleRate %g", dev->format.mSampleRate); + FLUID_LOG(FLUID_DBG, "mFormatFlags %08X", dev->format.mFormatFlags); + FLUID_LOG(FLUID_DBG, "mBytesPerPacket %d", dev->format.mBytesPerPacket); + FLUID_LOG(FLUID_DBG, "mFramesPerPacket %d", dev->format.mFramesPerPacket); + FLUID_LOG(FLUID_DBG, "mChannelsPerFrame %d", dev->format.mChannelsPerFrame); + FLUID_LOG(FLUID_DBG, "mBytesPerFrame %d", dev->format.mBytesPerFrame); + FLUID_LOG(FLUID_DBG, "mBitsPerChannel %d", dev->format.mBitsPerChannel); + + status = AudioUnitSetProperty(dev->outputUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &dev->format, + sizeof(AudioStreamBasicDescription)); + + if(status != noErr) + { + FLUID_LOG(FLUID_ERR, "Error setting the audio format. Status=%ld\n", (long int)status); + goto error_recovery; + } + + status = AudioUnitSetProperty(dev->outputUnit, + kAudioUnitProperty_MaximumFramesPerSlice, + kAudioUnitScope_Input, + 0, + &dev->buffer_size, + sizeof(unsigned int)); + + if(status != noErr) + { + FLUID_LOG(FLUID_ERR, "Failed to set the MaximumFramesPerSlice. Status=%ld\n", (long int)status); + goto error_recovery; + } + + FLUID_LOG(FLUID_DBG, "MaximumFramesPerSlice = %d", dev->buffer_size); + + dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size); + dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size); + + // Initialize the audio unit + status = AudioUnitInitialize(dev->outputUnit); + + if(status != noErr) + { + FLUID_LOG(FLUID_ERR, "Error calling AudioUnitInitialize(). Status=%ld\n", (long int)status); + goto error_recovery; + } + + // Start the rendering + status = AudioOutputUnitStart(dev->outputUnit); + + if(status != noErr) + { + FLUID_LOG(FLUID_ERR, "Error calling AudioOutputUnitStart(). Status=%ld\n", (long int)status); + goto error_recovery; + } + + return (fluid_audio_driver_t *) dev; error_recovery: - delete_fluid_core_audio_driver((fluid_audio_driver_t*) dev); - return NULL; + delete_fluid_core_audio_driver((fluid_audio_driver_t *) dev); + return NULL; } /* * delete_fluid_core_audio_driver */ void -delete_fluid_core_audio_driver(fluid_audio_driver_t* p) +delete_fluid_core_audio_driver(fluid_audio_driver_t *p) { - fluid_core_audio_driver_t* dev = (fluid_core_audio_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_core_audio_driver_t *dev = (fluid_core_audio_driver_t *) p; + fluid_return_if_fail(dev != NULL); - CloseComponent (dev->outputUnit); + CloseComponent(dev->outputUnit); - if (dev->buffers[0]) { - FLUID_FREE(dev->buffers[0]); - } - if (dev->buffers[1]) { - FLUID_FREE(dev->buffers[1]); - } + if(dev->buffers[0]) + { + FLUID_FREE(dev->buffers[0]); + } - FLUID_FREE(dev); + if(dev->buffers[1]) + { + FLUID_FREE(dev->buffers[1]); + } + + FLUID_FREE(dev); } OSStatus -fluid_core_audio_callback ( void *data, - AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList *ioData) +fluid_core_audio_callback(void *data, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) { - int i, k; - fluid_core_audio_driver_t* dev = (fluid_core_audio_driver_t*) data; - int len = inNumberFrames; - float* buffer = ioData->mBuffers[0].mData; + int i, k; + fluid_core_audio_driver_t *dev = (fluid_core_audio_driver_t *) data; + int len = inNumberFrames; + float *buffer = ioData->mBuffers[0].mData; - if (dev->callback) - { - float* left = dev->buffers[0]; - float* right = dev->buffers[1]; + if(dev->callback) + { + float *left = dev->buffers[0]; + float *right = dev->buffers[1]; - (*dev->callback)(dev->data, len, 0, NULL, 2, dev->buffers); + (*dev->callback)(dev->data, len, 0, NULL, 2, dev->buffers); - for (i = 0, k = 0; i < len; i++) { - buffer[k++] = left[i]; - buffer[k++] = right[i]; + for(i = 0, k = 0; i < len; i++) + { + buffer[k++] = left[i]; + buffer[k++] = right[i]; + } } - } - else fluid_synth_write_float((fluid_synth_t*) dev->data, len, buffer, 0, 2, - buffer, 1, 2); - return noErr; + else + fluid_synth_write_float((fluid_synth_t *) dev->data, len, buffer, 0, 2, + buffer, 1, 2); + + return noErr; } diff --git a/src/drivers/fluid_coremidi.c b/src/drivers/fluid_coremidi.c index 21f18b2d..b4ff9b36 100644 --- a/src/drivers/fluid_coremidi.c +++ b/src/drivers/fluid_coremidi.c @@ -52,146 +52,181 @@ #include #include -typedef struct { - fluid_midi_driver_t driver; - MIDIClientRef client; - MIDIEndpointRef endpoint; - fluid_midi_parser_t* parser; +typedef struct +{ + fluid_midi_driver_t driver; + MIDIClientRef client; + MIDIEndpointRef endpoint; + fluid_midi_parser_t *parser; } fluid_coremidi_driver_t; -fluid_midi_driver_t* new_fluid_coremidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, void* data); -void delete_fluid_coremidi_driver(fluid_midi_driver_t* p); +fluid_midi_driver_t *new_fluid_coremidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data); +void delete_fluid_coremidi_driver(fluid_midi_driver_t *p); void fluid_coremidi_callback(const MIDIPacketList *list, void *p, void *src); -void fluid_coremidi_driver_settings(fluid_settings_t* settings) +void fluid_coremidi_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "midi.coremidi.id", "pid", 0); + fluid_settings_register_str(settings, "midi.coremidi.id", "pid", 0); } /* * new_fluid_coremidi_driver */ -fluid_midi_driver_t* -new_fluid_coremidi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* data) +fluid_midi_driver_t * +new_fluid_coremidi_driver(fluid_settings_t *settings, handle_midi_event_func_t handler, void *data) { - fluid_coremidi_driver_t* dev; - MIDIClientRef client; - MIDIEndpointRef endpoint; - char clientid[32]; - char * portname; - char * id; - CFStringRef str_portname; - CFStringRef str_clientname; + fluid_coremidi_driver_t *dev; + MIDIClientRef client; + MIDIEndpointRef endpoint; + char clientid[32]; + char *portname; + char *id; + CFStringRef str_portname; + CFStringRef str_clientname; - /* not much use doing anything */ - if (handler == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid argument"); - return NULL; - } - - dev = FLUID_MALLOC(sizeof(fluid_coremidi_driver_t)); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - - dev->client = 0; - dev->endpoint = 0; - dev->parser = 0; - dev->driver.handler = handler; - dev->driver.data = data; - - dev->parser = new_fluid_midi_parser(); - if (dev->parser == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } - - fluid_settings_dupstr(settings, "midi.coremidi.id", &id); /* ++ alloc id string */ - memset (clientid, 0, sizeof(clientid)); - if (id != NULL) { - if (FLUID_STRCMP (id, "pid") == 0) { - FLUID_SNPRINTF (clientid, sizeof(clientid), " (%d)", getpid()); - } else { - FLUID_SNPRINTF (clientid, sizeof(clientid), " (%s)", id); + /* not much use doing anything */ + if(handler == NULL) + { + FLUID_LOG(FLUID_ERR, "Invalid argument"); + return NULL; } - FLUID_FREE (id); /* -- free id string */ - } - str_clientname = CFStringCreateWithFormat (NULL, NULL, - CFSTR("FluidSynth%s"), clientid); - fluid_settings_dupstr(settings, "midi.portname", &portname); /* ++ alloc port name */ - if (!portname || strlen(portname) == 0) - str_portname = CFStringCreateWithFormat (NULL, NULL, - CFSTR("FluidSynth virtual port%s"), - clientid); - else - str_portname = CFStringCreateWithCString (NULL, portname, - kCFStringEncodingASCII); + dev = FLUID_MALLOC(sizeof(fluid_coremidi_driver_t)); - if (portname) FLUID_FREE (portname); /* -- free port name */ + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - OSStatus result = MIDIClientCreate( str_clientname, NULL, NULL, &client ); - if ( result != noErr ) { - FLUID_LOG(FLUID_ERR, "Failed to create the MIDI input client"); - goto error_recovery; - } - dev->client = client; + dev->client = 0; + dev->endpoint = 0; + dev->parser = 0; + dev->driver.handler = handler; + dev->driver.data = data; - result = MIDIDestinationCreate( client, str_portname, - fluid_coremidi_callback, - (void *)dev, &endpoint ); - if ( result != noErr ) { - FLUID_LOG(FLUID_ERR, "Failed to create the MIDI input port. MIDI input not available."); - goto error_recovery; - } - dev->endpoint = endpoint; + dev->parser = new_fluid_midi_parser(); - return (fluid_midi_driver_t*) dev; + if(dev->parser == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + fluid_settings_dupstr(settings, "midi.coremidi.id", &id); /* ++ alloc id string */ + memset(clientid, 0, sizeof(clientid)); + + if(id != NULL) + { + if(FLUID_STRCMP(id, "pid") == 0) + { + FLUID_SNPRINTF(clientid, sizeof(clientid), " (%d)", getpid()); + } + else + { + FLUID_SNPRINTF(clientid, sizeof(clientid), " (%s)", id); + } + + FLUID_FREE(id); /* -- free id string */ + } + + str_clientname = CFStringCreateWithFormat(NULL, NULL, + CFSTR("FluidSynth%s"), clientid); + + fluid_settings_dupstr(settings, "midi.portname", &portname); /* ++ alloc port name */ + + if(!portname || strlen(portname) == 0) + str_portname = CFStringCreateWithFormat(NULL, NULL, + CFSTR("FluidSynth virtual port%s"), + clientid); + else + str_portname = CFStringCreateWithCString(NULL, portname, + kCFStringEncodingASCII); + + if(portname) + { + FLUID_FREE(portname); /* -- free port name */ + } + + OSStatus result = MIDIClientCreate(str_clientname, NULL, NULL, &client); + + if(result != noErr) + { + FLUID_LOG(FLUID_ERR, "Failed to create the MIDI input client"); + goto error_recovery; + } + + dev->client = client; + + result = MIDIDestinationCreate(client, str_portname, + fluid_coremidi_callback, + (void *)dev, &endpoint); + + if(result != noErr) + { + FLUID_LOG(FLUID_ERR, "Failed to create the MIDI input port. MIDI input not available."); + goto error_recovery; + } + + dev->endpoint = endpoint; + + return (fluid_midi_driver_t *) dev; error_recovery: - delete_fluid_coremidi_driver((fluid_midi_driver_t*) dev); - return NULL; + delete_fluid_coremidi_driver((fluid_midi_driver_t *) dev); + return NULL; } /* * delete_fluid_coremidi_driver */ void -delete_fluid_coremidi_driver(fluid_midi_driver_t* p) +delete_fluid_coremidi_driver(fluid_midi_driver_t *p) { - fluid_coremidi_driver_t* dev = (fluid_coremidi_driver_t*) p; - fluid_return_if_fail(dev != NULL); - - if (dev->client != NULL) { - MIDIClientDispose(dev->client); - } - if (dev->endpoint != NULL) { - MIDIEndpointDispose(dev->endpoint); - } - if (dev->parser != NULL) { - delete_fluid_midi_parser(dev->parser); - } - FLUID_FREE(dev); + fluid_coremidi_driver_t *dev = (fluid_coremidi_driver_t *) p; + fluid_return_if_fail(dev != NULL); + + if(dev->client != NULL) + { + MIDIClientDispose(dev->client); + } + + if(dev->endpoint != NULL) + { + MIDIEndpointDispose(dev->endpoint); + } + + if(dev->parser != NULL) + { + delete_fluid_midi_parser(dev->parser); + } + + FLUID_FREE(dev); } void fluid_coremidi_callback(const MIDIPacketList *list, void *p, void *src) { - unsigned int i, j; - fluid_midi_event_t* event; - fluid_coremidi_driver_t* dev = (fluid_coremidi_driver_t *)p; - const MIDIPacket *packet = &list->packet[0]; - for ( i = 0; i < list->numPackets; ++i ) { - for ( j = 0; j < packet->length; ++j ) { - event = fluid_midi_parser_parse(dev->parser, packet->data[j]); - if (event != NULL) { - (*dev->driver.handler)(dev->driver.data, event); - } + unsigned int i, j; + fluid_midi_event_t *event; + fluid_coremidi_driver_t *dev = (fluid_coremidi_driver_t *)p; + const MIDIPacket *packet = &list->packet[0]; + + for(i = 0; i < list->numPackets; ++i) + { + for(j = 0; j < packet->length; ++j) + { + event = fluid_midi_parser_parse(dev->parser, packet->data[j]); + + if(event != NULL) + { + (*dev->driver.handler)(dev->driver.data, event); + } + } + + packet = MIDIPacketNext(packet); } - packet = MIDIPacketNext(packet); - } } #endif /* COREMIDI_SUPPORT */ diff --git a/src/drivers/fluid_dart.c b/src/drivers/fluid_dart.c index 21fb08d2..0bf8b742 100644 --- a/src/drivers/fluid_dart.c +++ b/src/drivers/fluid_dart.c @@ -43,9 +43,10 @@ * This structure should not be accessed directly. Use audio port * functions instead. */ -typedef struct { +typedef struct +{ fluid_audio_driver_t driver; - fluid_synth_t* synth; + fluid_synth_t *synth; int frame_size; USHORT usDeviceID; /* Amp Mixer device id */ MCI_MIX_BUFFER MixBuffers[NUM_MIX_BUFS]; /* Device buffers */ @@ -54,15 +55,15 @@ typedef struct { } fluid_dart_audio_driver_t; static HMODULE m_hmodMDM = NULLHANDLE; -static ULONG (APIENTRY *m_pfnmciSendCommand)(USHORT, USHORT, ULONG, PVOID, USHORT) = NULL; +static ULONG(APIENTRY *m_pfnmciSendCommand)(USHORT, USHORT, ULONG, PVOID, USHORT) = NULL; -fluid_audio_driver_t* new_fluid_dart_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); +fluid_audio_driver_t *new_fluid_dart_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); -void delete_fluid_dart_audio_driver(fluid_audio_driver_t* p); -void fluid_dart_audio_driver_settings(fluid_settings_t* settings); +void delete_fluid_dart_audio_driver(fluid_audio_driver_t *p); +void fluid_dart_audio_driver_settings(fluid_settings_t *settings); -static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags ); +static LONG APIENTRY fluid_dart_audio_run(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags); /************************************************************** * @@ -70,16 +71,16 @@ static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuff * */ -void fluid_dart_audio_driver_settings(fluid_settings_t* settings) +void fluid_dart_audio_driver_settings(fluid_settings_t *settings) { fluid_settings_register_str(settings, "audio.dart.device", "default", 0); } -fluid_audio_driver_t* -new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_dart_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) { - fluid_dart_audio_driver_t* dev; + fluid_dart_audio_driver_t *dev; double sample_rate; int periods, period_size; UCHAR szFailedName[ 256 ]; @@ -88,10 +89,13 @@ new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) ULONG rc; dev = FLUID_NEW(fluid_dart_audio_driver_t); - if (dev == NULL) { + + if(dev == NULL) + { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(dev, 0, sizeof(fluid_dart_audio_driver_t)); fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); @@ -99,7 +103,8 @@ new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) fluid_settings_getint(settings, "audio.period-size", &period_size); /* check the format */ - if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) { + if(!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) + { FLUID_LOG(FLUID_ERR, "Unhandled sample format"); goto error_recovery; } @@ -109,18 +114,20 @@ new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) /* Load only once */ - if( m_hmodMDM == NULLHANDLE ) + if(m_hmodMDM == NULLHANDLE) { rc = DosLoadModule(szFailedName, sizeof(szFailedName), "MDM", &m_hmodMDM); - if (rc != 0 ) { + if(rc != 0) + { FLUID_LOG(FLUID_ERR, "Cannot load MDM.DLL for DART due to %s", szFailedName); goto error_recovery; } rc = DosQueryProcAddr(m_hmodMDM, 1, NULL, (PFN *)&m_pfnmciSendCommand); - if (rc != 0 ) { + if(rc != 0) + { FLUID_LOG(FLUID_ERR, "Cannot find mciSendCommand() in MDM.DLL"); DosFreeModule(m_hmodMDM); m_hmodMDM = NULLHANDLE; @@ -138,7 +145,8 @@ new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE, (PVOID)&AmpOpenParms, 0); - if (rc != MCIERR_SUCCESS) { + if(rc != MCIERR_SUCCESS) + { FLUID_LOG(FLUID_ERR, "Cannot open DART, rc = %lu", rc); goto error_recovery; } @@ -163,7 +171,8 @@ new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) MCI_WAIT | MCI_MIXSETUP_INIT, (PVOID)&dev->MixSetupParms, 0); - if (rc != MCIERR_SUCCESS) { + if(rc != MCIERR_SUCCESS) + { FLUID_LOG(FLUID_ERR, "Cannot setup DART, rc = %lu", rc); goto error_recovery; } @@ -179,20 +188,22 @@ new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) MCI_WAIT | MCI_ALLOCATE_MEMORY, (PVOID)&dev->BufferParms, 0); - if ((USHORT)rc != MCIERR_SUCCESS) { + if((USHORT)rc != MCIERR_SUCCESS) + { FLUID_LOG(FLUID_ERR, "Cannot allocate memory for DART, rc = %lu", rc); goto error_recovery; } /* Initialize all device buffers. */ - for (i = 0; i < NUM_MIX_BUFS; i++) { - FLUID_MEMSET(dev->MixBuffers[i].pBuffer, 0, dev->BufferParms.ulBufferSize); - dev->MixBuffers[i].ulBufferLength = dev->BufferParms.ulBufferSize; - dev->MixBuffers[i].ulFlags = 0; - dev->MixBuffers[i].ulUserParm = (ULONG)dev; - fluid_synth_write_s16(dev->synth, dev->MixBuffers[i].ulBufferLength / dev->frame_size, - dev->MixBuffers[i].pBuffer, 0, 2, dev->MixBuffers[i].pBuffer, 1, 2 ); + for(i = 0; i < NUM_MIX_BUFS; i++) + { + FLUID_MEMSET(dev->MixBuffers[i].pBuffer, 0, dev->BufferParms.ulBufferSize); + dev->MixBuffers[i].ulBufferLength = dev->BufferParms.ulBufferSize; + dev->MixBuffers[i].ulFlags = 0; + dev->MixBuffers[i].ulUserParm = (ULONG)dev; + fluid_synth_write_s16(dev->synth, dev->MixBuffers[i].ulBufferLength / dev->frame_size, + dev->MixBuffers[i].pBuffer, 0, 2, dev->MixBuffers[i].pBuffer, 1, 2); } /* Write buffers to kick off the amp mixer. @@ -201,20 +212,21 @@ new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) dev->MixBuffers, NUM_MIX_BUFS); - return (fluid_audio_driver_t*) dev; + return (fluid_audio_driver_t *) dev; error_recovery: - delete_fluid_dart_audio_driver((fluid_audio_driver_t*) dev); + delete_fluid_dart_audio_driver((fluid_audio_driver_t *) dev); return NULL; } -void delete_fluid_dart_audio_driver(fluid_audio_driver_t* p) +void delete_fluid_dart_audio_driver(fluid_audio_driver_t *p) { - fluid_dart_audio_driver_t* dev = (fluid_dart_audio_driver_t*) p; + fluid_dart_audio_driver_t *dev = (fluid_dart_audio_driver_t *) p; fluid_return_if_fail(dev != NULL); - if (dev->usDeviceID != 0) { + if(dev->usDeviceID != 0) + { MCI_GENERIC_PARMS GenericParms; /* Send message to stop the audio device @@ -237,18 +249,19 @@ void delete_fluid_dart_audio_driver(fluid_audio_driver_t* p) FLUID_FREE(dev); } -static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags ) +static LONG APIENTRY fluid_dart_audio_run(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) { - fluid_dart_audio_driver_t* dev=(fluid_dart_audio_driver_t*)pBuffer->ulUserParm; + fluid_dart_audio_driver_t *dev = (fluid_dart_audio_driver_t *)pBuffer->ulUserParm; - switch( ulFlags ) { - case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: /* error occur in device */ - case MIX_WRITE_COMPLETE: /* for playback */ - FLUID_MEMSET(pBuffer->pBuffer, 0, pBuffer->ulBufferLength); - fluid_synth_write_s16(dev->synth, pBuffer->ulBufferLength / dev->frame_size, - pBuffer->pBuffer, 0, 2, pBuffer->pBuffer, 1, 2 ); - dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle, pBuffer, 1); - break; + switch(ulFlags) + { + case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: /* error occur in device */ + case MIX_WRITE_COMPLETE: /* for playback */ + FLUID_MEMSET(pBuffer->pBuffer, 0, pBuffer->ulBufferLength); + fluid_synth_write_s16(dev->synth, pBuffer->ulBufferLength / dev->frame_size, + pBuffer->pBuffer, 0, 2, pBuffer->pBuffer, 1, 2); + dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle, pBuffer, 1); + break; } return TRUE; diff --git a/src/drivers/fluid_dsound.c b/src/drivers/fluid_dsound.c index 16363838..05f33c93 100644 --- a/src/drivers/fluid_dsound.c +++ b/src/drivers/fluid_dsound.c @@ -30,344 +30,431 @@ #include #include -fluid_audio_driver_t* -new_fluid_dsound_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth); +fluid_audio_driver_t * +new_fluid_dsound_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth); -void delete_fluid_dsound_audio_driver(fluid_audio_driver_t* data); +void delete_fluid_dsound_audio_driver(fluid_audio_driver_t *data); DWORD WINAPI fluid_dsound_audio_run(LPVOID lpParameter); -char* fluid_win32_error(HRESULT hr); +char *fluid_win32_error(HRESULT hr); -typedef struct { - fluid_audio_driver_t driver; - LPDIRECTSOUND direct_sound; - LPDIRECTSOUNDBUFFER prim_buffer; - LPDIRECTSOUNDBUFFER sec_buffer; - WAVEFORMATEX* format; - HANDLE thread; - DWORD threadID; - fluid_synth_t* synth; - fluid_audio_callback_t write; - int cont; - DWORD buffer_byte_size; - DWORD queue_byte_size; - DWORD frame_size; +typedef struct +{ + fluid_audio_driver_t driver; + LPDIRECTSOUND direct_sound; + LPDIRECTSOUNDBUFFER prim_buffer; + LPDIRECTSOUNDBUFFER sec_buffer; + WAVEFORMATEX *format; + HANDLE thread; + DWORD threadID; + fluid_synth_t *synth; + fluid_audio_callback_t write; + int cont; + DWORD buffer_byte_size; + DWORD queue_byte_size; + DWORD frame_size; } fluid_dsound_audio_driver_t; -typedef struct { - LPGUID devGUID; - char* devname; +typedef struct +{ + LPGUID devGUID; + char *devname; } fluid_dsound_devsel_t; BOOL CALLBACK fluid_dsound_enum_callback(LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context) { - fluid_settings_t* settings = (fluid_settings_t*) context; - fluid_settings_add_option(settings, "audio.dsound.device", (const char *)description); + fluid_settings_t *settings = (fluid_settings_t *) context; + fluid_settings_add_option(settings, "audio.dsound.device", (const char *)description); - return TRUE; + return TRUE; } BOOL CALLBACK fluid_dsound_enum_callback2(LPGUID guid, LPCTSTR description, LPCTSTR module, LPVOID context) { - fluid_dsound_devsel_t* devsel = (fluid_dsound_devsel_t*) context; - FLUID_LOG(FLUID_DBG, "Testing audio device: %s", description); - if (FLUID_STRCASECMP(devsel->devname, description) == 0) { - devsel->devGUID = FLUID_NEW(GUID); - if(devsel->devGUID) { - memcpy(devsel->devGUID, guid, sizeof(GUID)); - FLUID_LOG(FLUID_DBG, "Selected audio device GUID: %p", devsel->devGUID); + fluid_dsound_devsel_t *devsel = (fluid_dsound_devsel_t *) context; + FLUID_LOG(FLUID_DBG, "Testing audio device: %s", description); + + if(FLUID_STRCASECMP(devsel->devname, description) == 0) + { + devsel->devGUID = FLUID_NEW(GUID); + + if(devsel->devGUID) + { + memcpy(devsel->devGUID, guid, sizeof(GUID)); + FLUID_LOG(FLUID_DBG, "Selected audio device GUID: %p", devsel->devGUID); + } } - } - return TRUE; + + return TRUE; } -void fluid_dsound_audio_driver_settings(fluid_settings_t* settings) +void fluid_dsound_audio_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "audio.dsound.device", "default", 0); - fluid_settings_add_option(settings, "audio.dsound.device", "default"); - DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback, settings); + fluid_settings_register_str(settings, "audio.dsound.device", "default", 0); + fluid_settings_add_option(settings, "audio.dsound.device", "default"); + DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback, settings); } /* * new_fluid_dsound_audio_driver */ -fluid_audio_driver_t* -new_fluid_dsound_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_dsound_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) { - HRESULT hr; - DSBUFFERDESC desc; - fluid_dsound_audio_driver_t* dev = NULL; - DSCAPS caps; - char *buf1; - DWORD bytes1; - double sample_rate; - int periods, period_size; - fluid_dsound_devsel_t devsel; - - /* create and clear the driver data */ - dev = FLUID_NEW(fluid_dsound_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + HRESULT hr; + DSBUFFERDESC desc; + fluid_dsound_audio_driver_t *dev = NULL; + DSCAPS caps; + char *buf1; + DWORD bytes1; + double sample_rate; + int periods, period_size; + fluid_dsound_devsel_t devsel; + + /* create and clear the driver data */ + dev = FLUID_NEW(fluid_dsound_audio_driver_t); + + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_dsound_audio_driver_t)); + dev->synth = synth; + dev->cont = 1; + + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_getint(settings, "audio.periods", &periods); + fluid_settings_getint(settings, "audio.period-size", &period_size); + + /* check the format */ + if(!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) + { + FLUID_LOG(FLUID_ERR, "Unhandled sample format"); + goto error_recovery; + } + + dev->frame_size = 2 * sizeof(short); + dev->buffer_byte_size = period_size * dev->frame_size; + dev->queue_byte_size = periods * dev->buffer_byte_size; + dev->write = fluid_synth_write_s16; + + /* create and initialize the buffer format */ + dev->format = (WAVEFORMATEX *) FLUID_MALLOC(sizeof(WAVEFORMATEX)); + + if(dev->format == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + ZeroMemory(dev->format, sizeof(WAVEFORMATEX)); + + dev->format->wFormatTag = WAVE_FORMAT_PCM; + dev->format->nChannels = 2; + dev->format->wBitsPerSample = 16; + dev->format->nSamplesPerSec = (DWORD) sample_rate; + dev->format->nBlockAlign = (WORD) dev->frame_size; + dev->format->nAvgBytesPerSec = dev->format->nSamplesPerSec * dev->frame_size; + dev->format->cbSize = 0; + + devsel.devGUID = NULL; + + /* get the selected device name. if none is specified, use NULL for the default device. */ + if(fluid_settings_dupstr(settings, "audio.dsound.device", &devsel.devname) == FLUID_OK /* ++ alloc device name */ + && devsel.devname && strlen(devsel.devname) > 0) + { + /* look for the GUID of the selected device */ + DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback2, (void *)&devsel); + } + + if(devsel.devname) + { + FLUID_FREE(devsel.devname); /* -- free device name */ + } + + /* open DirectSound */ + hr = DirectSoundCreate(devsel.devGUID, &dev->direct_sound, NULL); + + if(hr != DS_OK) + { + FLUID_LOG(FLUID_ERR, "Failed to create the DirectSound object"); + goto error_recovery; + } + + hr = IDirectSound_SetCooperativeLevel(dev->direct_sound, GetDesktopWindow(), DSSCL_PRIORITY); + + if(hr != DS_OK) + { + FLUID_LOG(FLUID_ERR, "Failed to set the cooperative level"); + goto error_recovery; + } + + caps.dwSize = sizeof(caps); + hr = IDirectSound_GetCaps(dev->direct_sound, &caps); + + if(hr != DS_OK) + { + FLUID_LOG(FLUID_ERR, "Failed to query the device capacities"); + goto error_recovery; + } + + /* create primary buffer */ + + ZeroMemory(&desc, sizeof(DSBUFFERDESC)); + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_PRIMARYBUFFER; + + if(caps.dwFreeHwMixingStreamingBuffers > 0) + { + desc.dwFlags |= DSBCAPS_LOCHARDWARE; + } + + hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->prim_buffer, NULL); + + if(hr != DS_OK) + { + FLUID_LOG(FLUID_ERR, "Failed to allocate the primary buffer"); + goto error_recovery; + } + + /* set the primary sound buffer to this format. if it fails, just + print a warning. */ + hr = IDirectSoundBuffer_SetFormat(dev->prim_buffer, dev->format); + + if(hr != DS_OK) + { + FLUID_LOG(FLUID_WARN, "Can't set format of primary sound buffer", fluid_win32_error(hr)); + } + + /* initialize the buffer description */ + + ZeroMemory(&desc, sizeof(DSBUFFERDESC)); + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; + desc.lpwfxFormat = dev->format; + desc.dwBufferBytes = dev->queue_byte_size; + desc.dwReserved = 0; + + if(caps.dwFreeHwMixingStreamingBuffers > 0) + { + desc.dwFlags |= DSBCAPS_LOCHARDWARE; + } + + /* create the secondary sound buffer */ + + hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->sec_buffer, NULL); + + if(hr != DS_OK) + { + FLUID_LOG(FLUID_ERR, "dsound: Can't create sound buffer: %s", fluid_win32_error(hr)); + goto error_recovery; + } + + + /* Lock */ + hr = IDirectSoundBuffer_Lock(dev->sec_buffer, 0, 0, (void *) &buf1, &bytes1, 0, 0, DSBLOCK_ENTIREBUFFER); + + if((hr != DS_OK) || (buf1 == NULL)) + { + FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. Exiting."); + goto error_recovery; + } + + /* fill the buffer with silence */ + memset(buf1, 0, bytes1); + + /* Unlock */ + IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, 0, 0); + + + /* start the audio thread */ + dev->thread = CreateThread(NULL, 0, &fluid_dsound_audio_run, (LPVOID) dev, 0, &dev->threadID); + + if(dev->thread == NULL) + { + goto error_recovery; + } + + return (fluid_audio_driver_t *) dev; + +error_recovery: + delete_fluid_dsound_audio_driver((fluid_audio_driver_t *) dev); return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_dsound_audio_driver_t)); - dev->synth = synth; - dev->cont = 1; - - fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); - fluid_settings_getint(settings, "audio.periods", &periods); - fluid_settings_getint(settings, "audio.period-size", &period_size); - - /* check the format */ - if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) { - FLUID_LOG(FLUID_ERR, "Unhandled sample format"); - goto error_recovery; - } - - dev->frame_size = 2 * sizeof(short); - dev->buffer_byte_size = period_size * dev->frame_size; - dev->queue_byte_size = periods * dev->buffer_byte_size; - dev->write = fluid_synth_write_s16; - - /* create and initialize the buffer format */ - dev->format = (WAVEFORMATEX*) FLUID_MALLOC(sizeof(WAVEFORMATEX)); - if (dev->format == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } - ZeroMemory(dev->format, sizeof(WAVEFORMATEX)); - - dev->format->wFormatTag = WAVE_FORMAT_PCM; - dev->format->nChannels = 2; - dev->format->wBitsPerSample = 16; - dev->format->nSamplesPerSec = (DWORD) sample_rate; - dev->format->nBlockAlign = (WORD) dev->frame_size; - dev->format->nAvgBytesPerSec = dev->format->nSamplesPerSec * dev->frame_size; - dev->format->cbSize = 0; - - devsel.devGUID = NULL; - /* get the selected device name. if none is specified, use NULL for the default device. */ - if(fluid_settings_dupstr(settings, "audio.dsound.device", &devsel.devname) == FLUID_OK /* ++ alloc device name */ - && devsel.devname && strlen (devsel.devname) > 0) { - /* look for the GUID of the selected device */ - DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback2, (void *)&devsel); - } - - if (devsel.devname) FLUID_FREE (devsel.devname); /* -- free device name */ - - /* open DirectSound */ - hr = DirectSoundCreate(devsel.devGUID, &dev->direct_sound, NULL); - if (hr != DS_OK) { - FLUID_LOG(FLUID_ERR, "Failed to create the DirectSound object"); - goto error_recovery; - } - - hr = IDirectSound_SetCooperativeLevel(dev->direct_sound, GetDesktopWindow(), DSSCL_PRIORITY); - if (hr != DS_OK) { - FLUID_LOG(FLUID_ERR, "Failed to set the cooperative level"); - goto error_recovery; - } - - caps.dwSize = sizeof(caps); - hr = IDirectSound_GetCaps(dev->direct_sound, &caps); - if (hr != DS_OK) { - FLUID_LOG(FLUID_ERR, "Failed to query the device capacities"); - goto error_recovery; - } - - /* create primary buffer */ - - ZeroMemory(&desc, sizeof(DSBUFFERDESC)); - desc.dwSize = sizeof(DSBUFFERDESC); - desc.dwFlags = DSBCAPS_PRIMARYBUFFER; - - if (caps.dwFreeHwMixingStreamingBuffers > 0) { - desc.dwFlags |= DSBCAPS_LOCHARDWARE; - } - - hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->prim_buffer, NULL); - if (hr != DS_OK) { - FLUID_LOG(FLUID_ERR, "Failed to allocate the primary buffer"); - goto error_recovery; - } - - /* set the primary sound buffer to this format. if it fails, just - print a warning. */ - hr = IDirectSoundBuffer_SetFormat(dev->prim_buffer, dev->format); - if (hr != DS_OK) { - FLUID_LOG(FLUID_WARN, "Can't set format of primary sound buffer", fluid_win32_error(hr)); - } - - /* initialize the buffer description */ - - ZeroMemory(&desc, sizeof(DSBUFFERDESC)); - desc.dwSize = sizeof(DSBUFFERDESC); - desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; - desc.lpwfxFormat = dev->format; - desc.dwBufferBytes = dev->queue_byte_size; - desc.dwReserved = 0; - - if (caps.dwFreeHwMixingStreamingBuffers > 0) { - desc.dwFlags |= DSBCAPS_LOCHARDWARE; - } - - /* create the secondary sound buffer */ - - hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->sec_buffer, NULL); - if (hr != DS_OK) { - FLUID_LOG(FLUID_ERR, "dsound: Can't create sound buffer: %s", fluid_win32_error(hr)); - goto error_recovery; - } - - - /* Lock */ - hr = IDirectSoundBuffer_Lock(dev->sec_buffer, 0, 0, (void*) &buf1, &bytes1, 0, 0, DSBLOCK_ENTIREBUFFER); - - if ((hr != DS_OK) || (buf1 == NULL)) { - FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. Exiting."); - goto error_recovery; - } - - /* fill the buffer with silence */ - memset(buf1, 0, bytes1); - - /* Unlock */ - IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, 0, 0); - - - /* start the audio thread */ - dev->thread = CreateThread(NULL, 0, &fluid_dsound_audio_run, (LPVOID) dev, 0, &dev->threadID); - if (dev->thread == NULL) { - goto error_recovery; - } - - return (fluid_audio_driver_t*) dev; - - error_recovery: - delete_fluid_dsound_audio_driver((fluid_audio_driver_t*) dev); - return NULL; } -void delete_fluid_dsound_audio_driver(fluid_audio_driver_t* d) +void delete_fluid_dsound_audio_driver(fluid_audio_driver_t *d) { - fluid_dsound_audio_driver_t* dev = (fluid_dsound_audio_driver_t*) d; - fluid_return_if_fail(dev != NULL); + fluid_dsound_audio_driver_t *dev = (fluid_dsound_audio_driver_t *) d; + fluid_return_if_fail(dev != NULL); - /* tell the audio thread to stop its loop */ - dev->cont = 0; + /* tell the audio thread to stop its loop */ + dev->cont = 0; - /* wait till the audio thread exits */ - if (dev->thread != 0) { - if (WaitForSingleObject(dev->thread, 2000) != WAIT_OBJECT_0) { - /* on error kill the thread mercilessly */ - FLUID_LOG(FLUID_DBG, "Couldn't join the audio thread. killing it."); - TerminateThread(dev->thread, 0); + /* wait till the audio thread exits */ + if(dev->thread != 0) + { + if(WaitForSingleObject(dev->thread, 2000) != WAIT_OBJECT_0) + { + /* on error kill the thread mercilessly */ + FLUID_LOG(FLUID_DBG, "Couldn't join the audio thread. killing it."); + TerminateThread(dev->thread, 0); + } } - } - /* release all the allocated ressources */ + /* release all the allocated ressources */ FLUID_FREE(dev->format); - if (dev->sec_buffer != NULL) { - IDirectSoundBuffer_Stop(dev->sec_buffer); - IDirectSoundBuffer_Release(dev->sec_buffer); - } - if (dev->prim_buffer != NULL) { - IDirectSoundBuffer_Release(dev->prim_buffer); - } - if (dev->direct_sound != NULL) { - IDirectSound_Release(dev->direct_sound); - } - FLUID_FREE(dev); + if(dev->sec_buffer != NULL) + { + IDirectSoundBuffer_Stop(dev->sec_buffer); + IDirectSoundBuffer_Release(dev->sec_buffer); + } + + if(dev->prim_buffer != NULL) + { + IDirectSoundBuffer_Release(dev->prim_buffer); + } + + if(dev->direct_sound != NULL) + { + IDirectSound_Release(dev->direct_sound); + } + + FLUID_FREE(dev); } DWORD WINAPI fluid_dsound_audio_run(LPVOID lpParameter) { - fluid_dsound_audio_driver_t* dev = (fluid_dsound_audio_driver_t*) lpParameter; - short *buf1, *buf2; - DWORD bytes1, bytes2; - DWORD cur_position, frames, play_position, write_position, bytes; - HRESULT res; + fluid_dsound_audio_driver_t *dev = (fluid_dsound_audio_driver_t *) lpParameter; + short *buf1, *buf2; + DWORD bytes1, bytes2; + DWORD cur_position, frames, play_position, write_position, bytes; + HRESULT res; - cur_position = 0; + cur_position = 0; - /* boost the priority of the audio thread */ - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + /* boost the priority of the audio thread */ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - IDirectSoundBuffer_Play(dev->sec_buffer, 0, 0, DSBPLAY_LOOPING); + IDirectSoundBuffer_Play(dev->sec_buffer, 0, 0, DSBPLAY_LOOPING); - while (dev->cont) { + while(dev->cont) + { - IDirectSoundBuffer_GetCurrentPosition(dev->sec_buffer, &play_position, &write_position); + IDirectSoundBuffer_GetCurrentPosition(dev->sec_buffer, &play_position, &write_position); - if (cur_position <= play_position) { - bytes = play_position - cur_position; - } else if ((play_position < cur_position) && (write_position <= cur_position)) { - bytes = dev->queue_byte_size + play_position - cur_position; - } else { - bytes = 0; + if(cur_position <= play_position) + { + bytes = play_position - cur_position; + } + else if((play_position < cur_position) && (write_position <= cur_position)) + { + bytes = dev->queue_byte_size + play_position - cur_position; + } + else + { + bytes = 0; + } + + if(bytes >= dev->buffer_byte_size) + { + + /* Lock */ + res = IDirectSoundBuffer_Lock(dev->sec_buffer, cur_position, bytes, (void *) &buf1, &bytes1, (void *) &buf2, &bytes2, 0); + + if((res != DS_OK) || (buf1 == NULL)) + { + FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. System lockup might follow. Exiting."); + ExitProcess(0); + } + + /* fill the first part of the buffer */ + if(bytes1 > 0) + { + frames = bytes1 / dev->frame_size; + dev->write(dev->synth, frames, buf1, 0, 2, buf1, 1, 2); + cur_position += frames * dev->frame_size; + } + + /* fill the second part of the buffer */ + if((buf2 != NULL) && (bytes2 > 0)) + { + frames = bytes2 / dev->frame_size; + dev->write(dev->synth, frames, buf2, 0, 2, buf2, 1, 2); + cur_position += frames * dev->frame_size; + } + + /* Unlock */ + IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, buf2, bytes2); + + if(cur_position >= dev->queue_byte_size) + { + cur_position -= dev->queue_byte_size; + } + + } + else + { + Sleep(1); + } } - if (bytes >= dev->buffer_byte_size) { - - /* Lock */ - res = IDirectSoundBuffer_Lock(dev->sec_buffer, cur_position, bytes, (void*) &buf1, &bytes1, (void*) &buf2, &bytes2, 0); - - if ((res != DS_OK) || (buf1 == NULL)) { - FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. System lockup might follow. Exiting."); - ExitProcess(0); - } - - /* fill the first part of the buffer */ - if (bytes1 > 0) { - frames = bytes1 / dev->frame_size; - dev->write(dev->synth, frames, buf1, 0, 2, buf1, 1, 2); - cur_position += frames * dev->frame_size; - } - - /* fill the second part of the buffer */ - if ((buf2 != NULL) && (bytes2 > 0)) { - frames = bytes2 / dev->frame_size; - dev->write(dev->synth, frames, buf2, 0, 2, buf2, 1, 2); - cur_position += frames * dev->frame_size; - } - - /* Unlock */ - IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, buf2, bytes2); - - if (cur_position >= dev->queue_byte_size) { - cur_position -= dev->queue_byte_size; - } - - } else { - Sleep(1); - } - } - - ExitThread(0); - return 0; /* never reached */ + ExitThread(0); + return 0; /* never reached */ } -char* fluid_win32_error(HRESULT hr) { - char *s = "Don't know why"; - switch (hr) { - case E_NOINTERFACE: s = "No such interface"; break; - case DSERR_GENERIC: s = "Generic error"; break; - case DSERR_ALLOCATED: s = "Required resources already allocated"; break; - case DSERR_BADFORMAT: s = "The format is not supported"; break; - case DSERR_INVALIDPARAM: s = "Invalid parameter"; break; - case DSERR_NOAGGREGATION: s = "No aggregation"; break; - case DSERR_OUTOFMEMORY: s = "Out of memory"; break; - case DSERR_UNINITIALIZED: s = "Uninitialized"; break; - case DSERR_UNSUPPORTED: s = "Function not supported"; break; - } - return s; +char *fluid_win32_error(HRESULT hr) +{ + char *s = "Don't know why"; + + switch(hr) + { + case E_NOINTERFACE: + s = "No such interface"; + break; + + case DSERR_GENERIC: + s = "Generic error"; + break; + + case DSERR_ALLOCATED: + s = "Required resources already allocated"; + break; + + case DSERR_BADFORMAT: + s = "The format is not supported"; + break; + + case DSERR_INVALIDPARAM: + s = "Invalid parameter"; + break; + + case DSERR_NOAGGREGATION: + s = "No aggregation"; + break; + + case DSERR_OUTOFMEMORY: + s = "Out of memory"; + break; + + case DSERR_UNINITIALIZED: + s = "Uninitialized"; + break; + + case DSERR_UNSUPPORTED: + s = "Function not supported"; + break; + } + + return s; } #endif /* DSOUND_SUPPORT */ diff --git a/src/drivers/fluid_jack.c b/src/drivers/fluid_jack.c index 8e42d292..23479051 100644 --- a/src/drivers/fluid_jack.c +++ b/src/drivers/fluid_jack.c @@ -48,50 +48,50 @@ typedef struct _fluid_jack_midi_driver_t fluid_jack_midi_driver_t; /* Clients are shared for drivers using the same server. */ typedef struct { - jack_client_t *client; - char *server; /* Jack server name used */ - fluid_jack_audio_driver_t *audio_driver; - fluid_jack_midi_driver_t *midi_driver; + jack_client_t *client; + char *server; /* Jack server name used */ + fluid_jack_audio_driver_t *audio_driver; + fluid_jack_midi_driver_t *midi_driver; } fluid_jack_client_t; /* Jack audio driver instance */ struct _fluid_jack_audio_driver_t { - fluid_audio_driver_t driver; - fluid_jack_client_t *client_ref; - - int audio_channels; - - jack_port_t **output_ports; - int num_output_ports; - float **output_bufs; - - jack_port_t **fx_ports; - int num_fx_ports; - float **fx_bufs; - - fluid_audio_func_t callback; - void* data; + fluid_audio_driver_t driver; + fluid_jack_client_t *client_ref; + + int audio_channels; + + jack_port_t **output_ports; + int num_output_ports; + float **output_bufs; + + jack_port_t **fx_ports; + int num_fx_ports; + float **fx_bufs; + + fluid_audio_func_t callback; + void *data; }; /* Jack MIDI driver instance */ struct _fluid_jack_midi_driver_t { - fluid_midi_driver_t driver; - fluid_jack_client_t *client_ref; - int midi_port_count; - jack_port_t **midi_port; // array of midi port handles - fluid_midi_parser_t *parser; + fluid_midi_driver_t driver; + fluid_jack_client_t *client_ref; + int midi_port_count; + jack_port_t **midi_port; // array of midi port handles + fluid_midi_parser_t *parser; }; -static fluid_jack_client_t *new_fluid_jack_client (fluid_settings_t *settings, - int isaudio, void *driver); -static int fluid_jack_client_register_ports (void *driver, int isaudio, - jack_client_t *client, - fluid_settings_t *settings); -fluid_audio_driver_t* -new_fluid_jack_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data); -void delete_fluid_jack_audio_driver(fluid_audio_driver_t* p); +static fluid_jack_client_t *new_fluid_jack_client(fluid_settings_t *settings, + int isaudio, void *driver); +static int fluid_jack_client_register_ports(void *driver, int isaudio, + jack_client_t *client, + fluid_settings_t *settings); +fluid_audio_driver_t * +new_fluid_jack_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data); +void delete_fluid_jack_audio_driver(fluid_audio_driver_t *p); void fluid_jack_driver_shutdown(void *arg); int fluid_jack_driver_srate(jack_nframes_t nframes, void *arg); int fluid_jack_driver_bufsize(jack_nframes_t nframes, void *arg); @@ -104,12 +104,12 @@ static fluid_jack_client_t *last_client = NULL; /* Last unpaired client. F void -fluid_jack_audio_driver_settings(fluid_settings_t* settings) +fluid_jack_audio_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "audio.jack.id", "fluidsynth", 0); - fluid_settings_register_int(settings, "audio.jack.multi", 0, 0, 1, FLUID_HINT_TOGGLED); - fluid_settings_register_int(settings, "audio.jack.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED); - fluid_settings_register_str(settings, "audio.jack.server", "", 0); + fluid_settings_register_str(settings, "audio.jack.id", "fluidsynth", 0); + fluid_settings_register_int(settings, "audio.jack.multi", 0, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_int(settings, "audio.jack.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_str(settings, "audio.jack.server", "", 0); } /* @@ -121,585 +121,680 @@ fluid_jack_audio_driver_settings(fluid_settings_t* settings) * @return New or paired Audio/MIDI Jack client */ static fluid_jack_client_t * -new_fluid_jack_client (fluid_settings_t *settings, int isaudio, void *driver) +new_fluid_jack_client(fluid_settings_t *settings, int isaudio, void *driver) { - fluid_jack_client_t *client_ref = NULL; - char *server = NULL; - char* client_name; - char name[64]; + fluid_jack_client_t *client_ref = NULL; + char *server = NULL; + char *client_name; + char name[64]; - if (fluid_settings_dupstr (settings, isaudio ? "audio.jack.server" /* ++ alloc server name */ - : "midi.jack.server", &server) != FLUID_OK) - { - return NULL; - } + if(fluid_settings_dupstr(settings, isaudio ? "audio.jack.server" /* ++ alloc server name */ + : "midi.jack.server", &server) != FLUID_OK) + { + return NULL; + } - fluid_mutex_lock (last_client_mutex); /* ++ lock last_client */ + fluid_mutex_lock(last_client_mutex); /* ++ lock last_client */ - /* If the last client uses the same server and is not the same type (audio or MIDI), - * then re-use the client. */ - if (last_client && - (last_client->server != NULL && server != NULL && FLUID_STRCMP (last_client->server, server) == 0) && - ((!isaudio && last_client->midi_driver != NULL) || (isaudio && last_client->audio_driver != NULL))) - { - client_ref = last_client; - last_client = NULL; /* No more pairing for this client */ + /* If the last client uses the same server and is not the same type (audio or MIDI), + * then re-use the client. */ + if(last_client && + (last_client->server != NULL && server != NULL && FLUID_STRCMP(last_client->server, server) == 0) && + ((!isaudio && last_client->midi_driver != NULL) || (isaudio && last_client->audio_driver != NULL))) + { + client_ref = last_client; + last_client = NULL; /* No more pairing for this client */ + + /* Register ports */ + if(fluid_jack_client_register_ports(driver, isaudio, client_ref->client, settings) != FLUID_OK) + { + goto error_recovery; + } + + if(isaudio) + { + fluid_atomic_pointer_set(&client_ref->audio_driver, driver); + } + else + { + fluid_atomic_pointer_set(&client_ref->midi_driver, driver); + } + + fluid_mutex_unlock(last_client_mutex); /* -- unlock last_client */ + + if(server) + { + FLUID_FREE(server); + } + + return client_ref; + } + + /* No existing client for this Jack server */ + client_ref = FLUID_NEW(fluid_jack_client_t); + + if(!client_ref) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + FLUID_MEMSET(client_ref, 0, sizeof(fluid_jack_client_t)); + + fluid_settings_dupstr(settings, isaudio ? "audio.jack.id" /* ++ alloc client name */ + : "midi.jack.id", &client_name); + + if(client_name != NULL && client_name[0] != 0) + { + FLUID_SNPRINTF(name, 64, "%s", client_name); + } + else + { + strcpy(name, "fluidsynth"); + } + + name[63] = '\0'; + + if(client_name) + { + FLUID_FREE(client_name); /* -- free client name */ + } + + /* Open a connection to the Jack server and use the server name if specified */ + if(server && server[0] != '\0') + { + client_ref->client = jack_client_open(name, JackServerName, NULL, server); + } + else + { + client_ref->client = jack_client_open(name, JackNullOption, NULL); + } + + if(!client_ref->client) + { + FLUID_LOG(FLUID_ERR, "Failed to connect to Jack server."); + goto error_recovery; + } + + jack_set_process_callback(client_ref->client, fluid_jack_driver_process, client_ref); + jack_set_buffer_size_callback(client_ref->client, fluid_jack_driver_bufsize, client_ref); + jack_set_sample_rate_callback(client_ref->client, fluid_jack_driver_srate, client_ref); + jack_on_shutdown(client_ref->client, fluid_jack_driver_shutdown, client_ref); /* Register ports */ - if (fluid_jack_client_register_ports (driver, isaudio, client_ref->client, settings) != FLUID_OK) - goto error_recovery; + if(fluid_jack_client_register_ports(driver, isaudio, client_ref->client, settings) != FLUID_OK) + { + goto error_recovery; + } - if (isaudio) fluid_atomic_pointer_set (&client_ref->audio_driver, driver); - else fluid_atomic_pointer_set (&client_ref->midi_driver, driver); + /* tell the JACK server that we are ready to roll */ + if(jack_activate(client_ref->client)) + { + FLUID_LOG(FLUID_ERR, "Failed to activate Jack client"); + goto error_recovery; + } - fluid_mutex_unlock (last_client_mutex); /* -- unlock last_client */ - - if (server) FLUID_FREE (server); - - return client_ref; - } - - /* No existing client for this Jack server */ - client_ref = FLUID_NEW (fluid_jack_client_t); - - if (!client_ref) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - goto error_recovery; - } - - FLUID_MEMSET (client_ref, 0, sizeof (fluid_jack_client_t)); - - fluid_settings_dupstr (settings, isaudio ? "audio.jack.id" /* ++ alloc client name */ - : "midi.jack.id", &client_name); - - if (client_name != NULL && client_name[0] != 0) - FLUID_SNPRINTF (name, 64, "%s", client_name); - else strcpy (name, "fluidsynth"); - - name[63] = '\0'; - - if (client_name) FLUID_FREE (client_name); /* -- free client name */ - - /* Open a connection to the Jack server and use the server name if specified */ - if (server && server[0] != '\0') - client_ref->client = jack_client_open (name, JackServerName, NULL, server); - else client_ref->client = jack_client_open (name, JackNullOption, NULL); - - if (!client_ref->client) - { - FLUID_LOG (FLUID_ERR, "Failed to connect to Jack server."); - goto error_recovery; - } - - jack_set_process_callback (client_ref->client, fluid_jack_driver_process, client_ref); - jack_set_buffer_size_callback (client_ref->client, fluid_jack_driver_bufsize, client_ref); - jack_set_sample_rate_callback (client_ref->client, fluid_jack_driver_srate, client_ref); - jack_on_shutdown (client_ref->client, fluid_jack_driver_shutdown, client_ref); - - /* Register ports */ - if (fluid_jack_client_register_ports (driver, isaudio, client_ref->client, settings) != FLUID_OK) - goto error_recovery; - - /* tell the JACK server that we are ready to roll */ - if (jack_activate (client_ref->client)) - { - FLUID_LOG (FLUID_ERR, "Failed to activate Jack client"); - goto error_recovery; - } - - /* tell the lash server our client name */ + /* tell the lash server our client name */ #ifdef LASH_ENABLED - { - int enable_lash = 0; - fluid_settings_getint (settings, "lash.enable", &enable_lash); - if (enable_lash) - fluid_lash_jack_client_name (fluid_lash_client, name); - } + { + int enable_lash = 0; + fluid_settings_getint(settings, "lash.enable", &enable_lash); + + if(enable_lash) + { + fluid_lash_jack_client_name(fluid_lash_client, name); + } + } #endif /* LASH_ENABLED */ - client_ref->server = server; /* !! takes over allocation */ - server = NULL; /* Set to NULL so it doesn't get freed below */ + client_ref->server = server; /* !! takes over allocation */ + server = NULL; /* Set to NULL so it doesn't get freed below */ - last_client = client_ref; + last_client = client_ref; - if (isaudio) fluid_atomic_pointer_set (&client_ref->audio_driver, driver); - else fluid_atomic_pointer_set (&client_ref->midi_driver, driver); + if(isaudio) + { + fluid_atomic_pointer_set(&client_ref->audio_driver, driver); + } + else + { + fluid_atomic_pointer_set(&client_ref->midi_driver, driver); + } - fluid_mutex_unlock (last_client_mutex); /* -- unlock last_client */ + fluid_mutex_unlock(last_client_mutex); /* -- unlock last_client */ - if (server) FLUID_FREE (server); + if(server) + { + FLUID_FREE(server); + } - return client_ref; + return client_ref; error_recovery: - fluid_mutex_unlock (last_client_mutex); /* -- unlock clients list */ - if (server) FLUID_FREE (server); /* -- free server name */ + fluid_mutex_unlock(last_client_mutex); /* -- unlock clients list */ - if (client_ref) - { - if (client_ref->client) - jack_client_close (client_ref->client); + if(server) + { + FLUID_FREE(server); /* -- free server name */ + } - FLUID_FREE (client_ref); - } + if(client_ref) + { + if(client_ref->client) + { + jack_client_close(client_ref->client); + } - return NULL; + FLUID_FREE(client_ref); + } + + return NULL; } static int -fluid_jack_client_register_ports (void *driver, int isaudio, jack_client_t *client, - fluid_settings_t *settings) +fluid_jack_client_register_ports(void *driver, int isaudio, jack_client_t *client, + fluid_settings_t *settings) { - fluid_jack_audio_driver_t *dev; - char name[64]; - int multi; - int i; - int jack_srate; - double sample_rate; + fluid_jack_audio_driver_t *dev; + char name[64]; + int multi; + int i; + int jack_srate; + double sample_rate; - if (!isaudio) - { - fluid_jack_midi_driver_t *dev = driver; - int midi_channels, ports; - - fluid_settings_getint(settings, "synth.midi-channels", &midi_channels); - ports = midi_channels / 16; - if((dev->midi_port = FLUID_ARRAY(jack_port_t*, ports)) == NULL) + if(!isaudio) { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } - - for (i = 0; i < ports; i++) - { - FLUID_SNPRINTF(name, sizeof(name), "midi_%02d", i); - dev->midi_port[i] = jack_port_register (client, name, JACK_DEFAULT_MIDI_TYPE, - JackPortIsInput | JackPortIsTerminal, 0); - - if (dev->midi_port[i] == NULL) + fluid_jack_midi_driver_t *dev = driver; + int midi_channels, ports; + + fluid_settings_getint(settings, "synth.midi-channels", &midi_channels); + ports = midi_channels / 16; + + if((dev->midi_port = FLUID_ARRAY(jack_port_t *, ports)) == NULL) { - FLUID_LOG (FLUID_ERR, "Failed to create Jack MIDI port"); - FLUID_FREE(dev->midi_port); - dev->midi_port = NULL; + FLUID_LOG(FLUID_ERR, "Out of memory"); return FLUID_FAILED; } + + for(i = 0; i < ports; i++) + { + FLUID_SNPRINTF(name, sizeof(name), "midi_%02d", i); + dev->midi_port[i] = jack_port_register(client, name, JACK_DEFAULT_MIDI_TYPE, + JackPortIsInput | JackPortIsTerminal, 0); + + if(dev->midi_port[i] == NULL) + { + FLUID_LOG(FLUID_ERR, "Failed to create Jack MIDI port"); + FLUID_FREE(dev->midi_port); + dev->midi_port = NULL; + return FLUID_FAILED; + } + } + + dev->midi_port_count = ports; + return FLUID_OK; } - - dev->midi_port_count = ports; + + dev = driver; + + fluid_settings_getint(settings, "audio.jack.multi", &multi); + + if(!multi) + { + /* create the two audio output ports */ + dev->num_output_ports = 1; + dev->num_fx_ports = 0; + + dev->output_ports = FLUID_ARRAY(jack_port_t *, 2 * dev->num_output_ports); + + if(dev->output_ports == NULL) + { + FLUID_LOG(FLUID_PANIC, "Jack server not running?"); + return FLUID_FAILED; + } + + dev->output_bufs = FLUID_ARRAY(float *, 2 * dev->num_output_ports); + FLUID_MEMSET(dev->output_ports, 0, 2 * dev->num_output_ports * sizeof(jack_port_t *)); + + dev->output_ports[0] + = jack_port_register(client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + dev->output_ports[1] + = jack_port_register(client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + } + else + { + fluid_settings_getint(settings, "synth.audio-channels", &dev->num_output_ports); + + dev->output_ports = FLUID_ARRAY(jack_port_t *, 2 * dev->num_output_ports); + + if(dev->output_ports == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + + dev->output_bufs = FLUID_ARRAY(float *, 2 * dev->num_output_ports); + + if(dev->output_bufs == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + + FLUID_MEMSET(dev->output_ports, 0, 2 * dev->num_output_ports * sizeof(jack_port_t *)); + + for(i = 0; i < dev->num_output_ports; i++) + { + sprintf(name, "l_%02d", i); + dev->output_ports[2 * i] + = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + sprintf(name, "r_%02d", i); + dev->output_ports[2 * i + 1] + = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + + fluid_settings_getint(settings, "synth.effects-channels", &dev->num_fx_ports); + + dev->fx_ports = FLUID_ARRAY(jack_port_t *, 2 * dev->num_fx_ports); + + if(dev->fx_ports == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + + dev->fx_bufs = FLUID_ARRAY(float *, 2 * dev->num_fx_ports); + + if(dev->fx_bufs == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + + FLUID_MEMSET(dev->fx_ports, 0, 2 * dev->num_fx_ports * sizeof(jack_port_t *)); + + for(i = 0; i < dev->num_fx_ports; i++) + { + sprintf(name, "fx_l_%02d", i); + dev->fx_ports[2 * i] + = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + sprintf(name, "fx_r_%02d", i); + dev->fx_ports[2 * i + 1] + = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + } + + + /* Adjust sample rate to match JACK's */ + jack_srate = jack_get_sample_rate(client); + FLUID_LOG(FLUID_DBG, "Jack engine sample rate: %lu", jack_srate); + + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + + if((int)sample_rate != jack_srate) + { + FLUID_LOG(FLUID_INFO, "Jack sample rate mismatch, adjusting." + " (synth.sample-rate=%lu, jackd=%lu)", (int)sample_rate, jack_srate); + fluid_settings_setnum(settings, "synth.sample-rate", jack_srate); + } + + /* Changing sample rate is non RT, so make sure we process it and/or other things now */ + if(dev->callback == NULL) + { + fluid_synth_process_event_queue(dev->data); + } + return FLUID_OK; - } - - dev = driver; - - fluid_settings_getint (settings, "audio.jack.multi", &multi); - - if (!multi) - { - /* create the two audio output ports */ - dev->num_output_ports = 1; - dev->num_fx_ports = 0; - - dev->output_ports = FLUID_ARRAY (jack_port_t*, 2 * dev->num_output_ports); - - if (dev->output_ports == NULL) - { - FLUID_LOG (FLUID_PANIC, "Jack server not running?"); - return FLUID_FAILED; - } - - dev->output_bufs = FLUID_ARRAY (float*, 2 * dev->num_output_ports); - FLUID_MEMSET (dev->output_ports, 0, 2 * dev->num_output_ports * sizeof(jack_port_t*)); - - dev->output_ports[0] - = jack_port_register (client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - - dev->output_ports[1] - = jack_port_register (client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - - } - else - { - fluid_settings_getint (settings, "synth.audio-channels", &dev->num_output_ports); - - dev->output_ports = FLUID_ARRAY (jack_port_t *, 2 * dev->num_output_ports); - - if (dev->output_ports == NULL) - { - FLUID_LOG (FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; - } - - dev->output_bufs = FLUID_ARRAY (float *, 2 * dev->num_output_ports); - - if (dev->output_bufs == NULL) - { - FLUID_LOG (FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; - } - - FLUID_MEMSET (dev->output_ports, 0, 2 * dev->num_output_ports * sizeof (jack_port_t*)); - - for (i = 0; i < dev->num_output_ports; i++) - { - sprintf(name, "l_%02d", i); - dev->output_ports[2 * i] - = jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - - sprintf(name, "r_%02d", i); - dev->output_ports[2 * i + 1] - = jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - } - - fluid_settings_getint (settings, "synth.effects-channels", &dev->num_fx_ports); - - dev->fx_ports = FLUID_ARRAY(jack_port_t*, 2 * dev->num_fx_ports); - if (dev->fx_ports == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; - } - - dev->fx_bufs = FLUID_ARRAY(float*, 2 * dev->num_fx_ports); - if (dev->fx_bufs == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; - } - - FLUID_MEMSET(dev->fx_ports, 0, 2 * dev->num_fx_ports * sizeof(jack_port_t*)); - - for (i = 0; i < dev->num_fx_ports; i++) { - sprintf(name, "fx_l_%02d", i); - dev->fx_ports[2 * i] - = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - - sprintf(name, "fx_r_%02d", i); - dev->fx_ports[2 * i + 1] - = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - } - } - - - /* Adjust sample rate to match JACK's */ - jack_srate = jack_get_sample_rate (client); - FLUID_LOG (FLUID_DBG, "Jack engine sample rate: %lu", jack_srate); - - fluid_settings_getnum (settings, "synth.sample-rate", &sample_rate); - - if ((int)sample_rate != jack_srate) { - FLUID_LOG(FLUID_INFO, "Jack sample rate mismatch, adjusting." - " (synth.sample-rate=%lu, jackd=%lu)", (int)sample_rate, jack_srate); - fluid_settings_setnum (settings, "synth.sample-rate", jack_srate); - } - - /* Changing sample rate is non RT, so make sure we process it and/or other things now */ - if (dev->callback == NULL) - fluid_synth_process_event_queue(dev->data); - - return FLUID_OK; } static void -fluid_jack_client_close (fluid_jack_client_t *client_ref, void *driver) +fluid_jack_client_close(fluid_jack_client_t *client_ref, void *driver) { - if (client_ref->audio_driver == driver) - fluid_atomic_pointer_set (&client_ref->audio_driver, NULL); - else if (client_ref->midi_driver == driver) - fluid_atomic_pointer_set (&client_ref->midi_driver, NULL); - - if (client_ref->audio_driver || client_ref->midi_driver) - { - fluid_msleep(100); /* FIXME - Hack to make sure that resources don't get freed while Jack callback is active */ - return; - } - - fluid_mutex_lock (last_client_mutex); - - if (client_ref == last_client) - last_client = NULL; - - fluid_mutex_unlock (last_client_mutex); - - if (client_ref->client) - jack_client_close (client_ref->client); - - if (client_ref->server) - FLUID_FREE (client_ref->server); - - FLUID_FREE (client_ref); -} - - -fluid_audio_driver_t* -new_fluid_jack_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) -{ - return new_fluid_jack_audio_driver2(settings, NULL, synth); -} - -fluid_audio_driver_t* -new_fluid_jack_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data) -{ - fluid_jack_audio_driver_t* dev = NULL; - jack_client_t *client; - const char ** jack_ports; /* for looking up ports */ - int autoconnect = 0; - int i; - - dev = FLUID_NEW(fluid_jack_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_jack_audio_driver_t)); - - dev->callback = func; - dev->data = data; - - dev->client_ref = new_fluid_jack_client (settings, TRUE, dev); - - if (!dev->client_ref) - { - FLUID_FREE (dev); - return NULL; - } - - client = dev->client_ref->client; - - /* connect the ports. */ - - - /* FIXME: should be done by a patchbay application */ - - /* find some physical ports and connect to them */ - fluid_settings_getint (settings, "audio.jack.autoconnect", &autoconnect); - if (autoconnect) { - jack_ports = jack_get_ports (client, NULL, NULL, JackPortIsInput|JackPortIsPhysical); - if (jack_ports) { - int err; - int connected = 0; - - for (i = 0; jack_ports[i] && i<2 * dev->num_output_ports; ++i) { - err = jack_connect (client, jack_port_name(dev->output_ports[i]), jack_ports[i]); - if (err) { - FLUID_LOG(FLUID_ERR, "Error connecting jack port"); - } else { - connected++; - } - } - - for (i = 0; jack_ports[i] && i<2 * dev->num_fx_ports; ++i) { - err = jack_connect (client, jack_port_name(dev->fx_ports[i]), jack_ports[i]); - if (err) { - FLUID_LOG(FLUID_ERR, "Error connecting jack port"); - } else { - connected++; - } - } - - jack_free (jack_ports); /* free jack ports array (not the port values!) */ - } else { - FLUID_LOG(FLUID_WARN, "Could not connect to any physical jack ports; fluidsynth is unconnected"); + if(client_ref->audio_driver == driver) + { + fluid_atomic_pointer_set(&client_ref->audio_driver, NULL); + } + else if(client_ref->midi_driver == driver) + { + fluid_atomic_pointer_set(&client_ref->midi_driver, NULL); } - } - return (fluid_audio_driver_t*) dev; + if(client_ref->audio_driver || client_ref->midi_driver) + { + fluid_msleep(100); /* FIXME - Hack to make sure that resources don't get freed while Jack callback is active */ + return; + } + + fluid_mutex_lock(last_client_mutex); + + if(client_ref == last_client) + { + last_client = NULL; + } + + fluid_mutex_unlock(last_client_mutex); + + if(client_ref->client) + { + jack_client_close(client_ref->client); + } + + if(client_ref->server) + { + FLUID_FREE(client_ref->server); + } + + FLUID_FREE(client_ref); +} + + +fluid_audio_driver_t * +new_fluid_jack_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) +{ + return new_fluid_jack_audio_driver2(settings, NULL, synth); +} + +fluid_audio_driver_t * +new_fluid_jack_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data) +{ + fluid_jack_audio_driver_t *dev = NULL; + jack_client_t *client; + const char **jack_ports; /* for looking up ports */ + int autoconnect = 0; + int i; + + dev = FLUID_NEW(fluid_jack_audio_driver_t); + + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_jack_audio_driver_t)); + + dev->callback = func; + dev->data = data; + + dev->client_ref = new_fluid_jack_client(settings, TRUE, dev); + + if(!dev->client_ref) + { + FLUID_FREE(dev); + return NULL; + } + + client = dev->client_ref->client; + + /* connect the ports. */ + + + /* FIXME: should be done by a patchbay application */ + + /* find some physical ports and connect to them */ + fluid_settings_getint(settings, "audio.jack.autoconnect", &autoconnect); + + if(autoconnect) + { + jack_ports = jack_get_ports(client, NULL, NULL, JackPortIsInput | JackPortIsPhysical); + + if(jack_ports) + { + int err; + int connected = 0; + + for(i = 0; jack_ports[i] && i < 2 * dev->num_output_ports; ++i) + { + err = jack_connect(client, jack_port_name(dev->output_ports[i]), jack_ports[i]); + + if(err) + { + FLUID_LOG(FLUID_ERR, "Error connecting jack port"); + } + else + { + connected++; + } + } + + for(i = 0; jack_ports[i] && i < 2 * dev->num_fx_ports; ++i) + { + err = jack_connect(client, jack_port_name(dev->fx_ports[i]), jack_ports[i]); + + if(err) + { + FLUID_LOG(FLUID_ERR, "Error connecting jack port"); + } + else + { + connected++; + } + } + + jack_free(jack_ports); /* free jack ports array (not the port values!) */ + } + else + { + FLUID_LOG(FLUID_WARN, "Could not connect to any physical jack ports; fluidsynth is unconnected"); + } + } + + return (fluid_audio_driver_t *) dev; } /* * delete_fluid_jack_audio_driver */ void -delete_fluid_jack_audio_driver(fluid_audio_driver_t* p) +delete_fluid_jack_audio_driver(fluid_audio_driver_t *p) { - fluid_jack_audio_driver_t* dev = (fluid_jack_audio_driver_t*) p; - fluid_return_if_fail (dev != NULL); + fluid_jack_audio_driver_t *dev = (fluid_jack_audio_driver_t *) p; + fluid_return_if_fail(dev != NULL); - if (dev->client_ref != NULL) - fluid_jack_client_close (dev->client_ref, dev); + if(dev->client_ref != NULL) + { + fluid_jack_client_close(dev->client_ref, dev); + } - FLUID_FREE (dev->output_bufs); - FLUID_FREE (dev->output_ports); + FLUID_FREE(dev->output_bufs); + FLUID_FREE(dev->output_ports); FLUID_FREE(dev->fx_bufs); FLUID_FREE(dev->fx_ports); - FLUID_FREE(dev); + FLUID_FREE(dev); } /* Process function for audio and MIDI Jack drivers */ int -fluid_jack_driver_process (jack_nframes_t nframes, void *arg) +fluid_jack_driver_process(jack_nframes_t nframes, void *arg) { - fluid_jack_client_t *client = (fluid_jack_client_t *)arg; - fluid_jack_audio_driver_t *audio_driver; - fluid_jack_midi_driver_t *midi_driver; - float *left, *right; - int i, k; + fluid_jack_client_t *client = (fluid_jack_client_t *)arg; + fluid_jack_audio_driver_t *audio_driver; + fluid_jack_midi_driver_t *midi_driver; + float *left, *right; + int i, k; - jack_midi_event_t midi_event; - fluid_midi_event_t *evt; - void *midi_buffer; - jack_nframes_t event_count; - jack_nframes_t event_index; - unsigned int u; + jack_midi_event_t midi_event; + fluid_midi_event_t *evt; + void *midi_buffer; + jack_nframes_t event_count; + jack_nframes_t event_index; + unsigned int u; - /* Process MIDI events first, so that they take effect before audio synthesis */ - midi_driver = fluid_atomic_pointer_get (&client->midi_driver); + /* Process MIDI events first, so that they take effect before audio synthesis */ + midi_driver = fluid_atomic_pointer_get(&client->midi_driver); - if (midi_driver) - { - for (i = 0; i < midi_driver->midi_port_count; i++) + if(midi_driver) { - midi_buffer = jack_port_get_buffer (midi_driver->midi_port[i], 0); - event_count = jack_midi_get_event_count (midi_buffer); - - for (event_index = 0; event_index < event_count; event_index++) + for(i = 0; i < midi_driver->midi_port_count; i++) { - jack_midi_event_get (&midi_event, midi_buffer, event_index); + midi_buffer = jack_port_get_buffer(midi_driver->midi_port[i], 0); + event_count = jack_midi_get_event_count(midi_buffer); - /* let the parser convert the data into events */ - for (u = 0; u < midi_event.size; u++) + for(event_index = 0; event_index < event_count; event_index++) { - evt = fluid_midi_parser_parse (midi_driver->parser, midi_event.buffer[u]); + jack_midi_event_get(&midi_event, midi_buffer, event_index); - /* send the event to the next link in the chain */ - if (evt != NULL) + /* let the parser convert the data into events */ + for(u = 0; u < midi_event.size; u++) { - fluid_midi_event_set_channel(evt, fluid_midi_event_get_channel(evt) + i * 16); - midi_driver->driver.handler (midi_driver->driver.data, evt); + evt = fluid_midi_parser_parse(midi_driver->parser, midi_event.buffer[u]); + + /* send the event to the next link in the chain */ + if(evt != NULL) + { + fluid_midi_event_set_channel(evt, fluid_midi_event_get_channel(evt) + i * 16); + midi_driver->driver.handler(midi_driver->driver.data, evt); + } } } } } - } - audio_driver = fluid_atomic_pointer_get (&client->audio_driver); - if (!audio_driver) return 0; + audio_driver = fluid_atomic_pointer_get(&client->audio_driver); - if (audio_driver->callback != NULL) - { - for (i = 0; i < audio_driver->num_output_ports * 2; i++) - audio_driver->output_bufs[i] = (float *)jack_port_get_buffer (audio_driver->output_ports[i], nframes); - - return (*audio_driver->callback)(audio_driver->data, nframes, 0, NULL, - 2 * audio_driver->num_output_ports, - audio_driver->output_bufs); - } - else if (audio_driver->num_output_ports == 1 && audio_driver->num_fx_ports == 0) /* i.e. audio.jack.multi=no */ - { - left = (float*) jack_port_get_buffer (audio_driver->output_ports[0], nframes); - right = (float*) jack_port_get_buffer (audio_driver->output_ports[1], nframes); - - fluid_synth_write_float (audio_driver->data, nframes, left, 0, 1, right, 0, 1); - } - else - { - for (i = 0, k = audio_driver->num_output_ports; i < audio_driver->num_output_ports; i++, k++) { - audio_driver->output_bufs[i] = (float *)jack_port_get_buffer (audio_driver->output_ports[2*i], nframes); - audio_driver->output_bufs[k] = (float *)jack_port_get_buffer (audio_driver->output_ports[2*i+1], nframes); - } - for (i = 0, k = audio_driver->num_fx_ports; i < audio_driver->num_fx_ports; i++, k++) { - audio_driver->fx_bufs[i] = (float*) jack_port_get_buffer(audio_driver->fx_ports[2*i], nframes); - audio_driver->fx_bufs[k] = (float*) jack_port_get_buffer(audio_driver->fx_ports[2*i+1], nframes); + if(!audio_driver) + { + return 0; } - fluid_synth_nwrite_float (audio_driver->data, - nframes, - audio_driver->output_bufs, - audio_driver->output_bufs + audio_driver->num_output_ports, - audio_driver->fx_bufs, - audio_driver->fx_bufs + audio_driver->num_fx_ports); - } + if(audio_driver->callback != NULL) + { + for(i = 0; i < audio_driver->num_output_ports * 2; i++) + { + audio_driver->output_bufs[i] = (float *)jack_port_get_buffer(audio_driver->output_ports[i], nframes); + } - return 0; + return (*audio_driver->callback)(audio_driver->data, nframes, 0, NULL, + 2 * audio_driver->num_output_ports, + audio_driver->output_bufs); + } + else if(audio_driver->num_output_ports == 1 && audio_driver->num_fx_ports == 0) /* i.e. audio.jack.multi=no */ + { + left = (float *) jack_port_get_buffer(audio_driver->output_ports[0], nframes); + right = (float *) jack_port_get_buffer(audio_driver->output_ports[1], nframes); + + fluid_synth_write_float(audio_driver->data, nframes, left, 0, 1, right, 0, 1); + } + else + { + for(i = 0, k = audio_driver->num_output_ports; i < audio_driver->num_output_ports; i++, k++) + { + audio_driver->output_bufs[i] = (float *)jack_port_get_buffer(audio_driver->output_ports[2 * i], nframes); + audio_driver->output_bufs[k] = (float *)jack_port_get_buffer(audio_driver->output_ports[2 * i + 1], nframes); + } + + for(i = 0, k = audio_driver->num_fx_ports; i < audio_driver->num_fx_ports; i++, k++) + { + audio_driver->fx_bufs[i] = (float *) jack_port_get_buffer(audio_driver->fx_ports[2 * i], nframes); + audio_driver->fx_bufs[k] = (float *) jack_port_get_buffer(audio_driver->fx_ports[2 * i + 1], nframes); + } + + fluid_synth_nwrite_float(audio_driver->data, + nframes, + audio_driver->output_bufs, + audio_driver->output_bufs + audio_driver->num_output_ports, + audio_driver->fx_bufs, + audio_driver->fx_bufs + audio_driver->num_fx_ports); + } + + return 0; } int fluid_jack_driver_bufsize(jack_nframes_t nframes, void *arg) { -/* printf("the maximum buffer size is now %lu\n", nframes); */ - return 0; + /* printf("the maximum buffer size is now %lu\n", nframes); */ + return 0; } int fluid_jack_driver_srate(jack_nframes_t nframes, void *arg) { -/* printf("the sample rate is now %lu/sec\n", nframes); */ - /* FIXME: change the sample rate of the synthesizer! */ - return 0; + /* printf("the sample rate is now %lu/sec\n", nframes); */ + /* FIXME: change the sample rate of the synthesizer! */ + return 0; } void fluid_jack_driver_shutdown(void *arg) { // fluid_jack_audio_driver_t* dev = (fluid_jack_audio_driver_t*) arg; - FLUID_LOG(FLUID_ERR, "Help! Lost the connection to the JACK server"); -/* exit (1); */ + FLUID_LOG(FLUID_ERR, "Help! Lost the connection to the JACK server"); + /* exit (1); */ } -void fluid_jack_midi_driver_settings (fluid_settings_t *settings) +void fluid_jack_midi_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str (settings, "midi.jack.id", "fluidsynth-midi", 0); - fluid_settings_register_str (settings, "midi.jack.server", "", 0); + fluid_settings_register_str(settings, "midi.jack.id", "fluidsynth-midi", 0); + fluid_settings_register_str(settings, "midi.jack.server", "", 0); } /* * new_fluid_jack_midi_driver */ fluid_midi_driver_t * -new_fluid_jack_midi_driver (fluid_settings_t *settings, - handle_midi_event_func_t handler, void *data) +new_fluid_jack_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data) { - fluid_jack_midi_driver_t* dev; + fluid_jack_midi_driver_t *dev; - fluid_return_val_if_fail (handler != NULL, NULL); + fluid_return_val_if_fail(handler != NULL, NULL); - /* allocate the device */ - dev = FLUID_NEW (fluid_jack_midi_driver_t); + /* allocate the device */ + dev = FLUID_NEW(fluid_jack_midi_driver_t); - if (dev == NULL) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return NULL; - } + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - FLUID_MEMSET (dev, 0, sizeof (fluid_jack_midi_driver_t)); + FLUID_MEMSET(dev, 0, sizeof(fluid_jack_midi_driver_t)); - dev->driver.handler = handler; - dev->driver.data = data; + dev->driver.handler = handler; + dev->driver.data = data; - /* allocate one event to store the input data */ - dev->parser = new_fluid_midi_parser (); + /* allocate one event to store the input data */ + dev->parser = new_fluid_midi_parser(); - if (dev->parser == NULL) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - FLUID_FREE (dev); - return NULL; - } + if(dev->parser == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_FREE(dev); + return NULL; + } - dev->client_ref = new_fluid_jack_client (settings, FALSE, dev); + dev->client_ref = new_fluid_jack_client(settings, FALSE, dev); - if (!dev->client_ref) - { - FLUID_FREE (dev); - return NULL; - } + if(!dev->client_ref) + { + FLUID_FREE(dev); + return NULL; + } - return (fluid_midi_driver_t *)dev; + return (fluid_midi_driver_t *)dev; } void delete_fluid_jack_midi_driver(fluid_midi_driver_t *p) { - fluid_jack_midi_driver_t *dev = (fluid_jack_midi_driver_t *)p; - fluid_return_if_fail (dev != NULL); + fluid_jack_midi_driver_t *dev = (fluid_jack_midi_driver_t *)p; + fluid_return_if_fail(dev != NULL); - if (dev->client_ref != NULL) - fluid_jack_client_close (dev->client_ref, dev); + if(dev->client_ref != NULL) + { + fluid_jack_client_close(dev->client_ref, dev); + } - delete_fluid_midi_parser (dev->parser); - FLUID_FREE(dev->midi_port); - FLUID_FREE (dev); + delete_fluid_midi_parser(dev->parser); + FLUID_FREE(dev->midi_port); + FLUID_FREE(dev); } #endif /* JACK_SUPPORT */ diff --git a/src/drivers/fluid_mdriver.c b/src/drivers/fluid_mdriver.c index 6e3a1fee..ed3a8410 100644 --- a/src/drivers/fluid_mdriver.c +++ b/src/drivers/fluid_mdriver.c @@ -31,61 +31,61 @@ /* ALSA */ #if ALSA_SUPPORT -fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -void delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t* p); -void fluid_alsa_rawmidi_driver_settings(fluid_settings_t* settings); +fluid_midi_driver_t *new_fluid_alsa_rawmidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); +void delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t *p); +void fluid_alsa_rawmidi_driver_settings(fluid_settings_t *settings); -fluid_midi_driver_t* new_fluid_alsa_seq_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -void delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p); -void fluid_alsa_seq_driver_settings(fluid_settings_t* settings); +fluid_midi_driver_t *new_fluid_alsa_seq_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); +void delete_fluid_alsa_seq_driver(fluid_midi_driver_t *p); +void fluid_alsa_seq_driver_settings(fluid_settings_t *settings); #endif /* JACK */ #if JACK_SUPPORT -void fluid_jack_midi_driver_settings (fluid_settings_t *settings); -fluid_midi_driver_t *new_fluid_jack_midi_driver (fluid_settings_t *settings, - handle_midi_event_func_t handler, - void *data); +void fluid_jack_midi_driver_settings(fluid_settings_t *settings); +fluid_midi_driver_t *new_fluid_jack_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *data); void delete_fluid_jack_midi_driver(fluid_midi_driver_t *p); #endif /* OSS */ #if OSS_SUPPORT -fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -void delete_fluid_oss_midi_driver(fluid_midi_driver_t* p); -void fluid_oss_midi_driver_settings(fluid_settings_t* settings); +fluid_midi_driver_t *new_fluid_oss_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); +void delete_fluid_oss_midi_driver(fluid_midi_driver_t *p); +void fluid_oss_midi_driver_settings(fluid_settings_t *settings); #endif /* Windows MIDI service */ #if WINMIDI_SUPPORT -fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -void delete_fluid_winmidi_driver(fluid_midi_driver_t* p); -void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings); +fluid_midi_driver_t *new_fluid_winmidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); +void delete_fluid_winmidi_driver(fluid_midi_driver_t *p); +void fluid_winmidi_midi_driver_settings(fluid_settings_t *settings); #endif /* definitions for the MidiShare driver */ #if MIDISHARE_SUPPORT -fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -void delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p); +fluid_midi_driver_t *new_fluid_midishare_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); +void delete_fluid_midishare_midi_driver(fluid_midi_driver_t *p); #endif /* definitions for the CoreMidi driver */ #if COREMIDI_SUPPORT -fluid_midi_driver_t* new_fluid_coremidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* event_handler_data); -void delete_fluid_coremidi_driver(fluid_midi_driver_t* p); -void fluid_coremidi_driver_settings(fluid_settings_t* settings); +fluid_midi_driver_t *new_fluid_coremidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *event_handler_data); +void delete_fluid_coremidi_driver(fluid_midi_driver_t *p); +void fluid_coremidi_driver_settings(fluid_settings_t *settings); #endif @@ -94,116 +94,136 @@ void fluid_coremidi_driver_settings(fluid_settings_t* settings); /* * fluid_mdriver_definition */ -struct fluid_mdriver_definition_t { - const char* name; - fluid_midi_driver_t* (*new)(fluid_settings_t* settings, - handle_midi_event_func_t event_handler, - void* event_handler_data); - void (*free)(fluid_midi_driver_t* p); - void (*settings)(fluid_settings_t* settings); +struct fluid_mdriver_definition_t +{ + const char *name; + fluid_midi_driver_t *(*new)(fluid_settings_t *settings, + handle_midi_event_func_t event_handler, + void *event_handler_data); + void (*free)(fluid_midi_driver_t *p); + void (*settings)(fluid_settings_t *settings); }; -static const struct fluid_mdriver_definition_t fluid_midi_drivers[] = { +static const struct fluid_mdriver_definition_t fluid_midi_drivers[] = +{ #if JACK_SUPPORT - { "jack", - new_fluid_jack_midi_driver, - delete_fluid_jack_midi_driver, - fluid_jack_midi_driver_settings }, + { + "jack", + new_fluid_jack_midi_driver, + delete_fluid_jack_midi_driver, + fluid_jack_midi_driver_settings + }, #endif #if OSS_SUPPORT - { "oss", - new_fluid_oss_midi_driver, - delete_fluid_oss_midi_driver, - fluid_oss_midi_driver_settings }, + { + "oss", + new_fluid_oss_midi_driver, + delete_fluid_oss_midi_driver, + fluid_oss_midi_driver_settings + }, #endif #if ALSA_SUPPORT - { "alsa_raw", - new_fluid_alsa_rawmidi_driver, - delete_fluid_alsa_rawmidi_driver, - fluid_alsa_rawmidi_driver_settings }, - { "alsa_seq", - new_fluid_alsa_seq_driver, - delete_fluid_alsa_seq_driver, - fluid_alsa_seq_driver_settings }, + { + "alsa_raw", + new_fluid_alsa_rawmidi_driver, + delete_fluid_alsa_rawmidi_driver, + fluid_alsa_rawmidi_driver_settings + }, + { + "alsa_seq", + new_fluid_alsa_seq_driver, + delete_fluid_alsa_seq_driver, + fluid_alsa_seq_driver_settings + }, #endif #if WINMIDI_SUPPORT - { "winmidi", - new_fluid_winmidi_driver, - delete_fluid_winmidi_driver, - fluid_winmidi_midi_driver_settings }, + { + "winmidi", + new_fluid_winmidi_driver, + delete_fluid_winmidi_driver, + fluid_winmidi_midi_driver_settings + }, #endif #if MIDISHARE_SUPPORT - { "midishare", - new_fluid_midishare_midi_driver, - delete_fluid_midishare_midi_driver, - NULL }, + { + "midishare", + new_fluid_midishare_midi_driver, + delete_fluid_midishare_midi_driver, + NULL + }, #endif #if COREMIDI_SUPPORT - { "coremidi", - new_fluid_coremidi_driver, - delete_fluid_coremidi_driver, - fluid_coremidi_driver_settings }, + { + "coremidi", + new_fluid_coremidi_driver, + delete_fluid_coremidi_driver, + fluid_coremidi_driver_settings + }, #endif }; #endif /* FLUID_MIDI_SUPPORT */ -void fluid_midi_driver_settings(fluid_settings_t* settings) +void fluid_midi_driver_settings(fluid_settings_t *settings) { #ifdef FLUID_MIDI_SUPPORT - unsigned int i; + unsigned int i; #endif - fluid_settings_register_int (settings, "midi.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED); - - fluid_settings_register_int (settings, "midi.realtime-prio", - FLUID_DEFAULT_MIDI_RT_PRIO, 0, 99, 0); + fluid_settings_register_int(settings, "midi.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED); - /* Set the default driver */ + fluid_settings_register_int(settings, "midi.realtime-prio", + FLUID_DEFAULT_MIDI_RT_PRIO, 0, 99, 0); + + /* Set the default driver */ #if ALSA_SUPPORT - fluid_settings_register_str(settings, "midi.driver", "alsa_seq", 0); + fluid_settings_register_str(settings, "midi.driver", "alsa_seq", 0); #elif JACK_SUPPORT - fluid_settings_register_str(settings, "midi.driver", "jack", 0); + fluid_settings_register_str(settings, "midi.driver", "jack", 0); #elif OSS_SUPPORT - fluid_settings_register_str(settings, "midi.driver", "oss", 0); + fluid_settings_register_str(settings, "midi.driver", "oss", 0); #elif WINMIDI_SUPPORT - fluid_settings_register_str(settings, "midi.driver", "winmidi", 0); + fluid_settings_register_str(settings, "midi.driver", "winmidi", 0); #elif MIDISHARE_SUPPORT - fluid_settings_register_str(settings, "midi.driver", "midishare", 0); + fluid_settings_register_str(settings, "midi.driver", "midishare", 0); #elif COREMIDI_SUPPORT - fluid_settings_register_str(settings, "midi.driver", "coremidi", 0); + fluid_settings_register_str(settings, "midi.driver", "coremidi", 0); #else - fluid_settings_register_str(settings, "midi.driver", "", 0); + fluid_settings_register_str(settings, "midi.driver", "", 0); #endif - /* Add all drivers to the list of options */ + /* Add all drivers to the list of options */ #if ALSA_SUPPORT - fluid_settings_add_option(settings, "midi.driver", "alsa_seq"); - fluid_settings_add_option(settings, "midi.driver", "alsa_raw"); + fluid_settings_add_option(settings, "midi.driver", "alsa_seq"); + fluid_settings_add_option(settings, "midi.driver", "alsa_raw"); #endif #if JACK_SUPPORT - fluid_settings_add_option(settings, "midi.driver", "jack"); + fluid_settings_add_option(settings, "midi.driver", "jack"); #endif #if OSS_SUPPORT - fluid_settings_add_option(settings, "midi.driver", "oss"); + fluid_settings_add_option(settings, "midi.driver", "oss"); #endif #if WINMIDI_SUPPORT - fluid_settings_add_option(settings, "midi.driver", "winmidi"); + fluid_settings_add_option(settings, "midi.driver", "winmidi"); #endif #if MIDISHARE_SUPPORT - fluid_settings_add_option(settings, "midi.driver", "midishare"); + fluid_settings_add_option(settings, "midi.driver", "midishare"); #endif #if COREMIDI_SUPPORT - fluid_settings_add_option(settings, "midi.driver", "coremidi"); + fluid_settings_add_option(settings, "midi.driver", "coremidi"); #endif #ifdef FLUID_MIDI_SUPPORT - for (i = 0; i < FLUID_N_ELEMENTS(fluid_midi_drivers); i++) { - if (fluid_midi_drivers[i].settings != NULL) { - fluid_midi_drivers[i].settings(settings); + + for(i = 0; i < FLUID_N_ELEMENTS(fluid_midi_drivers); i++) + { + if(fluid_midi_drivers[i].settings != NULL) + { + fluid_midi_drivers[i].settings(settings); + } } - } + #endif } @@ -215,47 +235,60 @@ void fluid_midi_driver_settings(fluid_settings_t* settings) * @param event_handler_data Caller defined data to pass to 'handler' * @return New MIDI driver instance or NULL on error */ -fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data) +fluid_midi_driver_t *new_fluid_midi_driver(fluid_settings_t *settings, handle_midi_event_func_t handler, void *event_handler_data) { #ifdef FLUID_MIDI_SUPPORT - fluid_midi_driver_t* driver = NULL; - char *allnames; - unsigned int i; + fluid_midi_driver_t *driver = NULL; + char *allnames; + unsigned int i; - for (i = 0; i < FLUID_N_ELEMENTS(fluid_midi_drivers); i++) { - if (fluid_settings_str_equal(settings, "midi.driver", fluid_midi_drivers[i].name)) { - FLUID_LOG(FLUID_DBG, "Using '%s' midi driver", fluid_midi_drivers[i].name); - driver = fluid_midi_drivers[i].new(settings, handler, event_handler_data); - if (driver) { - driver->name = fluid_midi_drivers[i].name; - } - return driver; + for(i = 0; i < FLUID_N_ELEMENTS(fluid_midi_drivers); i++) + { + if(fluid_settings_str_equal(settings, "midi.driver", fluid_midi_drivers[i].name)) + { + FLUID_LOG(FLUID_DBG, "Using '%s' midi driver", fluid_midi_drivers[i].name); + driver = fluid_midi_drivers[i].new(settings, handler, event_handler_data); + + if(driver) + { + driver->name = fluid_midi_drivers[i].name; + } + + return driver; + } + } + + allnames = fluid_settings_option_concat(settings, "midi.driver", NULL); + FLUID_LOG(FLUID_ERR, "Couldn't find the requested midi driver. Valid drivers are: %s.", + allnames ? allnames : "ERROR"); + + if(allnames) + { + FLUID_FREE(allnames); } - } - allnames = fluid_settings_option_concat (settings, "midi.driver", NULL); - FLUID_LOG(FLUID_ERR, "Couldn't find the requested midi driver. Valid drivers are: %s.", - allnames ? allnames : "ERROR"); - if (allnames) FLUID_FREE (allnames); #endif - return NULL; + return NULL; } /** * Delete a MIDI driver instance. * @param driver MIDI driver to delete */ -void delete_fluid_midi_driver(fluid_midi_driver_t* driver) +void delete_fluid_midi_driver(fluid_midi_driver_t *driver) { #ifdef FLUID_MIDI_SUPPORT - unsigned int i; - fluid_return_if_fail(driver != NULL); + unsigned int i; + fluid_return_if_fail(driver != NULL); - for (i = 0; i < FLUID_N_ELEMENTS(fluid_midi_drivers); i++) { - if (fluid_midi_drivers[i].name == driver->name) { - fluid_midi_drivers[i].free(driver); - return; + for(i = 0; i < FLUID_N_ELEMENTS(fluid_midi_drivers); i++) + { + if(fluid_midi_drivers[i].name == driver->name) + { + fluid_midi_drivers[i].free(driver); + return; + } } - } + #endif } diff --git a/src/drivers/fluid_mdriver.h b/src/drivers/fluid_mdriver.h index fdb96944..1a88c37b 100644 --- a/src/drivers/fluid_mdriver.h +++ b/src/drivers/fluid_mdriver.h @@ -23,7 +23,7 @@ #include "fluid_sys.h" -void fluid_midi_driver_settings(fluid_settings_t* settings); +void fluid_midi_driver_settings(fluid_settings_t *settings); /* @@ -32,9 +32,9 @@ void fluid_midi_driver_settings(fluid_settings_t* settings); struct _fluid_midi_driver_t { - const char* name; - handle_midi_event_func_t handler; - void* data; + const char *name; + handle_midi_event_func_t handler; + void *data; }; diff --git a/src/drivers/fluid_midishare.c b/src/drivers/fluid_midishare.c index f5f60ea3..a65f47b0 100644 --- a/src/drivers/fluid_midishare.c +++ b/src/drivers/fluid_midishare.c @@ -49,167 +49,189 @@ #define MSHDriverName "fluidsynth" #endif -typedef struct { - fluid_midi_driver_t driver; - int status; - short refnum; - MidiFilterPtr filter; - #if defined(MACINTOSH) && defined(MACOS9) - UPPRcvAlarmPtr upp_alarm_ptr; - UPPDriverPtr upp_wakeup_ptr; - UPPDriverPtr upp_sleep_ptr; - UPPTaskPtr upp_task_ptr; - #endif - SlotRefNum slotRef; - unsigned char sysexbuf[FLUID_MIDI_PARSER_MAX_DATA_SIZE]; +typedef struct +{ + fluid_midi_driver_t driver; + int status; + short refnum; + MidiFilterPtr filter; +#if defined(MACINTOSH) && defined(MACOS9) + UPPRcvAlarmPtr upp_alarm_ptr; + UPPDriverPtr upp_wakeup_ptr; + UPPDriverPtr upp_sleep_ptr; + UPPTaskPtr upp_task_ptr; +#endif + SlotRefNum slotRef; + unsigned char sysexbuf[FLUID_MIDI_PARSER_MAX_DATA_SIZE]; } fluid_midishare_midi_driver_t; -fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* data); +fluid_midi_driver_t *new_fluid_midishare_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *data); -void delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p); -int fluid_midishare_midi_driver_status(fluid_midi_driver_t* p); +void delete_fluid_midishare_midi_driver(fluid_midi_driver_t *p); +int fluid_midishare_midi_driver_status(fluid_midi_driver_t *p); static void fluid_midishare_midi_driver_receive(short ref); #if defined(MIDISHARE_DRIVER) -static int fluid_midishare_open_driver (fluid_midishare_midi_driver_t* dev); -static void fluid_midishare_close_driver (fluid_midishare_midi_driver_t* dev); +static int fluid_midishare_open_driver(fluid_midishare_midi_driver_t *dev); +static void fluid_midishare_close_driver(fluid_midishare_midi_driver_t *dev); #else -static int fluid_midishare_open_appl (fluid_midishare_midi_driver_t* dev); -static void fluid_midishare_close_appl (fluid_midishare_midi_driver_t* dev); +static int fluid_midishare_open_appl(fluid_midishare_midi_driver_t *dev); +static void fluid_midishare_close_appl(fluid_midishare_midi_driver_t *dev); #endif /* * new_fluid_midishare_midi_driver */ -fluid_midi_driver_t* -new_fluid_midishare_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, - void* data) +fluid_midi_driver_t * +new_fluid_midishare_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, + void *data) { - fluid_midishare_midi_driver_t* dev; - int i; + fluid_midishare_midi_driver_t *dev; + int i; - /* not much use doing anything */ - if (handler == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid argument"); + /* not much use doing anything */ + if(handler == NULL) + { + FLUID_LOG(FLUID_ERR, "Invalid argument"); + return NULL; + } + + /* allocate the device */ + dev = FLUID_NEW(fluid_midishare_midi_driver_t); + + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_midishare_midi_driver_t)); + dev->driver.handler = handler; + dev->driver.data = data; + + /* register to MidiShare as Application or Driver */ +#if defined(MIDISHARE_DRIVER) + + if(!fluid_midishare_open_driver(dev)) + { + goto error_recovery; + } + +#else + + if(!fluid_midishare_open_appl(dev)) + { + goto error_recovery; + } + +#endif + + /*MidiSetInfo(dev->refnum, dev->router->synth); */ + MidiSetInfo(dev->refnum, dev); + dev->filter = MidiNewFilter(); + + if(dev->filter == 0) + { + FLUID_LOG(FLUID_ERR, "Can not allocate MidiShare filter"); + goto error_recovery; + } + + for(i = 0 ; i < 256; i++) + { + MidiAcceptPort(dev->filter, i, 1); /* accept all ports */ + MidiAcceptType(dev->filter, i, 0); /* reject all types */ + } + + for(i = 0 ; i < 16; i++) + { + MidiAcceptChan(dev->filter, i, 1); /* accept all chan */ + } + + /* accept only the following types */ + MidiAcceptType(dev->filter, typeNote, 1); + MidiAcceptType(dev->filter, typeKeyOn, 1); + MidiAcceptType(dev->filter, typeKeyOff, 1); + MidiAcceptType(dev->filter, typeCtrlChange, 1); + MidiAcceptType(dev->filter, typeProgChange, 1); + MidiAcceptType(dev->filter, typePitchWheel, 1); + MidiAcceptType(dev->filter, typeSysEx, 1); + + /* set the filter */ + MidiSetFilter(dev->refnum, dev->filter); + + dev->status = FLUID_MIDI_READY; + return (fluid_midi_driver_t *) dev; + +error_recovery: + delete_fluid_midishare_midi_driver((fluid_midi_driver_t *) dev); return NULL; - } - - /* allocate the device */ - dev = FLUID_NEW(fluid_midishare_midi_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_midishare_midi_driver_t)); - dev->driver.handler = handler; - dev->driver.data = data; - - /* register to MidiShare as Application or Driver */ - #if defined(MIDISHARE_DRIVER) - if (!fluid_midishare_open_driver(dev)) goto error_recovery; - #else - if (!fluid_midishare_open_appl(dev)) goto error_recovery; - #endif - - /*MidiSetInfo(dev->refnum, dev->router->synth); */ - MidiSetInfo(dev->refnum, dev); - dev->filter = MidiNewFilter(); - if (dev->filter == 0) { - FLUID_LOG(FLUID_ERR, "Can not allocate MidiShare filter"); - goto error_recovery; - } - - for (i = 0 ; i < 256; i++) { - MidiAcceptPort(dev->filter, i, 1); /* accept all ports */ - MidiAcceptType(dev->filter, i, 0); /* reject all types */ - } - - for (i = 0 ; i < 16; i++) { - MidiAcceptChan(dev->filter, i, 1); /* accept all chan */ - } - - /* accept only the following types */ - MidiAcceptType(dev->filter, typeNote, 1); - MidiAcceptType(dev->filter, typeKeyOn, 1); - MidiAcceptType(dev->filter, typeKeyOff, 1); - MidiAcceptType(dev->filter, typeCtrlChange, 1); - MidiAcceptType(dev->filter, typeProgChange, 1); - MidiAcceptType(dev->filter, typePitchWheel, 1); - MidiAcceptType(dev->filter, typeSysEx, 1); - - /* set the filter */ - MidiSetFilter(dev->refnum, dev->filter); - - dev->status = FLUID_MIDI_READY; - return (fluid_midi_driver_t*) dev; - - error_recovery: - delete_fluid_midishare_midi_driver((fluid_midi_driver_t*) dev); - return NULL; } /* * delete_fluid_midishare_midi_driver */ -void delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p) +void delete_fluid_midishare_midi_driver(fluid_midi_driver_t *p) { - fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_midishare_midi_driver_t *dev = (fluid_midishare_midi_driver_t *) p; + fluid_return_if_fail(dev != NULL); - if (dev->filter) MidiFreeFilter(dev->filter); + if(dev->filter) + { + MidiFreeFilter(dev->filter); + } - #if defined(MIDISHARE_DRIVER) - fluid_midishare_close_driver(dev); - #else - fluid_midishare_close_appl(dev); - #endif +#if defined(MIDISHARE_DRIVER) + fluid_midishare_close_driver(dev); +#else + fluid_midishare_close_appl(dev); +#endif - #if defined(MACINTOSH) && defined(MACOS9) - DisposeRoutineDescriptor(dev->upp_alarm_ptr); - DisposeRoutineDescriptor(dev->upp_wakeup_ptr); - DisposeRoutineDescriptor(dev->upp_sleep_ptr); - DisposeRoutineDescriptor(dev->upp_task_ptr); - #endif +#if defined(MACINTOSH) && defined(MACOS9) + DisposeRoutineDescriptor(dev->upp_alarm_ptr); + DisposeRoutineDescriptor(dev->upp_wakeup_ptr); + DisposeRoutineDescriptor(dev->upp_sleep_ptr); + DisposeRoutineDescriptor(dev->upp_task_ptr); +#endif - dev->status = FLUID_MIDI_DONE; + dev->status = FLUID_MIDI_DONE; - FLUID_FREE(dev); + FLUID_FREE(dev); } /* * fluid_midishare_midi_driver_status */ -int fluid_midishare_midi_driver_status(fluid_midi_driver_t* p) +int fluid_midishare_midi_driver_status(fluid_midi_driver_t *p) { - fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*) p; - return dev->status; + fluid_midishare_midi_driver_t *dev = (fluid_midishare_midi_driver_t *) p; + return dev->status; } /* * fluid_midishare_keyoff_task */ -static void fluid_midishare_keyoff_task (long date, short ref, long a1, long a2, long a3) +static void fluid_midishare_keyoff_task(long date, short ref, long a1, long a2, long a3) { - fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref); - fluid_midi_event_t new_event; - MidiEvPtr e =(MidiEvPtr)a1; + fluid_midishare_midi_driver_t *dev = (fluid_midishare_midi_driver_t *)MidiGetInfo(ref); + fluid_midi_event_t new_event; + MidiEvPtr e = (MidiEvPtr)a1; - fluid_midi_event_set_type(&new_event, NOTE_OFF); - fluid_midi_event_set_channel(&new_event, Chan(e)); - fluid_midi_event_set_pitch(&new_event, Pitch(e)); - fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */ + fluid_midi_event_set_type(&new_event, NOTE_OFF); + fluid_midi_event_set_channel(&new_event, Chan(e)); + fluid_midi_event_set_pitch(&new_event, Pitch(e)); + fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */ - /* and send it on its way to the router */ - (*dev->driver.handler)(dev->driver.data, &new_event); + /* and send it on its way to the router */ + (*dev->driver.handler)(dev->driver.data, &new_event); - MidiFreeEv(e); + MidiFreeEv(e); } @@ -218,101 +240,103 @@ static void fluid_midishare_keyoff_task (long date, short ref, long a1, long a2, */ static void fluid_midishare_midi_driver_receive(short ref) { - fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref); - fluid_midi_event_t new_event; - MidiEvPtr e; - int count, i; + fluid_midishare_midi_driver_t *dev = (fluid_midishare_midi_driver_t *)MidiGetInfo(ref); + fluid_midi_event_t new_event; + MidiEvPtr e; + int count, i; - while ((e = MidiGetEv (ref))) - { - switch (EvType (e)) + while((e = MidiGetEv(ref))) { - case typeNote: - /* Copy the data to fluid_midi_event_t */ - fluid_midi_event_set_type(&new_event, NOTE_ON); - fluid_midi_event_set_channel(&new_event, Chan(e)); - fluid_midi_event_set_pitch(&new_event, Pitch(e)); - fluid_midi_event_set_velocity(&new_event, Vel(e)); + switch(EvType(e)) + { + case typeNote: + /* Copy the data to fluid_midi_event_t */ + fluid_midi_event_set_type(&new_event, NOTE_ON); + fluid_midi_event_set_channel(&new_event, Chan(e)); + fluid_midi_event_set_pitch(&new_event, Pitch(e)); + fluid_midi_event_set_velocity(&new_event, Vel(e)); - /* and send it on its way to the router */ - (*dev->driver.handler)(dev->driver.data, &new_event); + /* and send it on its way to the router */ + (*dev->driver.handler)(dev->driver.data, &new_event); #if defined(MACINTOSH) && defined(MACOS9) - MidiTask(dev->upp_task_ptr, MidiGetTime()+Dur(e), ref, (long)e, 0, 0); + MidiTask(dev->upp_task_ptr, MidiGetTime() + Dur(e), ref, (long)e, 0, 0); #else - MidiTask(fluid_midishare_keyoff_task, MidiGetTime()+Dur(e), ref, (long)e, 0, 0); + MidiTask(fluid_midishare_keyoff_task, MidiGetTime() + Dur(e), ref, (long)e, 0, 0); #endif - /* e gets freed in fluid_midishare_keyoff_task */ - continue; + /* e gets freed in fluid_midishare_keyoff_task */ + continue; - case typeKeyOn: - /* Copy the data to fluid_midi_event_t */ - fluid_midi_event_set_type(&new_event, NOTE_ON); - fluid_midi_event_set_channel(&new_event, Chan(e)); - fluid_midi_event_set_pitch(&new_event, Pitch(e)); - fluid_midi_event_set_velocity(&new_event, Vel(e)); - break; + case typeKeyOn: + /* Copy the data to fluid_midi_event_t */ + fluid_midi_event_set_type(&new_event, NOTE_ON); + fluid_midi_event_set_channel(&new_event, Chan(e)); + fluid_midi_event_set_pitch(&new_event, Pitch(e)); + fluid_midi_event_set_velocity(&new_event, Vel(e)); + break; - case typeKeyOff: - /* Copy the data to fluid_midi_event_t */ - fluid_midi_event_set_type(&new_event, NOTE_OFF); - fluid_midi_event_set_channel(&new_event, Chan(e)); - fluid_midi_event_set_pitch(&new_event, Pitch(e)); - fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */ - break; + case typeKeyOff: + /* Copy the data to fluid_midi_event_t */ + fluid_midi_event_set_type(&new_event, NOTE_OFF); + fluid_midi_event_set_channel(&new_event, Chan(e)); + fluid_midi_event_set_pitch(&new_event, Pitch(e)); + fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */ + break; - case typeCtrlChange: - /* Copy the data to fluid_midi_event_t */ - fluid_midi_event_set_type(&new_event, CONTROL_CHANGE); - fluid_midi_event_set_channel(&new_event, Chan(e)); - fluid_midi_event_set_control(&new_event, MidiGetField(e,0)); - fluid_midi_event_set_value(&new_event, MidiGetField(e,1)); - break; + case typeCtrlChange: + /* Copy the data to fluid_midi_event_t */ + fluid_midi_event_set_type(&new_event, CONTROL_CHANGE); + fluid_midi_event_set_channel(&new_event, Chan(e)); + fluid_midi_event_set_control(&new_event, MidiGetField(e, 0)); + fluid_midi_event_set_value(&new_event, MidiGetField(e, 1)); + break; - case typeProgChange: - /* Copy the data to fluid_midi_event_t */ - fluid_midi_event_set_type(&new_event, PROGRAM_CHANGE); - fluid_midi_event_set_channel(&new_event, Chan(e)); - fluid_midi_event_set_program(&new_event, MidiGetField(e,0)); - break; + case typeProgChange: + /* Copy the data to fluid_midi_event_t */ + fluid_midi_event_set_type(&new_event, PROGRAM_CHANGE); + fluid_midi_event_set_channel(&new_event, Chan(e)); + fluid_midi_event_set_program(&new_event, MidiGetField(e, 0)); + break; - case typePitchWheel: - /* Copy the data to fluid_midi_event_t */ - fluid_midi_event_set_type(&new_event, PITCH_BEND); - fluid_midi_event_set_channel(&new_event, Chan(e)); - fluid_midi_event_set_value(&new_event, ((MidiGetField(e,0) - + (MidiGetField(e,1) << 7)) - - 8192)); - break; + case typePitchWheel: + /* Copy the data to fluid_midi_event_t */ + fluid_midi_event_set_type(&new_event, PITCH_BEND); + fluid_midi_event_set_channel(&new_event, Chan(e)); + fluid_midi_event_set_value(&new_event, ((MidiGetField(e, 0) + + (MidiGetField(e, 1) << 7)) + - 8192)); + break; - case typeSysEx: - count = MidiCountFields (e); + case typeSysEx: + count = MidiCountFields(e); - /* Discard empty or too large SYSEX messages */ - if (count == 0 || count > FLUID_MIDI_PARSER_MAX_DATA_SIZE) - { - MidiFreeEv (e); - continue; + /* Discard empty or too large SYSEX messages */ + if(count == 0 || count > FLUID_MIDI_PARSER_MAX_DATA_SIZE) + { + MidiFreeEv(e); + continue; + } + + /* Copy SYSEX data, one byte at a time */ + for(i = 0; i < count; i++) + { + dev->sysexbuf[i] = MidiGetField(e, i); + } + + fluid_midi_event_set_sysex(&new_event, dev->sysexbuf, count, FALSE); + break; + + default: + MidiFreeEv(e); + continue; } - /* Copy SYSEX data, one byte at a time */ - for (i = 0; i < count; i++) - dev->sysexbuf[i] = MidiGetField (e, i); + MidiFreeEv(e); - fluid_midi_event_set_sysex (&new_event, dev->sysexbuf, count, FALSE); - break; - - default: - MidiFreeEv (e); - continue; + /* Send the MIDI event */ + (*dev->driver.handler)(dev->driver.data, &new_event); } - - MidiFreeEv (e); - - /* Send the MIDI event */ - (*dev->driver.handler)(dev->driver.data, &new_event); - } } @@ -321,61 +345,70 @@ static void fluid_midishare_midi_driver_receive(short ref) /* * fluid_midishare_wakeup */ -static void fluid_midishare_wakeup (short r) +static void fluid_midishare_wakeup(short r) { - MidiConnect (MidiShareDrvRef, r, true); - MidiConnect (r, MidiShareDrvRef, true); + MidiConnect(MidiShareDrvRef, r, true); + MidiConnect(r, MidiShareDrvRef, true); } /* * fluid_midishare_sleep */ -static void fluid_midishare_sleep (short r){} +static void fluid_midishare_sleep(short r) {} /* * fluid_midishare_open_driver */ -static int fluid_midishare_open_driver (fluid_midishare_midi_driver_t* dev) +static int fluid_midishare_open_driver(fluid_midishare_midi_driver_t *dev) { - /* gcc wanted me to use {0,0} to initialize the reserved[2] fields */ - TDriverInfos infos = { MSHDriverName, 100, 0, { 0, 0 } }; - TDriverOperation op = { fluid_midishare_wakeup, fluid_midishare_sleep, { 0, 0, 0 } }; + /* gcc wanted me to use {0,0} to initialize the reserved[2] fields */ + TDriverInfos infos = { MSHDriverName, 100, 0, { 0, 0 } }; + TDriverOperation op = { fluid_midishare_wakeup, fluid_midishare_sleep, { 0, 0, 0 } }; - /* register to MidiShare */ - #if defined(MACINTOSH) && defined(MACOS9) - dev->upp_wakeup_ptr = NewDriverPtr(fluid_midishare_wakeup); - dev->upp_sleep_ptr = NewDriverPtr(fluid_midishare_sleep); + /* register to MidiShare */ +#if defined(MACINTOSH) && defined(MACOS9) + dev->upp_wakeup_ptr = NewDriverPtr(fluid_midishare_wakeup); + dev->upp_sleep_ptr = NewDriverPtr(fluid_midishare_sleep); - op.wakeup = (WakeupPtr)dev->upp_wakeup_ptr; - op.sleep = (SleepPtr)dev->upp_sleep_ptr; + op.wakeup = (WakeupPtr)dev->upp_wakeup_ptr; + op.sleep = (SleepPtr)dev->upp_sleep_ptr; - dev->refnum = MidiRegisterDriver(&infos, &op); - if (dev->refnum < 0) { - FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client"); - return 0; - } - dev->slotRef = MidiAddSlot (dev->refnum, MSHSlotName, MidiOutputSlot); - dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive); - dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task); - MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr); - #else - dev->refnum = MidiRegisterDriver(&infos, &op); - if (dev->refnum < 0) { - FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client"); - return 0; - } - dev->slotRef = MidiAddSlot (dev->refnum, MSHSlotName, MidiOutputSlot); - MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive); - #endif - return 1; + dev->refnum = MidiRegisterDriver(&infos, &op); + + if(dev->refnum < 0) + { + FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client"); + return 0; + } + + dev->slotRef = MidiAddSlot(dev->refnum, MSHSlotName, MidiOutputSlot); + dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive); + dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task); + MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr); +#else + dev->refnum = MidiRegisterDriver(&infos, &op); + + if(dev->refnum < 0) + { + FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client"); + return 0; + } + + dev->slotRef = MidiAddSlot(dev->refnum, MSHSlotName, MidiOutputSlot); + MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive); +#endif + return 1; } /* * fluid_midishare_close_driver */ -static void fluid_midishare_close_driver (fluid_midishare_midi_driver_t* dev) +static void fluid_midishare_close_driver(fluid_midishare_midi_driver_t *dev) { - if (dev->refnum > 0) MidiUnregisterDriver(dev->refnum); + if(dev->refnum > 0) + { + MidiUnregisterDriver(dev->refnum); + } } #else /* #if defined(MIDISHARE_DRIVER) */ @@ -383,36 +416,45 @@ static void fluid_midishare_close_driver (fluid_midishare_midi_driver_t* dev) /* * fluid_midishare_open_appl */ -static int fluid_midishare_open_appl (fluid_midishare_midi_driver_t* dev) +static int fluid_midishare_open_appl(fluid_midishare_midi_driver_t *dev) { - /* register to MidiShare */ - #if defined(MACINTOSH) && defined(MACOS9) - dev->refnum = MidiOpen(MSHDriverName); - if (dev->refnum < 0) { - FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client"); - return 0; - } - dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive); - dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task); - MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr); - #else - dev->refnum = MidiOpen(MSHDriverName); - if (dev->refnum < 0) { - FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client"); - return 0; - } - MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive); - MidiConnect(0,dev->refnum,true); - #endif - return 1; + /* register to MidiShare */ +#if defined(MACINTOSH) && defined(MACOS9) + dev->refnum = MidiOpen(MSHDriverName); + + if(dev->refnum < 0) + { + FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client"); + return 0; + } + + dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive); + dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task); + MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr); +#else + dev->refnum = MidiOpen(MSHDriverName); + + if(dev->refnum < 0) + { + FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client"); + return 0; + } + + MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive); + MidiConnect(0, dev->refnum, true); +#endif + return 1; } /* * fluid_midishare_close_appl */ -static void fluid_midishare_close_appl (fluid_midishare_midi_driver_t* dev) +static void fluid_midishare_close_appl(fluid_midishare_midi_driver_t *dev) { - if (dev->refnum > 0) MidiClose(dev->refnum); + if(dev->refnum > 0) + { + MidiClose(dev->refnum); + } } #endif /* #if defined(MIDISHARE_DRIVER) */ diff --git a/src/drivers/fluid_oss.c b/src/drivers/fluid_oss.c index 0fdad174..36f7f8cc 100644 --- a/src/drivers/fluid_oss.c +++ b/src/drivers/fluid_oss.c @@ -46,7 +46,7 @@ // Build issue on some systems (OSS 4.0)? #if !defined(SOUND_PCM_WRITE_CHANNELS) && defined(SNDCTL_DSP_CHANNELS) - #define SOUND_PCM_WRITE_CHANNELS SNDCTL_DSP_CHANNELS +#define SOUND_PCM_WRITE_CHANNELS SNDCTL_DSP_CHANNELS #endif /** fluid_oss_audio_driver_t @@ -54,337 +54,415 @@ * This structure should not be accessed directly. Use audio port * functions instead. */ -typedef struct { - fluid_audio_driver_t driver; - fluid_synth_t* synth; - fluid_audio_callback_t read; - void* buffer; - fluid_thread_t *thread; - int cont; - int dspfd; - int buffer_size; - int buffer_byte_size; - int bigendian; - int formats; - int format; - int caps; - fluid_audio_func_t callback; - void* data; - float* buffers[2]; +typedef struct +{ + fluid_audio_driver_t driver; + fluid_synth_t *synth; + fluid_audio_callback_t read; + void *buffer; + fluid_thread_t *thread; + int cont; + int dspfd; + int buffer_size; + int buffer_byte_size; + int bigendian; + int formats; + int format; + int caps; + fluid_audio_func_t callback; + void *data; + float *buffers[2]; } fluid_oss_audio_driver_t; -void delete_fluid_oss_audio_driver(fluid_audio_driver_t* p); +void delete_fluid_oss_audio_driver(fluid_audio_driver_t *p); /* local utilities */ -static int fluid_oss_set_queue_size(fluid_oss_audio_driver_t* dev, int ss, int ch, int qs, int bs); -static fluid_thread_return_t fluid_oss_audio_run(void* d); -static fluid_thread_return_t fluid_oss_audio_run2(void* d); +static int fluid_oss_set_queue_size(fluid_oss_audio_driver_t *dev, int ss, int ch, int qs, int bs); +static fluid_thread_return_t fluid_oss_audio_run(void *d); +static fluid_thread_return_t fluid_oss_audio_run2(void *d); -typedef struct { - fluid_midi_driver_t driver; - int fd; - fluid_thread_t *thread; - int status; - unsigned char buffer[BUFFER_LENGTH]; - fluid_midi_parser_t* parser; +typedef struct +{ + fluid_midi_driver_t driver; + int fd; + fluid_thread_t *thread; + int status; + unsigned char buffer[BUFFER_LENGTH]; + fluid_midi_parser_t *parser; } fluid_oss_midi_driver_t; -fluid_midi_driver_t* -new_fluid_oss_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, void* data); -void delete_fluid_oss_midi_driver(fluid_midi_driver_t* p); -int fluid_oss_midi_driver_status(fluid_midi_driver_t* p); -static fluid_thread_return_t fluid_oss_midi_run(void* d); +fluid_midi_driver_t * +new_fluid_oss_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data); +void delete_fluid_oss_midi_driver(fluid_midi_driver_t *p); +int fluid_oss_midi_driver_status(fluid_midi_driver_t *p); +static fluid_thread_return_t fluid_oss_midi_run(void *d); void -fluid_oss_audio_driver_settings(fluid_settings_t* settings) +fluid_oss_audio_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "audio.oss.device", "/dev/dsp", 0); + fluid_settings_register_str(settings, "audio.oss.device", "/dev/dsp", 0); } /* * new_fluid_oss_audio_driver */ -fluid_audio_driver_t* -new_fluid_oss_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_oss_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) { - fluid_oss_audio_driver_t* dev = NULL; - int channels, sr, sample_size = 0, oss_format; - struct stat devstat; - int queuesize; - double sample_rate; - int periods, period_size; - int realtime_prio = 0; - char* devname = NULL; - int format; + fluid_oss_audio_driver_t *dev = NULL; + int channels, sr, sample_size = 0, oss_format; + struct stat devstat; + int queuesize; + double sample_rate; + int periods, period_size; + int realtime_prio = 0; + char *devname = NULL; + int format; - dev = FLUID_NEW(fluid_oss_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_oss_audio_driver_t)); + dev = FLUID_NEW(fluid_oss_audio_driver_t); - fluid_settings_getint(settings, "audio.periods", &periods); - fluid_settings_getint(settings, "audio.period-size", &period_size); - fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); - fluid_settings_getint (settings, "audio.realtime-prio", &realtime_prio); - - dev->dspfd = -1; - dev->synth = synth; - dev->callback = NULL; - dev->data = NULL; - dev->cont = 1; - dev->buffer_size = (int) period_size; - queuesize = (int) (periods * period_size); - - if (fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) { - sample_size = 16; - oss_format = AFMT_S16_LE; - dev->read = fluid_synth_write_s16; - dev->buffer_byte_size = dev->buffer_size * 4; - - } else if (fluid_settings_str_equal(settings, "audio.sample-format", "float")) { - sample_size = 32; - oss_format = -1; - dev->read = fluid_synth_write_float; - dev->buffer_byte_size = dev->buffer_size * 8; - - } else { - FLUID_LOG(FLUID_ERR, "Unknown sample format"); - goto error_recovery; - } - - dev->buffer = FLUID_MALLOC(dev->buffer_byte_size); - if (dev->buffer == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } - - if (fluid_settings_dupstr(settings, "audio.oss.device", &devname) != FLUID_OK || !devname) { /* ++ alloc device name */ - devname = FLUID_STRDUP ("/dev/dsp"); - - if (devname == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - } - if (stat(devname, &devstat) == -1) { - FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname); - goto error_recovery; - } - if ((devstat.st_mode & S_IFCHR) != S_IFCHR) { - FLUID_LOG(FLUID_ERR, "Device <%s> is not a device file", devname); - goto error_recovery; - } + FLUID_MEMSET(dev, 0, sizeof(fluid_oss_audio_driver_t)); - dev->dspfd = open(devname, O_WRONLY, 0); + fluid_settings_getint(settings, "audio.periods", &periods); + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_getint(settings, "audio.realtime-prio", &realtime_prio); - if (dev->dspfd == -1) { - FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s", - devname, strerror(errno)); - goto error_recovery; - } + dev->dspfd = -1; + dev->synth = synth; + dev->callback = NULL; + dev->data = NULL; + dev->cont = 1; + dev->buffer_size = (int) period_size; + queuesize = (int)(periods * period_size); - if (fluid_oss_set_queue_size(dev, sample_size, 2, queuesize, period_size) < 0) { - FLUID_LOG(FLUID_ERR, "Can't set device buffer size"); - goto error_recovery; - } + if(fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) + { + sample_size = 16; + oss_format = AFMT_S16_LE; + dev->read = fluid_synth_write_s16; + dev->buffer_byte_size = dev->buffer_size * 4; - format = oss_format; - if (ioctl(dev->dspfd, SNDCTL_DSP_SETFMT, &oss_format) < 0) { - FLUID_LOG(FLUID_ERR, "Can't set the sample format"); - goto error_recovery; - } - if (oss_format != format) { - FLUID_LOG(FLUID_ERR, "Can't set the sample format"); - goto error_recovery; - } + } + else if(fluid_settings_str_equal(settings, "audio.sample-format", "float")) + { + sample_size = 32; + oss_format = -1; + dev->read = fluid_synth_write_float; + dev->buffer_byte_size = dev->buffer_size * 8; - channels = 2; - if (ioctl(dev->dspfd, SOUND_PCM_WRITE_CHANNELS, &channels) < 0){ - FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); - goto error_recovery; - } - if (channels != 2) { - FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); - goto error_recovery; - } + } + else + { + FLUID_LOG(FLUID_ERR, "Unknown sample format"); + goto error_recovery; + } - sr = sample_rate; - if (ioctl(dev->dspfd, SNDCTL_DSP_SPEED, &sr) < 0){ - FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); - goto error_recovery; - } - if ((sr < 0.95 * sample_rate) || - (sr > 1.05 * sample_rate)) { - FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); - goto error_recovery; - } + dev->buffer = FLUID_MALLOC(dev->buffer_byte_size); - /* Create the audio thread */ - dev->thread = new_fluid_thread ("oss-audio", fluid_oss_audio_run, dev, realtime_prio, FALSE); + if(dev->buffer == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } - if (!dev->thread) - goto error_recovery; + if(fluid_settings_dupstr(settings, "audio.oss.device", &devname) != FLUID_OK || !devname) /* ++ alloc device name */ + { + devname = FLUID_STRDUP("/dev/dsp"); - if (devname) FLUID_FREE (devname); /* -- free device name */ + if(devname == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + } - return (fluid_audio_driver_t*) dev; + if(stat(devname, &devstat) == -1) + { + FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname); + goto error_recovery; + } + + if((devstat.st_mode & S_IFCHR) != S_IFCHR) + { + FLUID_LOG(FLUID_ERR, "Device <%s> is not a device file", devname); + goto error_recovery; + } + + dev->dspfd = open(devname, O_WRONLY, 0); + + if(dev->dspfd == -1) + { + FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s", + devname, strerror(errno)); + goto error_recovery; + } + + if(fluid_oss_set_queue_size(dev, sample_size, 2, queuesize, period_size) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set device buffer size"); + goto error_recovery; + } + + format = oss_format; + + if(ioctl(dev->dspfd, SNDCTL_DSP_SETFMT, &oss_format) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample format"); + goto error_recovery; + } + + if(oss_format != format) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample format"); + goto error_recovery; + } + + channels = 2; + + if(ioctl(dev->dspfd, SOUND_PCM_WRITE_CHANNELS, &channels) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); + goto error_recovery; + } + + if(channels != 2) + { + FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); + goto error_recovery; + } + + sr = sample_rate; + + if(ioctl(dev->dspfd, SNDCTL_DSP_SPEED, &sr) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); + goto error_recovery; + } + + if((sr < 0.95 * sample_rate) || + (sr > 1.05 * sample_rate)) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); + goto error_recovery; + } + + /* Create the audio thread */ + dev->thread = new_fluid_thread("oss-audio", fluid_oss_audio_run, dev, realtime_prio, FALSE); + + if(!dev->thread) + { + goto error_recovery; + } + + if(devname) + { + FLUID_FREE(devname); /* -- free device name */ + } + + return (fluid_audio_driver_t *) dev; error_recovery: - if (devname) FLUID_FREE (devname); /* -- free device name */ - delete_fluid_oss_audio_driver((fluid_audio_driver_t*) dev); - return NULL; + + if(devname) + { + FLUID_FREE(devname); /* -- free device name */ + } + + delete_fluid_oss_audio_driver((fluid_audio_driver_t *) dev); + return NULL; } -fluid_audio_driver_t* -new_fluid_oss_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data) +fluid_audio_driver_t * +new_fluid_oss_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data) { - fluid_oss_audio_driver_t* dev = NULL; - int channels, sr; - struct stat devstat; - int queuesize; - double sample_rate; - int periods, period_size; - char* devname = NULL; - int realtime_prio = 0; - int format; + fluid_oss_audio_driver_t *dev = NULL; + int channels, sr; + struct stat devstat; + int queuesize; + double sample_rate; + int periods, period_size; + char *devname = NULL; + int realtime_prio = 0; + int format; - dev = FLUID_NEW(fluid_oss_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_oss_audio_driver_t)); + dev = FLUID_NEW(fluid_oss_audio_driver_t); - fluid_settings_getint(settings, "audio.periods", &periods); - fluid_settings_getint(settings, "audio.period-size", &period_size); - fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); - fluid_settings_getint (settings, "audio.realtime-prio", &realtime_prio); - - dev->dspfd = -1; - dev->synth = NULL; - dev->read = NULL; - dev->callback = func; - dev->data = data; - dev->cont = 1; - dev->buffer_size = (int) period_size; - queuesize = (int) (periods * period_size); - dev->buffer_byte_size = dev->buffer_size * 2 * 2; /* 2 channels * 16 bits audio */ - - - if (fluid_settings_dupstr(settings, "audio.oss.device", &devname) != FLUID_OK || !devname) { - devname = FLUID_STRDUP ("/dev/dsp"); - - if (!devname) + if(dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - } - if (stat(devname, &devstat) == -1) { - FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname); - goto error_recovery; - } - if ((devstat.st_mode & S_IFCHR) != S_IFCHR) { - FLUID_LOG(FLUID_ERR, "Device <%s> is not a device file", devname); - goto error_recovery; - } + FLUID_MEMSET(dev, 0, sizeof(fluid_oss_audio_driver_t)); - dev->dspfd = open(devname, O_WRONLY, 0); - if (dev->dspfd == -1) { - FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s", - devname, strerror(errno)); - goto error_recovery; - } + fluid_settings_getint(settings, "audio.periods", &periods); + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_getint(settings, "audio.realtime-prio", &realtime_prio); + + dev->dspfd = -1; + dev->synth = NULL; + dev->read = NULL; + dev->callback = func; + dev->data = data; + dev->cont = 1; + dev->buffer_size = (int) period_size; + queuesize = (int)(periods * period_size); + dev->buffer_byte_size = dev->buffer_size * 2 * 2; /* 2 channels * 16 bits audio */ - if (fluid_oss_set_queue_size(dev, 16, 2, queuesize, period_size) < 0) { - FLUID_LOG(FLUID_ERR, "Can't set device buffer size"); - goto error_recovery; - } + if(fluid_settings_dupstr(settings, "audio.oss.device", &devname) != FLUID_OK || !devname) + { + devname = FLUID_STRDUP("/dev/dsp"); - format = AFMT_S16_LE; - if (ioctl(dev->dspfd, SNDCTL_DSP_SETFMT, &format) < 0) { - FLUID_LOG(FLUID_ERR, "Can't set the sample format"); - goto error_recovery; - } - if (format != AFMT_S16_LE) { - FLUID_LOG(FLUID_ERR, "Can't set the sample format"); - goto error_recovery; - } + if(!devname) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + } - channels = 2; - if (ioctl(dev->dspfd, SOUND_PCM_WRITE_CHANNELS, &channels) < 0){ - FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); - goto error_recovery; - } - if (channels != 2) { - FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); - goto error_recovery; - } + if(stat(devname, &devstat) == -1) + { + FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname); + goto error_recovery; + } - sr = sample_rate; - if (ioctl(dev->dspfd, SNDCTL_DSP_SPEED, &sr) < 0){ - FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); - goto error_recovery; - } - if ((sr < 0.95 * sample_rate) || - (sr > 1.05 * sample_rate)) { - FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); - goto error_recovery; - } + if((devstat.st_mode & S_IFCHR) != S_IFCHR) + { + FLUID_LOG(FLUID_ERR, "Device <%s> is not a device file", devname); + goto error_recovery; + } - /* allocate the buffers. FIXME!!! don't use interleaved samples */ - dev->buffer = FLUID_MALLOC(dev->buffer_byte_size); - dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size); - dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size); - if ((dev->buffer == NULL) || (dev->buffers[0] == NULL) || (dev->buffers[1] == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } + dev->dspfd = open(devname, O_WRONLY, 0); - /* Create the audio thread */ - dev->thread = new_fluid_thread ("oss-audio", fluid_oss_audio_run2, dev, realtime_prio, FALSE); + if(dev->dspfd == -1) + { + FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s", + devname, strerror(errno)); + goto error_recovery; + } - if (!dev->thread) - goto error_recovery; - if (devname) FLUID_FREE (devname); /* -- free device name */ + if(fluid_oss_set_queue_size(dev, 16, 2, queuesize, period_size) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set device buffer size"); + goto error_recovery; + } - return (fluid_audio_driver_t*) dev; + format = AFMT_S16_LE; + + if(ioctl(dev->dspfd, SNDCTL_DSP_SETFMT, &format) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample format"); + goto error_recovery; + } + + if(format != AFMT_S16_LE) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample format"); + goto error_recovery; + } + + channels = 2; + + if(ioctl(dev->dspfd, SOUND_PCM_WRITE_CHANNELS, &channels) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); + goto error_recovery; + } + + if(channels != 2) + { + FLUID_LOG(FLUID_ERR, "Can't set the number of channels"); + goto error_recovery; + } + + sr = sample_rate; + + if(ioctl(dev->dspfd, SNDCTL_DSP_SPEED, &sr) < 0) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); + goto error_recovery; + } + + if((sr < 0.95 * sample_rate) || + (sr > 1.05 * sample_rate)) + { + FLUID_LOG(FLUID_ERR, "Can't set the sample rate"); + goto error_recovery; + } + + /* allocate the buffers. FIXME!!! don't use interleaved samples */ + dev->buffer = FLUID_MALLOC(dev->buffer_byte_size); + dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size); + dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size); + + if((dev->buffer == NULL) || (dev->buffers[0] == NULL) || (dev->buffers[1] == NULL)) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + /* Create the audio thread */ + dev->thread = new_fluid_thread("oss-audio", fluid_oss_audio_run2, dev, realtime_prio, FALSE); + + if(!dev->thread) + { + goto error_recovery; + } + + if(devname) + { + FLUID_FREE(devname); /* -- free device name */ + } + + return (fluid_audio_driver_t *) dev; error_recovery: - if (devname) FLUID_FREE (devname); /* -- free device name */ - delete_fluid_oss_audio_driver((fluid_audio_driver_t*) dev); - return NULL; + + if(devname) + { + FLUID_FREE(devname); /* -- free device name */ + } + + delete_fluid_oss_audio_driver((fluid_audio_driver_t *) dev); + return NULL; } /* * delete_fluid_oss_audio_driver */ void -delete_fluid_oss_audio_driver(fluid_audio_driver_t* p) +delete_fluid_oss_audio_driver(fluid_audio_driver_t *p) { - fluid_oss_audio_driver_t* dev = (fluid_oss_audio_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_oss_audio_driver_t *dev = (fluid_oss_audio_driver_t *) p; + fluid_return_if_fail(dev != NULL); - dev->cont = 0; + dev->cont = 0; - if (dev->thread) - fluid_thread_join (dev->thread); + if(dev->thread) + { + fluid_thread_join(dev->thread); + } - if (dev->dspfd >= 0) { - close(dev->dspfd); - } - - FLUID_FREE(dev->buffer); - FLUID_FREE(dev); + if(dev->dspfd >= 0) + { + close(dev->dspfd); + } + + FLUID_FREE(dev->buffer); + FLUID_FREE(dev); } /** @@ -398,68 +476,76 @@ delete_fluid_oss_audio_driver(fluid_audio_driver_t* p) * @param bs The synthesis buffer size in frames */ int -fluid_oss_set_queue_size(fluid_oss_audio_driver_t* dev, int ss, int ch, int qs, int bs) +fluid_oss_set_queue_size(fluid_oss_audio_driver_t *dev, int ss, int ch, int qs, int bs) { - unsigned int fragmentSize; - unsigned int fragSizePower; - unsigned int fragments; - unsigned int fragmentsPower; + unsigned int fragmentSize; + unsigned int fragSizePower; + unsigned int fragments; + unsigned int fragmentsPower; - fragmentSize = (unsigned int) (bs * ch * ss / 8); + fragmentSize = (unsigned int)(bs * ch * ss / 8); - fragSizePower = 0; - while (0 < fragmentSize) { - fragmentSize = (fragmentSize >> 1); - fragSizePower++; - } - fragSizePower--; + fragSizePower = 0; - fragments = (unsigned int) (qs / bs); - if (fragments < 2) { - fragments = 2; - } + while(0 < fragmentSize) + { + fragmentSize = (fragmentSize >> 1); + fragSizePower++; + } - /* make sure fragments is a power of 2 */ - fragmentsPower = 0; - while (0 < fragments) { - fragments = (fragments >> 1); - fragmentsPower++; - } - fragmentsPower--; + fragSizePower--; - fragments = (1 << fragmentsPower); - fragments = (fragments << 16) + fragSizePower; + fragments = (unsigned int)(qs / bs); - return ioctl(dev->dspfd, SNDCTL_DSP_SETFRAGMENT, &fragments); + if(fragments < 2) + { + fragments = 2; + } + + /* make sure fragments is a power of 2 */ + fragmentsPower = 0; + + while(0 < fragments) + { + fragments = (fragments >> 1); + fragmentsPower++; + } + + fragmentsPower--; + + fragments = (1 << fragmentsPower); + fragments = (fragments << 16) + fragSizePower; + + return ioctl(dev->dspfd, SNDCTL_DSP_SETFRAGMENT, &fragments); } /* * fluid_oss_audio_run */ fluid_thread_return_t -fluid_oss_audio_run(void* d) +fluid_oss_audio_run(void *d) { - fluid_oss_audio_driver_t* dev = (fluid_oss_audio_driver_t*) d; - fluid_synth_t* synth = dev->synth; - void* buffer = dev->buffer; - int len = dev->buffer_size; + fluid_oss_audio_driver_t *dev = (fluid_oss_audio_driver_t *) d; + fluid_synth_t *synth = dev->synth; + void *buffer = dev->buffer; + int len = dev->buffer_size; - /* it's as simple as that: */ - while (dev->cont) - { - dev->read (synth, len, buffer, 0, 2, buffer, 1, 2); - - if (write (dev->dspfd, buffer, dev->buffer_byte_size) < 0) + /* it's as simple as that: */ + while(dev->cont) { - FLUID_LOG(FLUID_ERR, "Error writing to OSS sound device: %s", - g_strerror (errno)); - break; + dev->read(synth, len, buffer, 0, 2, buffer, 1, 2); + + if(write(dev->dspfd, buffer, dev->buffer_byte_size) < 0) + { + FLUID_LOG(FLUID_ERR, "Error writing to OSS sound device: %s", + g_strerror(errno)); + break; + } } - } - FLUID_LOG(FLUID_DBG, "Audio thread finished"); + FLUID_LOG(FLUID_DBG, "Audio thread finished"); - return FLUID_THREAD_RETURN_VALUE; + return FLUID_THREAD_RETURN_VALUE; } @@ -467,209 +553,242 @@ fluid_oss_audio_run(void* d) * fluid_oss_audio_run */ fluid_thread_return_t -fluid_oss_audio_run2(void* d) +fluid_oss_audio_run2(void *d) { - fluid_oss_audio_driver_t* dev = (fluid_oss_audio_driver_t*) d; - short* buffer = (short*) dev->buffer; - float* left = dev->buffers[0]; - float* right = dev->buffers[1]; - int buffer_size = dev->buffer_size; - int dither_index = 0; + fluid_oss_audio_driver_t *dev = (fluid_oss_audio_driver_t *) d; + short *buffer = (short *) dev->buffer; + float *left = dev->buffers[0]; + float *right = dev->buffers[1]; + int buffer_size = dev->buffer_size; + int dither_index = 0; - FLUID_LOG(FLUID_DBG, "Audio thread running"); + FLUID_LOG(FLUID_DBG, "Audio thread running"); - /* it's as simple as that: */ - while (dev->cont) - { - (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->buffers); - - fluid_synth_dither_s16 (&dither_index, buffer_size, left, right, - buffer, 0, 2, buffer, 1, 2); - - if (write (dev->dspfd, buffer, dev->buffer_byte_size) < 0) + /* it's as simple as that: */ + while(dev->cont) { - FLUID_LOG(FLUID_ERR, "Error writing to OSS sound device: %s", - g_strerror (errno)); - break; + (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->buffers); + + fluid_synth_dither_s16(&dither_index, buffer_size, left, right, + buffer, 0, 2, buffer, 1, 2); + + if(write(dev->dspfd, buffer, dev->buffer_byte_size) < 0) + { + FLUID_LOG(FLUID_ERR, "Error writing to OSS sound device: %s", + g_strerror(errno)); + break; + } } - } - FLUID_LOG(FLUID_DBG, "Audio thread finished"); + FLUID_LOG(FLUID_DBG, "Audio thread finished"); - return FLUID_THREAD_RETURN_VALUE; + return FLUID_THREAD_RETURN_VALUE; } -void fluid_oss_midi_driver_settings(fluid_settings_t* settings) +void fluid_oss_midi_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "midi.oss.device", "/dev/midi", 0); + fluid_settings_register_str(settings, "midi.oss.device", "/dev/midi", 0); } /* * new_fluid_oss_midi_driver */ -fluid_midi_driver_t* -new_fluid_oss_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, void* data) +fluid_midi_driver_t * +new_fluid_oss_midi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data) { - fluid_oss_midi_driver_t* dev; - int realtime_prio = 0; - char* device = NULL; + fluid_oss_midi_driver_t *dev; + int realtime_prio = 0; + char *device = NULL; - /* not much use doing anything */ - if (handler == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid argument"); - return NULL; - } - - /* allocate the device */ - dev = FLUID_NEW(fluid_oss_midi_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_oss_midi_driver_t)); - dev->fd = -1; - - dev->driver.handler = handler; - dev->driver.data = data; - - /* allocate one event to store the input data */ - dev->parser = new_fluid_midi_parser(); - if (dev->parser == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } - - /* get the device name. if none is specified, use the default device. */ - fluid_settings_dupstr(settings, "midi.oss.device", &device); /* ++ alloc device name */ - - if (device == NULL) { - device = FLUID_STRDUP ("/dev/midi"); - - if (!device) + /* not much use doing anything */ + if(handler == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; + FLUID_LOG(FLUID_ERR, "Invalid argument"); + return NULL; } - } - fluid_settings_getint (settings, "midi.realtime-prio", &realtime_prio); + /* allocate the device */ + dev = FLUID_NEW(fluid_oss_midi_driver_t); - /* open the default hardware device. only use midi in. */ - dev->fd = open(device, O_RDONLY, 0); - if (dev->fd < 0) { - perror(device); - goto error_recovery; - } + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - if (fcntl (dev->fd, F_SETFL, O_NONBLOCK) == -1) - { - FLUID_LOG(FLUID_ERR, "Failed to set OSS MIDI device to non-blocking: %s", - strerror (errno)); - goto error_recovery; - } + FLUID_MEMSET(dev, 0, sizeof(fluid_oss_midi_driver_t)); + dev->fd = -1; - dev->status = FLUID_MIDI_READY; + dev->driver.handler = handler; + dev->driver.data = data; - /* create MIDI thread */ - dev->thread = new_fluid_thread ("oss-midi", fluid_oss_midi_run, dev, realtime_prio, FALSE); + /* allocate one event to store the input data */ + dev->parser = new_fluid_midi_parser(); - if (!dev->thread) - goto error_recovery; + if(dev->parser == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } - if (device) FLUID_FREE (device); /* ++ free device */ + /* get the device name. if none is specified, use the default device. */ + fluid_settings_dupstr(settings, "midi.oss.device", &device); /* ++ alloc device name */ - return (fluid_midi_driver_t*) dev; + if(device == NULL) + { + device = FLUID_STRDUP("/dev/midi"); - error_recovery: - if (device) FLUID_FREE (device); /* ++ free device */ - delete_fluid_oss_midi_driver((fluid_midi_driver_t*) dev); - return NULL; + if(!device) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + } + + fluid_settings_getint(settings, "midi.realtime-prio", &realtime_prio); + + /* open the default hardware device. only use midi in. */ + dev->fd = open(device, O_RDONLY, 0); + + if(dev->fd < 0) + { + perror(device); + goto error_recovery; + } + + if(fcntl(dev->fd, F_SETFL, O_NONBLOCK) == -1) + { + FLUID_LOG(FLUID_ERR, "Failed to set OSS MIDI device to non-blocking: %s", + strerror(errno)); + goto error_recovery; + } + + dev->status = FLUID_MIDI_READY; + + /* create MIDI thread */ + dev->thread = new_fluid_thread("oss-midi", fluid_oss_midi_run, dev, realtime_prio, FALSE); + + if(!dev->thread) + { + goto error_recovery; + } + + if(device) + { + FLUID_FREE(device); /* ++ free device */ + } + + return (fluid_midi_driver_t *) dev; + +error_recovery: + + if(device) + { + FLUID_FREE(device); /* ++ free device */ + } + + delete_fluid_oss_midi_driver((fluid_midi_driver_t *) dev); + return NULL; } /* * delete_fluid_oss_midi_driver */ void -delete_fluid_oss_midi_driver(fluid_midi_driver_t* p) +delete_fluid_oss_midi_driver(fluid_midi_driver_t *p) { - fluid_oss_midi_driver_t* dev = (fluid_oss_midi_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_oss_midi_driver_t *dev = (fluid_oss_midi_driver_t *) p; + fluid_return_if_fail(dev != NULL); - /* cancel the thread and wait for it before cleaning up */ - dev->status = FLUID_MIDI_DONE; + /* cancel the thread and wait for it before cleaning up */ + dev->status = FLUID_MIDI_DONE; - if (dev->thread) - fluid_thread_join (dev->thread); + if(dev->thread) + { + fluid_thread_join(dev->thread); + } - if (dev->fd >= 0) { - close(dev->fd); - } - - delete_fluid_midi_parser(dev->parser); - FLUID_FREE(dev); + if(dev->fd >= 0) + { + close(dev->fd); + } + + delete_fluid_midi_parser(dev->parser); + FLUID_FREE(dev); } /* * fluid_oss_midi_run */ fluid_thread_return_t -fluid_oss_midi_run(void* d) +fluid_oss_midi_run(void *d) { - fluid_oss_midi_driver_t* dev = (fluid_oss_midi_driver_t*) d; - fluid_midi_event_t* evt; - struct pollfd fds; - int n, i; + fluid_oss_midi_driver_t *dev = (fluid_oss_midi_driver_t *) d; + fluid_midi_event_t *evt; + struct pollfd fds; + int n, i; - /* go into a loop until someone tells us to stop */ - dev->status = FLUID_MIDI_LISTENING; + /* go into a loop until someone tells us to stop */ + dev->status = FLUID_MIDI_LISTENING; - fds.fd = dev->fd; - fds.events = POLLIN; - fds.revents = 0; + fds.fd = dev->fd; + fds.events = POLLIN; + fds.revents = 0; - while (dev->status == FLUID_MIDI_LISTENING) { - - n = poll (&fds, 1, 100); - - if (n == 0) continue; - - if (n < 0) + while(dev->status == FLUID_MIDI_LISTENING) { - FLUID_LOG(FLUID_ERR, "Error waiting for MIDI input: %s", strerror (errno)); - break; + + n = poll(&fds, 1, 100); + + if(n == 0) + { + continue; + } + + if(n < 0) + { + FLUID_LOG(FLUID_ERR, "Error waiting for MIDI input: %s", strerror(errno)); + break; + } + + /* read new data */ + n = read(dev->fd, dev->buffer, BUFFER_LENGTH); + + if(n == -EAGAIN) + { + continue; + } + + if(n < 0) + { + perror("read"); + FLUID_LOG(FLUID_ERR, "Failed to read the midi input"); + break; + } + + /* let the parser convert the data into events */ + for(i = 0; i < n; i++) + { + evt = fluid_midi_parser_parse(dev->parser, dev->buffer[i]); + + if(evt != NULL) + { + /* send the event to the next link in the chain */ + (*dev->driver.handler)(dev->driver.data, evt); + } + } } - /* read new data */ - n = read(dev->fd, dev->buffer, BUFFER_LENGTH); - - if (n == -EAGAIN) continue; - - if (n < 0) { - perror("read"); - FLUID_LOG(FLUID_ERR, "Failed to read the midi input"); - break; - } - - /* let the parser convert the data into events */ - for (i = 0; i < n; i++) { - evt = fluid_midi_parser_parse(dev->parser, dev->buffer[i]); - if (evt != NULL) { - /* send the event to the next link in the chain */ - (*dev->driver.handler)(dev->driver.data, evt); - } - } - } - - return FLUID_THREAD_RETURN_VALUE; + return FLUID_THREAD_RETURN_VALUE; } int -fluid_oss_midi_driver_status(fluid_midi_driver_t* p) +fluid_oss_midi_driver_status(fluid_midi_driver_t *p) { - fluid_oss_midi_driver_t* dev = (fluid_oss_midi_driver_t*) p; - return dev->status; + fluid_oss_midi_driver_t *dev = (fluid_oss_midi_driver_t *) p; + return dev->status; } #endif /*#if OSS_SUPPORT */ diff --git a/src/drivers/fluid_portaudio.c b/src/drivers/fluid_portaudio.c index c86cabb3..93532f69 100644 --- a/src/drivers/fluid_portaudio.c +++ b/src/drivers/fluid_portaudio.c @@ -46,67 +46,80 @@ */ typedef struct { - fluid_audio_driver_t driver; - fluid_synth_t *synth; - fluid_audio_callback_t read; - PaStream *stream; + fluid_audio_driver_t driver; + fluid_synth_t *synth; + fluid_audio_callback_t read; + PaStream *stream; } fluid_portaudio_driver_t; static int -fluid_portaudio_run (const void *input, void *output, unsigned long frameCount, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, void *userData); -void delete_fluid_portaudio_driver (fluid_audio_driver_t *p); +fluid_portaudio_run(const void *input, void *output, unsigned long frameCount, + const PaStreamCallbackTimeInfo *timeInfo, + PaStreamCallbackFlags statusFlags, void *userData); +void delete_fluid_portaudio_driver(fluid_audio_driver_t *p); #define PORTAUDIO_DEFAULT_DEVICE "PortAudio Default" /** * Checks if device_num is a valid device and returns the name of the portaudio device. * A device is valid if it is an output device with at least 2 channels. - * + * * @param device_num index of the portaudio device to check. * @param name_ptr if device_num is valid, set to a unique device name, ignored otherwise * - * The name returned is unique for each num_device index, so this + * The name returned is unique for each num_device index, so this * name is useful to identify any available host audio device. * This name is convenient for audio.portaudio.device setting. * * The format of the name is: device_index:host_api_name:host_device_name - * + * * example: 5:MME:SB PCI - * + * * 5: is the portaudio device index. * MME: is the host API name. * SB PCI: is the host device name. - * + * * @return #FLUID_OK if device_num is a valid output device, #FLUID_FAILED otherwise. * When #FLUID_OK, the name is returned in allocated memory. The caller must check * the name pointer for a valid memory allocation and should free the memory. */ static int fluid_portaudio_get_device_name(int device_num, char **name_ptr) { - const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo (device_num); + const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(device_num); - if( deviceInfo->maxOutputChannels >= 2 ) - { - const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); - /* The size of the buffer name for the following format: - device_index:host_api_name:host_device_name. - */ - int i = device_num; - int size = 0; - do {size++; i = i/10 ;} while(i); /* index size */ - /* host API size + host device size + 2 separators + zero termination */ - size += strlen(hostInfo->name) + strlen(deviceInfo->name) + 3; - *name_ptr = FLUID_MALLOC (size); - if (*name_ptr) - { /* the name is filled if allocation is successful */ - FLUID_SPRINTF(*name_ptr,"%d:%s:%s",device_num, - hostInfo->name, deviceInfo->name); - } - return FLUID_OK; /* device_num is a valid device */ - } - else return FLUID_FAILED; /* device_num is an invalid device */ + if(deviceInfo->maxOutputChannels >= 2) + { + const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi); + /* The size of the buffer name for the following format: + device_index:host_api_name:host_device_name. + */ + int i = device_num; + int size = 0; + + do + { + size++; + i = i / 10 ; + } + while(i); /* index size */ + + /* host API size + host device size + 2 separators + zero termination */ + size += strlen(hostInfo->name) + strlen(deviceInfo->name) + 3; + *name_ptr = FLUID_MALLOC(size); + + if(*name_ptr) + { + /* the name is filled if allocation is successful */ + FLUID_SPRINTF(*name_ptr, "%d:%s:%s", device_num, + hostInfo->name, deviceInfo->name); + } + + return FLUID_OK; /* device_num is a valid device */ + } + else + { + return FLUID_FAILED; /* device_num is an invalid device */ + } } /** @@ -115,55 +128,61 @@ static int fluid_portaudio_get_device_name(int device_num, char **name_ptr) * @param settings pointer to settings. */ void -fluid_portaudio_driver_settings (fluid_settings_t *settings) +fluid_portaudio_driver_settings(fluid_settings_t *settings) { - int numDevices; - PaError err; - int i; + int numDevices; + PaError err; + int i; - fluid_settings_register_str (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE, 0); - fluid_settings_add_option (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE); + fluid_settings_register_str(settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE, 0); + fluid_settings_add_option(settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE); - err = Pa_Initialize(); + err = Pa_Initialize(); - if (err != paNoError) - { - FLUID_LOG (FLUID_ERR, "Error initializing PortAudio driver: %s", - Pa_GetErrorText (err)); - return; - } - - numDevices = Pa_GetDeviceCount(); - - if (numDevices < 0) - { - FLUID_LOG (FLUID_ERR, "PortAudio returned unexpected device count %d", numDevices); - } - else for (i = 0; i < numDevices; i++) - { - char * name; - if(fluid_portaudio_get_device_name(i, &name) == FLUID_OK) + if(err != paNoError) { - /* the device i is a valid output device */ - if(name) - { - /* registers this name in the option list */ - fluid_settings_add_option (settings, "audio.portaudio.device", name); - FLUID_FREE (name); - } - else - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - break; - } - } + FLUID_LOG(FLUID_ERR, "Error initializing PortAudio driver: %s", + Pa_GetErrorText(err)); + return; } - /* done with PortAudio for now, may get reopened later */ - err = Pa_Terminate(); + numDevices = Pa_GetDeviceCount(); - if (err != paNoError) - printf ("PortAudio termination error: %s\n", Pa_GetErrorText (err) ); + if(numDevices < 0) + { + FLUID_LOG(FLUID_ERR, "PortAudio returned unexpected device count %d", numDevices); + } + else + { + for(i = 0; i < numDevices; i++) + { + char *name; + + if(fluid_portaudio_get_device_name(i, &name) == FLUID_OK) + { + /* the device i is a valid output device */ + if(name) + { + /* registers this name in the option list */ + fluid_settings_add_option(settings, "audio.portaudio.device", name); + FLUID_FREE(name); + } + else + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + break; + } + } + } + } + + /* done with PortAudio for now, may get reopened later */ + err = Pa_Terminate(); + + if(err != paNoError) + { + printf("PortAudio termination error: %s\n", Pa_GetErrorText(err)); + } } /** @@ -175,169 +194,180 @@ fluid_portaudio_driver_settings (fluid_settings_t *settings) * @return pointer to the driver on success, NULL otherwise. */ fluid_audio_driver_t * -new_fluid_portaudio_driver (fluid_settings_t *settings, fluid_synth_t *synth) +new_fluid_portaudio_driver(fluid_settings_t *settings, fluid_synth_t *synth) { - fluid_portaudio_driver_t *dev = NULL; - PaStreamParameters outputParams; - char *device = NULL; /* the portaudio device name to work with */ - double sample_rate; /* intended sample rate */ - int period_size; /* intended buffer size */ - PaError err; + fluid_portaudio_driver_t *dev = NULL; + PaStreamParameters outputParams; + char *device = NULL; /* the portaudio device name to work with */ + double sample_rate; /* intended sample rate */ + int period_size; /* intended buffer size */ + PaError err; - dev = FLUID_NEW (fluid_portaudio_driver_t); + dev = FLUID_NEW(fluid_portaudio_driver_t); - if (dev == NULL) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return NULL; - } - - err = Pa_Initialize (); - - if (err != paNoError) - { - FLUID_LOG (FLUID_ERR, "Error initializing PortAudio driver: %s", - Pa_GetErrorText (err)); - FLUID_FREE (dev); - return NULL; - } - - FLUID_MEMSET (dev, 0, sizeof (fluid_portaudio_driver_t)); - - dev->synth = synth; - - /* gets audio parameters from the settings */ - fluid_settings_getint (settings, "audio.period-size", &period_size); - fluid_settings_getnum (settings, "synth.sample-rate", &sample_rate); - fluid_settings_dupstr(settings, "audio.portaudio.device", &device); /* ++ alloc device name */ - - memset (&outputParams, 0, sizeof (outputParams)); - outputParams.channelCount = 2; /* For stereo output */ - outputParams.suggestedLatency = (PaTime)period_size / sample_rate; - - /* Locate the device if specified */ - if (FLUID_STRCMP (device, PORTAUDIO_DEFAULT_DEVICE) != 0) - { /* The intended device is not the default device name, so we search - a device among available devices */ - int numDevices; - int i; - - numDevices = Pa_GetDeviceCount (); - - if (numDevices < 0) + if(dev == NULL) { - FLUID_LOG (FLUID_ERR, "PortAudio returned unexpected device count %d", numDevices); - goto error_recovery; + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - for (i = 0; i < numDevices; i++) - { - char * name; - if(fluid_portaudio_get_device_name(i, &name) == FLUID_OK ) - { - /* the device i is a valid output device */ - if(name) - { - /* We see if the name corresponds to audio.portaudio.device */ - char found = (FLUID_STRCMP (device, name) == 0); - FLUID_FREE (name); + err = Pa_Initialize(); - if(found) + if(err != paNoError) + { + FLUID_LOG(FLUID_ERR, "Error initializing PortAudio driver: %s", + Pa_GetErrorText(err)); + FLUID_FREE(dev); + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_portaudio_driver_t)); + + dev->synth = synth; + + /* gets audio parameters from the settings */ + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_dupstr(settings, "audio.portaudio.device", &device); /* ++ alloc device name */ + + memset(&outputParams, 0, sizeof(outputParams)); + outputParams.channelCount = 2; /* For stereo output */ + outputParams.suggestedLatency = (PaTime)period_size / sample_rate; + + /* Locate the device if specified */ + if(FLUID_STRCMP(device, PORTAUDIO_DEFAULT_DEVICE) != 0) + { + /* The intended device is not the default device name, so we search + a device among available devices */ + int numDevices; + int i; + + numDevices = Pa_GetDeviceCount(); + + if(numDevices < 0) + { + FLUID_LOG(FLUID_ERR, "PortAudio returned unexpected device count %d", numDevices); + goto error_recovery; + } + + for(i = 0; i < numDevices; i++) + { + char *name; + + if(fluid_portaudio_get_device_name(i, &name) == FLUID_OK) + { + /* the device i is a valid output device */ + if(name) { - /* the device index is found */ - outputParams.device = i; - /* The search is finished */ - break; + /* We see if the name corresponds to audio.portaudio.device */ + char found = (FLUID_STRCMP(device, name) == 0); + FLUID_FREE(name); + + if(found) + { + /* the device index is found */ + outputParams.device = i; + /* The search is finished */ + break; + } + } + else + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; } } - else - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - goto error_recovery; - } + } + + if(i == numDevices) + { + FLUID_LOG(FLUID_ERR, "PortAudio device '%s' was not found", device); + goto error_recovery; } } - - if (i == numDevices) + else { - FLUID_LOG (FLUID_ERR, "PortAudio device '%s' was not found", device); - goto error_recovery; + /* the default device will be used */ + outputParams.device = Pa_GetDefaultOutputDevice(); } - } - else - { /* the default device will be used */ - outputParams.device = Pa_GetDefaultOutputDevice(); - } - /* The device is found. We set the sample format and the audio rendering - function suited to this format. - */ - if (fluid_settings_str_equal (settings, "audio.sample-format", "16bits")) - { - outputParams.sampleFormat = paInt16; - dev->read = fluid_synth_write_s16; - } - else if (fluid_settings_str_equal (settings, "audio.sample-format", "float")) - { - outputParams.sampleFormat = paFloat32; - dev->read = fluid_synth_write_float; - } - else - { - FLUID_LOG (FLUID_ERR, "Unknown sample format"); - goto error_recovery; - } + /* The device is found. We set the sample format and the audio rendering + function suited to this format. + */ + if(fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) + { + outputParams.sampleFormat = paInt16; + dev->read = fluid_synth_write_s16; + } + else if(fluid_settings_str_equal(settings, "audio.sample-format", "float")) + { + outputParams.sampleFormat = paFloat32; + dev->read = fluid_synth_write_float; + } + else + { + FLUID_LOG(FLUID_ERR, "Unknown sample format"); + goto error_recovery; + } - /* PortAudio section */ + /* PortAudio section */ - /* Open an audio I/O stream. */ - err = Pa_OpenStream (&dev->stream, - NULL, /* Input parameters */ - &outputParams, /* Output parameters */ - sample_rate, - period_size, - paNoFlag, - fluid_portaudio_run, /* callback */ - dev); + /* Open an audio I/O stream. */ + err = Pa_OpenStream(&dev->stream, + NULL, /* Input parameters */ + &outputParams, /* Output parameters */ + sample_rate, + period_size, + paNoFlag, + fluid_portaudio_run, /* callback */ + dev); - if (err != paNoError) - { - FLUID_LOG (FLUID_ERR, "Error opening PortAudio stream: %s", - Pa_GetErrorText (err)); - goto error_recovery; - } + if(err != paNoError) + { + FLUID_LOG(FLUID_ERR, "Error opening PortAudio stream: %s", + Pa_GetErrorText(err)); + goto error_recovery; + } - err = Pa_StartStream (dev->stream); /* starts the I/O stream */ + err = Pa_StartStream(dev->stream); /* starts the I/O stream */ - if (err != paNoError) - { - FLUID_LOG (FLUID_ERR, "Error starting PortAudio stream: %s", - Pa_GetErrorText (err)); - goto error_recovery; - } + if(err != paNoError) + { + FLUID_LOG(FLUID_ERR, "Error starting PortAudio stream: %s", + Pa_GetErrorText(err)); + goto error_recovery; + } - if (device) FLUID_FREE (device); /* -- free device name */ - - return (fluid_audio_driver_t *)dev; + if(device) + { + FLUID_FREE(device); /* -- free device name */ + } + + return (fluid_audio_driver_t *)dev; error_recovery: - if (device) FLUID_FREE (device); /* -- free device name */ - delete_fluid_portaudio_driver ((fluid_audio_driver_t *)dev); - return NULL; + + if(device) + { + FLUID_FREE(device); /* -- free device name */ + } + + delete_fluid_portaudio_driver((fluid_audio_driver_t *)dev); + return NULL; } /* PortAudio callback * fluid_portaudio_run */ static int -fluid_portaudio_run (const void *input, void *output, unsigned long frameCount, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, void *userData) +fluid_portaudio_run(const void *input, void *output, unsigned long frameCount, + const PaStreamCallbackTimeInfo *timeInfo, + PaStreamCallbackFlags statusFlags, void *userData) { - fluid_portaudio_driver_t *dev = (fluid_portaudio_driver_t *)userData; - /* it's as simple as that: */ - dev->read (dev->synth, frameCount, output, 0, 2, output, 1, 2); - return 0; + fluid_portaudio_driver_t *dev = (fluid_portaudio_driver_t *)userData; + /* it's as simple as that: */ + dev->read(dev->synth, frameCount, output, 0, 2, output, 1, 2); + return 0; } /* @@ -346,19 +376,24 @@ fluid_portaudio_run (const void *input, void *output, unsigned long frameCount, void delete_fluid_portaudio_driver(fluid_audio_driver_t *p) { - fluid_portaudio_driver_t* dev = (fluid_portaudio_driver_t*)p; - PaError err; - fluid_return_if_fail(dev != NULL); + fluid_portaudio_driver_t *dev = (fluid_portaudio_driver_t *)p; + PaError err; + fluid_return_if_fail(dev != NULL); - /* PortAudio section */ - if (dev->stream) Pa_CloseStream (dev->stream); + /* PortAudio section */ + if(dev->stream) + { + Pa_CloseStream(dev->stream); + } - err = Pa_Terminate(); + err = Pa_Terminate(); - if (err != paNoError) - printf ("PortAudio termination error: %s\n", Pa_GetErrorText (err) ); + if(err != paNoError) + { + printf("PortAudio termination error: %s\n", Pa_GetErrorText(err)); + } - FLUID_FREE (dev); + FLUID_FREE(dev); } #endif /* PORTAUDIO_SUPPORT */ diff --git a/src/drivers/fluid_pulse.c b/src/drivers/fluid_pulse.c index 553d927f..eaa16f0d 100644 --- a/src/drivers/fluid_pulse.c +++ b/src/drivers/fluid_pulse.c @@ -38,256 +38,286 @@ * This structure should not be accessed directly. Use audio port * functions instead. */ -typedef struct { - fluid_audio_driver_t driver; - pa_simple *pa_handle; - fluid_audio_func_t callback; - void* data; - int buffer_size; - fluid_thread_t *thread; - int cont; - - float *left; - float *right; - float *buf; +typedef struct +{ + fluid_audio_driver_t driver; + pa_simple *pa_handle; + fluid_audio_func_t callback; + void *data; + int buffer_size; + fluid_thread_t *thread; + int cont; + + float *left; + float *right; + float *buf; } fluid_pulse_audio_driver_t; -fluid_audio_driver_t* new_fluid_pulse_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); -fluid_audio_driver_t* new_fluid_pulse_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data); -void delete_fluid_pulse_audio_driver(fluid_audio_driver_t* p); -void fluid_pulse_audio_driver_settings(fluid_settings_t* settings); -static fluid_thread_return_t fluid_pulse_audio_run(void* d); -static fluid_thread_return_t fluid_pulse_audio_run2(void* d); +fluid_audio_driver_t *new_fluid_pulse_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); +fluid_audio_driver_t *new_fluid_pulse_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data); +void delete_fluid_pulse_audio_driver(fluid_audio_driver_t *p); +void fluid_pulse_audio_driver_settings(fluid_settings_t *settings); +static fluid_thread_return_t fluid_pulse_audio_run(void *d); +static fluid_thread_return_t fluid_pulse_audio_run2(void *d); -void fluid_pulse_audio_driver_settings(fluid_settings_t* settings) +void fluid_pulse_audio_driver_settings(fluid_settings_t *settings) { - fluid_settings_register_str(settings, "audio.pulseaudio.server", "default", 0); - fluid_settings_register_str(settings, "audio.pulseaudio.device", "default", 0); - fluid_settings_register_str(settings, "audio.pulseaudio.media-role", "music", 0); - fluid_settings_register_int(settings, "audio.pulseaudio.adjust-latency", 1, 0, 1, - FLUID_HINT_TOGGLED); + fluid_settings_register_str(settings, "audio.pulseaudio.server", "default", 0); + fluid_settings_register_str(settings, "audio.pulseaudio.device", "default", 0); + fluid_settings_register_str(settings, "audio.pulseaudio.media-role", "music", 0); + fluid_settings_register_int(settings, "audio.pulseaudio.adjust-latency", 1, 0, 1, + FLUID_HINT_TOGGLED); } -fluid_audio_driver_t* -new_fluid_pulse_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_pulse_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth) { - return new_fluid_pulse_audio_driver2(settings, NULL, synth); + return new_fluid_pulse_audio_driver2(settings, NULL, synth); } -fluid_audio_driver_t* -new_fluid_pulse_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, void* data) +fluid_audio_driver_t * +new_fluid_pulse_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, void *data) { - fluid_pulse_audio_driver_t* dev; - pa_sample_spec samplespec; - pa_buffer_attr bufattr; - double sample_rate; - int period_size, period_bytes, adjust_latency; - char *server = NULL; - char *device = NULL; - char *media_role = NULL; - int realtime_prio = 0; - int err; - float *left = NULL, - *right = NULL, - *buf = NULL; + fluid_pulse_audio_driver_t *dev; + pa_sample_spec samplespec; + pa_buffer_attr bufattr; + double sample_rate; + int period_size, period_bytes, adjust_latency; + char *server = NULL; + char *device = NULL; + char *media_role = NULL; + int realtime_prio = 0; + int err; + float *left = NULL, + *right = NULL, + *buf = NULL; - dev = FLUID_NEW(fluid_pulse_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + dev = FLUID_NEW(fluid_pulse_audio_driver_t); - FLUID_MEMSET(dev, 0, sizeof(fluid_pulse_audio_driver_t)); - - fluid_settings_getint(settings, "audio.period-size", &period_size); - fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); - fluid_settings_dupstr(settings, "audio.pulseaudio.server", &server); /* ++ alloc server string */ - fluid_settings_dupstr(settings, "audio.pulseaudio.device", &device); /* ++ alloc device string */ - fluid_settings_dupstr(settings, "audio.pulseaudio.media-role", &media_role); /* ++ alloc media-role string */ - fluid_settings_getint(settings, "audio.realtime-prio", &realtime_prio); - fluid_settings_getint(settings, "audio.pulseaudio.adjust-latency", &adjust_latency); - - if (media_role != NULL) { - if (FLUID_STRCMP(media_role, "") != 0) { - g_setenv("PULSE_PROP_media.role", media_role, TRUE); + if(dev == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - FLUID_FREE (media_role); /* -- free media_role string */ - } - if (server && FLUID_STRCMP (server, "default") == 0) - { - FLUID_FREE (server); /* -- free server string */ - server = NULL; - } + FLUID_MEMSET(dev, 0, sizeof(fluid_pulse_audio_driver_t)); - if (device && FLUID_STRCMP (device, "default") == 0) - { - FLUID_FREE (device); /* -- free device string */ - device = NULL; - } + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_dupstr(settings, "audio.pulseaudio.server", &server); /* ++ alloc server string */ + fluid_settings_dupstr(settings, "audio.pulseaudio.device", &device); /* ++ alloc device string */ + fluid_settings_dupstr(settings, "audio.pulseaudio.media-role", &media_role); /* ++ alloc media-role string */ + fluid_settings_getint(settings, "audio.realtime-prio", &realtime_prio); + fluid_settings_getint(settings, "audio.pulseaudio.adjust-latency", &adjust_latency); - dev->data = data; - dev->callback = func; - dev->cont = 1; - dev->buffer_size = period_size; + if(media_role != NULL) + { + if(FLUID_STRCMP(media_role, "") != 0) + { + g_setenv("PULSE_PROP_media.role", media_role, TRUE); + } - samplespec.format = PA_SAMPLE_FLOAT32NE; - samplespec.channels = 2; - samplespec.rate = sample_rate; + FLUID_FREE(media_role); /* -- free media_role string */ + } - period_bytes = period_size * sizeof (float) * 2; - bufattr.maxlength = adjust_latency ? -1 : period_bytes; - bufattr.tlength = period_bytes; - bufattr.minreq = -1; - bufattr.prebuf = -1; /* Just initialize to same value as tlength */ - bufattr.fragsize = -1; /* Not used */ + if(server && FLUID_STRCMP(server, "default") == 0) + { + FLUID_FREE(server); /* -- free server string */ + server = NULL; + } - dev->pa_handle = pa_simple_new (server, "FluidSynth", PA_STREAM_PLAYBACK, - device, "FluidSynth output", &samplespec, - NULL, /* pa_channel_map */ - &bufattr, - &err); + if(device && FLUID_STRCMP(device, "default") == 0) + { + FLUID_FREE(device); /* -- free device string */ + device = NULL; + } - if (!dev->pa_handle) - { - FLUID_LOG(FLUID_ERR, "Failed to create PulseAudio connection"); - goto error_recovery; - } + dev->data = data; + dev->callback = func; + dev->cont = 1; + dev->buffer_size = period_size; - FLUID_LOG(FLUID_INFO, "Using PulseAudio driver"); + samplespec.format = PA_SAMPLE_FLOAT32NE; + samplespec.channels = 2; + samplespec.rate = sample_rate; - if(func != NULL) - { - left = FLUID_ARRAY(float, period_size); - right = FLUID_ARRAY(float, period_size); + period_bytes = period_size * sizeof(float) * 2; + bufattr.maxlength = adjust_latency ? -1 : period_bytes; + bufattr.tlength = period_bytes; + bufattr.minreq = -1; + bufattr.prebuf = -1; /* Just initialize to same value as tlength */ + bufattr.fragsize = -1; /* Not used */ - if (left == NULL || right == NULL) + dev->pa_handle = pa_simple_new(server, "FluidSynth", PA_STREAM_PLAYBACK, + device, "FluidSynth output", &samplespec, + NULL, /* pa_channel_map */ + &bufattr, + &err); + + if(!dev->pa_handle) + { + FLUID_LOG(FLUID_ERR, "Failed to create PulseAudio connection"); + goto error_recovery; + } + + FLUID_LOG(FLUID_INFO, "Using PulseAudio driver"); + + if(func != NULL) + { + left = FLUID_ARRAY(float, period_size); + right = FLUID_ARRAY(float, period_size); + + if(left == NULL || right == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory."); + goto error_recovery; + } + } + + buf = FLUID_ARRAY(float, period_size * 2); + + if(buf == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory."); goto error_recovery; } - } - - buf = FLUID_ARRAY(float, period_size * 2); - if(buf == NULL) - { - FLUID_LOG(FLUID_ERR, "Out of memory."); - goto error_recovery; - } - - dev->left = left; - dev->right = right; - dev->buf = buf; - - /* Create the audio thread */ - dev->thread = new_fluid_thread ("pulse-audio", func ? fluid_pulse_audio_run2 : fluid_pulse_audio_run, - dev, realtime_prio, FALSE); - if (!dev->thread) - goto error_recovery; - if (server) FLUID_FREE (server); /* -- free server string */ - if (device) FLUID_FREE (device); /* -- free device string */ + dev->left = left; + dev->right = right; + dev->buf = buf; - return (fluid_audio_driver_t*) dev; + /* Create the audio thread */ + dev->thread = new_fluid_thread("pulse-audio", func ? fluid_pulse_audio_run2 : fluid_pulse_audio_run, + dev, realtime_prio, FALSE); - error_recovery: - if (server) FLUID_FREE (server); /* -- free server string */ - if (device) FLUID_FREE (device); /* -- free device string */ - delete_fluid_pulse_audio_driver((fluid_audio_driver_t*) dev); - return NULL; + if(!dev->thread) + { + goto error_recovery; + } + + if(server) + { + FLUID_FREE(server); /* -- free server string */ + } + + if(device) + { + FLUID_FREE(device); /* -- free device string */ + } + + return (fluid_audio_driver_t *) dev; + +error_recovery: + + if(server) + { + FLUID_FREE(server); /* -- free server string */ + } + + if(device) + { + FLUID_FREE(device); /* -- free device string */ + } + + delete_fluid_pulse_audio_driver((fluid_audio_driver_t *) dev); + return NULL; } -void delete_fluid_pulse_audio_driver(fluid_audio_driver_t* p) +void delete_fluid_pulse_audio_driver(fluid_audio_driver_t *p) { - fluid_pulse_audio_driver_t* dev = (fluid_pulse_audio_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_pulse_audio_driver_t *dev = (fluid_pulse_audio_driver_t *) p; + fluid_return_if_fail(dev != NULL); - dev->cont = 0; + dev->cont = 0; - if (dev->thread) - fluid_thread_join (dev->thread); + if(dev->thread) + { + fluid_thread_join(dev->thread); + } - if (dev->pa_handle) - pa_simple_free(dev->pa_handle); + if(dev->pa_handle) + { + pa_simple_free(dev->pa_handle); + } - FLUID_FREE(dev->left); - FLUID_FREE(dev->right); - FLUID_FREE(dev->buf); - - FLUID_FREE(dev); + FLUID_FREE(dev->left); + FLUID_FREE(dev->right); + FLUID_FREE(dev->buf); + + FLUID_FREE(dev); } /* Thread without audio callback, more efficient */ static fluid_thread_return_t -fluid_pulse_audio_run(void* d) +fluid_pulse_audio_run(void *d) { - fluid_pulse_audio_driver_t* dev = (fluid_pulse_audio_driver_t*) d; - float *buf = dev->buf; - int buffer_size; - int err; + fluid_pulse_audio_driver_t *dev = (fluid_pulse_audio_driver_t *) d; + float *buf = dev->buf; + int buffer_size; + int err; - buffer_size = dev->buffer_size; + buffer_size = dev->buffer_size; - while (dev->cont) - { - fluid_synth_write_float(dev->data, buffer_size, buf, 0, 2, buf, 1, 2); - - if (pa_simple_write (dev->pa_handle, buf, - buffer_size * sizeof (float) * 2, &err) < 0) + while(dev->cont) { - FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection."); - break; - } - } /* while (dev->cont) */ + fluid_synth_write_float(dev->data, buffer_size, buf, 0, 2, buf, 1, 2); - return FLUID_THREAD_RETURN_VALUE; + if(pa_simple_write(dev->pa_handle, buf, + buffer_size * sizeof(float) * 2, &err) < 0) + { + FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection."); + break; + } + } /* while (dev->cont) */ + + return FLUID_THREAD_RETURN_VALUE; } static fluid_thread_return_t -fluid_pulse_audio_run2(void* d) +fluid_pulse_audio_run2(void *d) { - fluid_pulse_audio_driver_t* dev = (fluid_pulse_audio_driver_t*) d; - fluid_synth_t *synth = (fluid_synth_t *)(dev->data); - float *left = dev->left, - *right = dev->right, - *buf = dev->buf; - float* handle[2]; - int buffer_size; - int err; - int i; + fluid_pulse_audio_driver_t *dev = (fluid_pulse_audio_driver_t *) d; + fluid_synth_t *synth = (fluid_synth_t *)(dev->data); + float *left = dev->left, + *right = dev->right, + *buf = dev->buf; + float *handle[2]; + int buffer_size; + int err; + int i; - buffer_size = dev->buffer_size; + buffer_size = dev->buffer_size; - handle[0] = left; - handle[1] = right; + handle[0] = left; + handle[1] = right; - while (dev->cont) - { - (*dev->callback)(synth, buffer_size, 0, NULL, 2, handle); - - /* Interleave the floating point data */ - for (i = 0; i < buffer_size; i++) + while(dev->cont) { - buf[i * 2] = left[i]; - buf[i * 2 + 1] = right[i]; - } + (*dev->callback)(synth, buffer_size, 0, NULL, 2, handle); - if (pa_simple_write (dev->pa_handle, buf, - buffer_size * sizeof (float) * 2, &err) < 0) - { - FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection."); - break; - } - } /* while (dev->cont) */ + /* Interleave the floating point data */ + for(i = 0; i < buffer_size; i++) + { + buf[i * 2] = left[i]; + buf[i * 2 + 1] = right[i]; + } - return FLUID_THREAD_RETURN_VALUE; + if(pa_simple_write(dev->pa_handle, buf, + buffer_size * sizeof(float) * 2, &err) < 0) + { + FLUID_LOG(FLUID_ERR, "Error writing to PulseAudio connection."); + break; + } + } /* while (dev->cont) */ + + return FLUID_THREAD_RETURN_VALUE; } #endif /* PULSE_SUPPORT */ diff --git a/src/drivers/fluid_sndmgr.c b/src/drivers/fluid_sndmgr.c index 9ea62e1e..7a1dbc02 100644 --- a/src/drivers/fluid_sndmgr.c +++ b/src/drivers/fluid_sndmgr.c @@ -32,27 +32,28 @@ #include -typedef struct { - fluid_audio_driver_t driver; - SndDoubleBufferHeader2* doubleHeader; - SndDoubleBackUPP doubleCallbackProc; - SndChannelPtr channel; - int callback_is_audio_func; - void* data; - fluid_audio_func_t callback; - float* convbuffers[2]; - int bufferByteSize; - int bufferFrameSize; +typedef struct +{ + fluid_audio_driver_t driver; + SndDoubleBufferHeader2 *doubleHeader; + SndDoubleBackUPP doubleCallbackProc; + SndChannelPtr channel; + int callback_is_audio_func; + void *data; + fluid_audio_func_t callback; + float *convbuffers[2]; + int bufferByteSize; + int bufferFrameSize; } fluid_sndmgr_audio_driver_t; -fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, - fluid_synth_t* synth); +fluid_audio_driver_t *new_fluid_sndmgr_audio_driver(fluid_settings_t *settings, + fluid_synth_t *synth); -fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings, - fluid_audio_func_t func, - void* data); +fluid_audio_driver_t *new_fluid_sndmgr_audio_driver2(fluid_settings_t *settings, + fluid_audio_func_t func, + void *data); -void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p); +void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t *p); void pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer); Fixed fluid_sndmgr_double_to_fix(long double theLD); @@ -60,120 +61,138 @@ Fixed fluid_sndmgr_double_to_fix(long double theLD); * generic new : returns error */ int -start_fluid_sndmgr_audio_driver(fluid_settings_t* settings, - fluid_sndmgr_audio_driver_t* dev, - int buffer_size) +start_fluid_sndmgr_audio_driver(fluid_settings_t *settings, + fluid_sndmgr_audio_driver_t *dev, + int buffer_size) { - int i; - SndDoubleBufferHeader2* doubleHeader = NULL; - SndDoubleBufferPtr doubleBuffer = NULL; - OSErr err; - SndChannelPtr channel = NULL; - double sample_rate; + int i; + SndDoubleBufferHeader2 *doubleHeader = NULL; + SndDoubleBufferPtr doubleBuffer = NULL; + OSErr err; + SndChannelPtr channel = NULL; + double sample_rate; - fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); + fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate); - dev->doubleCallbackProc = NewSndDoubleBackProc(fluid_sndmgr_callback); + dev->doubleCallbackProc = NewSndDoubleBackProc(fluid_sndmgr_callback); - /* the channel */ - FLUID_LOG(FLUID_DBG, "FLUID-SndManager@2"); - err = SndNewChannel(&channel, sampledSynth, initStereo, NULL); - if ((err != noErr) || (channel == NULL)) { - FLUID_LOG(FLUID_ERR, "Failed to allocate a sound channel (error %i)", err); - return err; - } + /* the channel */ + FLUID_LOG(FLUID_DBG, "FLUID-SndManager@2"); + err = SndNewChannel(&channel, sampledSynth, initStereo, NULL); - /* the double buffer struct */ - FLUID_LOG(FLUID_DBG, "FLUID-SndManager@3"); - doubleHeader = FLUID_NEW(SndDoubleBufferHeader2); - if (doubleHeader == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return -1; - } - doubleHeader->dbhBufferPtr[0] = NULL; - doubleHeader->dbhBufferPtr[1] = NULL; - doubleHeader->dbhNumChannels = 2; - doubleHeader->dbhSampleSize = 16; - doubleHeader->dbhCompressionID = 0; - doubleHeader->dbhPacketSize = 0; - doubleHeader->dbhSampleRate = fluid_sndmgr_double_to_fix((long double) sample_rate); - doubleHeader->dbhDoubleBack = dev->doubleCallbackProc; - doubleHeader->dbhFormat = 0; - - /* prepare dev */ - FLUID_LOG(FLUID_DBG, "FLUID-SndManager@4"); - dev->doubleHeader = doubleHeader; - dev->channel = channel; - dev->bufferFrameSize = buffer_size; - dev->bufferByteSize = buffer_size * 2 * 2; - - /* the 2 doublebuffers */ - FLUID_LOG(FLUID_DBG, "FLUID-SndManager@5"); - for (i = 0; i < 2; i++) { - doubleBuffer = (SndDoubleBufferPtr) FLUID_MALLOC(sizeof(SndDoubleBuffer) - + dev->bufferByteSize); - if (doubleBuffer == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return -1; + if((err != noErr) || (channel == NULL)) + { + FLUID_LOG(FLUID_ERR, "Failed to allocate a sound channel (error %i)", err); + return err; } - doubleBuffer->dbNumFrames = 0; - doubleBuffer->dbFlags = 0; - doubleBuffer->dbUserInfo[0] = (long) dev; - doubleHeader->dbhBufferPtr[i] = doubleBuffer; - CallSndDoubleBackProc(doubleHeader->dbhDoubleBack, channel, doubleBuffer); - } - /* start */ - FLUID_LOG(FLUID_DBG, "FLUID-SndManager@6"); + /* the double buffer struct */ + FLUID_LOG(FLUID_DBG, "FLUID-SndManager@3"); + doubleHeader = FLUID_NEW(SndDoubleBufferHeader2); - err = SndPlayDoubleBuffer(channel, (SndDoubleBufferHeader *)doubleHeader); - if (err != noErr) { - FLUID_LOG(FLUID_ERR, "Failed to start the sound driver (error %i)", err); - return err; - } + if(doubleHeader == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return -1; + } - FLUID_LOG(FLUID_DBG, "FLUID-SndManager@7"); - return 0; + doubleHeader->dbhBufferPtr[0] = NULL; + doubleHeader->dbhBufferPtr[1] = NULL; + doubleHeader->dbhNumChannels = 2; + doubleHeader->dbhSampleSize = 16; + doubleHeader->dbhCompressionID = 0; + doubleHeader->dbhPacketSize = 0; + doubleHeader->dbhSampleRate = fluid_sndmgr_double_to_fix((long double) sample_rate); + doubleHeader->dbhDoubleBack = dev->doubleCallbackProc; + doubleHeader->dbhFormat = 0; + + /* prepare dev */ + FLUID_LOG(FLUID_DBG, "FLUID-SndManager@4"); + dev->doubleHeader = doubleHeader; + dev->channel = channel; + dev->bufferFrameSize = buffer_size; + dev->bufferByteSize = buffer_size * 2 * 2; + + /* the 2 doublebuffers */ + FLUID_LOG(FLUID_DBG, "FLUID-SndManager@5"); + + for(i = 0; i < 2; i++) + { + doubleBuffer = (SndDoubleBufferPtr) FLUID_MALLOC(sizeof(SndDoubleBuffer) + + dev->bufferByteSize); + + if(doubleBuffer == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return -1; + } + + doubleBuffer->dbNumFrames = 0; + doubleBuffer->dbFlags = 0; + doubleBuffer->dbUserInfo[0] = (long) dev; + doubleHeader->dbhBufferPtr[i] = doubleBuffer; + CallSndDoubleBackProc(doubleHeader->dbhDoubleBack, channel, doubleBuffer); + } + + /* start */ + FLUID_LOG(FLUID_DBG, "FLUID-SndManager@6"); + + err = SndPlayDoubleBuffer(channel, (SndDoubleBufferHeader *)doubleHeader); + + if(err != noErr) + { + FLUID_LOG(FLUID_ERR, "Failed to start the sound driver (error %i)", err); + return err; + } + + FLUID_LOG(FLUID_DBG, "FLUID-SndManager@7"); + return 0; } /* * new_fluid_sndmgr_audio_driver * This implementation used the 16bit format. */ -fluid_audio_driver_t* -new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) +fluid_audio_driver_t * +new_fluid_sndmgr_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) { - fluid_sndmgr_audio_driver_t* dev = NULL; - int period_size, periods, buffer_size; + fluid_sndmgr_audio_driver_t *dev = NULL; + int period_size, periods, buffer_size; - /* check the format */ - if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) { - FLUID_LOG(FLUID_ERR, "Unhandled sample format"); - return NULL; - } + /* check the format */ + if(!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) + { + FLUID_LOG(FLUID_ERR, "Unhandled sample format"); + return NULL; + } - /* compute buffer size */ - fluid_settings_getint(settings, "audio.period-size", &period_size); - fluid_settings_getint(settings, "audio.periods", &periods); - buffer_size = period_size*periods; + /* compute buffer size */ + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getint(settings, "audio.periods", &periods); + buffer_size = period_size * periods; - /* allocated dev */ - dev = FLUID_NEW(fluid_sndmgr_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t)); + /* allocated dev */ + dev = FLUID_NEW(fluid_sndmgr_audio_driver_t); - dev->callback_is_audio_func = false; - dev->data = (void *)synth; - dev->callback = NULL; + if(dev == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return NULL; + } - if (start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) { - delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t*)dev); - return NULL; - } - return (fluid_audio_driver_t*)dev; + FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t)); + + dev->callback_is_audio_func = false; + dev->data = (void *)synth; + dev->callback = NULL; + + if(start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) + { + delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t *)dev); + return NULL; + } + + return (fluid_audio_driver_t *)dev; } /* @@ -182,70 +201,79 @@ new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) * This implementation used the audio_func float format, with * conversion from float to 16bits in the driver. */ -fluid_audio_driver_t* -new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data) +fluid_audio_driver_t * +new_fluid_sndmgr_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data) { - fluid_sndmgr_audio_driver_t* dev = NULL; - int period_size, periods, buffer_size; + fluid_sndmgr_audio_driver_t *dev = NULL; + int period_size, periods, buffer_size; - /* compute buffer size */ - fluid_settings_getint(settings, "audio.period-size", &period_size); - fluid_settings_getint(settings, "audio.periods", &periods); - buffer_size = period_size*periods; + /* compute buffer size */ + fluid_settings_getint(settings, "audio.period-size", &period_size); + fluid_settings_getint(settings, "audio.periods", &periods); + buffer_size = period_size * periods; - /* allocated dev */ - dev = FLUID_NEW(fluid_sndmgr_audio_driver_t); - if (dev == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); + /* allocated dev */ + dev = FLUID_NEW(fluid_sndmgr_audio_driver_t); + + if(dev == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t)); + + /* allocate the conversion buffers */ + dev->convbuffers[0] = FLUID_ARRAY(float, buffer_size); + dev->convbuffers[1] = FLUID_ARRAY(float, buffer_size); + + if((dev->convbuffers[0] == NULL) || (dev->convbuffers[1] == NULL)) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + goto error_recovery; + } + + dev->callback_is_audio_func = true; + dev->data = data; + dev->callback = func; + + if(start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) + { + goto error_recovery; + } + + return (fluid_audio_driver_t *)dev; + +error_recovery: + delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t *)dev); return NULL; - } - FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t)); - - /* allocate the conversion buffers */ - dev->convbuffers[0] = FLUID_ARRAY(float, buffer_size); - dev->convbuffers[1] = FLUID_ARRAY(float, buffer_size); - if ((dev->convbuffers[0] == NULL) || (dev->convbuffers[1] == NULL)) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - goto error_recovery; - } - - dev->callback_is_audio_func = true; - dev->data = data; - dev->callback = func; - - if (start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) { - goto error_recovery; - } - return (fluid_audio_driver_t*)dev; - - error_recovery: - delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t*)dev); - return NULL; } /* * delete_fluid_sndmgr_audio_driver */ -void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p) +void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t *p) { - fluid_sndmgr_audio_driver_t* dev = (fluid_sndmgr_audio_driver_t*) p; - fluid_return_if_fail(dev != NULL); + fluid_sndmgr_audio_driver_t *dev = (fluid_sndmgr_audio_driver_t *) p; + fluid_return_if_fail(dev != NULL); - if (dev->channel != NULL) { - SndDisposeChannel(dev->channel, 1); + if(dev->channel != NULL) + { + SndDisposeChannel(dev->channel, 1); } - - if (dev->doubleCallbackProc != NULL) { - DisposeRoutineDescriptor(dev->doubleCallbackProc); + + if(dev->doubleCallbackProc != NULL) + { + DisposeRoutineDescriptor(dev->doubleCallbackProc); } - - if (dev->doubleHeader != NULL) + + if(dev->doubleHeader != NULL) { FLUID_FREE(dev->doubleHeader->dbhBufferPtr[0]); FLUID_FREE(dev->doubleHeader->dbhBufferPtr[1]); FLUID_FREE(dev->doubleHeader); } - + FLUID_FREE(dev->convbuffers[0]); FLUID_FREE(dev->convbuffers[1]); FLUID_FREE(dev); @@ -257,41 +285,45 @@ void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p) */ void pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer) { - fluid_sndmgr_audio_driver_t* dev; - signed short* buf; - float* left; - float* right; - float v; - int i, k, buffer_size; + fluid_sndmgr_audio_driver_t *dev; + signed short *buf; + float *left; + float *right; + float v; + int i, k, buffer_size; - dev = (fluid_sndmgr_audio_driver_t*) doubleBuffer->dbUserInfo[0]; - buf = (signed short*)doubleBuffer->dbSoundData; - buffer_size = dev->bufferFrameSize; + dev = (fluid_sndmgr_audio_driver_t *) doubleBuffer->dbUserInfo[0]; + buf = (signed short *)doubleBuffer->dbSoundData; + buffer_size = dev->bufferFrameSize; - if (dev->callback_is_audio_func) { - /* float API : conversion to signed short */ - left = dev->convbuffers[0]; - right = dev->convbuffers[1]; + if(dev->callback_is_audio_func) + { + /* float API : conversion to signed short */ + left = dev->convbuffers[0]; + right = dev->convbuffers[1]; - (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->convbuffers); + (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->convbuffers); - for (i = 0, k = 0; i < buffer_size; i++) { - v = 32767.0f * left[i]; - fluid_clip(v, -32768.0f, 32767.0f); - buf[k++] = (signed short) v; + for(i = 0, k = 0; i < buffer_size; i++) + { + v = 32767.0f * left[i]; + fluid_clip(v, -32768.0f, 32767.0f); + buf[k++] = (signed short) v; - v = 32767.0f * right[i]; - fluid_clip(v, -32768.0f, 32767.0f); - buf[k++] = (signed short) v; + v = 32767.0f * right[i]; + fluid_clip(v, -32768.0f, 32767.0f); + buf[k++] = (signed short) v; + } + + } + else + { + /* let the synth do the convertion */ + fluid_synth_write_s16((fluid_synth_t *)dev->data, buffer_size, buf, 0, 2, buf, 1, 2); } - } else { - /* let the synth do the convertion */ - fluid_synth_write_s16((fluid_synth_t*)dev->data, buffer_size, buf, 0, 2, buf, 1, 2); - } - - doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbBufferReady; - doubleBuffer->dbNumFrames = buffer_size; + doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbBufferReady; + doubleBuffer->dbNumFrames = buffer_size; } /* @@ -314,23 +346,28 @@ void pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr double */ #define _MAX_VALUE 65535 #define _BITS_PER_BYTE 8 -Fixed fluid_sndmgr_double_to_fix(long double theLD) { - unsigned long theResult = 0; - unsigned short theSignificant = 0, theFraction = 0; +Fixed fluid_sndmgr_double_to_fix(long double theLD) +{ + unsigned long theResult = 0; + unsigned short theSignificant = 0, theFraction = 0; - if (theLD < _MAX_VALUE) { - theSignificant = theLD; - theFraction = theLD - theSignificant; - if (theFraction > _MAX_VALUE) { - /* Won't be able to convert */ - theSignificant = 0; - theFraction = 0; + if(theLD < _MAX_VALUE) + { + theSignificant = theLD; + theFraction = theLD - theSignificant; + + if(theFraction > _MAX_VALUE) + { + /* Won't be able to convert */ + theSignificant = 0; + theFraction = 0; + } } - } - theResult |= theSignificant; - theResult = theResult << (sizeof (unsigned short) * _BITS_PER_BYTE); - theResult |= theFraction; - return theResult; + + theResult |= theSignificant; + theResult = theResult << (sizeof(unsigned short) * _BITS_PER_BYTE); + theResult |= theFraction; + return theResult; } #endif diff --git a/src/drivers/fluid_winmidi.c b/src/drivers/fluid_winmidi.c index b63985ff..6c08be3b 100644 --- a/src/drivers/fluid_winmidi.c +++ b/src/drivers/fluid_winmidi.c @@ -40,19 +40,20 @@ #define MIDI_SYSEX_MAX_SIZE 512 #define MIDI_SYSEX_BUF_COUNT 16 -typedef struct { - fluid_midi_driver_t driver; - HMIDIIN hmidiin; +typedef struct +{ + fluid_midi_driver_t driver; + HMIDIIN hmidiin; - /* MIDI HDR for SYSEX buffer */ - MIDIHDR sysExHdrs[MIDI_SYSEX_BUF_COUNT]; + /* MIDI HDR for SYSEX buffer */ + MIDIHDR sysExHdrs[MIDI_SYSEX_BUF_COUNT]; - /* Thread for SYSEX re-add thread */ - HANDLE hThread; - DWORD dwThread; + /* Thread for SYSEX re-add thread */ + HANDLE hThread; + DWORD dwThread; - /* Sysex data buffer */ - unsigned char sysExBuf[MIDI_SYSEX_BUF_COUNT * MIDI_SYSEX_MAX_SIZE]; + /* Sysex data buffer */ + unsigned char sysExBuf[MIDI_SYSEX_BUF_COUNT * MIDI_SYSEX_MAX_SIZE]; } fluid_winmidi_driver_t; @@ -63,292 +64,335 @@ static char fluid_winmidi_error_buffer[256]; #define msg_p1(_m) ((_m >> 8) & 0x7f) #define msg_p2(_m) ((_m >> 16) & 0x7f) -fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, void* data); +fluid_midi_driver_t *new_fluid_winmidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data); -void delete_fluid_winmidi_driver(fluid_midi_driver_t* p); +void delete_fluid_winmidi_driver(fluid_midi_driver_t *p); void CALLBACK fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance, - DWORD_PTR msg, DWORD_PTR extra); -static char* fluid_winmidi_input_error(MMRESULT no); + DWORD_PTR msg, DWORD_PTR extra); +static char *fluid_winmidi_input_error(MMRESULT no); -void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings) +void fluid_winmidi_midi_driver_settings(fluid_settings_t *settings) { - MMRESULT res; - MIDIINCAPS in_caps; - UINT i, num; - fluid_settings_register_str(settings, "midi.winmidi.device", "default", 0); - num = midiInGetNumDevs(); - if (num > 0) { - fluid_settings_add_option(settings, "midi.winmidi.device", "default"); - for (i = 0; i < num; i++) { - res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS)); - if (res == MMSYSERR_NOERROR) { - fluid_settings_add_option(settings, "midi.winmidi.device", in_caps.szPname); - } + MMRESULT res; + MIDIINCAPS in_caps; + UINT i, num; + fluid_settings_register_str(settings, "midi.winmidi.device", "default", 0); + num = midiInGetNumDevs(); + + if(num > 0) + { + fluid_settings_add_option(settings, "midi.winmidi.device", "default"); + + for(i = 0; i < num; i++) + { + res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS)); + + if(res == MMSYSERR_NOERROR) + { + fluid_settings_add_option(settings, "midi.winmidi.device", in_caps.szPname); + } + } } - } } /* Thread for re-adding SYSEX buffers */ static DWORD WINAPI fluid_winmidi_add_sysex_thread(void *data) { - fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *)data; - MSG msg; - int code; + fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *)data; + MSG msg; + int code; - for (;;) { - code = GetMessage(&msg, NULL, 0, 0); + for(;;) + { + code = GetMessage(&msg, NULL, 0, 0); - if (code < 0) { - FLUID_LOG(FLUID_ERR, "fluid_winmidi_add_sysex_thread: GetMessage() failed."); - break; + if(code < 0) + { + FLUID_LOG(FLUID_ERR, "fluid_winmidi_add_sysex_thread: GetMessage() failed."); + break; + } + + if(msg.message == WM_CLOSE) + { + break; + } + + switch(msg.message) + { + case MM_MIM_LONGDATA: + midiInAddBuffer(dev->hmidiin, (LPMIDIHDR)msg.lParam, sizeof(MIDIHDR)); + break; + } } - if (msg.message == WM_CLOSE) - break; - - switch (msg.message) { - case MM_MIM_LONGDATA: - midiInAddBuffer(dev->hmidiin, (LPMIDIHDR)msg.lParam, sizeof(MIDIHDR)); - break; - } - } - - return 0; + return 0; } /* * new_fluid_winmidi_driver */ -fluid_midi_driver_t* -new_fluid_winmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, void* data) +fluid_midi_driver_t * +new_fluid_winmidi_driver(fluid_settings_t *settings, + handle_midi_event_func_t handler, void *data) { - fluid_winmidi_driver_t* dev; - MIDIHDR *hdr; - MMRESULT res; - UINT i, num, midi_num = 0; - MIDIINCAPS in_caps; - char* devname = NULL; + fluid_winmidi_driver_t *dev; + MIDIHDR *hdr; + MMRESULT res; + UINT i, num, midi_num = 0; + MIDIINCAPS in_caps; + char *devname = NULL; - /* not much use doing anything */ - if (handler == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid argument"); - return NULL; - } - - dev = FLUID_MALLOC(sizeof(fluid_winmidi_driver_t)); - if (dev == NULL) { - return NULL; - } - - FLUID_MEMSET (dev, 0, sizeof (fluid_winmidi_driver_t)); - - dev->hmidiin = NULL; - dev->driver.handler = handler; - dev->driver.data = data; - - /* get the device name. if none is specified, use the default device. */ - if(fluid_settings_dupstr(settings, "midi.winmidi.device", &devname) != FLUID_OK || !devname) { - devname = FLUID_STRDUP ("default"); - - if (!devname) + /* not much use doing anything */ + if(handler == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; + FLUID_LOG(FLUID_ERR, "Invalid argument"); + return NULL; } - } - - /* check if there any midi devices installed */ - num = midiInGetNumDevs(); - if (num == 0) { - FLUID_LOG(FLUID_ERR, "no MIDI in devices found"); - goto error_recovery; - } - /* find the device */ - if (FLUID_STRCASECMP("default", devname) != 0) { - for (i = 0; i < num; i++) { - res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS)); - if (res == MMSYSERR_NOERROR) { - FLUID_LOG(FLUID_DBG, "Testing midi device: %s\n", in_caps.szPname); - if (FLUID_STRCASECMP(devname, in_caps.szPname) == 0) { - FLUID_LOG(FLUID_DBG, "Selected midi device number: %d\n", i); - midi_num = i; - break; + dev = FLUID_MALLOC(sizeof(fluid_winmidi_driver_t)); + + if(dev == NULL) + { + return NULL; + } + + FLUID_MEMSET(dev, 0, sizeof(fluid_winmidi_driver_t)); + + dev->hmidiin = NULL; + dev->driver.handler = handler; + dev->driver.data = data; + + /* get the device name. if none is specified, use the default device. */ + if(fluid_settings_dupstr(settings, "midi.winmidi.device", &devname) != FLUID_OK || !devname) + { + devname = FLUID_STRDUP("default"); + + if(!devname) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; } - } } - if (midi_num != i) { - FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname); - goto error_recovery; - } - } - /* try opening the device */ - res = midiInOpen(&dev->hmidiin, midi_num, - (DWORD_PTR) fluid_winmidi_callback, - (DWORD_PTR) dev, CALLBACK_FUNCTION); - if (res != MMSYSERR_NOERROR) { - FLUID_LOG(FLUID_ERR, "Couldn't open MIDI input: %s (error %d)", - fluid_winmidi_input_error(res), res); - goto error_recovery; - } + /* check if there any midi devices installed */ + num = midiInGetNumDevs(); - /* Prepare and add SYSEX buffers */ - for (i = 0; i < MIDI_SYSEX_BUF_COUNT; i++) - { - hdr = &dev->sysExHdrs[i]; - - hdr->lpData = (LPSTR)&dev->sysExBuf[i * MIDI_SYSEX_MAX_SIZE]; - hdr->dwBufferLength = MIDI_SYSEX_MAX_SIZE; - - /* Prepare a buffer for SYSEX data and add it */ - res = midiInPrepareHeader (dev->hmidiin, hdr, sizeof (MIDIHDR)); - - if (res == MMSYSERR_NOERROR) + if(num == 0) { - res = midiInAddBuffer (dev->hmidiin, hdr, sizeof (MIDIHDR)); - - if (res != MMSYSERR_NOERROR) - { - FLUID_LOG (FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)", - fluid_winmidi_input_error (res), res); - midiInUnprepareHeader (dev->hmidiin, hdr, sizeof (MIDIHDR)); - } + FLUID_LOG(FLUID_ERR, "no MIDI in devices found"); + goto error_recovery; } - else FLUID_LOG (FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)", - fluid_winmidi_input_error (res), res); - } - /* Create thread which processes re-adding SYSEX buffers */ - dev->hThread = CreateThread( - NULL, - 0, - (LPTHREAD_START_ROUTINE) - fluid_winmidi_add_sysex_thread, - dev, - 0, - &dev->dwThread); + /* find the device */ + if(FLUID_STRCASECMP("default", devname) != 0) + { + for(i = 0; i < num; i++) + { + res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS)); - if (dev->hThread == NULL) - { - FLUID_LOG(FLUID_ERR, "Failed to create SYSEX buffer processing thread"); - goto error_recovery; - } + if(res == MMSYSERR_NOERROR) + { + FLUID_LOG(FLUID_DBG, "Testing midi device: %s\n", in_caps.szPname); - /* Start the MIDI input interface */ - if (midiInStart(dev->hmidiin) != MMSYSERR_NOERROR) { - FLUID_LOG(FLUID_ERR, "Failed to start the MIDI input. MIDI input not available."); - goto error_recovery; - } + if(FLUID_STRCASECMP(devname, in_caps.szPname) == 0) + { + FLUID_LOG(FLUID_DBG, "Selected midi device number: %d\n", i); + midi_num = i; + break; + } + } + } - if (devname) FLUID_FREE (devname); /* -- free device name */ + if(midi_num != i) + { + FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname); + goto error_recovery; + } + } - return (fluid_midi_driver_t*) dev; + /* try opening the device */ + res = midiInOpen(&dev->hmidiin, midi_num, + (DWORD_PTR) fluid_winmidi_callback, + (DWORD_PTR) dev, CALLBACK_FUNCTION); - error_recovery: - if (devname) FLUID_FREE (devname); /* -- free device name */ - delete_fluid_winmidi_driver((fluid_midi_driver_t*) dev); - return NULL; + if(res != MMSYSERR_NOERROR) + { + FLUID_LOG(FLUID_ERR, "Couldn't open MIDI input: %s (error %d)", + fluid_winmidi_input_error(res), res); + goto error_recovery; + } + + /* Prepare and add SYSEX buffers */ + for(i = 0; i < MIDI_SYSEX_BUF_COUNT; i++) + { + hdr = &dev->sysExHdrs[i]; + + hdr->lpData = (LPSTR)&dev->sysExBuf[i * MIDI_SYSEX_MAX_SIZE]; + hdr->dwBufferLength = MIDI_SYSEX_MAX_SIZE; + + /* Prepare a buffer for SYSEX data and add it */ + res = midiInPrepareHeader(dev->hmidiin, hdr, sizeof(MIDIHDR)); + + if(res == MMSYSERR_NOERROR) + { + res = midiInAddBuffer(dev->hmidiin, hdr, sizeof(MIDIHDR)); + + if(res != MMSYSERR_NOERROR) + { + FLUID_LOG(FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)", + fluid_winmidi_input_error(res), res); + midiInUnprepareHeader(dev->hmidiin, hdr, sizeof(MIDIHDR)); + } + } + else + FLUID_LOG(FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)", + fluid_winmidi_input_error(res), res); + } + + /* Create thread which processes re-adding SYSEX buffers */ + dev->hThread = CreateThread( + NULL, + 0, + (LPTHREAD_START_ROUTINE) + fluid_winmidi_add_sysex_thread, + dev, + 0, + &dev->dwThread); + + if(dev->hThread == NULL) + { + FLUID_LOG(FLUID_ERR, "Failed to create SYSEX buffer processing thread"); + goto error_recovery; + } + + /* Start the MIDI input interface */ + if(midiInStart(dev->hmidiin) != MMSYSERR_NOERROR) + { + FLUID_LOG(FLUID_ERR, "Failed to start the MIDI input. MIDI input not available."); + goto error_recovery; + } + + if(devname) + { + FLUID_FREE(devname); /* -- free device name */ + } + + return (fluid_midi_driver_t *) dev; + +error_recovery: + + if(devname) + { + FLUID_FREE(devname); /* -- free device name */ + } + + delete_fluid_winmidi_driver((fluid_midi_driver_t *) dev); + return NULL; } /* * delete_fluid_winmidi_driver */ void -delete_fluid_winmidi_driver(fluid_midi_driver_t* p) +delete_fluid_winmidi_driver(fluid_midi_driver_t *p) { - fluid_winmidi_driver_t* dev = (fluid_winmidi_driver_t*) p; - fluid_return_if_fail (dev != NULL); + fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *) p; + fluid_return_if_fail(dev != NULL); - if (dev->hThread != NULL) - { - PostThreadMessage(dev->dwThread, WM_CLOSE, 0, 0); - WaitForSingleObject(dev->hThread, INFINITE); + if(dev->hThread != NULL) + { + PostThreadMessage(dev->dwThread, WM_CLOSE, 0, 0); + WaitForSingleObject(dev->hThread, INFINITE); - dev->hThread = NULL; - } + dev->hThread = NULL; + } - if (dev->hmidiin != NULL) - { - midiInStop(dev->hmidiin); - midiInReset(dev->hmidiin); - midiInClose(dev->hmidiin); - } + if(dev->hmidiin != NULL) + { + midiInStop(dev->hmidiin); + midiInReset(dev->hmidiin); + midiInClose(dev->hmidiin); + } - FLUID_FREE(dev); + FLUID_FREE(dev); } void CALLBACK fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - fluid_winmidi_driver_t* dev = (fluid_winmidi_driver_t *) dwInstance; - fluid_midi_event_t event; - LPMIDIHDR pMidiHdr; - unsigned char *data; - unsigned int msg_param = (unsigned int) dwParam1; + fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *) dwInstance; + fluid_midi_event_t event; + LPMIDIHDR pMidiHdr; + unsigned char *data; + unsigned int msg_param = (unsigned int) dwParam1; - switch (wMsg) { - case MIM_OPEN: - break; - - case MIM_CLOSE: - break; - - case MIM_DATA: - event.type = msg_type(msg_param); - event.channel = msg_chan(msg_param); - - if (event.type != PITCH_BEND) { - event.param1 = msg_p1(msg_param); - event.param2 = msg_p2(msg_param); - } else { /* Pitch bend is a 14 bit value */ - event.param1 = (msg_p2 (msg_param) << 7) | msg_p1 (msg_param); - event.param2 = 0; - } - - (*dev->driver.handler)(dev->driver.data, &event); - break; - - case MIM_LONGDATA: /* SYSEX data */ - if (dev->hThread == NULL) - break; - - pMidiHdr = (LPMIDIHDR)dwParam1; - data = (unsigned char *)(pMidiHdr->lpData); - - /* We only process complete SYSEX messages (discard those that are too small or too large) */ - if (pMidiHdr->dwBytesRecorded > 2 && data[0] == 0xF0 - && data[pMidiHdr->dwBytesRecorded - 1] == 0xF7) + switch(wMsg) { - fluid_midi_event_set_sysex (&event, pMidiHdr->lpData + 1, - pMidiHdr->dwBytesRecorded - 2, FALSE); - (*dev->driver.handler)(dev->driver.data, &event); + case MIM_OPEN: + break; + + case MIM_CLOSE: + break; + + case MIM_DATA: + event.type = msg_type(msg_param); + event.channel = msg_chan(msg_param); + + if(event.type != PITCH_BEND) + { + event.param1 = msg_p1(msg_param); + event.param2 = msg_p2(msg_param); + } + else /* Pitch bend is a 14 bit value */ + { + event.param1 = (msg_p2(msg_param) << 7) | msg_p1(msg_param); + event.param2 = 0; + } + + (*dev->driver.handler)(dev->driver.data, &event); + break; + + case MIM_LONGDATA: /* SYSEX data */ + if(dev->hThread == NULL) + { + break; + } + + pMidiHdr = (LPMIDIHDR)dwParam1; + data = (unsigned char *)(pMidiHdr->lpData); + + /* We only process complete SYSEX messages (discard those that are too small or too large) */ + if(pMidiHdr->dwBytesRecorded > 2 && data[0] == 0xF0 + && data[pMidiHdr->dwBytesRecorded - 1] == 0xF7) + { + fluid_midi_event_set_sysex(&event, pMidiHdr->lpData + 1, + pMidiHdr->dwBytesRecorded - 2, FALSE); + (*dev->driver.handler)(dev->driver.data, &event); + } + + PostThreadMessage(dev->dwThread, MM_MIM_LONGDATA, 0, dwParam1); + break; + + case MIM_ERROR: + break; + + case MIM_LONGERROR: + break; + + case MIM_MOREDATA: + break; } - - PostThreadMessage(dev->dwThread, MM_MIM_LONGDATA, 0, dwParam1); - break; - - case MIM_ERROR: - break; - - case MIM_LONGERROR: - break; - - case MIM_MOREDATA: - break; - } } -static char* +static char * fluid_winmidi_input_error(MMRESULT no) { - midiInGetErrorText(no, fluid_winmidi_error_buffer, 256); - return fluid_winmidi_error_buffer; + midiInGetErrorText(no, fluid_winmidi_error_buffer, 256); + return fluid_winmidi_error_buffer; } #endif /* WINMIDI_SUPPORT */ diff --git a/src/fluidsynth.c b/src/fluidsynth.c index c0fe7025..0de01515 100644 --- a/src/fluidsynth.c +++ b/src/fluidsynth.c @@ -48,205 +48,264 @@ void print_configure(void); /* * the globals */ -fluid_cmd_handler_t* cmd_handler = NULL; +fluid_cmd_handler_t *cmd_handler = NULL; int option_help = 0; /* set to 1 if "-o help" is specified */ /* Process a command line option -o setting=value, for example: -o synth.polyhony=16 */ -void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg) +void process_o_cmd_line_option(fluid_settings_t *settings, char *optarg) { - char* val; - int hints; - int ival; + char *val; + int hints; + int ival; - for (val = optarg; *val != '\0'; val++) { - if (*val == '=') { - *val++ = 0; - break; - } - } - - /* did user request list of settings */ - if (FLUID_STRCMP (optarg, "help") == 0) - { - option_help = 1; - return; - } - - if (FLUID_STRCMP (optarg, "") == 0) { - fprintf (stderr, "Invalid -o option (name part is empty)\n"); - return; - } - - switch(fluid_settings_get_type(settings, optarg)){ - case FLUID_NUM_TYPE: - if (fluid_settings_setnum (settings, optarg, atof (val)) != FLUID_OK) + for(val = optarg; *val != '\0'; val++) { - fprintf (stderr, "Failed to set floating point parameter '%s'\n", optarg); - exit (1); + if(*val == '=') + { + *val++ = 0; + break; + } } - break; - case FLUID_INT_TYPE: - if (fluid_settings_get_hints (settings, optarg, &hints) == FLUID_OK - && hints & FLUID_HINT_TOGGLED) - { - if (FLUID_STRCASECMP (val, "yes") == 0 - || FLUID_STRCASECMP (val, "true") == 0 - || FLUID_STRCASECMP (val, "t") == 0) - ival = 1; - else ival = atoi (val); - } - else ival = atoi (val); - if (fluid_settings_setint (settings, optarg, ival) != FLUID_OK) + /* did user request list of settings */ + if(FLUID_STRCMP(optarg, "help") == 0) { - fprintf (stderr, "Failed to set integer parameter '%s'\n", optarg); - exit (1); + option_help = 1; + return; } - break; - case FLUID_STR_TYPE: - if (fluid_settings_setstr (settings, optarg, val) != FLUID_OK) + + if(FLUID_STRCMP(optarg, "") == 0) { - fprintf (stderr, "Failed to set string parameter '%s'\n", optarg); - exit (1); + fprintf(stderr, "Invalid -o option (name part is empty)\n"); + return; + } + + switch(fluid_settings_get_type(settings, optarg)) + { + case FLUID_NUM_TYPE: + if(fluid_settings_setnum(settings, optarg, atof(val)) != FLUID_OK) + { + fprintf(stderr, "Failed to set floating point parameter '%s'\n", optarg); + exit(1); + } + + break; + + case FLUID_INT_TYPE: + if(fluid_settings_get_hints(settings, optarg, &hints) == FLUID_OK + && hints & FLUID_HINT_TOGGLED) + { + if(FLUID_STRCASECMP(val, "yes") == 0 + || FLUID_STRCASECMP(val, "true") == 0 + || FLUID_STRCASECMP(val, "t") == 0) + { + ival = 1; + } + else + { + ival = atoi(val); + } + } + else + { + ival = atoi(val); + } + + if(fluid_settings_setint(settings, optarg, ival) != FLUID_OK) + { + fprintf(stderr, "Failed to set integer parameter '%s'\n", optarg); + exit(1); + } + + break; + + case FLUID_STR_TYPE: + if(fluid_settings_setstr(settings, optarg, val) != FLUID_OK) + { + fprintf(stderr, "Failed to set string parameter '%s'\n", optarg); + exit(1); + } + + break; + + default: + fprintf(stderr, "Setting parameter '%s' not found\n", optarg); + exit(1); } - break; - default: - fprintf (stderr, "Setting parameter '%s' not found\n", optarg); - exit (1); - } } static void -print_pretty_int (int i) +print_pretty_int(int i) { - if (i == INT_MAX) printf ("MAXINT"); - else if (i == INT_MIN) printf ("MININT"); - else printf ("%d", i); + if(i == INT_MAX) + { + printf("MAXINT"); + } + else if(i == INT_MIN) + { + printf("MININT"); + } + else + { + printf("%d", i); + } } typedef struct { - int count; /* Total count of options */ - int curindex; /* Current index in options */ + int count; /* Total count of options */ + int curindex; /* Current index in options */ } OptionBag; /* Function to display each string option value */ static void -settings_option_foreach_func (void *data, const char *name, const char *option) +settings_option_foreach_func(void *data, const char *name, const char *option) { - OptionBag *bag = data; + OptionBag *bag = data; - bag->curindex++; + bag->curindex++; - if (bag->curindex < bag->count) - printf ("'%s',", option); - else printf ("'%s'", option); + if(bag->curindex < bag->count) + { + printf("'%s',", option); + } + else + { + printf("'%s'", option); + } } /* fluid_settings_foreach function for displaying option help "-o help" */ static void -settings_foreach_func (void *data, const char *name, int type) +settings_foreach_func(void *data, const char *name, int type) { - fluid_settings_t *settings = (fluid_settings_t *)data; - double dmin, dmax, ddef; - int imin, imax, idef, hints; - char *defstr; - int count; - OptionBag bag; + fluid_settings_t *settings = (fluid_settings_t *)data; + double dmin, dmax, ddef; + int imin, imax, idef, hints; + char *defstr; + int count; + OptionBag bag; - switch (type) - { - case FLUID_NUM_TYPE: - fluid_settings_getnum_range (settings, name, &dmin, &dmax); - fluid_settings_getnum_default (settings, name, &ddef); - printf ("%-24s FLOAT [min=%0.3f, max=%0.3f, def=%0.3f]\n", - name, dmin, dmax, ddef); - break; - case FLUID_INT_TYPE: - fluid_settings_getint_range (settings, name, &imin, &imax); - fluid_settings_getint_default (settings, name, &idef); - fluid_settings_get_hints (settings, name, &hints); - - if (!(hints & FLUID_HINT_TOGGLED)) + switch(type) { - printf ("%-24s INT [min=", name); - print_pretty_int (imin); - printf (", max="); - print_pretty_int (imax); - printf (", def="); - print_pretty_int (idef); - printf ("]\n"); + case FLUID_NUM_TYPE: + fluid_settings_getnum_range(settings, name, &dmin, &dmax); + fluid_settings_getnum_default(settings, name, &ddef); + printf("%-24s FLOAT [min=%0.3f, max=%0.3f, def=%0.3f]\n", + name, dmin, dmax, ddef); + break; + + case FLUID_INT_TYPE: + fluid_settings_getint_range(settings, name, &imin, &imax); + fluid_settings_getint_default(settings, name, &idef); + fluid_settings_get_hints(settings, name, &hints); + + if(!(hints & FLUID_HINT_TOGGLED)) + { + printf("%-24s INT [min=", name); + print_pretty_int(imin); + printf(", max="); + print_pretty_int(imax); + printf(", def="); + print_pretty_int(idef); + printf("]\n"); + } + else + { + printf("%-24s BOOL [def=%s]\n", name, idef ? "True" : "False"); + } + + break; + + case FLUID_STR_TYPE: + printf("%-24s STR", name); + + fluid_settings_getstr_default(settings, name, &defstr); + count = fluid_settings_option_count(settings, name); + + if(defstr || count > 0) + { + if(defstr && count > 0) + { + printf(" [def='%s' vals:", defstr); + } + else if(defstr) + { + printf(" [def='%s'", defstr); + } + else + { + printf(" [vals:"); + } + + if(count > 0) + { + bag.count = count; + bag.curindex = 0; + fluid_settings_foreach_option(settings, name, &bag, + settings_option_foreach_func); + } + + printf("]\n"); + } + else + { + printf("\n"); + } + + break; + + case FLUID_SET_TYPE: + printf("%-24s SET\n", name); + break; } - else printf ("%-24s BOOL [def=%s]\n", name, idef ? "True" : "False"); - break; - case FLUID_STR_TYPE: - printf ("%-24s STR", name); - - fluid_settings_getstr_default (settings, name, &defstr); - count = fluid_settings_option_count (settings, name); - - if (defstr || count > 0) - { - if (defstr && count > 0) printf (" [def='%s' vals:", defstr); - else if (defstr) printf (" [def='%s'", defstr); - else printf (" [vals:"); - - if (count > 0) - { - bag.count = count; - bag.curindex = 0; - fluid_settings_foreach_option (settings, name, &bag, - settings_option_foreach_func); - } - - printf ("]\n"); - } - else printf ("\n"); - break; - case FLUID_SET_TYPE: - printf ("%-24s SET\n", name); - break; - } } /* Output options for a setting string to stdout */ static void -show_settings_str_options (fluid_settings_t *settings, char *name) +show_settings_str_options(fluid_settings_t *settings, char *name) { - OptionBag bag; + OptionBag bag; - bag.count = fluid_settings_option_count (settings, name); - bag.curindex = 0; - fluid_settings_foreach_option (settings, name, &bag, - settings_option_foreach_func); - printf ("\n"); + bag.count = fluid_settings_option_count(settings, name); + bag.curindex = 0; + fluid_settings_foreach_option(settings, name, &bag, + settings_option_foreach_func); + printf("\n"); } static void -fast_render_loop(fluid_settings_t* settings, fluid_synth_t* synth, fluid_player_t* player) +fast_render_loop(fluid_settings_t *settings, fluid_synth_t *synth, fluid_player_t *player) { - fluid_file_renderer_t* renderer; + fluid_file_renderer_t *renderer; - renderer = new_fluid_file_renderer (synth); - if (!renderer) return; + renderer = new_fluid_file_renderer(synth); - while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) { - if (fluid_file_renderer_process_block(renderer) != FLUID_OK) { - break; + if(!renderer) + { + return; } - } - delete_fluid_file_renderer(renderer); + + while(fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) + { + if(fluid_file_renderer_process_block(renderer) != FLUID_OK) + { + break; + } + } + + delete_fluid_file_renderer(renderer); } /* * main * Process initialization steps in the following order: - + 1)creating the settings. 2)reading/setting all options in command line. 3)creating the synth. - 4)loading the soundfonts specified in command line + 4)loading the soundfonts specified in command line (multiple soundfonts loading is possible). 5)create the audio driver (if not fast rendering). 6)create the router. @@ -260,553 +319,701 @@ fast_render_loop(fluid_settings_t* settings, fluid_synth_t* synth, fluid_player_ 13)create a synchronous user shell if interactive. 14)entering fast rendering loop if requested. */ -int main(int argc, char** argv) +int main(int argc, char **argv) { - fluid_settings_t* settings; - int arg1 = 1; - char buf[512]; - int c, i; - int interactive = 1; - int midi_in = 1; - fluid_player_t* player = NULL; - fluid_midi_router_t* router = NULL; - //fluid_sequencer_t* sequencer = NULL; - fluid_midi_driver_t* mdriver = NULL; - fluid_audio_driver_t* adriver = NULL; - fluid_synth_t* synth = NULL; + fluid_settings_t *settings; + int arg1 = 1; + char buf[512]; + int c, i; + int interactive = 1; + int midi_in = 1; + fluid_player_t *player = NULL; + fluid_midi_router_t *router = NULL; + //fluid_sequencer_t* sequencer = NULL; + fluid_midi_driver_t *mdriver = NULL; + fluid_audio_driver_t *adriver = NULL; + fluid_synth_t *synth = NULL; #ifdef NETWORK_SUPPORT - fluid_server_t* server = NULL; - int with_server = 0; + fluid_server_t *server = NULL; + int with_server = 0; #endif - char* config_file = NULL; - int audio_groups = 0; - int audio_channels = 0; - int dump = 0; - int fast_render = 0; - static const char optchars[] = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:R:r:sT:Vvz:"; + char *config_file = NULL; + int audio_groups = 0; + int audio_channels = 0; + int dump = 0; + int fast_render = 0; + static const char optchars[] = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:R:r:sT:Vvz:"; #ifdef LASH_ENABLED - int connect_lash = 1; - int enabled_lash = 0; /* set to TRUE if lash gets enabled */ - fluid_lash_args_t *lash_args; + int connect_lash = 1; + int enabled_lash = 0; /* set to TRUE if lash gets enabled */ + fluid_lash_args_t *lash_args; - lash_args = fluid_lash_extract_args (&argc, &argv); + lash_args = fluid_lash_extract_args(&argc, &argv); #endif - print_welcome (); + print_welcome(); - /* create the settings */ - settings = new_fluid_settings(); + /* create the settings */ + settings = new_fluid_settings(); - /* reading / setting options from the command line */ + /* reading / setting options from the command line */ #ifdef GETOPT_SUPPORT /* pre section of GETOPT supported argument handling */ - opterr = 0; + opterr = 0; - while (1) { - int option_index = 0; - - static struct option long_options[] = { - {"audio-bufcount", 1, 0, 'c'}, - {"audio-bufsize", 1, 0, 'z'}, - {"audio-channels", 1, 0, 'L'}, - {"audio-driver", 1, 0, 'a'}, - {"audio-file-endian", 1, 0, 'E'}, - {"audio-file-format", 1, 0, 'O'}, - {"audio-file-type", 1, 0, 'T'}, - {"audio-groups", 1, 0, 'G'}, - {"chorus", 1, 0, 'C'}, - {"connect-jack-outputs", 0, 0, 'j'}, - {"disable-lash", 0, 0, 'l'}, - {"dump", 0, 0, 'd'}, - {"fast-render", 1, 0, 'F'}, - {"gain", 1, 0, 'g'}, - {"help", 0, 0, 'h'}, - {"load-config", 1, 0, 'f'}, - {"midi-channels", 1, 0, 'K'}, - {"midi-driver", 1, 0, 'm'}, - {"no-midi-in", 0, 0, 'n'}, - {"no-shell", 0, 0, 'i'}, - {"option", 1, 0, 'o'}, - {"portname", 1, 0, 'p'}, - {"reverb", 1, 0, 'R'}, - {"sample-rate", 1, 0, 'r'}, - {"server", 0, 0, 's'}, - {"verbose", 0, 0, 'v'}, - {"version", 0, 0, 'V'}, - {0, 0, 0, 0} - }; - - c = getopt_long(argc, argv, optchars, long_options, &option_index); - if (c == -1) { - break; - } -#else /* "pre" section to non getopt argument handling */ - for (i = 1; i < argc; i++) { - char *optarg; - - /* Skip non switch arguments (assume they are file names) */ - if ((argv[i][0] != '-') || (argv[i][1] == '\0')) break; - - c = argv[i][1]; - - optarg = strchr (optchars, c); /* find the option character in optchars */ - if (optarg && optarg[1] == ':') /* colon follows if switch argument expected */ + while(1) { - if (++i >= argc) - { - printf ("Option -%c requires an argument\n", c); - print_usage(); - exit(0); - } - else - { - optarg = argv[i]; - if (optarg[0] == '-') - { - printf ("Expected argument to option -%c found switch instead\n", c); - print_usage(); - exit(0); - } - } - } - else optarg = ""; + int option_index = 0; + + static struct option long_options[] = + { + {"audio-bufcount", 1, 0, 'c'}, + {"audio-bufsize", 1, 0, 'z'}, + {"audio-channels", 1, 0, 'L'}, + {"audio-driver", 1, 0, 'a'}, + {"audio-file-endian", 1, 0, 'E'}, + {"audio-file-format", 1, 0, 'O'}, + {"audio-file-type", 1, 0, 'T'}, + {"audio-groups", 1, 0, 'G'}, + {"chorus", 1, 0, 'C'}, + {"connect-jack-outputs", 0, 0, 'j'}, + {"disable-lash", 0, 0, 'l'}, + {"dump", 0, 0, 'd'}, + {"fast-render", 1, 0, 'F'}, + {"gain", 1, 0, 'g'}, + {"help", 0, 0, 'h'}, + {"load-config", 1, 0, 'f'}, + {"midi-channels", 1, 0, 'K'}, + {"midi-driver", 1, 0, 'm'}, + {"no-midi-in", 0, 0, 'n'}, + {"no-shell", 0, 0, 'i'}, + {"option", 1, 0, 'o'}, + {"portname", 1, 0, 'p'}, + {"reverb", 1, 0, 'R'}, + {"sample-rate", 1, 0, 'r'}, + {"server", 0, 0, 's'}, + {"verbose", 0, 0, 'v'}, + {"version", 0, 0, 'V'}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, optchars, long_options, &option_index); + + if(c == -1) + { + break; + } + +#else /* "pre" section to non getopt argument handling */ + + for(i = 1; i < argc; i++) + { + char *optarg; + + /* Skip non switch arguments (assume they are file names) */ + if((argv[i][0] != '-') || (argv[i][1] == '\0')) + { + break; + } + + c = argv[i][1]; + + optarg = strchr(optchars, c); /* find the option character in optchars */ + + if(optarg && optarg[1] == ':') /* colon follows if switch argument expected */ + { + if(++i >= argc) + { + printf("Option -%c requires an argument\n", c); + print_usage(); + exit(0); + } + else + { + optarg = argv[i]; + + if(optarg[0] == '-') + { + printf("Expected argument to option -%c found switch instead\n", c); + print_usage(); + exit(0); + } + } + } + else + { + optarg = ""; + } + #endif - switch (c) { + switch(c) + { #ifdef GETOPT_SUPPORT - case 0: /* shouldn't normally happen, a long option's flag is set to NULL */ - printf ("option %s", long_options[option_index].name); - if (optarg) { - printf (" with arg %s", optarg); - } - printf ("\n"); - break; + + case 0: /* shouldn't normally happen, a long option's flag is set to NULL */ + printf("option %s", long_options[option_index].name); + + if(optarg) + { + printf(" with arg %s", optarg); + } + + printf("\n"); + break; #endif - case 'a': - if (FLUID_STRCMP (optarg, "help") == 0) - { - printf ("-a options (audio driver):\n "); - show_settings_str_options (settings, "audio.driver"); - exit (0); - } - else fluid_settings_setstr(settings, "audio.driver", optarg); - break; - case 'C': - if ((optarg != NULL) && ((FLUID_STRCMP(optarg, "0") == 0) || (FLUID_STRCMP(optarg, "no") == 0))) { - fluid_settings_setint(settings, "synth.chorus.active", FALSE); - } else { - fluid_settings_setint(settings, "synth.chorus.active", TRUE); - } - break; - case 'c': - fluid_settings_setint(settings, "audio.periods", atoi(optarg)); - break; - case 'd': - dump = 1; - break; - case 'E': - if (FLUID_STRCMP (optarg, "help") == 0) - { - printf ("-E options (audio file byte order):\n "); - show_settings_str_options (settings, "audio.file.endian"); + + case 'a': + if(FLUID_STRCMP(optarg, "help") == 0) + { + printf("-a options (audio driver):\n "); + show_settings_str_options(settings, "audio.driver"); + exit(0); + } + else + { + fluid_settings_setstr(settings, "audio.driver", optarg); + } + + break; + + case 'C': + if((optarg != NULL) && ((FLUID_STRCMP(optarg, "0") == 0) || (FLUID_STRCMP(optarg, "no") == 0))) + { + fluid_settings_setint(settings, "synth.chorus.active", FALSE); + } + else + { + fluid_settings_setint(settings, "synth.chorus.active", TRUE); + } + + break; + + case 'c': + fluid_settings_setint(settings, "audio.periods", atoi(optarg)); + break; + + case 'd': + dump = 1; + break; + + case 'E': + if(FLUID_STRCMP(optarg, "help") == 0) + { + printf("-E options (audio file byte order):\n "); + show_settings_str_options(settings, "audio.file.endian"); #if LIBSNDFILE_SUPPORT - printf ("\nauto: Use audio file format's default endian byte order\n" - "cpu: Use CPU native byte order\n"); + printf("\nauto: Use audio file format's default endian byte order\n" + "cpu: Use CPU native byte order\n"); #else - printf ("\nNOTE: No libsndfile support!\n" - "cpu: Use CPU native byte order\n"); + printf("\nNOTE: No libsndfile support!\n" + "cpu: Use CPU native byte order\n"); #endif - exit (0); - } - else fluid_settings_setstr(settings, "audio.file.endian", optarg); - break; - case 'f': - config_file = optarg; - break; - case 'F': - fluid_settings_setstr(settings, "audio.file.name", optarg); - fast_render = 1; - break; - case 'G': - audio_groups = atoi(optarg); - break; - case 'g': - fluid_settings_setnum(settings, "synth.gain", atof(optarg)); - break; - case 'h': - print_help(settings); - break; - case 'i': - interactive = 0; - break; - case 'j': - fluid_settings_setint(settings, "audio.jack.autoconnect", 1); - break; - case 'K': - fluid_settings_setint(settings, "synth.midi-channels", atoi(optarg)); - break; - case 'L': - audio_channels = atoi(optarg); - fluid_settings_setint(settings, "synth.audio-channels", audio_channels); - break; - case 'l': /* disable LASH */ + exit(0); + } + else + { + fluid_settings_setstr(settings, "audio.file.endian", optarg); + } + + break; + + case 'f': + config_file = optarg; + break; + + case 'F': + fluid_settings_setstr(settings, "audio.file.name", optarg); + fast_render = 1; + break; + + case 'G': + audio_groups = atoi(optarg); + break; + + case 'g': + fluid_settings_setnum(settings, "synth.gain", atof(optarg)); + break; + + case 'h': + print_help(settings); + break; + + case 'i': + interactive = 0; + break; + + case 'j': + fluid_settings_setint(settings, "audio.jack.autoconnect", 1); + break; + + case 'K': + fluid_settings_setint(settings, "synth.midi-channels", atoi(optarg)); + break; + + case 'L': + audio_channels = atoi(optarg); + fluid_settings_setint(settings, "synth.audio-channels", audio_channels); + break; + + case 'l': /* disable LASH */ #ifdef LASH_ENABLED - connect_lash = 0; + connect_lash = 0; #endif - break; - case 'm': - if (FLUID_STRCMP (optarg, "help") == 0) - { - printf ("-m options (MIDI driver):\n "); - show_settings_str_options (settings, "midi.driver"); - exit (0); - } - else fluid_settings_setstr(settings, "midi.driver", optarg); - break; - case 'n': - midi_in = 0; - break; - case 'O': - if (FLUID_STRCMP (optarg, "help") == 0) - { - printf ("-O options (audio file format):\n "); - show_settings_str_options (settings, "audio.file.format"); + break; + + case 'm': + if(FLUID_STRCMP(optarg, "help") == 0) + { + printf("-m options (MIDI driver):\n "); + show_settings_str_options(settings, "midi.driver"); + exit(0); + } + else + { + fluid_settings_setstr(settings, "midi.driver", optarg); + } + + break; + + case 'n': + midi_in = 0; + break; + + case 'O': + if(FLUID_STRCMP(optarg, "help") == 0) + { + printf("-O options (audio file format):\n "); + show_settings_str_options(settings, "audio.file.format"); #if LIBSNDFILE_SUPPORT - printf ("\ns8, s16, s24, s32: Signed PCM audio of the given number of bits\n"); - printf ("float, double: 32 bit and 64 bit floating point audio\n"); - printf ("u8: Unsigned 8 bit audio\n"); + printf("\ns8, s16, s24, s32: Signed PCM audio of the given number of bits\n"); + printf("float, double: 32 bit and 64 bit floating point audio\n"); + printf("u8: Unsigned 8 bit audio\n"); #else - printf ("\nNOTE: No libsndfile support!\n"); + printf("\nNOTE: No libsndfile support!\n"); #endif - exit (0); - } - else fluid_settings_setstr(settings, "audio.file.format", optarg); - break; - case 'o': - process_o_cmd_line_option(settings, optarg); - break; - case 'p' : - fluid_settings_setstr(settings, "midi.portname", optarg); - break; - case 'R': - if ((optarg != NULL) && ((FLUID_STRCMP(optarg, "0") == 0) || (FLUID_STRCMP(optarg, "no") == 0))) { - fluid_settings_setint(settings, "synth.reverb.active", FALSE); - } else { - fluid_settings_setint(settings, "synth.reverb.active", TRUE); - } - break; - case 'r': - fluid_settings_setnum(settings, "synth.sample-rate", atof(optarg)); - break; - case 's': + exit(0); + } + else + { + fluid_settings_setstr(settings, "audio.file.format", optarg); + } + + break; + + case 'o': + process_o_cmd_line_option(settings, optarg); + break; + + case 'p' : + fluid_settings_setstr(settings, "midi.portname", optarg); + break; + + case 'R': + if((optarg != NULL) && ((FLUID_STRCMP(optarg, "0") == 0) || (FLUID_STRCMP(optarg, "no") == 0))) + { + fluid_settings_setint(settings, "synth.reverb.active", FALSE); + } + else + { + fluid_settings_setint(settings, "synth.reverb.active", TRUE); + } + + break; + + case 'r': + fluid_settings_setnum(settings, "synth.sample-rate", atof(optarg)); + break; + + case 's': #ifdef NETWORK_SUPPORT - with_server = 1; + with_server = 1; #endif - break; - case 'T': - if (FLUID_STRCMP (optarg, "help") == 0) - { - printf ("-T options (audio file type):\n "); - show_settings_str_options (settings, "audio.file.type"); + break; + + case 'T': + if(FLUID_STRCMP(optarg, "help") == 0) + { + printf("-T options (audio file type):\n "); + show_settings_str_options(settings, "audio.file.type"); #if LIBSNDFILE_SUPPORT - printf ("\nauto: Determine type from file name extension, defaults to \"wav\"\n"); + printf("\nauto: Determine type from file name extension, defaults to \"wav\"\n"); #else - printf ("\nNOTE: No libsndfile support!\n"); + printf("\nNOTE: No libsndfile support!\n"); #endif - exit (0); - } - else fluid_settings_setstr(settings, "audio.file.type", optarg); - break; - case 'V': - print_configure(); - exit (0); - break; - case 'v': - fluid_settings_setint(settings, "synth.verbose", TRUE); - break; - case 'z': - fluid_settings_setint(settings, "audio.period-size", atoi(optarg)); - break; + exit(0); + } + else + { + fluid_settings_setstr(settings, "audio.file.type", optarg); + } + + break; + + case 'V': + print_configure(); + exit(0); + break; + + case 'v': + fluid_settings_setint(settings, "synth.verbose", TRUE); + break; + + case 'z': + fluid_settings_setint(settings, "audio.period-size", atoi(optarg)); + break; #ifdef GETOPT_SUPPORT - case '?': - printf ("Unknown option %c\n", optopt); - print_usage(); - exit(0); - break; - default: - printf ("?? getopt returned character code 0%o ??\n", c); - break; + + case '?': + printf("Unknown option %c\n", optopt); + print_usage(); + exit(0); + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + break; #else /* Non getopt default case */ - default: - printf ("Unknown switch '%c'\n", c); - print_usage(); - exit(0); - break; + + default: + printf("Unknown switch '%c'\n", c); + print_usage(); + exit(0); + break; #endif - } /* end of switch statement */ - } /* end of loop */ + } /* end of switch statement */ + } /* end of loop */ #ifdef GETOPT_SUPPORT - arg1 = optind; + arg1 = optind; #else - arg1 = i; + arg1 = i; #endif - /* option help requested? "-o help" */ - if (option_help) - { - printf ("FluidSynth settings:\n"); - fluid_settings_foreach (settings, settings, settings_foreach_func); - exit (0); - } + /* option help requested? "-o help" */ + if(option_help) + { + printf("FluidSynth settings:\n"); + fluid_settings_foreach(settings, settings, settings_foreach_func); + exit(0); + } #ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); #endif #ifdef LASH_ENABLED - /* connect to the lash server */ - if (connect_lash) + + /* connect to the lash server */ + if(connect_lash) { - enabled_lash = fluid_lash_connect (lash_args); - fluid_settings_setint (settings, "lash.enable", enabled_lash ? 1 : 0); + enabled_lash = fluid_lash_connect(lash_args); + fluid_settings_setint(settings, "lash.enable", enabled_lash ? 1 : 0); } + #endif - /* The 'groups' setting is relevant for LADSPA operation and channel mapping - * in rvoice_mixer. - * If not given, set number groups to number of audio channels, because - * they are the same (there is nothing between synth output and 'sound card') - */ - if ((audio_groups == 0) && (audio_channels != 0)) { - audio_groups = audio_channels; - } - if (audio_groups != 0) - { - fluid_settings_setint(settings, "synth.audio-groups", audio_groups); - } + /* The 'groups' setting is relevant for LADSPA operation and channel mapping + * in rvoice_mixer. + * If not given, set number groups to number of audio channels, because + * they are the same (there is nothing between synth output and 'sound card') + */ + if((audio_groups == 0) && (audio_channels != 0)) + { + audio_groups = audio_channels; + } - if (fast_render) - { - midi_in = 0; /* disable MIDI driver creation */ - interactive = 0; /* disable user shell creation */ + if(audio_groups != 0) + { + fluid_settings_setint(settings, "synth.audio-groups", audio_groups); + } + + if(fast_render) + { + midi_in = 0; /* disable MIDI driver creation */ + interactive = 0; /* disable user shell creation */ #ifdef NETWORK_SUPPORT - with_server = 0; /* disable tcp server shell creation */ + with_server = 0; /* disable tcp server shell creation */ #endif - fluid_settings_setstr(settings, "player.timing-source", "sample"); - fluid_settings_setint(settings, "synth.lock-memory", 0); - } - - /* create the synthesizer */ - synth = new_fluid_synth(settings); - if (synth == NULL) { - fprintf(stderr, "Failed to create the synthesizer\n"); - exit(-1); - } + fluid_settings_setstr(settings, "player.timing-source", "sample"); + fluid_settings_setint(settings, "synth.lock-memory", 0); + } - /* load the soundfonts (check that all non options are SoundFont or MIDI files) */ - for (i = arg1; i < argc; i++) { - if (fluid_is_soundfont(argv[i])) + /* create the synthesizer */ + synth = new_fluid_synth(settings); + + if(synth == NULL) { - if (fluid_synth_sfload(synth, argv[i], 1) == -1) - fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]); + fprintf(stderr, "Failed to create the synthesizer\n"); + exit(-1); } - else if (!fluid_is_midifile(argv[i])) - fprintf (stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n", - argv[i]); - } - /* start the synthesis thread */ - if (!fast_render) { - adriver = new_fluid_audio_driver(settings, synth); - if (adriver == NULL) { - fprintf(stderr, "Failed to create the audio driver\n"); - goto cleanup; + /* load the soundfonts (check that all non options are SoundFont or MIDI files) */ + for(i = arg1; i < argc; i++) + { + if(fluid_is_soundfont(argv[i])) + { + if(fluid_synth_sfload(synth, argv[i], 1) == -1) + { + fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]); + } + } + else if(!fluid_is_midifile(argv[i])) + { + fprintf(stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n", argv[i]); + } + } + + /* start the synthesis thread */ + if(!fast_render) + { + adriver = new_fluid_audio_driver(settings, synth); + + if(adriver == NULL) + { + fprintf(stderr, "Failed to create the audio driver\n"); + goto cleanup; + } } - } router = new_fluid_midi_router( - settings, - dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event, - (void*)synth); + settings, + dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event, + (void *)synth); - if (router == NULL) { - fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n" - "will be available. You can access the synthesizer \n" - "through the console.\n"); - } - - /* start the midi router and link it to the synth */ - if (midi_in && router != NULL) { - /* In dump mode, text output is generated for events going into and out of the router. - * The example dump functions are put into the chain before and after the router.. - */ - //sequencer = new_fluid_sequencer2(0); - mdriver = new_fluid_midi_driver( - settings, - dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event, - (void*) router); - if (mdriver == NULL) { - fprintf(stderr, "Failed to create the MIDI thread; no MIDI input\n" - "will be available. You can access the synthesizer \n" - "through the console.\n"); - } - } - - /* play the midi files, if any */ - for (i = arg1; i < argc; i++) { - if ((argv[i][0] != '-') && fluid_is_midifile(argv[i])) { - - if (player == NULL) { - player = new_fluid_player(synth); - if (player == NULL) { - fprintf(stderr, "Failed to create the midifile player.\n" - "Continuing without a player.\n"); - break; - } - if (router != NULL) + if(router == NULL) { - fluid_player_set_playback_callback(player, fluid_midi_router_handle_midi_event, router); + fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n" + "will be available. You can access the synthesizer \n" + "through the console.\n"); } - } - fluid_player_add(player, argv[i]); - } - } - /* start the player */ - if (player != NULL) - { - /* Try to load the default soundfont, if no soundfont specified */ - if (fluid_synth_get_sfont(synth, 0) == NULL) + /* start the midi router and link it to the synth */ + if(midi_in && router != NULL) { - char *s; - if (fluid_settings_dupstr(settings, "synth.default-soundfont", &s) != FLUID_OK) - s = NULL; - if ((s != NULL) && (s[0] != '\0')) - fluid_synth_sfload(synth, s, 1); - - FLUID_FREE(s); + /* In dump mode, text output is generated for events going into and out of the router. + * The example dump functions are put into the chain before and after the router.. + */ + //sequencer = new_fluid_sequencer2(0); + mdriver = new_fluid_midi_driver( + settings, + dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event, + (void *) router); + + if(mdriver == NULL) + { + fprintf(stderr, "Failed to create the MIDI thread; no MIDI input\n" + "will be available. You can access the synthesizer \n" + "through the console.\n"); + } } - fluid_player_play(player); - } + /* play the midi files, if any */ + for(i = arg1; i < argc; i++) + { + if((argv[i][0] != '-') && fluid_is_midifile(argv[i])) + { - /* try to load and execute the user or system configuration file */ - cmd_handler = new_fluid_cmd_handler(synth, router); - if (cmd_handler == NULL) { - fprintf(stderr, "Failed to create the command handler\n"); - goto cleanup; - } - - if (config_file != NULL) - { - fluid_source(cmd_handler, config_file); - } else if (fluid_get_userconf(buf, sizeof(buf)) != NULL) { - fluid_source(cmd_handler, buf); - } else if (fluid_get_sysconf(buf, sizeof(buf)) != NULL) { - fluid_source(cmd_handler, buf); - } - - /* run the server, if requested */ + if(player == NULL) + { + player = new_fluid_player(synth); + + if(player == NULL) + { + fprintf(stderr, "Failed to create the midifile player.\n" + "Continuing without a player.\n"); + break; + } + + if(router != NULL) + { + fluid_player_set_playback_callback(player, fluid_midi_router_handle_midi_event, router); + } + } + + fluid_player_add(player, argv[i]); + } + } + + /* start the player */ + if(player != NULL) + { + /* Try to load the default soundfont, if no soundfont specified */ + if(fluid_synth_get_sfont(synth, 0) == NULL) + { + char *s; + + if(fluid_settings_dupstr(settings, "synth.default-soundfont", &s) != FLUID_OK) + { + s = NULL; + } + + if((s != NULL) && (s[0] != '\0')) + { + fluid_synth_sfload(synth, s, 1); + } + + FLUID_FREE(s); + } + + fluid_player_play(player); + } + + /* try to load and execute the user or system configuration file */ + cmd_handler = new_fluid_cmd_handler(synth, router); + + if(cmd_handler == NULL) + { + fprintf(stderr, "Failed to create the command handler\n"); + goto cleanup; + } + + if(config_file != NULL) + { + fluid_source(cmd_handler, config_file); + } + else if(fluid_get_userconf(buf, sizeof(buf)) != NULL) + { + fluid_source(cmd_handler, buf); + } + else if(fluid_get_sysconf(buf, sizeof(buf)) != NULL) + { + fluid_source(cmd_handler, buf); + } + + /* run the server, if requested */ #ifdef NETWORK_SUPPORT - if (with_server) { - server = new_fluid_server(settings, synth, router); - if (server == NULL) { - fprintf(stderr, "Failed to create the server.\n" - "Continuing without it.\n"); + + if(with_server) + { + server = new_fluid_server(settings, synth, router); + + if(server == NULL) + { + fprintf(stderr, "Failed to create the server.\n" + "Continuing without it.\n"); + } } - } + #endif #ifdef LASH_ENABLED - if (enabled_lash) - fluid_lash_create_thread (synth); + + if(enabled_lash) + { + fluid_lash_create_thread(synth); + } + #endif - /* run the shell */ - if (interactive) { - printf ("Type 'help' for help topics.\n\n"); + /* run the shell */ + if(interactive) + { + printf("Type 'help' for help topics.\n\n"); - /* In dump mode we set the prompt to "". The UI cannot easily - * handle lines, which don't end with CR. Changing the prompt - * cannot be done through a command, because the current shell - * does not handle empty arguments. The ordinary case is dump == - * 0. - */ - fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> "); - fluid_usershell(settings, cmd_handler); /* this is a synchronous shell */ - } - /* fast rendering audio file, if requested */ - if (fast_render) - { - char *filename; - if (player == NULL) { - fprintf(stderr, "No midi file specified!\n"); - goto cleanup; - } + /* In dump mode we set the prompt to "". The UI cannot easily + * handle lines, which don't end with CR. Changing the prompt + * cannot be done through a command, because the current shell + * does not handle empty arguments. The ordinary case is dump == + * 0. + */ + fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> "); + fluid_usershell(settings, cmd_handler); /* this is a synchronous shell */ + } - fluid_settings_dupstr (settings, "audio.file.name", &filename); - printf ("Rendering audio to file '%s'..\n", filename); - if (filename) FLUID_FREE (filename); + /* fast rendering audio file, if requested */ + if(fast_render) + { + char *filename; - fast_render_loop(settings, synth, player); - } + if(player == NULL) + { + fprintf(stderr, "No midi file specified!\n"); + goto cleanup; + } - cleanup: + fluid_settings_dupstr(settings, "audio.file.name", &filename); + printf("Rendering audio to file '%s'..\n", filename); + + if(filename) + { + FLUID_FREE(filename); + } + + fast_render_loop(settings, synth, player); + } + +cleanup: #ifdef NETWORK_SUPPORT - if (server != NULL) { - /* if the user typed 'quit' in the shell, kill the server */ - if (!interactive) { - fluid_server_join(server); + + if(server != NULL) + { + /* if the user typed 'quit' in the shell, kill the server */ + if(!interactive) + { + fluid_server_join(server); + } + + delete_fluid_server(server); } - delete_fluid_server(server); - } + #endif - if (cmd_handler != NULL) { - delete_fluid_cmd_handler(cmd_handler); - } - - if (player != NULL) { - /* if the user typed 'quit' in the shell, stop the player */ - if (interactive) { - fluid_player_stop(player); + if(cmd_handler != NULL) + { + delete_fluid_cmd_handler(cmd_handler); } - if (adriver != NULL || !fluid_settings_str_equal(settings, "player.timing-source", "sample")) { - /* if no audio driver and sample timers are used, nothing makes the player advance */ - fluid_player_join(player); + + if(player != NULL) + { + /* if the user typed 'quit' in the shell, stop the player */ + if(interactive) + { + fluid_player_stop(player); + } + + if(adriver != NULL || !fluid_settings_str_equal(settings, "player.timing-source", "sample")) + { + /* if no audio driver and sample timers are used, nothing makes the player advance */ + fluid_player_join(player); + } + + delete_fluid_player(player); } - delete_fluid_player(player); - } - if (mdriver) { - delete_fluid_midi_driver(mdriver); + if(mdriver) + { + delete_fluid_midi_driver(mdriver); } - - if (router) { - delete_fluid_midi_router(router); - } - /*if (sequencer) { - delete_fluid_sequencer(sequencer); - }*/ + if(router) + { + delete_fluid_midi_router(router); + } - if (adriver) { - delete_fluid_audio_driver(adriver); - } + /*if (sequencer) { + delete_fluid_sequencer(sequencer); + }*/ - if (synth) { - delete_fluid_synth(synth); - } + if(adriver) + { + delete_fluid_audio_driver(adriver); + } - if (settings) { - delete_fluid_settings(settings); - } + if(synth) + { + delete_fluid_synth(synth); + } - return 0; + if(settings) + { + delete_fluid_settings(settings); + } + + return 0; } /* @@ -815,19 +1022,19 @@ int main(int argc, char** argv) void print_usage() { - fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n"); - fprintf(stderr, "Try -h for help.\n"); - exit(0); + fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n"); + fprintf(stderr, "Try -h for help.\n"); + exit(0); } void print_welcome() { - printf("FluidSynth runtime version %s\n" - "Copyright (C) 2000-2018 Peter Hanappe and others.\n" - "Distributed under the LGPL license.\n" - "SoundFont(R) is a registered trademark of E-mu Systems, Inc.\n\n", - fluid_version_str()); + printf("FluidSynth runtime version %s\n" + "Copyright (C) 2000-2018 Peter Hanappe and others.\n" + "Distributed under the LGPL license.\n" + "SoundFont(R) is a registered trademark of E-mu Systems, Inc.\n\n", + fluid_version_str()); } void print_configure() @@ -835,91 +1042,98 @@ void print_configure() puts("FluidSynth executable version " FLUIDSYNTH_VERSION); puts("Sample type=" #ifdef WITH_FLOAT - "float" + "float" #else - "double" + "double" #endif - ); + ); } /* * print_help */ void -print_help (fluid_settings_t *settings) +print_help(fluid_settings_t *settings) { - char *audio_options; - char *midi_options; + char *audio_options; + char *midi_options; - audio_options = fluid_settings_option_concat (settings, "audio.driver", NULL); - midi_options = fluid_settings_option_concat (settings, "midi.driver", NULL); + audio_options = fluid_settings_option_concat(settings, "audio.driver", NULL); + midi_options = fluid_settings_option_concat(settings, "midi.driver", NULL); - printf("Usage: \n"); - printf(" fluidsynth [options] [soundfonts] [midifiles]\n"); - printf("Possible options:\n"); - printf(" -a, --audio-driver=[label]\n" - " The name of the audio driver to use.\n" - " Valid values: %s\n", audio_options ? audio_options : "ERROR"); - printf(" -c, --audio-bufcount=[count]\n" - " Number of audio buffers\n"); - printf(" -C, --chorus\n" - " Turn the chorus on or off [0|1|yes|no, default = on]\n"); - printf(" -d, --dump\n" - " Dump incoming and outgoing MIDI events to stdout\n"); - printf(" -E, --audio-file-endian\n" - " Audio file endian for fast rendering or aufile driver (\"help\" for list)\n"); - printf(" -f, --load-config\n" - " Load command configuration file (shell commands)\n"); - printf(" -F, --fast-render=[file]\n" - " Render MIDI file to raw audio data and store in [file]\n"); - printf(" -g, --gain\n" - " Set the master gain [0 < gain < 10, default = 0.2]\n"); - printf(" -G, --audio-groups\n" - " Defines the number of LADSPA audio nodes\n"); - printf(" -h, --help\n" - " Print out this help summary\n"); - printf(" -i, --no-shell\n" - " Don't read commands from the shell [default = yes]\n"); - printf(" -j, --connect-jack-outputs\n" - " Attempt to connect the jack outputs to the physical ports\n"); - printf(" -K, --midi-channels=[num]\n" - " The number of midi channels [default = 16]\n"); + printf("Usage: \n"); + printf(" fluidsynth [options] [soundfonts] [midifiles]\n"); + printf("Possible options:\n"); + printf(" -a, --audio-driver=[label]\n" + " The name of the audio driver to use.\n" + " Valid values: %s\n", audio_options ? audio_options : "ERROR"); + printf(" -c, --audio-bufcount=[count]\n" + " Number of audio buffers\n"); + printf(" -C, --chorus\n" + " Turn the chorus on or off [0|1|yes|no, default = on]\n"); + printf(" -d, --dump\n" + " Dump incoming and outgoing MIDI events to stdout\n"); + printf(" -E, --audio-file-endian\n" + " Audio file endian for fast rendering or aufile driver (\"help\" for list)\n"); + printf(" -f, --load-config\n" + " Load command configuration file (shell commands)\n"); + printf(" -F, --fast-render=[file]\n" + " Render MIDI file to raw audio data and store in [file]\n"); + printf(" -g, --gain\n" + " Set the master gain [0 < gain < 10, default = 0.2]\n"); + printf(" -G, --audio-groups\n" + " Defines the number of LADSPA audio nodes\n"); + printf(" -h, --help\n" + " Print out this help summary\n"); + printf(" -i, --no-shell\n" + " Don't read commands from the shell [default = yes]\n"); + printf(" -j, --connect-jack-outputs\n" + " Attempt to connect the jack outputs to the physical ports\n"); + printf(" -K, --midi-channels=[num]\n" + " The number of midi channels [default = 16]\n"); #ifdef LASH_ENABLED - printf(" -l, --disable-lash\n" - " Don't connect to LASH server\n"); + printf(" -l, --disable-lash\n" + " Don't connect to LASH server\n"); #endif - printf(" -L, --audio-channels=[num]\n" - " The number of stereo audio channels [default = 1]\n"); - printf(" -m, --midi-driver=[label]\n" - " The name of the midi driver to use.\n" - " Valid values: %s\n", midi_options ? midi_options : "ERROR"); - printf(" -n, --no-midi-in\n" - " Don't create a midi driver to read MIDI input events [default = yes]\n"); - printf(" -o\n" - " Define a setting, -o name=value (\"-o help\" to dump current values)\n"); - printf(" -O, --audio-file-format\n" - " Audio file format for fast rendering or aufile driver (\"help\" for list)\n"); - printf(" -p, --portname=[label]\n" - " Set MIDI port name (alsa_seq, coremidi drivers)\n"); - printf(" -r, --sample-rate\n" - " Set the sample rate\n"); - printf(" -R, --reverb\n" - " Turn the reverb on or off [0|1|yes|no, default = on]\n"); - printf(" -s, --server\n" - " Start FluidSynth as a server process\n"); - printf(" -T, --audio-file-type\n" - " Audio file type for fast rendering or aufile driver (\"help\" for list)\n"); - printf(" -v, --verbose\n" - " Print out verbose messages about midi events\n"); - printf(" -V, --version\n" - " Show version of program\n"); - printf(" -z, --audio-bufsize=[size]\n" - " Size of each audio buffer\n"); + printf(" -L, --audio-channels=[num]\n" + " The number of stereo audio channels [default = 1]\n"); + printf(" -m, --midi-driver=[label]\n" + " The name of the midi driver to use.\n" + " Valid values: %s\n", midi_options ? midi_options : "ERROR"); + printf(" -n, --no-midi-in\n" + " Don't create a midi driver to read MIDI input events [default = yes]\n"); + printf(" -o\n" + " Define a setting, -o name=value (\"-o help\" to dump current values)\n"); + printf(" -O, --audio-file-format\n" + " Audio file format for fast rendering or aufile driver (\"help\" for list)\n"); + printf(" -p, --portname=[label]\n" + " Set MIDI port name (alsa_seq, coremidi drivers)\n"); + printf(" -r, --sample-rate\n" + " Set the sample rate\n"); + printf(" -R, --reverb\n" + " Turn the reverb on or off [0|1|yes|no, default = on]\n"); + printf(" -s, --server\n" + " Start FluidSynth as a server process\n"); + printf(" -T, --audio-file-type\n" + " Audio file type for fast rendering or aufile driver (\"help\" for list)\n"); + printf(" -v, --verbose\n" + " Print out verbose messages about midi events\n"); + printf(" -V, --version\n" + " Show version of program\n"); + printf(" -z, --audio-bufsize=[size]\n" + " Size of each audio buffer\n"); - if (audio_options) FLUID_FREE (audio_options); - if (midi_options) FLUID_FREE (midi_options); + if(audio_options) + { + FLUID_FREE(audio_options); + } - delete_fluid_settings (settings); + if(midi_options) + { + FLUID_FREE(midi_options); + } - exit(0); + delete_fluid_settings(settings); + + exit(0); } diff --git a/src/midi/fluid_midi.c b/src/midi/fluid_midi.c index 2a528d5d..83f26d1b 100644 --- a/src/midi/fluid_midi.c +++ b/src/midi/fluid_midi.c @@ -25,7 +25,7 @@ static int fluid_midi_event_length(unsigned char event); -static int fluid_isasciistring(char* s); +static int fluid_isasciistring(char *s); static long fluid_getlength(unsigned char *s); @@ -34,46 +34,46 @@ static long fluid_getlength(unsigned char *s); * Note: This rewinds the file to the start before reading. * Returns NULL if there was an error reading or allocating memory. */ -static char* fluid_file_read_full(fluid_file fp, size_t* length); +static char *fluid_file_read_full(fluid_file fp, size_t *length); static void fluid_midi_event_set_sysex_LOCAL(fluid_midi_event_t *evt, int type, void *data, int size, int dynamic); #define READ_FULL_INITIAL_BUFLEN 1024 -static fluid_track_t* new_fluid_track(int num); -static void delete_fluid_track(fluid_track_t* track); -static int fluid_track_set_name(fluid_track_t* track, char* name); -static int fluid_track_add_event(fluid_track_t* track, fluid_midi_event_t* evt); -static fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track); -static int fluid_track_get_duration(fluid_track_t* track); -static int fluid_track_reset(fluid_track_t* track); +static fluid_track_t *new_fluid_track(int num); +static void delete_fluid_track(fluid_track_t *track); +static int fluid_track_set_name(fluid_track_t *track, char *name); +static int fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt); +static fluid_midi_event_t *fluid_track_next_event(fluid_track_t *track); +static int fluid_track_get_duration(fluid_track_t *track); +static int fluid_track_reset(fluid_track_t *track); -static int fluid_track_send_events(fluid_track_t* track, - fluid_synth_t* synth, - fluid_player_t* player, - unsigned int ticks); +static int fluid_track_send_events(fluid_track_t *track, + fluid_synth_t *synth, + fluid_player_t *player, + unsigned int ticks); -static int fluid_player_add_track(fluid_player_t* player, fluid_track_t* track); -static int fluid_player_callback(void* data, unsigned int msec); -static int fluid_player_reset(fluid_player_t* player); -static int fluid_player_load(fluid_player_t* player, fluid_playlist_item *item); +static int fluid_player_add_track(fluid_player_t *player, fluid_track_t *track); +static int fluid_player_callback(void *data, unsigned int msec); +static int fluid_player_reset(fluid_player_t *player); +static int fluid_player_load(fluid_player_t *player, fluid_playlist_item *item); static void fluid_player_advancefile(fluid_player_t *player); static void fluid_player_playlist_load(fluid_player_t *player, unsigned int msec); -static fluid_midi_file* new_fluid_midi_file(const char* buffer, size_t length); -static void delete_fluid_midi_file(fluid_midi_file* mf); -static int fluid_midi_file_read_mthd(fluid_midi_file* midifile); -static int fluid_midi_file_load_tracks(fluid_midi_file* midifile, fluid_player_t* player); -static int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int num); -static int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track); -static int fluid_midi_file_read_varlen(fluid_midi_file* mf); -static int fluid_midi_file_getc(fluid_midi_file* mf); -static int fluid_midi_file_push(fluid_midi_file* mf, int c); -static int fluid_midi_file_read(fluid_midi_file* mf, void* buf, int len); -static int fluid_midi_file_skip(fluid_midi_file* mf, int len); -static int fluid_midi_file_eof(fluid_midi_file* mf); -static int fluid_midi_file_read_tracklen(fluid_midi_file* mf); -static int fluid_midi_file_eot(fluid_midi_file* mf); -static int fluid_midi_file_get_division(fluid_midi_file* midifile); +static fluid_midi_file *new_fluid_midi_file(const char *buffer, size_t length); +static void delete_fluid_midi_file(fluid_midi_file *mf); +static int fluid_midi_file_read_mthd(fluid_midi_file *midifile); +static int fluid_midi_file_load_tracks(fluid_midi_file *midifile, fluid_player_t *player); +static int fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num); +static int fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track); +static int fluid_midi_file_read_varlen(fluid_midi_file *mf); +static int fluid_midi_file_getc(fluid_midi_file *mf); +static int fluid_midi_file_push(fluid_midi_file *mf, int c); +static int fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len); +static int fluid_midi_file_skip(fluid_midi_file *mf, int len); +static int fluid_midi_file_eof(fluid_midi_file *mf); +static int fluid_midi_file_read_tracklen(fluid_midi_file *mf); +static int fluid_midi_file_eot(fluid_midi_file *mf); +static int fluid_midi_file_get_division(fluid_midi_file *midifile); /*************************************************************** @@ -90,15 +90,18 @@ static int fluid_midi_file_get_division(fluid_midi_file* midifile); * @return New MIDI file handle or NULL on error. */ fluid_midi_file * -new_fluid_midi_file(const char* buffer, size_t length) +new_fluid_midi_file(const char *buffer, size_t length) { fluid_midi_file *mf; mf = FLUID_NEW(fluid_midi_file); - if (mf == NULL) { + + if(mf == NULL) + { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(mf, 0, sizeof(fluid_midi_file)); mf->c = -1; @@ -109,45 +112,58 @@ new_fluid_midi_file(const char* buffer, size_t length) mf->buf_pos = 0; mf->eof = FALSE; - if (fluid_midi_file_read_mthd(mf) != FLUID_OK) { + if(fluid_midi_file_read_mthd(mf) != FLUID_OK) + { FLUID_FREE(mf); return NULL; } + return mf; } -static char* -fluid_file_read_full(fluid_file fp, size_t* length) +static char * +fluid_file_read_full(fluid_file fp, size_t *length) { size_t buflen; - char* buffer; + char *buffer; size_t n; + /* Work out the length of the file in advance */ - if (FLUID_FSEEK(fp, 0, SEEK_END) != 0) + if(FLUID_FSEEK(fp, 0, SEEK_END) != 0) { FLUID_LOG(FLUID_ERR, "File load: Could not seek within file"); return NULL; } + buflen = ftell(fp); - if (FLUID_FSEEK(fp, 0, SEEK_SET) != 0) + + if(FLUID_FSEEK(fp, 0, SEEK_SET) != 0) { FLUID_LOG(FLUID_ERR, "File load: Could not seek within file"); return NULL; } + FLUID_LOG(FLUID_DBG, "File load: Allocating %d bytes", buflen); buffer = FLUID_MALLOC(buflen); - if (buffer == NULL) { + + if(buffer == NULL) + { FLUID_LOG(FLUID_PANIC, "Out of memory"); return NULL; } + n = FLUID_FREAD(buffer, 1, buflen, fp); - if (n != buflen) { + + if(n != buflen) + { FLUID_LOG(FLUID_ERR, "Only read %d bytes; expected %d", n, buflen); FLUID_FREE(buffer); return NULL; }; + *length = n; + return buffer; } @@ -157,10 +173,10 @@ fluid_file_read_full(fluid_file fp, size_t* length) * @param mf MIDI file handle to close and free. */ void -delete_fluid_midi_file (fluid_midi_file *mf) +delete_fluid_midi_file(fluid_midi_file *mf) { fluid_return_if_fail(mf != NULL); - + FLUID_FREE(mf); } @@ -170,20 +186,27 @@ delete_fluid_midi_file (fluid_midi_file *mf) * returns -1 if EOF or read error */ int -fluid_midi_file_getc (fluid_midi_file *mf) +fluid_midi_file_getc(fluid_midi_file *mf) { unsigned char c; - if (mf->c >= 0) { + + if(mf->c >= 0) + { c = mf->c; mf->c = -1; - } else { - if (mf->buf_pos >= mf->buf_len) { + } + else + { + if(mf->buf_pos >= mf->buf_len) + { mf->eof = TRUE; return -1; } + c = mf->buffer[mf->buf_pos++]; mf->trackpos++; } + return (int) c; } @@ -205,23 +228,35 @@ int fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len) { int num = len < mf->buf_len - mf->buf_pos - ? len : mf->buf_len - mf->buf_pos; - if (num != len) { + ? len : mf->buf_len - mf->buf_pos; + + if(num != len) + { mf->eof = TRUE; } - if (num < 0) { + + if(num < 0) + { num = 0; } + /* Note: Read bytes, even if there aren't enough, but only increment * trackpos if successful (emulates old behaviour of fluid_midi_file_read) */ - FLUID_MEMCPY(buf, mf->buffer+mf->buf_pos, num); + FLUID_MEMCPY(buf, mf->buffer + mf->buf_pos, num); mf->buf_pos += num; - if (num == len) + + if(num == len) + { mf->trackpos += num; + } + #if DEBUG else + { FLUID_LOG(FLUID_DBG, "Could not read the requested number of bytes"); + } + #endif return (num != len) ? FLUID_FAILED : FLUID_OK; } @@ -230,15 +265,18 @@ fluid_midi_file_read(fluid_midi_file *mf, void *buf, int len) * fluid_midi_file_skip */ int -fluid_midi_file_skip (fluid_midi_file *mf, int skip) +fluid_midi_file_skip(fluid_midi_file *mf, int skip) { int new_pos = mf->buf_pos + skip; + /* Mimic the behaviour of fseek: Error to seek past the start of file, but * OK to seek past end (this just puts it into the EOF state). */ - if (new_pos < 0) { + if(new_pos < 0) + { FLUID_LOG(FLUID_ERR, "Failed to seek position in file"); return FLUID_FAILED; } + /* Clear the EOF flag, even if moved past the end of the file (this is * consistent with the behaviour of fseek). */ mf->eof = FALSE; @@ -249,15 +287,15 @@ fluid_midi_file_skip (fluid_midi_file *mf, int skip) /* * fluid_midi_file_eof */ -int fluid_midi_file_eof(fluid_midi_file* mf) +int fluid_midi_file_eof(fluid_midi_file *mf) { - /* Note: This does not simply test whether the file read pointer is past - * the end of the file. It mimics the behaviour of feof by actually - * testing the stateful EOF condition, which is set to TRUE if getc or - * fread have attempted to read past the end (but not if they have - * precisely reached the end), but reset to FALSE upon a successful seek. - */ - return mf->eof; + /* Note: This does not simply test whether the file read pointer is past + * the end of the file. It mimics the behaviour of feof by actually + * testing the stateful EOF condition, which is set to TRUE if getc or + * fread have attempted to read past the end (but not if they have + * precisely reached the end), but reset to FALSE upon a successful seek. + */ + return mf->eof; } /* @@ -267,29 +305,39 @@ int fluid_midi_file_read_mthd(fluid_midi_file *mf) { char mthd[14]; - if (fluid_midi_file_read(mf, mthd, sizeof(mthd)) != FLUID_OK) { + + if(fluid_midi_file_read(mf, mthd, sizeof(mthd)) != FLUID_OK) + { return FLUID_FAILED; } - if ((FLUID_STRNCMP(mthd, "MThd", 4) != 0) || (mthd[7] != 6) - || (mthd[9] > 2)) { + + 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"); + "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 ((signed char)mthd[12] < 0) { + mf->ntracks += (unsigned int)(mthd[10]) << 16; + + if((signed char)mthd[12] < 0) + { mf->uses_smpte = 1; mf->smpte_fps = -(signed char)mthd[12]; mf->smpte_res = (unsigned) mthd[13]; FLUID_LOG(FLUID_ERR, "File uses SMPTE timing -- Not implemented yet"); return FLUID_FAILED; - } else { + } + else + { mf->uses_smpte = 0; mf->division = ((unsigned)mthd[12] << 8) | ((unsigned)mthd[13] & 0xff); FLUID_LOG(FLUID_DBG, "Division=%d", mf->division); } + return FLUID_OK; } @@ -300,11 +348,15 @@ 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) { + + for(i = 0; i < mf->ntracks; i++) + { + if(fluid_midi_file_read_track(mf, player, i) != FLUID_OK) + { return FLUID_FAILED; } } + return FLUID_OK; } @@ -315,18 +367,22 @@ int fluid_isasciistring(char *s) { /* From ctype.h */ - #define fluid_isascii(c) (((c) & ~0x7f) == 0) +#define fluid_isascii(c) (((c) & ~0x7f) == 0) int i; int len = (int) FLUID_STRLEN(s); - for (i = 0; i < len; i++) { - if (!fluid_isascii(s[i])) { + + for(i = 0; i < len; i++) + { + if(!fluid_isascii(s[i])) + { return 0; } } + return 1; - - #undef fluid_isascii + +#undef fluid_isascii } /* @@ -347,9 +403,12 @@ int fluid_midi_file_read_tracklen(fluid_midi_file *mf) { unsigned char length[5]; - if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) { + + if(fluid_midi_file_read(mf, length, 4) != FLUID_OK) + { return FLUID_FAILED; } + mf->tracklen = fluid_getlength(length); mf->trackpos = 0; mf->eot = 0; @@ -363,9 +422,12 @@ int fluid_midi_file_eot(fluid_midi_file *mf) { #if DEBUG - if (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); } @@ -381,69 +443,93 @@ fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num) int found_track = 0; int skip; - if (fluid_midi_file_read(mf, id, 4) != FLUID_OK) { + if(fluid_midi_file_read(mf, id, 4) != FLUID_OK) + { return FLUID_FAILED; } + id[4] = '\0'; mf->dtime = 0; - while (!found_track) { + while(!found_track) + { - if (fluid_isasciistring((char *) id) == 0) { + if(fluid_isasciistring((char *) id) == 0) + { FLUID_LOG(FLUID_ERR, - "An non-ascii track header found, corrupt file"); + "An non-ascii track header found, corrupt file"); return FLUID_FAILED; - } else if (FLUID_STRCMP((char *) id, "MTrk") == 0) { + } + else if(FLUID_STRCMP((char *) id, "MTrk") == 0) + { found_track = 1; - if (fluid_midi_file_read_tracklen(mf) != FLUID_OK) { + if(fluid_midi_file_read_tracklen(mf) != FLUID_OK) + { return FLUID_FAILED; } track = new_fluid_track(num); - if (track == NULL) { + + 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) { + while(!fluid_midi_file_eot(mf)) + { + if(fluid_midi_file_read_event(mf, track) != FLUID_OK) + { delete_fluid_track(track); return FLUID_FAILED; } } /* Skip remaining track data, if any */ - if (mf->trackpos < mf->tracklen) { - if (fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos) != FLUID_OK) { + if(mf->trackpos < mf->tracklen) + { + if(fluid_midi_file_skip(mf, mf->tracklen - mf->trackpos) != FLUID_OK) + { delete_fluid_track(track); return FLUID_FAILED; } } - if (fluid_player_add_track(player, track) != FLUID_OK) { + if(fluid_player_add_track(player, track) != FLUID_OK) + { delete_fluid_track(track); return FLUID_FAILED; } - } else { + } + else + { found_track = 0; - if (fluid_midi_file_read(mf, length, 4) != FLUID_OK) { + + 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) { + if(fluid_midi_file_skip(mf, skip) != FLUID_OK) + { return FLUID_FAILED; } } } - if (fluid_midi_file_eof(mf)) { + + if(fluid_midi_file_eof(mf)) + { FLUID_LOG(FLUID_ERR, "Unexpected end of file"); return FLUID_FAILED; } + return FLUID_OK; } @@ -456,24 +542,35 @@ fluid_midi_file_read_varlen(fluid_midi_file *mf) int i; int c; mf->varlen = 0; - for (i = 0;; i++) { - if (i == 4) { + + 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) { + + if(c < 0) + { FLUID_LOG(FLUID_ERR, "Unexpected end of file"); return FLUID_FAILED; } - if (c & 0x80) { - mf->varlen |= (int) (c & 0x7F); + + if(c & 0x80) + { + mf->varlen |= (int)(c & 0x7F); mf->varlen <<= 7; - } else { + } + else + { mf->varlen += c; break; } } + return FLUID_OK; } @@ -497,24 +594,31 @@ fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track) int size; /* read the delta-time of the event */ - if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { + if(fluid_midi_file_read_varlen(mf) != FLUID_OK) + { return FLUID_FAILED; } + mf->dtime += mf->varlen; /* read the status byte */ status = fluid_midi_file_getc(mf); - if (status < 0) { + + 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) { + 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; } @@ -523,40 +627,49 @@ fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track) mf->running_status = status; - if (status == MIDI_SYSEX) { /* system exclusif */ + if(status == MIDI_SYSEX) /* system exclusif */ + { /* read the length of the message */ - if (fluid_midi_file_read_varlen(mf) != FLUID_OK) { + if(fluid_midi_file_read_varlen(mf) != FLUID_OK) + { return FLUID_FAILED; } - if (mf->varlen) { + if(mf->varlen) + { FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, - __LINE__, mf->varlen); + __LINE__, mf->varlen); metadata = FLUID_MALLOC(mf->varlen + 1); - if (metadata == NULL) { + if(metadata == NULL) + { FLUID_LOG(FLUID_PANIC, "Out of memory"); return FLUID_FAILED; } /* read the data of the message */ - if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) { - FLUID_FREE (metadata); + if(fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) + { + FLUID_FREE(metadata); return FLUID_FAILED; } evt = new_fluid_midi_event(); - if (evt == NULL) { + + if(evt == NULL) + { FLUID_LOG(FLUID_ERR, "Out of memory"); - FLUID_FREE (metadata); + FLUID_FREE(metadata); return FLUID_FAILED; } evt->dtime = mf->dtime; size = mf->varlen; - if (metadata[mf->varlen - 1] == MIDI_EOX) + if(metadata[mf->varlen - 1] == MIDI_EOX) + { size--; + } /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */ fluid_midi_event_set_sysex(evt, metadata, size, TRUE); @@ -566,261 +679,316 @@ fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track) return FLUID_OK; - } else if (status == MIDI_META_EVENT) { /* meta events */ + } + else if(status == MIDI_META_EVENT) /* meta events */ + { int result = FLUID_OK; /* get the type of the meta message */ type = fluid_midi_file_getc(mf); - if (type < 0) { + + 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) { + if(fluid_midi_file_read_varlen(mf) != FLUID_OK) + { return FLUID_FAILED; } - if (mf->varlen < 255) { + if(mf->varlen < 255) + { metadata = &static_buf[0]; - } else { + } + else + { FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__, - __LINE__, mf->varlen); + __LINE__, mf->varlen); dyn_buf = FLUID_MALLOC(mf->varlen + 1); - if (dyn_buf == NULL) { + + 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) { + 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) { + 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: - case MIDI_TEXT: + case MIDI_LYRIC: + case MIDI_TEXT: + { + void *tmp; + int size = mf->varlen + 1; + + /* NULL terminate strings for safety */ + metadata[size - 1] = '\0'; + + evt = new_fluid_midi_event(); + + if(evt == NULL) { - void* tmp; - int size = mf->varlen+1; - - /* NULL terminate strings for safety */ - metadata[size-1] = '\0'; - - evt = new_fluid_midi_event(); - if (evt == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - result = FLUID_FAILED; - break; - } - evt->dtime = mf->dtime; - - tmp = FLUID_MALLOC(size); - if (tmp == NULL) - { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - result = FLUID_FAILED; - break; - } - FLUID_MEMCPY(tmp, metadata, size); - - fluid_midi_event_set_sysex_LOCAL(evt, type, tmp, size, TRUE); - fluid_track_add_event(track, evt); - mf->dtime = 0; + FLUID_LOG(FLUID_ERR, "Out of memory"); + result = FLUID_FAILED; + break; } + + evt->dtime = mf->dtime; + + tmp = FLUID_MALLOC(size); + + if(tmp == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + result = FLUID_FAILED; break; + } - case MIDI_MARKER: + FLUID_MEMCPY(tmp, metadata, size); + + fluid_midi_event_set_sysex_LOCAL(evt, type, tmp, size, TRUE); + fluid_track_add_event(track, evt); + mf->dtime = 0; + } + break; + + case MIDI_MARKER: + break; + + 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; + } - case MIDI_CUE_POINT: - break; /* don't care much for text events */ + mf->eot = 1; + evt = new_fluid_midi_event(); - case MIDI_EOT: - if (mf->varlen != 0) { - FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event"); - result = FLUID_FAILED; - break; - } - mf->eot = 1; - evt = new_fluid_midi_event(); - if (evt == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - result = FLUID_FAILED; - break; - } - evt->dtime = mf->dtime; - evt->type = MIDI_EOT; - fluid_track_add_event(track, evt); - mf->dtime = 0; + if(evt == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + result = FLUID_FAILED; 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 = mf->dtime; - evt->type = MIDI_SET_TEMPO; - evt->channel = 0; - evt->param1 = tempo; - evt->param2 = 0; - fluid_track_add_event(track, evt); - mf->dtime = 0; + evt->dtime = mf->dtime; + evt->type = MIDI_EOT; + fluid_track_add_event(track, evt); + mf->dtime = 0; + break; + + case MIDI_SET_TEMPO: + if(mf->varlen != 3) + { + FLUID_LOG(FLUID_ERR, + "Invalid length for SetTempo meta event"); + result = FLUID_FAILED; 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_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", - nominator, denominator, clocks, notes); + 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; + } - case MIDI_KEY_SIGNATURE: - if (mf->varlen != 2) { - FLUID_LOG(FLUID_ERR, - "Invalid length for KeySignature meta event"); - result = FLUID_FAILED; - break; - } - /* We don't care about key signatures anyway */ - /* sf = metadata[0]; - mi = metadata[1]; */ - break; + evt->dtime = mf->dtime; + evt->type = MIDI_SET_TEMPO; + evt->channel = 0; + evt->param1 = tempo; + evt->param2 = 0; + fluid_track_add_event(track, evt); + mf->dtime = 0; + break; - case MIDI_SEQUENCER_EVENT: + case MIDI_SMPTE_OFFSET: + if(mf->varlen != 5) + { + FLUID_LOG(FLUID_ERR, + "Invalid length for SMPTE Offset meta event"); + result = FLUID_FAILED; break; + } - default: + 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]; + + FLUID_LOG(FLUID_DBG, + "signature=%d/%d, metronome=%d, 32nd-notes=%d", + nominator, denominator, clocks, notes); + + break; + + case MIDI_KEY_SIGNATURE: + if(mf->varlen != 2) + { + FLUID_LOG(FLUID_ERR, + "Invalid length for KeySignature meta event"); + result = FLUID_FAILED; + break; + } + + /* We don't care about key signatures anyway */ + /* sf = metadata[0]; + mi = metadata[1]; */ + break; + + case MIDI_SEQUENCER_EVENT: + break; + + default: + break; } - if (dyn_buf) { + if(dyn_buf) + { FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__); FLUID_FREE(dyn_buf); } return result; - } else { /* channel messages */ + } + else /* channel messages */ + { 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) { + 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; - } - 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"); + 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) { + + if(evt == NULL) + { FLUID_LOG(FLUID_ERR, "Out of memory"); return FLUID_FAILED; } + evt->dtime = mf->dtime; evt->type = type; evt->channel = channel; @@ -829,6 +997,7 @@ fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track) fluid_track_add_event(track, evt); mf->dtime = 0; } + return FLUID_OK; } @@ -851,14 +1020,17 @@ fluid_midi_file_get_division(fluid_midi_file *midifile) * @return New MIDI event structure or NULL when out of memory. */ fluid_midi_event_t * -new_fluid_midi_event () +new_fluid_midi_event() { - fluid_midi_event_t* evt; + fluid_midi_event_t *evt; evt = FLUID_NEW(fluid_midi_event_t); - if (evt == NULL) { + + if(evt == NULL) + { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + evt->dtime = 0; evt->type = 0; evt->channel = 0; @@ -879,14 +1051,17 @@ delete_fluid_midi_event(fluid_midi_event_t *evt) fluid_midi_event_t *temp; fluid_return_if_fail(evt != NULL); - while (evt) { + while(evt) + { temp = evt->next; /* Dynamic SYSEX event? - free (param2 indicates if dynamic) */ - if ((evt->type == MIDI_SYSEX || (evt-> type == MIDI_TEXT) || (evt->type == MIDI_LYRIC)) && - evt->paramptr && evt->param2) - FLUID_FREE (evt->paramptr); - + if((evt->type == MIDI_SYSEX || (evt-> type == MIDI_TEXT) || (evt->type == MIDI_LYRIC)) && + evt->paramptr && evt->param2) + { + FLUID_FREE(evt->paramptr); + } + FLUID_FREE(evt); evt = temp; } @@ -1111,7 +1286,7 @@ fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data, int size, int dy * @param dynamic TRUE if the data has been dynamically allocated and * should be freed when the event is freed via delete_fluid_midi_event() * @return Always returns #FLUID_OK - * + * * @since 2.0.0 * @note Unlike the other event assignment functions, this one sets evt->type. */ @@ -1130,7 +1305,7 @@ fluid_midi_event_set_text(fluid_midi_event_t *evt, void *data, int size, int dyn * @param dynamic TRUE if the data has been dynamically allocated and * should be freed when the event is freed via delete_fluid_midi_event() * @return Always returns #FLUID_OK - * + * * @since 2.0.0 * @note Unlike the other event assignment functions, this one sets evt->type. */ @@ -1162,9 +1337,12 @@ new_fluid_track(int num) { fluid_track_t *track; track = FLUID_NEW(fluid_track_t); - if (track == NULL) { + + if(track == NULL) + { return NULL; } + track->name = NULL; track->num = num; track->first = NULL; @@ -1181,7 +1359,7 @@ void delete_fluid_track(fluid_track_t *track) { fluid_return_if_fail(track != NULL); - + FLUID_FREE(track->name); delete_fluid_midi_event(track->first); FLUID_FREE(track); @@ -1194,19 +1372,27 @@ int fluid_track_set_name(fluid_track_t *track, char *name) { int len; - if (track->name != NULL) { + + if(track->name != NULL) + { FLUID_FREE(track->name); } - if (name == NULL) { + + if(name == NULL) + { track->name = NULL; return FLUID_OK; } + len = FLUID_STRLEN(name); track->name = FLUID_MALLOC(len + 1); - if (track->name == NULL) { + + if(track->name == NULL) + { FLUID_LOG(FLUID_ERR, "Out of memory"); return FLUID_FAILED; } + FLUID_STRCPY(track->name, name); return FLUID_OK; } @@ -1219,10 +1405,13 @@ fluid_track_get_duration(fluid_track_t *track) { int time = 0; fluid_midi_event_t *evt = track->first; - while (evt != NULL) { + + while(evt != NULL) + { time += evt->dtime; evt = evt->next; } + return time; } @@ -1233,14 +1422,19 @@ int fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt) { evt->next = NULL; - if (track->first == NULL) { + + if(track->first == NULL) + { track->first = evt; track->cur = evt; track->last = evt; - } else { + } + else + { track->last->next = evt; track->last = evt; } + return FLUID_OK; } @@ -1250,9 +1444,11 @@ fluid_track_add_event(fluid_track_t *track, fluid_midi_event_t *evt) fluid_midi_event_t * fluid_track_next_event(fluid_track_t *track) { - if (track->cur != NULL) { + if(track->cur != NULL) + { track->cur = track->cur->next; } + return track->cur; } @@ -1272,24 +1468,31 @@ 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 seeking = player->seek_ticks >= 0; - if (seeking) { + if(seeking) + { ticks = player->seek_ticks; /* update target ticks */ - if (track->ticks > ticks) - fluid_track_reset (track); /* reset track if seeking backwards */ + + if(track->ticks > ticks) + { + fluid_track_reset(track); /* reset track if seeking backwards */ + } } - while (1) { + while(1) + { event = track->cur; - if (event == NULL) { + + if(event == NULL) + { return status; } @@ -1300,23 +1503,29 @@ fluid_track_send_events(fluid_track_t *track, /* event->dtime, */ /* track->ticks + event->dtime); */ - if (track->ticks + event->dtime > ticks) { + if(track->ticks + event->dtime > ticks) + { return status; } track->ticks += event->dtime; - if (!player || event->type == MIDI_EOT) { + if(!player || event->type == MIDI_EOT) + { } - else if (seeking && (event->type == NOTE_ON || event->type == NOTE_OFF)) { + else if(seeking && (event->type == NOTE_ON || event->type == NOTE_OFF)) + { /* skip on/off messages */ } - else { - if (player->playback_callback) + else + { + if(player->playback_callback) + { player->playback_callback(player->playback_userdata, event); + } } - - if (event->type == MIDI_SET_TEMPO) + + if(event->type == MIDI_SET_TEMPO) { fluid_player_set_midi_tempo(player, event->param1); } @@ -1324,6 +1533,7 @@ fluid_track_send_events(fluid_track_t *track, fluid_track_next_event(track); } + return status; } @@ -1343,16 +1553,22 @@ new_fluid_player(fluid_synth_t *synth) int i; fluid_player_t *player; player = FLUID_NEW(fluid_player_t); - if (player == NULL) { + + if(player == NULL) + { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + player->status = FLUID_PLAYER_READY; player->loop = 1; player->ntracks = 0; - for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) { + + for(i = 0; i < MAX_NUMBER_OF_TRACKS; i++) + { player->track[i] = NULL; } + player->synth = synth; player->system_timer = NULL; player->sample_timer = NULL; @@ -1364,10 +1580,10 @@ new_fluid_player(fluid_synth_t *synth) player->deltatime = 4.0; player->cur_msec = 0; player->cur_ticks = 0; - player->seek_ticks = -1; + player->seek_ticks = -1; fluid_player_set_playback_callback(player, fluid_synth_handle_midi_event, synth); player->use_system_timer = fluid_settings_str_equal(synth->settings, - "player.timing-source", "system"); + "player.timing-source", "system"); fluid_settings_getint(synth->settings, "player.reset-synth", &i); player->reset_synth_between_songs = i; @@ -1383,16 +1599,17 @@ void delete_fluid_player(fluid_player_t *player) { fluid_list_t *q; - fluid_playlist_item* pi; + fluid_playlist_item *pi; fluid_return_if_fail(player != NULL); - + fluid_player_stop(player); fluid_player_reset(player); - while (player->playlist != NULL) { + while(player->playlist != NULL) + { q = player->playlist->next; - pi = (fluid_playlist_item*) player->playlist->data; + pi = (fluid_playlist_item *) player->playlist->data; FLUID_FREE(pi->filename); FLUID_FREE(pi->buffer); FLUID_FREE(pi); @@ -1425,12 +1642,15 @@ fluid_player_reset(fluid_player_t *player) { int i; - for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) { - if (player->track[i] != NULL) { + 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 = 1; */ @@ -1448,30 +1668,33 @@ 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) { + if(player->ntracks < MAX_NUMBER_OF_TRACKS) + { player->track[player->ntracks++] = track; return FLUID_OK; - } else { + } + else + { return FLUID_FAILED; } } /** - * Change the MIDI callback function. This is usually set to + * Change the MIDI callback function. This is usually set to * fluid_synth_handle_midi_event, but can optionally be changed * to a user-defined function instead, for intercepting all MIDI - * messages sent to the synth. You can also use a midi router as + * messages sent to the synth. You can also use a midi router as * the callback function to modify the MIDI messages before sending - * them to the synth. + * them to the synth. * @param player MIDI player instance * @param handler Pointer to callback function * @param handler_data Parameter sent to the callback function * @returns FLUID_OK * @since 1.1.4 */ -int -fluid_player_set_playback_callback(fluid_player_t* player, - handle_midi_event_func_t handler, void* handler_data) +int +fluid_player_set_playback_callback(fluid_player_t *player, + handle_midi_event_func_t handler, void *handler_data) { player->playback_callback = handler; player->playback_userdata = handler_data; @@ -1488,8 +1711,10 @@ int fluid_player_add(fluid_player_t *player, const char *midifile) { fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item)); - char* f = FLUID_STRDUP(midifile); - if (!pi || !f) { + char *f = FLUID_STRDUP(midifile); + + if(!pi || !f) + { FLUID_FREE(pi); FLUID_FREE(f); FLUID_LOG(FLUID_PANIC, "Out of memory"); @@ -1513,12 +1738,14 @@ fluid_player_add(fluid_player_t *player, const char *midifile) * @return #FLUID_OK or #FLUID_FAILED */ int -fluid_player_add_mem(fluid_player_t* player, const void *buffer, size_t len) +fluid_player_add_mem(fluid_player_t *player, const void *buffer, size_t len) { /* Take a copy of the buffer, so the caller can free immediately. */ fluid_playlist_item *pi = FLUID_MALLOC(sizeof(fluid_playlist_item)); void *buf_copy = FLUID_MALLOC(len); - if (!pi || !buf_copy) { + + if(!pi || !buf_copy) + { FLUID_FREE(pi); FLUID_FREE(buf_copy); FLUID_LOG(FLUID_PANIC, "Out of memory"); @@ -1540,28 +1767,33 @@ int fluid_player_load(fluid_player_t *player, fluid_playlist_item *item) { fluid_midi_file *midifile; - char* buffer; + char *buffer; size_t buffer_length; int buffer_owned; - if (item->filename != NULL) + if(item->filename != NULL) { fluid_file fp; /* This file is specified by filename; load the file from disk */ FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile %s", __FILE__, __LINE__, - item->filename); + item->filename); /* Read the entire contents of the file into the buffer */ fp = FLUID_FOPEN(item->filename, "rb"); - if (fp == NULL) { + + if(fp == NULL) + { FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file"); return FLUID_FAILED; } + buffer = fluid_file_read_full(fp, &buffer_length); - if (buffer == NULL) + + if(buffer == NULL) { FLUID_FCLOSE(fp); return FLUID_FAILED; } + buffer_owned = 1; FLUID_FCLOSE(fp); } @@ -1569,7 +1801,7 @@ fluid_player_load(fluid_player_t *player, fluid_playlist_item *item) { /* This file is specified by a pre-loaded buffer; load from memory */ FLUID_LOG(FLUID_DBG, "%s: %d: Loading midifile from memory (%p)", - __FILE__, __LINE__, item->buffer); + __FILE__, __LINE__, item->buffer); buffer = (char *) item->buffer; buffer_length = item->buffer_len; /* Do not free the buffer (it is owned by the playlist) */ @@ -1577,47 +1809,67 @@ fluid_player_load(fluid_player_t *player, fluid_playlist_item *item) } midifile = new_fluid_midi_file(buffer, buffer_length); - if (midifile == NULL) { - if (buffer_owned) { + + if(midifile == NULL) + { + if(buffer_owned) + { FLUID_FREE(buffer); } + return FLUID_FAILED; } + player->division = fluid_midi_file_get_division(midifile); fluid_player_set_midi_tempo(player, player->miditempo); // Update deltatime /*FLUID_LOG(FLUID_DBG, "quarter note division=%d\n", player->division); */ - if (fluid_midi_file_load_tracks(midifile, player) != FLUID_OK) { - if (buffer_owned) { + if(fluid_midi_file_load_tracks(midifile, player) != FLUID_OK) + { + if(buffer_owned) + { FLUID_FREE(buffer); } + delete_fluid_midi_file(midifile); return FLUID_FAILED; } + delete_fluid_midi_file(midifile); - if (buffer_owned) { + + if(buffer_owned) + { FLUID_FREE(buffer); } - + return FLUID_OK; } void fluid_player_advancefile(fluid_player_t *player) { - if (player->playlist == NULL) { + if(player->playlist == NULL) + { return; /* No files to play */ } - if (player->currentfile != NULL) { + + if(player->currentfile != NULL) + { player->currentfile = fluid_list_next(player->currentfile); } - if (player->currentfile == NULL) { - if (player->loop == 0) { + + if(player->currentfile == NULL) + { + if(player->loop == 0) + { return; /* We're done playing */ } - if (player->loop > 0) { + + if(player->loop > 0) + { player->loop--; } + player->currentfile = player->playlist; } } @@ -1625,12 +1877,15 @@ fluid_player_advancefile(fluid_player_t *player) void fluid_player_playlist_load(fluid_player_t *player, unsigned int msec) { - fluid_playlist_item* current_playitem; + fluid_playlist_item *current_playitem; int i; - do { + do + { fluid_player_advancefile(player); - if (player->currentfile == NULL) { + + if(player->currentfile == NULL) + { /* Failed to find next song, probably since we're finished */ player->status = FLUID_PLAYER_DONE; return; @@ -1638,7 +1893,8 @@ fluid_player_playlist_load(fluid_player_t *player, unsigned int msec) fluid_player_reset(player); current_playitem = (fluid_playlist_item *) player->currentfile->data; - } while (fluid_player_load(player, current_playitem) != FLUID_OK); + } + while(fluid_player_load(player, current_playitem) != FLUID_OK); /* Successfully loaded midi file */ @@ -1647,12 +1903,15 @@ fluid_player_playlist_load(fluid_player_t *player, unsigned int msec) player->start_ticks = 0; player->cur_ticks = 0; - if (player->reset_synth_between_songs) { + if(player->reset_synth_between_songs) + { fluid_synth_system_reset(player->synth); } - for (i = 0; i < player->ntracks; i++) { - if (player->track[i] != NULL) { + for(i = 0; i < player->ntracks; i++) + { + if(player->track[i] != NULL) + { fluid_track_reset(player->track[i]); } } @@ -1673,48 +1932,61 @@ fluid_player_callback(void *data, unsigned int msec) synth = player->synth; loadnextfile = player->currentfile == NULL ? 1 : 0; - do { - if (loadnextfile) { + + do + { + if(loadnextfile) + { loadnextfile = 0; fluid_player_playlist_load(player, msec); - if (player->currentfile == NULL) { + + if(player->currentfile == NULL) + { return 0; } } player->cur_msec = msec; player->cur_ticks = (player->start_ticks - + (int) ((double) (player->cur_msec - player->start_msec) - / player->deltatime + 0.5)); /* 0.5 to average overall error when casting */ + + (int)((double)(player->cur_msec - player->start_msec) + / player->deltatime + 0.5)); /* 0.5 to average overall error when casting */ - if (player->seek_ticks >= 0) { + if(player->seek_ticks >= 0) + { fluid_synth_all_sounds_off(synth, -1); /* avoid hanging notes */ } - for (i = 0; i < player->ntracks; i++) { - if (!fluid_track_eot(player->track[i])) { + 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, - player->cur_ticks) != FLUID_OK) { + + if(fluid_track_send_events(player->track[i], synth, player, + player->cur_ticks) != FLUID_OK) + { /* */ } } } - if (player->seek_ticks >= 0) { + if(player->seek_ticks >= 0) + { player->start_ticks = player->seek_ticks; /* tick position of last tempo value (which is now) */ player->cur_ticks = player->seek_ticks; player->begin_msec = msec; /* only used to calculate the duration of playing */ - player->start_msec = msec; /* should be the (synth)-time of the last tempo change */ + player->start_msec = msec; /* should be the (synth)-time of the last tempo change */ player->seek_ticks = -1; /* clear seek_ticks */ } - if (status == FLUID_PLAYER_DONE) { + if(status == FLUID_PLAYER_DONE) + { FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__, - __LINE__, (msec - player->begin_msec) / 1000.0); + __LINE__, (msec - player->begin_msec) / 1000.0); loadnextfile = 1; } - } while (loadnextfile); + } + while(loadnextfile); player->status = status; @@ -1729,30 +2001,39 @@ fluid_player_callback(void *data, unsigned int msec) int fluid_player_play(fluid_player_t *player) { - if (player->status == FLUID_PLAYER_PLAYING) { + if(player->status == FLUID_PLAYER_PLAYING) + { return FLUID_OK; } - if (player->playlist == NULL) { + if(player->playlist == NULL) + { return FLUID_OK; } player->status = FLUID_PLAYER_PLAYING; - if (player->use_system_timer) { + if(player->use_system_timer) + { player->system_timer = new_fluid_timer((int) player->deltatime, - fluid_player_callback, (void *) player, TRUE, FALSE, TRUE); - if (player->system_timer == NULL) { - return FLUID_FAILED; - } - } else { - player->sample_timer = new_fluid_sample_timer(player->synth, - fluid_player_callback, (void *) player); + fluid_player_callback, (void *) player, TRUE, FALSE, TRUE); - if (player->sample_timer == NULL) { + if(player->system_timer == NULL) + { return FLUID_FAILED; } } + else + { + player->sample_timer = new_fluid_sample_timer(player->synth, + fluid_player_callback, (void *) player); + + if(player->sample_timer == NULL) + { + return FLUID_FAILED; + } + } + return FLUID_OK; } @@ -1764,12 +2045,16 @@ fluid_player_play(fluid_player_t *player) int fluid_player_stop(fluid_player_t *player) { - if (player->system_timer != NULL) { + if(player->system_timer != NULL) + { delete_fluid_timer(player->system_timer); } - if (player->sample_timer != NULL) { + + if(player->sample_timer != NULL) + { delete_fluid_sample_timer(player->synth, player->sample_timer); } + player->status = FLUID_PLAYER_DONE; player->sample_timer = NULL; player->system_timer = NULL; @@ -1795,27 +2080,29 @@ fluid_player_get_status(fluid_player_t *player) * @return #FLUID_FAILED if ticks is negative or after the latest tick of the file, * #FLUID_OK otherwise * @since 2.0.0 - * + * * The actual seek is performed during the player_callback. */ int fluid_player_seek(fluid_player_t *player, int ticks) { - if (ticks < 0 || ticks > fluid_player_get_total_ticks(player)) { + if(ticks < 0 || ticks > fluid_player_get_total_ticks(player)) + { return FLUID_FAILED; } + player->seek_ticks = ticks; return FLUID_OK; } /** - * Enable looping of a MIDI player + * Enable looping of a MIDI player * @param player MIDI player instance * @param loop Times left to loop the playlist. -1 means loop infinitely. * @return Always returns #FLUID_OK * @since 1.1.0 * - * For example, if you want to loop the playlist twice, set loop to 2 + * For example, if you want to loop the playlist twice, set loop to 2 * and call this function before you start the player. */ int fluid_player_set_loop(fluid_player_t *player, int loop) @@ -1838,8 +2125,8 @@ int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo) player->start_ticks = player->cur_ticks; FLUID_LOG(FLUID_DBG, - "tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d", - tempo, player->deltatime, player->cur_msec, player->cur_ticks); + "tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d", + tempo, player->deltatime, player->cur_msec, player->cur_ticks); return FLUID_OK; } @@ -1852,7 +2139,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)); } /** @@ -1863,14 +2150,19 @@ int fluid_player_set_bpm(fluid_player_t *player, int bpm) int fluid_player_join(fluid_player_t *player) { - if (player->system_timer) { + if(player->system_timer) + { return fluid_timer_join(player->system_timer); - } else if (player->sample_timer) { + } + else if(player->sample_timer) + { /* Busy-wait loop, since there's no thread to wait for... */ - while (player->status != FLUID_PLAYER_DONE) { + while(player->status != FLUID_PLAYER_DONE) + { fluid_msleep(10); } } + return FLUID_OK; } @@ -1880,28 +2172,35 @@ fluid_player_join(fluid_player_t *player) * @return The number of tempo ticks passed * @since 1.1.7 */ -int fluid_player_get_current_tick(fluid_player_t * player) +int fluid_player_get_current_tick(fluid_player_t *player) { return player->cur_ticks; } /** - * Looks through all available MIDI tracks and gets the absolute tick of the very last event to play. + * Looks through all available MIDI tracks and gets the absolute tick of the very last event to play. * @param player MIDI player instance * @return Total tick count of the sequence * @since 1.1.7 */ -int fluid_player_get_total_ticks(fluid_player_t * player) +int fluid_player_get_total_ticks(fluid_player_t *player) { int i; int maxTicks = 0; - for (i = 0; i < player->ntracks; i++) { - if (player->track[i] != NULL) { + + for(i = 0; i < player->ntracks; i++) + { + if(player->track[i] != NULL) + { int ticks = fluid_track_get_duration(player->track[i]); - if( ticks > maxTicks ) + + if(ticks > maxTicks) + { maxTicks = ticks; + } } } + return maxTicks; } @@ -1911,7 +2210,7 @@ int fluid_player_get_total_ticks(fluid_player_t * player) * @return MIDI player tempo in BPM * @since 1.1.7 */ -int fluid_player_get_bpm(fluid_player_t * player) +int fluid_player_get_bpm(fluid_player_t *player) { return (int)(60e6 / player->miditempo); } @@ -1922,7 +2221,7 @@ int fluid_player_get_bpm(fluid_player_t * player) * @return Tempo of the MIDI player (in microseconds per quarter note, as per MIDI file spec) * @since 1.1.7 */ -int fluid_player_get_midi_tempo(fluid_player_t * player) +int fluid_player_get_midi_tempo(fluid_player_t *player) { return player->miditempo; } @@ -1936,14 +2235,17 @@ int fluid_player_get_midi_tempo(fluid_player_t * player) * new_fluid_midi_parser */ fluid_midi_parser_t * -new_fluid_midi_parser () +new_fluid_midi_parser() { fluid_midi_parser_t *parser; parser = FLUID_NEW(fluid_midi_parser_t); - if (parser == NULL) { + + 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; } @@ -1955,7 +2257,7 @@ void delete_fluid_midi_parser(fluid_midi_parser_t *parser) { fluid_return_if_fail(parser != NULL); - + FLUID_FREE(parser); } @@ -1978,8 +2280,10 @@ fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c) /* Real-time messages (0xF8-0xFF) can occur anywhere, even in the middle * of another message. */ - if (c >= 0xF8) { - if (c == MIDI_SYSTEM_RESET) { + if(c >= 0xF8) + { + if(c == MIDI_SYSTEM_RESET) + { parser->event.type = c; parser->status = 0; /* clear the status */ return &parser->event; @@ -1989,30 +2293,40 @@ fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c) } /* Status byte? - If previous message not yet complete, it is discarded (re-sync). */ - if (c & 0x80) { + if(c & 0x80) + { /* Any status byte terminates SYSEX messages (not just 0xF7) */ - if (parser->status == MIDI_SYSEX && parser->nr_bytes > 0) { + if(parser->status == MIDI_SYSEX && parser->nr_bytes > 0) + { event = &parser->event; fluid_midi_event_set_sysex(event, parser->data, parser->nr_bytes, - FALSE); - } else + FALSE); + } + else + { event = NULL; + } - if (c < 0xF0) /* Voice category message? */ + if(c < 0xF0) /* Voice category message? */ { 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; + - 1; parser->nr_bytes = 0; /* 0 bytes read so far */ - } else if (c == MIDI_SYSEX) { + } + else if(c == MIDI_SYSEX) + { parser->status = MIDI_SYSEX; parser->nr_bytes = 0; - } else - parser->status = 0; /* Discard other system messages (0xF1-0xF7) */ + } + else + { + parser->status = 0; /* Discard other system messages (0xF1-0xF7) */ + } return event; /* Return SYSEX event or NULL */ } @@ -2020,11 +2334,14 @@ fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c) /* Data/parameter byte */ /* Discard data bytes for events we don't care about */ - if (parser->status == 0) + if(parser->status == 0) + { return NULL; + } /* Max data size exceeded? (SYSEX messages only really) */ - if (parser->nr_bytes == FLUID_MIDI_PARSER_MAX_DATA_SIZE) { + if(parser->nr_bytes == FLUID_MIDI_PARSER_MAX_DATA_SIZE) + { parser->status = 0; /* Discard the rest of the message */ return NULL; } @@ -2033,8 +2350,10 @@ fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c) parser->data[parser->nr_bytes++] = c; /* Do we still need more data to get this event complete? */ - if (parser->status == MIDI_SYSEX || parser->nr_bytes < parser->nr_bytes_total) + if(parser->status == MIDI_SYSEX || parser->nr_bytes < parser->nr_bytes_total) + { return NULL; + } /* Event is complete, return it. * Running status byte MIDI feature is also handled here. */ @@ -2042,22 +2361,25 @@ fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c) parser->event.channel = parser->channel; parser->nr_bytes = 0; /* Reset data size, in case there are additional running status messages */ - 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->data[0]; /* For example key number */ - parser->event.param2 = parser->data[1]; /* For example velocity */ - break; - case PITCH_BEND: - /* Pitch-bend is transmitted with 14-bit precision. */ - parser->event.param1 = (parser->data[1] << 7) | parser->data[0]; - break; - default: /* Unlikely */ - return NULL; + 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->data[0]; /* For example key number */ + parser->event.param2 = parser->data[1]; /* For example velocity */ + break; + + case PITCH_BEND: + /* Pitch-bend is transmitted with 14-bit precision. */ + parser->event.param1 = (parser->data[1] << 7) | parser->data[0]; + break; + + default: /* Unlikely */ + return NULL; } return &parser->event; @@ -2068,27 +2390,34 @@ fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c) static int fluid_midi_event_length(unsigned char event) { - switch (event & 0xF0) { - case NOTE_OFF: - case NOTE_ON: - case KEY_PRESSURE: - case CONTROL_CHANGE: - case PITCH_BEND: - return 3; - case PROGRAM_CHANGE: - case CHANNEL_PRESSURE: - return 2; + switch(event & 0xF0) + { + case NOTE_OFF: + case NOTE_ON: + case KEY_PRESSURE: + case CONTROL_CHANGE: + case PITCH_BEND: + return 3; + + case PROGRAM_CHANGE: + case CHANNEL_PRESSURE: + return 2; } - switch (event) { - case MIDI_TIME_CODE: - case MIDI_SONG_SELECT: - case 0xF4: - case 0xF5: - return 2; - case MIDI_TUNE_REQUEST: - return 1; - case MIDI_SONG_POSITION: - return 3; + + switch(event) + { + case MIDI_TIME_CODE: + case MIDI_SONG_SELECT: + case 0xF4: + case 0xF5: + return 2; + + case MIDI_TUNE_REQUEST: + return 1; + + case MIDI_SONG_POSITION: + return 3; } + return 1; } diff --git a/src/midi/fluid_midi.h b/src/midi/fluid_midi.h index 0d38079c..9e34a0ff 100644 --- a/src/midi/fluid_midi.h +++ b/src/midi/fluid_midi.h @@ -27,9 +27,9 @@ typedef struct _fluid_midi_parser_t fluid_midi_parser_t; -fluid_midi_parser_t* new_fluid_midi_parser(void); -void 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); +fluid_midi_parser_t *new_fluid_midi_parser(void); +void 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); /*************************************************************** @@ -40,141 +40,146 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne #define MAX_NUMBER_OF_TRACKS 128 -enum fluid_midi_event_type { - /* channel messages */ - NOTE_OFF = 0x80, - NOTE_ON = 0x90, - KEY_PRESSURE = 0xa0, - CONTROL_CHANGE = 0xb0, - PROGRAM_CHANGE = 0xc0, - CHANNEL_PRESSURE = 0xd0, - PITCH_BEND = 0xe0, - /* system exclusive */ - MIDI_SYSEX = 0xf0, - /* system common - never in midi files */ - MIDI_TIME_CODE = 0xf1, - MIDI_SONG_POSITION = 0xf2, - MIDI_SONG_SELECT = 0xf3, - MIDI_TUNE_REQUEST = 0xf6, - MIDI_EOX = 0xf7, - /* system real-time - never in midi files */ - MIDI_SYNC = 0xf8, - MIDI_TICK = 0xf9, - MIDI_START = 0xfa, - MIDI_CONTINUE = 0xfb, - MIDI_STOP = 0xfc, - MIDI_ACTIVE_SENSING = 0xfe, - MIDI_SYSTEM_RESET = 0xff, - /* meta event - for midi files only */ - MIDI_META_EVENT = 0xff +enum fluid_midi_event_type +{ + /* channel messages */ + NOTE_OFF = 0x80, + NOTE_ON = 0x90, + KEY_PRESSURE = 0xa0, + CONTROL_CHANGE = 0xb0, + PROGRAM_CHANGE = 0xc0, + CHANNEL_PRESSURE = 0xd0, + PITCH_BEND = 0xe0, + /* system exclusive */ + MIDI_SYSEX = 0xf0, + /* system common - never in midi files */ + MIDI_TIME_CODE = 0xf1, + MIDI_SONG_POSITION = 0xf2, + MIDI_SONG_SELECT = 0xf3, + MIDI_TUNE_REQUEST = 0xf6, + MIDI_EOX = 0xf7, + /* system real-time - never in midi files */ + MIDI_SYNC = 0xf8, + MIDI_TICK = 0xf9, + MIDI_START = 0xfa, + MIDI_CONTINUE = 0xfb, + MIDI_STOP = 0xfc, + MIDI_ACTIVE_SENSING = 0xfe, + MIDI_SYSTEM_RESET = 0xff, + /* meta event - for midi files only */ + MIDI_META_EVENT = 0xff }; -enum fluid_midi_control_change { - BANK_SELECT_MSB = 0x00, - MODULATION_MSB = 0x01, - BREATH_MSB = 0x02, - FOOT_MSB = 0x04, - PORTAMENTO_TIME_MSB = 0x05, - DATA_ENTRY_MSB = 0x06, - VOLUME_MSB = 0x07, - BALANCE_MSB = 0x08, - PAN_MSB = 0x0A, - EXPRESSION_MSB = 0x0B, - EFFECTS1_MSB = 0x0C, - EFFECTS2_MSB = 0x0D, - GPC1_MSB = 0x10, /* general purpose controller */ - GPC2_MSB = 0x11, - GPC3_MSB = 0x12, - GPC4_MSB = 0x13, - BANK_SELECT_LSB = 0x20, - MODULATION_WHEEL_LSB = 0x21, - BREATH_LSB = 0x22, - FOOT_LSB = 0x24, - PORTAMENTO_TIME_LSB = 0x25, - DATA_ENTRY_LSB = 0x26, - VOLUME_LSB = 0x27, - BALANCE_LSB = 0x28, - PAN_LSB = 0x2A, - EXPRESSION_LSB = 0x2B, - EFFECTS1_LSB = 0x2C, - EFFECTS2_LSB = 0x2D, - GPC1_LSB = 0x30, - GPC2_LSB = 0x31, - GPC3_LSB = 0x32, - GPC4_LSB = 0x33, - SUSTAIN_SWITCH = 0x40, - PORTAMENTO_SWITCH = 0x41, - SOSTENUTO_SWITCH = 0x42, - SOFT_PEDAL_SWITCH = 0x43, - LEGATO_SWITCH = 0x44, - HOLD2_SWITCH = 0x45, - SOUND_CTRL1 = 0x46, - SOUND_CTRL2 = 0x47, - SOUND_CTRL3 = 0x48, - SOUND_CTRL4 = 0x49, - SOUND_CTRL5 = 0x4A, - SOUND_CTRL6 = 0x4B, - SOUND_CTRL7 = 0x4C, - SOUND_CTRL8 = 0x4D, - SOUND_CTRL9 = 0x4E, - SOUND_CTRL10 = 0x4F, - GPC5 = 0x50, - GPC6 = 0x51, - GPC7 = 0x52, - GPC8 = 0x53, - PORTAMENTO_CTRL = 0x54, - EFFECTS_DEPTH1 = 0x5B, - EFFECTS_DEPTH2 = 0x5C, - EFFECTS_DEPTH3 = 0x5D, - EFFECTS_DEPTH4 = 0x5E, - EFFECTS_DEPTH5 = 0x5F, - DATA_ENTRY_INCR = 0x60, - DATA_ENTRY_DECR = 0x61, - NRPN_LSB = 0x62, - NRPN_MSB = 0x63, - RPN_LSB = 0x64, - RPN_MSB = 0x65, - ALL_SOUND_OFF = 0x78, - ALL_CTRL_OFF = 0x79, - LOCAL_CONTROL = 0x7A, - ALL_NOTES_OFF = 0x7B, - OMNI_OFF = 0x7C, - OMNI_ON = 0x7D, - POLY_OFF = 0x7E, - POLY_ON = 0x7F +enum fluid_midi_control_change +{ + BANK_SELECT_MSB = 0x00, + MODULATION_MSB = 0x01, + BREATH_MSB = 0x02, + FOOT_MSB = 0x04, + PORTAMENTO_TIME_MSB = 0x05, + DATA_ENTRY_MSB = 0x06, + VOLUME_MSB = 0x07, + BALANCE_MSB = 0x08, + PAN_MSB = 0x0A, + EXPRESSION_MSB = 0x0B, + EFFECTS1_MSB = 0x0C, + EFFECTS2_MSB = 0x0D, + GPC1_MSB = 0x10, /* general purpose controller */ + GPC2_MSB = 0x11, + GPC3_MSB = 0x12, + GPC4_MSB = 0x13, + BANK_SELECT_LSB = 0x20, + MODULATION_WHEEL_LSB = 0x21, + BREATH_LSB = 0x22, + FOOT_LSB = 0x24, + PORTAMENTO_TIME_LSB = 0x25, + DATA_ENTRY_LSB = 0x26, + VOLUME_LSB = 0x27, + BALANCE_LSB = 0x28, + PAN_LSB = 0x2A, + EXPRESSION_LSB = 0x2B, + EFFECTS1_LSB = 0x2C, + EFFECTS2_LSB = 0x2D, + GPC1_LSB = 0x30, + GPC2_LSB = 0x31, + GPC3_LSB = 0x32, + GPC4_LSB = 0x33, + SUSTAIN_SWITCH = 0x40, + PORTAMENTO_SWITCH = 0x41, + SOSTENUTO_SWITCH = 0x42, + SOFT_PEDAL_SWITCH = 0x43, + LEGATO_SWITCH = 0x44, + HOLD2_SWITCH = 0x45, + SOUND_CTRL1 = 0x46, + SOUND_CTRL2 = 0x47, + SOUND_CTRL3 = 0x48, + SOUND_CTRL4 = 0x49, + SOUND_CTRL5 = 0x4A, + SOUND_CTRL6 = 0x4B, + SOUND_CTRL7 = 0x4C, + SOUND_CTRL8 = 0x4D, + SOUND_CTRL9 = 0x4E, + SOUND_CTRL10 = 0x4F, + GPC5 = 0x50, + GPC6 = 0x51, + GPC7 = 0x52, + GPC8 = 0x53, + PORTAMENTO_CTRL = 0x54, + EFFECTS_DEPTH1 = 0x5B, + EFFECTS_DEPTH2 = 0x5C, + EFFECTS_DEPTH3 = 0x5D, + EFFECTS_DEPTH4 = 0x5E, + EFFECTS_DEPTH5 = 0x5F, + DATA_ENTRY_INCR = 0x60, + DATA_ENTRY_DECR = 0x61, + NRPN_LSB = 0x62, + NRPN_MSB = 0x63, + RPN_LSB = 0x64, + RPN_MSB = 0x65, + ALL_SOUND_OFF = 0x78, + ALL_CTRL_OFF = 0x79, + LOCAL_CONTROL = 0x7A, + ALL_NOTES_OFF = 0x7B, + OMNI_OFF = 0x7C, + OMNI_ON = 0x7D, + POLY_OFF = 0x7E, + POLY_ON = 0x7F }; /* General MIDI RPN event numbers (LSB, MSB = 0) */ -enum midi_rpn_event { - RPN_PITCH_BEND_RANGE = 0x00, - RPN_CHANNEL_FINE_TUNE = 0x01, - RPN_CHANNEL_COARSE_TUNE = 0x02, - RPN_TUNING_PROGRAM_CHANGE = 0x03, - RPN_TUNING_BANK_SELECT = 0x04, - RPN_MODULATION_DEPTH_RANGE = 0x05 +enum midi_rpn_event +{ + RPN_PITCH_BEND_RANGE = 0x00, + RPN_CHANNEL_FINE_TUNE = 0x01, + RPN_CHANNEL_COARSE_TUNE = 0x02, + RPN_TUNING_PROGRAM_CHANGE = 0x03, + RPN_TUNING_BANK_SELECT = 0x04, + RPN_MODULATION_DEPTH_RANGE = 0x05 }; -enum midi_meta_event { - MIDI_TEXT = 0x01, - MIDI_COPYRIGHT = 0x02, - MIDI_TRACK_NAME = 0x03, - MIDI_INST_NAME = 0x04, - MIDI_LYRIC = 0x05, - MIDI_MARKER = 0x06, - MIDI_CUE_POINT = 0x07, - MIDI_EOT = 0x2f, - MIDI_SET_TEMPO = 0x51, - MIDI_SMPTE_OFFSET = 0x54, - MIDI_TIME_SIGNATURE = 0x58, - MIDI_KEY_SIGNATURE = 0x59, - MIDI_SEQUENCER_EVENT = 0x7f +enum midi_meta_event +{ + MIDI_TEXT = 0x01, + MIDI_COPYRIGHT = 0x02, + MIDI_TRACK_NAME = 0x03, + MIDI_INST_NAME = 0x04, + MIDI_LYRIC = 0x05, + MIDI_MARKER = 0x06, + MIDI_CUE_POINT = 0x07, + MIDI_EOT = 0x2f, + MIDI_SET_TEMPO = 0x51, + MIDI_SMPTE_OFFSET = 0x54, + MIDI_TIME_SIGNATURE = 0x58, + MIDI_KEY_SIGNATURE = 0x59, + MIDI_SEQUENCER_EVENT = 0x7f }; /* MIDI SYSEX useful manufacturer values */ -enum midi_sysex_manuf { - MIDI_SYSEX_MANUF_ROLAND = 0x41, /**< Roland manufacturer ID */ - MIDI_SYSEX_UNIV_NON_REALTIME = 0x7E, /**< Universal non realtime message */ - MIDI_SYSEX_UNIV_REALTIME = 0x7F /**< Universal realtime message */ +enum midi_sysex_manuf +{ + MIDI_SYSEX_MANUF_ROLAND = 0x41, /**< Roland manufacturer ID */ + MIDI_SYSEX_UNIV_NON_REALTIME = 0x7E, /**< Universal non realtime message */ + MIDI_SYSEX_UNIV_REALTIME = 0x7F /**< Universal realtime message */ }; #define MIDI_SYSEX_DEVICE_ID_ALL 0x7F /**< Device ID used in SYSEX messages to indicate all devices */ @@ -186,17 +191,18 @@ enum midi_sysex_manuf { /** * SYSEX tuning message IDs. */ -enum midi_sysex_tuning_msg_id { - MIDI_SYSEX_TUNING_BULK_DUMP_REQ = 0x00, /**< Bulk tuning dump request (non-realtime) */ - MIDI_SYSEX_TUNING_BULK_DUMP = 0x01, /**< Bulk tuning dump response (non-realtime) */ - MIDI_SYSEX_TUNING_NOTE_TUNE = 0x02, /**< Tuning note change message (realtime) */ - MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK = 0x03, /**< Bulk tuning dump request (with bank, non-realtime) */ - MIDI_SYSEX_TUNING_BULK_DUMP_BANK = 0x04, /**< Bulk tuning dump resonse (with bank, non-realtime) */ - MIDI_SYSEX_TUNING_OCTAVE_DUMP_1BYTE = 0x05, /**< Octave tuning dump using 1 byte values (non-realtime) */ - MIDI_SYSEX_TUNING_OCTAVE_DUMP_2BYTE = 0x06, /**< Octave tuning dump using 2 byte values (non-realtime) */ - MIDI_SYSEX_TUNING_NOTE_TUNE_BANK = 0x07, /**< Tuning note change message (with bank, realtime/non-realtime) */ - MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE = 0x08, /**< Octave tuning message using 1 byte values (realtime/non-realtime) */ - MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE = 0x09 /**< Octave tuning message using 2 byte values (realtime/non-realtime) */ +enum midi_sysex_tuning_msg_id +{ + MIDI_SYSEX_TUNING_BULK_DUMP_REQ = 0x00, /**< Bulk tuning dump request (non-realtime) */ + MIDI_SYSEX_TUNING_BULK_DUMP = 0x01, /**< Bulk tuning dump response (non-realtime) */ + MIDI_SYSEX_TUNING_NOTE_TUNE = 0x02, /**< Tuning note change message (realtime) */ + MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK = 0x03, /**< Bulk tuning dump request (with bank, non-realtime) */ + MIDI_SYSEX_TUNING_BULK_DUMP_BANK = 0x04, /**< Bulk tuning dump resonse (with bank, non-realtime) */ + MIDI_SYSEX_TUNING_OCTAVE_DUMP_1BYTE = 0x05, /**< Octave tuning dump using 1 byte values (non-realtime) */ + MIDI_SYSEX_TUNING_OCTAVE_DUMP_2BYTE = 0x06, /**< Octave tuning dump using 2 byte values (non-realtime) */ + MIDI_SYSEX_TUNING_NOTE_TUNE_BANK = 0x07, /**< Tuning note change message (with bank, realtime/non-realtime) */ + MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE = 0x08, /**< Octave tuning message using 1 byte values (realtime/non-realtime) */ + MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE = 0x09 /**< Octave tuning message using 2 byte values (realtime/non-realtime) */ }; /* General MIDI sub-ID #2 */ @@ -205,9 +211,9 @@ enum midi_sysex_tuning_msg_id { enum fluid_driver_status { - FLUID_MIDI_READY, - FLUID_MIDI_LISTENING, - FLUID_MIDI_DONE + FLUID_MIDI_READY, + FLUID_MIDI_LISTENING, + FLUID_MIDI_DONE }; /*************************************************************** @@ -218,27 +224,29 @@ enum fluid_driver_status /* * fluid_midi_event_t */ -struct _fluid_midi_event_t { - fluid_midi_event_t* next; /* Link to next event */ - void *paramptr; /* Pointer parameter (for SYSEX data), size is stored to param1, param2 indicates if pointer should be freed (dynamic if TRUE) */ - unsigned int dtime; /* Delay (ticks) between this and previous event. midi tracks. */ - unsigned int param1; /* First parameter */ - unsigned int param2; /* Second parameter */ - unsigned char type; /* MIDI event type */ - unsigned char channel; /* MIDI channel */ +struct _fluid_midi_event_t +{ + fluid_midi_event_t *next; /* Link to next event */ + void *paramptr; /* Pointer parameter (for SYSEX data), size is stored to param1, param2 indicates if pointer should be freed (dynamic if TRUE) */ + unsigned int dtime; /* Delay (ticks) between this and previous event. midi tracks. */ + unsigned int param1; /* First parameter */ + unsigned int param2; /* Second parameter */ + unsigned char type; /* MIDI event type */ + unsigned char channel; /* MIDI channel */ }; /* * fluid_track_t */ -struct _fluid_track_t { - char* name; - int num; - fluid_midi_event_t *first; - fluid_midi_event_t *cur; - fluid_midi_event_t *last; - unsigned int ticks; +struct _fluid_track_t +{ + char *name; + int num; + fluid_midi_event_t *first; + fluid_midi_event_t *cur; + fluid_midi_event_t *last; + unsigned int ticks; }; typedef struct _fluid_track_t fluid_track_t; @@ -254,69 +262,71 @@ typedef struct _fluid_track_t fluid_track_t; */ typedef struct { - char* filename; /** Name of file (owned); NULL if data pre-loaded */ - void* buffer; /** The MIDI file data (owned); NULL if filename */ + char *filename; /** Name of file (owned); NULL if data pre-loaded */ + void *buffer; /** The MIDI file data (owned); NULL if filename */ size_t buffer_len; /** Number of bytes in buffer; 0 if filename */ } fluid_playlist_item; /* * fluid_player */ -struct _fluid_player_t { - int status; - int ntracks; - fluid_track_t *track[MAX_NUMBER_OF_TRACKS]; - fluid_synth_t* synth; - fluid_timer_t* system_timer; - fluid_sample_timer_t* sample_timer; +struct _fluid_player_t +{ + int status; + int ntracks; + fluid_track_t *track[MAX_NUMBER_OF_TRACKS]; + fluid_synth_t *synth; + fluid_timer_t *system_timer; + fluid_sample_timer_t *sample_timer; - int loop; /* -1 = loop infinitely, otherwise times left to loop the playlist */ - fluid_list_t* playlist; /* List of fluid_playlist_item* objects */ - fluid_list_t* currentfile; /* points to an item in files, or NULL if not playing */ + int loop; /* -1 = loop infinitely, otherwise times left to loop the playlist */ + fluid_list_t *playlist; /* List of fluid_playlist_item* objects */ + fluid_list_t *currentfile; /* points to an item in files, or NULL if not playing */ - char send_program_change; /* should we ignore the program changes? */ - char use_system_timer; /* if zero, use sample timers, otherwise use system clock timer */ - char reset_synth_between_songs; /* 1 if system reset should be sent to the synth between songs. */ - int seek_ticks; /* new position in tempo ticks (midi ticks) for seeking */ - int start_ticks; /* the number of tempo ticks passed at the last tempo change */ - int cur_ticks; /* the number of tempo ticks passed */ - int begin_msec; /* the time (msec) of the beginning of the file */ - int start_msec; /* the start time of the last tempo change */ - int cur_msec; /* the current time */ - 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; + char send_program_change; /* should we ignore the program changes? */ + char use_system_timer; /* if zero, use sample timers, otherwise use system clock timer */ + char reset_synth_between_songs; /* 1 if system reset should be sent to the synth between songs. */ + int seek_ticks; /* new position in tempo ticks (midi ticks) for seeking */ + int start_ticks; /* the number of tempo ticks passed at the last tempo change */ + int cur_ticks; /* the number of tempo ticks passed */ + int begin_msec; /* the time (msec) of the beginning of the file */ + int start_msec; /* the start time of the last tempo change */ + int cur_msec; /* the current time */ + 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; - handle_midi_event_func_t playback_callback; /* function fired on each midi event as it is played */ - void* playback_userdata; /* pointer to user-defined data passed to playback_callback function */ + handle_midi_event_func_t playback_callback; /* function fired on each midi event as it is played */ + void *playback_userdata; /* pointer to user-defined data passed to playback_callback function */ }; -void fluid_player_settings(fluid_settings_t* settings); +void fluid_player_settings(fluid_settings_t *settings); /* * fluid_midi_file */ -typedef struct { - const char* buffer; /* Entire contents of MIDI file (borrowed) */ - int buf_len; /* Length of buffer, in bytes */ - int buf_pos; /* Current read position in contents buffer */ - int eof; /* The "end of file" condition */ - int running_status; - int c; - int type; - int ntracks; - int uses_smpte; - unsigned int smpte_fps; - unsigned int smpte_res; - unsigned int division; /* If uses_SMPTE == 0 then division is +typedef struct +{ + const char *buffer; /* Entire contents of MIDI file (borrowed) */ + int buf_len; /* Length of buffer, in bytes */ + int buf_pos; /* Current read position in contents buffer */ + int eof; /* The "end of file" condition */ + int running_status; + int c; + int type; + int ntracks; + int uses_smpte; + unsigned int smpte_fps; + unsigned int smpte_res; + unsigned int division; /* If uses_SMPTE == 0 then division is ticks per beat (quarter-note) */ - double tempo; /* Beats per second (SI rules =) */ - int tracklen; - int trackpos; - int eot; - int varlen; - int dtime; + double tempo; /* Beats per second (SI rules =) */ + int tracklen; + int trackpos; + int eot; + int varlen; + int dtime; } fluid_midi_file; @@ -326,13 +336,14 @@ typedef struct { /* * fluid_midi_parser_t */ -struct _fluid_midi_parser_t { - unsigned char status; /* Identifies the type of event, that is currently received ('Noteon', 'Pitch Bend' etc). */ - unsigned char channel; /* The channel of the event that is received (in case of a channel event) */ - unsigned int nr_bytes; /* How many bytes have been read for the current event? */ - unsigned int nr_bytes_total; /* How many bytes does the current event type include? */ - unsigned char data[FLUID_MIDI_PARSER_MAX_DATA_SIZE]; /* The parameters or SYSEX data */ - fluid_midi_event_t event; /* The event, that is returned to the MIDI driver. */ +struct _fluid_midi_parser_t +{ + unsigned char status; /* Identifies the type of event, that is currently received ('Noteon', 'Pitch Bend' etc). */ + unsigned char channel; /* The channel of the event that is received (in case of a channel event) */ + unsigned int nr_bytes; /* How many bytes have been read for the current event? */ + unsigned int nr_bytes_total; /* How many bytes does the current event type include? */ + unsigned char data[FLUID_MIDI_PARSER_MAX_DATA_SIZE]; /* The parameters or SYSEX data */ + fluid_midi_event_t event; /* The event, that is returned to the MIDI driver. */ }; diff --git a/src/midi/fluid_midi_router.c b/src/midi/fluid_midi_router.c index 1f96b489..c3bc8916 100644 --- a/src/midi/fluid_midi_router.c +++ b/src/midi/fluid_midi_router.c @@ -31,18 +31,20 @@ /* * fluid_midi_router */ -struct _fluid_midi_router_t { - fluid_mutex_t rules_mutex; - fluid_midi_router_rule_t *rules[FLUID_MIDI_ROUTER_RULE_COUNT]; /* List of rules for each rule type */ - fluid_midi_router_rule_t *free_rules; /* List of rules to free (was waiting for final events which were received) */ +struct _fluid_midi_router_t +{ + fluid_mutex_t rules_mutex; + fluid_midi_router_rule_t *rules[FLUID_MIDI_ROUTER_RULE_COUNT]; /* List of rules for each rule type */ + fluid_midi_router_rule_t *free_rules; /* List of rules to free (was waiting for final events which were received) */ - handle_midi_event_func_t event_handler; /* Callback function for generated events */ - void* event_handler_data; /* One arg for the callback */ + handle_midi_event_func_t event_handler; /* Callback function for generated events */ + void *event_handler_data; /* One arg for the callback */ - int nr_midi_channels; /* For clipping the midi channel */ + int nr_midi_channels; /* For clipping the midi channel */ }; -struct _fluid_midi_router_rule_t { +struct _fluid_midi_router_rule_t +{ int chan_min; /* Channel window, for which this rule is valid */ int chan_max; fluid_real_t chan_mul; /* Channel multiplier (usually 0 or 1) */ @@ -60,7 +62,7 @@ struct _fluid_midi_router_rule_t { int pending_events; /* In case of noteon: How many keys are still down? */ char keys_cc[128]; /* Flags, whether a key is down / controller is set (sustain) */ - fluid_midi_router_rule_t* next; /* next entry */ + fluid_midi_router_rule_t *next; /* next entry */ int waiting; /* Set to TRUE when rule has been deactivated but there are still pending_events */ }; @@ -81,39 +83,43 @@ fluid_midi_router_t * new_fluid_midi_router(fluid_settings_t *settings, handle_midi_event_func_t handler, void *event_handler_data) { - fluid_midi_router_t *router = NULL; - int i; + fluid_midi_router_t *router = NULL; + int i; - router = FLUID_NEW (fluid_midi_router_t); + router = FLUID_NEW(fluid_midi_router_t); - if (router == NULL) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); + if(router == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t)); + + /* Retrieve the number of MIDI channels for range limiting */ + fluid_settings_getint(settings, "synth.midi-channels", &router->nr_midi_channels); + + fluid_mutex_init(router->rules_mutex); + + router->event_handler = handler; + router->event_handler_data = event_handler_data; + + /* Create default routing rules which pass all events unmodified */ + for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) + { + router->rules[i] = new_fluid_midi_router_rule(); + + if(!router->rules[i]) + { + goto error_recovery; + } + } + + return router; + +error_recovery: + delete_fluid_midi_router(router); return NULL; - } - - FLUID_MEMSET (router, 0, sizeof (fluid_midi_router_t)); - - /* Retrieve the number of MIDI channels for range limiting */ - fluid_settings_getint(settings, "synth.midi-channels", &router->nr_midi_channels); - - fluid_mutex_init (router->rules_mutex); - - router->event_handler = handler; - router->event_handler_data = event_handler_data; - - /* Create default routing rules which pass all events unmodified */ - for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) - { - router->rules[i] = new_fluid_midi_router_rule (); - if (!router->rules[i]) goto error_recovery; - } - - return router; - - error_recovery: - delete_fluid_midi_router (router); - return NULL; } /** @@ -123,25 +129,25 @@ new_fluid_midi_router(fluid_settings_t *settings, handle_midi_event_func_t handl * \a router passed really) */ void -delete_fluid_midi_router (fluid_midi_router_t *router) +delete_fluid_midi_router(fluid_midi_router_t *router) { - fluid_midi_router_rule_t *rule; - fluid_midi_router_rule_t *next_rule; - int i; + fluid_midi_router_rule_t *rule; + fluid_midi_router_rule_t *next_rule; + int i; - fluid_return_if_fail (router != NULL); + fluid_return_if_fail(router != NULL); - for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) - { - for (rule = router->rules[i]; rule; rule = next_rule) + for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) { - next_rule = rule->next; - FLUID_FREE (rule); + for(rule = router->rules[i]; rule; rule = next_rule) + { + next_rule = rule->next; + FLUID_FREE(rule); + } } - } - fluid_mutex_destroy (router->rules_mutex); - FLUID_FREE (router); + fluid_mutex_destroy(router->rules_mutex); + FLUID_FREE(router); } /** @@ -152,79 +158,89 @@ delete_fluid_midi_router (fluid_midi_router_t *router) * @since 1.1.0 */ int -fluid_midi_router_set_default_rules (fluid_midi_router_t *router) +fluid_midi_router_set_default_rules(fluid_midi_router_t *router) { - fluid_midi_router_rule_t *new_rules[FLUID_MIDI_ROUTER_RULE_COUNT]; - fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT]; - fluid_midi_router_rule_t *rule, *next_rule, *prev_rule; - int i, i2; + fluid_midi_router_rule_t *new_rules[FLUID_MIDI_ROUTER_RULE_COUNT]; + fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT]; + fluid_midi_router_rule_t *rule, *next_rule, *prev_rule; + int i, i2; - fluid_return_val_if_fail (router != NULL, FLUID_FAILED); + fluid_return_val_if_fail(router != NULL, FLUID_FAILED); - /* Allocate new default rules outside of lock */ + /* Allocate new default rules outside of lock */ - for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) - { - new_rules[i] = new_fluid_midi_router_rule (); - - if (!new_rules[i]) - { /* Free already allocated rules */ - for (i2 = 0; i2 < i; i2++) - delete_fluid_midi_router_rule (new_rules[i2]); - - return FLUID_FAILED; - } - } - - - fluid_mutex_lock (router->rules_mutex); /* ++ lock */ - - for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) - { - del_rules[i] = NULL; - prev_rule = NULL; - - /* Process existing rules */ - for (rule = router->rules[i]; rule; rule = next_rule) + for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) { - next_rule = rule->next; + new_rules[i] = new_fluid_midi_router_rule(); - if (rule->pending_events == 0) /* Rule has no pending events? */ - { /* Remove rule from rule list */ - if (prev_rule) prev_rule->next = next_rule; - else if (rule == router->rules[i]) router->rules[i] = next_rule; + if(!new_rules[i]) + { + /* Free already allocated rules */ + for(i2 = 0; i2 < i; i2++) + { + delete_fluid_midi_router_rule(new_rules[i2]); + } - /* Prepend to delete list */ - rule->next = del_rules[i]; - del_rules[i] = rule; - } - else - { - rule->waiting = TRUE; /* Pending events, mark as waiting */ - prev_rule = rule; - } + return FLUID_FAILED; + } } - /* Prepend new default rule */ - new_rules[i]->next = router->rules[i]; - router->rules[i] = new_rules[i]; - } - fluid_mutex_unlock (router->rules_mutex); /* -- unlock */ + fluid_mutex_lock(router->rules_mutex); /* ++ lock */ - - /* Free old rules outside of lock */ - - for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) - { - for (rule = del_rules[i]; rule; rule = next_rule) + for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) { - next_rule = rule->next; - FLUID_FREE (rule); - } - } + del_rules[i] = NULL; + prev_rule = NULL; - return FLUID_OK; + /* Process existing rules */ + for(rule = router->rules[i]; rule; rule = next_rule) + { + next_rule = rule->next; + + if(rule->pending_events == 0) /* Rule has no pending events? */ + { + /* Remove rule from rule list */ + if(prev_rule) + { + prev_rule->next = next_rule; + } + else if(rule == router->rules[i]) + { + router->rules[i] = next_rule; + } + + /* Prepend to delete list */ + rule->next = del_rules[i]; + del_rules[i] = rule; + } + else + { + rule->waiting = TRUE; /* Pending events, mark as waiting */ + prev_rule = rule; + } + } + + /* Prepend new default rule */ + new_rules[i]->next = router->rules[i]; + router->rules[i] = new_rules[i]; + } + + fluid_mutex_unlock(router->rules_mutex); /* -- unlock */ + + + /* Free old rules outside of lock */ + + for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) + { + for(rule = del_rules[i]; rule; rule = next_rule) + { + next_rule = rule->next; + FLUID_FREE(rule); + } + } + + return FLUID_OK; } /** @@ -235,58 +251,65 @@ fluid_midi_router_set_default_rules (fluid_midi_router_t *router) * @since 1.1.0 */ int -fluid_midi_router_clear_rules (fluid_midi_router_t *router) +fluid_midi_router_clear_rules(fluid_midi_router_t *router) { - fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT]; - fluid_midi_router_rule_t *rule, *next_rule, *prev_rule; - int i; + fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT]; + fluid_midi_router_rule_t *rule, *next_rule, *prev_rule; + int i; - fluid_return_val_if_fail (router != NULL, FLUID_FAILED); + fluid_return_val_if_fail(router != NULL, FLUID_FAILED); - fluid_mutex_lock (router->rules_mutex); /* ++ lock */ + fluid_mutex_lock(router->rules_mutex); /* ++ lock */ - for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) - { - del_rules[i] = NULL; - prev_rule = NULL; - - /* Process existing rules */ - for (rule = router->rules[i]; rule; rule = next_rule) + for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) { - next_rule = rule->next; + del_rules[i] = NULL; + prev_rule = NULL; - if (rule->pending_events == 0) /* Rule has no pending events? */ - { /* Remove rule from rule list */ - if (prev_rule) prev_rule->next = next_rule; - else if (rule == router->rules[i]) router->rules[i] = next_rule; + /* Process existing rules */ + for(rule = router->rules[i]; rule; rule = next_rule) + { + next_rule = rule->next; - /* Prepend to delete list */ - rule->next = del_rules[i]; - del_rules[i] = rule; - } - else - { - rule->waiting = TRUE; /* Pending events, mark as waiting */ - prev_rule = rule; - } + if(rule->pending_events == 0) /* Rule has no pending events? */ + { + /* Remove rule from rule list */ + if(prev_rule) + { + prev_rule->next = next_rule; + } + else if(rule == router->rules[i]) + { + router->rules[i] = next_rule; + } + + /* Prepend to delete list */ + rule->next = del_rules[i]; + del_rules[i] = rule; + } + else + { + rule->waiting = TRUE; /* Pending events, mark as waiting */ + prev_rule = rule; + } + } } - } - fluid_mutex_unlock (router->rules_mutex); /* -- unlock */ + fluid_mutex_unlock(router->rules_mutex); /* -- unlock */ - /* Free old rules outside of lock */ + /* Free old rules outside of lock */ - for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) - { - for (rule = del_rules[i]; rule; rule = next_rule) + for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++) { - next_rule = rule->next; - FLUID_FREE (rule); + for(rule = del_rules[i]; rule; rule = next_rule) + { + next_rule = rule->next; + FLUID_FREE(rule); + } } - } - return FLUID_OK; + return FLUID_OK; } /** @@ -299,37 +322,37 @@ fluid_midi_router_clear_rules (fluid_midi_router_t *router) * @since 1.1.0 */ int -fluid_midi_router_add_rule (fluid_midi_router_t *router, fluid_midi_router_rule_t *rule, - int type) +fluid_midi_router_add_rule(fluid_midi_router_t *router, fluid_midi_router_rule_t *rule, + int type) { - fluid_midi_router_rule_t *free_rules, *next_rule; + fluid_midi_router_rule_t *free_rules, *next_rule; - fluid_return_val_if_fail (router != NULL, FLUID_FAILED); - fluid_return_val_if_fail (rule != NULL, FLUID_FAILED); - fluid_return_val_if_fail (type >= 0 && type < FLUID_MIDI_ROUTER_RULE_COUNT, FLUID_FAILED); + fluid_return_val_if_fail(router != NULL, FLUID_FAILED); + fluid_return_val_if_fail(rule != NULL, FLUID_FAILED); + fluid_return_val_if_fail(type >= 0 && type < FLUID_MIDI_ROUTER_RULE_COUNT, FLUID_FAILED); - fluid_mutex_lock (router->rules_mutex); /* ++ lock */ + fluid_mutex_lock(router->rules_mutex); /* ++ lock */ - /* Take over free rules list, if any (to free outside of lock) */ - free_rules = router->free_rules; - router->free_rules = NULL; + /* Take over free rules list, if any (to free outside of lock) */ + free_rules = router->free_rules; + router->free_rules = NULL; - rule->next = router->rules[type]; - router->rules[type] = rule; + rule->next = router->rules[type]; + router->rules[type] = rule; - fluid_mutex_unlock (router->rules_mutex); /* -- unlock */ + fluid_mutex_unlock(router->rules_mutex); /* -- unlock */ - /* Free any deactivated rules which were waiting for events and are now done */ + /* Free any deactivated rules which were waiting for events and are now done */ - for (; free_rules; free_rules = next_rule) - { - next_rule = free_rules->next; - FLUID_FREE (free_rules); - } + for(; free_rules; free_rules = next_rule) + { + next_rule = free_rules->next; + FLUID_FREE(free_rules); + } - return FLUID_OK; + return FLUID_OK; } /** @@ -341,33 +364,34 @@ fluid_midi_router_add_rule (fluid_midi_router_t *router, fluid_midi_router_rule_ * them. */ fluid_midi_router_rule_t * -new_fluid_midi_router_rule (void) +new_fluid_midi_router_rule(void) { - fluid_midi_router_rule_t *rule; + fluid_midi_router_rule_t *rule; - rule = FLUID_NEW (fluid_midi_router_rule_t); + rule = FLUID_NEW(fluid_midi_router_rule_t); - if (rule == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + if(rule == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - FLUID_MEMSET (rule, 0, sizeof (fluid_midi_router_rule_t)); + FLUID_MEMSET(rule, 0, sizeof(fluid_midi_router_rule_t)); - rule->chan_min = 0; - rule->chan_max = 999999; - rule->chan_mul = 1.0; - rule->chan_add = 0; - rule->par1_min = 0; - rule->par1_max = 999999; - rule->par1_mul = 1.0; - rule->par1_add = 0; - rule->par2_min = 0; - rule->par2_max = 999999; - rule->par2_mul = 1.0; - rule->par2_add = 0; + rule->chan_min = 0; + rule->chan_max = 999999; + rule->chan_mul = 1.0; + rule->chan_add = 0; + rule->par1_min = 0; + rule->par1_max = 999999; + rule->par1_mul = 1.0; + rule->par1_add = 0; + rule->par2_min = 0; + rule->par2_max = 999999; + rule->par2_mul = 1.0; + rule->par2_add = 0; - return rule; + return rule; }; /** @@ -379,10 +403,10 @@ new_fluid_midi_router_rule (void) * so this function should seldom be needed. */ void -delete_fluid_midi_router_rule (fluid_midi_router_rule_t *rule) +delete_fluid_midi_router_rule(fluid_midi_router_rule_t *rule) { - fluid_return_if_fail (rule != NULL); - FLUID_FREE (rule); + fluid_return_if_fail(rule != NULL); + FLUID_FREE(rule); } /** @@ -404,14 +428,14 @@ delete_fluid_midi_router_rule (fluid_midi_router_rule_t *rule) * sending the event, if the rule matches. */ void -fluid_midi_router_rule_set_chan (fluid_midi_router_rule_t *rule, int min, int max, - float mul, int add) +fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t *rule, int min, int max, + float mul, int add) { - fluid_return_if_fail (rule != NULL); - rule->chan_min = min; - rule->chan_max = max; - rule->chan_mul = mul; - rule->chan_add = add; + fluid_return_if_fail(rule != NULL); + rule->chan_min = min; + rule->chan_max = max; + rule->chan_mul = mul; + rule->chan_add = add; } /** @@ -442,14 +466,14 @@ fluid_midi_router_rule_set_chan (fluid_midi_router_rule_t *rule, int min, int ma * sending the event, if the rule matches. */ void -fluid_midi_router_rule_set_param1 (fluid_midi_router_rule_t *rule, int min, int max, - float mul, int add) +fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t *rule, int min, int max, + float mul, int add) { - fluid_return_if_fail (rule != NULL); - rule->par1_min = min; - rule->par1_max = max; - rule->par1_mul = mul; - rule->par1_add = add; + fluid_return_if_fail(rule != NULL); + rule->par1_min = min; + rule->par1_max = max; + rule->par1_mul = mul; + rule->par1_add = add; } /** @@ -477,14 +501,14 @@ fluid_midi_router_rule_set_param1 (fluid_midi_router_rule_t *rule, int min, int * sending the event, if the rule matches. */ void -fluid_midi_router_rule_set_param2 (fluid_midi_router_rule_t *rule, int min, int max, - float mul, int add) +fluid_midi_router_rule_set_param2(fluid_midi_router_rule_t *rule, int min, int max, + float mul, int add) { - fluid_return_if_fail (rule != NULL); - rule->par2_min = min; - rule->par2_max = max; - rule->par2_mul = mul; - rule->par2_add = add; + fluid_return_if_fail(rule != NULL); + rule->par2_min = min; + rule->par2_max = max; + rule->par2_mul = mul; + rule->par2_add = add; } /** @@ -513,224 +537,276 @@ fluid_midi_router_rule_set_param2 (fluid_midi_router_rule_t *rule, int min, int * - ... */ int -fluid_midi_router_handle_midi_event (void* data, fluid_midi_event_t* event) +fluid_midi_router_handle_midi_event(void *data, fluid_midi_event_t *event) { - fluid_midi_router_t* router = (fluid_midi_router_t *)data; - fluid_midi_router_rule_t **rulep, *rule, *next_rule, *prev_rule = NULL; - int event_has_par2 = 0; /* Flag, indicates that current event needs two parameters */ - int par1_max = 127; /* Range limit for par1 */ - int par2_max = 127; /* Range limit for par2 */ - int ret_val = FLUID_OK; + fluid_midi_router_t *router = (fluid_midi_router_t *)data; + fluid_midi_router_rule_t **rulep, *rule, *next_rule, *prev_rule = NULL; + int event_has_par2 = 0; /* Flag, indicates that current event needs two parameters */ + int par1_max = 127; /* Range limit for par1 */ + int par2_max = 127; /* Range limit for par2 */ + int ret_val = FLUID_OK; - int chan; /* Channel of the generated event */ - int par1; /* par1 of the generated event */ - int par2; - int event_par1; - int event_par2; - fluid_midi_event_t new_event; + int chan; /* Channel of the generated event */ + int par1; /* par1 of the generated event */ + int par2; + int event_par1; + int event_par2; + fluid_midi_event_t new_event; - /* Some keyboards report noteoff through a noteon event with vel=0. - * Convert those to noteoff to ease processing. */ - if (event->type == NOTE_ON && event->param2 == 0) - { - event->type = NOTE_OFF; - event->param2 = 127; /* Release velocity */ - } + /* Some keyboards report noteoff through a noteon event with vel=0. + * Convert those to noteoff to ease processing. */ + if(event->type == NOTE_ON && event->param2 == 0) + { + event->type = NOTE_OFF; + event->param2 = 127; /* Release velocity */ + } - fluid_mutex_lock (router->rules_mutex); /* ++ lock rules */ + fluid_mutex_lock(router->rules_mutex); /* ++ lock rules */ - /* Depending on the event type, choose the correct list of rules. */ - switch (event->type) - { - case NOTE_ON: - rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE]; - event_has_par2 = 1; - break; - case NOTE_OFF: - rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE]; - event_has_par2 = 1; - break; - case CONTROL_CHANGE: - rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CC]; - event_has_par2 = 1; - break; - case PROGRAM_CHANGE: - rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PROG_CHANGE]; - break; - case PITCH_BEND: - rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PITCH_BEND]; - par1_max = 16383; - break; - case CHANNEL_PRESSURE: - rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE]; - break; - case KEY_PRESSURE: - rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE]; - event_has_par2 = 1; - break; - case MIDI_SYSTEM_RESET: - case MIDI_SYSEX: - ret_val = router->event_handler (router->event_handler_data,event); - fluid_mutex_unlock (router->rules_mutex); /* -- unlock rules */ + /* Depending on the event type, choose the correct list of rules. */ + switch(event->type) + { + case NOTE_ON: + rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE]; + event_has_par2 = 1; + break; + + case NOTE_OFF: + rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE]; + event_has_par2 = 1; + break; + + case CONTROL_CHANGE: + rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CC]; + event_has_par2 = 1; + break; + + case PROGRAM_CHANGE: + rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PROG_CHANGE]; + break; + + case PITCH_BEND: + rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PITCH_BEND]; + par1_max = 16383; + break; + + case CHANNEL_PRESSURE: + rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE]; + break; + + case KEY_PRESSURE: + rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE]; + event_has_par2 = 1; + break; + + case MIDI_SYSTEM_RESET: + case MIDI_SYSEX: + ret_val = router->event_handler(router->event_handler_data, event); + fluid_mutex_unlock(router->rules_mutex); /* -- unlock rules */ return ret_val; - default: + + default: rulep = NULL; /* Event will not be passed on */ - break; - } - - /* Loop over rules in the list, looking for matches for this event. */ - for (rule = rulep ? *rulep : NULL; rule; prev_rule = rule, rule = next_rule) - { - event_par1 = (int)event->param1; - event_par2 = (int)event->param2; - next_rule = rule->next; /* Rule may get removed from list, so get next here */ - - /* Channel window */ - if (rule->chan_min > rule->chan_max) - { /* Inverted rule: Exclude everything between max and min (but not min/max) */ - if (event->channel > rule->chan_max && event->channel < rule->chan_min) - continue; + break; } - else /* Normal rule: Exclude everything < max or > min (but not min/max) */ + + /* Loop over rules in the list, looking for matches for this event. */ + for(rule = rulep ? *rulep : NULL; rule; prev_rule = rule, rule = next_rule) { - if (event->channel > rule->chan_max || event->channel < rule->chan_min) - continue; - } + event_par1 = (int)event->param1; + event_par2 = (int)event->param2; + next_rule = rule->next; /* Rule may get removed from list, so get next here */ - /* Par 1 window */ - if (rule->par1_min > rule->par1_max) - { /* Inverted rule: Exclude everything between max and min (but not min/max) */ - if (event_par1 > rule->par1_max && event_par1 < rule->par1_min) - continue; - } - else /* Normal rule: Exclude everything < max or > min (but not min/max)*/ - { - if (event_par1 > rule->par1_max || event_par1 < rule->par1_min) - continue; - } - - /* Par 2 window (only applies to event types, which have 2 pars) - * For noteoff events, velocity switching doesn't make any sense. - * Velocity scaling might be useful, though. - */ - if (event_has_par2 && event->type != NOTE_OFF) - { - if (rule->par2_min > rule->par2_max) - { /* Inverted rule: Exclude everything between max and min (but not min/max) */ - if (event_par2 > rule->par2_max && event_par2 < rule->par2_min) - continue; - } - else /* Normal rule: Exclude everything < max or > min (but not min/max)*/ - { - if (event_par2 > rule->par2_max || event_par2 < rule->par2_min) - continue; - } - } - - /* Channel scaling / offset - * Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all - * input channels is mapped to the same synth channel. - */ - chan = (int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul - + (fluid_real_t)rule->chan_add + 0.5); - - /* Par 1 scaling / offset */ - par1 = (int)((fluid_real_t)event_par1 * (fluid_real_t)rule->par1_mul - + (fluid_real_t)rule->par1_add + 0.5); - - /* Par 2 scaling / offset, if applicable */ - if (event_has_par2) - par2 = (int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul - + (fluid_real_t)rule->par2_add + 0.5); - else par2 = 0; - - /* Channel range limiting */ - if (chan < 0) - chan = 0; - else if (chan >= router->nr_midi_channels) - chan = router->nr_midi_channels - 1; - - /* Par1 range limiting */ - if (par1 < 0) - par1 = 0; - else if (par1 > par1_max) - par1 = par1_max; - - /* Par2 range limiting */ - if (event_has_par2) - { - if (par2 < 0) - par2 = 0; - else if (par2 > par2_max) - par2 = par2_max; - } - - /* At this point we have to create an event of event->type on 'chan' with par1 (maybe par2). - * We keep track on the state of noteon and sustain pedal events. If the application tries - * to delete a rule, it will only be fully removed, if pending noteoff / pedal off events have - * arrived. In the meantime while waiting, it will only let through 'negative' events - * (noteoff or pedal up). - */ - if (event->type == NOTE_ON || (event->type == CONTROL_CHANGE - && par1 == SUSTAIN_SWITCH && par2 >= 64)) - { - /* Noteon or sustain pedal down event generated */ - if (rule->keys_cc[par1] == 0) - { - rule->keys_cc[par1] = 1; - rule->pending_events++; - } - } - else if (event->type == NOTE_OFF || (event->type == CONTROL_CHANGE - && par1 == SUSTAIN_SWITCH && par2 < 64)) - { /* Noteoff or sustain pedal up event generated */ - if (rule->keys_cc[par1] > 0) - { - rule->keys_cc[par1] = 0; - rule->pending_events--; - - /* Rule is waiting for negative event to be destroyed? */ - if (rule->waiting) + /* Channel window */ + if(rule->chan_min > rule->chan_max) { - if (rule->pending_events == 0) - { /* Remove rule from rule list */ - if (prev_rule) prev_rule->next = next_rule; - else *rulep = next_rule; - - /* Add to free list */ - rule->next = router->free_rules; - router->free_rules = rule; - - rule = prev_rule; /* Set rule to previous rule, which gets assigned to the next prev_rule value (in for() statement) */ - } - - goto send_event; /* Pass the event to complete the cycle */ + /* Inverted rule: Exclude everything between max and min (but not min/max) */ + if(event->channel > rule->chan_max && event->channel < rule->chan_min) + { + continue; + } + } + else /* Normal rule: Exclude everything < max or > min (but not min/max) */ + { + if(event->channel > rule->chan_max || event->channel < rule->chan_min) + { + continue; + } } - } - } - /* Rule is still waiting for negative event? (note off or pedal up) */ - if (rule->waiting) - continue; /* Skip (rule is inactive except for matching negative event) */ + /* Par 1 window */ + if(rule->par1_min > rule->par1_max) + { + /* Inverted rule: Exclude everything between max and min (but not min/max) */ + if(event_par1 > rule->par1_max && event_par1 < rule->par1_min) + { + continue; + } + } + else /* Normal rule: Exclude everything < max or > min (but not min/max)*/ + { + if(event_par1 > rule->par1_max || event_par1 < rule->par1_min) + { + continue; + } + } + + /* Par 2 window (only applies to event types, which have 2 pars) + * For noteoff events, velocity switching doesn't make any sense. + * Velocity scaling might be useful, though. + */ + if(event_has_par2 && event->type != NOTE_OFF) + { + if(rule->par2_min > rule->par2_max) + { + /* Inverted rule: Exclude everything between max and min (but not min/max) */ + if(event_par2 > rule->par2_max && event_par2 < rule->par2_min) + { + continue; + } + } + else /* Normal rule: Exclude everything < max or > min (but not min/max)*/ + { + if(event_par2 > rule->par2_max || event_par2 < rule->par2_min) + { + continue; + } + } + } + + /* Channel scaling / offset + * Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all + * input channels is mapped to the same synth channel. + */ + chan = (int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul + + (fluid_real_t)rule->chan_add + 0.5); + + /* Par 1 scaling / offset */ + par1 = (int)((fluid_real_t)event_par1 * (fluid_real_t)rule->par1_mul + + (fluid_real_t)rule->par1_add + 0.5); + + /* Par 2 scaling / offset, if applicable */ + if(event_has_par2) + { + par2 = (int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul + + (fluid_real_t)rule->par2_add + 0.5); + } + else + { + par2 = 0; + } + + /* Channel range limiting */ + if(chan < 0) + { + chan = 0; + } + else if(chan >= router->nr_midi_channels) + { + chan = router->nr_midi_channels - 1; + } + + /* Par1 range limiting */ + if(par1 < 0) + { + par1 = 0; + } + else if(par1 > par1_max) + { + par1 = par1_max; + } + + /* Par2 range limiting */ + if(event_has_par2) + { + if(par2 < 0) + { + par2 = 0; + } + else if(par2 > par2_max) + { + par2 = par2_max; + } + } + + /* At this point we have to create an event of event->type on 'chan' with par1 (maybe par2). + * We keep track on the state of noteon and sustain pedal events. If the application tries + * to delete a rule, it will only be fully removed, if pending noteoff / pedal off events have + * arrived. In the meantime while waiting, it will only let through 'negative' events + * (noteoff or pedal up). + */ + if(event->type == NOTE_ON || (event->type == CONTROL_CHANGE + && par1 == SUSTAIN_SWITCH && par2 >= 64)) + { + /* Noteon or sustain pedal down event generated */ + if(rule->keys_cc[par1] == 0) + { + rule->keys_cc[par1] = 1; + rule->pending_events++; + } + } + else if(event->type == NOTE_OFF || (event->type == CONTROL_CHANGE + && par1 == SUSTAIN_SWITCH && par2 < 64)) + { + /* Noteoff or sustain pedal up event generated */ + if(rule->keys_cc[par1] > 0) + { + rule->keys_cc[par1] = 0; + rule->pending_events--; + + /* Rule is waiting for negative event to be destroyed? */ + if(rule->waiting) + { + if(rule->pending_events == 0) + { + /* Remove rule from rule list */ + if(prev_rule) + { + prev_rule->next = next_rule; + } + else + { + *rulep = next_rule; + } + + /* Add to free list */ + rule->next = router->free_rules; + router->free_rules = rule; + + rule = prev_rule; /* Set rule to previous rule, which gets assigned to the next prev_rule value (in for() statement) */ + } + + goto send_event; /* Pass the event to complete the cycle */ + } + } + } + + /* Rule is still waiting for negative event? (note off or pedal up) */ + if(rule->waiting) + { + continue; /* Skip (rule is inactive except for matching negative event) */ + } send_event: - /* At this point it is decided, what is sent to the synth. - * Create a new event and make the appropriate call */ + /* At this point it is decided, what is sent to the synth. + * Create a new event and make the appropriate call */ - fluid_midi_event_set_type (&new_event, event->type); - fluid_midi_event_set_channel (&new_event, chan); - new_event.param1 = par1; - new_event.param2 = par2; + fluid_midi_event_set_type(&new_event, event->type); + fluid_midi_event_set_channel(&new_event, chan); + new_event.param1 = par1; + new_event.param2 = par2; - /* FIXME - What should be done on failure? For now continue to process events, but return failure to caller. */ - if (router->event_handler (router->event_handler_data, &new_event) != FLUID_OK) - ret_val = FLUID_FAILED; - } + /* FIXME - What should be done on failure? For now continue to process events, but return failure to caller. */ + if(router->event_handler(router->event_handler_data, &new_event) != FLUID_OK) + { + ret_val = FLUID_FAILED; + } + } - fluid_mutex_unlock (router->rules_mutex); /* -- unlock rules */ + fluid_mutex_unlock(router->rules_mutex); /* -- unlock rules */ - return ret_val; + return ret_val; } /** @@ -743,38 +819,47 @@ send_event: * displaying MIDI event information between the MIDI driver and router to * stdout. Useful for adding into a MIDI router chain for debugging MIDI events. */ -int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event) +int fluid_midi_dump_prerouter(void *data, fluid_midi_event_t *event) { - switch (event->type) { - case NOTE_ON: - fprintf(stdout, "event_pre_noteon %i %i %i\n", - event->channel, event->param1, event->param2); - break; - case NOTE_OFF: - fprintf(stdout, "event_pre_noteoff %i %i %i\n", - event->channel, event->param1, event->param2); - break; - case CONTROL_CHANGE: - fprintf(stdout, "event_pre_cc %i %i %i\n", - event->channel, event->param1, event->param2); - break; - case PROGRAM_CHANGE: - fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1); - break; - case PITCH_BEND: + switch(event->type) + { + case NOTE_ON: + fprintf(stdout, "event_pre_noteon %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + case NOTE_OFF: + fprintf(stdout, "event_pre_noteoff %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + case CONTROL_CHANGE: + fprintf(stdout, "event_pre_cc %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + case PROGRAM_CHANGE: + fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1); + break; + + case PITCH_BEND: fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1); - break; - case CHANNEL_PRESSURE: - fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1); - break; - case KEY_PRESSURE: - fprintf(stdout, "event_pre_kpress %i %i %i\n", - event->channel, event->param1, event->param2); - break; - default: - break; - } - return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event); + break; + + case CHANNEL_PRESSURE: + fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1); + break; + + case KEY_PRESSURE: + fprintf(stdout, "event_pre_kpress %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + default: + break; + } + + return fluid_midi_router_handle_midi_event((fluid_midi_router_t *) data, event); } /** @@ -787,36 +872,45 @@ int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event) * displaying MIDI event information between the MIDI driver and router to * stdout. Useful for adding into a MIDI router chain for debugging MIDI events. */ -int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event) +int fluid_midi_dump_postrouter(void *data, fluid_midi_event_t *event) { - switch (event->type) { - case NOTE_ON: - fprintf(stdout, "event_post_noteon %i %i %i\n", - event->channel, event->param1, event->param2); - break; - case NOTE_OFF: - fprintf(stdout, "event_post_noteoff %i %i %i\n", - event->channel, event->param1, event->param2); - break; - case CONTROL_CHANGE: - fprintf(stdout, "event_post_cc %i %i %i\n", - event->channel, event->param1, event->param2); - break; - case PROGRAM_CHANGE: - fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1); - break; - case PITCH_BEND: - fprintf(stdout, "event_post_pitch %i %i\n", event->channel, event->param1); - break; - case CHANNEL_PRESSURE: - fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1); - break; - case KEY_PRESSURE: - fprintf(stdout, "event_post_kpress %i %i %i\n", - event->channel, event->param1, event->param2); - break; - default: - break; - } - return fluid_synth_handle_midi_event((fluid_synth_t*) data, event); + switch(event->type) + { + case NOTE_ON: + fprintf(stdout, "event_post_noteon %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + case NOTE_OFF: + fprintf(stdout, "event_post_noteoff %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + case CONTROL_CHANGE: + fprintf(stdout, "event_post_cc %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + case PROGRAM_CHANGE: + fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1); + break; + + case PITCH_BEND: + fprintf(stdout, "event_post_pitch %i %i\n", event->channel, event->param1); + break; + + case CHANNEL_PRESSURE: + fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1); + break; + + case KEY_PRESSURE: + fprintf(stdout, "event_post_kpress %i %i %i\n", + event->channel, event->param1, event->param2); + break; + + default: + break; + } + + return fluid_synth_handle_midi_event((fluid_synth_t *) data, event); } diff --git a/src/midi/fluid_seq.c b/src/midi/fluid_seq.c index 5dfb22be..b94bf5ed 100644 --- a/src/midi/fluid_seq.c +++ b/src/midi/fluid_seq.c @@ -39,49 +39,51 @@ #define FLUID_SEQUENCER_EVENTS_MAX 1000 /* Private data for SEQUENCER */ -struct _fluid_sequencer_t { - unsigned int startMs; - fluid_atomic_int_t currentMs; - int useSystemTimer; - double scale; // ticks per second - fluid_list_t* clients; - fluid_seq_id_t clientsID; - /* for queue + heap */ - fluid_evt_entry* preQueue; - fluid_evt_entry* preQueueLast; - fluid_timer_t* timer; - int queue0StartTime; - short prevCellNb; - fluid_evt_entry* queue0[256][2]; - fluid_evt_entry* queue1[255][2]; - fluid_evt_entry* queueLater; - fluid_evt_heap_t* heap; - fluid_mutex_t mutex; +struct _fluid_sequencer_t +{ + unsigned int startMs; + fluid_atomic_int_t currentMs; + int useSystemTimer; + double scale; // ticks per second + fluid_list_t *clients; + fluid_seq_id_t clientsID; + /* for queue + heap */ + fluid_evt_entry *preQueue; + fluid_evt_entry *preQueueLast; + fluid_timer_t *timer; + int queue0StartTime; + short prevCellNb; + fluid_evt_entry *queue0[256][2]; + fluid_evt_entry *queue1[255][2]; + fluid_evt_entry *queueLater; + fluid_evt_heap_t *heap; + fluid_mutex_t mutex; #if FLUID_SEQ_WITH_TRACE - char *tracebuf; - char *traceptr; - int tracelen; + char *tracebuf; + char *traceptr; + int tracelen; #endif }; /* Private data for clients */ -typedef struct _fluid_sequencer_client_t { - fluid_seq_id_t id; - char* name; - fluid_event_callback_t callback; - void* data; +typedef struct _fluid_sequencer_client_t +{ + fluid_seq_id_t id; + char *name; + fluid_event_callback_t callback; + void *data; } fluid_sequencer_client_t; /* prototypes */ -static short _fluid_seq_queue_init(fluid_sequencer_t* seq, int nbEvents); -static void _fluid_seq_queue_end(fluid_sequencer_t* seq); -static short _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt); -static void _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, fluid_seq_id_t src, fluid_seq_id_t dest, int type); -static int _fluid_seq_queue_process(void* data, unsigned int msec); // callback from timer -static void _fluid_seq_queue_insert_entry(fluid_sequencer_t* seq, fluid_evt_entry * evtentry); -static void _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry* temp); -static void _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq); -static void _fluid_free_evt_queue(fluid_evt_entry** first, fluid_evt_entry** last); +static short _fluid_seq_queue_init(fluid_sequencer_t *seq, int nbEvents); +static void _fluid_seq_queue_end(fluid_sequencer_t *seq); +static short _fluid_seq_queue_pre_insert(fluid_sequencer_t *seq, fluid_event_t *evt); +static void _fluid_seq_queue_pre_remove(fluid_sequencer_t *seq, fluid_seq_id_t src, fluid_seq_id_t dest, int type); +static int _fluid_seq_queue_process(void *data, unsigned int msec); // callback from timer +static void _fluid_seq_queue_insert_entry(fluid_sequencer_t *seq, fluid_evt_entry *evtentry); +static void _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t *seq, fluid_evt_entry *temp); +static void _fluid_seq_queue_send_queued_events(fluid_sequencer_t *seq); +static void _fluid_free_evt_queue(fluid_evt_entry **first, fluid_evt_entry **last); /* API implementation */ @@ -92,10 +94,10 @@ static void _fluid_free_evt_queue(fluid_evt_entry** first, fluid_evt_entry** las * fluid_sequencer_process() is used to advance the sequencer. * @return New sequencer instance */ -fluid_sequencer_t* -new_fluid_sequencer (void) +fluid_sequencer_t * +new_fluid_sequencer(void) { - return new_fluid_sequencer2 (TRUE); + return new_fluid_sequencer2(TRUE); } /** @@ -106,44 +108,50 @@ new_fluid_sequencer (void) * @return New sequencer instance * @since 1.1.0 */ -fluid_sequencer_t* -new_fluid_sequencer2 (int use_system_timer) +fluid_sequencer_t * +new_fluid_sequencer2(int use_system_timer) { - fluid_sequencer_t* seq; + fluid_sequencer_t *seq; - seq = FLUID_NEW(fluid_sequencer_t); - if (seq == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return NULL; - } + seq = FLUID_NEW(fluid_sequencer_t); - FLUID_MEMSET(seq, 0, sizeof(fluid_sequencer_t)); + if(seq == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return NULL; + } - seq->scale = 1000; // default value - seq->useSystemTimer = use_system_timer ? 1 : 0; - seq->startMs = seq->useSystemTimer ? fluid_curtime() : 0; - seq->clients = NULL; - seq->clientsID = 0; + FLUID_MEMSET(seq, 0, sizeof(fluid_sequencer_t)); - if (-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) { - FLUID_FREE(seq); - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return NULL; - } + seq->scale = 1000; // default value + seq->useSystemTimer = use_system_timer ? 1 : 0; + seq->startMs = seq->useSystemTimer ? fluid_curtime() : 0; + seq->clients = NULL; + seq->clientsID = 0; + + if(-1 == _fluid_seq_queue_init(seq, FLUID_SEQUENCER_EVENTS_MAX)) + { + FLUID_FREE(seq); + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return NULL; + } #if FLUID_SEQ_WITH_TRACE - seq->tracelen = 1024*100; - seq->tracebuf = (char *)FLUID_MALLOC(seq->tracelen); - if (seq->tracebuf == NULL) { - _fluid_seq_queue_end(seq); - FLUID_FREE(seq); - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return NULL; - } - seq->traceptr = seq->tracebuf; + seq->tracelen = 1024 * 100; + seq->tracebuf = (char *)FLUID_MALLOC(seq->tracelen); + + if(seq->tracebuf == NULL) + { + _fluid_seq_queue_end(seq); + FLUID_FREE(seq); + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return NULL; + } + + seq->traceptr = seq->tracebuf; #endif - return(seq); + return(seq); } /** @@ -151,36 +159,41 @@ new_fluid_sequencer2 (int use_system_timer) * @param seq Sequencer to delete */ void -delete_fluid_sequencer (fluid_sequencer_t* seq) +delete_fluid_sequencer(fluid_sequencer_t *seq) { fluid_return_if_fail(seq != NULL); - /* cleanup clients */ - while (seq->clients) { - fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)seq->clients->data; - fluid_sequencer_unregister_client(seq, client->id); - } + /* cleanup clients */ + while(seq->clients) + { + fluid_sequencer_client_t *client = (fluid_sequencer_client_t *)seq->clients->data; + fluid_sequencer_unregister_client(seq, client->id); + } - _fluid_seq_queue_end(seq); + _fluid_seq_queue_end(seq); -/* if (seq->clients) { - fluid_list_t *tmp = seq->clients; - while (tmp != NULL) { - fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; - if (client->name) FLUID_FREE(client->name); - tmp = tmp->next; - } - delete_fluid_list(seq->clients); - seq->clients = NULL; - }*/ + /* if (seq->clients) { + fluid_list_t *tmp = seq->clients; + while (tmp != NULL) { + fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; + if (client->name) FLUID_FREE(client->name); + tmp = tmp->next; + } + delete_fluid_list(seq->clients); + seq->clients = NULL; + }*/ #if FLUID_SEQ_WITH_TRACE - if (seq->tracebuf != NULL) - FLUID_FREE(seq->tracebuf); - seq->tracebuf = NULL; + + if(seq->tracebuf != NULL) + { + FLUID_FREE(seq->tracebuf); + } + + seq->tracebuf = NULL; #endif - FLUID_FREE(seq); + FLUID_FREE(seq); } /** @@ -189,10 +202,10 @@ delete_fluid_sequencer (fluid_sequencer_t* seq) * @return TRUE if system timer is being used, FALSE otherwise. * @since 1.1.0 */ -int -fluid_sequencer_get_use_system_timer (fluid_sequencer_t* seq) +int +fluid_sequencer_get_use_system_timer(fluid_sequencer_t *seq) { - return seq->useSystemTimer; + return seq->useSystemTimer; } @@ -200,27 +213,35 @@ fluid_sequencer_get_use_system_timer (fluid_sequencer_t* seq) /* trace */ void -fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) +fluid_seq_dotrace(fluid_sequencer_t *seq, char *fmt, ...) { - va_list args; - int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf); - if (remain <= 0) return; + va_list args; + int len, remain = seq->tracelen - (seq->traceptr - seq->tracebuf); - va_start (args, fmt); - len = FLUID_VSNPRINTF (seq->traceptr, remain, fmt, args); - va_end (args); + if(remain <= 0) + { + return; + } - if (len > 0) { - if (len <= remain) { - // all written, with 0 at end - seq->traceptr += len; - } else { - // not enough room, set to end - seq->traceptr = seq->tracebuf + seq->tracelen; - } - } + va_start(args, fmt); + len = FLUID_VSNPRINTF(seq->traceptr, remain, fmt, args); + va_end(args); - return; + if(len > 0) + { + if(len <= remain) + { + // all written, with 0 at end + seq->traceptr += len; + } + else + { + // not enough room, set to end + seq->traceptr = seq->tracebuf + seq->tracelen; + } + } + + return; } /** @@ -228,9 +249,9 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) * @param seq Sequencer object */ void -fluid_seq_cleartrace(fluid_sequencer_t* seq) +fluid_seq_cleartrace(fluid_sequencer_t *seq) { - seq->traceptr = seq->tracebuf; + seq->traceptr = seq->tracebuf; } /** @@ -238,13 +259,13 @@ fluid_seq_cleartrace(fluid_sequencer_t* seq) * @param seq Sequencer object */ char * -fluid_seq_gettrace(fluid_sequencer_t* seq) +fluid_seq_gettrace(fluid_sequencer_t *seq) { - return seq->tracebuf; + return seq->tracebuf; } #else -void fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) {} +void fluid_seq_dotrace(fluid_sequencer_t *seq, char *fmt, ...) {} #endif // FLUID_SEQ_WITH_TRACE @@ -260,40 +281,44 @@ void fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) {} * * Clients can be sources or destinations of events. Sources don't need to * register a callback. - * + * * @note The user must explicitly unregister any registered client with fluid_sequencer_unregister_client() * before deleting the sequencer! */ fluid_seq_id_t -fluid_sequencer_register_client (fluid_sequencer_t* seq, const char *name, - fluid_event_callback_t callback, void* data) +fluid_sequencer_register_client(fluid_sequencer_t *seq, const char *name, + fluid_event_callback_t callback, void *data) { - fluid_sequencer_client_t * client; - char * nameCopy; + fluid_sequencer_client_t *client; + char *nameCopy; - client = FLUID_NEW(fluid_sequencer_client_t); - if (client == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return FLUID_FAILED; - } + client = FLUID_NEW(fluid_sequencer_client_t); - nameCopy = FLUID_STRDUP(name); - if (nameCopy == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - FLUID_FREE(client); - return FLUID_FAILED; - } + if(client == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return FLUID_FAILED; + } - seq->clientsID++; + nameCopy = FLUID_STRDUP(name); - client->name = nameCopy; - client->id = seq->clientsID; - client->callback = callback; - client->data = data; + if(nameCopy == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + FLUID_FREE(client); + return FLUID_FAILED; + } - seq->clients = fluid_list_append(seq->clients, (void *)client); + seq->clientsID++; - return (client->id); + client->name = nameCopy; + client->id = seq->clientsID; + client->callback = callback; + client->data = data; + + seq->clients = fluid_list_append(seq->clients, (void *)client); + + return (client->id); } /** @@ -302,27 +327,38 @@ fluid_sequencer_register_client (fluid_sequencer_t* seq, const char *name, * @param id Client ID as returned by fluid_sequencer_register_client(). */ void -fluid_sequencer_unregister_client (fluid_sequencer_t* seq, fluid_seq_id_t id) +fluid_sequencer_unregister_client(fluid_sequencer_t *seq, fluid_seq_id_t id) { - fluid_list_t *tmp; + fluid_list_t *tmp; - if (seq->clients == NULL) return; + if(seq->clients == NULL) + { + return; + } - tmp = seq->clients; - while (tmp) { - fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; + tmp = seq->clients; - if (client->id == id) { - if (client->name) - FLUID_FREE(client->name); - seq->clients = fluid_list_remove_link(seq->clients, tmp); - delete1_fluid_list(tmp); - FLUID_FREE(client); - return; - } - tmp = tmp->next; - } - return; + while(tmp) + { + fluid_sequencer_client_t *client = (fluid_sequencer_client_t *)tmp->data; + + if(client->id == id) + { + if(client->name) + { + FLUID_FREE(client->name); + } + + seq->clients = fluid_list_remove_link(seq->clients, tmp); + delete1_fluid_list(tmp); + FLUID_FREE(client); + return; + } + + tmp = tmp->next; + } + + return; } /** @@ -331,11 +367,14 @@ fluid_sequencer_unregister_client (fluid_sequencer_t* seq, fluid_seq_id_t id) * @return Count of sequencer clients. */ int -fluid_sequencer_count_clients(fluid_sequencer_t* seq) +fluid_sequencer_count_clients(fluid_sequencer_t *seq) { - if (seq->clients == NULL) - return 0; - return fluid_list_size(seq->clients); + if(seq->clients == NULL) + { + return 0; + } + + return fluid_list_size(seq->clients); } /** @@ -344,15 +383,19 @@ fluid_sequencer_count_clients(fluid_sequencer_t* seq) * @param index Index of register client * @return Client ID or #FLUID_FAILED if not found */ -fluid_seq_id_t fluid_sequencer_get_client_id (fluid_sequencer_t* seq, int index) +fluid_seq_id_t fluid_sequencer_get_client_id(fluid_sequencer_t *seq, int index) { - fluid_list_t *tmp = fluid_list_nth(seq->clients, index); - if (tmp == NULL) { - return FLUID_FAILED; - } else { - fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; - return client->id; - } + fluid_list_t *tmp = fluid_list_nth(seq->clients, index); + + if(tmp == NULL) + { + return FLUID_FAILED; + } + else + { + fluid_sequencer_client_t *client = (fluid_sequencer_client_t *)tmp->data; + return client->id; + } } /** @@ -363,23 +406,30 @@ fluid_seq_id_t fluid_sequencer_get_client_id (fluid_sequencer_t* seq, int index) * be modified or freed. */ char * -fluid_sequencer_get_client_name(fluid_sequencer_t* seq, fluid_seq_id_t id) +fluid_sequencer_get_client_name(fluid_sequencer_t *seq, fluid_seq_id_t id) { - fluid_list_t *tmp; + fluid_list_t *tmp; - if (seq->clients == NULL) - return NULL; + if(seq->clients == NULL) + { + return NULL; + } - tmp = seq->clients; - while (tmp) { - fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; + tmp = seq->clients; - if (client->id == id) - return client->name; + while(tmp) + { + fluid_sequencer_client_t *client = (fluid_sequencer_client_t *)tmp->data; - tmp = tmp->next; - } - return NULL; + if(client->id == id) + { + return client->name; + } + + tmp = tmp->next; + } + + return NULL; } /** @@ -389,22 +439,30 @@ fluid_sequencer_get_client_name(fluid_sequencer_t* seq, fluid_seq_id_t id) * @return TRUE if client is a destination client, FALSE otherwise or if not found */ int -fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, fluid_seq_id_t id) +fluid_sequencer_client_is_dest(fluid_sequencer_t *seq, fluid_seq_id_t id) { - fluid_list_t *tmp; + fluid_list_t *tmp; - if (seq->clients == NULL) return FALSE; + if(seq->clients == NULL) + { + return FALSE; + } - tmp = seq->clients; - while (tmp) { - fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; + tmp = seq->clients; - if (client->id == id) - return (client->callback != NULL); + while(tmp) + { + fluid_sequencer_client_t *client = (fluid_sequencer_client_t *)tmp->data; - tmp = tmp->next; - } - return FALSE; + if(client->id == id) + { + return (client->callback != NULL); + } + + tmp = tmp->next; + } + + return FALSE; } /** @@ -414,23 +472,29 @@ fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, fluid_seq_id_t id) */ /* Event not actually copied, but since its used immediately it virtually is. */ void -fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt) +fluid_sequencer_send_now(fluid_sequencer_t *seq, fluid_event_t *evt) { - fluid_seq_id_t destID = fluid_event_get_dest(evt); + fluid_seq_id_t destID = fluid_event_get_dest(evt); - /* find callback */ - fluid_list_t *tmp = seq->clients; - while (tmp) { - fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data; + /* find callback */ + fluid_list_t *tmp = seq->clients; - if (dest->id == destID) { - if (dest->callback) - (dest->callback)(fluid_sequencer_get_tick(seq), - evt, seq, dest->data); - return; - } - tmp = tmp->next; - } + while(tmp) + { + fluid_sequencer_client_t *dest = (fluid_sequencer_client_t *)tmp->data; + + if(dest->id == destID) + { + if(dest->callback) + { + (dest->callback)(fluid_sequencer_get_tick(seq), evt, seq, dest->data); + } + + return; + } + + tmp = tmp->next; + } } /** @@ -443,20 +507,22 @@ fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_sequencer_send_at (fluid_sequencer_t* seq, fluid_event_t* evt, - unsigned int time, int absolute) +fluid_sequencer_send_at(fluid_sequencer_t *seq, fluid_event_t *evt, + unsigned int time, int absolute) { - unsigned int now = fluid_sequencer_get_tick(seq); + unsigned int now = fluid_sequencer_get_tick(seq); - /* set absolute */ - if (!absolute) - time = now + time; + /* set absolute */ + if(!absolute) + { + time = now + time; + } - /* time stamp event */ - fluid_event_set_time(evt, time); + /* time stamp event */ + fluid_event_set_time(evt, time); - /* queue for processing later */ - return _fluid_seq_queue_pre_insert(seq, evt); + /* queue for processing later */ + return _fluid_seq_queue_pre_insert(seq, evt); } /** @@ -467,10 +533,10 @@ fluid_sequencer_send_at (fluid_sequencer_t* seq, fluid_event_t* evt, * @param type Event type to match or -1 for wildcard (#fluid_seq_event_type) */ void -fluid_sequencer_remove_events (fluid_sequencer_t* seq, fluid_seq_id_t source, - fluid_seq_id_t dest, int type) +fluid_sequencer_remove_events(fluid_sequencer_t *seq, fluid_seq_id_t source, + fluid_seq_id_t dest, int type) { - _fluid_seq_queue_pre_remove(seq, source, dest, type); + _fluid_seq_queue_pre_remove(seq, source, dest, type); } @@ -484,14 +550,14 @@ fluid_sequencer_remove_events (fluid_sequencer_t* seq, fluid_seq_id_t source, * @return Current tick value */ unsigned int -fluid_sequencer_get_tick (fluid_sequencer_t* seq) +fluid_sequencer_get_tick(fluid_sequencer_t *seq) { - unsigned int absMs = seq->useSystemTimer ? (int) fluid_curtime() : fluid_atomic_int_get(&seq->currentMs); - double nowFloat; - unsigned int now; - nowFloat = ((double)(absMs - seq->startMs))*seq->scale/1000.0f; - now = nowFloat; - return now; + unsigned int absMs = seq->useSystemTimer ? (int) fluid_curtime() : fluid_atomic_int_get(&seq->currentMs); + double nowFloat; + unsigned int now; + nowFloat = ((double)(absMs - seq->startMs)) * seq->scale / 1000.0f; + now = nowFloat; + return now; } /** @@ -504,48 +570,58 @@ fluid_sequencer_get_tick (fluid_sequencer_t* seq) * the events are adjusted accordingly. */ void -fluid_sequencer_set_time_scale (fluid_sequencer_t* seq, double scale) +fluid_sequencer_set_time_scale(fluid_sequencer_t *seq, double scale) { - if (scale <= 0) { - fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale); - return; - } + if(scale <= 0) + { + fluid_log(FLUID_WARN, "sequencer: scale <= 0 : %f\n", scale); + return; + } - if (scale > 1000.0) - // Otherwise : problems with the timer = 0ms... - scale = 1000.0; + if(scale > 1000.0) + // Otherwise : problems with the timer = 0ms... + { + scale = 1000.0; + } - if (seq->scale != scale) { - double oldScale = seq->scale; + if(seq->scale != scale) + { + double oldScale = seq->scale; - // stop timer - if (seq->timer) { - delete_fluid_timer(seq->timer); - seq->timer = NULL; - } + // stop timer + if(seq->timer) + { + delete_fluid_timer(seq->timer); + seq->timer = NULL; + } - seq->scale = scale; + seq->scale = scale; - // change start0 so that cellNb is preserved - seq->queue0StartTime = (seq->queue0StartTime + seq->prevCellNb)*(seq->scale/oldScale) - seq->prevCellNb; + // change start0 so that cellNb is preserved + seq->queue0StartTime = (seq->queue0StartTime + seq->prevCellNb) * (seq->scale / oldScale) - seq->prevCellNb; - // change all preQueue events for new scale - { - fluid_evt_entry* tmp; - tmp = seq->preQueue; - while (tmp) { - if (tmp->entryType == FLUID_EVT_ENTRY_INSERT) - tmp->evt.time = tmp->evt.time*seq->scale/oldScale; + // change all preQueue events for new scale + { + fluid_evt_entry *tmp; + tmp = seq->preQueue; - tmp = tmp->next; - } - } + while(tmp) + { + if(tmp->entryType == FLUID_EVT_ENTRY_INSERT) + { + tmp->evt.time = tmp->evt.time * seq->scale / oldScale; + } - /* re-start timer */ - if (seq->useSystemTimer) { - seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, (void *)seq, TRUE, FALSE, TRUE); - } - } + tmp = tmp->next; + } + } + + /* re-start timer */ + if(seq->useSystemTimer) + { + seq->timer = new_fluid_timer((int)(1000 / seq->scale), _fluid_seq_queue_process, (void *)seq, TRUE, FALSE, TRUE); + } + } } /** @@ -554,9 +630,9 @@ fluid_sequencer_set_time_scale (fluid_sequencer_t* seq, double scale) * @return Time scale value in ticks per second. */ double -fluid_sequencer_get_time_scale(fluid_sequencer_t* seq) +fluid_sequencer_get_time_scale(fluid_sequencer_t *seq) { - return seq->scale; + return seq->scale; } @@ -639,59 +715,72 @@ fluid_sequencer_get_time_scale(fluid_sequencer_t* seq) /********************/ static short -_fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents) +_fluid_seq_queue_init(fluid_sequencer_t *seq, int maxEvents) { - seq->heap = _fluid_evt_heap_init(maxEvents); - if (seq->heap == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return -1; - } + seq->heap = _fluid_evt_heap_init(maxEvents); - seq->preQueue = NULL; - seq->preQueueLast = NULL; + if(seq->heap == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return -1; + } - FLUID_MEMSET(seq->queue0, 0, 2*256*sizeof(fluid_evt_entry *)); - FLUID_MEMSET(seq->queue1, 0, 2*255*sizeof(fluid_evt_entry *)); + seq->preQueue = NULL; + seq->preQueueLast = NULL; - seq->queueLater = NULL; - seq->queue0StartTime = fluid_sequencer_get_tick(seq); - seq->prevCellNb = -1; + FLUID_MEMSET(seq->queue0, 0, 2 * 256 * sizeof(fluid_evt_entry *)); + FLUID_MEMSET(seq->queue1, 0, 2 * 255 * sizeof(fluid_evt_entry *)); - fluid_mutex_init(seq->mutex); + seq->queueLater = NULL; + seq->queue0StartTime = fluid_sequencer_get_tick(seq); + seq->prevCellNb = -1; - /* start timer */ - if (seq->useSystemTimer) { - seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, - (void *)seq, TRUE, FALSE, TRUE); - } - return (0); + fluid_mutex_init(seq->mutex); + + /* start timer */ + if(seq->useSystemTimer) + { + seq->timer = new_fluid_timer((int)(1000 / seq->scale), _fluid_seq_queue_process, + (void *)seq, TRUE, FALSE, TRUE); + } + + return (0); } static void -_fluid_seq_queue_end(fluid_sequencer_t* seq) +_fluid_seq_queue_end(fluid_sequencer_t *seq) { - int i; + int i; - /* free all remaining events */ - _fluid_free_evt_queue(&seq->preQueue, &seq->preQueueLast); - for (i = 0; i < 256; i++) - _fluid_free_evt_queue(&(seq->queue0[i][0]), &(seq->queue0[i][1])); - for (i = 0; i < 255; i++) - _fluid_free_evt_queue(&(seq->queue1[i][0]), &(seq->queue1[i][1])); - _fluid_free_evt_queue(&seq->queueLater, NULL); + /* free all remaining events */ + _fluid_free_evt_queue(&seq->preQueue, &seq->preQueueLast); + + for(i = 0; i < 256; i++) + { + _fluid_free_evt_queue(&(seq->queue0[i][0]), &(seq->queue0[i][1])); + } + + for(i = 0; i < 255; i++) + { + _fluid_free_evt_queue(&(seq->queue1[i][0]), &(seq->queue1[i][1])); + } + + _fluid_free_evt_queue(&seq->queueLater, NULL); - if (seq->timer) { - delete_fluid_timer(seq->timer); - seq->timer = NULL; - } + if(seq->timer) + { + delete_fluid_timer(seq->timer); + seq->timer = NULL; + } - if (seq->heap) { - _fluid_evt_heap_free(seq->heap); - seq->heap = NULL; - } + if(seq->heap) + { + _fluid_evt_heap_free(seq->heap); + seq->heap = NULL; + } - fluid_mutex_destroy(seq->mutex); + fluid_mutex_destroy(seq->mutex); } @@ -704,501 +793,614 @@ _fluid_seq_queue_end(fluid_sequencer_t* seq) * May be called from the main thread (usually) but also recursively * from the queue thread, when a callback itself does an insert... */ static short -_fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt) +_fluid_seq_queue_pre_insert(fluid_sequencer_t *seq, fluid_event_t *evt) { - fluid_evt_entry * evtentry = _fluid_seq_heap_get_free(seq->heap); - if (evtentry == NULL) { - /* should not happen */ - fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); - return -1; - } + fluid_evt_entry *evtentry = _fluid_seq_heap_get_free(seq->heap); - evtentry->next = NULL; - evtentry->entryType = FLUID_EVT_ENTRY_INSERT; - FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t)); + if(evtentry == NULL) + { + /* should not happen */ + fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); + return -1; + } - fluid_mutex_lock(seq->mutex); + evtentry->next = NULL; + evtentry->entryType = FLUID_EVT_ENTRY_INSERT; + FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t)); - /* append to preQueue */ - if (seq->preQueueLast) { - seq->preQueueLast->next = evtentry; - } else { - seq->preQueue = evtentry; - } - seq->preQueueLast = evtentry; + fluid_mutex_lock(seq->mutex); - fluid_mutex_unlock(seq->mutex); + /* append to preQueue */ + if(seq->preQueueLast) + { + seq->preQueueLast->next = evtentry; + } + else + { + seq->preQueue = evtentry; + } - return (0); + seq->preQueueLast = evtentry; + + fluid_mutex_unlock(seq->mutex); + + return (0); } /* Create event_entry and append to the preQueue. * May be called from the main thread (usually) but also recursively * from the queue thread, when a callback itself does an insert... */ static void -_fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, fluid_seq_id_t src, fluid_seq_id_t dest, int type) +_fluid_seq_queue_pre_remove(fluid_sequencer_t *seq, fluid_seq_id_t src, fluid_seq_id_t dest, int type) { - fluid_evt_entry * evtentry = _fluid_seq_heap_get_free(seq->heap); - if (evtentry == NULL) { - /* should not happen */ - fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); - return; - } + fluid_evt_entry *evtentry = _fluid_seq_heap_get_free(seq->heap); - evtentry->next = NULL; - evtentry->entryType = FLUID_EVT_ENTRY_REMOVE; - { - fluid_event_t* evt = &(evtentry->evt); - fluid_event_set_source(evt, src); - fluid_event_set_source(evt, src); - fluid_event_set_dest(evt, dest); - evt->type = type; - } + if(evtentry == NULL) + { + /* should not happen */ + fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); + return; + } - fluid_mutex_lock(seq->mutex); + evtentry->next = NULL; + evtentry->entryType = FLUID_EVT_ENTRY_REMOVE; + { + fluid_event_t *evt = &(evtentry->evt); + fluid_event_set_source(evt, src); + fluid_event_set_source(evt, src); + fluid_event_set_dest(evt, dest); + evt->type = type; + } - /* append to preQueue */ - if (seq->preQueueLast) { - seq->preQueueLast->next = evtentry; - } else { - seq->preQueue = evtentry; - } - seq->preQueueLast = evtentry; + fluid_mutex_lock(seq->mutex); - fluid_mutex_unlock(seq->mutex); - return; + /* append to preQueue */ + if(seq->preQueueLast) + { + seq->preQueueLast->next = evtentry; + } + else + { + seq->preQueue = evtentry; + } + + seq->preQueueLast = evtentry; + + fluid_mutex_unlock(seq->mutex); + return; } static void -_fluid_free_evt_queue(fluid_evt_entry** first, fluid_evt_entry** last) +_fluid_free_evt_queue(fluid_evt_entry **first, fluid_evt_entry **last) { - fluid_evt_entry* tmp2; - fluid_evt_entry* tmp = *first; - while (tmp != NULL) { - tmp2 = tmp->next; - FLUID_FREE(tmp); - tmp = tmp2; - } - *first = NULL; - if (last != NULL) { - *last = NULL; - } + fluid_evt_entry *tmp2; + fluid_evt_entry *tmp = *first; + + while(tmp != NULL) + { + tmp2 = tmp->next; + FLUID_FREE(tmp); + tmp = tmp2; + } + + *first = NULL; + + if(last != NULL) + { + *last = NULL; + } } /* Callback from timer (may be in a different thread, or in an interrupt) */ static int -_fluid_seq_queue_process(void* data, unsigned int msec) +_fluid_seq_queue_process(void *data, unsigned int msec) { - fluid_sequencer_t* seq = (fluid_sequencer_t *)data; - fluid_sequencer_process(seq, msec); - /* continue timer */ - return 1; + fluid_sequencer_t *seq = (fluid_sequencer_t *)data; + fluid_sequencer_process(seq, msec); + /* continue timer */ + return 1; } -/** +/** * Advance a sequencer that isn't using the system timer. * @param seq Sequencer object * @param msec Time to advance sequencer to (absolute time since sequencer start). * @since 1.1.0 */ void -fluid_sequencer_process(fluid_sequencer_t* seq, unsigned int msec) +fluid_sequencer_process(fluid_sequencer_t *seq, unsigned int msec) { - /* process prequeue */ - fluid_evt_entry* tmp; - fluid_evt_entry* next; + /* process prequeue */ + fluid_evt_entry *tmp; + fluid_evt_entry *next; - fluid_mutex_lock(seq->mutex); + fluid_mutex_lock(seq->mutex); - /* get the preQueue */ - tmp = seq->preQueue; - seq->preQueue = NULL; - seq->preQueueLast = NULL; + /* get the preQueue */ + tmp = seq->preQueue; + seq->preQueue = NULL; + seq->preQueueLast = NULL; - fluid_mutex_unlock(seq->mutex); + fluid_mutex_unlock(seq->mutex); - /* walk all the preQueue and process them in order : inserts and removes */ - while (tmp) { - next = tmp->next; + /* walk all the preQueue and process them in order : inserts and removes */ + while(tmp) + { + next = tmp->next; - if (tmp->entryType == FLUID_EVT_ENTRY_REMOVE) { - _fluid_seq_queue_remove_entries_matching(seq, tmp); - } else { - _fluid_seq_queue_insert_entry(seq, tmp); - } + if(tmp->entryType == FLUID_EVT_ENTRY_REMOVE) + { + _fluid_seq_queue_remove_entries_matching(seq, tmp); + } + else + { + _fluid_seq_queue_insert_entry(seq, tmp); + } - tmp = next; - } + tmp = next; + } - /* send queued events */ - fluid_atomic_int_set(&seq->currentMs, msec); - _fluid_seq_queue_send_queued_events(seq); + /* send queued events */ + fluid_atomic_int_set(&seq->currentMs, msec); + _fluid_seq_queue_send_queued_events(seq); } #if 0 static void -_fluid_seq_queue_print_later(fluid_sequencer_t* seq) +_fluid_seq_queue_print_later(fluid_sequencer_t *seq) { - int count = 0; - fluid_evt_entry* tmp = seq->queueLater; + int count = 0; + fluid_evt_entry *tmp = seq->queueLater; - printf("queueLater:\n"); + printf("queueLater:\n"); - while (tmp) { - unsigned int delay = tmp->evt.time - seq->queue0StartTime; - printf("queueLater: Delay = %i\n", delay); - tmp = tmp->next; - count++; - } - printf("queueLater: Total of %i events\n", count); + while(tmp) + { + unsigned int delay = tmp->evt.time - seq->queue0StartTime; + printf("queueLater: Delay = %i\n", delay); + tmp = tmp->next; + count++; + } + + printf("queueLater: Total of %i events\n", count); } #endif static void -_fluid_seq_queue_insert_queue0(fluid_sequencer_t* seq, fluid_evt_entry* tmp, int cell) +_fluid_seq_queue_insert_queue0(fluid_sequencer_t *seq, fluid_evt_entry *tmp, int cell) { - if (seq->queue0[cell][1] == NULL) { - seq->queue0[cell][1] = seq->queue0[cell][0] = tmp; - } else { - seq->queue0[cell][1]->next = tmp; - seq->queue0[cell][1] = tmp; - } - tmp->next = NULL; + if(seq->queue0[cell][1] == NULL) + { + seq->queue0[cell][1] = seq->queue0[cell][0] = tmp; + } + else + { + seq->queue0[cell][1]->next = tmp; + seq->queue0[cell][1] = tmp; + } + + tmp->next = NULL; } static void -_fluid_seq_queue_insert_queue1(fluid_sequencer_t* seq, fluid_evt_entry* tmp, int cell) +_fluid_seq_queue_insert_queue1(fluid_sequencer_t *seq, fluid_evt_entry *tmp, int cell) { - if (seq->queue1[cell][1] == NULL) { - seq->queue1[cell][1] = seq->queue1[cell][0] = tmp; - } else { - seq->queue1[cell][1]->next = tmp; - seq->queue1[cell][1] = tmp; - } - tmp->next = NULL; + if(seq->queue1[cell][1] == NULL) + { + seq->queue1[cell][1] = seq->queue1[cell][0] = tmp; + } + else + { + seq->queue1[cell][1]->next = tmp; + seq->queue1[cell][1] = tmp; + } + + tmp->next = NULL; } static void -_fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evtentry) +_fluid_seq_queue_insert_queue_later(fluid_sequencer_t *seq, fluid_evt_entry *evtentry) { - fluid_evt_entry* prev; - fluid_evt_entry* tmp; - unsigned int time = evtentry->evt.time; + fluid_evt_entry *prev; + fluid_evt_entry *tmp; + unsigned int time = evtentry->evt.time; - /* insert in 'queueLater', after the ones that have the same - * time */ + /* insert in 'queueLater', after the ones that have the same + * time */ - /* first? */ - if ((seq->queueLater == NULL) - || (seq->queueLater->evt.time > time)) { - evtentry->next = seq->queueLater; - seq->queueLater = evtentry; - return; - } + /* first? */ + if((seq->queueLater == NULL) + || (seq->queueLater->evt.time > time)) + { + evtentry->next = seq->queueLater; + seq->queueLater = evtentry; + return; + } - /* walk queueLater */ - /* this is the only slow thing : if the event is more - than 65535 ticks after the current time */ + /* walk queueLater */ + /* this is the only slow thing : if the event is more + than 65535 ticks after the current time */ - prev = seq->queueLater; - tmp = prev->next; - while (tmp) { - if (tmp->evt.time > time) { - /* insert before tmp */ - evtentry->next = tmp; - prev->next = evtentry; - return; - } - prev = tmp; - tmp = prev->next; - } + prev = seq->queueLater; + tmp = prev->next; - /* last */ - evtentry->next = NULL; - prev->next = evtentry; + while(tmp) + { + if(tmp->evt.time > time) + { + /* insert before tmp */ + evtentry->next = tmp; + prev->next = evtentry; + return; + } + + prev = tmp; + tmp = prev->next; + } + + /* last */ + evtentry->next = NULL; + prev->next = evtentry; } static void -_fluid_seq_queue_insert_entry(fluid_sequencer_t* seq, fluid_evt_entry * evtentry) +_fluid_seq_queue_insert_entry(fluid_sequencer_t *seq, fluid_evt_entry *evtentry) { - /* time is relative to seq origin, in ticks */ - fluid_event_t * evt = &(evtentry->evt); - unsigned int time = evt->time; - unsigned int delay; + /* time is relative to seq origin, in ticks */ + fluid_event_t *evt = &(evtentry->evt); + unsigned int time = evt->time; + unsigned int delay; - if (seq->queue0StartTime > 0) { - /* queue0StartTime could be < 0 if the scale changed a - lot early, breaking the following comparison - */ - if (time < (unsigned int)seq->queue0StartTime) { - /* we are late, send now */ - fluid_sequencer_send_now(seq, evt); + if(seq->queue0StartTime > 0) + { + /* queue0StartTime could be < 0 if the scale changed a + lot early, breaking the following comparison + */ + if(time < (unsigned int)seq->queue0StartTime) + { + /* we are late, send now */ + fluid_sequencer_send_now(seq, evt); - _fluid_seq_heap_set_free(seq->heap, evtentry); - return; - } - } + _fluid_seq_heap_set_free(seq->heap, evtentry); + return; + } + } - if (seq->prevCellNb >= 0) { - /* prevCellNb could be -1 is seq was just started - unlikely */ - /* prevCellNb can also be -1 if cellNb was reset to 0 in - _fluid_seq_queue_send_queued_events() */ - if (time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) { - /* we are late, send now */ - fluid_sequencer_send_now(seq, evt); + if(seq->prevCellNb >= 0) + { + /* prevCellNb could be -1 is seq was just started - unlikely */ + /* prevCellNb can also be -1 if cellNb was reset to 0 in + _fluid_seq_queue_send_queued_events() */ + if(time <= (unsigned int)(seq->queue0StartTime + seq->prevCellNb)) + { + /* we are late, send now */ + fluid_sequencer_send_now(seq, evt); - _fluid_seq_heap_set_free(seq->heap, evtentry); - return; - } - } + _fluid_seq_heap_set_free(seq->heap, evtentry); + return; + } + } - delay = time - seq->queue0StartTime; + delay = time - seq->queue0StartTime; - if (delay > 65535) { - _fluid_seq_queue_insert_queue_later(seq, evtentry); + if(delay > 65535) + { + _fluid_seq_queue_insert_queue_later(seq, evtentry); - } else if (delay > 255) { - _fluid_seq_queue_insert_queue1(seq, evtentry, delay/256 - 1); + } + else if(delay > 255) + { + _fluid_seq_queue_insert_queue1(seq, evtentry, delay / 256 - 1); - } else { - _fluid_seq_queue_insert_queue0(seq, evtentry, delay); - } + } + else + { + _fluid_seq_queue_insert_queue0(seq, evtentry, delay); + } } static int -_fluid_seq_queue_matchevent(fluid_event_t* evt, int templType, fluid_seq_id_t templSrc, fluid_seq_id_t templDest) +_fluid_seq_queue_matchevent(fluid_event_t *evt, int templType, fluid_seq_id_t templSrc, fluid_seq_id_t templDest) { - int eventType; + int eventType; - if (templSrc != -1 && templSrc != fluid_event_get_source(evt)) - return 0; + if(templSrc != -1 && templSrc != fluid_event_get_source(evt)) + { + return 0; + } - if (templDest != -1 && templDest != fluid_event_get_dest(evt)) - return 0; + if(templDest != -1 && templDest != fluid_event_get_dest(evt)) + { + return 0; + } - if (templType == -1) - return 1; + if(templType == -1) + { + return 1; + } - eventType = fluid_event_get_type(evt); + eventType = fluid_event_get_type(evt); - if (templType == eventType) - return 1; + if(templType == eventType) + { + return 1; + } - if (templType == FLUID_SEQ_ANYCONTROLCHANGE) - if (eventType == FLUID_SEQ_PITCHBEND || - eventType == FLUID_SEQ_MODULATION || - eventType == FLUID_SEQ_SUSTAIN || - eventType == FLUID_SEQ_PAN || - eventType == FLUID_SEQ_VOLUME || - eventType == FLUID_SEQ_REVERBSEND || - eventType == FLUID_SEQ_CONTROLCHANGE || - eventType == FLUID_SEQ_CHORUSSEND) - return 1; + if(templType == FLUID_SEQ_ANYCONTROLCHANGE) + { + if(eventType == FLUID_SEQ_PITCHBEND || + eventType == FLUID_SEQ_MODULATION || + eventType == FLUID_SEQ_SUSTAIN || + eventType == FLUID_SEQ_PAN || + eventType == FLUID_SEQ_VOLUME || + eventType == FLUID_SEQ_REVERBSEND || + eventType == FLUID_SEQ_CONTROLCHANGE || + eventType == FLUID_SEQ_CHORUSSEND) + { + return 1; + } + } - return 0; + return 0; } static void -_fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry* templ) +_fluid_seq_queue_remove_entries_matching(fluid_sequencer_t *seq, fluid_evt_entry *templ) { - /* we walk everything : this is slow, but that is life */ - int i, type; - fluid_seq_id_t src, dest; + /* we walk everything : this is slow, but that is life */ + int i, type; + fluid_seq_id_t src, dest; - src = templ->evt.src; - dest = templ->evt.dest; - type = templ->evt.type; + src = templ->evt.src; + dest = templ->evt.dest; + type = templ->evt.type; - /* we can set it free now */ - _fluid_seq_heap_set_free(seq->heap, templ); + /* we can set it free now */ + _fluid_seq_heap_set_free(seq->heap, templ); - /* queue0 */ - for (i = 0 ; i < 256 ; i++) { - fluid_evt_entry* tmp = seq->queue0[i][0]; - fluid_evt_entry* prev = NULL; - while (tmp) { - /* remove and/or walk */ - if (_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) { - /* remove */ - if (prev) { - prev->next = tmp->next; - if (tmp == seq->queue0[i][1]) // last one in list - seq->queue0[i][1] = prev; + /* queue0 */ + for(i = 0 ; i < 256 ; i++) + { + fluid_evt_entry *tmp = seq->queue0[i][0]; + fluid_evt_entry *prev = NULL; - _fluid_seq_heap_set_free(seq->heap, tmp); - tmp = prev->next; - } else { - /* first one in list */ - seq->queue0[i][0] = tmp->next; - if (tmp == seq->queue0[i][1]) // last one in list - seq->queue0[i][1] = NULL; + while(tmp) + { + /* remove and/or walk */ + if(_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) + { + /* remove */ + if(prev) + { + prev->next = tmp->next; - _fluid_seq_heap_set_free(seq->heap, tmp); - tmp = seq->queue0[i][0]; - } - } else { - prev = tmp; - tmp = prev->next; - } - } - } + if(tmp == seq->queue0[i][1]) // last one in list + { + seq->queue0[i][1] = prev; + } - /* queue1 */ - for (i = 0 ; i < 255 ; i++) { - fluid_evt_entry* tmp = seq->queue1[i][0]; - fluid_evt_entry* prev = NULL; - while (tmp) { - if (_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) { - /* remove */ - if (prev) { - prev->next = tmp->next; - if (tmp == seq->queue1[i][1]) // last one in list - seq->queue1[i][1] = prev; + _fluid_seq_heap_set_free(seq->heap, tmp); + tmp = prev->next; + } + else + { + /* first one in list */ + seq->queue0[i][0] = tmp->next; - _fluid_seq_heap_set_free(seq->heap, tmp); - tmp = prev->next; - } else { - /* first one in list */ - seq->queue1[i][0] = tmp->next; - if (tmp == seq->queue1[i][1]) // last one in list - seq->queue1[i][1] = NULL; + if(tmp == seq->queue0[i][1]) // last one in list + { + seq->queue0[i][1] = NULL; + } - _fluid_seq_heap_set_free(seq->heap, tmp); - tmp = seq->queue1[i][0]; - } - } else { - prev = tmp; - tmp = prev->next; - } - } - } + _fluid_seq_heap_set_free(seq->heap, tmp); + tmp = seq->queue0[i][0]; + } + } + else + { + prev = tmp; + tmp = prev->next; + } + } + } - /* queueLater */ - { - fluid_evt_entry* tmp = seq->queueLater; - fluid_evt_entry* prev = NULL; - while (tmp) { - if (_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) { - /* remove */ - if (prev) { - prev->next = tmp->next; + /* queue1 */ + for(i = 0 ; i < 255 ; i++) + { + fluid_evt_entry *tmp = seq->queue1[i][0]; + fluid_evt_entry *prev = NULL; - _fluid_seq_heap_set_free(seq->heap, tmp); - tmp = prev->next; - } else { - seq->queueLater = tmp->next; + while(tmp) + { + if(_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) + { + /* remove */ + if(prev) + { + prev->next = tmp->next; - _fluid_seq_heap_set_free(seq->heap, tmp); - tmp = seq->queueLater; - } - } else { - prev = tmp; - tmp = prev->next; - } - } - } + if(tmp == seq->queue1[i][1]) // last one in list + { + seq->queue1[i][1] = prev; + } + + _fluid_seq_heap_set_free(seq->heap, tmp); + tmp = prev->next; + } + else + { + /* first one in list */ + seq->queue1[i][0] = tmp->next; + + if(tmp == seq->queue1[i][1]) // last one in list + { + seq->queue1[i][1] = NULL; + } + + _fluid_seq_heap_set_free(seq->heap, tmp); + tmp = seq->queue1[i][0]; + } + } + else + { + prev = tmp; + tmp = prev->next; + } + } + } + + /* queueLater */ + { + fluid_evt_entry *tmp = seq->queueLater; + fluid_evt_entry *prev = NULL; + + while(tmp) + { + if(_fluid_seq_queue_matchevent((&tmp->evt), type, src, dest)) + { + /* remove */ + if(prev) + { + prev->next = tmp->next; + + _fluid_seq_heap_set_free(seq->heap, tmp); + tmp = prev->next; + } + else + { + seq->queueLater = tmp->next; + + _fluid_seq_heap_set_free(seq->heap, tmp); + tmp = seq->queueLater; + } + } + else + { + prev = tmp; + tmp = prev->next; + } + } + } } static void -_fluid_seq_queue_send_cell_events(fluid_sequencer_t* seq, int cellNb) +_fluid_seq_queue_send_cell_events(fluid_sequencer_t *seq, int cellNb) { - fluid_evt_entry* next; - fluid_evt_entry* tmp; + fluid_evt_entry *next; + fluid_evt_entry *tmp; - tmp = seq->queue0[cellNb][0]; - while (tmp) { - fluid_sequencer_send_now(seq, &(tmp->evt)); + tmp = seq->queue0[cellNb][0]; - next = tmp->next; + while(tmp) + { + fluid_sequencer_send_now(seq, &(tmp->evt)); - _fluid_seq_heap_set_free(seq->heap, tmp); - tmp = next; - } - seq->queue0[cellNb][0] = NULL; - seq->queue0[cellNb][1] = NULL; + next = tmp->next; + + _fluid_seq_heap_set_free(seq->heap, tmp); + tmp = next; + } + + seq->queue0[cellNb][0] = NULL; + seq->queue0[cellNb][1] = NULL; } static void -_fluid_seq_queue_slide(fluid_sequencer_t* seq) +_fluid_seq_queue_slide(fluid_sequencer_t *seq) { - short i; - fluid_evt_entry* next; - fluid_evt_entry* tmp; - int count = 0; + short i; + fluid_evt_entry *next; + fluid_evt_entry *tmp; + int count = 0; - /* do the slide */ - seq->queue0StartTime += 256; + /* do the slide */ + seq->queue0StartTime += 256; - /* sort all queue1[0] into queue0 according to new queue0StartTime */ - tmp = seq->queue1[0][0]; - while (tmp) { - unsigned int delay = tmp->evt.time - seq->queue0StartTime; - next = tmp->next; - if (delay > 255) { - /* should not happen !! */ - /* append it to queue1[1] */ - _fluid_seq_queue_insert_queue1(seq, tmp, 1); - } else { - _fluid_seq_queue_insert_queue0(seq, tmp, delay); - } - tmp = next; - count++; - } + /* sort all queue1[0] into queue0 according to new queue0StartTime */ + tmp = seq->queue1[0][0]; - /* slide all queue1[i] into queue1[i-1] */ - for (i = 1 ; i < 255 ; i++) { - seq->queue1[i-1][0] = seq->queue1[i][0]; - seq->queue1[i-1][1] = seq->queue1[i][1]; - } - seq->queue1[254][0] = NULL; - seq->queue1[254][1] = NULL; + while(tmp) + { + unsigned int delay = tmp->evt.time - seq->queue0StartTime; + next = tmp->next; + + if(delay > 255) + { + /* should not happen !! */ + /* append it to queue1[1] */ + _fluid_seq_queue_insert_queue1(seq, tmp, 1); + } + else + { + _fluid_seq_queue_insert_queue0(seq, tmp, delay); + } + + tmp = next; + count++; + } + + /* slide all queue1[i] into queue1[i-1] */ + for(i = 1 ; i < 255 ; i++) + { + seq->queue1[i - 1][0] = seq->queue1[i][0]; + seq->queue1[i - 1][1] = seq->queue1[i][1]; + } + + seq->queue1[254][0] = NULL; + seq->queue1[254][1] = NULL; - /* append queueLater to queue1[254] */ - count = 0; - tmp = seq->queueLater; - while (tmp) { - unsigned int delay = tmp->evt.time - seq->queue0StartTime; + /* append queueLater to queue1[254] */ + count = 0; + tmp = seq->queueLater; - if (delay > 65535) { - break; - } + while(tmp) + { + unsigned int delay = tmp->evt.time - seq->queue0StartTime; - next = tmp->next; + if(delay > 65535) + { + break; + } - /* append it */ - _fluid_seq_queue_insert_queue1(seq, tmp, 254); - tmp = next; - count++; - } + next = tmp->next; - seq->queueLater = tmp; + /* append it */ + _fluid_seq_queue_insert_queue1(seq, tmp, 254); + tmp = next; + count++; + } + + seq->queueLater = tmp; } static void -_fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq) +_fluid_seq_queue_send_queued_events(fluid_sequencer_t *seq) { - unsigned int nowTicks = fluid_sequencer_get_tick(seq); - short cellNb; + unsigned int nowTicks = fluid_sequencer_get_tick(seq); + short cellNb; - cellNb = seq->prevCellNb + 1; - while (cellNb <= (int)(nowTicks - seq->queue0StartTime)) { - if (cellNb == 256) { - cellNb = 0; - _fluid_seq_queue_slide(seq); - } /* slide */ + cellNb = seq->prevCellNb + 1; - /* process queue0[cellNb] */ - _fluid_seq_queue_send_cell_events(seq, cellNb); - - /* the current scale may have changed through a callback event */ - nowTicks = fluid_sequencer_get_tick(seq); + while(cellNb <= (int)(nowTicks - seq->queue0StartTime)) + { + if(cellNb == 256) + { + cellNb = 0; + _fluid_seq_queue_slide(seq); + } /* slide */ - /* next cell */ - cellNb++; - } + /* process queue0[cellNb] */ + _fluid_seq_queue_send_cell_events(seq, cellNb); - seq->prevCellNb = cellNb - 1; + /* the current scale may have changed through a callback event */ + nowTicks = fluid_sequencer_get_tick(seq); + + /* next cell */ + cellNb++; + } + + seq->prevCellNb = cellNb - 1; } diff --git a/src/midi/fluid_seqbind.c b/src/midi/fluid_seqbind.c index 20dac5d2..6d4543e0 100644 --- a/src/midi/fluid_seqbind.c +++ b/src/midi/fluid_seqbind.c @@ -32,48 +32,51 @@ #include "fluid_midi.h" #include "fluid_event_priv.h" - /*************************************************************** - * - * SEQUENCER BINDING - */ +/*************************************************************** +* +* SEQUENCER BINDING +*/ -struct _fluid_seqbind_t { - fluid_synth_t* synth; - fluid_sequencer_t* seq; - fluid_sample_timer_t* sample_timer; - fluid_seq_id_t client_id; +struct _fluid_seqbind_t +{ + fluid_synth_t *synth; + fluid_sequencer_t *seq; + fluid_sample_timer_t *sample_timer; + fluid_seq_id_t client_id; }; typedef struct _fluid_seqbind_t fluid_seqbind_t; -int fluid_seqbind_timer_callback(void* data, unsigned int msec); -void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* event, fluid_sequencer_t* seq, void* data); +int fluid_seqbind_timer_callback(void *data, unsigned int msec); +void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t *event, fluid_sequencer_t *seq, void *data); /* Proper cleanup of the seqbind struct. */ -void -delete_fluid_seqbind(fluid_seqbind_t* seqbind) +void +delete_fluid_seqbind(fluid_seqbind_t *seqbind) { - fluid_return_if_fail(seqbind != NULL); + fluid_return_if_fail(seqbind != NULL); - if ((seqbind->client_id != -1) && (seqbind->seq != NULL)) { - fluid_sequencer_unregister_client(seqbind->seq, seqbind->client_id); - seqbind->client_id = -1; - } + if((seqbind->client_id != -1) && (seqbind->seq != NULL)) + { + fluid_sequencer_unregister_client(seqbind->seq, seqbind->client_id); + seqbind->client_id = -1; + } - if ((seqbind->sample_timer != NULL) && (seqbind->synth != NULL)) { - delete_fluid_sample_timer(seqbind->synth, seqbind->sample_timer); - seqbind->sample_timer = NULL; - } + if((seqbind->sample_timer != NULL) && (seqbind->synth != NULL)) + { + delete_fluid_sample_timer(seqbind->synth, seqbind->sample_timer); + seqbind->sample_timer = NULL; + } - FLUID_FREE(seqbind); + FLUID_FREE(seqbind); } -/** +/** * Registers a synthesizer as a destination client of the given sequencer. * The \a synth is registered with the name "fluidsynth". - * + * * @warning Due to internal memory allocation, the user must explicitly unregister - * the client by sending a fluid_event_unregistering(). Otherwise the behaviour is + * the client by sending a fluid_event_unregistering(). Otherwise the behaviour is * undefined after either \p seq or \p synth is destroyed. @code{.cpp} fluid_seq_id_t seqid = fluid_sequencer_register_fluidsynth(seq, synth); @@ -91,196 +94,209 @@ delete_fluid_event(evt); delete_fluid_synth(synth); delete_fluid_sequencer(seq); @endcode - * + * * @param seq Sequencer instance * @param synth Synthesizer instance * @returns Sequencer client ID, or #FLUID_FAILED on error. */ -fluid_seq_id_t -fluid_sequencer_register_fluidsynth (fluid_sequencer_t* seq, fluid_synth_t* synth) +fluid_seq_id_t +fluid_sequencer_register_fluidsynth(fluid_sequencer_t *seq, fluid_synth_t *synth) { - fluid_seqbind_t* seqbind; - - seqbind = FLUID_NEW(fluid_seqbind_t); - if (seqbind == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return FLUID_FAILED; - } + fluid_seqbind_t *seqbind; - seqbind->synth = synth; - seqbind->seq = seq; - seqbind->sample_timer = NULL; - seqbind->client_id = -1; + seqbind = FLUID_NEW(fluid_seqbind_t); - /* set up the sample timer */ - if (!fluid_sequencer_get_use_system_timer(seq)) { - seqbind->sample_timer = - new_fluid_sample_timer(synth, fluid_seqbind_timer_callback, (void *) seqbind); - if (seqbind->sample_timer == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - delete_fluid_seqbind(seqbind); - return FLUID_FAILED; - } - } + if(seqbind == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return FLUID_FAILED; + } - /* register fluidsynth itself */ - seqbind->client_id = - fluid_sequencer_register_client(seq, "fluidsynth", fluid_seq_fluidsynth_callback, (void *)seqbind); - if (seqbind->client_id == -1) { - delete_fluid_seqbind(seqbind); - return FLUID_FAILED; - } + seqbind->synth = synth; + seqbind->seq = seq; + seqbind->sample_timer = NULL; + seqbind->client_id = -1; - return seqbind->client_id; + /* set up the sample timer */ + if(!fluid_sequencer_get_use_system_timer(seq)) + { + seqbind->sample_timer = + new_fluid_sample_timer(synth, fluid_seqbind_timer_callback, (void *) seqbind); + + if(seqbind->sample_timer == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + delete_fluid_seqbind(seqbind); + return FLUID_FAILED; + } + } + + /* register fluidsynth itself */ + seqbind->client_id = + fluid_sequencer_register_client(seq, "fluidsynth", fluid_seq_fluidsynth_callback, (void *)seqbind); + + if(seqbind->client_id == -1) + { + delete_fluid_seqbind(seqbind); + return FLUID_FAILED; + } + + return seqbind->client_id; } /* Callback for sample timer */ int -fluid_seqbind_timer_callback(void* data, unsigned int msec) +fluid_seqbind_timer_callback(void *data, unsigned int msec) { - fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data; - fluid_sequencer_process(seqbind->seq, msec); - return 1; + fluid_seqbind_t *seqbind = (fluid_seqbind_t *) data; + fluid_sequencer_process(seqbind->seq, msec); + return 1; } /* Callback for midi events */ -void -fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data) +void +fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t *evt, fluid_sequencer_t *seq, void *data) { - fluid_synth_t* synth; - fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data; - synth = seqbind->synth; + fluid_synth_t *synth; + fluid_seqbind_t *seqbind = (fluid_seqbind_t *) data; + synth = seqbind->synth; - switch (fluid_event_get_type(evt)) { + switch(fluid_event_get_type(evt)) + { - case FLUID_SEQ_NOTEON: - fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt)); - break; + case FLUID_SEQ_NOTEON: + fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt)); + break; - case FLUID_SEQ_NOTEOFF: - fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt)); - break; + case FLUID_SEQ_NOTEOFF: + fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt)); + break; - case FLUID_SEQ_NOTE: - { - unsigned int dur; - fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt)); - dur = fluid_event_get_duration(evt); - fluid_event_noteoff(evt, fluid_event_get_channel(evt), fluid_event_get_key(evt)); - fluid_sequencer_send_at(seq, evt, dur, 0); - } - break; + case FLUID_SEQ_NOTE: + { + unsigned int dur; + fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt)); + dur = fluid_event_get_duration(evt); + fluid_event_noteoff(evt, fluid_event_get_channel(evt), fluid_event_get_key(evt)); + fluid_sequencer_send_at(seq, evt, dur, 0); + } + break; - case FLUID_SEQ_ALLSOUNDSOFF: + case FLUID_SEQ_ALLSOUNDSOFF: fluid_synth_all_sounds_off(synth, fluid_event_get_channel(evt)); - break; + break; - case FLUID_SEQ_ALLNOTESOFF: - fluid_synth_all_notes_off(synth, fluid_event_get_channel(evt)); - break; + case FLUID_SEQ_ALLNOTESOFF: + fluid_synth_all_notes_off(synth, fluid_event_get_channel(evt)); + break; - case FLUID_SEQ_BANKSELECT: - fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt)); - break; + case FLUID_SEQ_BANKSELECT: + fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt)); + break; - case FLUID_SEQ_PROGRAMCHANGE: - fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt)); - break; + case FLUID_SEQ_PROGRAMCHANGE: + fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt)); + break; - case FLUID_SEQ_PROGRAMSELECT: - fluid_synth_program_select(synth, - fluid_event_get_channel(evt), - fluid_event_get_sfont_id(evt), - fluid_event_get_bank(evt), - fluid_event_get_program(evt)); - break; + case FLUID_SEQ_PROGRAMSELECT: + fluid_synth_program_select(synth, + fluid_event_get_channel(evt), + fluid_event_get_sfont_id(evt), + fluid_event_get_bank(evt), + fluid_event_get_program(evt)); + break; - case FLUID_SEQ_ANYCONTROLCHANGE: - /* nothing = only used by remove_events */ - break; + case FLUID_SEQ_ANYCONTROLCHANGE: + /* nothing = only used by remove_events */ + break; - case FLUID_SEQ_PITCHBEND: - fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt)); - break; + case FLUID_SEQ_PITCHBEND: + fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt)); + break; - case FLUID_SEQ_PITCHWHEELSENS: - fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); - break; + case FLUID_SEQ_PITCHWHEELSENS: + fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); + break; - case FLUID_SEQ_CONTROLCHANGE: - fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt)); - break; + case FLUID_SEQ_CONTROLCHANGE: + fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt)); + break; - case FLUID_SEQ_MODULATION: - fluid_synth_cc(synth, fluid_event_get_channel(evt), MODULATION_MSB, fluid_event_get_value(evt)); - break; + case FLUID_SEQ_MODULATION: + fluid_synth_cc(synth, fluid_event_get_channel(evt), MODULATION_MSB, fluid_event_get_value(evt)); + break; - case FLUID_SEQ_SUSTAIN: - fluid_synth_cc(synth, fluid_event_get_channel(evt), SUSTAIN_SWITCH, fluid_event_get_value(evt)); - break; + case FLUID_SEQ_SUSTAIN: + fluid_synth_cc(synth, fluid_event_get_channel(evt), SUSTAIN_SWITCH, fluid_event_get_value(evt)); + break; - case FLUID_SEQ_PAN: - fluid_synth_cc(synth, fluid_event_get_channel(evt), PAN_MSB, fluid_event_get_value(evt)); - break; + case FLUID_SEQ_PAN: + fluid_synth_cc(synth, fluid_event_get_channel(evt), PAN_MSB, fluid_event_get_value(evt)); + break; - case FLUID_SEQ_VOLUME: - fluid_synth_cc(synth, fluid_event_get_channel(evt), VOLUME_MSB, fluid_event_get_value(evt)); - break; + case FLUID_SEQ_VOLUME: + fluid_synth_cc(synth, fluid_event_get_channel(evt), VOLUME_MSB, fluid_event_get_value(evt)); + break; - case FLUID_SEQ_REVERBSEND: - fluid_synth_cc(synth, fluid_event_get_channel(evt), EFFECTS_DEPTH1, fluid_event_get_value(evt)); - break; + case FLUID_SEQ_REVERBSEND: + fluid_synth_cc(synth, fluid_event_get_channel(evt), EFFECTS_DEPTH1, fluid_event_get_value(evt)); + break; - case FLUID_SEQ_CHORUSSEND: - fluid_synth_cc(synth, fluid_event_get_channel(evt), EFFECTS_DEPTH3, fluid_event_get_value(evt)); - break; + case FLUID_SEQ_CHORUSSEND: + fluid_synth_cc(synth, fluid_event_get_channel(evt), EFFECTS_DEPTH3, fluid_event_get_value(evt)); + break; - case FLUID_SEQ_CHANNELPRESSURE: - fluid_synth_channel_pressure(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); - break; + case FLUID_SEQ_CHANNELPRESSURE: + fluid_synth_channel_pressure(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); + break; - case FLUID_SEQ_KEYPRESSURE: - fluid_synth_key_pressure(synth, - fluid_event_get_channel(evt), - fluid_event_get_key(evt), - fluid_event_get_value(evt)); - break; + case FLUID_SEQ_KEYPRESSURE: + fluid_synth_key_pressure(synth, + fluid_event_get_channel(evt), + fluid_event_get_key(evt), + fluid_event_get_value(evt)); + break; - case FLUID_SEQ_SYSTEMRESET: - fluid_synth_system_reset(synth); - break; + case FLUID_SEQ_SYSTEMRESET: + fluid_synth_system_reset(synth); + break; - case FLUID_SEQ_UNREGISTERING: /* free ourselves */ - delete_fluid_seqbind(seqbind); - break; + case FLUID_SEQ_UNREGISTERING: /* free ourselves */ + delete_fluid_seqbind(seqbind); + break; - case FLUID_SEQ_TIMER: - /* nothing in fluidsynth */ - break; + case FLUID_SEQ_TIMER: + /* nothing in fluidsynth */ + break; - default: - break; - } + default: + break; + } } -static fluid_seq_id_t get_fluidsynth_dest(fluid_sequencer_t* seq) +static fluid_seq_id_t get_fluidsynth_dest(fluid_sequencer_t *seq) { - int i; - fluid_seq_id_t id; - char* name; - int j = fluid_sequencer_count_clients(seq); - for (i = 0; i < j; i++) { - id = fluid_sequencer_get_client_id(seq, i); - name = fluid_sequencer_get_client_name(seq, id); - if (name && (FLUID_STRCMP(name, "fluidsynth") == 0)) { - return id; - } - } - return -1; + int i; + fluid_seq_id_t id; + char *name; + int j = fluid_sequencer_count_clients(seq); + + for(i = 0; i < j; i++) + { + id = fluid_sequencer_get_client_id(seq, i); + name = fluid_sequencer_get_client_name(seq, id); + + if(name && (FLUID_STRCMP(name, "fluidsynth") == 0)) + { + return id; + } + } + + return -1; } /** - * Transforms an incoming midi event (from a midi driver or midi router) to a + * Transforms an incoming midi event (from a midi driver or midi router) to a * sequencer event and adds it to the sequencer queue for sending as soon as possible. * @param data The sequencer, must be a valid #fluid_sequencer_t * @param event MIDI event @@ -288,51 +304,60 @@ static fluid_seq_id_t get_fluidsynth_dest(fluid_sequencer_t* seq) * @since 1.1.0 */ int -fluid_sequencer_add_midi_event_to_buffer(void* data, fluid_midi_event_t* event) +fluid_sequencer_add_midi_event_to_buffer(void *data, fluid_midi_event_t *event) { - fluid_event_t evt; - fluid_sequencer_t* seq = (fluid_sequencer_t*) data; - int chan = fluid_midi_event_get_channel(event); + fluid_event_t evt; + fluid_sequencer_t *seq = (fluid_sequencer_t *) data; + int chan = fluid_midi_event_get_channel(event); - fluid_event_clear(&evt); - fluid_event_set_time(&evt, fluid_sequencer_get_tick(seq)); - fluid_event_set_dest(&evt, get_fluidsynth_dest(seq)); + fluid_event_clear(&evt); + fluid_event_set_time(&evt, fluid_sequencer_get_tick(seq)); + fluid_event_set_dest(&evt, get_fluidsynth_dest(seq)); - switch (fluid_midi_event_get_type(event)) { - case NOTE_OFF: - fluid_event_noteoff(&evt, chan, (short)fluid_midi_event_get_key(event)); - break; - case NOTE_ON: - fluid_event_noteon(&evt, fluid_midi_event_get_channel(event), - (short)fluid_midi_event_get_key(event), (short)fluid_midi_event_get_velocity(event)); - break; - case CONTROL_CHANGE: - fluid_event_control_change(&evt, chan, (short)fluid_midi_event_get_control(event), - (short)fluid_midi_event_get_value(event)); - break; - case PROGRAM_CHANGE: - fluid_event_program_change(&evt, chan, (short)fluid_midi_event_get_program(event)); - break; - case PITCH_BEND: - fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event)); - break; - case CHANNEL_PRESSURE: - fluid_event_channel_pressure(&evt, chan, (short)fluid_midi_event_get_program(event)); - break; - case KEY_PRESSURE: - fluid_event_key_pressure(&evt, chan, - (short)fluid_midi_event_get_key(event), - (short)fluid_midi_event_get_value(event)); - break; - case MIDI_SYSTEM_RESET: - fluid_event_system_reset(&evt); - break; - default: /* Not yet implemented */ - return FLUID_FAILED; - } + switch(fluid_midi_event_get_type(event)) + { + case NOTE_OFF: + fluid_event_noteoff(&evt, chan, (short)fluid_midi_event_get_key(event)); + break; - /* Schedule for sending at next call to fluid_sequencer_process */ - return fluid_sequencer_send_at(seq, &evt, 0, 0); + case NOTE_ON: + fluid_event_noteon(&evt, fluid_midi_event_get_channel(event), + (short)fluid_midi_event_get_key(event), (short)fluid_midi_event_get_velocity(event)); + break; + + case CONTROL_CHANGE: + fluid_event_control_change(&evt, chan, (short)fluid_midi_event_get_control(event), + (short)fluid_midi_event_get_value(event)); + break; + + case PROGRAM_CHANGE: + fluid_event_program_change(&evt, chan, (short)fluid_midi_event_get_program(event)); + break; + + case PITCH_BEND: + fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event)); + break; + + case CHANNEL_PRESSURE: + fluid_event_channel_pressure(&evt, chan, (short)fluid_midi_event_get_program(event)); + break; + + case KEY_PRESSURE: + fluid_event_key_pressure(&evt, chan, + (short)fluid_midi_event_get_key(event), + (short)fluid_midi_event_get_value(event)); + break; + + case MIDI_SYSTEM_RESET: + fluid_event_system_reset(&evt); + break; + + default: /* Not yet implemented */ + return FLUID_FAILED; + } + + /* Schedule for sending at next call to fluid_sequencer_process */ + return fluid_sequencer_send_at(seq, &evt, 0, 0); } diff --git a/src/rvoice/fluid_adsr_env.c b/src/rvoice/fluid_adsr_env.c index 0d3d7b60..00bdd40f 100644 --- a/src/rvoice/fluid_adsr_env.c +++ b/src/rvoice/fluid_adsr_env.c @@ -22,18 +22,18 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_adsr_env_set_data) { - fluid_adsr_env_t* env = obj; + fluid_adsr_env_t *env = obj; fluid_adsr_env_section_t section = param[0].i; unsigned int count = param[1].i; fluid_real_t coeff = param[2].real; fluid_real_t increment = param[3].real; fluid_real_t min = param[4].real; fluid_real_t max = param[5].real; - - env->data[section].count = count; - env->data[section].coeff = coeff; - env->data[section].increment = increment; - env->data[section].min = min; - env->data[section].max = max; + + env->data[section].count = count; + env->data[section].coeff = coeff; + env->data[section].increment = increment; + env->data[section].min = min; + env->data[section].max = max; } diff --git a/src/rvoice/fluid_adsr_env.h b/src/rvoice/fluid_adsr_env.h index abb267d4..9ed652d0 100644 --- a/src/rvoice/fluid_adsr_env.h +++ b/src/rvoice/fluid_adsr_env.h @@ -27,130 +27,141 @@ /* * envelope data */ -struct _fluid_env_data_t { - unsigned int count; - fluid_real_t coeff; - fluid_real_t increment; - fluid_real_t min; - fluid_real_t max; +struct _fluid_env_data_t +{ + unsigned int count; + fluid_real_t coeff; + fluid_real_t increment; + fluid_real_t min; + fluid_real_t max; }; /* Indices for envelope tables */ -enum fluid_voice_envelope_index_t{ - FLUID_VOICE_ENVDELAY, - FLUID_VOICE_ENVATTACK, - FLUID_VOICE_ENVHOLD, - FLUID_VOICE_ENVDECAY, - FLUID_VOICE_ENVSUSTAIN, - FLUID_VOICE_ENVRELEASE, - FLUID_VOICE_ENVFINISHED, - FLUID_VOICE_ENVLAST +enum fluid_voice_envelope_index_t +{ + FLUID_VOICE_ENVDELAY, + FLUID_VOICE_ENVATTACK, + FLUID_VOICE_ENVHOLD, + FLUID_VOICE_ENVDECAY, + FLUID_VOICE_ENVSUSTAIN, + FLUID_VOICE_ENVRELEASE, + FLUID_VOICE_ENVFINISHED, + FLUID_VOICE_ENVLAST }; typedef enum fluid_voice_envelope_index_t fluid_adsr_env_section_t; typedef struct _fluid_adsr_env_t fluid_adsr_env_t; -struct _fluid_adsr_env_t { - fluid_env_data_t data[FLUID_VOICE_ENVLAST]; - unsigned int count; - int section; - fluid_real_t val; /* the current value of the envelope */ +struct _fluid_adsr_env_t +{ + fluid_env_data_t data[FLUID_VOICE_ENVLAST]; + unsigned int count; + int section; + fluid_real_t val; /* the current value of the envelope */ }; /* For performance, all functions are inlined */ -static FLUID_INLINE void -fluid_adsr_env_calc(fluid_adsr_env_t* env, int is_volenv) +static FLUID_INLINE void +fluid_adsr_env_calc(fluid_adsr_env_t *env, int is_volenv) { - fluid_env_data_t* env_data; - fluid_real_t x; + fluid_env_data_t *env_data; + fluid_real_t x; - env_data = &env->data[env->section]; + env_data = &env->data[env->section]; - /* skip to the next section of the envelope if necessary */ - while (env->count >= env_data->count) - { - // If we're switching envelope stages from decay to sustain, force the value to be the end value of the previous stage - // Hmm, should this only apply to volenv? It was so before refactoring, so keep it for now. [DH] - if (env->section == FLUID_VOICE_ENVDECAY && is_volenv) - env->val = env_data->min * env_data->coeff; + /* skip to the next section of the envelope if necessary */ + while(env->count >= env_data->count) + { + // If we're switching envelope stages from decay to sustain, force the value to be the end value of the previous stage + // Hmm, should this only apply to volenv? It was so before refactoring, so keep it for now. [DH] + if(env->section == FLUID_VOICE_ENVDECAY && is_volenv) + { + env->val = env_data->min * env_data->coeff; + } - env_data = &env->data[++env->section]; - env->count = 0; - } + env_data = &env->data[++env->section]; + env->count = 0; + } - /* calculate the envelope value and check for valid range */ - x = env_data->coeff * env->val + env_data->increment; + /* calculate the envelope value and check for valid range */ + x = env_data->coeff * env->val + env_data->increment; - if (x < env_data->min) - { - x = env_data->min; - env->section++; - env->count = 0; - } - else if (x > env_data->max) - { - x = env_data->max; - env->section++; - env->count = 0; - } - else env->count++; + if(x < env_data->min) + { + x = env_data->min; + env->section++; + env->count = 0; + } + else if(x > env_data->max) + { + x = env_data->max; + env->section++; + env->count = 0; + } + else + { + env->count++; + } + + env->val = x; - env->val = x; - } -/* This one cannot be inlined since it is referenced in +/* This one cannot be inlined since it is referenced in the event queue */ DECLARE_FLUID_RVOICE_FUNCTION(fluid_adsr_env_set_data); -static FLUID_INLINE void -fluid_adsr_env_reset(fluid_adsr_env_t* env) +static FLUID_INLINE void +fluid_adsr_env_reset(fluid_adsr_env_t *env) { - env->count = 0; - env->section = 0; - env->val = 0.0f; + env->count = 0; + env->section = 0; + env->val = 0.0f; } -static FLUID_INLINE fluid_real_t -fluid_adsr_env_get_val(fluid_adsr_env_t* env) +static FLUID_INLINE fluid_real_t +fluid_adsr_env_get_val(fluid_adsr_env_t *env) { - return env->val; + return env->val; } static FLUID_INLINE void -fluid_adsr_env_set_val(fluid_adsr_env_t* env, fluid_real_t val) +fluid_adsr_env_set_val(fluid_adsr_env_t *env, fluid_real_t val) { - env->val = val; + env->val = val; } static FLUID_INLINE fluid_adsr_env_section_t -fluid_adsr_env_get_section(fluid_adsr_env_t* env) +fluid_adsr_env_get_section(fluid_adsr_env_t *env) { - return env->section; + return env->section; } -static FLUID_INLINE void -fluid_adsr_env_set_section(fluid_adsr_env_t* env, +static FLUID_INLINE void +fluid_adsr_env_set_section(fluid_adsr_env_t *env, fluid_adsr_env_section_t section) { - env->section = section; - env->count = 0; + env->section = section; + env->count = 0; } -/* Used for determining which voice to kill. +/* Used for determining which voice to kill. Returns max amplitude from now, and forward in time. */ static FLUID_INLINE fluid_real_t -fluid_adsr_env_get_max_val(fluid_adsr_env_t* env) +fluid_adsr_env_get_max_val(fluid_adsr_env_t *env) { - if (env->section > FLUID_VOICE_ENVATTACK){ - return env->val * 1000; - } else { - return env->data[FLUID_VOICE_ENVATTACK].max; - } + if(env->section > FLUID_VOICE_ENVATTACK) + { + return env->val * 1000; + } + else + { + return env->data[FLUID_VOICE_ENVATTACK].max; + } } #endif diff --git a/src/rvoice/fluid_chorus.c b/src/rvoice/fluid_chorus.c index 06799644..93c6c238 100644 --- a/src/rvoice/fluid_chorus.c +++ b/src/rvoice/fluid_chorus.c @@ -115,119 +115,136 @@ #define INTERPOLATION_SAMPLES 5 /* Private data for SKEL file */ -struct _fluid_chorus_t { - int type; - fluid_real_t depth_ms; - fluid_real_t level; - fluid_real_t speed_Hz; - int number_blocks; +struct _fluid_chorus_t +{ + int type; + fluid_real_t depth_ms; + fluid_real_t level; + fluid_real_t speed_Hz; + int number_blocks; - fluid_real_t *chorusbuf; - int counter; - long phase[MAX_CHORUS]; - long modulation_period_samples; - int *lookup_tab; - fluid_real_t sample_rate; + fluid_real_t *chorusbuf; + int counter; + long phase[MAX_CHORUS]; + long modulation_period_samples; + int *lookup_tab; + fluid_real_t sample_rate; - /* sinc lookup table */ - fluid_real_t sinc_table[INTERPOLATION_SAMPLES][INTERPOLATION_SUBSAMPLES]; + /* sinc lookup table */ + fluid_real_t sinc_table[INTERPOLATION_SAMPLES][INTERPOLATION_SUBSAMPLES]; }; static void fluid_chorus_triangle(int *buf, int len, int depth); static void fluid_chorus_sine(int *buf, int len, int depth); -fluid_chorus_t* +fluid_chorus_t * new_fluid_chorus(fluid_real_t sample_rate) { - int i; int ii; - fluid_chorus_t* chorus; + int i; + int ii; + fluid_chorus_t *chorus; - chorus = FLUID_NEW(fluid_chorus_t); - if (chorus == NULL) { - fluid_log(FLUID_PANIC, "chorus: Out of memory"); - return NULL; - } + chorus = FLUID_NEW(fluid_chorus_t); - FLUID_MEMSET(chorus, 0, sizeof(fluid_chorus_t)); + if(chorus == NULL) + { + fluid_log(FLUID_PANIC, "chorus: Out of memory"); + return NULL; + } - chorus->sample_rate = sample_rate; + FLUID_MEMSET(chorus, 0, sizeof(fluid_chorus_t)); - /* Lookup table for the SI function (impulse response of an ideal low pass) */ + chorus->sample_rate = sample_rate; - /* i: Offset in terms of whole samples */ - for (i = 0; i < INTERPOLATION_SAMPLES; i++){ + /* Lookup table for the SI function (impulse response of an ideal low pass) */ - /* ii: Offset in terms of fractional samples ('subsamples') */ - for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){ - /* Move the origin into the center of the table */ - double i_shifted = ((double) i- ((double) INTERPOLATION_SAMPLES) / 2. - + (double) ii / (double) INTERPOLATION_SUBSAMPLES); - if (fabs(i_shifted) < 0.000001) { - /* sinc(0) cannot be calculated straightforward (limit needed - for 0/0) */ - chorus->sinc_table[i][ii] = (fluid_real_t)1.; + /* i: Offset in terms of whole samples */ + for(i = 0; i < INTERPOLATION_SAMPLES; i++) + { - } else { - chorus->sinc_table[i][ii] = (fluid_real_t)sin(i_shifted * M_PI) / (M_PI * i_shifted); - /* Hamming window */ - chorus->sinc_table[i][ii] *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * M_PI * i_shifted / (fluid_real_t)INTERPOLATION_SAMPLES)); - }; + /* ii: Offset in terms of fractional samples ('subsamples') */ + for(ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++) + { + /* Move the origin into the center of the table */ + double i_shifted = ((double) i - ((double) INTERPOLATION_SAMPLES) / 2. + + (double) ii / (double) INTERPOLATION_SUBSAMPLES); + + if(fabs(i_shifted) < 0.000001) + { + /* sinc(0) cannot be calculated straightforward (limit needed + for 0/0) */ + chorus->sinc_table[i][ii] = (fluid_real_t)1.; + + } + else + { + chorus->sinc_table[i][ii] = (fluid_real_t)sin(i_shifted * M_PI) / (M_PI * i_shifted); + /* Hamming window */ + chorus->sinc_table[i][ii] *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * M_PI * i_shifted / (fluid_real_t)INTERPOLATION_SAMPLES)); + }; + }; }; - }; - /* allocate lookup tables */ - chorus->lookup_tab = FLUID_ARRAY(int, (int) (chorus->sample_rate / MIN_SPEED_HZ)); - if (chorus->lookup_tab == NULL) { - fluid_log(FLUID_PANIC, "chorus: Out of memory"); - goto error_recovery; - } + /* allocate lookup tables */ + chorus->lookup_tab = FLUID_ARRAY(int, (int)(chorus->sample_rate / MIN_SPEED_HZ)); - /* allocate sample buffer */ + if(chorus->lookup_tab == NULL) + { + fluid_log(FLUID_PANIC, "chorus: Out of memory"); + goto error_recovery; + } - chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES); - if (chorus->chorusbuf == NULL) { - fluid_log(FLUID_PANIC, "chorus: Out of memory"); - goto error_recovery; - } + /* allocate sample buffer */ - if (fluid_chorus_init(chorus) != FLUID_OK){ - goto error_recovery; - }; + chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES); - return chorus; + if(chorus->chorusbuf == NULL) + { + fluid_log(FLUID_PANIC, "chorus: Out of memory"); + goto error_recovery; + } - error_recovery: - delete_fluid_chorus(chorus); - return NULL; + if(fluid_chorus_init(chorus) != FLUID_OK) + { + goto error_recovery; + }; + + return chorus; + +error_recovery: + delete_fluid_chorus(chorus); + + return NULL; } void -delete_fluid_chorus(fluid_chorus_t* chorus) +delete_fluid_chorus(fluid_chorus_t *chorus) { - fluid_return_if_fail(chorus != NULL); - + fluid_return_if_fail(chorus != NULL); + FLUID_FREE(chorus->chorusbuf); FLUID_FREE(chorus->lookup_tab); FLUID_FREE(chorus); } int -fluid_chorus_init(fluid_chorus_t* chorus) +fluid_chorus_init(fluid_chorus_t *chorus) { - int i; + int i; - for (i = 0; i < MAX_SAMPLES; i++) { - chorus->chorusbuf[i] = 0.0; - } - - return FLUID_OK; + for(i = 0; i < MAX_SAMPLES; i++) + { + chorus->chorusbuf[i] = 0.0; + } + + return FLUID_OK; } void -fluid_chorus_reset(fluid_chorus_t* chorus) +fluid_chorus_reset(fluid_chorus_t *chorus) { - fluid_chorus_init(chorus); + fluid_chorus_init(chorus); } /** @@ -243,223 +260,270 @@ fluid_chorus_reset(fluid_chorus_t* chorus) * @param type Chorus waveform type (#fluid_chorus_mod) */ void -fluid_chorus_set(fluid_chorus_t* chorus, int set, int nr, fluid_real_t level, +fluid_chorus_set(fluid_chorus_t *chorus, int set, int nr, fluid_real_t level, fluid_real_t speed, fluid_real_t depth_ms, int type) { - int modulation_depth_samples; - int i; + int modulation_depth_samples; + int i; - if (set & FLUID_CHORUS_SET_NR) chorus->number_blocks = nr; - if (set & FLUID_CHORUS_SET_LEVEL) chorus->level = level; - if (set & FLUID_CHORUS_SET_SPEED) chorus->speed_Hz = speed; - if (set & FLUID_CHORUS_SET_DEPTH) chorus->depth_ms = depth_ms; - if (set & FLUID_CHORUS_SET_TYPE) chorus->type = type; + if(set & FLUID_CHORUS_SET_NR) + { + chorus->number_blocks = nr; + } - if (chorus->number_blocks < 0) { - fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0."); - chorus->number_blocks = 0; - } else if (chorus->number_blocks > MAX_CHORUS) { - fluid_log(FLUID_WARN, "chorus: number blocks larger than max. allowed! Setting value to %d.", - MAX_CHORUS); - chorus->number_blocks = MAX_CHORUS; - } + if(set & FLUID_CHORUS_SET_LEVEL) + { + chorus->level = level; + } - if (chorus->speed_Hz < MIN_SPEED_HZ) { - fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.", - (double) MIN_SPEED_HZ); - chorus->speed_Hz = MIN_SPEED_HZ; - } else if (chorus->speed_Hz > MAX_SPEED_HZ) { - fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.", - (double) MAX_SPEED_HZ); - chorus->speed_Hz = MAX_SPEED_HZ; - } + if(set & FLUID_CHORUS_SET_SPEED) + { + chorus->speed_Hz = speed; + } - if (chorus->depth_ms < 0.0) { - fluid_log(FLUID_WARN, "chorus: depth must be positive! Setting value to 0."); - chorus->depth_ms = 0.0; - } - /* Depth: Check for too high value through modulation_depth_samples. */ + if(set & FLUID_CHORUS_SET_DEPTH) + { + chorus->depth_ms = depth_ms; + } - if (chorus->level < 0.0) { - fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0."); - chorus->level = 0.0; - } else if (chorus->level > 10) { - fluid_log(FLUID_WARN, "chorus: level must be < 10. A reasonable level is << 1! " - "Setting it to 0.1."); - chorus->level = 0.1; - } + if(set & FLUID_CHORUS_SET_TYPE) + { + chorus->type = type; + } - /* The modulating LFO goes through a full period every x samples: */ - chorus->modulation_period_samples = chorus->sample_rate / chorus->speed_Hz; + if(chorus->number_blocks < 0) + { + fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0."); + chorus->number_blocks = 0; + } + else if(chorus->number_blocks > MAX_CHORUS) + { + fluid_log(FLUID_WARN, "chorus: number blocks larger than max. allowed! Setting value to %d.", + MAX_CHORUS); + chorus->number_blocks = MAX_CHORUS; + } - /* The variation in delay time is x: */ - modulation_depth_samples = (int) - (chorus->depth_ms / 1000.0 /* convert modulation depth in ms to s*/ - * chorus->sample_rate); + if(chorus->speed_Hz < MIN_SPEED_HZ) + { + fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.", + (double) MIN_SPEED_HZ); + chorus->speed_Hz = MIN_SPEED_HZ; + } + else if(chorus->speed_Hz > MAX_SPEED_HZ) + { + fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.", + (double) MAX_SPEED_HZ); + chorus->speed_Hz = MAX_SPEED_HZ; + } - if (modulation_depth_samples > MAX_SAMPLES) { - fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES); - modulation_depth_samples = MAX_SAMPLES; - } + if(chorus->depth_ms < 0.0) + { + fluid_log(FLUID_WARN, "chorus: depth must be positive! Setting value to 0."); + chorus->depth_ms = 0.0; + } - /* initialize LFO table */ - if (chorus->type == FLUID_CHORUS_MOD_SINE) { - fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples, - modulation_depth_samples); - } else if (chorus->type == FLUID_CHORUS_MOD_TRIANGLE) { - fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples, - modulation_depth_samples); - } else { - fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave."); - chorus->type = FLUID_CHORUS_MOD_SINE; - fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples, - modulation_depth_samples); - } + /* Depth: Check for too high value through modulation_depth_samples. */ - for (i = 0; i < chorus->number_blocks; i++) { - /* Set the phase of the chorus blocks equally spaced */ - chorus->phase[i] = (int) ((double) chorus->modulation_period_samples - * (double) i / (double) chorus->number_blocks); - } + if(chorus->level < 0.0) + { + fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0."); + chorus->level = 0.0; + } + else if(chorus->level > 10) + { + fluid_log(FLUID_WARN, "chorus: level must be < 10. A reasonable level is << 1! " + "Setting it to 0.1."); + chorus->level = 0.1; + } - /* Start of the circular buffer */ - chorus->counter = 0; + /* The modulating LFO goes through a full period every x samples: */ + chorus->modulation_period_samples = chorus->sample_rate / chorus->speed_Hz; + + /* The variation in delay time is x: */ + modulation_depth_samples = (int) + (chorus->depth_ms / 1000.0 /* convert modulation depth in ms to s*/ + * chorus->sample_rate); + + if(modulation_depth_samples > MAX_SAMPLES) + { + fluid_log(FLUID_WARN, "chorus: Too high depth. Setting it to max (%d).", MAX_SAMPLES); + modulation_depth_samples = MAX_SAMPLES; + } + + /* initialize LFO table */ + if(chorus->type == FLUID_CHORUS_MOD_SINE) + { + fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples, + modulation_depth_samples); + } + else if(chorus->type == FLUID_CHORUS_MOD_TRIANGLE) + { + fluid_chorus_triangle(chorus->lookup_tab, chorus->modulation_period_samples, + modulation_depth_samples); + } + else + { + fluid_log(FLUID_WARN, "chorus: Unknown modulation type. Using sinewave."); + chorus->type = FLUID_CHORUS_MOD_SINE; + fluid_chorus_sine(chorus->lookup_tab, chorus->modulation_period_samples, + modulation_depth_samples); + } + + for(i = 0; i < chorus->number_blocks; i++) + { + /* Set the phase of the chorus blocks equally spaced */ + chorus->phase[i] = (int)((double) chorus->modulation_period_samples + * (double) i / (double) chorus->number_blocks); + } + + /* Start of the circular buffer */ + chorus->counter = 0; } -void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out) +void fluid_chorus_processmix(fluid_chorus_t *chorus, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out) { - int sample_index; - int i; - fluid_real_t d_in, d_out; + int sample_index; + int i; + fluid_real_t d_in, d_out; - for (sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) { + for(sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) + { - d_in = in[sample_index]; - d_out = 0.0f; + d_in = in[sample_index]; + d_out = 0.0f; # if 0 - /* Debug: Listen to the chorus signal only */ - left_out[sample_index]=0; - right_out[sample_index]=0; + /* Debug: Listen to the chorus signal only */ + left_out[sample_index] = 0; + right_out[sample_index] = 0; #endif - /* Write the current sample into the circular buffer */ - chorus->chorusbuf[chorus->counter] = d_in; + /* Write the current sample into the circular buffer */ + chorus->chorusbuf[chorus->counter] = d_in; - for (i = 0; i < chorus->number_blocks; i++) { - int ii; - /* Calculate the delay in subsamples for the delay line of chorus block nr. */ + for(i = 0; i < chorus->number_blocks; i++) + { + int ii; + /* Calculate the delay in subsamples for the delay line of chorus block nr. */ - /* The value in the lookup table is so, that this expression - * will always be positive. It will always include a number of - * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to - * remain positive at all times. */ - int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter - - chorus->lookup_tab[chorus->phase[i]]); + /* The value in the lookup table is so, that this expression + * will always be positive. It will always include a number of + * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to + * remain positive at all times. */ + int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter + - chorus->lookup_tab[chorus->phase[i]]); - int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES; + int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES; - /* modulo divide by INTERPOLATION_SUBSAMPLES */ - pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK; + /* modulo divide by INTERPOLATION_SUBSAMPLES */ + pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK; - for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){ - /* Add the delayed signal to the chorus sum d_out Note: The - * delay in the delay line moves backwards for increasing - * delay!*/ + for(ii = 0; ii < INTERPOLATION_SAMPLES; ii++) + { + /* Add the delayed signal to the chorus sum d_out Note: The + * delay in the delay line moves backwards for increasing + * delay!*/ - /* The & in chorusbuf[...] is equivalent to a division modulo - MAX_SAMPLES, only faster. */ - d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] - * chorus->sinc_table[ii][pos_subsamples]; + /* The & in chorusbuf[...] is equivalent to a division modulo + MAX_SAMPLES, only faster. */ + d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] + * chorus->sinc_table[ii][pos_subsamples]; - pos_samples--; - }; - /* Cycle the phase of the modulating LFO */ - chorus->phase[i]++; - chorus->phase[i] %= (chorus->modulation_period_samples); - } /* foreach chorus block */ + pos_samples--; + }; - d_out *= chorus->level; + /* Cycle the phase of the modulating LFO */ + chorus->phase[i]++; - /* Add the chorus sum d_out to output */ - left_out[sample_index] += d_out; - right_out[sample_index] += d_out; + chorus->phase[i] %= (chorus->modulation_period_samples); + } /* foreach chorus block */ - /* Move forward in circular buffer */ - chorus->counter++; - chorus->counter %= MAX_SAMPLES; + d_out *= chorus->level; - } /* foreach sample */ + /* Add the chorus sum d_out to output */ + left_out[sample_index] += d_out; + right_out[sample_index] += d_out; + + /* Move forward in circular buffer */ + chorus->counter++; + chorus->counter %= MAX_SAMPLES; + + } /* foreach sample */ } /* Duplication of code ... (replaces sample data instead of mixing) */ -void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out) +void fluid_chorus_processreplace(fluid_chorus_t *chorus, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out) { - int sample_index; - int i; - fluid_real_t d_in, d_out; + int sample_index; + int i; + fluid_real_t d_in, d_out; - for (sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) { + for(sample_index = 0; sample_index < FLUID_BUFSIZE; sample_index++) + { - d_in = in[sample_index]; - d_out = 0.0f; + d_in = in[sample_index]; + d_out = 0.0f; # if 0 - /* Debug: Listen to the chorus signal only */ - left_out[sample_index]=0; - right_out[sample_index]=0; + /* Debug: Listen to the chorus signal only */ + left_out[sample_index] = 0; + right_out[sample_index] = 0; #endif - /* Write the current sample into the circular buffer */ - chorus->chorusbuf[chorus->counter] = d_in; + /* Write the current sample into the circular buffer */ + chorus->chorusbuf[chorus->counter] = d_in; - for (i = 0; i < chorus->number_blocks; i++) { - int ii; - /* Calculate the delay in subsamples for the delay line of chorus block nr. */ + for(i = 0; i < chorus->number_blocks; i++) + { + int ii; + /* Calculate the delay in subsamples for the delay line of chorus block nr. */ - /* The value in the lookup table is so, that this expression - * will always be positive. It will always include a number of - * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to - * remain positive at all times. */ - int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter - - chorus->lookup_tab[chorus->phase[i]]); + /* The value in the lookup table is so, that this expression + * will always be positive. It will always include a number of + * full periods of MAX_SAMPLES*INTERPOLATION_SUBSAMPLES to + * remain positive at all times. */ + int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter + - chorus->lookup_tab[chorus->phase[i]]); - int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES; + int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES; - /* modulo divide by INTERPOLATION_SUBSAMPLES */ - pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK; + /* modulo divide by INTERPOLATION_SUBSAMPLES */ + pos_subsamples &= INTERPOLATION_SUBSAMPLES_ANDMASK; - for (ii = 0; ii < INTERPOLATION_SAMPLES; ii++){ - /* Add the delayed signal to the chorus sum d_out Note: The - * delay in the delay line moves backwards for increasing - * delay!*/ + for(ii = 0; ii < INTERPOLATION_SAMPLES; ii++) + { + /* Add the delayed signal to the chorus sum d_out Note: The + * delay in the delay line moves backwards for increasing + * delay!*/ - /* The & in chorusbuf[...] is equivalent to a division modulo - MAX_SAMPLES, only faster. */ - d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] - * chorus->sinc_table[ii][pos_subsamples]; + /* The & in chorusbuf[...] is equivalent to a division modulo + MAX_SAMPLES, only faster. */ + d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] + * chorus->sinc_table[ii][pos_subsamples]; - pos_samples--; - }; - /* Cycle the phase of the modulating LFO */ - chorus->phase[i]++; - chorus->phase[i] %= (chorus->modulation_period_samples); - } /* foreach chorus block */ + pos_samples--; + }; - d_out *= chorus->level; + /* Cycle the phase of the modulating LFO */ + chorus->phase[i]++; - /* Store the chorus sum d_out to output */ - left_out[sample_index] = d_out; - right_out[sample_index] = d_out; + chorus->phase[i] %= (chorus->modulation_period_samples); + } /* foreach chorus block */ - /* Move forward in circular buffer */ - chorus->counter++; - chorus->counter %= MAX_SAMPLES; + d_out *= chorus->level; - } /* foreach sample */ + /* Store the chorus sum d_out to output */ + left_out[sample_index] = d_out; + right_out[sample_index] = d_out; + + /* Move forward in circular buffer */ + chorus->counter++; + chorus->counter %= MAX_SAMPLES; + + } /* foreach sample */ } /* Purpose: @@ -474,24 +538,25 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, static void fluid_chorus_sine(int *buf, int len, int depth) { - int i; - double angle, incr, mult; + int i; + double angle, incr, mult; - /* Pre-calculate increment between angles. */ - incr = (2. * M_PI) / (double)len; + /* Pre-calculate increment between angles. */ + incr = (2. * M_PI) / (double)len; - /* Pre-calculate 'depth' multiplier. */ - mult = (double) depth / 2.0 * (double) INTERPOLATION_SUBSAMPLES; + /* Pre-calculate 'depth' multiplier. */ + mult = (double) depth / 2.0 * (double) INTERPOLATION_SUBSAMPLES; - /* Initialize to zero degrees. */ - angle = 0.; + /* Initialize to zero degrees. */ + angle = 0.; - /* Build sine modulation waveform */ - for (i = 0; i < len; i++) { - buf[i] = (int) ((1. + sin(angle)) * mult) - 3 * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES; + /* Build sine modulation waveform */ + for(i = 0; i < len; i++) + { + buf[i] = (int)((1. + sin(angle)) * mult) - 3 * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES; - angle += incr; - } + angle += incr; + } } /* Purpose: @@ -501,25 +566,26 @@ fluid_chorus_sine(int *buf, int len, int depth) static void fluid_chorus_triangle(int *buf, int len, int depth) { - int *il = buf; - int *ir = buf + len-1; - int ival; - double val, incr; + int *il = buf; + int *ir = buf + len - 1; + int ival; + double val, incr; - /* Pre-calculate increment for the ramp. */ - incr = 2.0 / len * (double)depth * (double) INTERPOLATION_SUBSAMPLES; + /* Pre-calculate increment for the ramp. */ + incr = 2.0 / len * (double)depth * (double) INTERPOLATION_SUBSAMPLES; - /* Initialize first value */ - val = 0. - 3. * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES; + /* Initialize first value */ + val = 0. - 3. * MAX_SAMPLES * INTERPOLATION_SUBSAMPLES; - /* Build triangular modulation waveform */ - while (il <= ir) { - /* Assume 'val' to be always negative for rounding mode */ - ival = (int)(val - 0.5); + /* Build triangular modulation waveform */ + while(il <= ir) + { + /* Assume 'val' to be always negative for rounding mode */ + ival = (int)(val - 0.5); - *il++ = ival; - *ir-- = ival; + *il++ = ival; + *ir-- = ival; - val += incr; - } + val += incr; + } } diff --git a/src/rvoice/fluid_chorus.h b/src/rvoice/fluid_chorus.h index 57641e06..8a6734aa 100644 --- a/src/rvoice/fluid_chorus.h +++ b/src/rvoice/fluid_chorus.h @@ -30,35 +30,35 @@ typedef struct _fluid_chorus_t fluid_chorus_t; /** Flags for fluid_chorus_set() */ typedef enum { - FLUID_CHORUS_SET_NR = 1 << 0, - FLUID_CHORUS_SET_LEVEL = 1 << 1, - FLUID_CHORUS_SET_SPEED = 1 << 2, - FLUID_CHORUS_SET_DEPTH = 1 << 3, - FLUID_CHORUS_SET_TYPE = 1 << 4, - - /** Value for fluid_chorus_set() which sets all chorus parameters. */ - FLUID_CHORUS_SET_ALL = FLUID_CHORUS_SET_NR - | FLUID_CHORUS_SET_LEVEL - | FLUID_CHORUS_SET_SPEED - | FLUID_CHORUS_SET_DEPTH - | FLUID_CHORUS_SET_TYPE, + FLUID_CHORUS_SET_NR = 1 << 0, + FLUID_CHORUS_SET_LEVEL = 1 << 1, + FLUID_CHORUS_SET_SPEED = 1 << 2, + FLUID_CHORUS_SET_DEPTH = 1 << 3, + FLUID_CHORUS_SET_TYPE = 1 << 4, + + /** Value for fluid_chorus_set() which sets all chorus parameters. */ + FLUID_CHORUS_SET_ALL = FLUID_CHORUS_SET_NR + | FLUID_CHORUS_SET_LEVEL + | FLUID_CHORUS_SET_SPEED + | FLUID_CHORUS_SET_DEPTH + | FLUID_CHORUS_SET_TYPE, } fluid_chorus_set_t; /* * chorus */ -fluid_chorus_t* new_fluid_chorus(fluid_real_t sample_rate); -void delete_fluid_chorus(fluid_chorus_t* chorus); -int fluid_chorus_init(fluid_chorus_t* chorus); -void fluid_chorus_reset(fluid_chorus_t* chorus); +fluid_chorus_t *new_fluid_chorus(fluid_real_t sample_rate); +void delete_fluid_chorus(fluid_chorus_t *chorus); +int fluid_chorus_init(fluid_chorus_t *chorus); +void fluid_chorus_reset(fluid_chorus_t *chorus); -void fluid_chorus_set(fluid_chorus_t* chorus, int set, int nr, fluid_real_t level, +void fluid_chorus_set(fluid_chorus_t *chorus, int set, int nr, fluid_real_t level, fluid_real_t speed, fluid_real_t depth_ms, int type); -void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out); -void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out); +void fluid_chorus_processmix(fluid_chorus_t *chorus, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out); +void fluid_chorus_processreplace(fluid_chorus_t *chorus, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out); diff --git a/src/rvoice/fluid_iir_filter.c b/src/rvoice/fluid_iir_filter.c index 95ea5b69..0770ef62 100644 --- a/src/rvoice/fluid_iir_filter.c +++ b/src/rvoice/fluid_iir_filter.c @@ -46,129 +46,135 @@ * - dsp_hist1: same * - dsp_hist2: same */ -void -fluid_iir_filter_apply(fluid_iir_filter_t* iir_filter, +void +fluid_iir_filter_apply(fluid_iir_filter_t *iir_filter, fluid_real_t *dsp_buf, int count) { - if(iir_filter->type == FLUID_IIR_DISABLED || iir_filter->q_lin == 0) - { - return; - } - else - { - /* IIR filter sample history */ - fluid_real_t dsp_hist1 = iir_filter->hist1; - fluid_real_t dsp_hist2 = iir_filter->hist2; - - /* IIR filter coefficients */ - fluid_real_t dsp_a1 = iir_filter->a1; - fluid_real_t dsp_a2 = iir_filter->a2; - fluid_real_t dsp_b02 = iir_filter->b02; - fluid_real_t dsp_b1 = iir_filter->b1; - int dsp_filter_coeff_incr_count = iir_filter->filter_coeff_incr_count; - - fluid_real_t dsp_centernode; - int dsp_i; - - /* filter (implement the voice filter according to SoundFont standard) */ - - /* Check for denormal number (too close to zero). */ - if (fabs (dsp_hist1) < 1e-20) dsp_hist1 = 0.0f; /* FIXME JMG - Is this even needed? */ - - /* Two versions of the filter loop. One, while the filter is - * changing towards its new setting. The other, if the filter - * doesn't change. - */ - - if (dsp_filter_coeff_incr_count > 0) - { - fluid_real_t dsp_a1_incr = iir_filter->a1_incr; - fluid_real_t dsp_a2_incr = iir_filter->a2_incr; - fluid_real_t dsp_b02_incr = iir_filter->b02_incr; - fluid_real_t dsp_b1_incr = iir_filter->b1_incr; - - - /* Increment is added to each filter coefficient filter_coeff_incr_count times. */ - for (dsp_i = 0; dsp_i < count; dsp_i++) + if(iir_filter->type == FLUID_IIR_DISABLED || iir_filter->q_lin == 0) { - /* The filter is implemented in Direct-II form. */ - dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2; - dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1; - dsp_hist2 = dsp_hist1; - dsp_hist1 = dsp_centernode; - - if (dsp_filter_coeff_incr_count-- > 0) - { - fluid_real_t old_b02 = dsp_b02; - dsp_a1 += dsp_a1_incr; - dsp_a2 += dsp_a2_incr; - dsp_b02 += dsp_b02_incr; - dsp_b1 += dsp_b1_incr; - - /* Compensate history to avoid the filter going havoc with large frequency changes */ - if (iir_filter->compensate_incr && fabs(dsp_b02) > 0.001) { - fluid_real_t compensate = old_b02 / dsp_b02; - dsp_hist1 *= compensate; - dsp_hist2 *= compensate; - } - } - } /* for dsp_i */ - } - else /* The filter parameters are constant. This is duplicated to save time. */ - { - for (dsp_i = 0; dsp_i < count; dsp_i++) - { /* The filter is implemented in Direct-II form. */ - dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2; - dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1; - dsp_hist2 = dsp_hist1; - dsp_hist1 = dsp_centernode; + return; } - } + else + { + /* IIR filter sample history */ + fluid_real_t dsp_hist1 = iir_filter->hist1; + fluid_real_t dsp_hist2 = iir_filter->hist2; - iir_filter->hist1 = dsp_hist1; - iir_filter->hist2 = dsp_hist2; - iir_filter->a1 = dsp_a1; - iir_filter->a2 = dsp_a2; - iir_filter->b02 = dsp_b02; - iir_filter->b1 = dsp_b1; - iir_filter->filter_coeff_incr_count = dsp_filter_coeff_incr_count; + /* IIR filter coefficients */ + fluid_real_t dsp_a1 = iir_filter->a1; + fluid_real_t dsp_a2 = iir_filter->a2; + fluid_real_t dsp_b02 = iir_filter->b02; + fluid_real_t dsp_b1 = iir_filter->b1; + int dsp_filter_coeff_incr_count = iir_filter->filter_coeff_incr_count; - fluid_check_fpe ("voice_filter"); - } + fluid_real_t dsp_centernode; + int dsp_i; + + /* filter (implement the voice filter according to SoundFont standard) */ + + /* Check for denormal number (too close to zero). */ + if(fabs(dsp_hist1) < 1e-20) + { + dsp_hist1 = 0.0f; /* FIXME JMG - Is this even needed? */ + } + + /* Two versions of the filter loop. One, while the filter is + * changing towards its new setting. The other, if the filter + * doesn't change. + */ + + if(dsp_filter_coeff_incr_count > 0) + { + fluid_real_t dsp_a1_incr = iir_filter->a1_incr; + fluid_real_t dsp_a2_incr = iir_filter->a2_incr; + fluid_real_t dsp_b02_incr = iir_filter->b02_incr; + fluid_real_t dsp_b1_incr = iir_filter->b1_incr; + + + /* Increment is added to each filter coefficient filter_coeff_incr_count times. */ + for(dsp_i = 0; dsp_i < count; dsp_i++) + { + /* The filter is implemented in Direct-II form. */ + dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2; + dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1; + dsp_hist2 = dsp_hist1; + dsp_hist1 = dsp_centernode; + + if(dsp_filter_coeff_incr_count-- > 0) + { + fluid_real_t old_b02 = dsp_b02; + dsp_a1 += dsp_a1_incr; + dsp_a2 += dsp_a2_incr; + dsp_b02 += dsp_b02_incr; + dsp_b1 += dsp_b1_incr; + + /* Compensate history to avoid the filter going havoc with large frequency changes */ + if(iir_filter->compensate_incr && fabs(dsp_b02) > 0.001) + { + fluid_real_t compensate = old_b02 / dsp_b02; + dsp_hist1 *= compensate; + dsp_hist2 *= compensate; + } + } + } /* for dsp_i */ + } + else /* The filter parameters are constant. This is duplicated to save time. */ + { + for(dsp_i = 0; dsp_i < count; dsp_i++) + { + /* The filter is implemented in Direct-II form. */ + dsp_centernode = dsp_buf[dsp_i] - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2; + dsp_buf[dsp_i] = dsp_b02 * (dsp_centernode + dsp_hist2) + dsp_b1 * dsp_hist1; + dsp_hist2 = dsp_hist1; + dsp_hist1 = dsp_centernode; + } + } + + iir_filter->hist1 = dsp_hist1; + iir_filter->hist2 = dsp_hist2; + iir_filter->a1 = dsp_a1; + iir_filter->a2 = dsp_a2; + iir_filter->b02 = dsp_b02; + iir_filter->b1 = dsp_b1; + iir_filter->filter_coeff_incr_count = dsp_filter_coeff_incr_count; + + fluid_check_fpe("voice_filter"); + } } DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_init) { - fluid_iir_filter_t* iir_filter = obj; + fluid_iir_filter_t *iir_filter = obj; enum fluid_iir_filter_type type = param[0].i; enum fluid_iir_filter_flags flags = param[1].i; - + iir_filter->type = type; iir_filter->flags = flags; + if(type != FLUID_IIR_DISABLED) { fluid_iir_filter_reset(iir_filter); } } -void -fluid_iir_filter_reset(fluid_iir_filter_t* iir_filter) +void +fluid_iir_filter_reset(fluid_iir_filter_t *iir_filter) { - iir_filter->hist1 = 0; - iir_filter->hist2 = 0; - iir_filter->last_fres = -1.; - iir_filter->q_lin = 0; - iir_filter->filter_startup = 1; + iir_filter->hist1 = 0; + iir_filter->hist2 = 0; + iir_filter->last_fres = -1.; + iir_filter->q_lin = 0; + iir_filter->filter_startup = 1; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_fres) { - fluid_iir_filter_t* iir_filter = obj; - fluid_real_t fres = param[0].real; - - iir_filter->fres = fres; - iir_filter->last_fres = -1.; + fluid_iir_filter_t *iir_filter = obj; + fluid_real_t fres = param[0].real; + + iir_filter->fres = fres; + iir_filter->last_fres = -1.; } static fluid_real_t fluid_iir_filter_q_from_dB(fluid_real_t q_dB) @@ -196,7 +202,7 @@ static fluid_real_t fluid_iir_filter_q_from_dB(fluid_real_t q_dB) * response of a non-resonant filter. This idea is implemented as * follows: */ q_dB -= 3.01f; - + /* The 'sound font' Q is defined in dB. The filter needs a linear q. Convert. */ return pow(10.0f, q_dB / 20.0f); @@ -204,11 +210,11 @@ static fluid_real_t fluid_iir_filter_q_from_dB(fluid_real_t q_dB) DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q) { - fluid_iir_filter_t* iir_filter = obj; + fluid_iir_filter_t *iir_filter = obj; fluid_real_t q = param[0].real; int flags = iir_filter->flags; - - if(flags & FLUID_IIR_Q_ZERO_OFF && q<=0.0) + + if(flags & FLUID_IIR_Q_ZERO_OFF && q <= 0.0) { q = 0; } @@ -224,10 +230,10 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q) { q = fluid_iir_filter_q_from_dB(q); } - + iir_filter->q_lin = q; iir_filter->filter_gain = 1.0; - + if(!(flags & FLUID_IIR_NO_GAIN_AMP)) { /* SF 2.01 page 59: @@ -243,162 +249,171 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q) */ iir_filter->filter_gain /= sqrt(q); } - + /* The synthesis loop will have to recalculate the filter coefficients. */ iir_filter->last_fres = -1.; } -static FLUID_INLINE void -fluid_iir_filter_calculate_coefficients(fluid_iir_filter_t* iir_filter, - int transition_samples, +static FLUID_INLINE void +fluid_iir_filter_calculate_coefficients(fluid_iir_filter_t *iir_filter, + int transition_samples, fluid_real_t output_rate) { - /* FLUID_IIR_Q_LINEAR may switch the filter off by setting Q==0 */ - if(iir_filter->q_lin == 0) - { - return; - } - else - { - /* - * Those equations from Robert Bristow-Johnson's `Cookbook - * formulae for audio EQ biquad filter coefficients', obtained - * from Harmony-central.com / Computer / Programming. They are - * the result of the bilinear transform on an analogue filter - * prototype. To quote, `BLT frequency warping has been taken - * into account for both significant frequency relocation and for - * bandwidth readjustment'. */ - - fluid_real_t omega = (fluid_real_t) (2.0 * M_PI * - (iir_filter->last_fres / ((float) output_rate))); - fluid_real_t sin_coeff = (fluid_real_t) sin(omega); - fluid_real_t cos_coeff = (fluid_real_t) cos(omega); - fluid_real_t alpha_coeff = sin_coeff / (2.0f * iir_filter->q_lin); - fluid_real_t a0_inv = 1.0f / (1.0f + alpha_coeff); - - /* Calculate the filter coefficients. All coefficients are - * normalized by a0. Think of `a1' as `a1/a0'. - * - * Here a couple of multiplications are saved by reusing common expressions. - * The original equations should be: - * iir_filter->b0=(1.-cos_coeff)*a0_inv*0.5*iir_filter->filter_gain; - * iir_filter->b1=(1.-cos_coeff)*a0_inv*iir_filter->filter_gain; - * iir_filter->b2=(1.-cos_coeff)*a0_inv*0.5*iir_filter->filter_gain; */ - - /* "a" coeffs are same for all 3 available filter types */ - fluid_real_t a1_temp = -2.0f * cos_coeff * a0_inv; - fluid_real_t a2_temp = (1.0f - alpha_coeff) * a0_inv; - - fluid_real_t b02_temp, b1_temp; - switch(iir_filter->type) - { - case FLUID_IIR_HIGHPASS: - b1_temp = (1.0f + cos_coeff) * a0_inv * iir_filter->filter_gain; - - /* both b0 -and- b2 */ - b02_temp = b1_temp * 0.5f; - - b1_temp *= -1.0f; - break; - - case FLUID_IIR_LOWPASS: - b1_temp = (1.0f - cos_coeff) * a0_inv * iir_filter->filter_gain; - - /* both b0 -and- b2 */ - b02_temp = b1_temp * 0.5f; - break; - - default: - /* filter disabled, should never get here */ - return; - } - - iir_filter->compensate_incr = 0; - - if (iir_filter->filter_startup || (transition_samples == 0)) - { - /* The filter is calculated, because the voice was started up. - * In this case set the filter coefficients without delay. - */ - iir_filter->a1 = a1_temp; - iir_filter->a2 = a2_temp; - iir_filter->b02 = b02_temp; - iir_filter->b1 = b1_temp; - iir_filter->filter_coeff_incr_count = 0; - iir_filter->filter_startup = 0; -// printf("Setting initial filter coefficients.\n"); - } - else - { - - /* The filter frequency is changed. Calculate an increment - * factor, so that the new setting is reached after one buffer - * length. x_incr is added to the current value FLUID_BUFSIZE - * times. The length is arbitrarily chosen. Longer than one - * buffer will sacrifice some performance, though. Note: If - * the filter is still too 'grainy', then increase this number - * at will. - */ - - iir_filter->a1_incr = (a1_temp - iir_filter->a1) / transition_samples; - iir_filter->a2_incr = (a2_temp - iir_filter->a2) / transition_samples; - iir_filter->b02_incr = (b02_temp - iir_filter->b02) / transition_samples; - iir_filter->b1_incr = (b1_temp - iir_filter->b1) / transition_samples; - if (fabs(iir_filter->b02) > 0.0001) { - fluid_real_t quota = b02_temp / iir_filter->b02; - iir_filter->compensate_incr = quota < 0.5 || quota > 2; + /* FLUID_IIR_Q_LINEAR may switch the filter off by setting Q==0 */ + if(iir_filter->q_lin == 0) + { + return; + } + else + { + /* + * Those equations from Robert Bristow-Johnson's `Cookbook + * formulae for audio EQ biquad filter coefficients', obtained + * from Harmony-central.com / Computer / Programming. They are + * the result of the bilinear transform on an analogue filter + * prototype. To quote, `BLT frequency warping has been taken + * into account for both significant frequency relocation and for + * bandwidth readjustment'. */ + + fluid_real_t omega = (fluid_real_t)(2.0 * M_PI * + (iir_filter->last_fres / ((float) output_rate))); + fluid_real_t sin_coeff = (fluid_real_t) sin(omega); + fluid_real_t cos_coeff = (fluid_real_t) cos(omega); + fluid_real_t alpha_coeff = sin_coeff / (2.0f * iir_filter->q_lin); + fluid_real_t a0_inv = 1.0f / (1.0f + alpha_coeff); + + /* Calculate the filter coefficients. All coefficients are + * normalized by a0. Think of `a1' as `a1/a0'. + * + * Here a couple of multiplications are saved by reusing common expressions. + * The original equations should be: + * iir_filter->b0=(1.-cos_coeff)*a0_inv*0.5*iir_filter->filter_gain; + * iir_filter->b1=(1.-cos_coeff)*a0_inv*iir_filter->filter_gain; + * iir_filter->b2=(1.-cos_coeff)*a0_inv*0.5*iir_filter->filter_gain; */ + + /* "a" coeffs are same for all 3 available filter types */ + fluid_real_t a1_temp = -2.0f * cos_coeff * a0_inv; + fluid_real_t a2_temp = (1.0f - alpha_coeff) * a0_inv; + + fluid_real_t b02_temp, b1_temp; + + switch(iir_filter->type) + { + case FLUID_IIR_HIGHPASS: + b1_temp = (1.0f + cos_coeff) * a0_inv * iir_filter->filter_gain; + + /* both b0 -and- b2 */ + b02_temp = b1_temp * 0.5f; + + b1_temp *= -1.0f; + break; + + case FLUID_IIR_LOWPASS: + b1_temp = (1.0f - cos_coeff) * a0_inv * iir_filter->filter_gain; + + /* both b0 -and- b2 */ + b02_temp = b1_temp * 0.5f; + break; + + default: + /* filter disabled, should never get here */ + return; + } + + iir_filter->compensate_incr = 0; + + if(iir_filter->filter_startup || (transition_samples == 0)) + { + /* The filter is calculated, because the voice was started up. + * In this case set the filter coefficients without delay. + */ + iir_filter->a1 = a1_temp; + iir_filter->a2 = a2_temp; + iir_filter->b02 = b02_temp; + iir_filter->b1 = b1_temp; + iir_filter->filter_coeff_incr_count = 0; + iir_filter->filter_startup = 0; +// printf("Setting initial filter coefficients.\n"); + } + else + { + + /* The filter frequency is changed. Calculate an increment + * factor, so that the new setting is reached after one buffer + * length. x_incr is added to the current value FLUID_BUFSIZE + * times. The length is arbitrarily chosen. Longer than one + * buffer will sacrifice some performance, though. Note: If + * the filter is still too 'grainy', then increase this number + * at will. + */ + + iir_filter->a1_incr = (a1_temp - iir_filter->a1) / transition_samples; + iir_filter->a2_incr = (a2_temp - iir_filter->a2) / transition_samples; + iir_filter->b02_incr = (b02_temp - iir_filter->b02) / transition_samples; + iir_filter->b1_incr = (b1_temp - iir_filter->b1) / transition_samples; + + if(fabs(iir_filter->b02) > 0.0001) + { + fluid_real_t quota = b02_temp / iir_filter->b02; + iir_filter->compensate_incr = quota < 0.5 || quota > 2; + } + + /* Have to add the increments filter_coeff_incr_count times. */ + iir_filter->filter_coeff_incr_count = transition_samples; + } + + fluid_check_fpe("voice_write filter calculation"); } - /* Have to add the increments filter_coeff_incr_count times. */ - iir_filter->filter_coeff_incr_count = transition_samples; - } - fluid_check_fpe ("voice_write filter calculation"); - } } -void fluid_iir_filter_calc(fluid_iir_filter_t* iir_filter, - fluid_real_t output_rate, +void fluid_iir_filter_calc(fluid_iir_filter_t *iir_filter, + fluid_real_t output_rate, fluid_real_t fres_mod) { - fluid_real_t fres; + fluid_real_t fres; - /* calculate the frequency of the resonant filter in Hz */ - fres = fluid_ct2hz(iir_filter->fres + fres_mod); + /* calculate the frequency of the resonant filter in Hz */ + fres = fluid_ct2hz(iir_filter->fres + fres_mod); - /* FIXME - Still potential for a click during turn on, can we interpolate - between 20khz cutoff and 0 Q? */ + /* FIXME - Still potential for a click during turn on, can we interpolate + between 20khz cutoff and 0 Q? */ - /* I removed the optimization of turning the filter off when the - * resonance frequence is above the maximum frequency. Instead, the - * filter frequency is set to a maximum of 0.45 times the sampling - * rate. For a 44100 kHz sampling rate, this amounts to 19845 - * Hz. The reason is that there were problems with anti-aliasing when the - * synthesizer was run at lower sampling rates. Thanks to Stephan - * Tassart for pointing me to this bug. By turning the filter on and - * clipping the maximum filter frequency at 0.45*srate, the filter - * is used as an anti-aliasing filter. */ + /* I removed the optimization of turning the filter off when the + * resonance frequence is above the maximum frequency. Instead, the + * filter frequency is set to a maximum of 0.45 times the sampling + * rate. For a 44100 kHz sampling rate, this amounts to 19845 + * Hz. The reason is that there were problems with anti-aliasing when the + * synthesizer was run at lower sampling rates. Thanks to Stephan + * Tassart for pointing me to this bug. By turning the filter on and + * clipping the maximum filter frequency at 0.45*srate, the filter + * is used as an anti-aliasing filter. */ - if (fres > 0.45f * output_rate) - fres = 0.45f * output_rate; - else if (fres < 5) - fres = 5; + if(fres > 0.45f * output_rate) + { + fres = 0.45f * output_rate; + } + else if(fres < 5) + { + fres = 5; + } - /* if filter enabled and there is a significant frequency change.. */ - if (iir_filter->type != FLUID_IIR_DISABLED && fabs (fres - iir_filter->last_fres) > 0.01) - { - /* The filter coefficients have to be recalculated (filter - * parameters have changed). Recalculation for various reasons is - * forced by setting last_fres to -1. The flag filter_startup - * indicates, that the DSP loop runs for the first time, in this - * case, the filter is set directly, instead of smoothly fading - * between old and new settings. */ - iir_filter->last_fres = fres; - fluid_iir_filter_calculate_coefficients(iir_filter, FLUID_BUFSIZE, - output_rate); - } + /* if filter enabled and there is a significant frequency change.. */ + if(iir_filter->type != FLUID_IIR_DISABLED && fabs(fres - iir_filter->last_fres) > 0.01) + { + /* The filter coefficients have to be recalculated (filter + * parameters have changed). Recalculation for various reasons is + * forced by setting last_fres to -1. The flag filter_startup + * indicates, that the DSP loop runs for the first time, in this + * case, the filter is set directly, instead of smoothly fading + * between old and new settings. */ + iir_filter->last_fres = fres; + fluid_iir_filter_calculate_coefficients(iir_filter, FLUID_BUFSIZE, + output_rate); + } - fluid_check_fpe ("voice_write DSP coefficients"); + fluid_check_fpe("voice_write DSP coefficients"); } diff --git a/src/rvoice/fluid_iir_filter.h b/src/rvoice/fluid_iir_filter.h index 23268848..355d197f 100644 --- a/src/rvoice/fluid_iir_filter.h +++ b/src/rvoice/fluid_iir_filter.h @@ -29,46 +29,46 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_init); DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_fres); DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q); -void fluid_iir_filter_apply(fluid_iir_filter_t* iir_filter, +void fluid_iir_filter_apply(fluid_iir_filter_t *iir_filter, fluid_real_t *dsp_buf, int dsp_buf_count); -void fluid_iir_filter_reset(fluid_iir_filter_t* iir_filter); +void fluid_iir_filter_reset(fluid_iir_filter_t *iir_filter); -void fluid_iir_filter_calc(fluid_iir_filter_t* iir_filter, - fluid_real_t output_rate, +void fluid_iir_filter_calc(fluid_iir_filter_t *iir_filter, + fluid_real_t output_rate, fluid_real_t fres_mod); /* We can't do information hiding here, as fluid_voice_t includes the struct without a pointer. */ struct _fluid_iir_filter_t { - enum fluid_iir_filter_type type; /* specifies the type of this filter */ - enum fluid_iir_filter_flags flags; /* additional flags to customize this filter */ - - /* filter coefficients */ - /* The coefficients are normalized to a0. */ - /* b0 and b2 are identical => b02 */ - fluid_real_t b02; /* b0 / a0 */ - fluid_real_t b1; /* b1 / a0 */ - fluid_real_t a1; /* a0 / a0 */ - fluid_real_t a2; /* a1 / a0 */ + enum fluid_iir_filter_type type; /* specifies the type of this filter */ + enum fluid_iir_filter_flags flags; /* additional flags to customize this filter */ - fluid_real_t b02_incr; - fluid_real_t b1_incr; - fluid_real_t a1_incr; - fluid_real_t a2_incr; - int filter_coeff_incr_count; - int compensate_incr; /* Flag: If set, must compensate history */ - fluid_real_t hist1, hist2; /* Sample history for the IIR filter */ - int filter_startup; /* Flag: If set, the filter will be set directly. + /* filter coefficients */ + /* The coefficients are normalized to a0. */ + /* b0 and b2 are identical => b02 */ + fluid_real_t b02; /* b0 / a0 */ + fluid_real_t b1; /* b1 / a0 */ + fluid_real_t a1; /* a0 / a0 */ + fluid_real_t a2; /* a1 / a0 */ + + fluid_real_t b02_incr; + fluid_real_t b1_incr; + fluid_real_t a1_incr; + fluid_real_t a2_incr; + int filter_coeff_incr_count; + int compensate_incr; /* Flag: If set, must compensate history */ + fluid_real_t hist1, hist2; /* Sample history for the IIR filter */ + int filter_startup; /* Flag: If set, the filter will be set directly. Else it changes smoothly. */ - fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */ - fluid_real_t last_fres; /* Current resonance frequency of the IIR filter */ - /* Serves as a flag: A deviation between fres and last_fres */ - /* indicates, that the filter has to be recalculated. */ - fluid_real_t q_lin; /* the q-factor on a linear scale */ - fluid_real_t filter_gain; /* Gain correction factor, depends on q */ + fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */ + fluid_real_t last_fres; /* Current resonance frequency of the IIR filter */ + /* Serves as a flag: A deviation between fres and last_fres */ + /* indicates, that the filter has to be recalculated. */ + fluid_real_t q_lin; /* the q-factor on a linear scale */ + fluid_real_t filter_gain; /* Gain correction factor, depends on q */ }; #endif diff --git a/src/rvoice/fluid_lfo.c b/src/rvoice/fluid_lfo.c index a6d2f6ff..ae21cdd0 100644 --- a/src/rvoice/fluid_lfo.c +++ b/src/rvoice/fluid_lfo.c @@ -2,16 +2,16 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_incr) { - fluid_lfo_t* lfo = obj; + fluid_lfo_t *lfo = obj; fluid_real_t increment = param[0].real; - + lfo->increment = increment; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_delay) { - fluid_lfo_t* lfo = obj; + fluid_lfo_t *lfo = obj; unsigned int delay = param[0].i; - + lfo->delay = delay; } diff --git a/src/rvoice/fluid_lfo.h b/src/rvoice/fluid_lfo.h index 7f2906a0..b9a9ca6e 100644 --- a/src/rvoice/fluid_lfo.h +++ b/src/rvoice/fluid_lfo.h @@ -25,16 +25,17 @@ typedef struct _fluid_lfo_t fluid_lfo_t; -struct _fluid_lfo_t { - fluid_real_t val; /* the current value of the LFO */ - unsigned int delay; /* the delay of the lfo in samples */ - fluid_real_t increment; /* the lfo frequency is converted to a per-buffer increment */ +struct _fluid_lfo_t +{ + fluid_real_t val; /* the current value of the LFO */ + unsigned int delay; /* the delay of the lfo in samples */ + fluid_real_t increment; /* the lfo frequency is converted to a per-buffer increment */ }; -static FLUID_INLINE void -fluid_lfo_reset(fluid_lfo_t* lfo) +static FLUID_INLINE void +fluid_lfo_reset(fluid_lfo_t *lfo) { - lfo->val = 0.0f; + lfo->val = 0.0f; } // These two cannot be inlined since they're used by event_dispatch @@ -42,29 +43,31 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_incr); DECLARE_FLUID_RVOICE_FUNCTION(fluid_lfo_set_delay); static FLUID_INLINE fluid_real_t -fluid_lfo_get_val(fluid_lfo_t* lfo) +fluid_lfo_get_val(fluid_lfo_t *lfo) { - return lfo->val; + return lfo->val; } -static FLUID_INLINE void -fluid_lfo_calc(fluid_lfo_t* lfo, unsigned int cur_delay) +static FLUID_INLINE void +fluid_lfo_calc(fluid_lfo_t *lfo, unsigned int cur_delay) { - if (cur_delay < lfo->delay) - return; - - lfo->val += lfo->increment; - - if (lfo->val > (fluid_real_t) 1.0) - { - lfo->increment = -lfo->increment; - lfo->val = (fluid_real_t) 2.0 - lfo->val; - } - else if (lfo->val < (fluid_real_t) -1.0) - { - lfo->increment = -lfo->increment; - lfo->val = (fluid_real_t) -2.0 - lfo->val; - } + if(cur_delay < lfo->delay) + { + return; + } + + lfo->val += lfo->increment; + + if(lfo->val > (fluid_real_t) 1.0) + { + lfo->increment = -lfo->increment; + lfo->val = (fluid_real_t) 2.0 - lfo->val; + } + else if(lfo->val < (fluid_real_t) -1.0) + { + lfo->increment = -lfo->increment; + lfo->val = (fluid_real_t) -2.0 - lfo->val; + } } diff --git a/src/rvoice/fluid_rev.c b/src/rvoice/fluid_rev.c index dc784fe1..8a58d1e8 100644 --- a/src/rvoice/fluid_rev.c +++ b/src/rvoice/fluid_rev.c @@ -39,52 +39,55 @@ typedef struct _fluid_allpass fluid_allpass; typedef struct _fluid_comb fluid_comb; -struct _fluid_allpass { - fluid_real_t feedback; - fluid_real_t *buffer; - int bufsize; - int bufidx; +struct _fluid_allpass +{ + fluid_real_t feedback; + fluid_real_t *buffer; + int bufsize; + int bufidx; }; -void fluid_allpass_init(fluid_allpass* allpass); -void fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val); -fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass); +void fluid_allpass_init(fluid_allpass *allpass); +void fluid_allpass_setfeedback(fluid_allpass *allpass, fluid_real_t val); +fluid_real_t fluid_allpass_getfeedback(fluid_allpass *allpass); void -fluid_allpass_setbuffer(fluid_allpass* allpass, int size) +fluid_allpass_setbuffer(fluid_allpass *allpass, int size) { - allpass->bufidx = 0; - allpass->buffer = FLUID_ARRAY(fluid_real_t,size); - allpass->bufsize = size; + allpass->bufidx = 0; + allpass->buffer = FLUID_ARRAY(fluid_real_t, size); + allpass->bufsize = size; } void -fluid_allpass_release(fluid_allpass* allpass) +fluid_allpass_release(fluid_allpass *allpass) { - FLUID_FREE(allpass->buffer); + FLUID_FREE(allpass->buffer); } void -fluid_allpass_init(fluid_allpass* allpass) +fluid_allpass_init(fluid_allpass *allpass) { - int i; - int len = allpass->bufsize; - fluid_real_t* buf = allpass->buffer; - for (i = 0; i < len; i++) { - buf[i] = DC_OFFSET; /* this is not 100 % correct. */ - } + int i; + int len = allpass->bufsize; + fluid_real_t *buf = allpass->buffer; + + for(i = 0; i < len; i++) + { + buf[i] = DC_OFFSET; /* this is not 100 % correct. */ + } } void -fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val) +fluid_allpass_setfeedback(fluid_allpass *allpass, fluid_real_t val) { - allpass->feedback = val; + allpass->feedback = val; } fluid_real_t -fluid_allpass_getfeedback(fluid_allpass* allpass) +fluid_allpass_getfeedback(fluid_allpass *allpass) { - return allpass->feedback; + return allpass->feedback; } #define fluid_allpass_process(_allpass, _input) \ @@ -100,73 +103,76 @@ fluid_allpass_getfeedback(fluid_allpass* allpass) _input = output; \ } -struct _fluid_comb { - fluid_real_t feedback; - fluid_real_t filterstore; - fluid_real_t damp1; - fluid_real_t damp2; - fluid_real_t *buffer; - int bufsize; - int bufidx; +struct _fluid_comb +{ + fluid_real_t feedback; + fluid_real_t filterstore; + fluid_real_t damp1; + fluid_real_t damp2; + fluid_real_t *buffer; + int bufsize; + int bufidx; }; -void fluid_comb_setbuffer(fluid_comb* comb, int size); -void fluid_comb_release(fluid_comb* comb); -void fluid_comb_init(fluid_comb* comb); -void fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val); -fluid_real_t fluid_comb_getdamp(fluid_comb* comb); -void fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val); -fluid_real_t fluid_comb_getfeedback(fluid_comb* comb); +void fluid_comb_setbuffer(fluid_comb *comb, int size); +void fluid_comb_release(fluid_comb *comb); +void fluid_comb_init(fluid_comb *comb); +void fluid_comb_setdamp(fluid_comb *comb, fluid_real_t val); +fluid_real_t fluid_comb_getdamp(fluid_comb *comb); +void fluid_comb_setfeedback(fluid_comb *comb, fluid_real_t val); +fluid_real_t fluid_comb_getfeedback(fluid_comb *comb); void -fluid_comb_setbuffer(fluid_comb* comb, int size) +fluid_comb_setbuffer(fluid_comb *comb, int size) { - comb->filterstore = 0; - comb->bufidx = 0; - comb->buffer = FLUID_ARRAY(fluid_real_t,size); - comb->bufsize = size; + comb->filterstore = 0; + comb->bufidx = 0; + comb->buffer = FLUID_ARRAY(fluid_real_t, size); + comb->bufsize = size; } void -fluid_comb_release(fluid_comb* comb) +fluid_comb_release(fluid_comb *comb) { - FLUID_FREE(comb->buffer); + FLUID_FREE(comb->buffer); } void -fluid_comb_init(fluid_comb* comb) +fluid_comb_init(fluid_comb *comb) { - int i; - fluid_real_t* buf = comb->buffer; - int len = comb->bufsize; - for (i = 0; i < len; i++) { - buf[i] = DC_OFFSET; /* This is not 100 % correct. */ - } + int i; + fluid_real_t *buf = comb->buffer; + int len = comb->bufsize; + + for(i = 0; i < len; i++) + { + buf[i] = DC_OFFSET; /* This is not 100 % correct. */ + } } void -fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val) +fluid_comb_setdamp(fluid_comb *comb, fluid_real_t val) { - comb->damp1 = val; - comb->damp2 = 1 - val; + comb->damp1 = val; + comb->damp2 = 1 - val; } fluid_real_t -fluid_comb_getdamp(fluid_comb* comb) +fluid_comb_getdamp(fluid_comb *comb) { - return comb->damp1; + return comb->damp1; } void -fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val) +fluid_comb_setfeedback(fluid_comb *comb, fluid_real_t val) { - comb->feedback = val; + comb->feedback = val; } fluid_real_t -fluid_comb_getfeedback(fluid_comb* comb) +fluid_comb_getfeedback(fluid_comb *comb) { - return comb->feedback; + return comb->feedback; } #define fluid_comb_process(_comb, _input, _output) \ @@ -187,10 +193,10 @@ fluid_comb_getfeedback(fluid_comb* comb) amplitude (wet) rather independent of the width setting. 0: the output amplitude is fully dependant on the width setting. >0: the output amplitude is less dependant on the width setting. - With a scale_wet_width of 0.2 the output amplitude is rather + With a scale_wet_width of 0.2 the output amplitude is rather independent of width setting (see fluid_revmodel_update()). */ -#define scale_wet_width 0.2f +#define scale_wet_width 0.2f #define scalewet 3.0f #define scaledamp 1.0f #define scaleroom 0.28f @@ -228,234 +234,255 @@ fluid_comb_getfeedback(fluid_comb* comb) #define allpasstuningL4 225 #define allpasstuningR4 (225 + stereospread) -struct _fluid_revmodel_t { - fluid_real_t roomsize; - fluid_real_t damp; - fluid_real_t level, wet1, wet2; - fluid_real_t width; - fluid_real_t gain; - /* - The following are all declared inline - to remove the need for dynamic allocation - with its subsequent error-checking messiness - */ - /* Comb filters */ - fluid_comb combL[numcombs]; - fluid_comb combR[numcombs]; - /* Allpass filters */ - fluid_allpass allpassL[numallpasses]; - fluid_allpass allpassR[numallpasses]; +struct _fluid_revmodel_t +{ + fluid_real_t roomsize; + fluid_real_t damp; + fluid_real_t level, wet1, wet2; + fluid_real_t width; + fluid_real_t gain; + /* + The following are all declared inline + to remove the need for dynamic allocation + with its subsequent error-checking messiness + */ + /* Comb filters */ + fluid_comb combL[numcombs]; + fluid_comb combR[numcombs]; + /* Allpass filters */ + fluid_allpass allpassL[numallpasses]; + fluid_allpass allpassR[numallpasses]; }; -static void fluid_revmodel_update(fluid_revmodel_t* rev); -static void fluid_revmodel_init(fluid_revmodel_t* rev); -void fluid_set_revmodel_buffers(fluid_revmodel_t* rev, fluid_real_t sample_rate); +static void fluid_revmodel_update(fluid_revmodel_t *rev); +static void fluid_revmodel_init(fluid_revmodel_t *rev); +void fluid_set_revmodel_buffers(fluid_revmodel_t *rev, fluid_real_t sample_rate); -fluid_revmodel_t* +fluid_revmodel_t * new_fluid_revmodel(fluid_real_t sample_rate) { - fluid_revmodel_t* rev; - rev = FLUID_NEW(fluid_revmodel_t); - if (rev == NULL) { - return NULL; - } + fluid_revmodel_t *rev; + rev = FLUID_NEW(fluid_revmodel_t); - fluid_set_revmodel_buffers(rev, sample_rate); + if(rev == NULL) + { + return NULL; + } - /* Set default values */ - fluid_allpass_setfeedback(&rev->allpassL[0], 0.5f); - fluid_allpass_setfeedback(&rev->allpassR[0], 0.5f); - fluid_allpass_setfeedback(&rev->allpassL[1], 0.5f); - fluid_allpass_setfeedback(&rev->allpassR[1], 0.5f); - fluid_allpass_setfeedback(&rev->allpassL[2], 0.5f); - fluid_allpass_setfeedback(&rev->allpassR[2], 0.5f); - fluid_allpass_setfeedback(&rev->allpassL[3], 0.5f); - fluid_allpass_setfeedback(&rev->allpassR[3], 0.5f); + fluid_set_revmodel_buffers(rev, sample_rate); - rev->gain = fixedgain; + /* Set default values */ + fluid_allpass_setfeedback(&rev->allpassL[0], 0.5f); + fluid_allpass_setfeedback(&rev->allpassR[0], 0.5f); + fluid_allpass_setfeedback(&rev->allpassL[1], 0.5f); + fluid_allpass_setfeedback(&rev->allpassR[1], 0.5f); + fluid_allpass_setfeedback(&rev->allpassL[2], 0.5f); + fluid_allpass_setfeedback(&rev->allpassR[2], 0.5f); + fluid_allpass_setfeedback(&rev->allpassL[3], 0.5f); + fluid_allpass_setfeedback(&rev->allpassR[3], 0.5f); - return rev; + rev->gain = fixedgain; + + return rev; } void -delete_fluid_revmodel(fluid_revmodel_t* rev) +delete_fluid_revmodel(fluid_revmodel_t *rev) { - int i; - fluid_return_if_fail(rev != NULL); - - for (i = 0; i < numcombs;i++) { - fluid_comb_release(&rev->combL[i]); - fluid_comb_release(&rev->combR[i]); - } - for (i = 0; i < numallpasses; i++) { - fluid_allpass_release(&rev->allpassL[i]); - fluid_allpass_release(&rev->allpassR[i]); - } + int i; + fluid_return_if_fail(rev != NULL); - FLUID_FREE(rev); + for(i = 0; i < numcombs; i++) + { + fluid_comb_release(&rev->combL[i]); + fluid_comb_release(&rev->combR[i]); + } + + for(i = 0; i < numallpasses; i++) + { + fluid_allpass_release(&rev->allpassL[i]); + fluid_allpass_release(&rev->allpassR[i]); + } + + FLUID_FREE(rev); } void -fluid_set_revmodel_buffers(fluid_revmodel_t* rev, fluid_real_t sample_rate) { +fluid_set_revmodel_buffers(fluid_revmodel_t *rev, fluid_real_t sample_rate) +{ - float srfactor = sample_rate/44100.0f; + float srfactor = sample_rate / 44100.0f; - fluid_comb_setbuffer(&rev->combL[0], combtuningL1*srfactor); - fluid_comb_setbuffer(&rev->combR[0], combtuningR1*srfactor); - fluid_comb_setbuffer(&rev->combL[1], combtuningL2*srfactor); - fluid_comb_setbuffer(&rev->combR[1], combtuningR2*srfactor); - fluid_comb_setbuffer(&rev->combL[2], combtuningL3*srfactor); - fluid_comb_setbuffer(&rev->combR[2], combtuningR3*srfactor); - fluid_comb_setbuffer(&rev->combL[3], combtuningL4*srfactor); - fluid_comb_setbuffer(&rev->combR[3], combtuningR4*srfactor); - fluid_comb_setbuffer(&rev->combL[4], combtuningL5*srfactor); - fluid_comb_setbuffer(&rev->combR[4], combtuningR5*srfactor); - fluid_comb_setbuffer(&rev->combL[5], combtuningL6*srfactor); - fluid_comb_setbuffer(&rev->combR[5], combtuningR6*srfactor); - fluid_comb_setbuffer(&rev->combL[6], combtuningL7*srfactor); - fluid_comb_setbuffer(&rev->combR[6], combtuningR7*srfactor); - fluid_comb_setbuffer(&rev->combL[7], combtuningL8*srfactor); - fluid_comb_setbuffer(&rev->combR[7], combtuningR8*srfactor); - fluid_allpass_setbuffer(&rev->allpassL[0], allpasstuningL1*srfactor); - fluid_allpass_setbuffer(&rev->allpassR[0], allpasstuningR1*srfactor); - fluid_allpass_setbuffer(&rev->allpassL[1], allpasstuningL2*srfactor); - fluid_allpass_setbuffer(&rev->allpassR[1], allpasstuningR2*srfactor); - fluid_allpass_setbuffer(&rev->allpassL[2], allpasstuningL3*srfactor); - fluid_allpass_setbuffer(&rev->allpassR[2], allpasstuningR3*srfactor); - fluid_allpass_setbuffer(&rev->allpassL[3], allpasstuningL4*srfactor); - fluid_allpass_setbuffer(&rev->allpassR[3], allpasstuningR4*srfactor); + fluid_comb_setbuffer(&rev->combL[0], combtuningL1 * srfactor); + fluid_comb_setbuffer(&rev->combR[0], combtuningR1 * srfactor); + fluid_comb_setbuffer(&rev->combL[1], combtuningL2 * srfactor); + fluid_comb_setbuffer(&rev->combR[1], combtuningR2 * srfactor); + fluid_comb_setbuffer(&rev->combL[2], combtuningL3 * srfactor); + fluid_comb_setbuffer(&rev->combR[2], combtuningR3 * srfactor); + fluid_comb_setbuffer(&rev->combL[3], combtuningL4 * srfactor); + fluid_comb_setbuffer(&rev->combR[3], combtuningR4 * srfactor); + fluid_comb_setbuffer(&rev->combL[4], combtuningL5 * srfactor); + fluid_comb_setbuffer(&rev->combR[4], combtuningR5 * srfactor); + fluid_comb_setbuffer(&rev->combL[5], combtuningL6 * srfactor); + fluid_comb_setbuffer(&rev->combR[5], combtuningR6 * srfactor); + fluid_comb_setbuffer(&rev->combL[6], combtuningL7 * srfactor); + fluid_comb_setbuffer(&rev->combR[6], combtuningR7 * srfactor); + fluid_comb_setbuffer(&rev->combL[7], combtuningL8 * srfactor); + fluid_comb_setbuffer(&rev->combR[7], combtuningR8 * srfactor); + fluid_allpass_setbuffer(&rev->allpassL[0], allpasstuningL1 * srfactor); + fluid_allpass_setbuffer(&rev->allpassR[0], allpasstuningR1 * srfactor); + fluid_allpass_setbuffer(&rev->allpassL[1], allpasstuningL2 * srfactor); + fluid_allpass_setbuffer(&rev->allpassR[1], allpasstuningR2 * srfactor); + fluid_allpass_setbuffer(&rev->allpassL[2], allpasstuningL3 * srfactor); + fluid_allpass_setbuffer(&rev->allpassR[2], allpasstuningR3 * srfactor); + fluid_allpass_setbuffer(&rev->allpassL[3], allpasstuningL4 * srfactor); + fluid_allpass_setbuffer(&rev->allpassR[3], allpasstuningR4 * srfactor); - /* Clear all buffers */ - fluid_revmodel_init(rev); + /* Clear all buffers */ + fluid_revmodel_init(rev); } static void -fluid_revmodel_init(fluid_revmodel_t* rev) +fluid_revmodel_init(fluid_revmodel_t *rev) { - int i; - for (i = 0; i < numcombs;i++) { - fluid_comb_init(&rev->combL[i]); - fluid_comb_init(&rev->combR[i]); - } - for (i = 0; i < numallpasses; i++) { - fluid_allpass_init(&rev->allpassL[i]); - fluid_allpass_init(&rev->allpassR[i]); - } + int i; + + for(i = 0; i < numcombs; i++) + { + fluid_comb_init(&rev->combL[i]); + fluid_comb_init(&rev->combR[i]); + } + + for(i = 0; i < numallpasses; i++) + { + fluid_allpass_init(&rev->allpassL[i]); + fluid_allpass_init(&rev->allpassR[i]); + } } void -fluid_revmodel_reset(fluid_revmodel_t* rev) +fluid_revmodel_reset(fluid_revmodel_t *rev) { - fluid_revmodel_init(rev); + fluid_revmodel_init(rev); } void -fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out) +fluid_revmodel_processreplace(fluid_revmodel_t *rev, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out) { - int i, k = 0; - fluid_real_t outL, outR, input; + int i, k = 0; + fluid_real_t outL, outR, input; - for (k = 0; k < FLUID_BUFSIZE; k++) { + for(k = 0; k < FLUID_BUFSIZE; k++) + { - outL = outR = 0; + outL = outR = 0; - /* The original Freeverb code expects a stereo signal and 'input' - * is set to the sum of the left and right input sample. Since - * this code works on a mono signal, 'input' is set to twice the - * input sample. */ - input = (2.0f * in[k] + DC_OFFSET) * rev->gain; + /* The original Freeverb code expects a stereo signal and 'input' + * is set to the sum of the left and right input sample. Since + * this code works on a mono signal, 'input' is set to twice the + * input sample. */ + input = (2.0f * in[k] + DC_OFFSET) * rev->gain; - /* Accumulate comb filters in parallel */ - for (i = 0; i < numcombs; i++) { - fluid_comb_process(rev->combL[i], input, outL); - fluid_comb_process(rev->combR[i], input, outR); + /* Accumulate comb filters in parallel */ + for(i = 0; i < numcombs; i++) + { + fluid_comb_process(rev->combL[i], input, outL); + fluid_comb_process(rev->combR[i], input, outR); + } + + /* Feed through allpasses in series */ + for(i = 0; i < numallpasses; i++) + { + fluid_allpass_process(rev->allpassL[i], outL); + fluid_allpass_process(rev->allpassR[i], outR); + } + + /* Remove the DC offset */ + outL -= DC_OFFSET; + outR -= DC_OFFSET; + + /* Calculate output REPLACING anything already there */ + left_out[k] = outL * rev->wet1 + outR * rev->wet2; + right_out[k] = outR * rev->wet1 + outL * rev->wet2; } - /* Feed through allpasses in series */ - for (i = 0; i < numallpasses; i++) { - fluid_allpass_process(rev->allpassL[i], outL); - fluid_allpass_process(rev->allpassR[i], outR); - } - - /* Remove the DC offset */ - outL -= DC_OFFSET; - outR -= DC_OFFSET; - - /* Calculate output REPLACING anything already there */ - left_out[k] = outL * rev->wet1 + outR * rev->wet2; - right_out[k] = outR * rev->wet1 + outL * rev->wet2; - } } void -fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out) +fluid_revmodel_processmix(fluid_revmodel_t *rev, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out) { - int i, k = 0; - fluid_real_t outL, outR, input; + int i, k = 0; + fluid_real_t outL, outR, input; - for (k = 0; k < FLUID_BUFSIZE; k++) { + for(k = 0; k < FLUID_BUFSIZE; k++) + { - outL = outR = 0; + outL = outR = 0; - /* The original Freeverb code expects a stereo signal and 'input' - * is set to the sum of the left and right input sample. Since - * this code works on a mono signal, 'input' is set to twice the - * input sample. */ - input = (2.0f * in[k] + DC_OFFSET) * rev->gain; + /* The original Freeverb code expects a stereo signal and 'input' + * is set to the sum of the left and right input sample. Since + * this code works on a mono signal, 'input' is set to twice the + * input sample. */ + input = (2.0f * in[k] + DC_OFFSET) * rev->gain; - /* Accumulate comb filters in parallel */ - for (i = 0; i < numcombs; i++) { - fluid_comb_process(rev->combL[i], input, outL); - fluid_comb_process(rev->combR[i], input, outR); + /* Accumulate comb filters in parallel */ + for(i = 0; i < numcombs; i++) + { + fluid_comb_process(rev->combL[i], input, outL); + fluid_comb_process(rev->combR[i], input, outR); + } + + /* Feed through allpasses in series */ + for(i = 0; i < numallpasses; i++) + { + fluid_allpass_process(rev->allpassL[i], outL); + fluid_allpass_process(rev->allpassR[i], outR); + } + + /* Remove the DC offset */ + outL -= DC_OFFSET; + outR -= DC_OFFSET; + + /* Calculate output MIXING with anything already there */ + left_out[k] += outL * rev->wet1 + outR * rev->wet2; + right_out[k] += outR * rev->wet1 + outL * rev->wet2; } - /* Feed through allpasses in series */ - for (i = 0; i < numallpasses; i++) { - fluid_allpass_process(rev->allpassL[i], outL); - fluid_allpass_process(rev->allpassR[i], outR); - } - - /* Remove the DC offset */ - outL -= DC_OFFSET; - outR -= DC_OFFSET; - - /* Calculate output MIXING with anything already there */ - left_out[k] += outL * rev->wet1 + outR * rev->wet2; - right_out[k] += outR * rev->wet1 + outL * rev->wet2; - } } static void -fluid_revmodel_update(fluid_revmodel_t* rev) +fluid_revmodel_update(fluid_revmodel_t *rev) { - /* Recalculate internal values after parameter change */ - int i; + /* Recalculate internal values after parameter change */ + int i; - /* The stereo amplitude equation (wet1 and wet2 below) have a - tendency to produce high amplitude with high width values ( 1 < width < 100). - This results in an unwanted noisy output clipped by the audio card. - To avoid this dependency, we divide by (1 + rev->width * scale_wet_width) - Actually, with a scale_wet_width of 0.2, (regardless of level setting), - the output amplitude (wet) seems rather independent of width setting */ - fluid_real_t wet = (rev->level * scalewet) / - (1.0f + rev->width * scale_wet_width); - - /* wet1 and wet2 are used by the stereo effect controled by the width setting - for producing a stereo ouptput from a monophonic reverb signal. - Please see the note above about a side effect tendency */ - rev->wet1 = wet * (rev->width / 2.0f + 0.5f); - rev->wet2 = wet * ((1.0f - rev->width) / 2.0f); + /* The stereo amplitude equation (wet1 and wet2 below) have a + tendency to produce high amplitude with high width values ( 1 < width < 100). + This results in an unwanted noisy output clipped by the audio card. + To avoid this dependency, we divide by (1 + rev->width * scale_wet_width) + Actually, with a scale_wet_width of 0.2, (regardless of level setting), + the output amplitude (wet) seems rather independent of width setting */ + fluid_real_t wet = (rev->level * scalewet) / + (1.0f + rev->width * scale_wet_width); - for (i = 0; i < numcombs; i++) { - fluid_comb_setfeedback(&rev->combL[i], rev->roomsize); - fluid_comb_setfeedback(&rev->combR[i], rev->roomsize); - } + /* wet1 and wet2 are used by the stereo effect controled by the width setting + for producing a stereo ouptput from a monophonic reverb signal. + Please see the note above about a side effect tendency */ + rev->wet1 = wet * (rev->width / 2.0f + 0.5f); + rev->wet2 = wet * ((1.0f - rev->width) / 2.0f); - for (i = 0; i < numcombs; i++) { - fluid_comb_setdamp(&rev->combL[i], rev->damp); - fluid_comb_setdamp(&rev->combR[i], rev->damp); - } + for(i = 0; i < numcombs; i++) + { + fluid_comb_setfeedback(&rev->combL[i], rev->roomsize); + fluid_comb_setfeedback(&rev->combR[i], rev->roomsize); + } + + for(i = 0; i < numcombs; i++) + { + fluid_comb_setdamp(&rev->combL[i], rev->damp); + fluid_comb_setdamp(&rev->combR[i], rev->damp); + } } /** @@ -469,43 +496,53 @@ fluid_revmodel_update(fluid_revmodel_t* rev) * @param level Reverb level */ void -fluid_revmodel_set(fluid_revmodel_t* rev, int set, fluid_real_t roomsize, +fluid_revmodel_set(fluid_revmodel_t *rev, int set, fluid_real_t roomsize, fluid_real_t damping, fluid_real_t width, fluid_real_t level) { - if (set & FLUID_REVMODEL_SET_ROOMSIZE) - { + if(set & FLUID_REVMODEL_SET_ROOMSIZE) + { /* With upper limit above 1.07, the output amplitude will grow - exponentially. So, keeping this upper limit to 1.0 seems sufficient - as it produces yet a long reverb time */ - fluid_clip(roomsize, 0.0f, 1.0f); - rev->roomsize = (roomsize * scaleroom) + offsetroom; - } + exponentially. So, keeping this upper limit to 1.0 seems sufficient + as it produces yet a long reverb time */ + fluid_clip(roomsize, 0.0f, 1.0f); + rev->roomsize = (roomsize * scaleroom) + offsetroom; + } - if (set & FLUID_REVMODEL_SET_DAMPING) - rev->damp = damping * scaledamp; + if(set & FLUID_REVMODEL_SET_DAMPING) + { + rev->damp = damping * scaledamp; + } - if (set & FLUID_REVMODEL_SET_WIDTH) - rev->width = width; + if(set & FLUID_REVMODEL_SET_WIDTH) + { + rev->width = width; + } - if (set & FLUID_REVMODEL_SET_LEVEL) - { - fluid_clip(level, 0.0f, 1.0f); - rev->level = level; - } + if(set & FLUID_REVMODEL_SET_LEVEL) + { + fluid_clip(level, 0.0f, 1.0f); + rev->level = level; + } - fluid_revmodel_update (rev); + fluid_revmodel_update(rev); } void -fluid_revmodel_samplerate_change(fluid_revmodel_t* rev, fluid_real_t sample_rate) { - int i; - for (i = 0; i < numcombs;i++) { - fluid_comb_release(&rev->combL[i]); - fluid_comb_release(&rev->combR[i]); - } - for (i = 0; i < numallpasses; i++) { - fluid_allpass_release(&rev->allpassL[i]); - fluid_allpass_release(&rev->allpassR[i]); - } - fluid_set_revmodel_buffers(rev, sample_rate); +fluid_revmodel_samplerate_change(fluid_revmodel_t *rev, fluid_real_t sample_rate) +{ + int i; + + for(i = 0; i < numcombs; i++) + { + fluid_comb_release(&rev->combL[i]); + fluid_comb_release(&rev->combR[i]); + } + + for(i = 0; i < numallpasses; i++) + { + fluid_allpass_release(&rev->allpassL[i]); + fluid_allpass_release(&rev->allpassR[i]); + } + + fluid_set_revmodel_buffers(rev, sample_rate); } diff --git a/src/rvoice/fluid_rev.h b/src/rvoice/fluid_rev.h index 3b4c3b4c..69c00ea7 100644 --- a/src/rvoice/fluid_rev.h +++ b/src/rvoice/fluid_rev.h @@ -30,47 +30,48 @@ typedef struct _fluid_revmodel_t fluid_revmodel_t; /** Flags for fluid_revmodel_set() */ typedef enum { - FLUID_REVMODEL_SET_ROOMSIZE = 1 << 0, - FLUID_REVMODEL_SET_DAMPING = 1 << 1, - FLUID_REVMODEL_SET_WIDTH = 1 << 2, - FLUID_REVMODEL_SET_LEVEL = 1 << 3, - - /** Value for fluid_revmodel_set() which sets all reverb parameters. */ - FLUID_REVMODEL_SET_ALL = FLUID_REVMODEL_SET_LEVEL - | FLUID_REVMODEL_SET_WIDTH - | FLUID_REVMODEL_SET_DAMPING - | FLUID_REVMODEL_SET_ROOMSIZE, + FLUID_REVMODEL_SET_ROOMSIZE = 1 << 0, + FLUID_REVMODEL_SET_DAMPING = 1 << 1, + FLUID_REVMODEL_SET_WIDTH = 1 << 2, + FLUID_REVMODEL_SET_LEVEL = 1 << 3, + + /** Value for fluid_revmodel_set() which sets all reverb parameters. */ + FLUID_REVMODEL_SET_ALL = FLUID_REVMODEL_SET_LEVEL + | FLUID_REVMODEL_SET_WIDTH + | FLUID_REVMODEL_SET_DAMPING + | FLUID_REVMODEL_SET_ROOMSIZE, } fluid_revmodel_set_t; /* * reverb preset */ -typedef struct _fluid_revmodel_presets_t { - const char* name; - fluid_real_t roomsize; - fluid_real_t damp; - fluid_real_t width; - fluid_real_t level; +typedef struct _fluid_revmodel_presets_t +{ + const char *name; + fluid_real_t roomsize; + fluid_real_t damp; + fluid_real_t width; + fluid_real_t level; } fluid_revmodel_presets_t; /* * reverb */ -fluid_revmodel_t* new_fluid_revmodel(fluid_real_t sample_rate); -void delete_fluid_revmodel(fluid_revmodel_t* rev); +fluid_revmodel_t *new_fluid_revmodel(fluid_real_t sample_rate); +void delete_fluid_revmodel(fluid_revmodel_t *rev); -void fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out); +void fluid_revmodel_processmix(fluid_revmodel_t *rev, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out); -void fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, - fluid_real_t *left_out, fluid_real_t *right_out); +void fluid_revmodel_processreplace(fluid_revmodel_t *rev, fluid_real_t *in, + fluid_real_t *left_out, fluid_real_t *right_out); -void fluid_revmodel_reset(fluid_revmodel_t* rev); +void fluid_revmodel_reset(fluid_revmodel_t *rev); -void fluid_revmodel_set(fluid_revmodel_t* rev, int set, fluid_real_t roomsize, +void fluid_revmodel_set(fluid_revmodel_t *rev, int set, fluid_real_t roomsize, fluid_real_t damping, fluid_real_t width, fluid_real_t level); -void fluid_revmodel_samplerate_change(fluid_revmodel_t* rev, fluid_real_t sample_rate); +void fluid_revmodel_samplerate_change(fluid_revmodel_t *rev, fluid_real_t sample_rate); #endif /* _FLUID_REV_H */ diff --git a/src/rvoice/fluid_rvoice.c b/src/rvoice/fluid_rvoice.c index fa67f281..e7687116 100644 --- a/src/rvoice/fluid_rvoice.c +++ b/src/rvoice/fluid_rvoice.c @@ -23,82 +23,90 @@ #include "fluid_sys.h" -static void fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t* voice, unsigned int min_ticks); +static void fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t *voice, unsigned int min_ticks); /** * @return -1 if voice has finished, 0 if it's currently quiet, 1 otherwise */ static FLUID_INLINE int -fluid_rvoice_calc_amp(fluid_rvoice_t* voice) +fluid_rvoice_calc_amp(fluid_rvoice_t *voice) { - fluid_real_t target_amp; /* target amplitude */ + fluid_real_t target_amp; /* target amplitude */ - if (fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVDELAY) - return -1; /* The volume amplitude is in hold phase. No sound is produced. */ - - if (fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVATTACK) - { - /* the envelope is in the attack section: ramp linearly to max value. - * A positive modlfo_to_vol should increase volume (negative attenuation). - */ - target_amp = fluid_cb2amp (voice->dsp.attenuation) - * fluid_cb2amp (fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol) - * fluid_adsr_env_get_val(&voice->envlfo.volenv); - } - else - { - fluid_real_t amplitude_that_reaches_noise_floor; - fluid_real_t amp_max; - - target_amp = fluid_cb2amp (voice->dsp.attenuation) - * fluid_cb2amp (FLUID_PEAK_ATTENUATION * (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)) - + fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol); - - /* We turn off a voice, if the volume has dropped low enough. */ - - /* A voice can be turned off, when an estimate for the volume - * (upper bound) falls below that volume, that will drop the - * sample below the noise floor. - */ - - /* If the loop amplitude is known, we can use it if the voice loop is within - * the sample loop - */ - - /* Is the playing pointer already in the loop? */ - if (voice->dsp.has_looped) - amplitude_that_reaches_noise_floor = voice->dsp.amplitude_that_reaches_noise_floor_loop; - else - amplitude_that_reaches_noise_floor = voice->dsp.amplitude_that_reaches_noise_floor_nonloop; - - /* voice->attenuation_min is a lower boundary for the attenuation - * now and in the future (possibly 0 in the worst case). Now the - * amplitude of sample and volenv cannot exceed amp_max (since - * volenv_val can only drop): - */ - - amp_max = fluid_cb2amp (voice->dsp.min_attenuation_cB) * - fluid_adsr_env_get_val(&voice->envlfo.volenv); - - /* And if amp_max is already smaller than the known amplitude, - * which will attenuate the sample below the noise floor, then we - * can safely turn off the voice. Duh. */ - if (amp_max < amplitude_that_reaches_noise_floor) + if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVDELAY) { - return 0; + return -1; /* The volume amplitude is in hold phase. No sound is produced. */ } - } - /* Volume increment to go from voice->amp to target_amp in FLUID_BUFSIZE steps */ - voice->dsp.amp_incr = (target_amp - voice->dsp.amp) / FLUID_BUFSIZE; + if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVATTACK) + { + /* the envelope is in the attack section: ramp linearly to max value. + * A positive modlfo_to_vol should increase volume (negative attenuation). + */ + target_amp = fluid_cb2amp(voice->dsp.attenuation) + * fluid_cb2amp(fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol) + * fluid_adsr_env_get_val(&voice->envlfo.volenv); + } + else + { + fluid_real_t amplitude_that_reaches_noise_floor; + fluid_real_t amp_max; - fluid_check_fpe ("voice_write amplitude calculation"); + target_amp = fluid_cb2amp(voice->dsp.attenuation) + * fluid_cb2amp(FLUID_PEAK_ATTENUATION * (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)) + + fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol); - /* no volume and not changing? - No need to process */ - if ((voice->dsp.amp == 0.0f) && (voice->dsp.amp_incr == 0.0f)) - return -1; + /* We turn off a voice, if the volume has dropped low enough. */ - return 1; + /* A voice can be turned off, when an estimate for the volume + * (upper bound) falls below that volume, that will drop the + * sample below the noise floor. + */ + + /* If the loop amplitude is known, we can use it if the voice loop is within + * the sample loop + */ + + /* Is the playing pointer already in the loop? */ + if(voice->dsp.has_looped) + { + amplitude_that_reaches_noise_floor = voice->dsp.amplitude_that_reaches_noise_floor_loop; + } + else + { + amplitude_that_reaches_noise_floor = voice->dsp.amplitude_that_reaches_noise_floor_nonloop; + } + + /* voice->attenuation_min is a lower boundary for the attenuation + * now and in the future (possibly 0 in the worst case). Now the + * amplitude of sample and volenv cannot exceed amp_max (since + * volenv_val can only drop): + */ + + amp_max = fluid_cb2amp(voice->dsp.min_attenuation_cB) * + fluid_adsr_env_get_val(&voice->envlfo.volenv); + + /* And if amp_max is already smaller than the known amplitude, + * which will attenuate the sample below the noise floor, then we + * can safely turn off the voice. Duh. */ + if(amp_max < amplitude_that_reaches_noise_floor) + { + return 0; + } + } + + /* Volume increment to go from voice->amp to target_amp in FLUID_BUFSIZE steps */ + voice->dsp.amp_incr = (target_amp - voice->dsp.amp) / FLUID_BUFSIZE; + + fluid_check_fpe("voice_write amplitude calculation"); + + /* no volume and not changing? - No need to process */ + if((voice->dsp.amp == 0.0f) && (voice->dsp.amp_incr == 0.0f)) + { + return -1; + } + + return 1; } @@ -116,136 +124,164 @@ fluid_rvoice_calc_amp(fluid_rvoice_t* voice) * TODO: Investigate whether this can be moved from rvoice to voice. */ static void -fluid_rvoice_check_sample_sanity(fluid_rvoice_t* voice) +fluid_rvoice_check_sample_sanity(fluid_rvoice_t *voice) { - int min_index_nonloop=(int) voice->dsp.sample->start; - int max_index_nonloop=(int) voice->dsp.sample->end; + int min_index_nonloop = (int) voice->dsp.sample->start; + int max_index_nonloop = (int) voice->dsp.sample->end; /* make sure we have enough samples surrounding the loop */ - int min_index_loop=(int) voice->dsp.sample->start + FLUID_MIN_LOOP_PAD; - int max_index_loop=(int) voice->dsp.sample->end - FLUID_MIN_LOOP_PAD + 1; /* 'end' is last valid sample, loopend can be + 1 */ + int min_index_loop = (int) voice->dsp.sample->start + FLUID_MIN_LOOP_PAD; + int max_index_loop = (int) voice->dsp.sample->end - FLUID_MIN_LOOP_PAD + 1; /* 'end' is last valid sample, loopend can be + 1 */ fluid_check_fpe("voice_check_sample_sanity start"); #if 0 - printf("Sample from %i to %i\n",voice->dsp.sample->start, voice->dsp.sample->end); - printf("Sample loop from %i %i\n",voice->dsp.sample->loopstart, voice->dsp.sample->loopend); + printf("Sample from %i to %i\n", voice->dsp.sample->start, voice->dsp.sample->end); + printf("Sample loop from %i %i\n", voice->dsp.sample->loopstart, voice->dsp.sample->loopend); printf("Playback from %i to %i\n", voice->dsp.start, voice->dsp.end); - printf("Playback loop from %i to %i\n",voice->dsp.loopstart, voice->dsp.loopend); + printf("Playback loop from %i to %i\n", voice->dsp.loopstart, voice->dsp.loopend); #endif /* Keep the start point within the sample data */ - if (voice->dsp.start < min_index_nonloop){ - voice->dsp.start = min_index_nonloop; - } else if (voice->dsp.start > max_index_nonloop){ - voice->dsp.start = max_index_nonloop; + if(voice->dsp.start < min_index_nonloop) + { + voice->dsp.start = min_index_nonloop; + } + else if(voice->dsp.start > max_index_nonloop) + { + voice->dsp.start = max_index_nonloop; } /* Keep the end point within the sample data */ - if (voice->dsp.end < min_index_nonloop){ - voice->dsp.end = min_index_nonloop; - } else if (voice->dsp.end > max_index_nonloop){ - voice->dsp.end = max_index_nonloop; + if(voice->dsp.end < min_index_nonloop) + { + voice->dsp.end = min_index_nonloop; + } + else if(voice->dsp.end > max_index_nonloop) + { + voice->dsp.end = max_index_nonloop; } /* Keep start and end point in the right order */ - if (voice->dsp.start > voice->dsp.end){ - int temp = voice->dsp.start; - voice->dsp.start = voice->dsp.end; - voice->dsp.end = temp; - /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of start / end points!"); */ + if(voice->dsp.start > voice->dsp.end) + { + int temp = voice->dsp.start; + voice->dsp.start = voice->dsp.end; + voice->dsp.end = temp; + /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of start / end points!"); */ } /* Zero length? */ - if (voice->dsp.start == voice->dsp.end){ - fluid_rvoice_voiceoff(voice, NULL); - return; + if(voice->dsp.start == voice->dsp.end) + { + fluid_rvoice_voiceoff(voice, NULL); + return; } - if ((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE) - || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE)) { - /* Keep the loop start point within the sample data */ - if (voice->dsp.loopstart < min_index_loop){ - voice->dsp.loopstart = min_index_loop; - } else if (voice->dsp.loopstart > max_index_loop){ - voice->dsp.loopstart = max_index_loop; - } + if((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE) + || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE)) + { + /* Keep the loop start point within the sample data */ + if(voice->dsp.loopstart < min_index_loop) + { + voice->dsp.loopstart = min_index_loop; + } + else if(voice->dsp.loopstart > max_index_loop) + { + voice->dsp.loopstart = max_index_loop; + } - /* Keep the loop end point within the sample data */ - if (voice->dsp.loopend < min_index_loop){ - voice->dsp.loopend = min_index_loop; - } else if (voice->dsp.loopend > max_index_loop){ - voice->dsp.loopend = max_index_loop; - } + /* Keep the loop end point within the sample data */ + if(voice->dsp.loopend < min_index_loop) + { + voice->dsp.loopend = min_index_loop; + } + else if(voice->dsp.loopend > max_index_loop) + { + voice->dsp.loopend = max_index_loop; + } - /* Keep loop start and end point in the right order */ - if (voice->dsp.loopstart > voice->dsp.loopend){ - int temp = voice->dsp.loopstart; - voice->dsp.loopstart = voice->dsp.loopend; - voice->dsp.loopend = temp; - /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of loop points!"); */ - } + /* Keep loop start and end point in the right order */ + if(voice->dsp.loopstart > voice->dsp.loopend) + { + int temp = voice->dsp.loopstart; + voice->dsp.loopstart = voice->dsp.loopend; + voice->dsp.loopend = temp; + /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of loop points!"); */ + } - /* Loop too short? Then don't loop. */ - if (voice->dsp.loopend < voice->dsp.loopstart + FLUID_MIN_LOOP_SIZE){ - voice->dsp.samplemode = FLUID_UNLOOPED; - } + /* Loop too short? Then don't loop. */ + if(voice->dsp.loopend < voice->dsp.loopstart + FLUID_MIN_LOOP_SIZE) + { + voice->dsp.samplemode = FLUID_UNLOOPED; + } - /* The loop points may have changed. Obtain a new estimate for the loop volume. */ - /* Is the voice loop within the sample loop? */ - if ((int)voice->dsp.loopstart >= (int)voice->dsp.sample->loopstart - && (int)voice->dsp.loopend <= (int)voice->dsp.sample->loopend){ - /* Is there a valid peak amplitude available for the loop, and can we use it? */ - if (voice->dsp.sample->amplitude_that_reaches_noise_floor_is_valid && voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE){ - voice->dsp.amplitude_that_reaches_noise_floor_loop=voice->dsp.sample->amplitude_that_reaches_noise_floor / voice->dsp.synth_gain; - } else { - /* Worst case */ - voice->dsp.amplitude_that_reaches_noise_floor_loop=voice->dsp.amplitude_that_reaches_noise_floor_nonloop; - }; - }; + /* The loop points may have changed. Obtain a new estimate for the loop volume. */ + /* Is the voice loop within the sample loop? */ + if((int)voice->dsp.loopstart >= (int)voice->dsp.sample->loopstart + && (int)voice->dsp.loopend <= (int)voice->dsp.sample->loopend) + { + /* Is there a valid peak amplitude available for the loop, and can we use it? */ + if(voice->dsp.sample->amplitude_that_reaches_noise_floor_is_valid && voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE) + { + voice->dsp.amplitude_that_reaches_noise_floor_loop = voice->dsp.sample->amplitude_that_reaches_noise_floor / voice->dsp.synth_gain; + } + else + { + /* Worst case */ + voice->dsp.amplitude_that_reaches_noise_floor_loop = voice->dsp.amplitude_that_reaches_noise_floor_nonloop; + }; + }; } /* if sample mode is looped */ /* Run startup specific code (only once, when the voice is started) */ - if (voice->dsp.check_sample_sanity_flag & FLUID_SAMPLESANITY_STARTUP){ - if (max_index_loop - min_index_loop < FLUID_MIN_LOOP_SIZE){ - if ((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE) - || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE)){ - voice->dsp.samplemode = FLUID_UNLOOPED; - } - } + if(voice->dsp.check_sample_sanity_flag & FLUID_SAMPLESANITY_STARTUP) + { + if(max_index_loop - min_index_loop < FLUID_MIN_LOOP_SIZE) + { + if((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE) + || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE)) + { + voice->dsp.samplemode = FLUID_UNLOOPED; + } + } - /* Set the initial phase of the voice (using the result from the - start offset modulators). */ - fluid_phase_set_int(voice->dsp.phase, voice->dsp.start); + /* Set the initial phase of the voice (using the result from the + start offset modulators). */ + fluid_phase_set_int(voice->dsp.phase, voice->dsp.start); } /* if startup */ /* Is this voice run in loop mode, or does it run straight to the end of the waveform data? */ - if (((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE) && - (fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE)) - || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE)) { - /* Yes, it will loop as soon as it reaches the loop point. In - * this case we must prevent, that the playback pointer (phase) - * happens to end up beyond the 2nd loop point, because the - * point has moved. The DSP algorithm is unable to cope with - * that situation. So if the phase is beyond the 2nd loop - * point, set it to the start of the loop. No way to avoid some - * noise here. Note: If the sample pointer ends up -before the - * first loop point- instead, then the DSP loop will just play - * the sample, enter the loop and proceed as expected => no - * actions required. - */ - int index_in_sample = fluid_phase_index(voice->dsp.phase); - if (index_in_sample >= voice->dsp.loopend){ - /* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Phase after 2nd loop point!"); */ - fluid_phase_set_int(voice->dsp.phase, voice->dsp.loopstart); - } + if(((voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE) && + (fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE)) + || (voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE)) + { + /* Yes, it will loop as soon as it reaches the loop point. In + * this case we must prevent, that the playback pointer (phase) + * happens to end up beyond the 2nd loop point, because the + * point has moved. The DSP algorithm is unable to cope with + * that situation. So if the phase is beyond the 2nd loop + * point, set it to the start of the loop. No way to avoid some + * noise here. Note: If the sample pointer ends up -before the + * first loop point- instead, then the DSP loop will just play + * the sample, enter the loop and proceed as expected => no + * actions required. + */ + int index_in_sample = fluid_phase_index(voice->dsp.phase); + + if(index_in_sample >= voice->dsp.loopend) + { + /* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Phase after 2nd loop point!"); */ + fluid_phase_set_int(voice->dsp.phase, voice->dsp.loopstart); + } } -/* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Sample from %i to %i, loop from %i to %i", voice->dsp.start, voice->dsp.end, voice->dsp.loopstart, voice->dsp.loopend); */ + + /* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Sample from %i to %i, loop from %i to %i", voice->dsp.start, voice->dsp.end, voice->dsp.loopstart, voice->dsp.loopend); */ /* Sample sanity has been assured. Don't check again, until some sample parameter is changed by modulation. */ - voice->dsp.check_sample_sanity_flag=0; + voice->dsp.check_sample_sanity_flag = 0; #if 0 printf("Sane? playback loop from %i to %i\n", voice->dsp.loopstart, voice->dsp.loopend); #endif @@ -258,337 +294,394 @@ fluid_rvoice_check_sample_sanity(fluid_rvoice_t* voice) * * @param voice rvoice to synthesize * @param dsp_buf Audio buffer to synthesize to (#FLUID_BUFSIZE in length) - * @return Count of samples written to dsp_buf. (-1 means voice is currently + * @return Count of samples written to dsp_buf. (-1 means voice is currently * quiet, 0 .. #FLUID_BUFSIZE-1 means voice finished.) * * Panning, reverb and chorus are processed separately. The dsp interpolation * routine is in (fluid_rvoice_dsp.c). */ int -fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf) +fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf) { - int ticks = voice->envlfo.ticks; - int count, is_looping; + int ticks = voice->envlfo.ticks; + int count, is_looping; - /******************* sample sanity check **********/ + /******************* sample sanity check **********/ - if (!voice->dsp.sample) - return 0; - if (voice->dsp.check_sample_sanity_flag) - fluid_rvoice_check_sample_sanity(voice); + if(!voice->dsp.sample) + { + return 0; + } - /******************* noteoff check ****************/ + if(voice->dsp.check_sample_sanity_flag) + { + fluid_rvoice_check_sample_sanity(voice); + } - if (voice->envlfo.noteoff_ticks != 0 && - voice->envlfo.ticks >= voice->envlfo.noteoff_ticks) { - fluid_rvoice_noteoff_LOCAL(voice, 0); - } + /******************* noteoff check ****************/ - voice->envlfo.ticks += FLUID_BUFSIZE; + if(voice->envlfo.noteoff_ticks != 0 && + voice->envlfo.ticks >= voice->envlfo.noteoff_ticks) + { + fluid_rvoice_noteoff_LOCAL(voice, 0); + } - /******************* vol env **********************/ + voice->envlfo.ticks += FLUID_BUFSIZE; - fluid_adsr_env_calc(&voice->envlfo.volenv, 1); - fluid_check_fpe ("voice_write vol env"); - if (fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVFINISHED) - return 0; + /******************* vol env **********************/ - /******************* mod env **********************/ + fluid_adsr_env_calc(&voice->envlfo.volenv, 1); + fluid_check_fpe("voice_write vol env"); - fluid_adsr_env_calc(&voice->envlfo.modenv, 0); - fluid_check_fpe ("voice_write mod env"); + if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVFINISHED) + { + return 0; + } - /******************* lfo **********************/ + /******************* mod env **********************/ - fluid_lfo_calc(&voice->envlfo.modlfo, ticks); - fluid_check_fpe ("voice_write mod LFO"); - fluid_lfo_calc(&voice->envlfo.viblfo, ticks); - fluid_check_fpe ("voice_write vib LFO"); + fluid_adsr_env_calc(&voice->envlfo.modenv, 0); + fluid_check_fpe("voice_write mod env"); - /******************* amplitude **********************/ + /******************* lfo **********************/ - count = fluid_rvoice_calc_amp(voice); - if (count <= 0) - return count; + fluid_lfo_calc(&voice->envlfo.modlfo, ticks); + fluid_check_fpe("voice_write mod LFO"); + fluid_lfo_calc(&voice->envlfo.viblfo, ticks); + fluid_check_fpe("voice_write vib LFO"); - /******************* phase **********************/ + /******************* amplitude **********************/ - /* Calculate the number of samples, that the DSP loop advances - * through the original waveform with each step in the output - * buffer. It is the ratio between the frequencies of original - * waveform and output waveform.*/ - voice->dsp.phase_incr = fluid_ct2hz_real(voice->dsp.pitch + - voice->dsp.pitchoffset + - fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_pitch - + fluid_lfo_get_val(&voice->envlfo.viblfo) * voice->envlfo.viblfo_to_pitch - + fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_pitch) - / voice->dsp.root_pitch_hz; + count = fluid_rvoice_calc_amp(voice); - /******************* portamento ****************/ - /* pitchoffset is updated if enabled. - Pitchoffset will be added to dsp pitch at next phase calculation time */ + if(count <= 0) + { + return count; + } - /* In most cases portamento will be disabled. Thus first verify that portamento is - * enabled before updating pitchoffset and before disabling portamento when necessary, - * in order to keep the performance loss at minimum. - * If the algorithm would first update pitchoffset and then verify if portamento - * needs to be disabled, there would be a significant performance drop on a x87 FPU - */ - if (voice->dsp.pitchinc > 0.0f) - { /* portamento is enabled, so update pitchoffset */ - voice->dsp.pitchoffset += voice->dsp.pitchinc; - /* when pitchoffset reaches 0.0f, portamento is disabled */ - if (voice->dsp.pitchoffset > 0.0f) - voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f; - } - else if (voice->dsp.pitchinc < 0.0f) - { /* portamento is enabled, so update pitchoffset */ - voice->dsp.pitchoffset += voice->dsp.pitchinc; - /* when pitchoffset reaches 0.0f, portamento is disabled */ - if (voice->dsp.pitchoffset < 0.0f) - voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f; - } - - fluid_check_fpe ("voice_write phase calculation"); + /******************* phase **********************/ - /* if phase_incr is not advancing, set it to the minimum fraction value (prevent stuckage) */ - if (voice->dsp.phase_incr == 0) voice->dsp.phase_incr = 1; + /* Calculate the number of samples, that the DSP loop advances + * through the original waveform with each step in the output + * buffer. It is the ratio between the frequencies of original + * waveform and output waveform.*/ + voice->dsp.phase_incr = fluid_ct2hz_real(voice->dsp.pitch + + voice->dsp.pitchoffset + + fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_pitch + + fluid_lfo_get_val(&voice->envlfo.viblfo) * voice->envlfo.viblfo_to_pitch + + fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_pitch) + / voice->dsp.root_pitch_hz; - /* voice is currently looping? */ - is_looping = voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE - || (voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE - && fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE); + /******************* portamento ****************/ + /* pitchoffset is updated if enabled. + Pitchoffset will be added to dsp pitch at next phase calculation time */ - /*********************** run the dsp chain ************************ - * The sample is mixed with the output buffer. - * The buffer has to be filled from 0 to FLUID_BUFSIZE-1. - * Depending on the position in the loop and the loop size, this - * may require several runs. */ + /* In most cases portamento will be disabled. Thus first verify that portamento is + * enabled before updating pitchoffset and before disabling portamento when necessary, + * in order to keep the performance loss at minimum. + * If the algorithm would first update pitchoffset and then verify if portamento + * needs to be disabled, there would be a significant performance drop on a x87 FPU + */ + if(voice->dsp.pitchinc > 0.0f) + { + /* portamento is enabled, so update pitchoffset */ + voice->dsp.pitchoffset += voice->dsp.pitchinc; - switch (voice->dsp.interp_method) - { + /* when pitchoffset reaches 0.0f, portamento is disabled */ + if(voice->dsp.pitchoffset > 0.0f) + { + voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f; + } + } + else if(voice->dsp.pitchinc < 0.0f) + { + /* portamento is enabled, so update pitchoffset */ + voice->dsp.pitchoffset += voice->dsp.pitchinc; + + /* when pitchoffset reaches 0.0f, portamento is disabled */ + if(voice->dsp.pitchoffset < 0.0f) + { + voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f; + } + } + + fluid_check_fpe("voice_write phase calculation"); + + /* if phase_incr is not advancing, set it to the minimum fraction value (prevent stuckage) */ + if(voice->dsp.phase_incr == 0) + { + voice->dsp.phase_incr = 1; + } + + /* voice is currently looping? */ + is_looping = voice->dsp.samplemode == FLUID_LOOP_DURING_RELEASE + || (voice->dsp.samplemode == FLUID_LOOP_UNTIL_RELEASE + && fluid_adsr_env_get_section(&voice->envlfo.volenv) < FLUID_VOICE_ENVRELEASE); + + /*********************** run the dsp chain ************************ + * The sample is mixed with the output buffer. + * The buffer has to be filled from 0 to FLUID_BUFSIZE-1. + * Depending on the position in the loop and the loop size, this + * may require several runs. */ + + switch(voice->dsp.interp_method) + { case FLUID_INTERP_NONE: - count = fluid_rvoice_dsp_interpolate_none (&voice->dsp, dsp_buf, is_looping); - break; + count = fluid_rvoice_dsp_interpolate_none(&voice->dsp, dsp_buf, is_looping); + break; + case FLUID_INTERP_LINEAR: - count = fluid_rvoice_dsp_interpolate_linear (&voice->dsp, dsp_buf, is_looping); - break; + count = fluid_rvoice_dsp_interpolate_linear(&voice->dsp, dsp_buf, is_looping); + break; + case FLUID_INTERP_4THORDER: default: - count = fluid_rvoice_dsp_interpolate_4th_order (&voice->dsp, dsp_buf, is_looping); - break; + count = fluid_rvoice_dsp_interpolate_4th_order(&voice->dsp, dsp_buf, is_looping); + break; + case FLUID_INTERP_7THORDER: - count = fluid_rvoice_dsp_interpolate_7th_order (&voice->dsp, dsp_buf, is_looping); - break; - } - fluid_check_fpe ("voice_write interpolation"); - if (count == 0) + count = fluid_rvoice_dsp_interpolate_7th_order(&voice->dsp, dsp_buf, is_looping); + break; + } + + fluid_check_fpe("voice_write interpolation"); + + if(count == 0) + { + return count; + } + + /*************** resonant filter ******************/ + + fluid_iir_filter_calc(&voice->resonant_filter, voice->dsp.output_rate, + fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_fc + + fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_fc); + + fluid_iir_filter_apply(&voice->resonant_filter, dsp_buf, count); + + /* additional custom filter - only uses the fixed modulator, no lfos... */ + fluid_iir_filter_calc(&voice->resonant_custom_filter, voice->dsp.output_rate, 0); + fluid_iir_filter_apply(&voice->resonant_custom_filter, dsp_buf, count); + return count; - - /*************** resonant filter ******************/ - - fluid_iir_filter_calc(&voice->resonant_filter, voice->dsp.output_rate, - fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_fc + - fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_fc); - - fluid_iir_filter_apply(&voice->resonant_filter, dsp_buf, count); - - /* additional custom filter - only uses the fixed modulator, no lfos... */ - fluid_iir_filter_calc(&voice->resonant_custom_filter, voice->dsp.output_rate, 0); - fluid_iir_filter_apply(&voice->resonant_custom_filter, dsp_buf, count); - - return count; } /** * Initialize buffers up to (and including) bufnum */ static int -fluid_rvoice_buffers_check_bufnum(fluid_rvoice_buffers_t* buffers, unsigned int bufnum) +fluid_rvoice_buffers_check_bufnum(fluid_rvoice_buffers_t *buffers, unsigned int bufnum) { - unsigned int i; + unsigned int i; - if (bufnum < buffers->count) return FLUID_OK; - if (bufnum >= FLUID_RVOICE_MAX_BUFS) return FLUID_FAILED; + if(bufnum < buffers->count) + { + return FLUID_OK; + } - for (i = buffers->count; i <= bufnum; i++) { - buffers->bufs[i].amp = 0.0f; - } - buffers->count = bufnum+1; - return FLUID_OK; + if(bufnum >= FLUID_RVOICE_MAX_BUFS) + { + return FLUID_FAILED; + } + + for(i = buffers->count; i <= bufnum; i++) + { + buffers->bufs[i].amp = 0.0f; + } + + buffers->count = bufnum + 1; + return FLUID_OK; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp) { - fluid_rvoice_buffers_t* buffers = obj; - unsigned int bufnum = param[0].i; - fluid_real_t value = param[1].real; - - if (fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK) - return; - buffers->bufs[bufnum].amp = value; + fluid_rvoice_buffers_t *buffers = obj; + unsigned int bufnum = param[0].i; + fluid_real_t value = param[1].real; + + if(fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK) + { + return; + } + + buffers->bufs[bufnum].amp = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping) { - fluid_rvoice_buffers_t* buffers = obj; - unsigned int bufnum = param[0].i; - int mapping = param[1].i; - - if (fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK) - return; - buffers->bufs[bufnum].mapping = mapping; + fluid_rvoice_buffers_t *buffers = obj; + unsigned int bufnum = param[0].i; + int mapping = param[1].i; + + if(fluid_rvoice_buffers_check_bufnum(buffers, bufnum) != FLUID_OK) + { + return; + } + + buffers->bufs[bufnum].mapping = mapping; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_reset) { - fluid_rvoice_t* voice = obj; - - voice->dsp.has_looped = 0; - voice->envlfo.ticks = 0; - voice->envlfo.noteoff_ticks = 0; - voice->dsp.amp = 0.0f; /* The last value of the volume envelope, used to + fluid_rvoice_t *voice = obj; + + voice->dsp.has_looped = 0; + voice->envlfo.ticks = 0; + voice->envlfo.noteoff_ticks = 0; + voice->dsp.amp = 0.0f; /* The last value of the volume envelope, used to calculate the volume increment during processing */ - /* legato initialization */ - voice->dsp.pitchoffset = 0.0; /* portamento initialization */ - voice->dsp.pitchinc = 0.0; - - /* mod env initialization*/ - fluid_adsr_env_reset(&voice->envlfo.modenv); + /* legato initialization */ + voice->dsp.pitchoffset = 0.0; /* portamento initialization */ + voice->dsp.pitchinc = 0.0; - /* vol env initialization */ - fluid_adsr_env_reset(&voice->envlfo.volenv); + /* mod env initialization*/ + fluid_adsr_env_reset(&voice->envlfo.modenv); - /* Fixme: Retrieve from any other existing - voice on this channel to keep LFOs in - unison? */ - fluid_lfo_reset(&voice->envlfo.viblfo); - fluid_lfo_reset(&voice->envlfo.modlfo); + /* vol env initialization */ + fluid_adsr_env_reset(&voice->envlfo.volenv); - /* Clear sample history in filter */ - fluid_iir_filter_reset(&voice->resonant_filter); - fluid_iir_filter_reset(&voice->resonant_custom_filter); + /* Fixme: Retrieve from any other existing + voice on this channel to keep LFOs in + unison? */ + fluid_lfo_reset(&voice->envlfo.viblfo); + fluid_lfo_reset(&voice->envlfo.modlfo); - /* Force setting of the phase at the first DSP loop run - * This cannot be done earlier, because it depends on modulators. - [DH] Is that comment really true? */ - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP; + /* Clear sample history in filter */ + fluid_iir_filter_reset(&voice->resonant_filter); + fluid_iir_filter_reset(&voice->resonant_custom_filter); + + /* Force setting of the phase at the first DSP loop run + * This cannot be done earlier, because it depends on modulators. + [DH] Is that comment really true? */ + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_noteoff) { - fluid_rvoice_t* rvoice = obj; + fluid_rvoice_t *rvoice = obj; unsigned int min_ticks = param[0].i; - + fluid_rvoice_noteoff_LOCAL(rvoice, min_ticks); } -static void -fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t* voice, unsigned int min_ticks) +static void +fluid_rvoice_noteoff_LOCAL(fluid_rvoice_t *voice, unsigned int min_ticks) { - if (min_ticks > voice->envlfo.ticks) { - /* Delay noteoff */ - voice->envlfo.noteoff_ticks = min_ticks; - return; - } - voice->envlfo.noteoff_ticks = 0; - - if (fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVATTACK) { - /* A voice is turned off during the attack section of the volume - * envelope. The attack section ramps up linearly with - * amplitude. The other sections use logarithmic scaling. Calculate new - * volenv_val to achieve equievalent amplitude during the release phase - * for seamless volume transition. - */ - if (fluid_adsr_env_get_val(&voice->envlfo.volenv) > 0){ - fluid_real_t lfo = fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol; - fluid_real_t amp = fluid_adsr_env_get_val(&voice->envlfo.volenv) * fluid_cb2amp(lfo); - fluid_real_t env_value = - ((-200 * log (amp) / log (10.0) - lfo) / FLUID_PEAK_ATTENUATION - 1); - fluid_clip (env_value, 0.0, 1.0); - fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value); + if(min_ticks > voice->envlfo.ticks) + { + /* Delay noteoff */ + voice->envlfo.noteoff_ticks = min_ticks; + return; } - } - fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVRELEASE); - fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVRELEASE); + + voice->envlfo.noteoff_ticks = 0; + + if(fluid_adsr_env_get_section(&voice->envlfo.volenv) == FLUID_VOICE_ENVATTACK) + { + /* A voice is turned off during the attack section of the volume + * envelope. The attack section ramps up linearly with + * amplitude. The other sections use logarithmic scaling. Calculate new + * volenv_val to achieve equievalent amplitude during the release phase + * for seamless volume transition. + */ + if(fluid_adsr_env_get_val(&voice->envlfo.volenv) > 0) + { + fluid_real_t lfo = fluid_lfo_get_val(&voice->envlfo.modlfo) * -voice->envlfo.modlfo_to_vol; + fluid_real_t amp = fluid_adsr_env_get_val(&voice->envlfo.volenv) * fluid_cb2amp(lfo); + fluid_real_t env_value = - ((-200 * log(amp) / log(10.0) - lfo) / FLUID_PEAK_ATTENUATION - 1); + fluid_clip(env_value, 0.0, 1.0); + fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value); + } + } + + fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVRELEASE); + fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVRELEASE); } /** * skips to Attack section - * - * Updates vol and attack data + * + * Updates vol and attack data * Correction on volume val to achieve equivalent amplitude at noteOn legato - * + * * @param voice the synthesis voice to be updated */ -static FLUID_INLINE void fluid_rvoice_local_retrigger_attack (fluid_rvoice_t* voice) +static FLUID_INLINE void fluid_rvoice_local_retrigger_attack(fluid_rvoice_t *voice) { - /* skips to Attack section */ - /* Once in Attack section, current count must be reset, to be sure - that the section will be not be prematurely finished. */ - fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVATTACK); - { - /* Correction on volume val to achieve equivalent amplitude at noteOn legato */ - fluid_env_data_t* env_data; - fluid_real_t peak = fluid_cb2amp (voice->dsp.attenuation); - fluid_real_t prev_peak = fluid_cb2amp (voice->dsp.prev_attenuation); - voice->envlfo.volenv.val = (voice->envlfo.volenv.val * prev_peak) / peak; - /* Correction on slope direction for Attack section */ - env_data = &voice->envlfo.volenv.data[FLUID_VOICE_ENVATTACK]; - if(voice->envlfo.volenv.val <=1.0f) - { /* slope attack for legato note needs to be positive from val up to 1 */ - env_data->increment = 1.0f / env_data->count; - env_data->min = -1.0f; env_data->max = 1.0f; - } - else - { /* slope attack for legato note needs to be negative: from val down to 1 */ - env_data->increment = -voice->envlfo.volenv.val / env_data->count; - env_data->min = 1.0f; env_data->max = voice->envlfo.volenv.val; - } - } + /* skips to Attack section */ + /* Once in Attack section, current count must be reset, to be sure + that the section will be not be prematurely finished. */ + fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVATTACK); + { + /* Correction on volume val to achieve equivalent amplitude at noteOn legato */ + fluid_env_data_t *env_data; + fluid_real_t peak = fluid_cb2amp(voice->dsp.attenuation); + fluid_real_t prev_peak = fluid_cb2amp(voice->dsp.prev_attenuation); + voice->envlfo.volenv.val = (voice->envlfo.volenv.val * prev_peak) / peak; + /* Correction on slope direction for Attack section */ + env_data = &voice->envlfo.volenv.data[FLUID_VOICE_ENVATTACK]; + + if(voice->envlfo.volenv.val <= 1.0f) + { + /* slope attack for legato note needs to be positive from val up to 1 */ + env_data->increment = 1.0f / env_data->count; + env_data->min = -1.0f; + env_data->max = 1.0f; + } + else + { + /* slope attack for legato note needs to be negative: from val down to 1 */ + env_data->increment = -voice->envlfo.volenv.val / env_data->count; + env_data->min = 1.0f; + env_data->max = voice->envlfo.volenv.val; + } + } } /** - * Used by legato Mode : multi_retrigger - * see fluid_synth_noteon_mono_legato_multi_retrigger() + * Used by legato Mode : multi_retrigger + * see fluid_synth_noteon_mono_legato_multi_retrigger() * @param voice the synthesis voice to be updated */ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack) { - fluid_rvoice_t* voice = obj; - int section = fluid_adsr_env_get_section(&voice->envlfo.volenv); - /*------------------------------------------------------------------------- - Section skip for volume envelope - --------------------------------------------------------------------------*/ - if (section >= FLUID_VOICE_ENVHOLD) - { - /* DECAY, SUSTAIN,RELEASE section use logarithmic scaling. Calculates new + fluid_rvoice_t *voice = obj; + int section = fluid_adsr_env_get_section(&voice->envlfo.volenv); + + /*------------------------------------------------------------------------- + Section skip for volume envelope + --------------------------------------------------------------------------*/ + if(section >= FLUID_VOICE_ENVHOLD) + { + /* DECAY, SUSTAIN,RELEASE section use logarithmic scaling. Calculates new volenv_val to achieve equivalent amplitude during the attack phase - for seamless volume transition. */ - fluid_real_t amp_cb, env_value; - amp_cb = FLUID_PEAK_ATTENUATION * - (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)); - env_value = fluid_cb2amp(amp_cb); /* a bit of optimization */ - fluid_clip (env_value, 0.0, 1.0); - fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value); - /* next, skips to Attack section */ - } - /* skips to Attack section from any section */ - /* Update vol and attack data */ - fluid_rvoice_local_retrigger_attack(voice); - /*------------------------------------------------------------------------- - Section skip for modulation envelope - --------------------------------------------------------------------------*/ - /* Skips from any section to ATTACK section */ - fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVATTACK); - /* Actually (v 1.1.6) all sections are linear, so there is no need to - correct val value. However soundfont 2.01/2.4 spec. says that Attack should - be convex (see issue #153 from Christian Collins). In the case Attack - section would be changed to a non linear shape it will be necessary to do - a correction for seamless val transition. Here is the place to do this */ + for seamless volume transition. */ + fluid_real_t amp_cb, env_value; + amp_cb = FLUID_PEAK_ATTENUATION * + (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv)); + env_value = fluid_cb2amp(amp_cb); /* a bit of optimization */ + fluid_clip(env_value, 0.0, 1.0); + fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value); + /* next, skips to Attack section */ + } + + /* skips to Attack section from any section */ + /* Update vol and attack data */ + fluid_rvoice_local_retrigger_attack(voice); + /*------------------------------------------------------------------------- + Section skip for modulation envelope + --------------------------------------------------------------------------*/ + /* Skips from any section to ATTACK section */ + fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVATTACK); + /* Actually (v 1.1.6) all sections are linear, so there is no need to + correct val value. However soundfont 2.01/2.4 spec. says that Attack should + be convex (see issue #153 from Christian Collins). In the case Attack + section would be changed to a non linear shape it will be necessary to do + a correction for seamless val transition. Here is the place to do this */ } /** @@ -601,200 +694,203 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_multi_retrigger_attack) * 1) To get continuous portamento between consecutive noteOn (n1,n2,n3...), * pitchoffset is accumulated in current dsp pitchoffset. * 2) And to get constant portamento duration, dsp pitch increment is updated. -*/ +*/ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_portamento) { - fluid_rvoice_t * voice = obj; + fluid_rvoice_t *voice = obj; unsigned int countinc = param[0].i; fluid_real_t pitchoffset = param[1].real; - - if (countinc) - { - voice->dsp.pitchoffset += pitchoffset; - voice->dsp.pitchinc = - voice->dsp.pitchoffset / countinc; - } - /* Then during the voice processing (in fluid_rvoice_write()), - dsp.pitchoffset will be incremented by dsp pitchinc. */ + + if(countinc) + { + voice->dsp.pitchoffset += pitchoffset; + voice->dsp.pitchinc = - voice->dsp.pitchoffset / countinc; + } + + /* Then during the voice processing (in fluid_rvoice_write()), + dsp.pitchoffset will be incremented by dsp pitchinc. */ } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_output_rate) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->dsp.output_rate = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->dsp.output_rate = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_interp_method) { - fluid_rvoice_t* voice = obj; - int value = param[0].i; - - voice->dsp.interp_method = value; + fluid_rvoice_t *voice = obj; + int value = param[0].i; + + voice->dsp.interp_method = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_root_pitch_hz) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->dsp.root_pitch_hz = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->dsp.root_pitch_hz = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_pitch) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->dsp.pitch = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->dsp.pitch = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_attenuation) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->dsp.prev_attenuation = voice->dsp.attenuation; - voice->dsp.attenuation = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->dsp.prev_attenuation = voice->dsp.attenuation; + voice->dsp.attenuation = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_min_attenuation_cB) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->dsp.min_attenuation_cB = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->dsp.min_attenuation_cB = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_viblfo_to_pitch) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->envlfo.viblfo_to_pitch = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->envlfo.viblfo_to_pitch = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_pitch) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->envlfo.modlfo_to_pitch = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->envlfo.modlfo_to_pitch = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_vol) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->envlfo.modlfo_to_vol = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->envlfo.modlfo_to_vol = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modlfo_to_fc) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->envlfo.modlfo_to_fc = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->envlfo.modlfo_to_fc = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_fc) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->envlfo.modenv_to_fc = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->envlfo.modenv_to_fc = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_modenv_to_pitch) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->envlfo.modenv_to_pitch = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; + + voice->envlfo.modenv_to_pitch = value; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_synth_gain) { - fluid_rvoice_t* voice = obj; - fluid_real_t value = param[0].real; - - voice->dsp.synth_gain = value; + fluid_rvoice_t *voice = obj; + fluid_real_t value = param[0].real; - /* For a looped sample, this value will be overwritten as soon as the - * loop parameters are initialized (they may depend on modulators). - * This value can be kept, it is a worst-case estimate. - */ - voice->dsp.amplitude_that_reaches_noise_floor_nonloop = FLUID_NOISE_FLOOR / value; - voice->dsp.amplitude_that_reaches_noise_floor_loop = FLUID_NOISE_FLOOR / value; - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; + voice->dsp.synth_gain = value; + + /* For a looped sample, this value will be overwritten as soon as the + * loop parameters are initialized (they may depend on modulators). + * This value can be kept, it is a worst-case estimate. + */ + voice->dsp.amplitude_that_reaches_noise_floor_nonloop = FLUID_NOISE_FLOOR / value; + voice->dsp.amplitude_that_reaches_noise_floor_loop = FLUID_NOISE_FLOOR / value; + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_start) { - fluid_rvoice_t* voice = obj; - int value = param[0].i; - - voice->dsp.start = value; - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; + fluid_rvoice_t *voice = obj; + int value = param[0].i; + + voice->dsp.start = value; + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_end) { - fluid_rvoice_t* voice = obj; - int value = param[0].i; - - voice->dsp.end = value; - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; + fluid_rvoice_t *voice = obj; + int value = param[0].i; + + voice->dsp.end = value; + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopstart) { - fluid_rvoice_t* voice = obj; - int value = param[0].i; - - voice->dsp.loopstart = value; - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; + fluid_rvoice_t *voice = obj; + int value = param[0].i; + + voice->dsp.loopstart = value; + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_loopend) { - fluid_rvoice_t* voice = obj; - int value = param[0].i; - - voice->dsp.loopend = value; - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; + fluid_rvoice_t *voice = obj; + int value = param[0].i; + + voice->dsp.loopend = value; + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_samplemode) { - fluid_rvoice_t* voice = obj; - enum fluid_loop value = param[0].i; - - voice->dsp.samplemode = value; - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; + fluid_rvoice_t *voice = obj; + enum fluid_loop value = param[0].i; + + voice->dsp.samplemode = value; + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_CHECK; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample) { - fluid_rvoice_t* voice = obj; - fluid_sample_t* value = param[0].ptr; - - voice->dsp.sample = value; - if (value) { - voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP; - } + fluid_rvoice_t *voice = obj; + fluid_sample_t *value = param[0].ptr; + + voice->dsp.sample = value; + + if(value) + { + voice->dsp.check_sample_sanity_flag |= FLUID_SAMPLESANITY_STARTUP; + } } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_voiceoff) { - fluid_rvoice_t* voice = obj; - - fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVFINISHED); - fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVFINISHED); + fluid_rvoice_t *voice = obj; + + fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVFINISHED); + fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVFINISHED); } diff --git a/src/rvoice/fluid_rvoice.h b/src/rvoice/fluid_rvoice.h index 2b81646a..bae3ac93 100644 --- a/src/rvoice/fluid_rvoice.h +++ b/src/rvoice/fluid_rvoice.h @@ -41,11 +41,12 @@ typedef struct _fluid_rvoice_t fluid_rvoice_t; */ #define FLUID_NOISE_FLOOR 2.e-7 -enum fluid_loop { - FLUID_UNLOOPED = 0, - FLUID_LOOP_DURING_RELEASE = 1, - FLUID_NOTUSED = 2, - FLUID_LOOP_UNTIL_RELEASE = 3 +enum fluid_loop +{ + FLUID_UNLOOPED = 0, + FLUID_LOOP_DURING_RELEASE = 1, + FLUID_NOTUSED = 2, + FLUID_LOOP_UNTIL_RELEASE = 3 }; /* @@ -54,27 +55,27 @@ enum fluid_loop { */ struct _fluid_rvoice_envlfo_t { - /* Note-off minimum length */ - unsigned int ticks; - unsigned int noteoff_ticks; + /* Note-off minimum length */ + unsigned int ticks; + unsigned int noteoff_ticks; - /* vol env */ - fluid_adsr_env_t volenv; + /* vol env */ + fluid_adsr_env_t volenv; - /* mod env */ - fluid_adsr_env_t modenv; - fluid_real_t modenv_to_fc; - fluid_real_t modenv_to_pitch; + /* mod env */ + fluid_adsr_env_t modenv; + fluid_real_t modenv_to_fc; + fluid_real_t modenv_to_pitch; - /* mod lfo */ - fluid_lfo_t modlfo; - fluid_real_t modlfo_to_fc; - fluid_real_t modlfo_to_pitch; - fluid_real_t modlfo_to_vol; + /* mod lfo */ + fluid_lfo_t modlfo; + fluid_real_t modlfo_to_fc; + fluid_real_t modlfo_to_pitch; + fluid_real_t modlfo_to_vol; - /* vib lfo */ - fluid_lfo_t viblfo; - fluid_real_t viblfo_to_pitch; + /* vib lfo */ + fluid_lfo_t viblfo; + fluid_real_t viblfo_to_pitch; }; /* @@ -82,52 +83,52 @@ struct _fluid_rvoice_envlfo_t */ struct _fluid_rvoice_dsp_t { - /* interpolation method, as in fluid_interp in fluidsynth.h */ - enum fluid_interp interp_method; - enum fluid_loop samplemode; - + /* interpolation method, as in fluid_interp in fluidsynth.h */ + enum fluid_interp interp_method; + enum fluid_loop samplemode; + /* Flag that is set as soon as the first loop is completed. */ - char has_looped; - + char has_looped; + /* Flag that initiates, that sample-related parameters have to be checked. */ - char check_sample_sanity_flag; - - fluid_sample_t* sample; + char check_sample_sanity_flag; - /* sample and loop start and end points (offset in sample memory). */ - int start; - int end; - int loopstart; - int loopend; /* Note: first point following the loop (superimposed on loopstart) */ + fluid_sample_t *sample; - /* Stuff needed for portamento calculations */ - fluid_real_t pitchoffset; /* the portamento range in midicents */ - fluid_real_t pitchinc; /* the portamento increment in midicents */ + /* sample and loop start and end points (offset in sample memory). */ + int start; + int end; + int loopstart; + int loopend; /* Note: first point following the loop (superimposed on loopstart) */ - /* Stuff needed for phase calculations */ + /* Stuff needed for portamento calculations */ + fluid_real_t pitchoffset; /* the portamento range in midicents */ + fluid_real_t pitchinc; /* the portamento increment in midicents */ - fluid_real_t pitch; /* the pitch in midicents */ - fluid_real_t root_pitch_hz; - fluid_real_t output_rate; + /* Stuff needed for phase calculations */ - /* Stuff needed for amplitude calculations */ + fluid_real_t pitch; /* the pitch in midicents */ + fluid_real_t root_pitch_hz; + fluid_real_t output_rate; - fluid_real_t attenuation; /* the attenuation in centibels */ - fluid_real_t prev_attenuation; /* the previous attenuation in centibels + /* Stuff needed for amplitude calculations */ + + fluid_real_t attenuation; /* the attenuation in centibels */ + fluid_real_t prev_attenuation; /* the previous attenuation in centibels used by fluid_rvoice_multi_retrigger_attack() */ - fluid_real_t min_attenuation_cB; /* Estimate on the smallest possible attenuation + fluid_real_t min_attenuation_cB; /* Estimate on the smallest possible attenuation * during the lifetime of the voice */ - fluid_real_t amplitude_that_reaches_noise_floor_nonloop; - fluid_real_t amplitude_that_reaches_noise_floor_loop; - fluid_real_t synth_gain; /* master gain */ + fluid_real_t amplitude_that_reaches_noise_floor_nonloop; + fluid_real_t amplitude_that_reaches_noise_floor_loop; + fluid_real_t synth_gain; /* master gain */ - /* Dynamic input to the interpolator below */ - - fluid_real_t amp; /* current linear amplitude */ - fluid_real_t amp_incr; /* amplitude increment value for the next FLUID_BUFSIZE samples */ + /* Dynamic input to the interpolator below */ - fluid_phase_t phase; /* the phase (current sample offset) of the sample wave */ - fluid_real_t phase_incr; /* the phase increment for the next FLUID_BUFSIZE samples */ + fluid_real_t amp; /* current linear amplitude */ + fluid_real_t amp_incr; /* amplitude increment value for the next FLUID_BUFSIZE samples */ + + fluid_phase_t phase; /* the phase (current sample offset) of the sample wave */ + fluid_real_t phase_incr; /* the phase increment for the next FLUID_BUFSIZE samples */ }; /* Currently left, right, reverb, chorus. To be changed if we @@ -139,11 +140,12 @@ struct _fluid_rvoice_dsp_t */ struct _fluid_rvoice_buffers_t { - unsigned int count; /* Number of records in "bufs" */ - struct { - fluid_real_t amp; - int mapping; /* Mapping to mixdown buffer index */ - } bufs[FLUID_RVOICE_MAX_BUFS]; + unsigned int count; /* Number of records in "bufs" */ + struct + { + fluid_real_t amp; + int mapping; /* Mapping to mixdown buffer index */ + } bufs[FLUID_RVOICE_MAX_BUFS]; }; @@ -152,15 +154,15 @@ struct _fluid_rvoice_buffers_t */ struct _fluid_rvoice_t { - fluid_rvoice_envlfo_t envlfo; - fluid_rvoice_dsp_t dsp; - fluid_iir_filter_t resonant_filter; /* IIR resonant dsp filter */ - fluid_iir_filter_t resonant_custom_filter; /* optional custom/general-purpose IIR resonant filter */ - fluid_rvoice_buffers_t buffers; + fluid_rvoice_envlfo_t envlfo; + fluid_rvoice_dsp_t dsp; + fluid_iir_filter_t resonant_filter; /* IIR resonant dsp filter */ + fluid_iir_filter_t resonant_custom_filter; /* optional custom/general-purpose IIR resonant filter */ + fluid_rvoice_buffers_t buffers; }; -int fluid_rvoice_write(fluid_rvoice_t* voice, fluid_real_t *dsp_buf); +int fluid_rvoice_write(fluid_rvoice_t *voice, fluid_real_t *dsp_buf); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping); @@ -191,11 +193,11 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_samplemode); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_set_sample); /* defined in fluid_rvoice_dsp.c */ -void fluid_rvoice_dsp_config (void); -int fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); -int fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); -int fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); -int fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); +void fluid_rvoice_dsp_config(void); +int fluid_rvoice_dsp_interpolate_none(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); +int fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); +int fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); +int fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int is_looping); /* @@ -203,20 +205,20 @@ int fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice, fluid_rea * least sig. 8 bit part in order to create a 24 bit sample. */ static FLUID_INLINE int32_t -fluid_rvoice_get_sample(const short int* dsp_msb, const char* dsp_lsb, unsigned int idx) +fluid_rvoice_get_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx) { /* cast sample to unsigned type, so we can safely shift and bitwise or * without relying on undefined behaviour (should never happen anyway ofc...) */ uint32_t msb = (uint32_t)dsp_msb[idx]; uint8_t lsb = 0U; - + /* most soundfonts have 16 bit samples, assume that it's unlikely we * experience 24 bit samples here */ if(FLUID_UNLIKELY(dsp_lsb != NULL)) { lsb = (uint8_t)dsp_lsb[idx]; } - + return (int32_t)((msb << 8) | lsb); } diff --git a/src/rvoice/fluid_rvoice_dsp.c b/src/rvoice/fluid_rvoice_dsp.c index 0214c3d7..8d9be34e 100644 --- a/src/rvoice/fluid_rvoice_dsp.c +++ b/src/rvoice/fluid_rvoice_dsp.c @@ -61,66 +61,72 @@ static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7]; /* Initializes interpolation tables */ -void fluid_rvoice_dsp_config (void) +void fluid_rvoice_dsp_config(void) { - int i, i2; - double x, v; - double i_shifted; + int i, i2; + double x, v; + double i_shifted; - /* Initialize the coefficients for the interpolation. The math comes - * from a mail, posted by Olli Niemitalo to the music-dsp mailing - * list (I found it in the music-dsp archives - * http://www.smartelectronix.com/musicdsp/). */ + /* Initialize the coefficients for the interpolation. The math comes + * from a mail, posted by Olli Niemitalo to the music-dsp mailing + * list (I found it in the music-dsp archives + * http://www.smartelectronix.com/musicdsp/). */ - for (i = 0; i < FLUID_INTERP_MAX; i++) - { - x = (double) i / (double) FLUID_INTERP_MAX; - - interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x))); - interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5)); - interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x))); - interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0)); - - interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x); - interp_coeff_linear[i][1] = (fluid_real_t)x; - } - - /* i: Offset in terms of whole samples */ - for (i = 0; i < SINC_INTERP_ORDER; i++) - { /* i2: Offset in terms of fractional samples ('subsamples') */ - for (i2 = 0; i2 < FLUID_INTERP_MAX; i2++) + for(i = 0; i < FLUID_INTERP_MAX; i++) { - /* center on middle of table */ - i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0) - + (double)i2 / (double)FLUID_INTERP_MAX; + x = (double) i / (double) FLUID_INTERP_MAX; - /* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */ - if (fabs (i_shifted) > 0.000001) - { - v = (fluid_real_t)sin (i_shifted * M_PI) / (M_PI * i_shifted); - /* Hamming window */ - v *= (fluid_real_t)0.5 * (1.0 + cos (2.0 * M_PI * i_shifted / (fluid_real_t)SINC_INTERP_ORDER)); - } - else v = 1.0; + interp_coeff[i][0] = (fluid_real_t)(x * (-0.5 + x * (1 - 0.5 * x))); + interp_coeff[i][1] = (fluid_real_t)(1.0 + x * x * (1.5 * x - 2.5)); + interp_coeff[i][2] = (fluid_real_t)(x * (0.5 + x * (2.0 - 1.5 * x))); + interp_coeff[i][3] = (fluid_real_t)(0.5 * x * x * (x - 1.0)); - sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v; + interp_coeff_linear[i][0] = (fluid_real_t)(1.0 - x); + interp_coeff_linear[i][1] = (fluid_real_t)x; + } + + /* i: Offset in terms of whole samples */ + for(i = 0; i < SINC_INTERP_ORDER; i++) + { + /* i2: Offset in terms of fractional samples ('subsamples') */ + for(i2 = 0; i2 < FLUID_INTERP_MAX; i2++) + { + /* center on middle of table */ + i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0) + + (double)i2 / (double)FLUID_INTERP_MAX; + + /* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */ + if(fabs(i_shifted) > 0.000001) + { + v = (fluid_real_t)sin(i_shifted * M_PI) / (M_PI * i_shifted); + /* Hamming window */ + v *= (fluid_real_t)0.5 * (1.0 + cos(2.0 * M_PI * i_shifted / (fluid_real_t)SINC_INTERP_ORDER)); + } + else + { + v = 1.0; + } + + sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v; + } } - } #if 0 - for (i = 0; i < FLUID_INTERP_MAX; i++) - { - printf ("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n", - i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i], - sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]); - } + + for(i = 0; i < FLUID_INTERP_MAX; i++) + { + printf("%d %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f %0.3f\n", + i, sinc_table7[0][i], sinc_table7[1][i], sinc_table7[2][i], + sinc_table7[3][i], sinc_table7[4][i], sinc_table7[5][i], sinc_table7[6][i]); + } + #endif - fluid_check_fpe("interpolation table calculation"); + fluid_check_fpe("interpolation table calculation"); } static FLUID_INLINE fluid_real_t -fluid_rvoice_get_float_sample(const short int* dsp_msb, const char* dsp_lsb, unsigned int idx) +fluid_rvoice_get_float_sample(const short int *dsp_msb, const char *dsp_lsb, unsigned int idx) { int32_t sample = fluid_rvoice_get_sample(dsp_msb, dsp_lsb, idx); return (fluid_real_t)sample; @@ -130,56 +136,62 @@ fluid_rvoice_get_float_sample(const short int* dsp_msb, const char* dsp_lsb, uns * the playback pointer. Questionable quality, but very * efficient. */ int -fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) +fluid_rvoice_dsp_interpolate_none(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) { - fluid_phase_t dsp_phase = voice->phase; - fluid_phase_t dsp_phase_incr; - short int *dsp_data = voice->sample->data; - char *dsp_data24 = voice->sample->data24; - fluid_real_t dsp_amp = voice->amp; - fluid_real_t dsp_amp_incr = voice->amp_incr; - unsigned int dsp_i = 0; - unsigned int dsp_phase_index; - unsigned int end_index; + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr; + short int *dsp_data = voice->sample->data; + char *dsp_data24 = voice->sample->data24; + fluid_real_t dsp_amp = voice->amp; + fluid_real_t dsp_amp_incr = voice->amp_incr; + unsigned int dsp_i = 0; + unsigned int dsp_phase_index; + unsigned int end_index; - /* Convert playback "speed" floating point value to phase index/fract */ - fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); - - end_index = looping ? voice->loopend - 1 : voice->end; + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float(dsp_phase_incr, voice->phase_incr); - while (1) - { - dsp_phase_index = fluid_phase_index_round (dsp_phase); /* round to nearest point */ + end_index = looping ? voice->loopend - 1 : voice->end; - /* interpolate sequence of sample points */ - for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + while(1) { - dsp_buf[dsp_i] = dsp_amp * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index); + dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */ - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index_round (dsp_phase); /* round to nearest point */ - dsp_amp += dsp_amp_incr; + /* interpolate sequence of sample points */ + for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + { + dsp_buf[dsp_i] = dsp_amp * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index_round(dsp_phase); /* round to nearest point */ + dsp_amp += dsp_amp_incr; + } + + /* break out if not looping (buffer may not be full) */ + if(!looping) + { + break; + } + + /* go back to loop start */ + if(dsp_phase_index > end_index) + { + fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart); + voice->has_looped = 1; + } + + /* break out if filled buffer */ + if(dsp_i >= FLUID_BUFSIZE) + { + break; + } } - /* break out if not looping (buffer may not be full) */ - if (!looping) break; + voice->phase = dsp_phase; + voice->amp = dsp_amp; - /* go back to loop start */ - if (dsp_phase_index > end_index) - { - fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart); - voice->has_looped = 1; - } - - /* break out if filled buffer */ - if (dsp_i >= FLUID_BUFSIZE) break; - } - - voice->phase = dsp_phase; - voice->amp = dsp_amp; - - return (dsp_i); + return (dsp_i); } /* Straight line interpolation. @@ -187,84 +199,99 @@ fluid_rvoice_dsp_interpolate_none (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUI * smaller if end of sample occurs). */ int -fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) +fluid_rvoice_dsp_interpolate_linear(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) { - fluid_phase_t dsp_phase = voice->phase; - fluid_phase_t dsp_phase_incr; - short int *dsp_data = voice->sample->data; - char *dsp_data24 = voice->sample->data24; - fluid_real_t dsp_amp = voice->amp; - fluid_real_t dsp_amp_incr = voice->amp_incr; - unsigned int dsp_i = 0; - unsigned int dsp_phase_index; - unsigned int end_index; - fluid_real_t point; - const fluid_real_t *FLUID_RESTRICT coeffs; + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr; + short int *dsp_data = voice->sample->data; + char *dsp_data24 = voice->sample->data24; + fluid_real_t dsp_amp = voice->amp; + fluid_real_t dsp_amp_incr = voice->amp_incr; + unsigned int dsp_i = 0; + unsigned int dsp_phase_index; + unsigned int end_index; + fluid_real_t point; + const fluid_real_t *FLUID_RESTRICT coeffs; - /* Convert playback "speed" floating point value to phase index/fract */ - fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float(dsp_phase_incr, voice->phase_incr); - /* last index before 2nd interpolation point must be specially handled */ - end_index = (looping ? voice->loopend - 1 : voice->end) - 1; + /* last index before 2nd interpolation point must be specially handled */ + end_index = (looping ? voice->loopend - 1 : voice->end) - 1; - /* 2nd interpolation point to use at end of loop or sample */ - if (looping) point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); /* loop start */ - else point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); /* duplicate end for samples no longer looping */ - - while (1) - { - dsp_phase_index = fluid_phase_index (dsp_phase); - - /* interpolate the sequence of sample points */ - for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + /* 2nd interpolation point to use at end of loop or sample */ + if(looping) { - coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)]; - dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1)); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; + point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); /* loop start */ + } + else + { + point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); /* duplicate end for samples no longer looping */ } - /* break out if buffer filled */ - if (dsp_i >= FLUID_BUFSIZE) break; - - end_index++; /* we're now interpolating the last point */ - - /* interpolate within last point */ - for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + while(1) { - coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)]; - dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[1] * point); + dsp_phase_index = fluid_phase_index(dsp_phase); - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; /* increment amplitude */ + /* interpolate the sequence of sample points */ + for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + { + coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1)); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + /* break out if buffer filled */ + if(dsp_i >= FLUID_BUFSIZE) + { + break; + } + + end_index++; /* we're now interpolating the last point */ + + /* interpolate within last point */ + for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[1] * point); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; /* increment amplitude */ + } + + if(!looping) + { + break; /* break out if not looping (end of sample) */ + } + + /* go back to loop start (if past */ + if(dsp_phase_index > end_index) + { + fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart); + voice->has_looped = 1; + } + + /* break out if filled buffer */ + if(dsp_i >= FLUID_BUFSIZE) + { + break; + } + + end_index--; /* set end back to second to last sample point */ } - if (!looping) break; /* break out if not looping (end of sample) */ + voice->phase = dsp_phase; + voice->amp = dsp_amp; - /* go back to loop start (if past */ - if (dsp_phase_index > end_index) - { - fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart); - voice->has_looped = 1; - } - - /* break out if filled buffer */ - if (dsp_i >= FLUID_BUFSIZE) break; - - end_index--; /* set end back to second to last sample point */ - } - - voice->phase = dsp_phase; - voice->amp = dsp_amp; - - return (dsp_i); + return (dsp_i); } /* 4th order (cubic) interpolation. @@ -272,149 +299,158 @@ fluid_rvoice_dsp_interpolate_linear (fluid_rvoice_dsp_t *voice, fluid_real_t *FL * smaller if end of sample occurs). */ int -fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) +fluid_rvoice_dsp_interpolate_4th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) { - fluid_phase_t dsp_phase = voice->phase; - fluid_phase_t dsp_phase_incr; - short int *dsp_data = voice->sample->data; - char *dsp_data24 = voice->sample->data24; - fluid_real_t dsp_amp = voice->amp; - fluid_real_t dsp_amp_incr = voice->amp_incr; - unsigned int dsp_i = 0; - unsigned int dsp_phase_index; - unsigned int start_index, end_index; - fluid_real_t start_point, end_point1, end_point2; - const fluid_real_t *FLUID_RESTRICT coeffs; + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr; + short int *dsp_data = voice->sample->data; + char *dsp_data24 = voice->sample->data24; + fluid_real_t dsp_amp = voice->amp; + fluid_real_t dsp_amp_incr = voice->amp_incr; + unsigned int dsp_i = 0; + unsigned int dsp_phase_index; + unsigned int start_index, end_index; + fluid_real_t start_point, end_point1, end_point2; + const fluid_real_t *FLUID_RESTRICT coeffs; - /* Convert playback "speed" floating point value to phase index/fract */ - fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float(dsp_phase_incr, voice->phase_incr); - /* last index before 4th interpolation point must be specially handled */ - end_index = (looping ? voice->loopend - 1 : voice->end) - 2; + /* last index before 4th interpolation point must be specially handled */ + end_index = (looping ? voice->loopend - 1 : voice->end) - 2; - if (voice->has_looped) /* set start_index and start point if looped or not */ - { - start_index = voice->loopstart; - start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); /* last point in loop (wrap around) */ - } - else - { - start_index = voice->start; - start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the point */ - } - - /* get points off the end (loop start if looping, duplicate point if end) */ - if (looping) - { - end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); - end_point2 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1); - } - else - { - end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); - end_point2 = end_point1; - } - - while (1) - { - dsp_phase_index = fluid_phase_index (dsp_phase); - - /* interpolate first sample point (start or loop start) if needed */ - for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + if(voice->has_looped) /* set start_index and start point if looped or not */ { - coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)]; - dsp_buf[dsp_i] = dsp_amp * - ( coeffs[0] * start_point - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+2)); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; + start_index = voice->loopstart; + start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); /* last point in loop (wrap around) */ + } + else + { + start_index = voice->start; + start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the point */ } - /* interpolate the sequence of sample points */ - for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + /* get points off the end (loop start if looping, duplicate point if end) */ + if(looping) { - coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)]; - dsp_buf[dsp_i] = dsp_amp * - ( coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+2)); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; + end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); + end_point2 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1); + } + else + { + end_point1 = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); + end_point2 = end_point1; } - /* break out if buffer filled */ - if (dsp_i >= FLUID_BUFSIZE) break; - - end_index++; /* we're now interpolating the 2nd to last point */ - - /* interpolate within 2nd to last point */ - for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + while(1) { - coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)]; - dsp_buf[dsp_i] = dsp_amp * - ( coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[3] * end_point1); + dsp_phase_index = fluid_phase_index(dsp_phase); - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; + /* interpolate first sample point (start or loop start) if needed */ + for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * + (coeffs[0] * start_point + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + /* interpolate the sequence of sample points */ + for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + { + coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * + (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2)); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + /* break out if buffer filled */ + if(dsp_i >= FLUID_BUFSIZE) + { + break; + } + + end_index++; /* we're now interpolating the 2nd to last point */ + + /* interpolate within 2nd to last point */ + for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * + (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[3] * end_point1); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + end_index++; /* we're now interpolating the last point */ + + /* interpolate within the last point */ + for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * + (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[2] * end_point1 + + coeffs[3] * end_point2); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + if(!looping) + { + break; /* break out if not looping (end of sample) */ + } + + /* go back to loop start */ + if(dsp_phase_index > end_index) + { + fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart); + + if(!voice->has_looped) + { + voice->has_looped = 1; + start_index = voice->loopstart; + start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); + } + } + + /* break out if filled buffer */ + if(dsp_i >= FLUID_BUFSIZE) + { + break; + } + + end_index -= 2; /* set end back to third to last sample point */ } - end_index++; /* we're now interpolating the last point */ + voice->phase = dsp_phase; + voice->amp = dsp_amp; - /* interpolate within the last point */ - for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) - { - coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)]; - dsp_buf[dsp_i] = dsp_amp * - ( coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[2] * end_point1 - + coeffs[3] * end_point2); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; - } - - if (!looping) break; /* break out if not looping (end of sample) */ - - /* go back to loop start */ - if (dsp_phase_index > end_index) - { - fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart); - - if (!voice->has_looped) - { - voice->has_looped = 1; - start_index = voice->loopstart; - start_point = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend-1); - } - } - - /* break out if filled buffer */ - if (dsp_i >= FLUID_BUFSIZE) break; - - end_index -= 2; /* set end back to third to last sample point */ - } - - voice->phase = dsp_phase; - voice->amp = dsp_amp; - - return (dsp_i); + return (dsp_i); } /* 7th order interpolation. @@ -422,248 +458,257 @@ fluid_rvoice_dsp_interpolate_4th_order (fluid_rvoice_dsp_t *voice, fluid_real_t * smaller if end of sample occurs). */ int -fluid_rvoice_dsp_interpolate_7th_order (fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) +fluid_rvoice_dsp_interpolate_7th_order(fluid_rvoice_dsp_t *voice, fluid_real_t *FLUID_RESTRICT dsp_buf, int looping) { - fluid_phase_t dsp_phase = voice->phase; - fluid_phase_t dsp_phase_incr; - short int *dsp_data = voice->sample->data; - char *dsp_data24 = voice->sample->data24; - fluid_real_t dsp_amp = voice->amp; - fluid_real_t dsp_amp_incr = voice->amp_incr; - unsigned int dsp_i = 0; - unsigned int dsp_phase_index; - unsigned int start_index, end_index; - fluid_real_t start_points[3], end_points[3]; - const fluid_real_t *FLUID_RESTRICT coeffs; + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr; + short int *dsp_data = voice->sample->data; + char *dsp_data24 = voice->sample->data24; + fluid_real_t dsp_amp = voice->amp; + fluid_real_t dsp_amp_incr = voice->amp_incr; + unsigned int dsp_i = 0; + unsigned int dsp_phase_index; + unsigned int start_index, end_index; + fluid_real_t start_points[3], end_points[3]; + const fluid_real_t *FLUID_RESTRICT coeffs; - /* Convert playback "speed" floating point value to phase index/fract */ - fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float(dsp_phase_incr, voice->phase_incr); - /* add 1/2 sample to dsp_phase since 7th order interpolation is centered on - * the 4th sample point */ - fluid_phase_incr (dsp_phase, (fluid_phase_t)0x80000000); + /* add 1/2 sample to dsp_phase since 7th order interpolation is centered on + * the 4th sample point */ + fluid_phase_incr(dsp_phase, (fluid_phase_t)0x80000000); - /* last index before 7th interpolation point must be specially handled */ - end_index = (looping ? voice->loopend - 1 : voice->end) - 3; + /* last index before 7th interpolation point must be specially handled */ + end_index = (looping ? voice->loopend - 1 : voice->end) - 3; - if (voice->has_looped) /* set start_index and start point if looped or not */ - { - start_index = voice->loopstart; - start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); - start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2); - start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3); - } - else - { - start_index = voice->start; - start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the start point */ - start_points[1] = start_points[0]; - start_points[2] = start_points[0]; - } - - /* get the 3 points off the end (loop start if looping, duplicate point if end) */ - if (looping) - { - end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); - end_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1); - end_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 2); - } - else - { - end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); - end_points[1] = end_points[0]; - end_points[2] = end_points[0]; - } - - while (1) - { - dsp_phase_index = fluid_phase_index (dsp_phase); - - /* interpolate first sample point (start or loop start) if needed */ - for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + if(voice->has_looped) /* set start_index and start point if looped or not */ { - coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; - - dsp_buf[dsp_i] = dsp_amp - * (coeffs[0] * start_points[2] - + coeffs[1] * start_points[1] - + coeffs[2] * start_points[0] - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+2) - + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+3)); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; + start_index = voice->loopstart; + start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); + start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2); + start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3); + } + else + { + start_index = voice->start; + start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->start); /* just duplicate the start point */ + start_points[1] = start_points[0]; + start_points[2] = start_points[0]; } - start_index++; - - /* interpolate 2nd to first sample point (start or loop start) if needed */ - for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + /* get the 3 points off the end (loop start if looping, duplicate point if end) */ + if(looping) { - coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; - - dsp_buf[dsp_i] = dsp_amp - * (coeffs[0] * start_points[1] - + coeffs[1] * start_points[0] - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+2) - + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+3)); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; + end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart); + end_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 1); + end_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopstart + 2); + } + else + { + end_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->end); + end_points[1] = end_points[0]; + end_points[2] = end_points[0]; } - start_index++; - - /* interpolate 3rd to first sample point (start or loop start) if needed */ - for ( ; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + while(1) { - coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; + dsp_phase_index = fluid_phase_index(dsp_phase); - dsp_buf[dsp_i] = dsp_amp - * (coeffs[0] * start_points[0] - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-2) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+2) - + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+3)); + /* interpolate first sample point (start or loop start) if needed */ + for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)]; - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * start_points[2] + + coeffs[1] * start_points[1] + + coeffs[2] * start_points[0] + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2) + + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3)); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + start_index++; + + /* interpolate 2nd to first sample point (start or loop start) if needed */ + for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)]; + + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * start_points[1] + + coeffs[1] * start_points[0] + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2) + + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3)); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + start_index++; + + /* interpolate 3rd to first sample point (start or loop start) if needed */ + for(; dsp_phase_index == start_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)]; + + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * start_points[0] + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2) + + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3)); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + start_index -= 2; /* set back to original start index */ + + + /* interpolate the sequence of sample points */ + for(; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)]; + + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2) + + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 3)); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + /* break out if buffer filled */ + if(dsp_i >= FLUID_BUFSIZE) + { + break; + } + + end_index++; /* we're now interpolating the 3rd to last point */ + + /* interpolate within 3rd to last point */ + for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)]; + + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 2) + + coeffs[6] * end_points[0]); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + end_index++; /* we're now interpolating the 2nd to last point */ + + /* interpolate within 2nd to last point */ + for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)]; + + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index + 1) + + coeffs[5] * end_points[0] + + coeffs[6] * end_points[1]); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + end_index++; /* we're now interpolating the last point */ + + /* interpolate within last point */ + for(; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow(dsp_phase)]; + + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 3) + + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 2) + + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index - 1) + + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) + + coeffs[4] * end_points[0] + + coeffs[5] * end_points[1] + + coeffs[6] * end_points[2]); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_amp += dsp_amp_incr; + } + + if(!looping) + { + break; /* break out if not looping (end of sample) */ + } + + /* go back to loop start */ + if(dsp_phase_index > end_index) + { + fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart); + + if(!voice->has_looped) + { + voice->has_looped = 1; + start_index = voice->loopstart; + start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); + start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2); + start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3); + } + } + + /* break out if filled buffer */ + if(dsp_i >= FLUID_BUFSIZE) + { + break; + } + + end_index -= 3; /* set end back to 4th to last sample point */ } - start_index -= 2; /* set back to original start index */ + /* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on + * the 4th sample point (correct back to real value) */ + fluid_phase_decr(dsp_phase, (fluid_phase_t)0x80000000); + voice->phase = dsp_phase; + voice->amp = dsp_amp; - /* interpolate the sequence of sample points */ - for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) - { - coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; - - dsp_buf[dsp_i] = dsp_amp - * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-3) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-2) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+2) - + coeffs[6] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+3)); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; - } - - /* break out if buffer filled */ - if (dsp_i >= FLUID_BUFSIZE) break; - - end_index++; /* we're now interpolating the 3rd to last point */ - - /* interpolate within 3rd to last point */ - for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) - { - coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; - - dsp_buf[dsp_i] = dsp_amp - * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-3) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-2) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[5] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+2) - + coeffs[6] * end_points[0]); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; - } - - end_index++; /* we're now interpolating the 2nd to last point */ - - /* interpolate within 2nd to last point */ - for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) - { - coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; - - dsp_buf[dsp_i] = dsp_amp - * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-3) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-2) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[4] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index+1) - + coeffs[5] * end_points[0] - + coeffs[6] * end_points[1]); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; - } - - end_index++; /* we're now interpolating the last point */ - - /* interpolate within last point */ - for (; dsp_phase_index <= end_index && dsp_i < FLUID_BUFSIZE; dsp_i++) - { - coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; - - dsp_buf[dsp_i] = dsp_amp - * (coeffs[0] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-3) - + coeffs[1] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-2) - + coeffs[2] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index-1) - + coeffs[3] * fluid_rvoice_get_float_sample(dsp_data, dsp_data24, dsp_phase_index) - + coeffs[4] * end_points[0] - + coeffs[5] * end_points[1] - + coeffs[6] * end_points[2]); - - /* increment phase and amplitude */ - fluid_phase_incr (dsp_phase, dsp_phase_incr); - dsp_phase_index = fluid_phase_index (dsp_phase); - dsp_amp += dsp_amp_incr; - } - - if (!looping) break; /* break out if not looping (end of sample) */ - - /* go back to loop start */ - if (dsp_phase_index > end_index) - { - fluid_phase_sub_int (dsp_phase, voice->loopend - voice->loopstart); - - if (!voice->has_looped) - { - voice->has_looped = 1; - start_index = voice->loopstart; - start_points[0] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 1); - start_points[1] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 2); - start_points[2] = fluid_rvoice_get_float_sample(dsp_data, dsp_data24, voice->loopend - 3); - } - } - - /* break out if filled buffer */ - if (dsp_i >= FLUID_BUFSIZE) break; - - end_index -= 3; /* set end back to 4th to last sample point */ - } - - /* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on - * the 4th sample point (correct back to real value) */ - fluid_phase_decr (dsp_phase, (fluid_phase_t)0x80000000); - - voice->phase = dsp_phase; - voice->amp = dsp_amp; - - return (dsp_i); + return (dsp_i); } diff --git a/src/rvoice/fluid_rvoice_event.c b/src/rvoice/fluid_rvoice_event.c index f17edb85..6f4276a3 100644 --- a/src/rvoice/fluid_rvoice_event.c +++ b/src/rvoice/fluid_rvoice_event.c @@ -25,10 +25,10 @@ #include "fluid_lfo.h" #include "fluid_adsr_env.h" -static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event); +static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t *handler, const fluid_rvoice_event_t *src_event); static FLUID_INLINE void -fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event) +fluid_rvoice_event_dispatch(fluid_rvoice_event_t *event) { event->method(event->object, event->param); } @@ -36,116 +36,133 @@ fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event) /** * In order to be able to push more than one event atomically, - * use push for all events, then use flush to commit them to the + * use push for all events, then use flush to commit them to the * queue. If threadsafe is false, all events are processed immediately. */ int -fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t* handler, - fluid_rvoice_function_t method, void* object, int intparam, - fluid_real_t realparam) +fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t *handler, + fluid_rvoice_function_t method, void *object, int intparam, + fluid_real_t realparam) { - fluid_rvoice_event_t local_event; - - local_event.method = method; - local_event.object = object; - local_event.param[0].i = intparam; - local_event.param[1].real = realparam; - - return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); + fluid_rvoice_event_t local_event; + + local_event.method = method; + local_event.object = object; + local_event.param[0].i = intparam; + local_event.param[1].real = realparam; + + return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); } int -fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler, fluid_rvoice_function_t method, void* object, fluid_rvoice_param_t param[MAX_EVENT_PARAMS]) +fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t *handler, fluid_rvoice_function_t method, void *object, fluid_rvoice_param_t param[MAX_EVENT_PARAMS]) { - fluid_rvoice_event_t local_event; - - local_event.method = method; - local_event.object = object; - FLUID_MEMCPY(&local_event.param, param, sizeof(*param) * MAX_EVENT_PARAMS); - - return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); + fluid_rvoice_event_t local_event; + + local_event.method = method; + local_event.object = object; + FLUID_MEMCPY(&local_event.param, param, sizeof(*param) * MAX_EVENT_PARAMS); + + return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); } -int -fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler, - fluid_rvoice_function_t method, void* object, void* ptr) +int +fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t *handler, + fluid_rvoice_function_t method, void *object, void *ptr) { - fluid_rvoice_event_t local_event; - - local_event.method = method; - local_event.object = object; - local_event.param[0].ptr = ptr; - - return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); + fluid_rvoice_event_t local_event; + + local_event.method = method; + local_event.object = object; + local_event.param[0].ptr = ptr; + + return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event); } -static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event) +static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t *handler, const fluid_rvoice_event_t *src_event) { - fluid_rvoice_event_t* event; - int old_queue_stored = fluid_atomic_int_add(&handler->queue_stored, 1); - - event = fluid_ringbuffer_get_inptr(handler->queue, old_queue_stored); + fluid_rvoice_event_t *event; + int old_queue_stored = fluid_atomic_int_add(&handler->queue_stored, 1); - if (event == NULL) { - fluid_atomic_int_add(&handler->queue_stored, -1); - FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing polyphony!"); - return FLUID_FAILED; // Buffer full... - } + event = fluid_ringbuffer_get_inptr(handler->queue, old_queue_stored); - FLUID_MEMCPY(event, src_event, sizeof(*event)); - - return FLUID_OK; + if(event == NULL) + { + fluid_atomic_int_add(&handler->queue_stored, -1); + FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing polyphony!"); + return FLUID_FAILED; // Buffer full... + } + + FLUID_MEMCPY(event, src_event, sizeof(*event)); + + return FLUID_OK; } -void -fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t* eventhandler, fluid_rvoice_t* rvoice) +void +fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t *eventhandler, fluid_rvoice_t *rvoice) { - fluid_rvoice_t** vptr = fluid_ringbuffer_get_inptr(eventhandler->finished_voices, 0); - if (vptr == NULL) - return; // Buffer full - *vptr = rvoice; - fluid_ringbuffer_next_inptr(eventhandler->finished_voices, 1); + fluid_rvoice_t **vptr = fluid_ringbuffer_get_inptr(eventhandler->finished_voices, 0); + + if(vptr == NULL) + { + return; // Buffer full + } + + *vptr = rvoice; + fluid_ringbuffer_next_inptr(eventhandler->finished_voices, 1); } -fluid_rvoice_eventhandler_t* -new_fluid_rvoice_eventhandler(int queuesize, - int finished_voices_size, int bufs, int fx_bufs, fluid_real_t sample_rate, int extra_threads, int prio) +fluid_rvoice_eventhandler_t * +new_fluid_rvoice_eventhandler(int queuesize, + int finished_voices_size, int bufs, int fx_bufs, fluid_real_t sample_rate, int extra_threads, int prio) { - fluid_rvoice_eventhandler_t* eventhandler = FLUID_NEW(fluid_rvoice_eventhandler_t); - if (eventhandler == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - eventhandler->mixer = NULL; - eventhandler->queue = NULL; - eventhandler->finished_voices = NULL; - - fluid_atomic_int_set(&eventhandler->queue_stored, 0); - - eventhandler->finished_voices = new_fluid_ringbuffer(finished_voices_size, - sizeof(fluid_rvoice_t*)); - if (eventhandler->finished_voices == NULL) - goto error_recovery; + fluid_rvoice_eventhandler_t *eventhandler = FLUID_NEW(fluid_rvoice_eventhandler_t); - eventhandler->queue = new_fluid_ringbuffer(queuesize, sizeof(fluid_rvoice_event_t)); - if (eventhandler->queue == NULL) - goto error_recovery; + if(eventhandler == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + eventhandler->mixer = NULL; + eventhandler->queue = NULL; + eventhandler->finished_voices = NULL; + + fluid_atomic_int_set(&eventhandler->queue_stored, 0); + + eventhandler->finished_voices = new_fluid_ringbuffer(finished_voices_size, + sizeof(fluid_rvoice_t *)); + + if(eventhandler->finished_voices == NULL) + { + goto error_recovery; + } + + eventhandler->queue = new_fluid_ringbuffer(queuesize, sizeof(fluid_rvoice_event_t)); + + if(eventhandler->queue == NULL) + { + goto error_recovery; + } + + eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs, sample_rate, eventhandler, extra_threads, prio); + + if(eventhandler->mixer == NULL) + { + goto error_recovery; + } + + return eventhandler; - eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs, sample_rate, eventhandler, extra_threads, prio); - if (eventhandler->mixer == NULL) - goto error_recovery; - - return eventhandler; - error_recovery: - delete_fluid_rvoice_eventhandler(eventhandler); - return NULL; + delete_fluid_rvoice_eventhandler(eventhandler); + return NULL; } -int -fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t* handler) +int +fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t *handler) { - return fluid_ringbuffer_get_count(handler->queue); + return fluid_ringbuffer_get_count(handler->queue); } @@ -153,27 +170,30 @@ fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t* handler) * Call fluid_rvoice_event_dispatch for all events in queue * @return number of events dispatched */ -int -fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t* handler) +int +fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t *handler) { - fluid_rvoice_event_t* event; - int result = 0; - while (NULL != (event = fluid_ringbuffer_get_outptr(handler->queue))) { - fluid_rvoice_event_dispatch(event); - result++; - fluid_ringbuffer_next_outptr(handler->queue); - } - return result; + fluid_rvoice_event_t *event; + int result = 0; + + while(NULL != (event = fluid_ringbuffer_get_outptr(handler->queue))) + { + fluid_rvoice_event_dispatch(event); + result++; + fluid_ringbuffer_next_outptr(handler->queue); + } + + return result; } -void -delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t* handler) +void +delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t *handler) { - fluid_return_if_fail(handler != NULL); - - delete_fluid_rvoice_mixer(handler->mixer); - delete_fluid_ringbuffer(handler->queue); - delete_fluid_ringbuffer(handler->finished_voices); - FLUID_FREE(handler); + fluid_return_if_fail(handler != NULL); + + delete_fluid_rvoice_mixer(handler->mixer); + delete_fluid_ringbuffer(handler->queue); + delete_fluid_ringbuffer(handler->finished_voices); + FLUID_FREE(handler); } diff --git a/src/rvoice/fluid_rvoice_event.h b/src/rvoice/fluid_rvoice_event.h index 5ad8aad3..0dbd6100 100644 --- a/src/rvoice/fluid_rvoice_event.h +++ b/src/rvoice/fluid_rvoice_event.h @@ -28,74 +28,82 @@ typedef struct _fluid_rvoice_event_t fluid_rvoice_event_t; -struct _fluid_rvoice_event_t { - fluid_rvoice_function_t method; - void* object; +struct _fluid_rvoice_event_t +{ + fluid_rvoice_function_t method; + void *object; fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; }; /* - * Bridge between the renderer thread and the midi state thread. + * Bridge between the renderer thread and the midi state thread. * fluid_rvoice_eventhandler_fetch_all() can be called in parallell * with fluid_rvoice_eventhandler_push/flush() */ -struct _fluid_rvoice_eventhandler_t { - fluid_ringbuffer_t* queue; /**< List of fluid_rvoice_event_t */ - fluid_atomic_int_t queue_stored; /**< Extras pushed but not flushed */ - fluid_ringbuffer_t* finished_voices; /**< return queue from handler, list of fluid_rvoice_t* */ - fluid_rvoice_mixer_t* mixer; +struct _fluid_rvoice_eventhandler_t +{ + fluid_ringbuffer_t *queue; /**< List of fluid_rvoice_event_t */ + fluid_atomic_int_t queue_stored; /**< Extras pushed but not flushed */ + fluid_ringbuffer_t *finished_voices; /**< return queue from handler, list of fluid_rvoice_t* */ + fluid_rvoice_mixer_t *mixer; }; -fluid_rvoice_eventhandler_t* new_fluid_rvoice_eventhandler( - int queuesize, int finished_voices_size, int bufs, - int fx_bufs, fluid_real_t sample_rate, int, int); +fluid_rvoice_eventhandler_t *new_fluid_rvoice_eventhandler( + int queuesize, int finished_voices_size, int bufs, + int fx_bufs, fluid_real_t sample_rate, int, int); -void delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t*); +void delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t *); -int fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t*); -int fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t*); -void fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t* eventhandler, - fluid_rvoice_t* rvoice); +int fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t *); +int fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t *); +void fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t *eventhandler, + fluid_rvoice_t *rvoice); -static FLUID_INLINE void -fluid_rvoice_eventhandler_flush(fluid_rvoice_eventhandler_t* handler) +static FLUID_INLINE void +fluid_rvoice_eventhandler_flush(fluid_rvoice_eventhandler_t *handler) { - int queue_stored = fluid_atomic_int_get(&handler->queue_stored); - - if (queue_stored > 0) { - fluid_atomic_int_set(&handler->queue_stored, 0); - fluid_ringbuffer_next_inptr(handler->queue, queue_stored); - } + int queue_stored = fluid_atomic_int_get(&handler->queue_stored); + + if(queue_stored > 0) + { + fluid_atomic_int_set(&handler->queue_stored, 0); + fluid_ringbuffer_next_inptr(handler->queue, queue_stored); + } } /** * @return next finished voice, or NULL if nothing in queue */ -static FLUID_INLINE fluid_rvoice_t* -fluid_rvoice_eventhandler_get_finished_voice(fluid_rvoice_eventhandler_t* handler) +static FLUID_INLINE fluid_rvoice_t * +fluid_rvoice_eventhandler_get_finished_voice(fluid_rvoice_eventhandler_t *handler) { - void* result = fluid_ringbuffer_get_outptr(handler->finished_voices); - if (result == NULL) return NULL; - result = * (fluid_rvoice_t**) result; - fluid_ringbuffer_next_outptr(handler->finished_voices); - return result; + void *result = fluid_ringbuffer_get_outptr(handler->finished_voices); + + if(result == NULL) + { + return NULL; + } + + result = * (fluid_rvoice_t **) result; + fluid_ringbuffer_next_outptr(handler->finished_voices); + return result; } -int fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t* handler, - fluid_rvoice_function_t method, void* object, int intparam, - fluid_real_t realparam); +int fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t *handler, + fluid_rvoice_function_t method, void *object, int intparam, + fluid_real_t realparam); -int fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler, - fluid_rvoice_function_t method, void* object, void* ptr); +int fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t *handler, + fluid_rvoice_function_t method, void *object, void *ptr); -int fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler, - fluid_rvoice_function_t method, void* object, - fluid_rvoice_param_t param[MAX_EVENT_PARAMS]); +int fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t *handler, + fluid_rvoice_function_t method, void *object, + fluid_rvoice_param_t param[MAX_EVENT_PARAMS]); static FLUID_INLINE void -fluid_rvoice_eventhandler_add_rvoice(fluid_rvoice_eventhandler_t* handler, - fluid_rvoice_t* rvoice) +fluid_rvoice_eventhandler_add_rvoice(fluid_rvoice_eventhandler_t *handler, + fluid_rvoice_t *rvoice) { fluid_rvoice_eventhandler_push_ptr(handler, fluid_rvoice_mixer_add_voice, handler->mixer, rvoice); diff --git a/src/rvoice/fluid_rvoice_mixer.c b/src/rvoice/fluid_rvoice_mixer.c index df5ef5a6..9f2b57a3 100644 --- a/src/rvoice/fluid_rvoice_mixer.c +++ b/src/rvoice/fluid_rvoice_mixer.c @@ -36,159 +36,171 @@ typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t; -struct _fluid_mixer_buffers_t { - fluid_rvoice_mixer_t* mixer; /**< Owner of object */ +struct _fluid_mixer_buffers_t +{ + fluid_rvoice_mixer_t *mixer; /**< Owner of object */ #if ENABLE_MIXER_THREADS - fluid_thread_t* thread; /**< Thread object */ + fluid_thread_t *thread; /**< Thread object */ #endif - fluid_rvoice_t** finished_voices; /* List of voices who have finished */ - int finished_voice_count; + fluid_rvoice_t **finished_voices; /* List of voices who have finished */ + int finished_voice_count; - fluid_atomic_int_t ready; /**< Atomic: buffers are ready for mixing */ - - fluid_real_t* local_buf; - - int buf_count; - int fx_buf_count; - - /** buffer to store the left part of a stereo channel to. - * Specifically a two dimensional array, containing \c buf_count sample buffers - * (i.e. for each synth.audio-channels), of which each contains - * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples) - * @note Each sample buffer is aligned to the FLUID_DEFAULT_ALIGNMENT - * boundary provided that this pointer points to an aligned buffer. - * So make sure to access the sample buffer by first aligning this - * pointer using fluid_align_ptr() - */ - fluid_real_t* left_buf; - - /** dito, but for right part of a stereo channel */ - fluid_real_t* right_buf; + fluid_atomic_int_t ready; /**< Atomic: buffers are ready for mixing */ - /** buffer to store the left part of a stereo effects channel to. - * Specifically a two dimensional array, containing \c fx_buf_count buffers - * (i.e. for each synth.effects-channels), of which each buffer contains - * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples) - */ - fluid_real_t* fx_left_buf; - fluid_real_t* fx_right_buf; + fluid_real_t *local_buf; + + int buf_count; + int fx_buf_count; + + /** buffer to store the left part of a stereo channel to. + * Specifically a two dimensional array, containing \c buf_count sample buffers + * (i.e. for each synth.audio-channels), of which each contains + * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples) + * @note Each sample buffer is aligned to the FLUID_DEFAULT_ALIGNMENT + * boundary provided that this pointer points to an aligned buffer. + * So make sure to access the sample buffer by first aligning this + * pointer using fluid_align_ptr() + */ + fluid_real_t *left_buf; + + /** dito, but for right part of a stereo channel */ + fluid_real_t *right_buf; + + /** buffer to store the left part of a stereo effects channel to. + * Specifically a two dimensional array, containing \c fx_buf_count buffers + * (i.e. for each synth.effects-channels), of which each buffer contains + * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT audio items (=samples) + */ + fluid_real_t *fx_left_buf; + fluid_real_t *fx_right_buf; }; typedef struct _fluid_mixer_fx_t fluid_mixer_fx_t; -struct _fluid_mixer_fx_t { - fluid_revmodel_t* reverb; /**< Reverb unit */ - fluid_chorus_t* chorus; /**< Chorus unit */ - int with_reverb; /**< Should the synth use the built-in reverb unit? */ - int with_chorus; /**< Should the synth use the built-in chorus unit? */ - int mix_fx_to_out; /**< Should the effects be mixed in with the primary output? */ +struct _fluid_mixer_fx_t +{ + fluid_revmodel_t *reverb; /**< Reverb unit */ + fluid_chorus_t *chorus; /**< Chorus unit */ + int with_reverb; /**< Should the synth use the built-in reverb unit? */ + int with_chorus; /**< Should the synth use the built-in chorus unit? */ + int mix_fx_to_out; /**< Should the effects be mixed in with the primary output? */ }; -struct _fluid_rvoice_mixer_t { - fluid_mixer_fx_t fx; +struct _fluid_rvoice_mixer_t +{ + fluid_mixer_fx_t fx; - fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */ - fluid_rvoice_eventhandler_t* eventhandler; + fluid_mixer_buffers_t buffers; /**< Used by mixer only: own buffers */ + fluid_rvoice_eventhandler_t *eventhandler; - fluid_rvoice_t** rvoices; /**< Read-only: Voices array, sorted so that all nulls are last */ - int polyphony; /**< Read-only: Length of voices array */ - int active_voices; /**< Read-only: Number of non-null voices */ - int current_blockcount; /**< Read-only: how many blocks to process this time */ + fluid_rvoice_t **rvoices; /**< Read-only: Voices array, sorted so that all nulls are last */ + int polyphony; /**< Read-only: Length of voices array */ + int active_voices; /**< Read-only: Number of non-null voices */ + int current_blockcount; /**< Read-only: how many blocks to process this time */ #ifdef LADSPA - fluid_ladspa_fx_t* ladspa_fx; /**< Used by mixer only: Effects unit for LADSPA support. Never created or freed */ + fluid_ladspa_fx_t *ladspa_fx; /**< Used by mixer only: Effects unit for LADSPA support. Never created or freed */ #endif #if ENABLE_MIXER_THREADS // int sleeping_threads; /**< Atomic: number of threads currently asleep */ // int active_threads; /**< Atomic: number of threads in the thread loop */ - fluid_atomic_int_t threads_should_terminate; /**< Atomic: Set to TRUE when threads should terminate */ - fluid_atomic_int_t current_rvoice; /**< Atomic: for the threads to know next voice to */ - fluid_cond_t* wakeup_threads; /**< Signalled when the threads should wake up */ - fluid_cond_mutex_t* wakeup_threads_m; /**< wakeup_threads mutex companion */ - fluid_cond_t* thread_ready; /**< Signalled from thread, when the thread has a buffer ready for mixing */ - fluid_cond_mutex_t* thread_ready_m; /**< thread_ready mutex companion */ + fluid_atomic_int_t threads_should_terminate; /**< Atomic: Set to TRUE when threads should terminate */ + fluid_atomic_int_t current_rvoice; /**< Atomic: for the threads to know next voice to */ + fluid_cond_t *wakeup_threads; /**< Signalled when the threads should wake up */ + fluid_cond_mutex_t *wakeup_threads_m; /**< wakeup_threads mutex companion */ + fluid_cond_t *thread_ready; /**< Signalled from thread, when the thread has a buffer ready for mixing */ + fluid_cond_mutex_t *thread_ready_m; /**< thread_ready mutex companion */ - int thread_count; /**< Number of extra mixer threads for multi-core rendering */ - fluid_mixer_buffers_t* threads; /**< Array of mixer threads (thread_count in length) */ + int thread_count; /**< Number of extra mixer threads for multi-core rendering */ + fluid_mixer_buffers_t *threads; /**< Array of mixer threads (thread_count in length) */ #endif }; #if ENABLE_MIXER_THREADS -static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t* mixer); -static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t* mixer, int thread_count, int prio_level); +static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer); +static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int thread_count, int prio_level); #endif -static FLUID_INLINE void -fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t* mixer, int current_blockcount) +static FLUID_INLINE void +fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t *mixer, int current_blockcount) { - int i; - - void (*reverb_process_func)(fluid_revmodel_t* rev, fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out); - void (*chorus_process_func)(fluid_chorus_t* chorus, fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out); - + int i; + + void (*reverb_process_func)(fluid_revmodel_t *rev, fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out); + void (*chorus_process_func)(fluid_chorus_t *chorus, fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out); + fluid_real_t *out_rev_l, *out_rev_r, *out_ch_l, *out_ch_r; - - fluid_real_t* in_rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); - fluid_real_t* in_ch = in_rev; - + + fluid_real_t *in_rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); + fluid_real_t *in_ch = in_rev; + fluid_profile_ref_var(prof_ref); - + in_rev = &in_rev[SYNTH_REVERB_CHANNEL * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; in_ch = &in_ch [SYNTH_CHORUS_CHANNEL * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; - if (mixer->fx.mix_fx_to_out) + if(mixer->fx.mix_fx_to_out) { out_rev_l = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT); out_rev_r = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT); - + out_ch_l = &out_rev_l[0 * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; out_ch_r = &out_rev_r[0 * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; - + reverb_process_func = fluid_revmodel_processmix; chorus_process_func = fluid_chorus_processmix; - + } else { out_ch_l = out_rev_l = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); out_ch_r = out_rev_r = fluid_align_ptr(mixer->buffers.fx_right_buf, FLUID_DEFAULT_ALIGNMENT); - + out_rev_l = &out_rev_l[SYNTH_REVERB_CHANNEL * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; out_rev_r = &out_rev_r[SYNTH_REVERB_CHANNEL * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; - + out_ch_l = &out_ch_l[SYNTH_CHORUS_CHANNEL * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; out_ch_r = &out_ch_r[SYNTH_CHORUS_CHANNEL * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE]; - + reverb_process_func = fluid_revmodel_processreplace; chorus_process_func = fluid_chorus_processreplace; } - - - if (mixer->fx.with_reverb) { - for (i=0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE) - reverb_process_func(mixer->fx.reverb, &in_rev[i], &out_rev_l[i], &out_rev_r[i]); - - fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref,0, - current_blockcount * FLUID_BUFSIZE); - } - - if (mixer->fx.with_chorus) { - for (i=0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE) - chorus_process_func(mixer->fx.chorus, &in_ch[i], &out_ch_l[i], &out_ch_r[i]); - - fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref,0, - current_blockcount * FLUID_BUFSIZE); - } - + + + if(mixer->fx.with_reverb) + { + for(i = 0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE) + { + reverb_process_func(mixer->fx.reverb, &in_rev[i], &out_rev_l[i], &out_rev_r[i]); + } + + fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref, 0, + current_blockcount * FLUID_BUFSIZE); + } + + if(mixer->fx.with_chorus) + { + for(i = 0; i < current_blockcount * FLUID_BUFSIZE; i += FLUID_BUFSIZE) + { + chorus_process_func(mixer->fx.chorus, &in_ch[i], &out_ch_l[i], &out_ch_r[i]); + } + + fluid_profile(FLUID_PROF_ONE_BLOCK_CHORUS, prof_ref, 0, + current_blockcount * FLUID_BUFSIZE); + } + #ifdef LADSPA - /* Run the signal through the LADSPA Fx unit. The buffers have already been - * set up in fluid_rvoice_mixer_set_ladspa. */ - if (mixer->ladspa_fx) { - fluid_ladspa_run(mixer->ladspa_fx, current_blockcount, FLUID_BUFSIZE); - fluid_check_fpe("LADSPA"); - } + + /* Run the signal through the LADSPA Fx unit. The buffers have already been + * set up in fluid_rvoice_mixer_set_ladspa. */ + if(mixer->ladspa_fx) + { + fluid_ladspa_run(mixer->ladspa_fx, current_blockcount, FLUID_BUFSIZE); + fluid_check_fpe("LADSPA"); + } + #endif } @@ -196,102 +208,130 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t* mixer, int current_blockcoun * Glue to get fluid_rvoice_buffers_mix what it wants * Note: Make sure outbufs has 2 * (buf_count + fx_buf_count) elements before calling */ -static FLUID_INLINE int -fluid_mixer_buffers_prepare(fluid_mixer_buffers_t* buffers, fluid_real_t** outbufs) +static FLUID_INLINE int +fluid_mixer_buffers_prepare(fluid_mixer_buffers_t *buffers, fluid_real_t **outbufs) { - fluid_real_t *base_ptr; - int i; - int with_reverb = buffers->mixer->fx.with_reverb; - int with_chorus = buffers->mixer->fx.with_chorus; + fluid_real_t *base_ptr; + int i; + int with_reverb = buffers->mixer->fx.with_reverb; + int with_chorus = buffers->mixer->fx.with_chorus; - /* Set up the reverb and chorus buffers only when the effect is enabled or - * when LADSPA is active. Nonexisting buffers are detected in the DSP loop. - * Not sending the effect signals saves some time in that case. */ + /* Set up the reverb and chorus buffers only when the effect is enabled or + * when LADSPA is active. Nonexisting buffers are detected in the DSP loop. + * Not sending the effect signals saves some time in that case. */ #ifdef LADSPA - int with_ladspa = (buffers->mixer->ladspa_fx != NULL); - with_reverb = (with_reverb | with_ladspa); - with_chorus = (with_chorus | with_ladspa); + int with_ladspa = (buffers->mixer->ladspa_fx != NULL); + with_reverb = (with_reverb | with_ladspa); + with_chorus = (with_chorus | with_ladspa); #endif - - base_ptr = fluid_align_ptr(buffers->fx_left_buf, FLUID_DEFAULT_ALIGNMENT); - - outbufs[buffers->buf_count*2 + SYNTH_REVERB_CHANNEL] = (with_reverb) ? &base_ptr[SYNTH_REVERB_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT] : NULL; - outbufs[buffers->buf_count*2 + SYNTH_CHORUS_CHANNEL] = (with_chorus) ? &base_ptr[SYNTH_CHORUS_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT] : NULL; - /* The output associated with a MIDI channel is wrapped around - * using the number of audio groups as modulo divider. This is - * typically the number of output channels on the 'sound card', - * as long as the LADSPA Fx unit is not used. In case of LADSPA - * unit, think of it as subgroups on a mixer. - * - * For example: Assume that the number of groups is set to 2. - * Then MIDI channel 1, 3, 5, 7 etc. go to output 1, channels 2, - * 4, 6, 8 etc to output 2. Or assume 3 groups: Then MIDI - * channels 1, 4, 7, 10 etc go to output 1; 2, 5, 8, 11 etc to - * output 2, 3, 6, 9, 12 etc to output 3. - */ - base_ptr = fluid_align_ptr(buffers->left_buf, FLUID_DEFAULT_ALIGNMENT); - for (i = 0; i < buffers->buf_count; i++) { - outbufs[i*2] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; - } - - base_ptr = fluid_align_ptr(buffers->right_buf, FLUID_DEFAULT_ALIGNMENT); - for (i = 0; i < buffers->buf_count; i++) { - outbufs[i*2+1] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; - } - return buffers->buf_count*2 + 2; + base_ptr = fluid_align_ptr(buffers->fx_left_buf, FLUID_DEFAULT_ALIGNMENT); + + outbufs[buffers->buf_count * 2 + SYNTH_REVERB_CHANNEL] = (with_reverb) ? &base_ptr[SYNTH_REVERB_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT] : NULL; + outbufs[buffers->buf_count * 2 + SYNTH_CHORUS_CHANNEL] = (with_chorus) ? &base_ptr[SYNTH_CHORUS_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT] : NULL; + + /* The output associated with a MIDI channel is wrapped around + * using the number of audio groups as modulo divider. This is + * typically the number of output channels on the 'sound card', + * as long as the LADSPA Fx unit is not used. In case of LADSPA + * unit, think of it as subgroups on a mixer. + * + * For example: Assume that the number of groups is set to 2. + * Then MIDI channel 1, 3, 5, 7 etc. go to output 1, channels 2, + * 4, 6, 8 etc to output 2. Or assume 3 groups: Then MIDI + * channels 1, 4, 7, 10 etc go to output 1; 2, 5, 8, 11 etc to + * output 2, 3, 6, 9, 12 etc to output 3. + */ + base_ptr = fluid_align_ptr(buffers->left_buf, FLUID_DEFAULT_ALIGNMENT); + + for(i = 0; i < buffers->buf_count; i++) + { + outbufs[i * 2] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; + } + + base_ptr = fluid_align_ptr(buffers->right_buf, FLUID_DEFAULT_ALIGNMENT); + + for(i = 0; i < buffers->buf_count; i++) + { + outbufs[i * 2 + 1] = &base_ptr[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; + } + + return buffers->buf_count * 2 + 2; } static FLUID_INLINE void -fluid_finish_rvoice(fluid_mixer_buffers_t* buffers, fluid_rvoice_t* rvoice) +fluid_finish_rvoice(fluid_mixer_buffers_t *buffers, fluid_rvoice_t *rvoice) { - if (buffers->finished_voice_count < buffers->mixer->polyphony) - buffers->finished_voices[buffers->finished_voice_count++] = rvoice; - else - FLUID_LOG(FLUID_ERR, "Exceeded finished voices array, try increasing polyphony"); -} - -static void -fluid_mixer_buffer_process_finished_voices(fluid_mixer_buffers_t* buffers) -{ - int i,j; - for (i=0; i < buffers->finished_voice_count; i++) { - fluid_rvoice_t* v = buffers->finished_voices[i]; - int av = buffers->mixer->active_voices; - for (j=0; j < av; j++) { - if (v == buffers->mixer->rvoices[j]) { - av--; - /* Pack the array */ - if (j < av) - buffers->mixer->rvoices[j] = buffers->mixer->rvoices[av]; - } + if(buffers->finished_voice_count < buffers->mixer->polyphony) + { + buffers->finished_voices[buffers->finished_voice_count++] = rvoice; + } + else + { + FLUID_LOG(FLUID_ERR, "Exceeded finished voices array, try increasing polyphony"); } - buffers->mixer->active_voices = av; - - fluid_rvoice_eventhandler_finished_voice_callback(buffers->mixer->eventhandler, v); - } - buffers->finished_voice_count = 0; } -static FLUID_INLINE void fluid_rvoice_mixer_process_finished_voices(fluid_rvoice_mixer_t* mixer) +static void +fluid_mixer_buffer_process_finished_voices(fluid_mixer_buffers_t *buffers) { -#if ENABLE_MIXER_THREADS - int i; - for (i=0; i < mixer->thread_count; i++) - fluid_mixer_buffer_process_finished_voices(&mixer->threads[i]); + int i, j; + + for(i = 0; i < buffers->finished_voice_count; i++) + { + fluid_rvoice_t *v = buffers->finished_voices[i]; + int av = buffers->mixer->active_voices; + + for(j = 0; j < av; j++) + { + if(v == buffers->mixer->rvoices[j]) + { + av--; + + /* Pack the array */ + if(j < av) + { + buffers->mixer->rvoices[j] = buffers->mixer->rvoices[av]; + } + } + } + + buffers->mixer->active_voices = av; + + fluid_rvoice_eventhandler_finished_voice_callback(buffers->mixer->eventhandler, v); + } + + buffers->finished_voice_count = 0; +} + +static FLUID_INLINE void fluid_rvoice_mixer_process_finished_voices(fluid_rvoice_mixer_t *mixer) +{ +#if ENABLE_MIXER_THREADS + int i; + + for(i = 0; i < mixer->thread_count; i++) + { + fluid_mixer_buffer_process_finished_voices(&mixer->threads[i]); + } + #endif - fluid_mixer_buffer_process_finished_voices(&mixer->buffers); + fluid_mixer_buffer_process_finished_voices(&mixer->buffers); } -static FLUID_INLINE fluid_real_t* -get_dest_buf(fluid_rvoice_buffers_t* buffers, int index, - fluid_real_t** dest_bufs, int dest_bufcount) +static FLUID_INLINE fluid_real_t * +get_dest_buf(fluid_rvoice_buffers_t *buffers, int index, + fluid_real_t **dest_bufs, int dest_bufcount) { - int j = buffers->bufs[index].mapping; - if (j >= dest_bufcount || j < 0) return NULL; - return dest_bufs[j]; + int j = buffers->bufs[index].mapping; + + if(j >= dest_bufcount || j < 0) + { + return NULL; + } + + return dest_bufs[j]; } /** @@ -304,111 +344,136 @@ get_dest_buf(fluid_rvoice_buffers_t* buffers, int index, * @param dest_bufs Array of buffers to mixdown to * @param dest_bufcount Length of dest_bufs */ -static void -fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t* buffers, +static void +fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers, fluid_real_t *FLUID_RESTRICT dsp_buf, - int start_block, int sample_count, - fluid_real_t** dest_bufs, int dest_bufcount) + int start_block, int sample_count, + fluid_real_t **dest_bufs, int dest_bufcount) { - int bufcount = buffers->count; - int i, dsp_i; - if (sample_count <= 0 || dest_bufcount <= 0) - return; + int bufcount = buffers->count; + int i, dsp_i; - FLUID_ASSERT((uintptr_t)dsp_buf % FLUID_DEFAULT_ALIGNMENT == 0); - FLUID_ASSERT((uintptr_t)(&dsp_buf[start_block * FLUID_BUFSIZE]) % FLUID_DEFAULT_ALIGNMENT == 0); - - for (i=0; i < bufcount; i++) { - fluid_real_t *FLUID_RESTRICT buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount); - fluid_real_t amp = buffers->bufs[i].amp; - - if (buf == NULL || amp == 0.0f) - continue; + if(sample_count <= 0 || dest_bufcount <= 0) + { + return; + } - FLUID_ASSERT((uintptr_t)buf % FLUID_DEFAULT_ALIGNMENT == 0); - - #pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT) - for (dsp_i = (start_block * FLUID_BUFSIZE); dsp_i < sample_count; dsp_i++) - { - buf[dsp_i] += amp * dsp_buf[dsp_i]; - } - } + FLUID_ASSERT((uintptr_t)dsp_buf % FLUID_DEFAULT_ALIGNMENT == 0); + FLUID_ASSERT((uintptr_t)(&dsp_buf[start_block * FLUID_BUFSIZE]) % FLUID_DEFAULT_ALIGNMENT == 0); + + for(i = 0; i < bufcount; i++) + { + fluid_real_t *FLUID_RESTRICT buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount); + fluid_real_t amp = buffers->bufs[i].amp; + + if(buf == NULL || amp == 0.0f) + { + continue; + } + + FLUID_ASSERT((uintptr_t)buf % FLUID_DEFAULT_ALIGNMENT == 0); + + #pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT) + + for(dsp_i = (start_block * FLUID_BUFSIZE); dsp_i < sample_count; dsp_i++) + { + buf[dsp_i] += amp * dsp_buf[dsp_i]; + } + } } /** * Synthesize one voice and add to buffer. - * NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means + * NOTE: If return value is less than blockcount*FLUID_BUFSIZE, that means * voice has been finished, removed and possibly replaced with another voice. */ static FLUID_INLINE void -fluid_mixer_buffers_render_one(fluid_mixer_buffers_t* buffers, - fluid_rvoice_t* rvoice, fluid_real_t** dest_bufs, - unsigned int dest_bufcount, fluid_real_t* src_buf, int blockcount) +fluid_mixer_buffers_render_one(fluid_mixer_buffers_t *buffers, + fluid_rvoice_t *rvoice, fluid_real_t **dest_bufs, + unsigned int dest_bufcount, fluid_real_t *src_buf, int blockcount) { - int i, total_samples = 0, start_block = 0; + int i, total_samples = 0, start_block = 0; - for (i=0; i < blockcount; i++) { - int s = fluid_rvoice_write(rvoice, &src_buf[FLUID_BUFSIZE*i]); - if (s == -1) { - start_block += s; - s = FLUID_BUFSIZE; - } - total_samples += s; - - if (s < FLUID_BUFSIZE) { - break; - } - } - fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, -start_block, total_samples-((-start_block)*FLUID_BUFSIZE), dest_bufs, dest_bufcount); + for(i = 0; i < blockcount; i++) + { + int s = fluid_rvoice_write(rvoice, &src_buf[FLUID_BUFSIZE * i]); - if (total_samples < blockcount * FLUID_BUFSIZE) { - fluid_finish_rvoice(buffers, rvoice); - } + if(s == -1) + { + start_block += s; + s = FLUID_BUFSIZE; + } + + total_samples += s; + + if(s < FLUID_BUFSIZE) + { + break; + } + } + + fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, -start_block, total_samples - ((-start_block)*FLUID_BUFSIZE), dest_bufs, dest_bufcount); + + if(total_samples < blockcount * FLUID_BUFSIZE) + { + fluid_finish_rvoice(buffers, rvoice); + } } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice) { - int i; - fluid_rvoice_mixer_t* mixer = obj; - fluid_rvoice_t* voice = param[0].ptr; + int i; + fluid_rvoice_mixer_t *mixer = obj; + fluid_rvoice_t *voice = param[0].ptr; - if (mixer->active_voices < mixer->polyphony) { - mixer->rvoices[mixer->active_voices++] = voice; - return; // success - } - - /* See if any voices just finished, if so, take its place. - This can happen in voice overflow conditions. */ - for (i=0; i < mixer->active_voices; i++) { - if (mixer->rvoices[i] == voice) { - FLUID_LOG(FLUID_ERR, "Internal error: Trying to replace an existing rvoice in fluid_rvoice_mixer_add_voice?!"); - return; + if(mixer->active_voices < mixer->polyphony) + { + mixer->rvoices[mixer->active_voices++] = voice; + return; // success } - if (mixer->rvoices[i]->envlfo.volenv.section == FLUID_VOICE_ENVFINISHED) { - fluid_finish_rvoice(&mixer->buffers, mixer->rvoices[i]); - mixer->rvoices[i] = voice; - return; // success - } - } - /* This should never happen */ - FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice"); - return; + /* See if any voices just finished, if so, take its place. + This can happen in voice overflow conditions. */ + for(i = 0; i < mixer->active_voices; i++) + { + if(mixer->rvoices[i] == voice) + { + FLUID_LOG(FLUID_ERR, "Internal error: Trying to replace an existing rvoice in fluid_rvoice_mixer_add_voice?!"); + return; + } + + if(mixer->rvoices[i]->envlfo.volenv.section == FLUID_VOICE_ENVFINISHED) + { + fluid_finish_rvoice(&mixer->buffers, mixer->rvoices[i]); + mixer->rvoices[i] = voice; + return; // success + } + } + + /* This should never happen */ + FLUID_LOG(FLUID_ERR, "Trying to exceed polyphony in fluid_rvoice_mixer_add_voice"); + return; } -static int -fluid_mixer_buffers_update_polyphony(fluid_mixer_buffers_t* buffers, int value) +static int +fluid_mixer_buffers_update_polyphony(fluid_mixer_buffers_t *buffers, int value) { - void* newptr; + void *newptr; - if (buffers->finished_voice_count > value) - return FLUID_FAILED; - - newptr = FLUID_REALLOC(buffers->finished_voices, value * sizeof(fluid_rvoice_t*)); - if (newptr == NULL && value > 0) - return FLUID_FAILED; - buffers->finished_voices = newptr; - return FLUID_OK; + if(buffers->finished_voice_count > value) + { + return FLUID_FAILED; + } + + newptr = FLUID_REALLOC(buffers->finished_voices, value * sizeof(fluid_rvoice_t *)); + + if(newptr == NULL && value > 0) + { + return FLUID_FAILED; + } + + buffers->finished_voices = newptr; + return FLUID_OK; } /** @@ -417,121 +482,142 @@ fluid_mixer_buffers_update_polyphony(fluid_mixer_buffers_t* buffers, int value) */ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_polyphony) { - void* newptr; - fluid_rvoice_mixer_t* handler = obj; - int value = param[0].i; - - if (handler->active_voices > value) - return /*FLUID_FAILED*/; + void *newptr; + fluid_rvoice_mixer_t *handler = obj; + int value = param[0].i; - newptr = FLUID_REALLOC(handler->rvoices, value * sizeof(fluid_rvoice_t*)); - if (newptr == NULL) - return /*FLUID_FAILED*/; - handler->rvoices = newptr; + if(handler->active_voices > value) + { + return /*FLUID_FAILED*/; + } - if (fluid_mixer_buffers_update_polyphony(&handler->buffers, value) - == FLUID_FAILED) - return /*FLUID_FAILED*/; + newptr = FLUID_REALLOC(handler->rvoices, value * sizeof(fluid_rvoice_t *)); + + if(newptr == NULL) + { + return /*FLUID_FAILED*/; + } + + handler->rvoices = newptr; + + if(fluid_mixer_buffers_update_polyphony(&handler->buffers, value) + == FLUID_FAILED) + { + return /*FLUID_FAILED*/; + } #if ENABLE_MIXER_THREADS - { - int i; - for (i=0; i < handler->thread_count; i++) - if (fluid_mixer_buffers_update_polyphony(&handler->threads[i], value) - == FLUID_FAILED) - return /*FLUID_FAILED*/; - } + { + int i; + + for(i = 0; i < handler->thread_count; i++) + { + if(fluid_mixer_buffers_update_polyphony(&handler->threads[i], value) + == FLUID_FAILED) + { + return /*FLUID_FAILED*/; + } + } + } #endif - handler->polyphony = value; - return /*FLUID_OK*/; + handler->polyphony = value; + return /*FLUID_OK*/; } -static void -fluid_render_loop_singlethread(fluid_rvoice_mixer_t* mixer, int blockcount) +static void +fluid_render_loop_singlethread(fluid_rvoice_mixer_t *mixer, int blockcount) { - int i; - FLUID_DECLARE_VLA(fluid_real_t*, bufs, - mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2); - int bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs); - - fluid_real_t* local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT); - - fluid_profile_ref_var(prof_ref); - for (i=0; i < mixer->active_voices; i++) { - fluid_mixer_buffers_render_one(&mixer->buffers, mixer->rvoices[i], bufs, - bufcount, local_buf, blockcount); - fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref,1, - blockcount * FLUID_BUFSIZE); - } + int i; + FLUID_DECLARE_VLA(fluid_real_t *, bufs, + mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2); + int bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs); + + fluid_real_t *local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT); + + fluid_profile_ref_var(prof_ref); + + for(i = 0; i < mixer->active_voices; i++) + { + fluid_mixer_buffers_render_one(&mixer->buffers, mixer->rvoices[i], bufs, + bufcount, local_buf, blockcount); + fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref, 1, + blockcount * FLUID_BUFSIZE); + } } static FLUID_INLINE void -fluid_mixer_buffers_zero(fluid_mixer_buffers_t* buffers, int current_blockcount) +fluid_mixer_buffers_zero(fluid_mixer_buffers_t *buffers, int current_blockcount) { int i, size = current_blockcount * FLUID_BUFSIZE * sizeof(fluid_real_t); - + /* TODO: Optimize by only zero out the buffers we actually use later on. */ int buf_count = buffers->buf_count, fx_buf_count = buffers->fx_buf_count; - + fluid_real_t *FLUID_RESTRICT buf_l = fluid_align_ptr(buffers->left_buf, FLUID_DEFAULT_ALIGNMENT); fluid_real_t *FLUID_RESTRICT buf_r = fluid_align_ptr(buffers->right_buf, FLUID_DEFAULT_ALIGNMENT); - - for (i=0; i < buf_count; i++) { + + for(i = 0; i < buf_count; i++) + { FLUID_MEMSET(&buf_l[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size); FLUID_MEMSET(&buf_r[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size); } - + buf_l = fluid_align_ptr(buffers->fx_left_buf, FLUID_DEFAULT_ALIGNMENT); buf_r = fluid_align_ptr(buffers->fx_right_buf, FLUID_DEFAULT_ALIGNMENT); - - for (i=0; i < fx_buf_count; i++) { + + for(i = 0; i < fx_buf_count; i++) + { FLUID_MEMSET(&buf_l[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size); FLUID_MEMSET(&buf_r[i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE], 0, size); } } -static int -fluid_mixer_buffers_init(fluid_mixer_buffers_t* buffers, fluid_rvoice_mixer_t* mixer) +static int +fluid_mixer_buffers_init(fluid_mixer_buffers_t *buffers, fluid_rvoice_mixer_t *mixer) { - const int samplecount = FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT; - - buffers->mixer = mixer; - buffers->buf_count = mixer->buffers.buf_count; - buffers->fx_buf_count = mixer->buffers.fx_buf_count; + const int samplecount = FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT; - /* Local mono voice buf */ - buffers->local_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, samplecount, FLUID_DEFAULT_ALIGNMENT); - - /* Left and right audio buffers */ + buffers->mixer = mixer; + buffers->buf_count = mixer->buffers.buf_count; + buffers->fx_buf_count = mixer->buffers.fx_buf_count; - buffers->left_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); - buffers->right_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); + /* Local mono voice buf */ + buffers->local_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, samplecount, FLUID_DEFAULT_ALIGNMENT); - if ((buffers->local_buf == NULL) || (buffers->left_buf == NULL) || (buffers->right_buf == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return 0; - } + /* Left and right audio buffers */ - /* Effects audio buffers */ + buffers->left_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); + buffers->right_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); - buffers->fx_left_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); - buffers->fx_right_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); + if((buffers->local_buf == NULL) || (buffers->left_buf == NULL) || (buffers->right_buf == NULL)) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return 0; + } - if ((buffers->fx_left_buf == NULL) || (buffers->fx_right_buf == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return 0; - } + /* Effects audio buffers */ - buffers->finished_voices = NULL; - if (fluid_mixer_buffers_update_polyphony(buffers, mixer->polyphony) - == FLUID_FAILED) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return 0; - } - - return 1; + buffers->fx_left_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); + buffers->fx_right_buf = FLUID_ARRAY_ALIGNED(fluid_real_t, buffers->fx_buf_count * samplecount, FLUID_DEFAULT_ALIGNMENT); + + if((buffers->fx_left_buf == NULL) || (buffers->fx_right_buf == NULL)) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return 0; + } + + buffers->finished_voices = NULL; + + if(fluid_mixer_buffers_update_polyphony(buffers, mixer->polyphony) + == FLUID_FAILED) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return 0; + } + + return 1; } /** @@ -539,21 +625,28 @@ fluid_mixer_buffers_init(fluid_mixer_buffers_t* buffers, fluid_rvoice_mixer_t* m */ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate) { - fluid_rvoice_mixer_t* mixer = obj; - fluid_real_t samplerate = param[1].real; // becausee fluid_synth_update_mixer() puts real into arg2 - - if (mixer->fx.chorus) - delete_fluid_chorus(mixer->fx.chorus); - - mixer->fx.chorus = new_fluid_chorus(samplerate); - if (mixer->fx.reverb) - fluid_revmodel_samplerate_change(mixer->fx.reverb, samplerate); - + fluid_rvoice_mixer_t *mixer = obj; + fluid_real_t samplerate = param[1].real; // becausee fluid_synth_update_mixer() puts real into arg2 + + if(mixer->fx.chorus) + { + delete_fluid_chorus(mixer->fx.chorus); + } + + mixer->fx.chorus = new_fluid_chorus(samplerate); + + if(mixer->fx.reverb) + { + fluid_revmodel_samplerate_change(mixer->fx.reverb, samplerate); + } + #if LADSPA - if (mixer->ladspa_fx != NULL) - { - fluid_ladspa_set_sample_rate(mixer->ladspa_fx, samplerate); - } + + if(mixer->ladspa_fx != NULL) + { + fluid_ladspa_set_sample_rate(mixer->ladspa_fx, samplerate); + } + #endif } @@ -562,114 +655,142 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_samplerate) * @param buf_count number of primary stereo buffers * @param fx_buf_count number of stereo effect buffers */ -fluid_rvoice_mixer_t* -new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, fluid_real_t sample_rate, fluid_rvoice_eventhandler_t* evthandler, int extra_threads, int prio) +fluid_rvoice_mixer_t * +new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, fluid_real_t sample_rate, fluid_rvoice_eventhandler_t *evthandler, int extra_threads, int prio) { - fluid_rvoice_mixer_t* mixer = FLUID_NEW(fluid_rvoice_mixer_t); - if (mixer == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(mixer, 0, sizeof(fluid_rvoice_mixer_t)); - mixer->eventhandler = evthandler; - mixer->buffers.buf_count = buf_count; - mixer->buffers.fx_buf_count = fx_buf_count; - - /* allocate the reverb module */ - mixer->fx.reverb = new_fluid_revmodel(sample_rate); - mixer->fx.chorus = new_fluid_chorus(sample_rate); - if (mixer->fx.reverb == NULL || mixer->fx.chorus == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - delete_fluid_rvoice_mixer(mixer); - return NULL; - } - - if (!fluid_mixer_buffers_init(&mixer->buffers, mixer)) { - delete_fluid_rvoice_mixer(mixer); - return NULL; - } - + fluid_rvoice_mixer_t *mixer = FLUID_NEW(fluid_rvoice_mixer_t); + + if(mixer == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + FLUID_MEMSET(mixer, 0, sizeof(fluid_rvoice_mixer_t)); + mixer->eventhandler = evthandler; + mixer->buffers.buf_count = buf_count; + mixer->buffers.fx_buf_count = fx_buf_count; + + /* allocate the reverb module */ + mixer->fx.reverb = new_fluid_revmodel(sample_rate); + mixer->fx.chorus = new_fluid_chorus(sample_rate); + + if(mixer->fx.reverb == NULL || mixer->fx.chorus == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + delete_fluid_rvoice_mixer(mixer); + return NULL; + } + + if(!fluid_mixer_buffers_init(&mixer->buffers, mixer)) + { + delete_fluid_rvoice_mixer(mixer); + return NULL; + } + #if ENABLE_MIXER_THREADS - mixer->thread_ready = new_fluid_cond(); - mixer->wakeup_threads = new_fluid_cond(); - mixer->thread_ready_m = new_fluid_cond_mutex(); - mixer->wakeup_threads_m = new_fluid_cond_mutex(); - if (!mixer->thread_ready || !mixer->wakeup_threads || - !mixer->thread_ready_m || !mixer->wakeup_threads_m) { - delete_fluid_rvoice_mixer(mixer); - return NULL; - } - - if(fluid_rvoice_mixer_set_threads(mixer, extra_threads, prio) != FLUID_OK) - { - delete_fluid_rvoice_mixer(mixer); - return NULL; - } + mixer->thread_ready = new_fluid_cond(); + mixer->wakeup_threads = new_fluid_cond(); + mixer->thread_ready_m = new_fluid_cond_mutex(); + mixer->wakeup_threads_m = new_fluid_cond_mutex(); + + if(!mixer->thread_ready || !mixer->wakeup_threads || + !mixer->thread_ready_m || !mixer->wakeup_threads_m) + { + delete_fluid_rvoice_mixer(mixer); + return NULL; + } + + if(fluid_rvoice_mixer_set_threads(mixer, extra_threads, prio) != FLUID_OK) + { + delete_fluid_rvoice_mixer(mixer); + return NULL; + } + #endif - - return mixer; + + return mixer; } static void -fluid_mixer_buffers_free(fluid_mixer_buffers_t* buffers) +fluid_mixer_buffers_free(fluid_mixer_buffers_t *buffers) { - FLUID_FREE(buffers->finished_voices); - - /* free all the sample buffers */ - FLUID_FREE(buffers->local_buf); - FLUID_FREE(buffers->left_buf); - FLUID_FREE(buffers->right_buf); - FLUID_FREE(buffers->fx_left_buf); - FLUID_FREE(buffers->fx_right_buf); + FLUID_FREE(buffers->finished_voices); + + /* free all the sample buffers */ + FLUID_FREE(buffers->local_buf); + FLUID_FREE(buffers->left_buf); + FLUID_FREE(buffers->right_buf); + FLUID_FREE(buffers->fx_left_buf); + FLUID_FREE(buffers->fx_right_buf); } -void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t* mixer) +void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *mixer) { - fluid_return_if_fail(mixer != NULL); - + fluid_return_if_fail(mixer != NULL); + #if ENABLE_MIXER_THREADS - delete_rvoice_mixer_threads(mixer); - - if (mixer->thread_ready) - delete_fluid_cond(mixer->thread_ready); - if (mixer->wakeup_threads) - delete_fluid_cond(mixer->wakeup_threads); - if (mixer->thread_ready_m) - delete_fluid_cond_mutex(mixer->thread_ready_m); - if (mixer->wakeup_threads_m) - delete_fluid_cond_mutex(mixer->wakeup_threads_m); + delete_rvoice_mixer_threads(mixer); + + if(mixer->thread_ready) + { + delete_fluid_cond(mixer->thread_ready); + } + + if(mixer->wakeup_threads) + { + delete_fluid_cond(mixer->wakeup_threads); + } + + if(mixer->thread_ready_m) + { + delete_fluid_cond_mutex(mixer->thread_ready_m); + } + + if(mixer->wakeup_threads_m) + { + delete_fluid_cond_mutex(mixer->wakeup_threads_m); + } + #endif - fluid_mixer_buffers_free(&mixer->buffers); - if (mixer->fx.reverb) - delete_fluid_revmodel(mixer->fx.reverb); - if (mixer->fx.chorus) - delete_fluid_chorus(mixer->fx.chorus); - - FLUID_FREE(mixer->rvoices); - FLUID_FREE(mixer); + fluid_mixer_buffers_free(&mixer->buffers); + + if(mixer->fx.reverb) + { + delete_fluid_revmodel(mixer->fx.reverb); + } + + if(mixer->fx.chorus) + { + delete_fluid_chorus(mixer->fx.chorus); + } + + FLUID_FREE(mixer->rvoices); + FLUID_FREE(mixer); } -#ifdef LADSPA +#ifdef LADSPA /** * Set a LADSPS fx instance to be used by the mixer and assign the mixer buffers * as LADSPA host buffers with sensible names */ -void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer, - fluid_ladspa_fx_t *ladspa_fx, int audio_groups) +void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t *mixer, + fluid_ladspa_fx_t *ladspa_fx, int audio_groups) { mixer->ladspa_fx = ladspa_fx; - if (ladspa_fx == NULL) + + if(ladspa_fx == NULL) { return; } else { - fluid_real_t* main_l = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT); - fluid_real_t* main_r = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT); - - fluid_real_t* rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); - fluid_real_t* chor = rev; - + fluid_real_t *main_l = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT); + fluid_real_t *main_r = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT); + + fluid_real_t *rev = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); + fluid_real_t *chor = rev; + rev = &rev[SYNTH_REVERB_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; chor = &chor[SYNTH_CHORUS_CHANNEL * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT]; @@ -694,98 +815,102 @@ void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer, DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_enabled) { - fluid_rvoice_mixer_t* mixer = obj; - int on = param[0].i; - - mixer->fx.with_reverb = on; + fluid_rvoice_mixer_t *mixer = obj; + int on = param[0].i; + + mixer->fx.with_reverb = on; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_enabled) { - fluid_rvoice_mixer_t* mixer = obj; - int on = param[0].i; - mixer->fx.with_chorus = on; + fluid_rvoice_mixer_t *mixer = obj; + int on = param[0].i; + mixer->fx.with_chorus = on; } -void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t* mixer, int on) +void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t *mixer, int on) { - mixer->fx.mix_fx_to_out = on; + mixer->fx.mix_fx_to_out = on; } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_chorus_params) { - fluid_rvoice_mixer_t* mixer = obj; - int set = param[0].i; - int nr = param[1].i; - fluid_real_t level = param[2].real; - fluid_real_t speed = param[3].real; - fluid_real_t depth_ms = param[4].real; - int type = param[5].i; - - fluid_chorus_set(mixer->fx.chorus, set, nr, level, speed, depth_ms, type); + fluid_rvoice_mixer_t *mixer = obj; + int set = param[0].i; + int nr = param[1].i; + fluid_real_t level = param[2].real; + fluid_real_t speed = param[3].real; + fluid_real_t depth_ms = param[4].real; + int type = param[5].i; + + fluid_chorus_set(mixer->fx.chorus, set, nr, level, speed, depth_ms, type); } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_set_reverb_params) { - fluid_rvoice_mixer_t* mixer = obj; + fluid_rvoice_mixer_t *mixer = obj; int set = param[0].i; fluid_real_t roomsize = param[1].real; fluid_real_t damping = param[2].real; fluid_real_t width = param[3].real; fluid_real_t level = param[4].real; - - fluid_revmodel_set(mixer->fx.reverb, set, roomsize, damping, width, level); + + fluid_revmodel_set(mixer->fx.reverb, set, roomsize, damping, width, level); } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_reverb) { - fluid_rvoice_mixer_t* mixer = obj; - fluid_revmodel_reset(mixer->fx.reverb); + fluid_rvoice_mixer_t *mixer = obj; + fluid_revmodel_reset(mixer->fx.reverb); } DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_chorus) { - fluid_rvoice_mixer_t* mixer = obj; - fluid_chorus_reset(mixer->fx.chorus); + fluid_rvoice_mixer_t *mixer = obj; + fluid_chorus_reset(mixer->fx.chorus); } -int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t* mixer, - fluid_real_t** left, fluid_real_t** right) +int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t *mixer, + fluid_real_t **left, fluid_real_t **right) { - *left = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT); - *right = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT); - return mixer->buffers.buf_count; + *left = fluid_align_ptr(mixer->buffers.left_buf, FLUID_DEFAULT_ALIGNMENT); + *right = fluid_align_ptr(mixer->buffers.right_buf, FLUID_DEFAULT_ALIGNMENT); + return mixer->buffers.buf_count; } -int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t* mixer, - fluid_real_t** fx_left, fluid_real_t** fx_right) +int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t *mixer, + fluid_real_t **fx_left, fluid_real_t **fx_right) { - *fx_left = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); - *fx_right = fluid_align_ptr(mixer->buffers.fx_right_buf, FLUID_DEFAULT_ALIGNMENT); - return mixer->buffers.fx_buf_count; + *fx_left = fluid_align_ptr(mixer->buffers.fx_left_buf, FLUID_DEFAULT_ALIGNMENT); + *fx_right = fluid_align_ptr(mixer->buffers.fx_right_buf, FLUID_DEFAULT_ALIGNMENT); + return mixer->buffers.fx_buf_count; } -int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t* mixer) +int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t *mixer) { return FLUID_MIXER_MAX_BUFFERS_DEFAULT; } #if WITH_PROFILING -int fluid_rvoice_mixer_get_active_voices(fluid_rvoice_mixer_t* mixer) +int fluid_rvoice_mixer_get_active_voices(fluid_rvoice_mixer_t *mixer) { - return mixer->active_voices; + return mixer->active_voices; } #endif #if ENABLE_MIXER_THREADS -static FLUID_INLINE fluid_rvoice_t* -fluid_mixer_get_mt_rvoice(fluid_rvoice_mixer_t* mixer) +static FLUID_INLINE fluid_rvoice_t * +fluid_mixer_get_mt_rvoice(fluid_rvoice_mixer_t *mixer) { - int i = fluid_atomic_int_exchange_and_add(&mixer->current_rvoice, 1); - if (i >= mixer->active_voices) - return NULL; - return mixer->rvoices[i]; + int i = fluid_atomic_int_exchange_and_add(&mixer->current_rvoice, 1); + + if(i >= mixer->active_voices) + { + return NULL; + } + + return mixer->rvoices[i]; } #define THREAD_BUF_PROCESSING 0 @@ -795,302 +920,390 @@ fluid_mixer_get_mt_rvoice(fluid_rvoice_mixer_t* mixer) /* Core thread function (processes voices in parallel to primary synthesis thread) */ static fluid_thread_return_t -fluid_mixer_thread_func (void* data) +fluid_mixer_thread_func(void *data) { - fluid_mixer_buffers_t* buffers = data; - fluid_rvoice_mixer_t* mixer = buffers->mixer; - int hasValidData = 0; - FLUID_DECLARE_VLA(fluid_real_t*, bufs, buffers->buf_count*2 + buffers->fx_buf_count*2); - int bufcount=0; - int current_blockcount=0; - fluid_real_t* local_buf = fluid_align_ptr(buffers->local_buf, FLUID_DEFAULT_ALIGNMENT); - - while (!fluid_atomic_int_get(&mixer->threads_should_terminate)) { - fluid_rvoice_t* rvoice = fluid_mixer_get_mt_rvoice(mixer); - if (rvoice == NULL) { - // if no voices: signal rendered buffers, sleep - fluid_atomic_int_set(&buffers->ready, hasValidData ? THREAD_BUF_VALID : THREAD_BUF_NODATA); - fluid_cond_mutex_lock(mixer->thread_ready_m); - fluid_cond_signal(mixer->thread_ready); - fluid_cond_mutex_unlock(mixer->thread_ready_m); - - fluid_cond_mutex_lock(mixer->wakeup_threads_m); - while (1) { - int j = fluid_atomic_int_get(&buffers->ready); - if (j == THREAD_BUF_PROCESSING || j == THREAD_BUF_TERMINATE) - break; - fluid_cond_wait(mixer->wakeup_threads, mixer->wakeup_threads_m); - } - fluid_cond_mutex_unlock(mixer->wakeup_threads_m); - - hasValidData = 0; - } - else { - // else: if buffer is not zeroed, zero buffers - if (!hasValidData) { - // blockcount may have changed, since thread was put to sleep - current_blockcount = mixer->current_blockcount; - fluid_mixer_buffers_zero(buffers, current_blockcount); - bufcount = fluid_mixer_buffers_prepare(buffers, bufs); - hasValidData = 1; - } - // then render voice to buffers - fluid_mixer_buffers_render_one(buffers, rvoice, bufs, bufcount, local_buf, current_blockcount); - } - } + fluid_mixer_buffers_t *buffers = data; + fluid_rvoice_mixer_t *mixer = buffers->mixer; + int hasValidData = 0; + FLUID_DECLARE_VLA(fluid_real_t *, bufs, buffers->buf_count * 2 + buffers->fx_buf_count * 2); + int bufcount = 0; + int current_blockcount = 0; + fluid_real_t *local_buf = fluid_align_ptr(buffers->local_buf, FLUID_DEFAULT_ALIGNMENT); - return FLUID_THREAD_RETURN_VALUE; + while(!fluid_atomic_int_get(&mixer->threads_should_terminate)) + { + fluid_rvoice_t *rvoice = fluid_mixer_get_mt_rvoice(mixer); + + if(rvoice == NULL) + { + // if no voices: signal rendered buffers, sleep + fluid_atomic_int_set(&buffers->ready, hasValidData ? THREAD_BUF_VALID : THREAD_BUF_NODATA); + fluid_cond_mutex_lock(mixer->thread_ready_m); + fluid_cond_signal(mixer->thread_ready); + fluid_cond_mutex_unlock(mixer->thread_ready_m); + + fluid_cond_mutex_lock(mixer->wakeup_threads_m); + + while(1) + { + int j = fluid_atomic_int_get(&buffers->ready); + + if(j == THREAD_BUF_PROCESSING || j == THREAD_BUF_TERMINATE) + { + break; + } + + fluid_cond_wait(mixer->wakeup_threads, mixer->wakeup_threads_m); + } + + fluid_cond_mutex_unlock(mixer->wakeup_threads_m); + + hasValidData = 0; + } + else + { + // else: if buffer is not zeroed, zero buffers + if(!hasValidData) + { + // blockcount may have changed, since thread was put to sleep + current_blockcount = mixer->current_blockcount; + fluid_mixer_buffers_zero(buffers, current_blockcount); + bufcount = fluid_mixer_buffers_prepare(buffers, bufs); + hasValidData = 1; + } + + // then render voice to buffers + fluid_mixer_buffers_render_one(buffers, rvoice, bufs, bufcount, local_buf, current_blockcount); + } + } + + return FLUID_THREAD_RETURN_VALUE; } static void -fluid_mixer_buffers_mix(fluid_mixer_buffers_t* dst, fluid_mixer_buffers_t* src, int current_blockcount) +fluid_mixer_buffers_mix(fluid_mixer_buffers_t *dst, fluid_mixer_buffers_t *src, int current_blockcount) { - int i,j; - int scount = current_blockcount * FLUID_BUFSIZE; - int minbuf; - fluid_real_t *FLUID_RESTRICT base_src; - fluid_real_t *FLUID_RESTRICT base_dst; - - minbuf = dst->buf_count; - if (minbuf > src->buf_count) - minbuf = src->buf_count; - - base_src = fluid_align_ptr(src->left_buf, FLUID_DEFAULT_ALIGNMENT); - base_dst = fluid_align_ptr(dst->left_buf, FLUID_DEFAULT_ALIGNMENT); - for (i=0; i < minbuf; i++) - { - #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) - for (j=0; j < scount; j++) - { - int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; - base_dst[dsp_i] += base_src[dsp_i]; - } - } - - base_src = fluid_align_ptr(src->right_buf, FLUID_DEFAULT_ALIGNMENT); - base_dst = fluid_align_ptr(dst->right_buf, FLUID_DEFAULT_ALIGNMENT); - for (i=0; i < minbuf; i++) - { - #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) - for (j=0; j < scount; j++) - { - int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; - base_dst[dsp_i] += base_src[dsp_i]; - } - } + int i, j; + int scount = current_blockcount * FLUID_BUFSIZE; + int minbuf; + fluid_real_t *FLUID_RESTRICT base_src; + fluid_real_t *FLUID_RESTRICT base_dst; - minbuf = dst->fx_buf_count; - if (minbuf > src->fx_buf_count) - minbuf = src->fx_buf_count; - - base_src = fluid_align_ptr(src->fx_left_buf, FLUID_DEFAULT_ALIGNMENT); - base_dst = fluid_align_ptr(dst->fx_left_buf, FLUID_DEFAULT_ALIGNMENT); - for (i=0; i < minbuf; i++) - { - #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) - for (j=0; j < scount; j++) + minbuf = dst->buf_count; + + if(minbuf > src->buf_count) { - int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; - base_dst[dsp_i] += base_src[dsp_i]; + minbuf = src->buf_count; } - } - - base_src = fluid_align_ptr(src->fx_right_buf, FLUID_DEFAULT_ALIGNMENT); - base_dst = fluid_align_ptr(dst->fx_right_buf, FLUID_DEFAULT_ALIGNMENT); - for (i=0; i < minbuf; i++) - { - #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) - for (j=0; j < scount; j++) + + base_src = fluid_align_ptr(src->left_buf, FLUID_DEFAULT_ALIGNMENT); + base_dst = fluid_align_ptr(dst->left_buf, FLUID_DEFAULT_ALIGNMENT); + + for(i = 0; i < minbuf; i++) { - int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; - base_dst[dsp_i] += base_src[dsp_i]; + #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) + + for(j = 0; j < scount; j++) + { + int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; + base_dst[dsp_i] += base_src[dsp_i]; + } + } + + base_src = fluid_align_ptr(src->right_buf, FLUID_DEFAULT_ALIGNMENT); + base_dst = fluid_align_ptr(dst->right_buf, FLUID_DEFAULT_ALIGNMENT); + + for(i = 0; i < minbuf; i++) + { + #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) + + for(j = 0; j < scount; j++) + { + int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; + base_dst[dsp_i] += base_src[dsp_i]; + } + } + + minbuf = dst->fx_buf_count; + + if(minbuf > src->fx_buf_count) + { + minbuf = src->fx_buf_count; + } + + base_src = fluid_align_ptr(src->fx_left_buf, FLUID_DEFAULT_ALIGNMENT); + base_dst = fluid_align_ptr(dst->fx_left_buf, FLUID_DEFAULT_ALIGNMENT); + + for(i = 0; i < minbuf; i++) + { + #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) + + for(j = 0; j < scount; j++) + { + int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; + base_dst[dsp_i] += base_src[dsp_i]; + } + } + + base_src = fluid_align_ptr(src->fx_right_buf, FLUID_DEFAULT_ALIGNMENT); + base_dst = fluid_align_ptr(dst->fx_right_buf, FLUID_DEFAULT_ALIGNMENT); + + for(i = 0; i < minbuf; i++) + { + #pragma omp simd aligned(base_dst,base_src:FLUID_DEFAULT_ALIGNMENT) + + for(j = 0; j < scount; j++) + { + int dsp_i = i * FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE + j; + base_dst[dsp_i] += base_src[dsp_i]; + } } - } } /** - * Go through all threads and see if someone is finished for mixing + * Go through all threads and see if someone is finished for mixing */ static int -fluid_mixer_mix_in(fluid_rvoice_mixer_t* mixer, int extra_threads, int current_blockcount) +fluid_mixer_mix_in(fluid_rvoice_mixer_t *mixer, int extra_threads, int current_blockcount) { - int i, result, hasmixed; - do { - hasmixed = 0; - result = 0; - for (i=0; i < extra_threads; i++) { - int j = fluid_atomic_int_get(&mixer->threads[i].ready); - switch (j) { - case THREAD_BUF_PROCESSING: - result = 1; - break; - case THREAD_BUF_VALID: - fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_NODATA); - fluid_mixer_buffers_mix(&mixer->buffers, &mixer->threads[i], current_blockcount); - hasmixed = 1; - break; - } + int i, result, hasmixed; + + do + { + hasmixed = 0; + result = 0; + + for(i = 0; i < extra_threads; i++) + { + int j = fluid_atomic_int_get(&mixer->threads[i].ready); + + switch(j) + { + case THREAD_BUF_PROCESSING: + result = 1; + break; + + case THREAD_BUF_VALID: + fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_NODATA); + fluid_mixer_buffers_mix(&mixer->buffers, &mixer->threads[i], current_blockcount); + hasmixed = 1; + break; + } + } } - } while (hasmixed); - return result; + while(hasmixed); + + return result; } -static void -fluid_render_loop_multithread(fluid_rvoice_mixer_t* mixer, int current_blockcount) +static void +fluid_render_loop_multithread(fluid_rvoice_mixer_t *mixer, int current_blockcount) { - int i, bufcount; - fluid_real_t* local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT); - - FLUID_DECLARE_VLA(fluid_real_t*, bufs, - mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2); - // How many threads should we start this time? - int extra_threads = mixer->active_voices / VOICES_PER_THREAD; - if (extra_threads > mixer->thread_count) - extra_threads = mixer->thread_count; - if (extra_threads == 0) { - // No extra threads? No thread overhead! - fluid_render_loop_singlethread(mixer, current_blockcount); - return; - } + int i, bufcount; + fluid_real_t *local_buf = fluid_align_ptr(mixer->buffers.local_buf, FLUID_DEFAULT_ALIGNMENT); - bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs); - - // Prepare voice list - fluid_cond_mutex_lock(mixer->wakeup_threads_m); - fluid_atomic_int_set(&mixer->current_rvoice, 0); - for (i=0; i < extra_threads; i++) - fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_PROCESSING); - // Signal threads to wake up - fluid_cond_broadcast(mixer->wakeup_threads); - fluid_cond_mutex_unlock(mixer->wakeup_threads_m); - - // If thread is finished, mix it in - while (fluid_mixer_mix_in(mixer, extra_threads, current_blockcount)) { - // Otherwise get a voice and render it - fluid_rvoice_t* rvoice = fluid_mixer_get_mt_rvoice(mixer); - if (rvoice != NULL) { - fluid_profile_ref_var(prof_ref); - fluid_mixer_buffers_render_one(&mixer->buffers, rvoice, bufs, bufcount, local_buf, current_blockcount); - fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref,1, - current_blockcount * FLUID_BUFSIZE); - //test++; + FLUID_DECLARE_VLA(fluid_real_t *, bufs, + mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2); + // How many threads should we start this time? + int extra_threads = mixer->active_voices / VOICES_PER_THREAD; + + if(extra_threads > mixer->thread_count) + { + extra_threads = mixer->thread_count; } - else { - // If no voices, wait for mixes. Make sure one is still processing to avoid deadlock - int is_processing = 0; - //waits++; - fluid_cond_mutex_lock(mixer->thread_ready_m); - for (i=0; i < extra_threads; i++) - if (fluid_atomic_int_get(&mixer->threads[i].ready) == - THREAD_BUF_PROCESSING) - is_processing = 1; - if (is_processing) - fluid_cond_wait(mixer->thread_ready, mixer->thread_ready_m); - fluid_cond_mutex_unlock(mixer->thread_ready_m); + + if(extra_threads == 0) + { + // No extra threads? No thread overhead! + fluid_render_loop_singlethread(mixer, current_blockcount); + return; } - } - //FLUID_LOG(FLUID_DBG, "Blockcount: %d, mixed %d of %d voices myself, waits = %d", - // current_blockcount, test, mixer->active_voices, waits); + + bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs); + + // Prepare voice list + fluid_cond_mutex_lock(mixer->wakeup_threads_m); + fluid_atomic_int_set(&mixer->current_rvoice, 0); + + for(i = 0; i < extra_threads; i++) + { + fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_PROCESSING); + } + + // Signal threads to wake up + fluid_cond_broadcast(mixer->wakeup_threads); + fluid_cond_mutex_unlock(mixer->wakeup_threads_m); + + // If thread is finished, mix it in + while(fluid_mixer_mix_in(mixer, extra_threads, current_blockcount)) + { + // Otherwise get a voice and render it + fluid_rvoice_t *rvoice = fluid_mixer_get_mt_rvoice(mixer); + + if(rvoice != NULL) + { + fluid_profile_ref_var(prof_ref); + fluid_mixer_buffers_render_one(&mixer->buffers, rvoice, bufs, bufcount, local_buf, current_blockcount); + fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref, 1, + current_blockcount * FLUID_BUFSIZE); + //test++; + } + else + { + // If no voices, wait for mixes. Make sure one is still processing to avoid deadlock + int is_processing = 0; + //waits++; + fluid_cond_mutex_lock(mixer->thread_ready_m); + + for(i = 0; i < extra_threads; i++) + { + if(fluid_atomic_int_get(&mixer->threads[i].ready) == + THREAD_BUF_PROCESSING) + { + is_processing = 1; + } + } + + if(is_processing) + { + fluid_cond_wait(mixer->thread_ready, mixer->thread_ready_m); + } + + fluid_cond_mutex_unlock(mixer->thread_ready_m); + } + } + + //FLUID_LOG(FLUID_DBG, "Blockcount: %d, mixed %d of %d voices myself, waits = %d", + // current_blockcount, test, mixer->active_voices, waits); } -static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t* mixer) +static void delete_rvoice_mixer_threads(fluid_rvoice_mixer_t *mixer) { int i; fluid_atomic_int_set(&mixer->threads_should_terminate, 1); // Signal threads to wake up fluid_cond_mutex_lock(mixer->wakeup_threads_m); - for (i=0; i < mixer->thread_count; i++) - fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE); + + for(i = 0; i < mixer->thread_count; i++) + { + fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE); + } + fluid_cond_broadcast(mixer->wakeup_threads); fluid_cond_mutex_unlock(mixer->wakeup_threads_m); - - for (i=0; i < mixer->thread_count; i++) { - if (mixer->threads[i].thread) { - fluid_thread_join(mixer->threads[i].thread); - delete_fluid_thread(mixer->threads[i].thread); - } - fluid_mixer_buffers_free(&mixer->threads[i]); + + for(i = 0; i < mixer->thread_count; i++) + { + if(mixer->threads[i].thread) + { + fluid_thread_join(mixer->threads[i].thread); + delete_fluid_thread(mixer->threads[i].thread); + } + + fluid_mixer_buffers_free(&mixer->threads[i]); } + FLUID_FREE(mixer->threads); mixer->thread_count = 0; mixer->threads = NULL; } /** - * Update amount of extra mixer threads. + * Update amount of extra mixer threads. * @param thread_count Number of extra mixer threads for multi-core rendering * @param prio_level real-time prio level for the extra mixer threads */ -static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t* mixer, int thread_count, int prio_level) +static int fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t *mixer, int thread_count, int prio_level) { - char name[16]; - int i; - - // Kill all existing threads first - if (mixer->thread_count) - { - delete_rvoice_mixer_threads(mixer); - } - - if (thread_count == 0) + char name[16]; + int i; + + // Kill all existing threads first + if(mixer->thread_count) + { + delete_rvoice_mixer_threads(mixer); + } + + if(thread_count == 0) + { + return FLUID_OK; + } + + // Now prepare the new threads + fluid_atomic_int_set(&mixer->threads_should_terminate, 0); + mixer->threads = FLUID_ARRAY(fluid_mixer_buffers_t, thread_count); + + if(mixer->threads == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } + + FLUID_MEMSET(mixer->threads, 0, thread_count * sizeof(fluid_mixer_buffers_t)); + mixer->thread_count = thread_count; + + for(i = 0; i < thread_count; i++) + { + fluid_mixer_buffers_t *b = &mixer->threads[i]; + + if(!fluid_mixer_buffers_init(b, mixer)) + { + return FLUID_FAILED; + } + + fluid_atomic_int_set(&b->ready, THREAD_BUF_NODATA); + FLUID_SNPRINTF(name, sizeof(name), "mixer%d", i); + b->thread = new_fluid_thread(name, fluid_mixer_thread_func, b, prio_level, 0); + + if(!b->thread) + { + return FLUID_FAILED; + } + } + return FLUID_OK; - - // Now prepare the new threads - fluid_atomic_int_set(&mixer->threads_should_terminate, 0); - mixer->threads = FLUID_ARRAY(fluid_mixer_buffers_t, thread_count); - if (mixer->threads == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } - FLUID_MEMSET(mixer->threads, 0, thread_count*sizeof(fluid_mixer_buffers_t)); - mixer->thread_count = thread_count; - for (i=0; i < thread_count; i++) { - fluid_mixer_buffers_t* b = &mixer->threads[i]; - if (!fluid_mixer_buffers_init(b, mixer)) - return FLUID_FAILED; - fluid_atomic_int_set(&b->ready, THREAD_BUF_NODATA); - FLUID_SNPRINTF (name, sizeof (name), "mixer%d", i); - b->thread = new_fluid_thread(name, fluid_mixer_thread_func, b, prio_level, 0); - if (!b->thread) - return FLUID_FAILED; - } - return FLUID_OK; } #endif /** * Synthesize audio into buffers - * @param blockcount number of blocks to render, each having FLUID_BUFSIZE samples + * @param blockcount number of blocks to render, each having FLUID_BUFSIZE samples * @return number of blocks rendered */ -int -fluid_rvoice_mixer_render(fluid_rvoice_mixer_t* mixer, int blockcount) +int +fluid_rvoice_mixer_render(fluid_rvoice_mixer_t *mixer, int blockcount) { - fluid_profile_ref_var(prof_ref); - - mixer->current_blockcount = blockcount; + fluid_profile_ref_var(prof_ref); + + mixer->current_blockcount = blockcount; + + // Zero buffers + fluid_mixer_buffers_zero(&mixer->buffers, blockcount); + fluid_profile(FLUID_PROF_ONE_BLOCK_CLEAR, prof_ref, mixer->active_voices, + blockcount * FLUID_BUFSIZE); - // Zero buffers - fluid_mixer_buffers_zero(&mixer->buffers, blockcount); - fluid_profile(FLUID_PROF_ONE_BLOCK_CLEAR, prof_ref, mixer->active_voices, - blockcount * FLUID_BUFSIZE); - #if ENABLE_MIXER_THREADS - if (mixer->thread_count > 0) - fluid_render_loop_multithread(mixer, blockcount); - else + + if(mixer->thread_count > 0) + { + fluid_render_loop_multithread(mixer, blockcount); + } + else + { #endif - fluid_render_loop_singlethread(mixer, blockcount); - fluid_profile(FLUID_PROF_ONE_BLOCK_VOICES, prof_ref, mixer->active_voices, - blockcount * FLUID_BUFSIZE); - + fluid_render_loop_singlethread(mixer, blockcount); + } - // Process reverb & chorus - fluid_rvoice_mixer_process_fx(mixer, blockcount); + fluid_profile(FLUID_PROF_ONE_BLOCK_VOICES, prof_ref, mixer->active_voices, + blockcount * FLUID_BUFSIZE); - // Call the callback and pack active voice array - fluid_rvoice_mixer_process_finished_voices(mixer); - return blockcount; + // Process reverb & chorus + fluid_rvoice_mixer_process_fx(mixer, blockcount); + + // Call the callback and pack active voice array + fluid_rvoice_mixer_process_finished_voices(mixer); + + return blockcount; } diff --git a/src/rvoice/fluid_rvoice_mixer.h b/src/rvoice/fluid_rvoice_mixer.h index c61a212e..61b4359d 100644 --- a/src/rvoice/fluid_rvoice_mixer.h +++ b/src/rvoice/fluid_rvoice_mixer.h @@ -28,19 +28,19 @@ typedef struct _fluid_rvoice_mixer_t fluid_rvoice_mixer_t; -int fluid_rvoice_mixer_render(fluid_rvoice_mixer_t* mixer, int blockcount); -int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t* mixer, - fluid_real_t** left, fluid_real_t** right); -int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t* mixer, - fluid_real_t** fx_left, fluid_real_t** fx_right); -int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t* mixer); +int fluid_rvoice_mixer_render(fluid_rvoice_mixer_t *mixer, int blockcount); +int fluid_rvoice_mixer_get_bufs(fluid_rvoice_mixer_t *mixer, + fluid_real_t **left, fluid_real_t **right); +int fluid_rvoice_mixer_get_fx_bufs(fluid_rvoice_mixer_t *mixer, + fluid_real_t **fx_left, fluid_real_t **fx_right); +int fluid_rvoice_mixer_get_bufcount(fluid_rvoice_mixer_t *mixer); #if WITH_PROFILING -int fluid_rvoice_mixer_get_active_voices(fluid_rvoice_mixer_t* mixer); +int fluid_rvoice_mixer_get_active_voices(fluid_rvoice_mixer_t *mixer); #endif -fluid_rvoice_mixer_t* new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, - fluid_real_t sample_rate, fluid_rvoice_eventhandler_t*, int, int); +fluid_rvoice_mixer_t *new_fluid_rvoice_mixer(int buf_count, int fx_buf_count, + fluid_real_t sample_rate, fluid_rvoice_eventhandler_t *, int, int); -void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t*); +void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t *); DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_add_voice); @@ -56,10 +56,10 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_mixer_reset_chorus); -void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t* mixer, int on); +void fluid_rvoice_mixer_set_mix_fx(fluid_rvoice_mixer_t *mixer, int on); #ifdef LADSPA -void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer, - fluid_ladspa_fx_t *ladspa_fx, int audio_groups); +void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t *mixer, + fluid_ladspa_fx_t *ladspa_fx, int audio_groups); #endif #endif diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index de10542b..0a2e3708 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -39,7 +39,7 @@ static int unload_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *pre static void unload_sample(fluid_sample_t *sample); static int dynamic_samples_preset_notify(fluid_preset_t *preset, int reason, int chan); static int dynamic_samples_sample_notify(fluid_sample_t *sample, int reason); -static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t* preset_zone); +static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t *preset_zone); static fluid_inst_t *find_inst_by_idx(fluid_defsfont_t *defsfont, int idx); @@ -52,59 +52,63 @@ static fluid_inst_t *find_inst_by_idx(fluid_defsfont_t *defsfont, int idx); * Creates a default soundfont2 loader that can be used with fluid_synth_add_sfloader(). * By default every synth instance has an initial default soundfont loader instance. * Calling this function is usually only necessary to load a soundfont from memory, by providing custom callback functions via fluid_sfloader_set_callbacks(). - * + * * @param settings A settings instance obtained by new_fluid_settings() * @return A default soundfont2 loader struct */ -fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings) +fluid_sfloader_t *new_fluid_defsfloader(fluid_settings_t *settings) { - fluid_sfloader_t* loader; - fluid_return_val_if_fail(settings != NULL, NULL); + fluid_sfloader_t *loader; + fluid_return_val_if_fail(settings != NULL, NULL); - loader = new_fluid_sfloader(fluid_defsfloader_load, delete_fluid_sfloader); - - if (loader == NULL) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + loader = new_fluid_sfloader(fluid_defsfloader_load, delete_fluid_sfloader); - fluid_sfloader_set_data(loader, settings); + if(loader == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - return loader; + fluid_sfloader_set_data(loader, settings); + + return loader; } -fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* filename) +fluid_sfont_t *fluid_defsfloader_load(fluid_sfloader_t *loader, const char *filename) { - fluid_defsfont_t* defsfont; - fluid_sfont_t* sfont; + fluid_defsfont_t *defsfont; + fluid_sfont_t *sfont; - defsfont = new_fluid_defsfont(fluid_sfloader_get_data(loader)); + defsfont = new_fluid_defsfont(fluid_sfloader_get_data(loader)); - if (defsfont == NULL) { - return NULL; - } + if(defsfont == NULL) + { + return NULL; + } - sfont = new_fluid_sfont(fluid_defsfont_sfont_get_name, - fluid_defsfont_sfont_get_preset, - fluid_defsfont_sfont_iteration_start, - fluid_defsfont_sfont_iteration_next, - fluid_defsfont_sfont_delete); - if (sfont == NULL) - { - delete_fluid_defsfont(defsfont); - return NULL; - } - - fluid_sfont_set_data(sfont, defsfont); + sfont = new_fluid_sfont(fluid_defsfont_sfont_get_name, + fluid_defsfont_sfont_get_preset, + fluid_defsfont_sfont_iteration_start, + fluid_defsfont_sfont_iteration_next, + fluid_defsfont_sfont_delete); - defsfont->sfont = sfont; - if (fluid_defsfont_load(defsfont, &loader->file_callbacks, filename) == FLUID_FAILED) { - fluid_sfont_delete_internal(sfont); - return NULL; - } + if(sfont == NULL) + { + delete_fluid_defsfont(defsfont); + return NULL; + } - return sfont; + fluid_sfont_set_data(sfont, defsfont); + + defsfont->sfont = sfont; + + if(fluid_defsfont_load(defsfont, &loader->file_callbacks, filename) == FLUID_FAILED) + { + fluid_sfont_delete_internal(sfont); + return NULL; + } + + return sfont; } @@ -114,72 +118,74 @@ fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* file * PUBLIC INTERFACE */ -int fluid_defsfont_sfont_delete(fluid_sfont_t* sfont) +int fluid_defsfont_sfont_delete(fluid_sfont_t *sfont) { - if (delete_fluid_defsfont(fluid_sfont_get_data(sfont)) != FLUID_OK) { - return -1; - } - delete_fluid_sfont(sfont); - return 0; + if(delete_fluid_defsfont(fluid_sfont_get_data(sfont)) != FLUID_OK) + { + return -1; + } + + delete_fluid_sfont(sfont); + return 0; } -const char* fluid_defsfont_sfont_get_name(fluid_sfont_t* sfont) +const char *fluid_defsfont_sfont_get_name(fluid_sfont_t *sfont) { - return fluid_defsfont_get_name(fluid_sfont_get_data(sfont)); + return fluid_defsfont_get_name(fluid_sfont_get_data(sfont)); } -fluid_preset_t* -fluid_defsfont_sfont_get_preset(fluid_sfont_t* sfont, int bank, int prenum) +fluid_preset_t * +fluid_defsfont_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum) { - return fluid_defsfont_get_preset(fluid_sfont_get_data(sfont), bank, prenum); + return fluid_defsfont_get_preset(fluid_sfont_get_data(sfont), bank, prenum); } -void fluid_defsfont_sfont_iteration_start(fluid_sfont_t* sfont) +void fluid_defsfont_sfont_iteration_start(fluid_sfont_t *sfont) { - fluid_defsfont_iteration_start(fluid_sfont_get_data(sfont)); + fluid_defsfont_iteration_start(fluid_sfont_get_data(sfont)); } -fluid_preset_t *fluid_defsfont_sfont_iteration_next(fluid_sfont_t* sfont) +fluid_preset_t *fluid_defsfont_sfont_iteration_next(fluid_sfont_t *sfont) { - return fluid_defsfont_iteration_next(fluid_sfont_get_data(sfont)); + return fluid_defsfont_iteration_next(fluid_sfont_get_data(sfont)); } -void fluid_defpreset_preset_delete(fluid_preset_t* preset) +void fluid_defpreset_preset_delete(fluid_preset_t *preset) { - fluid_defsfont_t* defsfont; - fluid_defpreset_t* defpreset; + fluid_defsfont_t *defsfont; + fluid_defpreset_t *defpreset; - defsfont = fluid_sfont_get_data(preset->sfont); - defpreset = fluid_preset_get_data(preset); + defsfont = fluid_sfont_get_data(preset->sfont); + defpreset = fluid_preset_get_data(preset); - if (defsfont) - { - defsfont->preset = fluid_list_remove(defsfont->preset, defpreset); - } + if(defsfont) + { + defsfont->preset = fluid_list_remove(defsfont->preset, defpreset); + } - delete_fluid_defpreset(defpreset); - delete_fluid_preset(preset); + delete_fluid_defpreset(defpreset); + delete_fluid_preset(preset); } -const char* fluid_defpreset_preset_get_name(fluid_preset_t* preset) +const char *fluid_defpreset_preset_get_name(fluid_preset_t *preset) { - return fluid_defpreset_get_name(fluid_preset_get_data(preset)); + return fluid_defpreset_get_name(fluid_preset_get_data(preset)); } -int fluid_defpreset_preset_get_banknum(fluid_preset_t* preset) +int fluid_defpreset_preset_get_banknum(fluid_preset_t *preset) { - return fluid_defpreset_get_banknum(fluid_preset_get_data(preset)); + return fluid_defpreset_get_banknum(fluid_preset_get_data(preset)); } -int fluid_defpreset_preset_get_num(fluid_preset_t* preset) +int fluid_defpreset_preset_get_num(fluid_preset_t *preset) { - return fluid_defpreset_get_num(fluid_preset_get_data(preset)); + return fluid_defpreset_get_num(fluid_preset_get_data(preset)); } -int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, - int chan, int key, int vel) +int fluid_defpreset_preset_noteon(fluid_preset_t *preset, fluid_synth_t *synth, + int chan, int key, int vel) { - return fluid_defpreset_noteon(fluid_preset_get_data(preset), synth, chan, key, vel); + return fluid_defpreset_noteon(fluid_preset_get_data(preset), synth, chan, key, vel); } @@ -191,80 +197,93 @@ int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, /* * new_fluid_defsfont */ -fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings) +fluid_defsfont_t *new_fluid_defsfont(fluid_settings_t *settings) { - fluid_defsfont_t* defsfont; + fluid_defsfont_t *defsfont; - defsfont = FLUID_NEW(fluid_defsfont_t); - if (defsfont == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + defsfont = FLUID_NEW(fluid_defsfont_t); - FLUID_MEMSET(defsfont, 0, sizeof(*defsfont)); - - fluid_settings_getint(settings, "synth.lock-memory", &defsfont->mlock); - fluid_settings_getint(settings, "synth.dynamic-sample-loading", &defsfont->dynamic_samples); + if(defsfont == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - return defsfont; + FLUID_MEMSET(defsfont, 0, sizeof(*defsfont)); + + fluid_settings_getint(settings, "synth.lock-memory", &defsfont->mlock); + fluid_settings_getint(settings, "synth.dynamic-sample-loading", &defsfont->dynamic_samples); + + return defsfont; } /* * delete_fluid_defsfont */ -int delete_fluid_defsfont(fluid_defsfont_t* defsfont) +int delete_fluid_defsfont(fluid_defsfont_t *defsfont) { - fluid_list_t *list; - fluid_preset_t* preset; - fluid_sample_t* sample; + fluid_list_t *list; + fluid_preset_t *preset; + fluid_sample_t *sample; - fluid_return_val_if_fail(defsfont != NULL, FLUID_OK); - - /* Check that no samples are currently used */ - for (list = defsfont->sample; list; list = fluid_list_next(list)) { - sample = (fluid_sample_t*) fluid_list_get(list); - if (sample->refcount != 0) { - return FLUID_FAILED; + fluid_return_val_if_fail(defsfont != NULL, FLUID_OK); + + /* Check that no samples are currently used */ + for(list = defsfont->sample; list; list = fluid_list_next(list)) + { + sample = (fluid_sample_t *) fluid_list_get(list); + + if(sample->refcount != 0) + { + return FLUID_FAILED; + } } - } - if (defsfont->filename != NULL) { - FLUID_FREE(defsfont->filename); - } + if(defsfont->filename != NULL) + { + FLUID_FREE(defsfont->filename); + } - for (list = defsfont->sample; list; list = fluid_list_next(list)) { - delete_fluid_sample((fluid_sample_t*) fluid_list_get(list)); - } + for(list = defsfont->sample; list; list = fluid_list_next(list)) + { + delete_fluid_sample((fluid_sample_t *) fluid_list_get(list)); + } - if (defsfont->sample) { - delete_fluid_list(defsfont->sample); - } + if(defsfont->sample) + { + delete_fluid_list(defsfont->sample); + } - if (defsfont->sampledata != NULL) { - fluid_samplecache_unload(defsfont->sampledata); - } + if(defsfont->sampledata != NULL) + { + fluid_samplecache_unload(defsfont->sampledata); + } - for (list = defsfont->preset; list; list = fluid_list_next(list)) { - preset = (fluid_preset_t *)fluid_list_get(list); - fluid_defpreset_preset_delete(preset); - } - delete_fluid_list(defsfont->preset); + for(list = defsfont->preset; list; list = fluid_list_next(list)) + { + preset = (fluid_preset_t *)fluid_list_get(list); + fluid_defpreset_preset_delete(preset); + } - for (list = defsfont->inst; list; list = fluid_list_next(list)) { - delete_fluid_inst(fluid_list_get(list)); - } - delete_fluid_list(defsfont->inst); + delete_fluid_list(defsfont->preset); - FLUID_FREE(defsfont); - return FLUID_OK; + for(list = defsfont->inst; list; list = fluid_list_next(list)) + { + delete_fluid_inst(fluid_list_get(list)); + } + + delete_fluid_list(defsfont->inst); + + FLUID_FREE(defsfont); + return FLUID_OK; } /* * fluid_defsfont_get_name */ -const char* fluid_defsfont_get_name(fluid_defsfont_t* defsfont) +const char *fluid_defsfont_get_name(fluid_defsfont_t *defsfont) { - return defsfont->filename; + return defsfont->filename; } /* Load sample data for a single sample from the Soundfont file. @@ -278,37 +297,37 @@ int fluid_defsfont_load_sampledata(fluid_defsfont_t *defsfont, SFData *sfdata, f /* For uncompressed samples we want to include the 46 zero sample word area following each sample * in the Soundfont. Otherwise samples with loopend > end, which we have decided not to correct, would * be corrected after all in fluid_sample_sanitize_loop */ - if (!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS)) + if(!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS)) { source_end += 46; /* Length of zero sample word after each sample, according to SF specs */ /* Safeguard against Soundfonts that are not quite valid and don't include 46 sample words after the * last sample */ - if (source_end >= (defsfont->samplesize / sizeof(short))) + if(source_end >= (defsfont->samplesize / sizeof(short))) { source_end = defsfont->samplesize / sizeof(short); } } num_samples = fluid_samplecache_load( - sfdata, sample->source_start, source_end, sample->sampletype, - defsfont->mlock, &sample->data, &sample->data24); + sfdata, sample->source_start, source_end, sample->sampletype, + defsfont->mlock, &sample->data, &sample->data24); - if (num_samples < 0) + if(num_samples < 0) { return FLUID_FAILED; } - if (num_samples == 0) + if(num_samples == 0) { sample->start = sample->end = 0; - sample->loopstart= sample->loopend = 0; + sample->loopstart = sample->loopend = 0; return FLUID_OK; } /* Ogg Vorbis samples already have loop pointers relative to the invididual decompressed sample, * but SF2 samples are relative to sample chunk start, so they need to be adjusted */ - if (!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS)) + if(!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS)) { sample->loopstart = sample->source_loopstart - sample->source_start; sample->loopend = sample->source_loopend - sample->source_start; @@ -333,34 +352,36 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat int sf3_file = (sfdata->version.major == 3); /* For SF2 files, we load the sample data in one large block */ - if (!sf3_file) + if(!sf3_file) { int read_samples; int num_samples = sfdata->samplesize / sizeof(short); read_samples = fluid_samplecache_load(sfdata, 0, num_samples - 1, 0, defsfont->mlock, - &defsfont->sampledata, &defsfont->sample24data); - if (read_samples != num_samples) + &defsfont->sampledata, &defsfont->sample24data); + + if(read_samples != num_samples) { FLUID_LOG(FLUID_ERR, "Attempted to read %d words of sample data, but got %d instead", - num_samples, read_samples); + num_samples, read_samples); return FLUID_FAILED; } } - for (list = defsfont->sample; list; list = fluid_list_next(list)) + for(list = defsfont->sample; list; list = fluid_list_next(list)) { sample = fluid_list_get(list); - if (sf3_file) + if(sf3_file) { /* SF3 samples get loaded individually, as most (or all) of them are in Ogg Vorbis format * anyway */ - if (fluid_defsfont_load_sampledata(defsfont, sfdata, sample) == FLUID_FAILED) + if(fluid_defsfont_load_sampledata(defsfont, sfdata, sample) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Failed to load sample '%s'", sample->name); return FLUID_FAILED; } + fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short)); } else @@ -380,117 +401,138 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat /* * fluid_defsfont_load */ -int fluid_defsfont_load(fluid_defsfont_t* defsfont, const fluid_file_callbacks_t* fcbs, const char* file) +int fluid_defsfont_load(fluid_defsfont_t *defsfont, const fluid_file_callbacks_t *fcbs, const char *file) { - SFData* sfdata; - fluid_list_t *p; - SFPreset* sfpreset; - SFSample* sfsample; - fluid_sample_t* sample; - fluid_defpreset_t* defpreset = NULL; + SFData *sfdata; + fluid_list_t *p; + SFPreset *sfpreset; + SFSample *sfsample; + fluid_sample_t *sample; + fluid_defpreset_t *defpreset = NULL; - defsfont->filename = FLUID_STRDUP(file); - if (defsfont->filename == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } + defsfont->filename = FLUID_STRDUP(file); - defsfont->fcbs = fcbs; - - /* The actual loading is done in the sfont and sffile files */ - sfdata = fluid_sffile_open(file, fcbs); - if (sfdata == NULL) { - FLUID_LOG(FLUID_ERR, "Couldn't load soundfont file"); - return FLUID_FAILED; - } - - if (fluid_sffile_parse_presets(sfdata) == FLUID_FAILED) { - FLUID_LOG(FLUID_ERR, "Couldn't parse presets from soundfont file"); - goto err_exit; - } - - /* Keep track of the position and size of the sample data because - it's loaded separately (and might be unoaded/reloaded in future) */ - defsfont->samplepos = sfdata->samplepos; - defsfont->samplesize = sfdata->samplesize; - defsfont->sample24pos = sfdata->sample24pos; - defsfont->sample24size = sfdata->sample24size; - - /* Create all samples from sample headers */ - p = sfdata->sample; - while (p != NULL) { - sfsample = (SFSample *)fluid_list_get(p); - - sample = new_fluid_sample(); - if (sample == NULL) goto err_exit; - - if (fluid_sample_import_sfont(sample, sfsample, defsfont) == FLUID_OK) + if(defsfont->filename == NULL) { - fluid_defsfont_add_sample(defsfont, sample); - } - else - { - delete_fluid_sample(sample); - sample = NULL; + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; } - /* Store reference to FluidSynth sample in SFSample for later IZone fixups */ - sfsample->fluid_sample = sample; + defsfont->fcbs = fcbs; - p = fluid_list_next(p); - } + /* The actual loading is done in the sfont and sffile files */ + sfdata = fluid_sffile_open(file, fcbs); - /* If dynamic sample loading is disabled, load all samples in the Soundfont */ - if (!defsfont->dynamic_samples) - { - if (fluid_defsfont_load_all_sampledata(defsfont, sfdata) == FLUID_FAILED) + if(sfdata == NULL) { - FLUID_LOG(FLUID_ERR, "Unable to load all sample data"); + FLUID_LOG(FLUID_ERR, "Couldn't load soundfont file"); + return FLUID_FAILED; + } + + if(fluid_sffile_parse_presets(sfdata) == FLUID_FAILED) + { + FLUID_LOG(FLUID_ERR, "Couldn't parse presets from soundfont file"); goto err_exit; } - } - /* Load all the presets */ - p = sfdata->preset; - while (p != NULL) { - sfpreset = (SFPreset *)fluid_list_get(p); - defpreset = new_fluid_defpreset(defsfont); - if (defpreset == NULL) goto err_exit; + /* Keep track of the position and size of the sample data because + it's loaded separately (and might be unoaded/reloaded in future) */ + defsfont->samplepos = sfdata->samplepos; + defsfont->samplesize = sfdata->samplesize; + defsfont->sample24pos = sfdata->sample24pos; + defsfont->sample24size = sfdata->sample24size; - if (fluid_defpreset_import_sfont(defpreset, sfpreset, defsfont) != FLUID_OK) - goto err_exit; + /* Create all samples from sample headers */ + p = sfdata->sample; - if (fluid_defsfont_add_preset(defsfont, defpreset) == FLUID_FAILED) + while(p != NULL) { - goto err_exit; - } - p = fluid_list_next(p); - } - fluid_sffile_close (sfdata); + sfsample = (SFSample *)fluid_list_get(p); - return FLUID_OK; + sample = new_fluid_sample(); + + if(sample == NULL) + { + goto err_exit; + } + + if(fluid_sample_import_sfont(sample, sfsample, defsfont) == FLUID_OK) + { + fluid_defsfont_add_sample(defsfont, sample); + } + else + { + delete_fluid_sample(sample); + sample = NULL; + } + + /* Store reference to FluidSynth sample in SFSample for later IZone fixups */ + sfsample->fluid_sample = sample; + + p = fluid_list_next(p); + } + + /* If dynamic sample loading is disabled, load all samples in the Soundfont */ + if(!defsfont->dynamic_samples) + { + if(fluid_defsfont_load_all_sampledata(defsfont, sfdata) == FLUID_FAILED) + { + FLUID_LOG(FLUID_ERR, "Unable to load all sample data"); + goto err_exit; + } + } + + /* Load all the presets */ + p = sfdata->preset; + + while(p != NULL) + { + sfpreset = (SFPreset *)fluid_list_get(p); + defpreset = new_fluid_defpreset(defsfont); + + if(defpreset == NULL) + { + goto err_exit; + } + + if(fluid_defpreset_import_sfont(defpreset, sfpreset, defsfont) != FLUID_OK) + { + goto err_exit; + } + + if(fluid_defsfont_add_preset(defsfont, defpreset) == FLUID_FAILED) + { + goto err_exit; + } + + p = fluid_list_next(p); + } + + fluid_sffile_close(sfdata); + + return FLUID_OK; err_exit: - fluid_sffile_close (sfdata); - delete_fluid_defpreset(defpreset); - return FLUID_FAILED; + fluid_sffile_close(sfdata); + delete_fluid_defpreset(defpreset); + return FLUID_FAILED; } /* fluid_defsfont_add_sample * * Add a sample to the SoundFont */ -int fluid_defsfont_add_sample(fluid_defsfont_t* defsfont, fluid_sample_t* sample) +int fluid_defsfont_add_sample(fluid_defsfont_t *defsfont, fluid_sample_t *sample) { - defsfont->sample = fluid_list_append(defsfont->sample, sample); - return FLUID_OK; + defsfont->sample = fluid_list_append(defsfont->sample, sample); + return FLUID_OK; } /* fluid_defsfont_add_preset * * Add a preset to the SoundFont */ -int fluid_defsfont_add_preset(fluid_defsfont_t* defsfont, fluid_defpreset_t* defpreset) +int fluid_defsfont_add_preset(fluid_defsfont_t *defsfont, fluid_defpreset_t *defpreset) { fluid_preset_t *preset; @@ -501,12 +543,13 @@ int fluid_defsfont_add_preset(fluid_defsfont_t* defsfont, fluid_defpreset_t* def fluid_defpreset_preset_noteon, fluid_defpreset_preset_delete); - if (defsfont->dynamic_samples) + if(defsfont->dynamic_samples) { preset->notify = dynamic_samples_preset_notify; } - if (preset == NULL) { + if(preset == NULL) + { return FLUID_FAILED; } @@ -520,7 +563,7 @@ int fluid_defsfont_add_preset(fluid_defsfont_t* defsfont, fluid_defpreset_t* def /* * fluid_defsfont_get_preset */ -fluid_preset_t* fluid_defsfont_get_preset(fluid_defsfont_t* defsfont, int bank, int num) +fluid_preset_t *fluid_defsfont_get_preset(fluid_defsfont_t *defsfont, int bank, int num) { fluid_preset_t *preset; fluid_list_t *list; @@ -529,7 +572,7 @@ fluid_preset_t* fluid_defsfont_get_preset(fluid_defsfont_t* defsfont, int bank, { preset = (fluid_preset_t *)fluid_list_get(list); - if ((fluid_preset_get_banknum(preset) == bank) && (fluid_preset_get_num(preset) == num)) + if((fluid_preset_get_banknum(preset) == bank) && (fluid_preset_get_num(preset) == num)) { return preset; } @@ -541,15 +584,15 @@ fluid_preset_t* fluid_defsfont_get_preset(fluid_defsfont_t* defsfont, int bank, /* * fluid_defsfont_iteration_start */ -void fluid_defsfont_iteration_start(fluid_defsfont_t* defsfont) +void fluid_defsfont_iteration_start(fluid_defsfont_t *defsfont) { - defsfont->preset_iter_cur = defsfont->preset; + defsfont->preset_iter_cur = defsfont->preset; } /* * fluid_defsfont_iteration_next */ -fluid_preset_t *fluid_defsfont_iteration_next(fluid_defsfont_t* defsfont) +fluid_preset_t *fluid_defsfont_iteration_next(fluid_defsfont_t *defsfont) { fluid_preset_t *preset = (fluid_preset_t *)fluid_list_get(defsfont->preset_iter_cur); @@ -566,71 +609,77 @@ fluid_preset_t *fluid_defsfont_iteration_next(fluid_defsfont_t* defsfont) /* * new_fluid_defpreset */ -fluid_defpreset_t* -new_fluid_defpreset(fluid_defsfont_t* defsfont) +fluid_defpreset_t * +new_fluid_defpreset(fluid_defsfont_t *defsfont) { - fluid_defpreset_t* defpreset = FLUID_NEW(fluid_defpreset_t); - if (defpreset == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - defpreset->next = NULL; - defpreset->defsfont = defsfont; - defpreset->name[0] = 0; - defpreset->bank = 0; - defpreset->num = 0; - defpreset->global_zone = NULL; - defpreset->zone = NULL; - return defpreset; + fluid_defpreset_t *defpreset = FLUID_NEW(fluid_defpreset_t); + + if(defpreset == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + defpreset->next = NULL; + defpreset->defsfont = defsfont; + defpreset->name[0] = 0; + defpreset->bank = 0; + defpreset->num = 0; + defpreset->global_zone = NULL; + defpreset->zone = NULL; + return defpreset; } /* * delete_fluid_defpreset */ void -delete_fluid_defpreset(fluid_defpreset_t* defpreset) +delete_fluid_defpreset(fluid_defpreset_t *defpreset) { - fluid_preset_zone_t* zone; - - fluid_return_if_fail(defpreset != NULL); - + fluid_preset_zone_t *zone; + + fluid_return_if_fail(defpreset != NULL); + delete_fluid_preset_zone(defpreset->global_zone); defpreset->global_zone = NULL; - - zone = defpreset->zone; - while (zone != NULL) { - defpreset->zone = zone->next; - delete_fluid_preset_zone(zone); + zone = defpreset->zone; - } - FLUID_FREE(defpreset); + + while(zone != NULL) + { + defpreset->zone = zone->next; + delete_fluid_preset_zone(zone); + zone = defpreset->zone; + } + + FLUID_FREE(defpreset); } int -fluid_defpreset_get_banknum(fluid_defpreset_t* defpreset) +fluid_defpreset_get_banknum(fluid_defpreset_t *defpreset) { - return defpreset->bank; + return defpreset->bank; } int -fluid_defpreset_get_num(fluid_defpreset_t* defpreset) +fluid_defpreset_get_num(fluid_defpreset_t *defpreset) { - return defpreset->num; + return defpreset->num; } -const char* -fluid_defpreset_get_name(fluid_defpreset_t* defpreset) +const char * +fluid_defpreset_get_name(fluid_defpreset_t *defpreset) { - return defpreset->name; + return defpreset->name; } /* * fluid_defpreset_next */ -fluid_defpreset_t* -fluid_defpreset_next(fluid_defpreset_t* defpreset) +fluid_defpreset_t * +fluid_defpreset_next(fluid_defpreset_t *defpreset) { - return defpreset->next; + return defpreset->next; } @@ -638,308 +687,369 @@ fluid_defpreset_next(fluid_defpreset_t* defpreset) * fluid_defpreset_noteon */ int -fluid_defpreset_noteon(fluid_defpreset_t* defpreset, fluid_synth_t* synth, int chan, int key, int vel) +fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int chan, int key, int vel) { - fluid_preset_zone_t *preset_zone, *global_preset_zone; - fluid_inst_t* inst; - fluid_inst_zone_t *inst_zone, *global_inst_zone; - fluid_voice_zone_t *voice_zone; - fluid_list_t *list; - fluid_voice_t* voice; - fluid_mod_t * mod; - fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */ - int mod_list_count; - int i; + fluid_preset_zone_t *preset_zone, *global_preset_zone; + fluid_inst_t *inst; + fluid_inst_zone_t *inst_zone, *global_inst_zone; + fluid_voice_zone_t *voice_zone; + fluid_list_t *list; + fluid_voice_t *voice; + fluid_mod_t *mod; + fluid_mod_t *mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */ + int mod_list_count; + int i; - global_preset_zone = fluid_defpreset_get_global_zone(defpreset); + global_preset_zone = fluid_defpreset_get_global_zone(defpreset); - /* run thru all the zones of this preset */ - preset_zone = fluid_defpreset_get_zone(defpreset); - while (preset_zone != NULL) { + /* run thru all the zones of this preset */ + preset_zone = fluid_defpreset_get_zone(defpreset); - /* check if the note falls into the key and velocity range of this - preset */ - if (fluid_zone_inside_range(&preset_zone->range, key, vel)) { + while(preset_zone != NULL) + { - inst = fluid_preset_zone_get_inst(preset_zone); - global_inst_zone = fluid_inst_get_global_zone(inst); + /* check if the note falls into the key and velocity range of this + preset */ + if(fluid_zone_inside_range(&preset_zone->range, key, vel)) + { - /* run thru all the zones of this instrument that could start a voice */ - for (list = preset_zone->voice_zone; list != NULL; list = fluid_list_next(list)) { - voice_zone = fluid_list_get(list); + inst = fluid_preset_zone_get_inst(preset_zone); + global_inst_zone = fluid_inst_get_global_zone(inst); - /* check if the instrument zone is ignored and the note falls into - the key and velocity range of this instrument zone. - An instrument zone must be ignored when its voice is already running - played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */ - if (fluid_zone_inside_range(&voice_zone->range, key, vel)) { + /* run thru all the zones of this instrument that could start a voice */ + for(list = preset_zone->voice_zone; list != NULL; list = fluid_list_next(list)) + { + voice_zone = fluid_list_get(list); - inst_zone = voice_zone->inst_zone; + /* check if the instrument zone is ignored and the note falls into + the key and velocity range of this instrument zone. + An instrument zone must be ignored when its voice is already running + played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */ + if(fluid_zone_inside_range(&voice_zone->range, key, vel)) + { - /* this is a good zone. allocate a new synthesis process and initialize it */ - voice = fluid_synth_alloc_voice_LOCAL(synth, inst_zone->sample, chan, key, vel, &voice_zone->range); - if (voice == NULL) { - return FLUID_FAILED; - } + inst_zone = voice_zone->inst_zone; + + /* this is a good zone. allocate a new synthesis process and initialize it */ + voice = fluid_synth_alloc_voice_LOCAL(synth, inst_zone->sample, chan, key, vel, &voice_zone->range); + + if(voice == NULL) + { + return FLUID_FAILED; + } - /* Instrument level, generators */ + /* Instrument level, generators */ - for (i = 0; i < GEN_LAST; i++) { + for(i = 0; i < GEN_LAST; i++) + { - /* SF 2.01 section 9.4 'bullet' 4: - * - * A generator in a local instrument zone supersedes a - * global instrument zone generator. Both cases supersede - * the default generator -> voice_gen_set */ + /* SF 2.01 section 9.4 'bullet' 4: + * + * A generator in a local instrument zone supersedes a + * global instrument zone generator. Both cases supersede + * the default generator -> voice_gen_set */ - if (inst_zone->gen[i].flags){ - fluid_voice_gen_set(voice, i, inst_zone->gen[i].val); + if(inst_zone->gen[i].flags) + { + fluid_voice_gen_set(voice, i, inst_zone->gen[i].val); - } else if ((global_inst_zone != NULL) && (global_inst_zone->gen[i].flags)) { - fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val); + } + else if((global_inst_zone != NULL) && (global_inst_zone->gen[i].flags)) + { + fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val); - } else { - /* The generator has not been defined in this instrument. - * Do nothing, leave it at the default. - */ - } + } + else + { + /* The generator has not been defined in this instrument. + * Do nothing, leave it at the default. + */ + } - } /* for all generators */ + } /* for all generators */ - /* global instrument zone, modulators: Put them all into a - * list. */ + /* global instrument zone, modulators: Put them all into a + * list. */ - mod_list_count = 0; + mod_list_count = 0; - if (global_inst_zone){ - mod = global_inst_zone->mod; - while (mod){ - mod_list[mod_list_count++] = mod; - mod = mod->next; - } - } + if(global_inst_zone) + { + mod = global_inst_zone->mod; - /* local instrument zone, modulators. - * Replace modulators with the same definition in the list: - * SF 2.01 page 69, 'bullet' 8 - */ - mod = inst_zone->mod; + while(mod) + { + mod_list[mod_list_count++] = mod; + mod = mod->next; + } + } - while (mod){ + /* local instrument zone, modulators. + * Replace modulators with the same definition in the list: + * SF 2.01 page 69, 'bullet' 8 + */ + mod = inst_zone->mod; - /* 'Identical' modulators will be deleted by setting their - * list entry to NULL. The list length is known, NULL - * entries will be ignored later. SF2.01 section 9.5.1 - * page 69, 'bullet' 3 defines 'identical'. */ + while(mod) + { - for (i = 0; i < mod_list_count; i++){ - if (mod_list[i] && fluid_mod_test_identity(mod,mod_list[i])){ - mod_list[i] = NULL; - } - } + /* 'Identical' modulators will be deleted by setting their + * list entry to NULL. The list length is known, NULL + * entries will be ignored later. SF2.01 section 9.5.1 + * page 69, 'bullet' 3 defines 'identical'. */ - /* Finally add the new modulator to to the list. */ - mod_list[mod_list_count++] = mod; - mod = mod->next; - } + for(i = 0; i < mod_list_count; i++) + { + if(mod_list[i] && fluid_mod_test_identity(mod, mod_list[i])) + { + mod_list[i] = NULL; + } + } - /* Add instrument modulators (global / local) to the voice. */ - for (i = 0; i < mod_list_count; i++){ + /* Finally add the new modulator to to the list. */ + mod_list[mod_list_count++] = mod; + mod = mod->next; + } - mod = mod_list[i]; + /* Add instrument modulators (global / local) to the voice. */ + for(i = 0; i < mod_list_count; i++) + { - if (mod != NULL){ /* disabled modulators CANNOT be skipped. */ + mod = mod_list[i]; - /* Instrument modulators -supersede- existing (default) - * modulators. SF 2.01 page 69, 'bullet' 6 */ - fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE); - } - } + if(mod != NULL) /* disabled modulators CANNOT be skipped. */ + { - /* Preset level, generators */ + /* Instrument modulators -supersede- existing (default) + * modulators. SF 2.01 page 69, 'bullet' 6 */ + fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE); + } + } - for (i = 0; i < GEN_LAST; i++) { + /* Preset level, generators */ - /* SF 2.01 section 8.5 page 58: If some generators are - * encountered at preset level, they should be ignored */ - if ((i != GEN_STARTADDROFS) - && (i != GEN_ENDADDROFS) - && (i != GEN_STARTLOOPADDROFS) - && (i != GEN_ENDLOOPADDROFS) - && (i != GEN_STARTADDRCOARSEOFS) - && (i != GEN_ENDADDRCOARSEOFS) - && (i != GEN_STARTLOOPADDRCOARSEOFS) - && (i != GEN_KEYNUM) - && (i != GEN_VELOCITY) - && (i != GEN_ENDLOOPADDRCOARSEOFS) - && (i != GEN_SAMPLEMODE) - && (i != GEN_EXCLUSIVECLASS) - && (i != GEN_OVERRIDEROOTKEY)) { + for(i = 0; i < GEN_LAST; i++) + { - /* SF 2.01 section 9.4 'bullet' 9: A generator in a - * local preset zone supersedes a global preset zone - * generator. The effect is -added- to the destination - * summing node -> voice_gen_incr */ + /* SF 2.01 section 8.5 page 58: If some generators are + * encountered at preset level, they should be ignored */ + if((i != GEN_STARTADDROFS) + && (i != GEN_ENDADDROFS) + && (i != GEN_STARTLOOPADDROFS) + && (i != GEN_ENDLOOPADDROFS) + && (i != GEN_STARTADDRCOARSEOFS) + && (i != GEN_ENDADDRCOARSEOFS) + && (i != GEN_STARTLOOPADDRCOARSEOFS) + && (i != GEN_KEYNUM) + && (i != GEN_VELOCITY) + && (i != GEN_ENDLOOPADDRCOARSEOFS) + && (i != GEN_SAMPLEMODE) + && (i != GEN_EXCLUSIVECLASS) + && (i != GEN_OVERRIDEROOTKEY)) + { - if (preset_zone->gen[i].flags) { - fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val); - } else if ((global_preset_zone != NULL) && global_preset_zone->gen[i].flags) { - fluid_voice_gen_incr(voice, i, global_preset_zone->gen[i].val); - } else { - /* The generator has not been defined in this preset - * Do nothing, leave it unchanged. - */ - } - } /* if available at preset level */ - } /* for all generators */ + /* SF 2.01 section 9.4 'bullet' 9: A generator in a + * local preset zone supersedes a global preset zone + * generator. The effect is -added- to the destination + * summing node -> voice_gen_incr */ + + if(preset_zone->gen[i].flags) + { + fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val); + } + else if((global_preset_zone != NULL) && global_preset_zone->gen[i].flags) + { + fluid_voice_gen_incr(voice, i, global_preset_zone->gen[i].val); + } + else + { + /* The generator has not been defined in this preset + * Do nothing, leave it unchanged. + */ + } + } /* if available at preset level */ + } /* for all generators */ - /* Global preset zone, modulators: put them all into a - * list. */ - mod_list_count = 0; - if (global_preset_zone){ - mod = global_preset_zone->mod; - while (mod){ - mod_list[mod_list_count++] = mod; - mod = mod->next; - } - } + /* Global preset zone, modulators: put them all into a + * list. */ + mod_list_count = 0; - /* Process the modulators of the local preset zone. Kick - * out all identical modulators from the global preset zone - * (SF 2.01 page 69, second-last bullet) */ + if(global_preset_zone) + { + mod = global_preset_zone->mod; - mod = preset_zone->mod; - while (mod){ - for (i = 0; i < mod_list_count; i++){ - if (mod_list[i] && fluid_mod_test_identity(mod,mod_list[i])){ - mod_list[i] = NULL; - } - } + while(mod) + { + mod_list[mod_list_count++] = mod; + mod = mod->next; + } + } - /* Finally add the new modulator to the list. */ - mod_list[mod_list_count++] = mod; - mod = mod->next; - } + /* Process the modulators of the local preset zone. Kick + * out all identical modulators from the global preset zone + * (SF 2.01 page 69, second-last bullet) */ - /* Add preset modulators (global / local) to the voice. */ - for (i = 0; i < mod_list_count; i++){ - mod = mod_list[i]; - if ((mod != NULL) && (mod->amount != 0)) { /* disabled modulators can be skipped. */ + mod = preset_zone->mod; - /* Preset modulators -add- to existing instrument / - * default modulators. SF2.01 page 70 first bullet on - * page */ - fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD); - } - } + while(mod) + { + for(i = 0; i < mod_list_count; i++) + { + if(mod_list[i] && fluid_mod_test_identity(mod, mod_list[i])) + { + mod_list[i] = NULL; + } + } - /* add the synthesis process to the synthesis loop. */ - fluid_synth_start_voice(synth, voice); + /* Finally add the new modulator to the list. */ + mod_list[mod_list_count++] = mod; + mod = mod->next; + } - /* Store the ID of the first voice that was created by this noteon event. - * Exclusive class may only terminate older voices. - * That avoids killing voices, which have just been created. - * (a noteon event can create several voice processes with the same exclusive - * class - for example when using stereo samples) - */ - } + /* Add preset modulators (global / local) to the voice. */ + for(i = 0; i < mod_list_count; i++) + { + mod = mod_list[i]; - } - } - preset_zone = fluid_preset_zone_next(preset_zone); - } + if((mod != NULL) && (mod->amount != 0)) /* disabled modulators can be skipped. */ + { - return FLUID_OK; + /* Preset modulators -add- to existing instrument / + * default modulators. SF2.01 page 70 first bullet on + * page */ + fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD); + } + } + + /* add the synthesis process to the synthesis loop. */ + fluid_synth_start_voice(synth, voice); + + /* Store the ID of the first voice that was created by this noteon event. + * Exclusive class may only terminate older voices. + * That avoids killing voices, which have just been created. + * (a noteon event can create several voice processes with the same exclusive + * class - for example when using stereo samples) + */ + } + + } + } + + preset_zone = fluid_preset_zone_next(preset_zone); + } + + return FLUID_OK; } /* * fluid_defpreset_set_global_zone */ int -fluid_defpreset_set_global_zone(fluid_defpreset_t* defpreset, fluid_preset_zone_t* zone) +fluid_defpreset_set_global_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone) { - defpreset->global_zone = zone; - return FLUID_OK; + defpreset->global_zone = zone; + return FLUID_OK; } /* * fluid_defpreset_import_sfont */ int -fluid_defpreset_import_sfont(fluid_defpreset_t* defpreset, - SFPreset* sfpreset, - fluid_defsfont_t* defsfont) +fluid_defpreset_import_sfont(fluid_defpreset_t *defpreset, + SFPreset *sfpreset, + fluid_defsfont_t *defsfont) { - fluid_list_t *p; - SFZone* sfzone; - fluid_preset_zone_t* zone; - int count; - char zone_name[256]; - if (FLUID_STRLEN(sfpreset->name) > 0) { - FLUID_STRCPY(defpreset->name, sfpreset->name); - } else { - FLUID_SNPRINTF(defpreset->name, sizeof(defpreset->name), "Bank%d,Pre%d", sfpreset->bank, sfpreset->prenum); - } - defpreset->bank = sfpreset->bank; - defpreset->num = sfpreset->prenum; - p = sfpreset->zone; - count = 0; - while (p != NULL) { - sfzone = (SFZone *)fluid_list_get(p); - FLUID_SNPRINTF(zone_name, sizeof(zone_name), "%s/%d", defpreset->name, count); - zone = new_fluid_preset_zone(zone_name); - if (zone == NULL) { - return FLUID_FAILED; + fluid_list_t *p; + SFZone *sfzone; + fluid_preset_zone_t *zone; + int count; + char zone_name[256]; + + if(FLUID_STRLEN(sfpreset->name) > 0) + { + FLUID_STRCPY(defpreset->name, sfpreset->name); } - if (fluid_preset_zone_import_sfont(zone, sfzone, defsfont) != FLUID_OK) { - delete_fluid_preset_zone(zone); - return FLUID_FAILED; + else + { + FLUID_SNPRINTF(defpreset->name, sizeof(defpreset->name), "Bank%d,Pre%d", sfpreset->bank, sfpreset->prenum); } - if ((count == 0) && (fluid_preset_zone_get_inst(zone) == NULL)) { - fluid_defpreset_set_global_zone(defpreset, zone); - } else if (fluid_defpreset_add_zone(defpreset, zone) != FLUID_OK) { - return FLUID_FAILED; + + defpreset->bank = sfpreset->bank; + defpreset->num = sfpreset->prenum; + p = sfpreset->zone; + count = 0; + + while(p != NULL) + { + sfzone = (SFZone *)fluid_list_get(p); + FLUID_SNPRINTF(zone_name, sizeof(zone_name), "%s/%d", defpreset->name, count); + zone = new_fluid_preset_zone(zone_name); + + if(zone == NULL) + { + return FLUID_FAILED; + } + + if(fluid_preset_zone_import_sfont(zone, sfzone, defsfont) != FLUID_OK) + { + delete_fluid_preset_zone(zone); + return FLUID_FAILED; + } + + if((count == 0) && (fluid_preset_zone_get_inst(zone) == NULL)) + { + fluid_defpreset_set_global_zone(defpreset, zone); + } + else if(fluid_defpreset_add_zone(defpreset, zone) != FLUID_OK) + { + return FLUID_FAILED; + } + + p = fluid_list_next(p); + count++; } - p = fluid_list_next(p); - count++; - } - return FLUID_OK; + + return FLUID_OK; } /* * fluid_defpreset_add_zone */ int -fluid_defpreset_add_zone(fluid_defpreset_t* defpreset, fluid_preset_zone_t* zone) +fluid_defpreset_add_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone) { - if (defpreset->zone == NULL) { - zone->next = NULL; - defpreset->zone = zone; - } else { - zone->next = defpreset->zone; - defpreset->zone = zone; - } - return FLUID_OK; + if(defpreset->zone == NULL) + { + zone->next = NULL; + defpreset->zone = zone; + } + else + { + zone->next = defpreset->zone; + defpreset->zone = zone; + } + + return FLUID_OK; } /* * fluid_defpreset_get_zone */ -fluid_preset_zone_t* -fluid_defpreset_get_zone(fluid_defpreset_t* defpreset) +fluid_preset_zone_t * +fluid_defpreset_get_zone(fluid_defpreset_t *defpreset) { - return defpreset->zone; + return defpreset->zone; } /* * fluid_defpreset_get_global_zone */ -fluid_preset_zone_t* -fluid_defpreset_get_global_zone(fluid_defpreset_t* defpreset) +fluid_preset_zone_t * +fluid_defpreset_get_global_zone(fluid_defpreset_t *defpreset) { - return defpreset->global_zone; + return defpreset->global_zone; } /*************************************************************** @@ -950,77 +1060,85 @@ fluid_defpreset_get_global_zone(fluid_defpreset_t* defpreset) /* * fluid_preset_zone_next */ -fluid_preset_zone_t* -fluid_preset_zone_next(fluid_preset_zone_t* zone) +fluid_preset_zone_t * +fluid_preset_zone_next(fluid_preset_zone_t *zone) { - return zone->next; + return zone->next; } /* * new_fluid_preset_zone */ -fluid_preset_zone_t* +fluid_preset_zone_t * new_fluid_preset_zone(char *name) { - fluid_preset_zone_t* zone = NULL; - zone = FLUID_NEW(fluid_preset_zone_t); - if (zone == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - zone->next = NULL; - zone->voice_zone = NULL; - zone->name = FLUID_STRDUP(name); - if (zone->name == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - FLUID_FREE(zone); - return NULL; - } - zone->inst = NULL; - zone->range.keylo = 0; - zone->range.keyhi = 128; - zone->range.vello = 0; - zone->range.velhi = 128; - zone->range.ignore = FALSE; + fluid_preset_zone_t *zone = NULL; + zone = FLUID_NEW(fluid_preset_zone_t); - /* Flag all generators as unused (default, they will be set when they are found - * in the sound font). - * This also sets the generator values to default, but that is of no concern here.*/ - fluid_gen_set_default_values(&zone->gen[0]); - zone->mod = NULL; /* list of modulators */ - return zone; + if(zone == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + zone->next = NULL; + zone->voice_zone = NULL; + zone->name = FLUID_STRDUP(name); + + if(zone->name == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_FREE(zone); + return NULL; + } + + zone->inst = NULL; + zone->range.keylo = 0; + zone->range.keyhi = 128; + zone->range.vello = 0; + zone->range.velhi = 128; + zone->range.ignore = FALSE; + + /* Flag all generators as unused (default, they will be set when they are found + * in the sound font). + * This also sets the generator values to default, but that is of no concern here.*/ + fluid_gen_set_default_values(&zone->gen[0]); + zone->mod = NULL; /* list of modulators */ + return zone; } /* * delete_fluid_preset_zone */ void -delete_fluid_preset_zone(fluid_preset_zone_t* zone) +delete_fluid_preset_zone(fluid_preset_zone_t *zone) { - fluid_mod_t *mod, *tmp; - fluid_list_t *list; + fluid_mod_t *mod, *tmp; + fluid_list_t *list; - fluid_return_if_fail(zone != NULL); - - mod = zone->mod; - while (mod) /* delete the modulators */ + fluid_return_if_fail(zone != NULL); + + mod = zone->mod; + + while(mod) /* delete the modulators */ { - tmp = mod; - mod = mod->next; - delete_fluid_mod (tmp); + tmp = mod; + mod = mod->next; + delete_fluid_mod(tmp); } - for (list = zone->voice_zone; list != NULL; list = fluid_list_next(list)) - { - FLUID_FREE(fluid_list_get(list)); - } - delete_fluid_list(zone->voice_zone); + for(list = zone->voice_zone; list != NULL; list = fluid_list_next(list)) + { + FLUID_FREE(fluid_list_get(list)); + } - FLUID_FREE (zone->name); - FLUID_FREE(zone); + delete_fluid_list(zone->voice_zone); + + FLUID_FREE(zone->name); + FLUID_FREE(zone); } -static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t* preset_zone) +static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t *preset_zone) { fluid_inst_zone_t *inst_zone; fluid_sample_t *sample; @@ -1031,19 +1149,23 @@ static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t* preset_zone fluid_return_val_if_fail(preset_zone->inst != NULL, FLUID_FAILED); inst_zone = fluid_inst_get_zone(preset_zone->inst); - while (inst_zone != NULL) { + + while(inst_zone != NULL) + { /* We only create voice ranges for zones that could actually start a voice, * i.e. that have a sample and don't point to ROM */ sample = fluid_inst_zone_get_sample(inst_zone); - if ((sample == NULL) || fluid_sample_in_rom(sample)) + + if((sample == NULL) || fluid_sample_in_rom(sample)) { inst_zone = fluid_inst_zone_next(inst_zone); continue; } voice_zone = FLUID_NEW(fluid_voice_zone_t); - if (voice_zone == NULL) + + if(voice_zone == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return FLUID_FAILED; @@ -1071,197 +1193,254 @@ static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t* preset_zone * fluid_preset_zone_import_sfont */ int -fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* defsfont) +fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defsfont) { - fluid_list_t *r; - SFGen* sfgen; - SFInst* sfinst; - int count; - for (count = 0, r = sfzone->gen; r != NULL; count++) { - sfgen = (SFGen *)fluid_list_get(r); - switch (sfgen->id) { - case GEN_KEYRANGE: - zone->range.keylo = sfgen->amount.range.lo; - zone->range.keyhi = sfgen->amount.range.hi; - break; - case GEN_VELRANGE: - zone->range.vello = sfgen->amount.range.lo; - zone->range.velhi = sfgen->amount.range.hi; - break; - case GEN_ATTENUATION: - /* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at - * preset and instrument level */ - zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR; - zone->gen[sfgen->id].flags = GEN_SET; - break; - default: - /* FIXME: some generators have an unsigne word amount value but i don't know which ones */ - zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; - zone->gen[sfgen->id].flags = GEN_SET; - break; - } - r = fluid_list_next(r); - } - if ((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) { - sfinst = sfzone->instsamp->data; + fluid_list_t *r; + SFGen *sfgen; + SFInst *sfinst; + int count; - zone->inst = find_inst_by_idx(defsfont, sfinst->idx); - if (zone->inst == NULL) + for(count = 0, r = sfzone->gen; r != NULL; count++) { - zone->inst = fluid_inst_import_sfont(zone, sfinst, defsfont); + sfgen = (SFGen *)fluid_list_get(r); + + switch(sfgen->id) + { + case GEN_KEYRANGE: + zone->range.keylo = sfgen->amount.range.lo; + zone->range.keyhi = sfgen->amount.range.hi; + break; + + case GEN_VELRANGE: + zone->range.vello = sfgen->amount.range.lo; + zone->range.velhi = sfgen->amount.range.hi; + break; + + case GEN_ATTENUATION: + /* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at + * preset and instrument level */ + zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR; + zone->gen[sfgen->id].flags = GEN_SET; + break; + + default: + /* FIXME: some generators have an unsigne word amount value but i don't know which ones */ + zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; + zone->gen[sfgen->id].flags = GEN_SET; + break; + } + + r = fluid_list_next(r); } - if (zone->inst == NULL) + if((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) { - return FLUID_FAILED; + sfinst = sfzone->instsamp->data; + + zone->inst = find_inst_by_idx(defsfont, sfinst->idx); + + if(zone->inst == NULL) + { + zone->inst = fluid_inst_import_sfont(zone, sfinst, defsfont); + } + + if(zone->inst == NULL) + { + return FLUID_FAILED; + } + + if(fluid_preset_zone_create_voice_zones(zone) == FLUID_FAILED) + { + return FLUID_FAILED; + } } - if (fluid_preset_zone_create_voice_zones(zone) == FLUID_FAILED) + /* Import the modulators (only SF2.1 and higher) */ + for(count = 0, r = sfzone->mod; r != NULL; count++) { - return FLUID_FAILED; - } - } - /* Import the modulators (only SF2.1 and higher) */ - for (count = 0, r = sfzone->mod; r != NULL; count++) { + SFMod *mod_src = (SFMod *)fluid_list_get(r); + fluid_mod_t *mod_dest = new_fluid_mod(); + int type; - SFMod* mod_src = (SFMod *)fluid_list_get(r); - fluid_mod_t * mod_dest = new_fluid_mod(); - int type; + if(mod_dest == NULL) + { + return FLUID_FAILED; + } - if (mod_dest == NULL){ - return FLUID_FAILED; - } - mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ + mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ - /* *** Amount *** */ - mod_dest->amount = mod_src->amount; + /* *** Amount *** */ + mod_dest->amount = mod_src->amount; - /* *** Source *** */ - mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */ - mod_dest->flags1 = 0; + /* *** Source *** */ + mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */ + mod_dest->flags1 = 0; - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if (mod_src->src & (1<<7)){ - mod_dest->flags1 |= FLUID_MOD_CC; - } else { - mod_dest->flags1 |= FLUID_MOD_GC; - } + /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ + if(mod_src->src & (1 << 7)) + { + mod_dest->flags1 |= FLUID_MOD_CC; + } + else + { + mod_dest->flags1 |= FLUID_MOD_GC; + } - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if (mod_src->src & (1<<8)){ - mod_dest->flags1 |= FLUID_MOD_NEGATIVE; - } else { - mod_dest->flags1 |= FLUID_MOD_POSITIVE; - } + /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ + if(mod_src->src & (1 << 8)) + { + mod_dest->flags1 |= FLUID_MOD_NEGATIVE; + } + else + { + mod_dest->flags1 |= FLUID_MOD_POSITIVE; + } - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if (mod_src->src & (1<<9)){ - mod_dest->flags1 |= FLUID_MOD_BIPOLAR; - } else { - mod_dest->flags1 |= FLUID_MOD_UNIPOLAR; - } + /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ + if(mod_src->src & (1 << 9)) + { + mod_dest->flags1 |= FLUID_MOD_BIPOLAR; + } + else + { + mod_dest->flags1 |= FLUID_MOD_UNIPOLAR; + } - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type=(mod_src->src) >> 10; - type &= 63; /* type is a 6-bit value */ - if (type == 0){ - mod_dest->flags1 |= FLUID_MOD_LINEAR; - } else if (type == 1){ - mod_dest->flags1 |= FLUID_MOD_CONCAVE; - } else if (type == 2){ - mod_dest->flags1 |= FLUID_MOD_CONVEX; - } else if (type == 3){ - mod_dest->flags1 |= FLUID_MOD_SWITCH; - } else { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount=0; - } + /* modulator source types: SF2.01 section 8.2.1 page 52 */ + type = (mod_src->src) >> 10; + type &= 63; /* type is a 6-bit value */ - /* *** Dest *** */ - mod_dest->dest = mod_src->dest; /* index of controlled generator */ + if(type == 0) + { + mod_dest->flags1 |= FLUID_MOD_LINEAR; + } + else if(type == 1) + { + mod_dest->flags1 |= FLUID_MOD_CONCAVE; + } + else if(type == 2) + { + mod_dest->flags1 |= FLUID_MOD_CONVEX; + } + else if(type == 3) + { + mod_dest->flags1 |= FLUID_MOD_SWITCH; + } + else + { + /* This shouldn't happen - unknown type! + * Deactivate the modulator by setting the amount to 0. */ + mod_dest->amount = 0; + } - /* *** Amount source *** */ - mod_dest->src2 = mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, p.50 */ - mod_dest->flags2 = 0; + /* *** Dest *** */ + mod_dest->dest = mod_src->dest; /* index of controlled generator */ - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if (mod_src->amtsrc & (1<<7)){ - mod_dest->flags2 |= FLUID_MOD_CC; - } else { - mod_dest->flags2 |= FLUID_MOD_GC; - } + /* *** Amount source *** */ + mod_dest->src2 = mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, p.50 */ + mod_dest->flags2 = 0; - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if (mod_src->amtsrc & (1<<8)){ - mod_dest->flags2 |= FLUID_MOD_NEGATIVE; - } else { - mod_dest->flags2 |= FLUID_MOD_POSITIVE; - } + /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ + if(mod_src->amtsrc & (1 << 7)) + { + mod_dest->flags2 |= FLUID_MOD_CC; + } + else + { + mod_dest->flags2 |= FLUID_MOD_GC; + } - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if (mod_src->amtsrc & (1<<9)){ - mod_dest->flags2 |= FLUID_MOD_BIPOLAR; - } else { - mod_dest->flags2 |= FLUID_MOD_UNIPOLAR; - } + /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ + if(mod_src->amtsrc & (1 << 8)) + { + mod_dest->flags2 |= FLUID_MOD_NEGATIVE; + } + else + { + mod_dest->flags2 |= FLUID_MOD_POSITIVE; + } - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type = (mod_src->amtsrc) >> 10; - type &= 63; /* type is a 6-bit value */ - if (type == 0){ - mod_dest->flags2 |= FLUID_MOD_LINEAR; - } else if (type == 1){ - mod_dest->flags2 |= FLUID_MOD_CONCAVE; - } else if (type == 2){ - mod_dest->flags2 |= FLUID_MOD_CONVEX; - } else if (type == 3){ - mod_dest->flags2 |= FLUID_MOD_SWITCH; - } else { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount=0; - } + /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ + if(mod_src->amtsrc & (1 << 9)) + { + mod_dest->flags2 |= FLUID_MOD_BIPOLAR; + } + else + { + mod_dest->flags2 |= FLUID_MOD_UNIPOLAR; + } - /* *** Transform *** */ - /* SF2.01 only uses the 'linear' transform (0). - * Deactivate the modulator by setting the amount to 0 in any other case. - */ - if (mod_src->trans !=0){ - mod_dest->amount = 0; - } + /* modulator source types: SF2.01 section 8.2.1 page 52 */ + type = (mod_src->amtsrc) >> 10; + type &= 63; /* type is a 6-bit value */ - /* Store the new modulator in the zone The order of modulators - * will make a difference, at least in an instrument context: The - * second modulator overwrites the first one, if they only differ - * in amount. */ - if (count == 0){ - zone->mod = mod_dest; - } else { - fluid_mod_t * last_mod = zone->mod; + if(type == 0) + { + mod_dest->flags2 |= FLUID_MOD_LINEAR; + } + else if(type == 1) + { + mod_dest->flags2 |= FLUID_MOD_CONCAVE; + } + else if(type == 2) + { + mod_dest->flags2 |= FLUID_MOD_CONVEX; + } + else if(type == 3) + { + mod_dest->flags2 |= FLUID_MOD_SWITCH; + } + else + { + /* This shouldn't happen - unknown type! + * Deactivate the modulator by setting the amount to 0. */ + mod_dest->amount = 0; + } - /* Find the end of the list */ - while (last_mod->next != NULL){ - last_mod=last_mod->next; - } + /* *** Transform *** */ + /* SF2.01 only uses the 'linear' transform (0). + * Deactivate the modulator by setting the amount to 0 in any other case. + */ + if(mod_src->trans != 0) + { + mod_dest->amount = 0; + } - last_mod->next = mod_dest; - } + /* Store the new modulator in the zone The order of modulators + * will make a difference, at least in an instrument context: The + * second modulator overwrites the first one, if they only differ + * in amount. */ + if(count == 0) + { + zone->mod = mod_dest; + } + else + { + fluid_mod_t *last_mod = zone->mod; - r = fluid_list_next(r); - } /* foreach modulator */ + /* Find the end of the list */ + while(last_mod->next != NULL) + { + last_mod = last_mod->next; + } - return FLUID_OK; + last_mod->next = mod_dest; + } + + r = fluid_list_next(r); + } /* foreach modulator */ + + return FLUID_OK; } /* * fluid_preset_zone_get_inst */ -fluid_inst_t* -fluid_preset_zone_get_inst(fluid_preset_zone_t* zone) +fluid_inst_t * +fluid_preset_zone_get_inst(fluid_preset_zone_t *zone) { - return zone->inst; + return zone->inst; } @@ -1273,143 +1452,167 @@ fluid_preset_zone_get_inst(fluid_preset_zone_t* zone) /* * new_fluid_inst */ -fluid_inst_t* +fluid_inst_t * new_fluid_inst() { - fluid_inst_t* inst = FLUID_NEW(fluid_inst_t); - if (inst == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - inst->name[0] = 0; - inst->global_zone = NULL; - inst->zone = NULL; - return inst; + fluid_inst_t *inst = FLUID_NEW(fluid_inst_t); + + if(inst == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + inst->name[0] = 0; + inst->global_zone = NULL; + inst->zone = NULL; + return inst; } /* * delete_fluid_inst */ void -delete_fluid_inst(fluid_inst_t* inst) +delete_fluid_inst(fluid_inst_t *inst) { - fluid_inst_zone_t* zone; - - fluid_return_if_fail(inst != NULL); - + fluid_inst_zone_t *zone; + + fluid_return_if_fail(inst != NULL); + delete_fluid_inst_zone(inst->global_zone); inst->global_zone = NULL; - - zone = inst->zone; - while (zone != NULL) { - inst->zone = zone->next; - delete_fluid_inst_zone(zone); + zone = inst->zone; - } - FLUID_FREE(inst); + + while(zone != NULL) + { + inst->zone = zone->next; + delete_fluid_inst_zone(zone); + zone = inst->zone; + } + + FLUID_FREE(inst); } /* * fluid_inst_set_global_zone */ int -fluid_inst_set_global_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone) +fluid_inst_set_global_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone) { - inst->global_zone = zone; - return FLUID_OK; + inst->global_zone = zone; + return FLUID_OK; } /* * fluid_inst_import_sfont */ fluid_inst_t * -fluid_inst_import_sfont(fluid_preset_zone_t* preset_zone, SFInst *sfinst, fluid_defsfont_t* defsfont) +fluid_inst_import_sfont(fluid_preset_zone_t *preset_zone, SFInst *sfinst, fluid_defsfont_t *defsfont) { - fluid_list_t *p; - fluid_inst_t *inst; - SFZone* sfzone; - fluid_inst_zone_t* inst_zone; - char zone_name[256]; - int count; + fluid_list_t *p; + fluid_inst_t *inst; + SFZone *sfzone; + fluid_inst_zone_t *inst_zone; + char zone_name[256]; + int count; - inst = (fluid_inst_t*) new_fluid_inst(); - if (inst == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + inst = (fluid_inst_t *) new_fluid_inst(); - inst->source_idx = sfinst->idx; - - p = sfinst->zone; - if (FLUID_STRLEN(sfinst->name) > 0) { - FLUID_STRCPY(inst->name, sfinst->name); - } else { - FLUID_STRCPY(inst->name, ""); - } - - count = 0; - while (p != NULL) { - - sfzone = (SFZone *)fluid_list_get(p); - FLUID_SNPRINTF(zone_name, sizeof(zone_name), "%s/%d", inst->name, count); - - inst_zone = new_fluid_inst_zone(zone_name); - if (inst_zone == NULL) { - return NULL; + if(inst == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - if (fluid_inst_zone_import_sfont(inst_zone, sfzone, defsfont) != FLUID_OK) { - delete_fluid_inst_zone(inst_zone); - return NULL; + inst->source_idx = sfinst->idx; + + p = sfinst->zone; + + if(FLUID_STRLEN(sfinst->name) > 0) + { + FLUID_STRCPY(inst->name, sfinst->name); + } + else + { + FLUID_STRCPY(inst->name, ""); } - if ((count == 0) && (fluid_inst_zone_get_sample(inst_zone) == NULL)) { - fluid_inst_set_global_zone(inst, inst_zone); + count = 0; - } else if (fluid_inst_add_zone(inst, inst_zone) != FLUID_OK) { - return NULL; + while(p != NULL) + { + + sfzone = (SFZone *)fluid_list_get(p); + FLUID_SNPRINTF(zone_name, sizeof(zone_name), "%s/%d", inst->name, count); + + inst_zone = new_fluid_inst_zone(zone_name); + + if(inst_zone == NULL) + { + return NULL; + } + + if(fluid_inst_zone_import_sfont(inst_zone, sfzone, defsfont) != FLUID_OK) + { + delete_fluid_inst_zone(inst_zone); + return NULL; + } + + if((count == 0) && (fluid_inst_zone_get_sample(inst_zone) == NULL)) + { + fluid_inst_set_global_zone(inst, inst_zone); + + } + else if(fluid_inst_add_zone(inst, inst_zone) != FLUID_OK) + { + return NULL; + } + + p = fluid_list_next(p); + count++; } - p = fluid_list_next(p); - count++; - } - - defsfont->inst = fluid_list_append(defsfont->inst, inst); - return inst; + defsfont->inst = fluid_list_append(defsfont->inst, inst); + return inst; } /* * fluid_inst_add_zone */ int -fluid_inst_add_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone) +fluid_inst_add_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone) { - if (inst->zone == NULL) { - zone->next = NULL; - inst->zone = zone; - } else { - zone->next = inst->zone; - inst->zone = zone; - } - return FLUID_OK; + if(inst->zone == NULL) + { + zone->next = NULL; + inst->zone = zone; + } + else + { + zone->next = inst->zone; + inst->zone = zone; + } + + return FLUID_OK; } /* * fluid_inst_get_zone */ -fluid_inst_zone_t* -fluid_inst_get_zone(fluid_inst_t* inst) +fluid_inst_zone_t * +fluid_inst_get_zone(fluid_inst_t *inst) { - return inst->zone; + return inst->zone; } /* * fluid_inst_get_global_zone */ -fluid_inst_zone_t* -fluid_inst_get_global_zone(fluid_inst_t* inst) +fluid_inst_zone_t * +fluid_inst_get_global_zone(fluid_inst_t *inst) { - return inst->global_zone; + return inst->global_zone; } /*************************************************************** @@ -1420,265 +1623,330 @@ fluid_inst_get_global_zone(fluid_inst_t* inst) /* * new_fluid_inst_zone */ -fluid_inst_zone_t* -new_fluid_inst_zone(char* name) +fluid_inst_zone_t * +new_fluid_inst_zone(char *name) { - fluid_inst_zone_t* zone = NULL; - zone = FLUID_NEW(fluid_inst_zone_t); - if (zone == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - zone->next = NULL; - zone->name = FLUID_STRDUP(name); - if (zone->name == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - FLUID_FREE(zone); - return NULL; - } - zone->sample = NULL; - zone->range.keylo = 0; - zone->range.keyhi = 128; - zone->range.vello = 0; - zone->range.velhi = 128; - zone->range.ignore = FALSE; - /* Flag the generators as unused. - * This also sets the generator values to default, but they will be overwritten anyway, if used.*/ - fluid_gen_set_default_values(&zone->gen[0]); - zone->mod=NULL; /* list of modulators */ - return zone; + fluid_inst_zone_t *zone = NULL; + zone = FLUID_NEW(fluid_inst_zone_t); + + if(zone == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + zone->next = NULL; + zone->name = FLUID_STRDUP(name); + + if(zone->name == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_FREE(zone); + return NULL; + } + + zone->sample = NULL; + zone->range.keylo = 0; + zone->range.keyhi = 128; + zone->range.vello = 0; + zone->range.velhi = 128; + zone->range.ignore = FALSE; + /* Flag the generators as unused. + * This also sets the generator values to default, but they will be overwritten anyway, if used.*/ + fluid_gen_set_default_values(&zone->gen[0]); + zone->mod = NULL; /* list of modulators */ + return zone; } /* * delete_fluid_inst_zone */ void -delete_fluid_inst_zone(fluid_inst_zone_t* zone) +delete_fluid_inst_zone(fluid_inst_zone_t *zone) { - fluid_mod_t *mod, *tmp; + fluid_mod_t *mod, *tmp; - fluid_return_if_fail(zone != NULL); - - mod = zone->mod; - while (mod) /* delete the modulators */ + fluid_return_if_fail(zone != NULL); + + mod = zone->mod; + + while(mod) /* delete the modulators */ { - tmp = mod; - mod = mod->next; - delete_fluid_mod (tmp); + tmp = mod; + mod = mod->next; + delete_fluid_mod(tmp); } - FLUID_FREE (zone->name); - FLUID_FREE(zone); + FLUID_FREE(zone->name); + FLUID_FREE(zone); } /* * fluid_inst_zone_next */ -fluid_inst_zone_t* -fluid_inst_zone_next(fluid_inst_zone_t* zone) +fluid_inst_zone_t * +fluid_inst_zone_next(fluid_inst_zone_t *zone) { - return zone->next; + return zone->next; } /* * fluid_inst_zone_import_sfont */ int -fluid_inst_zone_import_sfont(fluid_inst_zone_t* inst_zone, SFZone *sfzone, fluid_defsfont_t* defsfont) +fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid_defsfont_t *defsfont) { - fluid_list_t *r; - SFGen* sfgen; - int count; + fluid_list_t *r; + SFGen *sfgen; + int count; - for (count = 0, r = sfzone->gen; r != NULL; count++) { - sfgen = (SFGen *)fluid_list_get(r); - switch (sfgen->id) { - case GEN_KEYRANGE: - inst_zone->range.keylo = sfgen->amount.range.lo; - inst_zone->range.keyhi = sfgen->amount.range.hi; - break; - case GEN_VELRANGE: - inst_zone->range.vello = sfgen->amount.range.lo; - inst_zone->range.velhi = sfgen->amount.range.hi; - break; - case GEN_ATTENUATION: - /* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at - * preset and instrument level */ - inst_zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR; - inst_zone->gen[sfgen->id].flags = GEN_SET; - break; - default: - /* FIXME: some generators have an unsigned word amount value but - i don't know which ones */ - inst_zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; - inst_zone->gen[sfgen->id].flags = GEN_SET; - break; - } - r = fluid_list_next(r); - } + for(count = 0, r = sfzone->gen; r != NULL; count++) + { + sfgen = (SFGen *)fluid_list_get(r); - /* FIXME */ -/* if (zone->gen[GEN_EXCLUSIVECLASS].flags == GEN_SET) { */ -/* FLUID_LOG(FLUID_DBG, "ExclusiveClass=%d\n", (int) zone->gen[GEN_EXCLUSIVECLASS].val); */ -/* } */ + switch(sfgen->id) + { + case GEN_KEYRANGE: + inst_zone->range.keylo = sfgen->amount.range.lo; + inst_zone->range.keyhi = sfgen->amount.range.hi; + break; - /* fixup sample pointer */ - if ((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) - inst_zone->sample = ((SFSample *)(sfzone->instsamp->data))->fluid_sample; + case GEN_VELRANGE: + inst_zone->range.vello = sfgen->amount.range.lo; + inst_zone->range.velhi = sfgen->amount.range.hi; + break; - /* Import the modulators (only SF2.1 and higher) */ - for (count = 0, r = sfzone->mod; r != NULL; count++) { - SFMod* mod_src = (SFMod *)fluid_list_get(r); - int type; - fluid_mod_t* mod_dest; + case GEN_ATTENUATION: + /* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at + * preset and instrument level */ + inst_zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR; + inst_zone->gen[sfgen->id].flags = GEN_SET; + break; - mod_dest = new_fluid_mod(); - if (mod_dest == NULL){ - return FLUID_FAILED; + default: + /* FIXME: some generators have an unsigned word amount value but + i don't know which ones */ + inst_zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; + inst_zone->gen[sfgen->id].flags = GEN_SET; + break; + } + + r = fluid_list_next(r); } - mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ + /* FIXME */ + /* if (zone->gen[GEN_EXCLUSIVECLASS].flags == GEN_SET) { */ + /* FLUID_LOG(FLUID_DBG, "ExclusiveClass=%d\n", (int) zone->gen[GEN_EXCLUSIVECLASS].val); */ + /* } */ - /* *** Amount *** */ - mod_dest->amount = mod_src->amount; - - /* *** Source *** */ - mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */ - mod_dest->flags1 = 0; - - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if (mod_src->src & (1<<7)){ - mod_dest->flags1 |= FLUID_MOD_CC; - } else { - mod_dest->flags1 |= FLUID_MOD_GC; + /* fixup sample pointer */ + if((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) + { + inst_zone->sample = ((SFSample *)(sfzone->instsamp->data))->fluid_sample; } - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if (mod_src->src & (1<<8)){ - mod_dest->flags1 |= FLUID_MOD_NEGATIVE; - } else { - mod_dest->flags1 |= FLUID_MOD_POSITIVE; - } + /* Import the modulators (only SF2.1 and higher) */ + for(count = 0, r = sfzone->mod; r != NULL; count++) + { + SFMod *mod_src = (SFMod *)fluid_list_get(r); + int type; + fluid_mod_t *mod_dest; - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if (mod_src->src & (1<<9)){ - mod_dest->flags1 |= FLUID_MOD_BIPOLAR; - } else { - mod_dest->flags1 |= FLUID_MOD_UNIPOLAR; - } + mod_dest = new_fluid_mod(); - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type = (mod_src->src) >> 10; - type &= 63; /* type is a 6-bit value */ - if (type == 0){ - mod_dest->flags1 |= FLUID_MOD_LINEAR; - } else if (type == 1){ - mod_dest->flags1 |= FLUID_MOD_CONCAVE; - } else if (type == 2){ - mod_dest->flags1 |= FLUID_MOD_CONVEX; - } else if (type == 3){ - mod_dest->flags1 |= FLUID_MOD_SWITCH; - } else { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount = 0; - } + if(mod_dest == NULL) + { + return FLUID_FAILED; + } - /* *** Dest *** */ - mod_dest->dest=mod_src->dest; /* index of controlled generator */ + mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ - /* *** Amount source *** */ - mod_dest->src2=mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, page 50 */ - mod_dest->flags2 = 0; + /* *** Amount *** */ + mod_dest->amount = mod_src->amount; - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if (mod_src->amtsrc & (1<<7)){ - mod_dest->flags2 |= FLUID_MOD_CC; - } else { - mod_dest->flags2 |= FLUID_MOD_GC; - } + /* *** Source *** */ + mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */ + mod_dest->flags1 = 0; - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if (mod_src->amtsrc & (1<<8)){ - mod_dest->flags2 |= FLUID_MOD_NEGATIVE; - } else { - mod_dest->flags2 |= FLUID_MOD_POSITIVE; - } + /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ + if(mod_src->src & (1 << 7)) + { + mod_dest->flags1 |= FLUID_MOD_CC; + } + else + { + mod_dest->flags1 |= FLUID_MOD_GC; + } - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if (mod_src->amtsrc & (1<<9)){ - mod_dest->flags2 |= FLUID_MOD_BIPOLAR; - } else { - mod_dest->flags2 |= FLUID_MOD_UNIPOLAR; - } + /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ + if(mod_src->src & (1 << 8)) + { + mod_dest->flags1 |= FLUID_MOD_NEGATIVE; + } + else + { + mod_dest->flags1 |= FLUID_MOD_POSITIVE; + } - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type=(mod_src->amtsrc) >> 10; - type &= 63; /* type is a 6-bit value */ - if (type == 0){ - mod_dest->flags2 |= FLUID_MOD_LINEAR; - } else if (type == 1){ - mod_dest->flags2 |= FLUID_MOD_CONCAVE; - } else if (type == 2){ - mod_dest->flags2 |= FLUID_MOD_CONVEX; - } else if (type == 3){ - mod_dest->flags2 |= FLUID_MOD_SWITCH; - } else { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount = 0; - } + /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ + if(mod_src->src & (1 << 9)) + { + mod_dest->flags1 |= FLUID_MOD_BIPOLAR; + } + else + { + mod_dest->flags1 |= FLUID_MOD_UNIPOLAR; + } - /* *** Transform *** */ - /* SF2.01 only uses the 'linear' transform (0). - * Deactivate the modulator by setting the amount to 0 in any other case. - */ - if (mod_src->trans !=0){ - mod_dest->amount = 0; - } + /* modulator source types: SF2.01 section 8.2.1 page 52 */ + type = (mod_src->src) >> 10; + type &= 63; /* type is a 6-bit value */ - /* Store the new modulator in the zone - * The order of modulators will make a difference, at least in an instrument context: - * The second modulator overwrites the first one, if they only differ in amount. */ - if (count == 0){ - inst_zone->mod=mod_dest; - } else { - fluid_mod_t * last_mod=inst_zone->mod; - /* Find the end of the list */ - while (last_mod->next != NULL){ - last_mod=last_mod->next; - } - last_mod->next=mod_dest; - } + if(type == 0) + { + mod_dest->flags1 |= FLUID_MOD_LINEAR; + } + else if(type == 1) + { + mod_dest->flags1 |= FLUID_MOD_CONCAVE; + } + else if(type == 2) + { + mod_dest->flags1 |= FLUID_MOD_CONVEX; + } + else if(type == 3) + { + mod_dest->flags1 |= FLUID_MOD_SWITCH; + } + else + { + /* This shouldn't happen - unknown type! + * Deactivate the modulator by setting the amount to 0. */ + mod_dest->amount = 0; + } - r = fluid_list_next(r); - } /* foreach modulator */ - return FLUID_OK; + /* *** Dest *** */ + mod_dest->dest = mod_src->dest; /* index of controlled generator */ + + /* *** Amount source *** */ + mod_dest->src2 = mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, page 50 */ + mod_dest->flags2 = 0; + + /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ + if(mod_src->amtsrc & (1 << 7)) + { + mod_dest->flags2 |= FLUID_MOD_CC; + } + else + { + mod_dest->flags2 |= FLUID_MOD_GC; + } + + /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ + if(mod_src->amtsrc & (1 << 8)) + { + mod_dest->flags2 |= FLUID_MOD_NEGATIVE; + } + else + { + mod_dest->flags2 |= FLUID_MOD_POSITIVE; + } + + /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ + if(mod_src->amtsrc & (1 << 9)) + { + mod_dest->flags2 |= FLUID_MOD_BIPOLAR; + } + else + { + mod_dest->flags2 |= FLUID_MOD_UNIPOLAR; + } + + /* modulator source types: SF2.01 section 8.2.1 page 52 */ + type = (mod_src->amtsrc) >> 10; + type &= 63; /* type is a 6-bit value */ + + if(type == 0) + { + mod_dest->flags2 |= FLUID_MOD_LINEAR; + } + else if(type == 1) + { + mod_dest->flags2 |= FLUID_MOD_CONCAVE; + } + else if(type == 2) + { + mod_dest->flags2 |= FLUID_MOD_CONVEX; + } + else if(type == 3) + { + mod_dest->flags2 |= FLUID_MOD_SWITCH; + } + else + { + /* This shouldn't happen - unknown type! + * Deactivate the modulator by setting the amount to 0. */ + mod_dest->amount = 0; + } + + /* *** Transform *** */ + /* SF2.01 only uses the 'linear' transform (0). + * Deactivate the modulator by setting the amount to 0 in any other case. + */ + if(mod_src->trans != 0) + { + mod_dest->amount = 0; + } + + /* Store the new modulator in the zone + * The order of modulators will make a difference, at least in an instrument context: + * The second modulator overwrites the first one, if they only differ in amount. */ + if(count == 0) + { + inst_zone->mod = mod_dest; + } + else + { + fluid_mod_t *last_mod = inst_zone->mod; + + /* Find the end of the list */ + while(last_mod->next != NULL) + { + last_mod = last_mod->next; + } + + last_mod->next = mod_dest; + } + + r = fluid_list_next(r); + } /* foreach modulator */ + + return FLUID_OK; } /* * fluid_inst_zone_get_sample */ -fluid_sample_t* -fluid_inst_zone_get_sample(fluid_inst_zone_t* zone) +fluid_sample_t * +fluid_inst_zone_get_sample(fluid_inst_zone_t *zone) { - return zone->sample; + return zone->sample; } int -fluid_zone_inside_range(fluid_zone_range_t* range, int key, int vel) +fluid_zone_inside_range(fluid_zone_range_t *range, int key, int vel) { /* ignoreInstrumentZone is set in mono legato playing */ int ignore_zone = range->ignore; - + /* Reset the 'ignore' request */ range->ignore = FALSE; - - return !ignore_zone && ((range->keylo <= key) && - (range->keyhi >= key) && - (range->vello <= vel) && - (range->velhi >= vel)); + + return !ignore_zone && ((range->keylo <= key) && + (range->keyhi >= key) && + (range->vello <= vel) && + (range->velhi >= vel)); } /*************************************************************** @@ -1690,9 +1958,9 @@ fluid_zone_inside_range(fluid_zone_range_t* range, int key, int vel) * fluid_sample_in_rom */ int -fluid_sample_in_rom(fluid_sample_t* sample) +fluid_sample_in_rom(fluid_sample_t *sample) { - return (sample->sampletype & FLUID_SAMPLETYPE_ROM); + return (sample->sampletype & FLUID_SAMPLETYPE_ROM); } @@ -1700,35 +1968,35 @@ fluid_sample_in_rom(fluid_sample_t* sample) * fluid_sample_import_sfont */ int -fluid_sample_import_sfont(fluid_sample_t* sample, SFSample* sfsample, fluid_defsfont_t* defsfont) +fluid_sample_import_sfont(fluid_sample_t *sample, SFSample *sfsample, fluid_defsfont_t *defsfont) { - FLUID_STRCPY(sample->name, sfsample->name); + FLUID_STRCPY(sample->name, sfsample->name); - sample->source_start = sfsample->start; - sample->source_end = (sfsample->end > 0) ? sfsample->end - 1 : 0; /* marks last sample, contrary to SF spec. */ - sample->source_loopstart = sfsample->loopstart; - sample->source_loopend = sfsample->loopend; + sample->source_start = sfsample->start; + sample->source_end = (sfsample->end > 0) ? sfsample->end - 1 : 0; /* marks last sample, contrary to SF spec. */ + sample->source_loopstart = sfsample->loopstart; + sample->source_loopend = sfsample->loopend; - sample->start = sample->source_start; - sample->end = sample->source_end; - sample->loopstart = sample->source_loopstart; - sample->loopend = sample->source_loopend; - sample->samplerate = sfsample->samplerate; - sample->origpitch = sfsample->origpitch; - sample->pitchadj = sfsample->pitchadj; - sample->sampletype = sfsample->sampletype; + sample->start = sample->source_start; + sample->end = sample->source_end; + sample->loopstart = sample->source_loopstart; + sample->loopend = sample->source_loopend; + sample->samplerate = sfsample->samplerate; + sample->origpitch = sfsample->origpitch; + sample->pitchadj = sfsample->pitchadj; + sample->sampletype = sfsample->sampletype; - if (defsfont->dynamic_samples) - { - sample->notify = dynamic_samples_sample_notify; - } + if(defsfont->dynamic_samples) + { + sample->notify = dynamic_samples_sample_notify; + } - if (fluid_sample_validate(sample, defsfont->samplesize) == FLUID_FAILED) - { - return FLUID_FAILED; - } + if(fluid_sample_validate(sample, defsfont->samplesize) == FLUID_FAILED) + { + return FLUID_FAILED; + } - return FLUID_OK; + return FLUID_OK; } /* Called if a sample is no longer used by a voice. Used by dynamic sample loading @@ -1736,7 +2004,7 @@ fluid_sample_import_sfont(fluid_sample_t* sample, SFSample* sfsample, fluid_defs * be unloaded straight away because it was still in use by a voice. */ static int dynamic_samples_sample_notify(fluid_sample_t *sample, int reason) { - if (reason == FLUID_SAMPLE_DONE && sample->preset_count == 0) + if(reason == FLUID_SAMPLE_DONE && sample->preset_count == 0) { unload_sample(sample); } @@ -1750,13 +2018,13 @@ static int dynamic_samples_preset_notify(fluid_preset_t *preset, int reason, int { fluid_defsfont_t *defsfont; - if (reason == FLUID_PRESET_SELECTED) + if(reason == FLUID_PRESET_SELECTED) { FLUID_LOG(FLUID_DBG, "Selected preset '%s' on channel %d", fluid_preset_get_name(preset), chan); defsfont = fluid_sfont_get_data(preset->sfont); load_preset_samples(defsfont, preset); } - else if (reason == FLUID_PRESET_UNSELECTED) + else if(reason == FLUID_PRESET_UNSELECTED) { FLUID_LOG(FLUID_DBG, "Deselected preset '%s' from channel %d", fluid_preset_get_name(preset), chan); defsfont = fluid_sfont_get_data(preset->sfont); @@ -1780,35 +2048,39 @@ static int load_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *prese defpreset = fluid_preset_get_data(preset); preset_zone = fluid_defpreset_get_zone(defpreset); - while (preset_zone != NULL) + + while(preset_zone != NULL) { inst = fluid_preset_zone_get_inst(preset_zone); inst_zone = fluid_inst_get_zone(inst); - while (inst_zone != NULL) { + + while(inst_zone != NULL) + { sample = fluid_inst_zone_get_sample(inst_zone); - if ((sample != NULL) && (sample->start != sample->end)) + if((sample != NULL) && (sample->start != sample->end)) { sample->preset_count++; /* If this is the first time this sample has been selected, * load the sampledata */ - if (sample->preset_count == 1) + if(sample->preset_count == 1) { /* Make sure we have an open Soundfont file. Do this here * to avoid having to open the file if no loading is necessary * for a preset */ - if (sffile == NULL) + if(sffile == NULL) { sffile = fluid_sffile_open(defsfont->filename, defsfont->fcbs); - if (sffile == NULL) + + if(sffile == NULL) { FLUID_LOG(FLUID_ERR, "Unable to open Soundfont file"); return FLUID_FAILED; } } - if (fluid_defsfont_load_sampledata(defsfont, sffile, sample) == FLUID_OK) + if(fluid_defsfont_load_sampledata(defsfont, sffile, sample) == FLUID_OK) { fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short)); fluid_voice_optimize_sample(sample); @@ -1823,10 +2095,11 @@ static int load_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *prese inst_zone = fluid_inst_zone_next(inst_zone); } + preset_zone = fluid_preset_zone_next(preset_zone); } - if (sffile != NULL) + if(sffile != NULL) { fluid_sffile_close(sffile); } @@ -1847,14 +2120,17 @@ static int unload_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *pre defpreset = fluid_preset_get_data(preset); preset_zone = fluid_defpreset_get_zone(defpreset); - while (preset_zone != NULL) + + while(preset_zone != NULL) { inst = fluid_preset_zone_get_inst(preset_zone); inst_zone = fluid_inst_get_zone(inst); - while (inst_zone != NULL) { + + while(inst_zone != NULL) + { sample = fluid_inst_zone_get_sample(inst_zone); - if ((sample != NULL) && (sample->preset_count > 0)) + if((sample != NULL) && (sample->preset_count > 0)) { sample->preset_count--; @@ -1863,7 +2139,7 @@ static int unload_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *pre * still in use by a voice, dynamic_samples_sample_notify will * take care of unloading the sample as soon as the voice is * finished with it (but only on the next API call). */ - if (sample->preset_count == 0 && sample->refcount == 0) + if(sample->preset_count == 0 && sample->refcount == 0) { unload_sample(sample); } @@ -1871,6 +2147,7 @@ static int unload_preset_samples(fluid_defsfont_t *defsfont, fluid_preset_t *pre inst_zone = fluid_inst_zone_next(inst_zone); } + preset_zone = fluid_preset_zone_next(preset_zone); } @@ -1887,7 +2164,7 @@ static void unload_sample(fluid_sample_t *sample) FLUID_LOG(FLUID_DBG, "Unloading sample '%s'", sample->name); - if (fluid_samplecache_unload(sample->data) == FLUID_FAILED) + if(fluid_samplecache_unload(sample->data) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Unable to unload sample '%s'", sample->name); } @@ -1903,11 +2180,11 @@ static fluid_inst_t *find_inst_by_idx(fluid_defsfont_t *defsfont, int idx) fluid_list_t *list; fluid_inst_t *inst; - for (list = defsfont->inst; list != NULL; list = fluid_list_next(list)) + for(list = defsfont->inst; list != NULL; list = fluid_list_next(list)) { inst = fluid_list_get(list); - if (inst->source_idx == idx) + if(inst->source_idx == idx) { return inst; } diff --git a/src/sfloader/fluid_defsfont.h b/src/sfloader/fluid_defsfont.h index 3470aa0e..8b24934d 100644 --- a/src/sfloader/fluid_defsfont.h +++ b/src/sfloader/fluid_defsfont.h @@ -58,11 +58,11 @@ typedef struct _fluid_voice_zone_t fluid_voice_zone_t; /* defines the velocity and key range for a zone */ struct _fluid_zone_range_t { - int keylo; - int keyhi; - int vello; - int velhi; - unsigned char ignore; /* set to TRUE for legato playing to ignore this range zone */ + int keylo; + int keyhi; + int vello; + int velhi; + unsigned char ignore; /* set to TRUE for legato playing to ignore this range zone */ }; /* Stored on a preset zone to keep track of the inst zones that could start a voice @@ -79,62 +79,62 @@ struct _fluid_voice_zone_t */ -fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* filename); +fluid_sfont_t *fluid_defsfloader_load(fluid_sfloader_t *loader, const char *filename); -int fluid_defsfont_sfont_delete(fluid_sfont_t* sfont); -const char* fluid_defsfont_sfont_get_name(fluid_sfont_t* sfont); -fluid_preset_t* fluid_defsfont_sfont_get_preset(fluid_sfont_t* sfont, int bank, int prenum); -void fluid_defsfont_sfont_iteration_start(fluid_sfont_t* sfont); -fluid_preset_t *fluid_defsfont_sfont_iteration_next(fluid_sfont_t* sfont); +int fluid_defsfont_sfont_delete(fluid_sfont_t *sfont); +const char *fluid_defsfont_sfont_get_name(fluid_sfont_t *sfont); +fluid_preset_t *fluid_defsfont_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum); +void fluid_defsfont_sfont_iteration_start(fluid_sfont_t *sfont); +fluid_preset_t *fluid_defsfont_sfont_iteration_next(fluid_sfont_t *sfont); -void fluid_defpreset_preset_delete(fluid_preset_t* preset); -const char* fluid_defpreset_preset_get_name(fluid_preset_t* preset); -int fluid_defpreset_preset_get_banknum(fluid_preset_t* preset); -int fluid_defpreset_preset_get_num(fluid_preset_t* preset); -int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel); +void fluid_defpreset_preset_delete(fluid_preset_t *preset); +const char *fluid_defpreset_preset_get_name(fluid_preset_t *preset); +int fluid_defpreset_preset_get_banknum(fluid_preset_t *preset); +int fluid_defpreset_preset_get_num(fluid_preset_t *preset); +int fluid_defpreset_preset_noteon(fluid_preset_t *preset, fluid_synth_t *synth, int chan, int key, int vel); -int fluid_zone_inside_range(fluid_zone_range_t* zone_range, int key, int vel); +int fluid_zone_inside_range(fluid_zone_range_t *zone_range, int key, int vel); /* * fluid_defsfont_t */ struct _fluid_defsfont_t { - const fluid_file_callbacks_t* fcbs; /* the file callbacks used to load this Soundfont */ - char* filename; /* the filename of this soundfont */ - unsigned int samplepos; /* the position in the file at which the sample data starts */ - unsigned int samplesize; /* the size of the sample data in bytes */ - short* sampledata; /* the sample data, loaded in ram */ - - unsigned int sample24pos; /* position within sffd of the sm24 chunk, set to zero if no 24 bit sample support */ - unsigned int sample24size; /* length within sffd of the sm24 chunk */ - char* sample24data; /* if not NULL, the least significant byte of the 24bit sample data, loaded in ram */ - - fluid_sfont_t *sfont; /* pointer to parent sfont */ - fluid_list_t* sample; /* the samples in this soundfont */ - fluid_list_t* preset; /* the presets of this soundfont */ - fluid_list_t* inst; /* the instruments of this soundfont */ - int mlock; /* Should we try memlock (avoid swapping)? */ - int dynamic_samples; /* Enables dynamic sample loading if set */ + const fluid_file_callbacks_t *fcbs; /* the file callbacks used to load this Soundfont */ + char *filename; /* the filename of this soundfont */ + unsigned int samplepos; /* the position in the file at which the sample data starts */ + unsigned int samplesize; /* the size of the sample data in bytes */ + short *sampledata; /* the sample data, loaded in ram */ - fluid_list_t *preset_iter_cur; /* the current preset in the iteration */ + unsigned int sample24pos; /* position within sffd of the sm24 chunk, set to zero if no 24 bit sample support */ + unsigned int sample24size; /* length within sffd of the sm24 chunk */ + char *sample24data; /* if not NULL, the least significant byte of the 24bit sample data, loaded in ram */ + + fluid_sfont_t *sfont; /* pointer to parent sfont */ + fluid_list_t *sample; /* the samples in this soundfont */ + fluid_list_t *preset; /* the presets of this soundfont */ + fluid_list_t *inst; /* the instruments of this soundfont */ + int mlock; /* Should we try memlock (avoid swapping)? */ + int dynamic_samples; /* Enables dynamic sample loading if set */ + + fluid_list_t *preset_iter_cur; /* the current preset in the iteration */ }; -fluid_defsfont_t* new_fluid_defsfont(fluid_settings_t* settings); -int delete_fluid_defsfont(fluid_defsfont_t* defsfont); -int fluid_defsfont_load(fluid_defsfont_t* defsfont, const fluid_file_callbacks_t* file_callbacks, const char* file); -const char* fluid_defsfont_get_name(fluid_defsfont_t* defsfont); -fluid_preset_t* fluid_defsfont_get_preset(fluid_defsfont_t* defsfont, int bank, int prenum); -void fluid_defsfont_iteration_start(fluid_defsfont_t* defsfont); -fluid_preset_t *fluid_defsfont_iteration_next(fluid_defsfont_t* defsfont); +fluid_defsfont_t *new_fluid_defsfont(fluid_settings_t *settings); +int delete_fluid_defsfont(fluid_defsfont_t *defsfont); +int fluid_defsfont_load(fluid_defsfont_t *defsfont, const fluid_file_callbacks_t *file_callbacks, const char *file); +const char *fluid_defsfont_get_name(fluid_defsfont_t *defsfont); +fluid_preset_t *fluid_defsfont_get_preset(fluid_defsfont_t *defsfont, int bank, int prenum); +void fluid_defsfont_iteration_start(fluid_defsfont_t *defsfont); +fluid_preset_t *fluid_defsfont_iteration_next(fluid_defsfont_t *defsfont); int fluid_defsfont_load_sampledata(fluid_defsfont_t *defsfont, SFData *sfdata, fluid_sample_t *sample); int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdata); -int fluid_defsfont_add_sample(fluid_defsfont_t* defsfont, fluid_sample_t* sample); -int fluid_defsfont_add_preset(fluid_defsfont_t* defsfont, fluid_defpreset_t* defpreset); +int fluid_defsfont_add_sample(fluid_defsfont_t *defsfont, fluid_sample_t *sample); +int fluid_defsfont_add_preset(fluid_defsfont_t *defsfont, fluid_defpreset_t *defpreset); /* @@ -142,90 +142,90 @@ int fluid_defsfont_add_preset(fluid_defsfont_t* defsfont, fluid_defpreset_t* def */ struct _fluid_defpreset_t { - fluid_defpreset_t* next; - fluid_defsfont_t* defsfont; /* the soundfont this preset belongs to */ - char name[21]; /* the name of the preset */ - unsigned int bank; /* the bank number */ - unsigned int num; /* the preset number */ - fluid_preset_zone_t* global_zone; /* the global zone of the preset */ - fluid_preset_zone_t* zone; /* the chained list of preset zones */ + fluid_defpreset_t *next; + fluid_defsfont_t *defsfont; /* the soundfont this preset belongs to */ + char name[21]; /* the name of the preset */ + unsigned int bank; /* the bank number */ + unsigned int num; /* the preset number */ + fluid_preset_zone_t *global_zone; /* the global zone of the preset */ + fluid_preset_zone_t *zone; /* the chained list of preset zones */ }; -fluid_defpreset_t* new_fluid_defpreset(fluid_defsfont_t* defsfont); -void delete_fluid_defpreset(fluid_defpreset_t* defpreset); -fluid_defpreset_t* fluid_defpreset_next(fluid_defpreset_t* defpreset); -int fluid_defpreset_import_sfont(fluid_defpreset_t* defpreset, SFPreset* sfpreset, fluid_defsfont_t* defsfont); -int fluid_defpreset_set_global_zone(fluid_defpreset_t* defpreset, fluid_preset_zone_t* zone); -int fluid_defpreset_add_zone(fluid_defpreset_t* defpreset, fluid_preset_zone_t* zone); -fluid_preset_zone_t* fluid_defpreset_get_zone(fluid_defpreset_t* defpreset); -fluid_preset_zone_t* fluid_defpreset_get_global_zone(fluid_defpreset_t* defpreset); -int fluid_defpreset_get_banknum(fluid_defpreset_t* defpreset); -int fluid_defpreset_get_num(fluid_defpreset_t* defpreset); -const char* fluid_defpreset_get_name(fluid_defpreset_t* defpreset); -int fluid_defpreset_noteon(fluid_defpreset_t* defpreset, fluid_synth_t* synth, int chan, int key, int vel); +fluid_defpreset_t *new_fluid_defpreset(fluid_defsfont_t *defsfont); +void delete_fluid_defpreset(fluid_defpreset_t *defpreset); +fluid_defpreset_t *fluid_defpreset_next(fluid_defpreset_t *defpreset); +int fluid_defpreset_import_sfont(fluid_defpreset_t *defpreset, SFPreset *sfpreset, fluid_defsfont_t *defsfont); +int fluid_defpreset_set_global_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone); +int fluid_defpreset_add_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone); +fluid_preset_zone_t *fluid_defpreset_get_zone(fluid_defpreset_t *defpreset); +fluid_preset_zone_t *fluid_defpreset_get_global_zone(fluid_defpreset_t *defpreset); +int fluid_defpreset_get_banknum(fluid_defpreset_t *defpreset); +int fluid_defpreset_get_num(fluid_defpreset_t *defpreset); +const char *fluid_defpreset_get_name(fluid_defpreset_t *defpreset); +int fluid_defpreset_noteon(fluid_defpreset_t *defpreset, fluid_synth_t *synth, int chan, int key, int vel); /* * fluid_preset_zone */ struct _fluid_preset_zone_t { - fluid_preset_zone_t* next; - char* name; - fluid_inst_t* inst; - fluid_list_t* voice_zone; - fluid_zone_range_t range; - fluid_gen_t gen[GEN_LAST]; - fluid_mod_t * mod; /* List of modulators */ + fluid_preset_zone_t *next; + char *name; + fluid_inst_t *inst; + fluid_list_t *voice_zone; + fluid_zone_range_t range; + fluid_gen_t gen[GEN_LAST]; + fluid_mod_t *mod; /* List of modulators */ }; -fluid_preset_zone_t* new_fluid_preset_zone(char* name); -void delete_fluid_preset_zone(fluid_preset_zone_t* zone); -fluid_preset_zone_t* fluid_preset_zone_next(fluid_preset_zone_t* zone); -int fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone* sfzone, fluid_defsfont_t* defssfont); -fluid_inst_t* fluid_preset_zone_get_inst(fluid_preset_zone_t* zone); +fluid_preset_zone_t *new_fluid_preset_zone(char *name); +void delete_fluid_preset_zone(fluid_preset_zone_t *zone); +fluid_preset_zone_t *fluid_preset_zone_next(fluid_preset_zone_t *zone); +int fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defssfont); +fluid_inst_t *fluid_preset_zone_get_inst(fluid_preset_zone_t *zone); /* * fluid_inst_t */ struct _fluid_inst_t { - char name[21]; - int source_idx; /* Index of instrument in source Soundfont */ - fluid_inst_zone_t* global_zone; - fluid_inst_zone_t* zone; + char name[21]; + int source_idx; /* Index of instrument in source Soundfont */ + fluid_inst_zone_t *global_zone; + fluid_inst_zone_t *zone; }; -fluid_inst_t* new_fluid_inst(void); -fluid_inst_t* fluid_inst_import_sfont(fluid_preset_zone_t* preset_zone, SFInst *sfinst, fluid_defsfont_t* defsfont); -void delete_fluid_inst(fluid_inst_t* inst); -int fluid_inst_set_global_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone); -int fluid_inst_add_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone); -fluid_inst_zone_t* fluid_inst_get_zone(fluid_inst_t* inst); -fluid_inst_zone_t* fluid_inst_get_global_zone(fluid_inst_t* inst); +fluid_inst_t *new_fluid_inst(void); +fluid_inst_t *fluid_inst_import_sfont(fluid_preset_zone_t *preset_zone, SFInst *sfinst, fluid_defsfont_t *defsfont); +void delete_fluid_inst(fluid_inst_t *inst); +int fluid_inst_set_global_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone); +int fluid_inst_add_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone); +fluid_inst_zone_t *fluid_inst_get_zone(fluid_inst_t *inst); +fluid_inst_zone_t *fluid_inst_get_global_zone(fluid_inst_t *inst); /* * fluid_inst_zone_t */ struct _fluid_inst_zone_t { - fluid_inst_zone_t* next; - char* name; - fluid_sample_t* sample; - fluid_zone_range_t range; - fluid_gen_t gen[GEN_LAST]; - fluid_mod_t * mod; /* List of modulators */ + fluid_inst_zone_t *next; + char *name; + fluid_sample_t *sample; + fluid_zone_range_t range; + fluid_gen_t gen[GEN_LAST]; + fluid_mod_t *mod; /* List of modulators */ }; -fluid_inst_zone_t* new_fluid_inst_zone(char* name); -void delete_fluid_inst_zone(fluid_inst_zone_t* zone); -fluid_inst_zone_t* fluid_inst_zone_next(fluid_inst_zone_t* zone); -int fluid_inst_zone_import_sfont(fluid_inst_zone_t* inst_zone, SFZone *sfzone, fluid_defsfont_t* defsfont); -fluid_sample_t* fluid_inst_zone_get_sample(fluid_inst_zone_t* zone); +fluid_inst_zone_t *new_fluid_inst_zone(char *name); +void delete_fluid_inst_zone(fluid_inst_zone_t *zone); +fluid_inst_zone_t *fluid_inst_zone_next(fluid_inst_zone_t *zone); +int fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid_defsfont_t *defsfont); +fluid_sample_t *fluid_inst_zone_get_sample(fluid_inst_zone_t *zone); -int fluid_sample_import_sfont(fluid_sample_t* sample, SFSample* sfsample, fluid_defsfont_t* defsfont); -int fluid_sample_in_rom(fluid_sample_t* sample); +int fluid_sample_import_sfont(fluid_sample_t *sample, SFSample *sfsample, fluid_defsfont_t *defsfont); +int fluid_sample_in_rom(fluid_sample_t *sample); #endif /* _FLUID_SFONT_H */ diff --git a/src/sfloader/fluid_ramsfont.c b/src/sfloader/fluid_ramsfont.c index ce084a4a..33085897 100644 --- a/src/sfloader/fluid_ramsfont.c +++ b/src/sfloader/fluid_ramsfont.c @@ -24,171 +24,177 @@ /* Prototypes */ -static int fluid_ramsfont_sfont_delete(fluid_sfont_t* sfont); -static const char *fluid_ramsfont_sfont_get_name(fluid_sfont_t* sfont); -static fluid_preset_t *fluid_ramsfont_sfont_get_preset(fluid_sfont_t* sfont, - int bank, - int prenum); -static void fluid_ramsfont_sfont_iteration_start(fluid_sfont_t* sfont); -static fluid_preset_t *fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont); -static void fluid_rampreset_preset_delete(fluid_preset_t* preset); -static const char *fluid_rampreset_preset_get_name(fluid_preset_t* preset); -static int fluid_rampreset_preset_get_banknum(fluid_preset_t* preset); -static int fluid_rampreset_preset_get_num(fluid_preset_t* preset); -static int fluid_rampreset_preset_noteon(fluid_preset_t* preset, - fluid_synth_t* synth, int chan, - int key, int vel); -static fluid_ramsfont_t *new_fluid_ramsfont (void); -static int delete_fluid_ramsfont (fluid_ramsfont_t* sfont); -static const char *fluid_ramsfont_get_name(fluid_ramsfont_t* sfont); -static int fluid_ramsfont_add_preset (fluid_ramsfont_t* sfont, - fluid_rampreset_t* rampreset); -static fluid_preset_t *fluid_ramsfont_get_preset (fluid_ramsfont_t* sfont, - int bank, int num); -static void fluid_ramsfont_iteration_start (fluid_ramsfont_t* sfont); -static fluid_preset_t *fluid_ramsfont_iteration_next (fluid_ramsfont_t* sfont); -static fluid_rampreset_t* new_fluid_rampreset(fluid_ramsfont_t* sfont); -static void delete_fluid_rampreset (fluid_rampreset_t* preset); -static int fluid_rampreset_get_banknum (fluid_rampreset_t* preset); -static int fluid_rampreset_get_num (fluid_rampreset_t* preset); -static const char *fluid_rampreset_get_name (fluid_rampreset_t* preset); -static int fluid_rampreset_add_zone(fluid_rampreset_t* preset, - fluid_preset_zone_t* zone); -static int fluid_rampreset_add_sample (fluid_rampreset_t* preset, - fluid_sample_t* sample, - int lokey, int hikey); -static fluid_inst_zone_t *fluid_rampreset_izoneforsample (fluid_rampreset_t* preset, - fluid_sample_t* sample); -static int fluid_rampreset_izone_set_loop (fluid_rampreset_t* preset, - fluid_sample_t* sample, - int on, float loopstart, float loopend); -static int fluid_rampreset_izone_set_gen (fluid_rampreset_t* preset, - fluid_sample_t* sample, - int gen_type, float value); -static int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, - fluid_sample_t* sample); -static int fluid_rampreset_remembervoice (fluid_rampreset_t* preset, - fluid_voice_t* voice); -static void fluid_rampreset_updatevoices (fluid_rampreset_t* preset, - int gen_type, float val); -static int fluid_rampreset_noteon (fluid_rampreset_t* preset, fluid_synth_t* synth, - int chan, int key, int vel); +static int fluid_ramsfont_sfont_delete(fluid_sfont_t *sfont); +static const char *fluid_ramsfont_sfont_get_name(fluid_sfont_t *sfont); +static fluid_preset_t *fluid_ramsfont_sfont_get_preset(fluid_sfont_t *sfont, + int bank, + int prenum); +static void fluid_ramsfont_sfont_iteration_start(fluid_sfont_t *sfont); +static fluid_preset_t *fluid_ramsfont_sfont_iteration_next(fluid_sfont_t *sfont); +static void fluid_rampreset_preset_delete(fluid_preset_t *preset); +static const char *fluid_rampreset_preset_get_name(fluid_preset_t *preset); +static int fluid_rampreset_preset_get_banknum(fluid_preset_t *preset); +static int fluid_rampreset_preset_get_num(fluid_preset_t *preset); +static int fluid_rampreset_preset_noteon(fluid_preset_t *preset, + fluid_synth_t *synth, int chan, + int key, int vel); +static fluid_ramsfont_t *new_fluid_ramsfont(void); +static int delete_fluid_ramsfont(fluid_ramsfont_t *sfont); +static const char *fluid_ramsfont_get_name(fluid_ramsfont_t *sfont); +static int fluid_ramsfont_add_preset(fluid_ramsfont_t *sfont, + fluid_rampreset_t *rampreset); +static fluid_preset_t *fluid_ramsfont_get_preset(fluid_ramsfont_t *sfont, + int bank, int num); +static void fluid_ramsfont_iteration_start(fluid_ramsfont_t *sfont); +static fluid_preset_t *fluid_ramsfont_iteration_next(fluid_ramsfont_t *sfont); +static fluid_rampreset_t *new_fluid_rampreset(fluid_ramsfont_t *sfont); +static void delete_fluid_rampreset(fluid_rampreset_t *preset); +static int fluid_rampreset_get_banknum(fluid_rampreset_t *preset); +static int fluid_rampreset_get_num(fluid_rampreset_t *preset); +static const char *fluid_rampreset_get_name(fluid_rampreset_t *preset); +static int fluid_rampreset_add_zone(fluid_rampreset_t *preset, + fluid_preset_zone_t *zone); +static int fluid_rampreset_add_sample(fluid_rampreset_t *preset, + fluid_sample_t *sample, + int lokey, int hikey); +static fluid_inst_zone_t *fluid_rampreset_izoneforsample(fluid_rampreset_t *preset, + fluid_sample_t *sample); +static int fluid_rampreset_izone_set_loop(fluid_rampreset_t *preset, + fluid_sample_t *sample, + int on, float loopstart, float loopend); +static int fluid_rampreset_izone_set_gen(fluid_rampreset_t *preset, + fluid_sample_t *sample, + int gen_type, float value); +static int fluid_rampreset_remove_izone(fluid_rampreset_t *preset, + fluid_sample_t *sample); +static int fluid_rampreset_remembervoice(fluid_rampreset_t *preset, + fluid_voice_t *voice); +static void fluid_rampreset_updatevoices(fluid_rampreset_t *preset, + int gen_type, float val); +static int fluid_rampreset_noteon(fluid_rampreset_t *preset, fluid_synth_t *synth, + int chan, int key, int vel); /** * Create a #fluid_sfont_t wrapping a #fluid_ramsfont_t * @return New #fluid_sfont_t or NULL if out of memory */ -fluid_sfont_t* +fluid_sfont_t * fluid_ramsfont_create_sfont() { - fluid_sfont_t* sfont; - fluid_ramsfont_t* ramsfont; + fluid_sfont_t *sfont; + fluid_ramsfont_t *ramsfont; - ramsfont = new_fluid_ramsfont(); - if (ramsfont == NULL) { - return NULL; - } + ramsfont = new_fluid_ramsfont(); - sfont = new_fluid_sfont(fluid_ramsfont_sfont_get_name, - fluid_ramsfont_sfont_get_preset, - fluid_ramsfont_sfont_iteration_start, - fluid_ramsfont_sfont_iteration_next, - fluid_ramsfont_sfont_delete); - if (sfont == NULL) - { - delete_fluid_ramsfont(ramsfont); - return NULL; - } - - fluid_sfont_set_data(sfont, ramsfont); - ramsfont->sfont = sfont; + if(ramsfont == NULL) + { + return NULL; + } - return sfont; + sfont = new_fluid_sfont(fluid_ramsfont_sfont_get_name, + fluid_ramsfont_sfont_get_preset, + fluid_ramsfont_sfont_iteration_start, + fluid_ramsfont_sfont_iteration_next, + fluid_ramsfont_sfont_delete); + + if(sfont == NULL) + { + delete_fluid_ramsfont(ramsfont); + return NULL; + } + + fluid_sfont_set_data(sfont, ramsfont); + ramsfont->sfont = sfont; + + return sfont; } /* RAM SoundFont loader method to delete SoundFont */ static int -fluid_ramsfont_sfont_delete(fluid_sfont_t* sfont) +fluid_ramsfont_sfont_delete(fluid_sfont_t *sfont) { - if (delete_fluid_ramsfont(sfont->data) != 0) - return -1; - delete_fluid_sfont(sfont); - return 0; + if(delete_fluid_ramsfont(sfont->data) != 0) + { + return -1; + } + + delete_fluid_sfont(sfont); + return 0; } /* RAM SoundFont loader method to get name */ static const char * -fluid_ramsfont_sfont_get_name(fluid_sfont_t* sfont) +fluid_ramsfont_sfont_get_name(fluid_sfont_t *sfont) { - return fluid_ramsfont_get_name((fluid_ramsfont_t*) sfont->data); + return fluid_ramsfont_get_name((fluid_ramsfont_t *) sfont->data); } /* RAM SoundFont loader method to get a preset */ static fluid_preset_t * -fluid_ramsfont_sfont_get_preset(fluid_sfont_t* sfont, int bank, int prenum) +fluid_ramsfont_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum) { - return fluid_ramsfont_get_preset((fluid_ramsfont_t*) sfont->data, bank, prenum); + return fluid_ramsfont_get_preset((fluid_ramsfont_t *) sfont->data, bank, prenum); } /* RAM SoundFont loader method to start preset iteration */ static void -fluid_ramsfont_sfont_iteration_start(fluid_sfont_t* sfont) +fluid_ramsfont_sfont_iteration_start(fluid_sfont_t *sfont) { - fluid_ramsfont_iteration_start((fluid_ramsfont_t*) sfont->data); + fluid_ramsfont_iteration_start((fluid_ramsfont_t *) sfont->data); } /* RAM SoundFont loader method to advance preset iteration */ -static fluid_preset_t* -fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont) +static fluid_preset_t * +fluid_ramsfont_sfont_iteration_next(fluid_sfont_t *sfont) { - return fluid_ramsfont_iteration_next((fluid_ramsfont_t*) sfont->data); + return fluid_ramsfont_iteration_next((fluid_ramsfont_t *) sfont->data); } -void fluid_rampreset_preset_delete(fluid_preset_t* preset) +void fluid_rampreset_preset_delete(fluid_preset_t *preset) { - fluid_ramsfont_t* ramsfont; - fluid_rampreset_t* rampreset; - fluid_return_if_fail(preset != NULL); + fluid_ramsfont_t *ramsfont; + fluid_rampreset_t *rampreset; + fluid_return_if_fail(preset != NULL); - ramsfont = fluid_sfont_get_data(preset->sfont); - rampreset = fluid_preset_get_data(preset); + ramsfont = fluid_sfont_get_data(preset->sfont); + rampreset = fluid_preset_get_data(preset); - if (ramsfont) - { - ramsfont->preset = fluid_list_remove(ramsfont->preset, rampreset); - } + if(ramsfont) + { + ramsfont->preset = fluid_list_remove(ramsfont->preset, rampreset); + } - delete_fluid_rampreset(rampreset); - delete_fluid_preset(preset); + delete_fluid_rampreset(rampreset); + delete_fluid_preset(preset); } /* RAM SoundFont loader get preset name method */ static const char * -fluid_rampreset_preset_get_name(fluid_preset_t* preset) +fluid_rampreset_preset_get_name(fluid_preset_t *preset) { - return fluid_rampreset_get_name((fluid_rampreset_t*) preset->data); + return fluid_rampreset_get_name((fluid_rampreset_t *) preset->data); } /* RAM SoundFont loader get preset bank method */ static int -fluid_rampreset_preset_get_banknum(fluid_preset_t* preset) +fluid_rampreset_preset_get_banknum(fluid_preset_t *preset) { - return fluid_rampreset_get_banknum((fluid_rampreset_t*) preset->data); + return fluid_rampreset_get_banknum((fluid_rampreset_t *) preset->data); } /* RAM SoundFont loader get preset program method */ static int -fluid_rampreset_preset_get_num(fluid_preset_t* preset) +fluid_rampreset_preset_get_num(fluid_preset_t *preset) { - return fluid_rampreset_get_num((fluid_rampreset_t*) preset->data); + return fluid_rampreset_get_num((fluid_rampreset_t *) preset->data); } /* RAM SoundFont loader preset noteon method */ static int -fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel) +fluid_rampreset_preset_noteon(fluid_preset_t *preset, fluid_synth_t *synth, int chan, int key, int vel) { - return fluid_rampreset_noteon((fluid_rampreset_t*) preset->data, synth, chan, key, vel); + return fluid_rampreset_noteon((fluid_rampreset_t *) preset->data, synth, chan, key, vel); } @@ -200,62 +206,71 @@ fluid_rampreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int */ static fluid_ramsfont_t * -new_fluid_ramsfont (void) +new_fluid_ramsfont(void) { - fluid_ramsfont_t* sfont; + fluid_ramsfont_t *sfont; - sfont = FLUID_NEW(fluid_ramsfont_t); - if (sfont == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + sfont = FLUID_NEW(fluid_ramsfont_t); - sfont->name[0] = 0; - sfont->sample = NULL; - sfont->preset = NULL; + if(sfont == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - return sfont; + sfont->name[0] = 0; + sfont->sample = NULL; + sfont->preset = NULL; + + return sfont; } static int -delete_fluid_ramsfont (fluid_ramsfont_t* sfont) +delete_fluid_ramsfont(fluid_ramsfont_t *sfont) { - fluid_list_t *list; - fluid_preset_t* preset; - fluid_return_val_if_fail(sfont != NULL, FLUID_OK); + fluid_list_t *list; + fluid_preset_t *preset; + fluid_return_val_if_fail(sfont != NULL, FLUID_OK); - /* Check that no samples are currently used */ - for (list = sfont->sample; list; list = fluid_list_next(list)) { - fluid_sample_t* sam = (fluid_sample_t*) fluid_list_get(list); - if (sam->refcount != 0) { - return -1; + /* Check that no samples are currently used */ + for(list = sfont->sample; list; list = fluid_list_next(list)) + { + fluid_sample_t *sam = (fluid_sample_t *) fluid_list_get(list); + + if(sam->refcount != 0) + { + return -1; + } } - } - for (list = sfont->sample; list; list = fluid_list_next(list)) { - /* in ram soundfonts, the samples hold their data : so we should free it ourselves */ - fluid_sample_t* sam = (fluid_sample_t*)fluid_list_get(list); - delete_fluid_sample(sam); - } + for(list = sfont->sample; list; list = fluid_list_next(list)) + { + /* in ram soundfonts, the samples hold their data : so we should free it ourselves */ + fluid_sample_t *sam = (fluid_sample_t *)fluid_list_get(list); + delete_fluid_sample(sam); + } - if (sfont->sample) { - delete_fluid_list(sfont->sample); - } + if(sfont->sample) + { + delete_fluid_list(sfont->sample); + } - for (list = sfont->preset; list; list = fluid_list_next(list)) { - preset = (fluid_preset_t *)fluid_list_get(list); - fluid_rampreset_preset_delete(preset); - } - delete_fluid_list(sfont->preset); + for(list = sfont->preset; list; list = fluid_list_next(list)) + { + preset = (fluid_preset_t *)fluid_list_get(list); + fluid_rampreset_preset_delete(preset); + } - FLUID_FREE(sfont); - return FLUID_OK; + delete_fluid_list(sfont->preset); + + FLUID_FREE(sfont); + return FLUID_OK; } static const char * -fluid_ramsfont_get_name(fluid_ramsfont_t* sfont) +fluid_ramsfont_get_name(fluid_ramsfont_t *sfont) { - return sfont->name; + return sfont->name; } /** @@ -265,33 +280,36 @@ fluid_ramsfont_get_name(fluid_ramsfont_t* sfont) * @return #FLUID_OK */ int -fluid_ramsfont_set_name (fluid_ramsfont_t *sfont, const char *name) +fluid_ramsfont_set_name(fluid_ramsfont_t *sfont, const char *name) { - FLUID_MEMCPY(sfont->name, name, 20); - return FLUID_OK; + FLUID_MEMCPY(sfont->name, name, 20); + return FLUID_OK; } /* Add a preset to a RAM SoundFont */ static int -fluid_ramsfont_add_preset (fluid_ramsfont_t* sfont, fluid_rampreset_t* rampreset) +fluid_ramsfont_add_preset(fluid_ramsfont_t *sfont, fluid_rampreset_t *rampreset) { - fluid_preset_t *preset; + fluid_preset_t *preset; - preset = new_fluid_preset(sfont->sfont, - fluid_rampreset_preset_get_name, - fluid_rampreset_preset_get_banknum, - fluid_rampreset_preset_get_num, - fluid_rampreset_preset_noteon, - fluid_rampreset_preset_delete); /* TODO: free modulators */ - if (preset == NULL) { - return FLUID_FAILED; - } - fluid_preset_set_data(preset, rampreset); + preset = new_fluid_preset(sfont->sfont, + fluid_rampreset_preset_get_name, + fluid_rampreset_preset_get_banknum, + fluid_rampreset_preset_get_num, + fluid_rampreset_preset_noteon, + fluid_rampreset_preset_delete); /* TODO: free modulators */ - sfont->preset = fluid_list_append(sfont->preset, preset); + if(preset == NULL) + { + return FLUID_FAILED; + } - return FLUID_OK; + fluid_preset_set_data(preset, rampreset); + + sfont->preset = fluid_list_append(sfont->preset, preset); + + return FLUID_OK; } /** @@ -306,51 +324,61 @@ fluid_ramsfont_add_preset (fluid_ramsfont_t* sfont, fluid_rampreset_t* rampreset * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont, int bank, - int num, fluid_sample_t* sample, +fluid_ramsfont_add_izone(fluid_ramsfont_t *sfont, int bank, + int num, fluid_sample_t *sample, int lokey, int hikey) { - /*- find or create a preset - - add it the sample using the fluid_rampreset_add_sample fucntion - - add the sample to the list of samples - */ - int err; + /*- find or create a preset + - add it the sample using the fluid_rampreset_add_sample fucntion + - add the sample to the list of samples + */ + int err; - fluid_rampreset_t* rampreset; - fluid_preset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); - if (preset == NULL) { - // Create it - rampreset = new_fluid_rampreset(sfont); - if (rampreset == NULL) { - return FLUID_FAILED; - } + fluid_rampreset_t *rampreset; + fluid_preset_t *preset = fluid_ramsfont_get_preset(sfont, bank, num); - rampreset->bank = bank; - rampreset->num = num; + if(preset == NULL) + { + // Create it + rampreset = new_fluid_rampreset(sfont); - // sort the preset - fluid_ramsfont_add_preset(sfont, rampreset); + if(rampreset == NULL) + { + return FLUID_FAILED; + } - err = fluid_rampreset_add_sample(rampreset, sample, lokey, hikey); - if (err != FLUID_OK) { + rampreset->bank = bank; + rampreset->num = num; + + // sort the preset + fluid_ramsfont_add_preset(sfont, rampreset); + + err = fluid_rampreset_add_sample(rampreset, sample, lokey, hikey); + + if(err != FLUID_OK) + { // MWE: delete preset (also check that all preset delete also remove list item!) fluid_rampreset_preset_delete(preset); - return FLUID_FAILED; - } + return FLUID_FAILED; + } - } else { + } + else + { - // just add it + // just add it rampreset = fluid_preset_get_data(preset); - err = fluid_rampreset_add_sample(rampreset, sample, lokey, hikey); - if (err != FLUID_OK) { - return FLUID_FAILED; - } - } + err = fluid_rampreset_add_sample(rampreset, sample, lokey, hikey); - sfont->sample = fluid_list_append(sfont->sample, sample); - return FLUID_OK; + if(err != FLUID_OK) + { + return FLUID_FAILED; + } + } + + sfont->sample = fluid_list_append(sfont->sample, sample); + return FLUID_OK; } /** @@ -362,28 +390,33 @@ fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont, int bank, * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_ramsfont_remove_izone (fluid_ramsfont_t* sfont, int bank, - int num, fluid_sample_t* sample) +fluid_ramsfont_remove_izone(fluid_ramsfont_t *sfont, int bank, + int num, fluid_sample_t *sample) { - int err; + int err; fluid_rampreset_t *rampreset; - fluid_preset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); - if (preset == NULL) { - return FLUID_FAILED; - } + fluid_preset_t *preset = fluid_ramsfont_get_preset(sfont, bank, num); + + if(preset == NULL) + { + return FLUID_FAILED; + } rampreset = fluid_preset_get_data(preset); - // Fixed a crash bug : remove the sample from the sfont list after - // removing the izone (aschmitt august 2005) - err = fluid_rampreset_remove_izone(rampreset, sample); - if (err != FLUID_OK) - return err; + // Fixed a crash bug : remove the sample from the sfont list after + // removing the izone (aschmitt august 2005) + err = fluid_rampreset_remove_izone(rampreset, sample); - // now we must remove the sample from sfont->sample - sfont->sample = fluid_list_remove(sfont->sample, sample); + if(err != FLUID_OK) + { + return err; + } - return FLUID_OK; + // now we must remove the sample from sfont->sample + sfont->sample = fluid_list_remove(sfont->sample, sample); + + return FLUID_OK; } /** @@ -397,19 +430,21 @@ fluid_ramsfont_remove_izone (fluid_ramsfont_t* sfont, int bank, * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_ramsfont_izone_set_gen (fluid_ramsfont_t* sfont, int bank, - int num, fluid_sample_t* sample, - int gen_type, float value) +fluid_ramsfont_izone_set_gen(fluid_ramsfont_t *sfont, int bank, + int num, fluid_sample_t *sample, + int gen_type, float value) { - fluid_rampreset_t* rampreset; - fluid_preset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); - if (preset == NULL) { - return FLUID_FAILED; - } + fluid_rampreset_t *rampreset; + fluid_preset_t *preset = fluid_ramsfont_get_preset(sfont, bank, num); + + if(preset == NULL) + { + return FLUID_FAILED; + } rampreset = fluid_preset_get_data(preset); - return fluid_rampreset_izone_set_gen(rampreset, sample, gen_type, value); + return fluid_rampreset_izone_set_gen(rampreset, sample, gen_type, value); } /** @@ -426,24 +461,26 @@ fluid_ramsfont_izone_set_gen (fluid_ramsfont_t* sfont, int bank, * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_ramsfont_izone_set_loop (fluid_ramsfont_t *sfont, int bank, - int num, fluid_sample_t* sample, - int on, float loopstart, float loopend) +fluid_ramsfont_izone_set_loop(fluid_ramsfont_t *sfont, int bank, + int num, fluid_sample_t *sample, + int on, float loopstart, float loopend) { - fluid_rampreset_t* rampreset; - fluid_preset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); - if (preset == NULL) { - return FLUID_FAILED; - } + fluid_rampreset_t *rampreset; + fluid_preset_t *preset = fluid_ramsfont_get_preset(sfont, bank, num); + + if(preset == NULL) + { + return FLUID_FAILED; + } rampreset = fluid_preset_get_data(preset); - return fluid_rampreset_izone_set_loop(rampreset, sample, on, loopstart, loopend); + return fluid_rampreset_izone_set_loop(rampreset, sample, on, loopstart, loopend); } /* Get a preset from a RAM SoundFont */ static fluid_preset_t * -fluid_ramsfont_get_preset (fluid_ramsfont_t* sfont, int bank, int num) +fluid_ramsfont_get_preset(fluid_ramsfont_t *sfont, int bank, int num) { fluid_preset_t *preset; fluid_list_t *list; @@ -452,7 +489,7 @@ fluid_ramsfont_get_preset (fluid_ramsfont_t* sfont, int bank, int num) { preset = (fluid_preset_t *)fluid_list_get(list); - if ((fluid_preset_get_banknum(preset) == bank) && (fluid_preset_get_num(preset) == num)) + if((fluid_preset_get_banknum(preset) == bank) && (fluid_preset_get_num(preset) == num)) { return preset; } @@ -463,20 +500,20 @@ fluid_ramsfont_get_preset (fluid_ramsfont_t* sfont, int bank, int num) /* Start preset iteration in a RAM SoundFont */ static void -fluid_ramsfont_iteration_start (fluid_ramsfont_t* sfont) +fluid_ramsfont_iteration_start(fluid_ramsfont_t *sfont) { - sfont->preset_iter_cur = sfont->preset; + sfont->preset_iter_cur = sfont->preset; } /* Advance preset iteration in a RAM SoundFont */ static fluid_preset_t * -fluid_ramsfont_iteration_next (fluid_ramsfont_t* sfont) +fluid_ramsfont_iteration_next(fluid_ramsfont_t *sfont) { - fluid_preset_t *preset = (fluid_preset_t *)fluid_list_get(sfont->preset_iter_cur); + fluid_preset_t *preset = (fluid_preset_t *)fluid_list_get(sfont->preset_iter_cur); - sfont->preset_iter_cur = fluid_list_next(sfont->preset_iter_cur); + sfont->preset_iter_cur = fluid_list_next(sfont->preset_iter_cur); - return preset; + return preset; } /*************************************************************** @@ -485,582 +522,716 @@ fluid_ramsfont_iteration_next (fluid_ramsfont_t* sfont) */ typedef struct _fluid_rampreset_voice_t fluid_rampreset_voice_t; -struct _fluid_rampreset_voice_t { - fluid_voice_t *voice; - unsigned int voiceID; +struct _fluid_rampreset_voice_t +{ + fluid_voice_t *voice; + unsigned int voiceID; }; /* Create a new RAM SoundFont preset */ -static fluid_rampreset_t* -new_fluid_rampreset(fluid_ramsfont_t* sfont) +static fluid_rampreset_t * +new_fluid_rampreset(fluid_ramsfont_t *sfont) { - fluid_rampreset_t* preset = FLUID_NEW(fluid_rampreset_t); - if (preset == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - preset->next = NULL; - preset->sfont = sfont; - preset->name[0] = 0; - preset->bank = 0; - preset->num = 0; - preset->global_zone = NULL; - preset->zone = NULL; - preset->presetvoices = NULL; - return preset; + fluid_rampreset_t *preset = FLUID_NEW(fluid_rampreset_t); + + if(preset == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + preset->next = NULL; + preset->sfont = sfont; + preset->name[0] = 0; + preset->bank = 0; + preset->num = 0; + preset->global_zone = NULL; + preset->zone = NULL; + preset->presetvoices = NULL; + return preset; } /* Delete a RAM SoundFont preset */ static void -delete_fluid_rampreset (fluid_rampreset_t* preset) +delete_fluid_rampreset(fluid_rampreset_t *preset) { - fluid_preset_zone_t* zone; - fluid_rampreset_voice_t *data; - fluid_return_if_fail(preset != NULL); + fluid_preset_zone_t *zone; + fluid_rampreset_voice_t *data; + fluid_return_if_fail(preset != NULL); + + if(preset->global_zone != NULL) + { + delete_fluid_preset_zone(preset->global_zone); + preset->global_zone = NULL; + } - if (preset->global_zone != NULL) { - delete_fluid_preset_zone(preset->global_zone); - preset->global_zone = NULL; - } - zone = preset->zone; - while (zone != NULL) { - preset->zone = zone->next; - delete_fluid_preset_zone(zone); zone = preset->zone; - } - if (preset->presetvoices != NULL) { - fluid_list_t *tmp = preset->presetvoices, *next; - while (tmp) { - data = (fluid_rampreset_voice_t *)(tmp->data); - FLUID_FREE(data); + while(zone != NULL) + { + preset->zone = zone->next; + delete_fluid_preset_zone(zone); + zone = preset->zone; + } - next = tmp->next; - FLUID_FREE(tmp); - tmp = next; - } - } - preset->presetvoices = NULL; + if(preset->presetvoices != NULL) + { + fluid_list_t *tmp = preset->presetvoices, *next; - FLUID_FREE(preset); + while(tmp) + { + data = (fluid_rampreset_voice_t *)(tmp->data); + FLUID_FREE(data); + + next = tmp->next; + FLUID_FREE(tmp); + tmp = next; + } + } + + preset->presetvoices = NULL; + + FLUID_FREE(preset); } /* Get a RAM SoundFont preset bank */ static int -fluid_rampreset_get_banknum (fluid_rampreset_t* preset) +fluid_rampreset_get_banknum(fluid_rampreset_t *preset) { - return preset->bank; + return preset->bank; } /* Get a RAM SoundFont preset program */ static int -fluid_rampreset_get_num (fluid_rampreset_t* preset) +fluid_rampreset_get_num(fluid_rampreset_t *preset) { - return preset->num; + return preset->num; } /* Get a RAM SoundFont preset name */ static const char * -fluid_rampreset_get_name (fluid_rampreset_t* preset) +fluid_rampreset_get_name(fluid_rampreset_t *preset) { - return preset->name; + return preset->name; } /* Add a zone to a RAM SoundFont preset */ static int -fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone) +fluid_rampreset_add_zone(fluid_rampreset_t *preset, fluid_preset_zone_t *zone) { - if (preset->zone == NULL) { - zone->next = NULL; - preset->zone = zone; - } else { - zone->next = preset->zone; - preset->zone = zone; - } - return FLUID_OK; + if(preset->zone == NULL) + { + zone->next = NULL; + preset->zone = zone; + } + else + { + zone->next = preset->zone; + preset->zone = zone; + } + + return FLUID_OK; } /* Add a sample to a RAM SoundFont preset */ static int -fluid_rampreset_add_sample (fluid_rampreset_t* preset, fluid_sample_t* sample, - int lokey, int hikey) +fluid_rampreset_add_sample(fluid_rampreset_t *preset, fluid_sample_t *sample, + int lokey, int hikey) { - /* create a new instrument zone, with the given sample */ + /* create a new instrument zone, with the given sample */ - /* one preset zone */ - if (preset->zone == NULL) { - fluid_preset_zone_t* zone; - zone = new_fluid_preset_zone(""); - if (zone == NULL) { - return FLUID_FAILED; - } + /* one preset zone */ + if(preset->zone == NULL) + { + fluid_preset_zone_t *zone; + zone = new_fluid_preset_zone(""); - /* its instrument */ - zone->inst = (fluid_inst_t*) new_fluid_inst(); - if (zone->inst == NULL) { - delete_fluid_preset_zone(zone); - return FLUID_FAILED; + if(zone == NULL) + { + return FLUID_FAILED; + } + + /* its instrument */ + zone->inst = (fluid_inst_t *) new_fluid_inst(); + + if(zone->inst == NULL) + { + delete_fluid_preset_zone(zone); + return FLUID_FAILED; + } + + fluid_rampreset_add_zone(preset, zone); } - fluid_rampreset_add_zone(preset, zone); - } + /* add an instrument zone for each sample */ + { + fluid_inst_t *inst = fluid_preset_zone_get_inst(preset->zone); + fluid_inst_zone_t *izone = new_fluid_inst_zone(""); - /* add an instrument zone for each sample */ - { - fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone); - fluid_inst_zone_t* izone = new_fluid_inst_zone(""); - if (izone == NULL) { - return FLUID_FAILED; - } + if(izone == NULL) + { + return FLUID_FAILED; + } - if (fluid_inst_add_zone(inst, izone) != FLUID_OK) { - delete_fluid_inst_zone(izone); - return FLUID_FAILED; - } + if(fluid_inst_add_zone(inst, izone) != FLUID_OK) + { + delete_fluid_inst_zone(izone); + return FLUID_FAILED; + } - izone->sample = sample; - izone->range.keylo = lokey; - izone->range.keyhi = hikey; + izone->sample = sample; + izone->range.keylo = lokey; + izone->range.keyhi = hikey; - // give the preset the name of the sample - FLUID_MEMCPY(preset->name, sample->name, 20); - } + // give the preset the name of the sample + FLUID_MEMCPY(preset->name, sample->name, 20); + } - return FLUID_OK; + return FLUID_OK; } /* Find an instrument zone with the given sample */ static fluid_inst_zone_t * -fluid_rampreset_izoneforsample (fluid_rampreset_t* preset, fluid_sample_t* sample) +fluid_rampreset_izoneforsample(fluid_rampreset_t *preset, fluid_sample_t *sample) { - fluid_inst_t* inst; - fluid_inst_zone_t* izone; + fluid_inst_t *inst; + fluid_inst_zone_t *izone; - if (preset->zone == NULL) return NULL; + if(preset->zone == NULL) + { + return NULL; + } - inst = fluid_preset_zone_get_inst(preset->zone); - izone = inst->zone; - while (izone) { - if (izone->sample == sample) - return izone; - izone = izone->next; - } - return NULL; + inst = fluid_preset_zone_get_inst(preset->zone); + izone = inst->zone; + + while(izone) + { + if(izone->sample == sample) + { + return izone; + } + + izone = izone->next; + } + + return NULL; } /* Set loop of an instrument zone */ static int -fluid_rampreset_izone_set_loop (fluid_rampreset_t* preset, fluid_sample_t* sample, - int on, float loopstart, float loopend) +fluid_rampreset_izone_set_loop(fluid_rampreset_t *preset, fluid_sample_t *sample, + int on, float loopstart, float loopend) { - fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample); - short coarse, fine; + fluid_inst_zone_t *izone = fluid_rampreset_izoneforsample(preset, sample); + short coarse, fine; - if (izone == NULL) - return FLUID_FAILED; + if(izone == NULL) + { + return FLUID_FAILED; + } - if (!on) { - izone->gen[GEN_SAMPLEMODE].flags = GEN_SET; - izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED; - fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED); - return FLUID_OK; - } + if(!on) + { + izone->gen[GEN_SAMPLEMODE].flags = GEN_SET; + izone->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED; + fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_UNLOOPED); + return FLUID_OK; + } - /* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */ + /* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */ - /* loopstart */ - if (loopstart > 32767. || loopstart < -32767.) { - coarse = (short)(loopstart/32768.); - fine = (short)(loopstart - (float)(coarse)*32768.); - } else { - coarse = 0; - fine = (short)loopstart; - } - izone->gen[GEN_STARTLOOPADDROFS].flags = GEN_SET; - izone->gen[GEN_STARTLOOPADDROFS].val = fine; - fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDROFS, fine); - if (coarse) { - izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_SET; - izone->gen[GEN_STARTLOOPADDRCOARSEOFS].val = coarse; - } else { - izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_UNUSED; - } - fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDRCOARSEOFS, coarse); + /* loopstart */ + if(loopstart > 32767. || loopstart < -32767.) + { + coarse = (short)(loopstart / 32768.); + fine = (short)(loopstart - (float)(coarse) * 32768.); + } + else + { + coarse = 0; + fine = (short)loopstart; + } - /* loopend */ - if (loopend > 32767. || loopend < -32767.) { - coarse = (short)(loopend/32768.); - fine = (short)(loopend - (float)(coarse)*32768.); - } else { - coarse = 0; - fine = (short)loopend; - } - izone->gen[GEN_ENDLOOPADDROFS].flags = GEN_SET; - izone->gen[GEN_ENDLOOPADDROFS].val = fine; - fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDROFS, fine); - if (coarse) { - izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_SET; - izone->gen[GEN_ENDLOOPADDRCOARSEOFS].val = coarse; - } else { - izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_UNUSED; - } - fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDRCOARSEOFS, coarse); + izone->gen[GEN_STARTLOOPADDROFS].flags = GEN_SET; + izone->gen[GEN_STARTLOOPADDROFS].val = fine; + fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDROFS, fine); - izone->gen[GEN_SAMPLEMODE].flags = GEN_SET; - izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE; - fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE); + if(coarse) + { + izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_SET; + izone->gen[GEN_STARTLOOPADDRCOARSEOFS].val = coarse; + } + else + { + izone->gen[GEN_STARTLOOPADDRCOARSEOFS].flags = GEN_UNUSED; + } - /* If the loop points are the whole samples, we are supposed to - copy the frames around in the margins (the start to the end margin and - the end to the start margin), but it works fine without this. Maybe some time - it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */ + fluid_rampreset_updatevoices(preset, GEN_STARTLOOPADDRCOARSEOFS, coarse); - return FLUID_OK; + /* loopend */ + if(loopend > 32767. || loopend < -32767.) + { + coarse = (short)(loopend / 32768.); + fine = (short)(loopend - (float)(coarse) * 32768.); + } + else + { + coarse = 0; + fine = (short)loopend; + } + + izone->gen[GEN_ENDLOOPADDROFS].flags = GEN_SET; + izone->gen[GEN_ENDLOOPADDROFS].val = fine; + fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDROFS, fine); + + if(coarse) + { + izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_SET; + izone->gen[GEN_ENDLOOPADDRCOARSEOFS].val = coarse; + } + else + { + izone->gen[GEN_ENDLOOPADDRCOARSEOFS].flags = GEN_UNUSED; + } + + fluid_rampreset_updatevoices(preset, GEN_ENDLOOPADDRCOARSEOFS, coarse); + + izone->gen[GEN_SAMPLEMODE].flags = GEN_SET; + izone->gen[GEN_SAMPLEMODE].val = FLUID_LOOP_DURING_RELEASE; + fluid_rampreset_updatevoices(preset, GEN_SAMPLEMODE, FLUID_LOOP_DURING_RELEASE); + + /* If the loop points are the whole samples, we are supposed to + copy the frames around in the margins (the start to the end margin and + the end to the start margin), but it works fine without this. Maybe some time + it will be needed (see SAMPLE_LOOP_MARGIN) -- Antoie Schmitt May 2003 */ + + return FLUID_OK; } /* Set a generator on the instrument zone in preset having sample */ static int -fluid_rampreset_izone_set_gen (fluid_rampreset_t* preset, fluid_sample_t* sample, - int gen_type, float value) +fluid_rampreset_izone_set_gen(fluid_rampreset_t *preset, fluid_sample_t *sample, + int gen_type, float value) { - fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample); - if (izone == NULL) - return FLUID_FAILED; + fluid_inst_zone_t *izone = fluid_rampreset_izoneforsample(preset, sample); - izone->gen[gen_type].flags = GEN_SET; - izone->gen[gen_type].val = value; + if(izone == NULL) + { + return FLUID_FAILED; + } - fluid_rampreset_updatevoices(preset, gen_type, value); + izone->gen[gen_type].flags = GEN_SET; + izone->gen[gen_type].val = value; - return FLUID_OK; + fluid_rampreset_updatevoices(preset, gen_type, value); + + return FLUID_OK; } /* Remove the instrument zone from preset having sample */ static int -fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* sample) +fluid_rampreset_remove_izone(fluid_rampreset_t *preset, fluid_sample_t *sample) { - fluid_inst_t* inst; - fluid_inst_zone_t* izone, * prev; - int found = 0; + fluid_inst_t *inst; + fluid_inst_zone_t *izone, * prev; + int found = 0; - if (preset->zone == NULL) return FLUID_FAILED; - inst = fluid_preset_zone_get_inst(preset->zone); - izone = inst->zone; - prev = NULL; - while (izone && !found) { - if (izone->sample == sample) { - if (prev == NULL) { - inst->zone = izone->next; - } else { - prev->next = izone->next; - } - izone->next = NULL; - delete_fluid_inst_zone(izone); - found = 1; - } else { - prev = izone; - izone = izone->next; - } - } - if (!found) - return FLUID_FAILED; + if(preset->zone == NULL) + { + return FLUID_FAILED; + } - // stop all the voices that use this sample, so that - // the sample can be cleared up - { - fluid_list_t *tmp = preset->presetvoices; - while (tmp) { - fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data); - fluid_voice_t *voice = presetvoice->voice; - if (fluid_voice_is_playing(voice) && (fluid_voice_get_id(voice) == presetvoice->voiceID)) { - // still belongs to the preset - if (voice->sample == sample) { - // uses this sample : turn it off. - // our presetvoices struct will be cleaneup at the next update - fluid_voice_off(voice); - } - } - tmp = tmp->next; - } - } - return FLUID_OK; + inst = fluid_preset_zone_get_inst(preset->zone); + izone = inst->zone; + prev = NULL; + + while(izone && !found) + { + if(izone->sample == sample) + { + if(prev == NULL) + { + inst->zone = izone->next; + } + else + { + prev->next = izone->next; + } + + izone->next = NULL; + delete_fluid_inst_zone(izone); + found = 1; + } + else + { + prev = izone; + izone = izone->next; + } + } + + if(!found) + { + return FLUID_FAILED; + } + + // stop all the voices that use this sample, so that + // the sample can be cleared up + { + fluid_list_t *tmp = preset->presetvoices; + + while(tmp) + { + fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data); + fluid_voice_t *voice = presetvoice->voice; + + if(fluid_voice_is_playing(voice) && (fluid_voice_get_id(voice) == presetvoice->voiceID)) + { + // still belongs to the preset + if(voice->sample == sample) + { + // uses this sample : turn it off. + // our presetvoices struct will be cleaneup at the next update + fluid_voice_off(voice); + } + } + + tmp = tmp->next; + } + } + return FLUID_OK; } /* Stores the voice and the its ID in the preset for later update on gen_set */ static int -fluid_rampreset_remembervoice (fluid_rampreset_t* preset, fluid_voice_t* voice) +fluid_rampreset_remembervoice(fluid_rampreset_t *preset, fluid_voice_t *voice) { - fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t); - if (presetvoice == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } + fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t); - presetvoice->voice = voice; - presetvoice->voiceID = fluid_voice_get_id(voice); + if(presetvoice == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } - preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice); - if (preset->presetvoices == NULL) { - FLUID_FREE(presetvoice); - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } - return FLUID_OK; + presetvoice->voice = voice; + presetvoice->voiceID = fluid_voice_get_id(voice); + + preset->presetvoices = fluid_list_append(preset->presetvoices, (void *)presetvoice); + + if(preset->presetvoices == NULL) + { + FLUID_FREE(presetvoice); + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } + + return FLUID_OK; } /* Update a generator in realtime for a preset */ static void -fluid_rampreset_updatevoices (fluid_rampreset_t* preset, int gen_type, float val) +fluid_rampreset_updatevoices(fluid_rampreset_t *preset, int gen_type, float val) { - fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next; + fluid_list_t *tmp = preset->presetvoices, *prev = NULL, *next; - /* Walk the presetvoice to update them if they are still active and ours. - * If their ID has changed or their state is not playing, they are not - * ours, so we forget them. */ - while (tmp) { - fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data); - fluid_voice_t *voice = presetvoice->voice; - if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) { - /* forget it */ - FLUID_FREE(presetvoice); + /* Walk the presetvoice to update them if they are still active and ours. + * If their ID has changed or their state is not playing, they are not + * ours, so we forget them. */ + while(tmp) + { + fluid_rampreset_voice_t *presetvoice = (fluid_rampreset_voice_t *)(tmp->data); + fluid_voice_t *voice = presetvoice->voice; - /* unlink it */ - next = tmp->next; - FLUID_FREE(tmp); - if (prev) { - prev->next = next; - } else { - preset->presetvoices = next; - } - tmp = next; + if(!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) + { + /* forget it */ + FLUID_FREE(presetvoice); - } else { + /* unlink it */ + next = tmp->next; + FLUID_FREE(tmp); - /* update */ - fluid_voice_gen_set(voice, gen_type, val); - fluid_voice_update_param(voice, gen_type); + if(prev) + { + prev->next = next; + } + else + { + preset->presetvoices = next; + } - /* next */ - prev = tmp; - tmp = tmp->next; - } - } + tmp = next; + + } + else + { + + /* update */ + fluid_voice_gen_set(voice, gen_type, val); + fluid_voice_update_param(voice, gen_type); + + /* next */ + prev = tmp; + tmp = tmp->next; + } + } } /* RAM SoundFont preset note on */ static int -fluid_rampreset_noteon (fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, - int key, int vel) +fluid_rampreset_noteon(fluid_rampreset_t *preset, fluid_synth_t *synth, int chan, + int key, int vel) { - fluid_preset_zone_t *preset_zone; - fluid_inst_t* inst; - fluid_inst_zone_t *inst_zone, *global_inst_zone; - fluid_sample_t* sample; - fluid_voice_t* voice; - fluid_mod_t * mod; - fluid_mod_t * mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */ - int mod_list_count; - int i; + fluid_preset_zone_t *preset_zone; + fluid_inst_t *inst; + fluid_inst_zone_t *inst_zone, *global_inst_zone; + fluid_sample_t *sample; + fluid_voice_t *voice; + fluid_mod_t *mod; + fluid_mod_t *mod_list[FLUID_NUM_MOD]; /* list for 'sorting' preset modulators */ + int mod_list_count; + int i; - /* run thru all the zones of this preset */ - preset_zone = preset->zone; - while (preset_zone != NULL) { + /* run thru all the zones of this preset */ + preset_zone = preset->zone; - /* check if the note falls into the key and velocity range of this - preset */ - if (fluid_zone_inside_range(&preset_zone->range, key, vel)) { + while(preset_zone != NULL) + { - inst = fluid_preset_zone_get_inst(preset_zone); - global_inst_zone = fluid_inst_get_global_zone(inst); + /* check if the note falls into the key and velocity range of this + preset */ + if(fluid_zone_inside_range(&preset_zone->range, key, vel)) + { - /* run thru all the zones of this instrument */ - inst_zone = fluid_inst_get_zone(inst); - while (inst_zone != NULL) { - - /* make sure this instrument zone has a valid sample */ - sample = fluid_inst_zone_get_sample(inst_zone); - if ((sample == NULL) || fluid_sample_in_rom(sample)) { - inst_zone = fluid_inst_zone_next(inst_zone); - continue; - } + inst = fluid_preset_zone_get_inst(preset_zone); + global_inst_zone = fluid_inst_get_global_zone(inst); - /* check if the instrument zone doesn't be ignored and the note falls into - the key and velocity range of this instrument zone. - An instrument zone must be ignored when its voice is already running - played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */ - if (fluid_zone_inside_range(&inst_zone->range, key, vel)) { + /* run thru all the zones of this instrument */ + inst_zone = fluid_inst_get_zone(inst); - /* this is a good zone. allocate a new synthesis process and initialize it */ - voice = fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, &inst_zone->range); - if (voice == NULL) { - return FLUID_FAILED; - } + while(inst_zone != NULL) + { - if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) { - return FLUID_FAILED; - } + /* make sure this instrument zone has a valid sample */ + sample = fluid_inst_zone_get_sample(inst_zone); - /* Instrument level, generators */ + if((sample == NULL) || fluid_sample_in_rom(sample)) + { + inst_zone = fluid_inst_zone_next(inst_zone); + continue; + } - for (i = 0; i < GEN_LAST; i++) { + /* check if the instrument zone doesn't be ignored and the note falls into + the key and velocity range of this instrument zone. + An instrument zone must be ignored when its voice is already running + played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */ + if(fluid_zone_inside_range(&inst_zone->range, key, vel)) + { - /* SF 2.01 section 9.4 'bullet' 4: - * - * A generator in a local instrument zone supersedes a - * global instrument zone generator. Both cases supersede - * the default generator -> voice_gen_set */ + /* this is a good zone. allocate a new synthesis process and initialize it */ + voice = fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, &inst_zone->range); - if (inst_zone->gen[i].flags){ - fluid_voice_gen_set(voice, i, inst_zone->gen[i].val); + if(voice == NULL) + { + return FLUID_FAILED; + } - } else if (global_inst_zone != NULL && global_inst_zone->gen[i].flags){ - fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val); + if(fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) + { + return FLUID_FAILED; + } - } else { - /* The generator has not been defined in this instrument. - * Do nothing, leave it at the default. - */ - }; + /* Instrument level, generators */ - }; /* for all generators */ + for(i = 0; i < GEN_LAST; i++) + { - /* global instrument zone, modulators: Put them all into a - * list. */ + /* SF 2.01 section 9.4 'bullet' 4: + * + * A generator in a local instrument zone supersedes a + * global instrument zone generator. Both cases supersede + * the default generator -> voice_gen_set */ - mod_list_count = 0; + if(inst_zone->gen[i].flags) + { + fluid_voice_gen_set(voice, i, inst_zone->gen[i].val); - if (global_inst_zone){ - mod = global_inst_zone->mod; - while (mod){ - mod_list[mod_list_count++] = mod; - mod = mod->next; - }; - }; + } + else if(global_inst_zone != NULL && global_inst_zone->gen[i].flags) + { + fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val); - /* local instrument zone, modulators. - * Replace modulators with the same definition in the list: - * SF 2.01 page 69, 'bullet' 8 - */ - mod = inst_zone->mod; + } + else + { + /* The generator has not been defined in this instrument. + * Do nothing, leave it at the default. + */ + }; - while (mod){ + }; /* for all generators */ - /* 'Identical' modulators will be deleted by setting their - * list entry to NULL. The list length is known, NULL - * entries will be ignored later. SF2.01 section 9.5.1 - * page 69, 'bullet' 3 defines 'identical'. */ + /* global instrument zone, modulators: Put them all into a + * list. */ - for (i = 0; i < mod_list_count; i++){ - if (fluid_mod_test_identity(mod,mod_list[i])){ - mod_list[i] = NULL; - }; - }; + mod_list_count = 0; - /* Finally add the new modulator to to the list. */ - mod_list[mod_list_count++] = mod; - mod = mod->next; - }; + if(global_inst_zone) + { + mod = global_inst_zone->mod; - /* Add instrument modulators (global / local) to the voice. */ - for (i = 0; i < mod_list_count; i++){ + while(mod) + { + mod_list[mod_list_count++] = mod; + mod = mod->next; + }; + }; - mod = mod_list[i]; + /* local instrument zone, modulators. + * Replace modulators with the same definition in the list: + * SF 2.01 page 69, 'bullet' 8 + */ + mod = inst_zone->mod; - if (mod != NULL){ /* disabled modulators CANNOT be skipped. */ + while(mod) + { - /* Instrument modulators -supersede- existing (default) - * modulators. SF 2.01 page 69, 'bullet' 6 */ - fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE); - }; - }; + /* 'Identical' modulators will be deleted by setting their + * list entry to NULL. The list length is known, NULL + * entries will be ignored later. SF2.01 section 9.5.1 + * page 69, 'bullet' 3 defines 'identical'. */ - /* Preset level, generators */ + for(i = 0; i < mod_list_count; i++) + { + if(fluid_mod_test_identity(mod, mod_list[i])) + { + mod_list[i] = NULL; + }; + }; - for (i = 0; i < GEN_LAST; i++) { + /* Finally add the new modulator to to the list. */ + mod_list[mod_list_count++] = mod; - /* SF 2.01 section 8.5 page 58: If some generators are - * encountered at preset level, they should be ignored */ - if ((i != GEN_STARTADDROFS) - && (i != GEN_ENDADDROFS) - && (i != GEN_STARTLOOPADDROFS) - && (i != GEN_ENDLOOPADDROFS) - && (i != GEN_STARTADDRCOARSEOFS) - && (i != GEN_ENDADDRCOARSEOFS) - && (i != GEN_STARTLOOPADDRCOARSEOFS) - && (i != GEN_KEYNUM) - && (i != GEN_VELOCITY) - && (i != GEN_ENDLOOPADDRCOARSEOFS) - && (i != GEN_SAMPLEMODE) - && (i != GEN_EXCLUSIVECLASS) - && (i != GEN_OVERRIDEROOTKEY)) { + mod = mod->next; + }; - /* SF 2.01 section 9.4 'bullet' 9: A generator in a - * local preset zone supersedes a global preset zone - * generator. The effect is -added- to the destination - * summing node -> voice_gen_incr */ + /* Add instrument modulators (global / local) to the voice. */ + for(i = 0; i < mod_list_count; i++) + { - if (preset_zone->gen[i].flags){ - fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val); - } else { - /* The generator has not been defined in this preset - * Do nothing, leave it unchanged. - */ - }; - }; /* if available at preset level */ - }; /* for all generators */ + mod = mod_list[i]; + + if(mod != NULL) /* disabled modulators CANNOT be skipped. */ + { + + /* Instrument modulators -supersede- existing (default) + * modulators. SF 2.01 page 69, 'bullet' 6 */ + fluid_voice_add_mod(voice, mod, FLUID_VOICE_OVERWRITE); + }; + }; + + /* Preset level, generators */ + + for(i = 0; i < GEN_LAST; i++) + { + + /* SF 2.01 section 8.5 page 58: If some generators are + * encountered at preset level, they should be ignored */ + if((i != GEN_STARTADDROFS) + && (i != GEN_ENDADDROFS) + && (i != GEN_STARTLOOPADDROFS) + && (i != GEN_ENDLOOPADDROFS) + && (i != GEN_STARTADDRCOARSEOFS) + && (i != GEN_ENDADDRCOARSEOFS) + && (i != GEN_STARTLOOPADDRCOARSEOFS) + && (i != GEN_KEYNUM) + && (i != GEN_VELOCITY) + && (i != GEN_ENDLOOPADDRCOARSEOFS) + && (i != GEN_SAMPLEMODE) + && (i != GEN_EXCLUSIVECLASS) + && (i != GEN_OVERRIDEROOTKEY)) + { + + /* SF 2.01 section 9.4 'bullet' 9: A generator in a + * local preset zone supersedes a global preset zone + * generator. The effect is -added- to the destination + * summing node -> voice_gen_incr */ + + if(preset_zone->gen[i].flags) + { + fluid_voice_gen_incr(voice, i, preset_zone->gen[i].val); + } + else + { + /* The generator has not been defined in this preset + * Do nothing, leave it unchanged. + */ + }; + }; /* if available at preset level */ + }; /* for all generators */ - /* Global preset zone, modulators: put them all into a - * list. */ - mod_list_count = 0; + /* Global preset zone, modulators: put them all into a + * list. */ + mod_list_count = 0; - /* Process the modulators of the local preset zone. Kick - * out all identical modulators from the global preset zone - * (SF 2.01 page 69, second-last bullet) */ + /* Process the modulators of the local preset zone. Kick + * out all identical modulators from the global preset zone + * (SF 2.01 page 69, second-last bullet) */ - mod = preset_zone->mod; - while (mod){ - for (i = 0; i < mod_list_count; i++){ - if (fluid_mod_test_identity(mod,mod_list[i])){ - mod_list[i] = NULL; - }; - }; + mod = preset_zone->mod; - /* Finally add the new modulator to the list. */ - mod_list[mod_list_count++] = mod; - mod = mod->next; - }; + while(mod) + { + for(i = 0; i < mod_list_count; i++) + { + if(fluid_mod_test_identity(mod, mod_list[i])) + { + mod_list[i] = NULL; + }; + }; - /* Add preset modulators (global / local) to the voice. */ - for (i = 0; i < mod_list_count; i++){ - mod = mod_list[i]; - if ((mod != NULL) && (mod->amount != 0)) { /* disabled modulators can be skipped. */ + /* Finally add the new modulator to the list. */ + mod_list[mod_list_count++] = mod; - /* Preset modulators -add- to existing instrument / - * default modulators. SF2.01 page 70 first bullet on - * page */ - fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD); - }; - }; + mod = mod->next; + }; - /* add the synthesis process to the synthesis loop. */ - fluid_synth_start_voice(synth, voice); + /* Add preset modulators (global / local) to the voice. */ + for(i = 0; i < mod_list_count; i++) + { + mod = mod_list[i]; - /* Store the ID of the first voice that was created by this noteon event. - * Exclusive class may only terminate older voices. - * That avoids killing voices, which have just been created. - * (a noteon event can create several voice processes with the same exclusive - * class - for example when using stereo samples) - */ - } + if((mod != NULL) && (mod->amount != 0)) /* disabled modulators can be skipped. */ + { - inst_zone = fluid_inst_zone_next(inst_zone); - } + /* Preset modulators -add- to existing instrument / + * default modulators. SF2.01 page 70 first bullet on + * page */ + fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD); + }; + }; + + /* add the synthesis process to the synthesis loop. */ + fluid_synth_start_voice(synth, voice); + + /* Store the ID of the first voice that was created by this noteon event. + * Exclusive class may only terminate older voices. + * That avoids killing voices, which have just been created. + * (a noteon event can create several voice processes with the same exclusive + * class - for example when using stereo samples) + */ + } + + inst_zone = fluid_inst_zone_next(inst_zone); + } + } + + preset_zone = fluid_preset_zone_next(preset_zone); } - preset_zone = fluid_preset_zone_next(preset_zone); - } - return FLUID_OK; + return FLUID_OK; } diff --git a/src/sfloader/fluid_ramsfont.h b/src/sfloader/fluid_ramsfont.h index 58f77851..f83713e8 100644 --- a/src/sfloader/fluid_ramsfont.h +++ b/src/sfloader/fluid_ramsfont.h @@ -35,17 +35,17 @@ extern "C" { #endif - /* - * fluid_ramsfont_t - */ +/* +* fluid_ramsfont_t +*/ struct _fluid_ramsfont_t { - char name[21]; /* the name of the soundfont */ - fluid_sfont_t* sfont; /* parent sfont */ - fluid_list_t* sample; /* the samples in this soundfont */ - fluid_list_t* preset; /* the presets of this soundfont */ + char name[21]; /* the name of the soundfont */ + fluid_sfont_t *sfont; /* parent sfont */ + fluid_list_t *sample; /* the samples in this soundfont */ + fluid_list_t *preset; /* the presets of this soundfont */ - fluid_list_t* preset_iter_cur; /* the current preset in the iteration */ + fluid_list_t *preset_iter_cur; /* the current preset in the iteration */ }; /* @@ -53,14 +53,14 @@ struct _fluid_ramsfont_t */ struct _fluid_rampreset_t { - fluid_rampreset_t* next; - fluid_ramsfont_t* sfont; /* the soundfont this preset belongs to */ - char name[21]; /* the name of the preset */ - unsigned int bank; /* the bank number */ - unsigned int num; /* the preset number */ - fluid_preset_zone_t* global_zone; /* the global zone of the preset */ - fluid_preset_zone_t* zone; /* the chained list of preset zones */ - fluid_list_t *presetvoices; /* chained list of used voices */ + fluid_rampreset_t *next; + fluid_ramsfont_t *sfont; /* the soundfont this preset belongs to */ + char name[21]; /* the name of the preset */ + unsigned int bank; /* the bank number */ + unsigned int num; /* the preset number */ + fluid_preset_zone_t *global_zone; /* the global zone of the preset */ + fluid_preset_zone_t *zone; /* the chained list of preset zones */ + fluid_list_t *presetvoices; /* chained list of used voices */ }; diff --git a/src/sfloader/fluid_samplecache.c b/src/sfloader/fluid_samplecache.c index 001e4a96..773e19fe 100644 --- a/src/sfloader/fluid_samplecache.c +++ b/src/sfloader/fluid_samplecache.c @@ -79,10 +79,12 @@ int fluid_samplecache_load(SFData *sf, fluid_mutex_lock(samplecache_mutex); entry = get_samplecache_entry(sf, sample_start, sample_end, sample_type); - if (entry == NULL) + + if(entry == NULL) { entry = new_samplecache_entry(sf, sample_start, sample_end, sample_type); - if (entry == NULL) + + if(entry == NULL) { ret = -1; goto unlock_exit; @@ -91,13 +93,13 @@ int fluid_samplecache_load(SFData *sf, samplecache_list = fluid_list_prepend(samplecache_list, entry); } - if (try_mlock && !entry->mlocked) + if(try_mlock && !entry->mlocked) { /* Lock the memory to disable paging. It's okay if this fails. It * probably means that the user doesn't have the required permission. */ - if (fluid_mlock(entry->sample_data, entry->sample_count * sizeof(short)) == 0) + if(fluid_mlock(entry->sample_data, entry->sample_count * sizeof(short)) == 0) { - if (entry->sample_data24 != NULL) + if(entry->sample_data24 != NULL) { entry->mlocked = (fluid_mlock(entry->sample_data24, entry->sample_count) == 0); } @@ -106,7 +108,7 @@ int fluid_samplecache_load(SFData *sf, entry->mlocked = TRUE; } - if (!entry->mlocked) + if(!entry->mlocked) { fluid_munlock(entry->sample_data, entry->sample_count * sizeof(short)); FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible."); @@ -133,20 +135,22 @@ int fluid_samplecache_unload(const short *sample_data) fluid_mutex_lock(samplecache_mutex); entry_list = samplecache_list; - while (entry_list) + + while(entry_list) { entry = (fluid_samplecache_entry_t *)fluid_list_get(entry_list); - if (sample_data == entry->sample_data) + if(sample_data == entry->sample_data) { entry->num_references--; - if (entry->num_references == 0) + if(entry->num_references == 0) { - if (entry->mlocked) + if(entry->mlocked) { fluid_munlock(entry->sample_data, entry->sample_count * sizeof(short)); - if (entry->sample_data24 != NULL) + + if(entry->sample_data24 != NULL) { fluid_munlock(entry->sample_data24, entry->sample_count); } @@ -174,28 +178,31 @@ unlock_exit: /* Private functions */ static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf, - unsigned int sample_start, - unsigned int sample_end, - int sample_type) + unsigned int sample_start, + unsigned int sample_end, + int sample_type) { fluid_samplecache_entry_t *entry; entry = FLUID_NEW(fluid_samplecache_entry_t); - if (entry == NULL) + + if(entry == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(entry, 0, sizeof(*entry)); entry->filename = FLUID_STRDUP(sf->fname); - if (entry->filename == NULL) + + if(entry->filename == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_exit; } - if (fluid_get_file_modification_time(entry->filename, &entry->modification_time) == FLUID_FAILED) + if(fluid_get_file_modification_time(entry->filename, &entry->modification_time) == FLUID_FAILED) { FLUID_LOG(FLUID_WARN, "Unable to read modificaton time of soundfont file."); entry->modification_time = 0; @@ -210,8 +217,9 @@ static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf, entry->sample_type = sample_type; entry->sample_count = fluid_sffile_read_sample_data(sf, sample_start, sample_end, sample_type, - &entry->sample_data, &entry->sample_data24); - if (entry->sample_count < 0) + &entry->sample_data, &entry->sample_data24); + + if(entry->sample_count < 0) { goto error_exit; } @@ -234,34 +242,35 @@ static void delete_samplecache_entry(fluid_samplecache_entry_t *entry) } static fluid_samplecache_entry_t *get_samplecache_entry(SFData *sf, - unsigned int sample_start, - unsigned int sample_end, - int sample_type) + unsigned int sample_start, + unsigned int sample_end, + int sample_type) { time_t mtime; fluid_list_t *entry_list; fluid_samplecache_entry_t *entry; - if (fluid_get_file_modification_time(sf->fname, &mtime) == FLUID_FAILED) + if(fluid_get_file_modification_time(sf->fname, &mtime) == FLUID_FAILED) { FLUID_LOG(FLUID_WARN, "Unable to read modificaton time of soundfont file."); mtime = 0; } entry_list = samplecache_list; - while (entry_list) + + while(entry_list) { entry = (fluid_samplecache_entry_t *)fluid_list_get(entry_list); - if ((FLUID_STRCMP(sf->fname, entry->filename) == 0) && - (mtime == entry->modification_time) && - (sf->samplepos == entry->sf_samplepos) && - (sf->samplesize == entry->sf_samplesize) && - (sf->sample24pos == entry->sf_sample24pos) && - (sf->sample24size == entry->sf_sample24size) && - (sample_start == entry->sample_start) && - (sample_end == entry->sample_end) && - (sample_type == entry->sample_type)) + if((FLUID_STRCMP(sf->fname, entry->filename) == 0) && + (mtime == entry->modification_time) && + (sf->samplepos == entry->sf_samplepos) && + (sf->samplesize == entry->sf_samplesize) && + (sf->sample24pos == entry->sf_sample24pos) && + (sf->sample24size == entry->sf_sample24size) && + (sample_start == entry->sample_start) && + (sample_end == entry->sample_end) && + (sample_type == entry->sample_type)) { return entry; } @@ -276,7 +285,7 @@ static int fluid_get_file_modification_time(char *filename, time_t *modification { fluid_stat_buf_t buf; - if (fluid_stat(filename, &buf)) + if(fluid_stat(filename, &buf)) { return FLUID_FAILED; } diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 230ffeaa..a98d37f3 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -78,11 +78,13 @@ enum }; static const char idlist[] = {"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD" - "ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24"}; + "ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24" + }; /* generator types */ -typedef enum { +typedef enum +{ Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddrOfs, @@ -150,7 +152,8 @@ typedef enum { #define GenArrSize sizeof(SFGenAmount) * Gen_Count /* gen array size */ -static const unsigned short invalid_inst_gen[] = { +static const unsigned short invalid_inst_gen[] = +{ Gen_Unused1, Gen_Unused2, Gen_Unused3, @@ -161,7 +164,8 @@ static const unsigned short invalid_inst_gen[] = { 0 }; -static const unsigned short invalid_preset_gen[] = { +static const unsigned short invalid_preset_gen[] = +{ Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddrOfs, @@ -308,48 +312,52 @@ SFData *fluid_sffile_open(const char *fname, const fluid_file_callbacks_t *fcbs) SFData *sf; int fsize = 0; - if (!(sf = FLUID_NEW(SFData))) + if(!(sf = FLUID_NEW(SFData))) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(sf, 0, sizeof(SFData)); sf->fcbs = fcbs; - if ((sf->sffd = fcbs->fopen(fname)) == NULL) + if((sf->sffd = fcbs->fopen(fname)) == NULL) { FLUID_LOG(FLUID_ERR, "Unable to open file '%s'", fname); goto error_exit; } sf->fname = FLUID_STRDUP(fname); - if (sf->fname == NULL) + + if(sf->fname == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_exit; } /* get size of file by seeking to end */ - if (fcbs->fseek(sf->sffd, 0L, SEEK_END) == FLUID_FAILED) + if(fcbs->fseek(sf->sffd, 0L, SEEK_END) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Seek to end of file failed"); goto error_exit; } - if ((fsize = fcbs->ftell(sf->sffd)) == FLUID_FAILED) + + if((fsize = fcbs->ftell(sf->sffd)) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Get end of file position failed"); goto error_exit; } + sf->filesize = fsize; - if (fcbs->fseek(sf->sffd, 0, SEEK_SET) == FLUID_FAILED) + if(fcbs->fseek(sf->sffd, 0, SEEK_SET) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Rewind to start of file failed"); goto error_exit; } - if (!load_header(sf)) + if(!load_header(sf)) { goto error_exit; } @@ -368,7 +376,7 @@ error_exit: */ int fluid_sffile_parse_presets(SFData *sf) { - if (!load_body(sf)) + if(!load_body(sf)) { return FLUID_FAILED; } @@ -392,11 +400,11 @@ int fluid_sffile_parse_presets(SFData *sf) * @return The number of sample words in returned buffers or -1 on failure */ int fluid_sffile_read_sample_data(SFData *sf, unsigned int sample_start, unsigned int sample_end, - int sample_type, short **data, char **data24) + int sample_type, short **data, char **data24) { int num_samples; - if (sample_type & FLUID_SAMPLETYPE_OGG_VORBIS) + if(sample_type & FLUID_SAMPLETYPE_OGG_VORBIS) { num_samples = fluid_sffile_read_vorbis(sf, sample_start, sample_end, data); } @@ -420,7 +428,7 @@ void fluid_sffile_close(SFData *sf) SFPreset *preset; SFInst *inst; - if (sf->sffd) + if(sf->sffd) { sf->fcbs->fclose(sf->sffd); } @@ -428,37 +436,45 @@ void fluid_sffile_close(SFData *sf) FLUID_FREE(sf->fname); entry = sf->info; + while(entry) { FLUID_FREE(fluid_list_get(entry)); entry = fluid_list_next(entry); } + delete_fluid_list(sf->info); entry = sf->preset; + while(entry) { preset = (SFPreset *)fluid_list_get(entry); delete_preset(preset); entry = fluid_list_next(entry); } + delete_fluid_list(sf->preset); entry = sf->inst; + while(entry) { inst = (SFInst *)fluid_list_get(entry); delete_inst(inst); entry = fluid_list_next(entry); } + delete_fluid_list(sf->inst); entry = sf->sample; + while(entry) { FLUID_FREE(fluid_list_get(entry)); entry = fluid_list_next(entry); } + delete_fluid_list(sf->sample); FLUID_FREE(sf); @@ -476,9 +492,14 @@ static int chunkid(unsigned int id) unsigned int *p; p = (unsigned int *)&idlist; - for (i = 0; i < sizeof(idlist) / sizeof(int); i++, p += 1) - if (*p == id) + + for(i = 0; i < sizeof(idlist) / sizeof(int); i++, p += 1) + { + if(*p == id) + { return (i + 1); + } + } return UNKN_ID; } @@ -488,51 +509,70 @@ static int load_header(SFData *sf) SFChunk chunk; READCHUNK(sf, &chunk); /* load RIFF chunk */ - if (chunkid(chunk.id) != RIFF_ID) - { /* error if not RIFF */ + + if(chunkid(chunk.id) != RIFF_ID) + { + /* error if not RIFF */ FLUID_LOG(FLUID_ERR, "Not a RIFF file"); return FALSE; } READID(sf, &chunk.id); /* load file ID */ - if (chunkid(chunk.id) != SFBK_ID) - { /* error if not SFBK_ID */ + + if(chunkid(chunk.id) != SFBK_ID) + { + /* error if not SFBK_ID */ FLUID_LOG(FLUID_ERR, "Not a SoundFont file"); return FALSE; } - if (chunk.size != sf->filesize - 8) + if(chunk.size != sf->filesize - 8) { FLUID_LOG(FLUID_ERR, "SoundFont file size mismatch"); return FALSE; } /* Process INFO block */ - if (!read_listchunk(sf, &chunk)) + if(!read_listchunk(sf, &chunk)) + { return FALSE; - if (chunkid(chunk.id) != INFO_ID) + } + + if(chunkid(chunk.id) != INFO_ID) { FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting INFO chunk"); return FALSE; } - if (!process_info(sf, chunk.size)) + + if(!process_info(sf, chunk.size)) + { return FALSE; + } /* Process sample chunk */ - if (!read_listchunk(sf, &chunk)) + if(!read_listchunk(sf, &chunk)) + { return FALSE; - if (chunkid(chunk.id) != SDTA_ID) + } + + if(chunkid(chunk.id) != SDTA_ID) { FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting SAMPLE chunk"); return FALSE; } - if (!process_sdta(sf, chunk.size)) + + if(!process_sdta(sf, chunk.size)) + { return FALSE; + } /* process HYDRA chunk */ - if (!read_listchunk(sf, &chunk)) + if(!read_listchunk(sf, &chunk)) + { return FALSE; - if (chunkid(chunk.id) != PDTA_ID) + } + + if(chunkid(chunk.id) != PDTA_ID) { FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting HYDRA chunk"); return FALSE; @@ -546,20 +586,26 @@ static int load_header(SFData *sf) static int load_body(SFData *sf) { - if (sf->fcbs->fseek(sf->sffd, sf->hydrapos, SEEK_SET) == FLUID_FAILED) + if(sf->fcbs->fseek(sf->sffd, sf->hydrapos, SEEK_SET) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Failed to seek to HYDRA position"); return FALSE; } - if (!process_pdta(sf, sf->hydrasize)) + if(!process_pdta(sf, sf->hydrasize)) + { return FALSE; + } - if (!fixup_pgen(sf)) + if(!fixup_pgen(sf)) + { return FALSE; + } - if (!fixup_igen(sf)) + if(!fixup_igen(sf)) + { return FALSE; + } /* sort preset list by bank, preset # */ sf->preset = fluid_list_sort(sf->preset, (fluid_compare_func_t)preset_compare_func); @@ -570,11 +616,13 @@ static int load_body(SFData *sf) static int read_listchunk(SFData *sf, SFChunk *chunk) { READCHUNK(sf, chunk); /* read list chunk */ - if (chunkid(chunk->id) != LIST_ID) /* error if ! list chunk */ + + if(chunkid(chunk->id) != LIST_ID) /* error if ! list chunk */ { FLUID_LOG(FLUID_ERR, "Invalid chunk id in level 0 parse"); return FALSE; } + READID(sf, &chunk->id); /* read id string */ chunk->size -= 4; return TRUE; @@ -587,16 +635,17 @@ static int process_info(SFData *sf, int size) char *item; unsigned short ver; - while (size > 0) + while(size > 0) { READCHUNK(sf, &chunk); size -= 8; id = chunkid(chunk.id); - if (id == IFIL_ID) - { /* sound font version chunk? */ - if (chunk.size != 4) + if(id == IFIL_ID) + { + /* sound font version chunk? */ + if(chunk.size != 4) { FLUID_LOG(FLUID_ERR, "Sound font version info chunk has invalid size"); return FALSE; @@ -607,36 +656,37 @@ static int process_info(SFData *sf, int size) READW(sf, ver); sf->version.minor = ver; - if (sf->version.major < 2) + if(sf->version.major < 2) { FLUID_LOG(FLUID_ERR, "Sound font version is %d.%d which is not" - " supported, convert to version 2.0x", + " supported, convert to version 2.0x", sf->version.major, sf->version.minor); return FALSE; } - if (sf->version.major == 3) + if(sf->version.major == 3) { #if !LIBSNDFILE_SUPPORT FLUID_LOG(FLUID_WARN, "Sound font version is %d.%d but fluidsynth was compiled without" - " support for (v3.x)", + " support for (v3.x)", sf->version.major, sf->version.minor); return FALSE; #endif } - else if (sf->version.major > 2) + else if(sf->version.major > 2) { FLUID_LOG(FLUID_WARN, "Sound font version is %d.%d which is newer than" - " what this version of fluidsynth was designed for (v2.0x)", + " what this version of fluidsynth was designed for (v2.0x)", sf->version.major, sf->version.minor); return FALSE; } } - else if (id == IVER_ID) - { /* ROM version chunk? */ - if (chunk.size != 4) + else if(id == IVER_ID) + { + /* ROM version chunk? */ + if(chunk.size != 4) { FLUID_LOG(FLUID_ERR, "ROM version info chunk has invalid size"); return FALSE; @@ -647,9 +697,9 @@ static int process_info(SFData *sf, int size) READW(sf, ver); sf->romver.minor = ver; } - else if (id != UNKN_ID) + else if(id != UNKN_ID) { - if ((id != ICMT_ID && chunk.size > 256) || (chunk.size > 65536) || (chunk.size % 2)) + if((id != ICMT_ID && chunk.size > 256) || (chunk.size > 65536) || (chunk.size % 2)) { FLUID_LOG(FLUID_ERR, "INFO sub chunk %.4s has invalid chunk size of %d bytes", &chunk.id, chunk.size); @@ -657,7 +707,7 @@ static int process_info(SFData *sf, int size) } /* alloc for chunk id and da chunk */ - if (!(item = FLUID_MALLOC(chunk.size + 1))) + if(!(item = FLUID_MALLOC(chunk.size + 1))) { FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; @@ -667,8 +717,11 @@ static int process_info(SFData *sf, int size) sf->info = fluid_list_append(sf->info, item); *(unsigned char *)item = id; - if (sf->fcbs->fread(&item[1], chunk.size, sf->sffd) == FLUID_FAILED) + + if(sf->fcbs->fread(&item[1], chunk.size, sf->sffd) == FLUID_FAILED) + { return FALSE; + } /* force terminate info item (don't forget uint8 info ID) */ *(item + chunk.size) = '\0'; @@ -678,10 +731,11 @@ static int process_info(SFData *sf, int size) FLUID_LOG(FLUID_ERR, "Invalid chunk id in INFO chunk"); return FALSE; } + size -= chunk.size; } - if (size < 0) + if(size < 0) { FLUID_LOG(FLUID_ERR, "INFO chunk size mismatch"); return FALSE; @@ -694,14 +748,16 @@ static int process_sdta(SFData *sf, unsigned int size) { SFChunk chunk; - if (size == 0) - return TRUE; /* no sample data? */ + if(size == 0) + { + return TRUE; /* no sample data? */ + } /* read sub chunk */ READCHUNK(sf, &chunk); size -= 8; - if (chunkid(chunk.id) != SMPL_ID) + if(chunkid(chunk.id) != SMPL_ID) { FLUID_LOG(FLUID_ERR, "Expected SMPL chunk found invalid id instead"); return FALSE; @@ -710,7 +766,7 @@ static int process_sdta(SFData *sf, unsigned int size) /* SDTA chunk may also contain sm24 chunk for 24 bit samples * (not yet supported), only an error if SMPL chunk size is * greater than SDTA. */ - if (chunk.size > size) + if(chunk.size > size) { FLUID_LOG(FLUID_ERR, "SDTA chunk size mismatch"); return FALSE; @@ -725,21 +781,22 @@ static int process_sdta(SFData *sf, unsigned int size) FSKIP(sf, chunk.size); size -= chunk.size; - if (sf->version.major >= 2 && sf->version.minor >= 4) + if(sf->version.major >= 2 && sf->version.minor >= 4) { /* any chance to find another chunk here? */ - if (size > 8) + if(size > 8) { /* read sub chunk */ READCHUNK(sf, &chunk); size -= 8; - if (chunkid(chunk.id) == SM24_ID) + if(chunkid(chunk.id) == SM24_ID) { int sm24size, sdtahalfsize; FLUID_LOG(FLUID_DBG, "Found SM24 chunk"); - if (chunk.size > size) + + if(chunk.size > size) { FLUID_LOG(FLUID_WARN, "SM24 exeeds SDTA chunk, ignoring SM24"); goto ret; // no error @@ -750,10 +807,10 @@ static int process_sdta(SFData *sf, unsigned int size) sdtahalfsize += sdtahalfsize % 2; sm24size = chunk.size; - if (sdtahalfsize != sm24size) + if(sdtahalfsize != sm24size) { FLUID_LOG(FLUID_WARN, "SM24 not equal to half the size of SMPL chunk (0x%X != " - "0x%X), ignoring SM24", + "0x%X), ignoring SM24", sm24size, sdtahalfsize); goto ret; // no error } @@ -781,22 +838,24 @@ static int pdtahelper(SFData *sf, unsigned int expid, unsigned int reclen, SFChu READCHUNK(sf, chunk); *size -= 8; - if ((id = chunkid(chunk->id)) != expid) + if((id = chunkid(chunk->id)) != expid) { FLUID_LOG(FLUID_ERR, "Expected PDTA sub-chunk '%.4s' found invalid id instead", expstr); return FALSE; } - if (chunk->size % reclen) /* valid chunk size? */ + if(chunk->size % reclen) /* valid chunk size? */ { FLUID_LOG(FLUID_ERR, "'%.4s' chunk size is not a multiple of %d bytes", expstr, reclen); return FALSE; } - if ((*size -= chunk->size) < 0) + + if((*size -= chunk->size) < 0) { FLUID_LOG(FLUID_ERR, "'%.4s' chunk size exceeds remaining PDTA chunk size", expstr); return FALSE; } + return TRUE; } @@ -804,50 +863,95 @@ static int process_pdta(SFData *sf, int size) { SFChunk chunk; - if (!pdtahelper(sf, PHDR_ID, SF_PHDR_SIZE, &chunk, &size)) - return FALSE; - if (!load_phdr(sf, chunk.size)) + if(!pdtahelper(sf, PHDR_ID, SF_PHDR_SIZE, &chunk, &size)) + { return FALSE; + } - if (!pdtahelper(sf, PBAG_ID, SF_BAG_SIZE, &chunk, &size)) - return FALSE; - if (!load_pbag(sf, chunk.size)) + if(!load_phdr(sf, chunk.size)) + { return FALSE; + } - if (!pdtahelper(sf, PMOD_ID, SF_MOD_SIZE, &chunk, &size)) - return FALSE; - if (!load_pmod(sf, chunk.size)) + if(!pdtahelper(sf, PBAG_ID, SF_BAG_SIZE, &chunk, &size)) + { return FALSE; + } - if (!pdtahelper(sf, PGEN_ID, SF_GEN_SIZE, &chunk, &size)) - return FALSE; - if (!load_pgen(sf, chunk.size)) + if(!load_pbag(sf, chunk.size)) + { return FALSE; + } - if (!pdtahelper(sf, IHDR_ID, SF_IHDR_SIZE, &chunk, &size)) - return FALSE; - if (!load_ihdr(sf, chunk.size)) + if(!pdtahelper(sf, PMOD_ID, SF_MOD_SIZE, &chunk, &size)) + { return FALSE; + } - if (!pdtahelper(sf, IBAG_ID, SF_BAG_SIZE, &chunk, &size)) - return FALSE; - if (!load_ibag(sf, chunk.size)) + if(!load_pmod(sf, chunk.size)) + { return FALSE; + } - if (!pdtahelper(sf, IMOD_ID, SF_MOD_SIZE, &chunk, &size)) - return FALSE; - if (!load_imod(sf, chunk.size)) + if(!pdtahelper(sf, PGEN_ID, SF_GEN_SIZE, &chunk, &size)) + { return FALSE; + } - if (!pdtahelper(sf, IGEN_ID, SF_GEN_SIZE, &chunk, &size)) - return FALSE; - if (!load_igen(sf, chunk.size)) + if(!load_pgen(sf, chunk.size)) + { return FALSE; + } - if (!pdtahelper(sf, SHDR_ID, SF_SHDR_SIZE, &chunk, &size)) + if(!pdtahelper(sf, IHDR_ID, SF_IHDR_SIZE, &chunk, &size)) + { return FALSE; - if (!load_shdr(sf, chunk.size)) + } + + if(!load_ihdr(sf, chunk.size)) + { return FALSE; + } + + if(!pdtahelper(sf, IBAG_ID, SF_BAG_SIZE, &chunk, &size)) + { + return FALSE; + } + + if(!load_ibag(sf, chunk.size)) + { + return FALSE; + } + + if(!pdtahelper(sf, IMOD_ID, SF_MOD_SIZE, &chunk, &size)) + { + return FALSE; + } + + if(!load_imod(sf, chunk.size)) + { + return FALSE; + } + + if(!pdtahelper(sf, IGEN_ID, SF_GEN_SIZE, &chunk, &size)) + { + return FALSE; + } + + if(!load_igen(sf, chunk.size)) + { + return FALSE; + } + + if(!pdtahelper(sf, SHDR_ID, SF_SHDR_SIZE, &chunk, &size)) + { + return FALSE; + } + + if(!load_shdr(sf, chunk.size)) + { + return FALSE; + } return TRUE; } @@ -859,22 +963,25 @@ static int load_phdr(SFData *sf, int size) SFPreset *preset, *prev_preset = NULL; unsigned short pbag_idx, prev_pbag_idx = 0; - if (size % SF_PHDR_SIZE || size == 0) + if(size % SF_PHDR_SIZE || size == 0) { FLUID_LOG(FLUID_ERR, "Preset header chunk size is invalid"); return FALSE; } i = size / SF_PHDR_SIZE - 1; - if (i == 0) - { /* at least one preset + term record */ + + if(i == 0) + { + /* at least one preset + term record */ FLUID_LOG(FLUID_WARN, "File contains no presets"); FSKIP(sf, SF_PHDR_SIZE); return TRUE; } - for (; i > 0; i--) - { /* load all preset headers */ + for(; i > 0; i--) + { + /* load all preset headers */ preset = FLUID_NEW(SFPreset); sf->preset = fluid_list_append(sf->preset, preset); preset->zone = NULL; /* In case of failure, fluid_sffile_close can cleanup */ @@ -886,21 +993,27 @@ static int load_phdr(SFData *sf, int size) READD(sf, preset->genre); READD(sf, preset->morph); - if (prev_preset) - { /* not first preset? */ - if (pbag_idx < prev_pbag_idx) + if(prev_preset) + { + /* not first preset? */ + if(pbag_idx < prev_pbag_idx) { FLUID_LOG(FLUID_ERR, "Preset header indices not monotonic"); return FALSE; } + i2 = pbag_idx - prev_pbag_idx; - while (i2--) + + while(i2--) { prev_preset->zone = fluid_list_prepend(prev_preset->zone, NULL); } } - else if (pbag_idx > 0) /* 1st preset, warn if ofs >0 */ + else if(pbag_idx > 0) /* 1st preset, warn if ofs >0 */ + { FLUID_LOG(FLUID_WARN, "%d preset zones not referenced, discarding", pbag_idx); + } + prev_preset = preset; /* update preset ptr */ prev_pbag_idx = pbag_idx; } @@ -909,13 +1022,15 @@ static int load_phdr(SFData *sf, int size) READW(sf, pbag_idx); /* Read terminal generator index */ FSKIP(sf, 12); - if (pbag_idx < prev_pbag_idx) + if(pbag_idx < prev_pbag_idx) { FLUID_LOG(FLUID_ERR, "Preset header indices not monotonic"); return FALSE; } + i2 = pbag_idx - prev_pbag_idx; - while (i2--) + + while(i2--) { prev_preset->zone = fluid_list_prepend(prev_preset->zone, NULL); } @@ -932,23 +1047,28 @@ static int load_pbag(SFData *sf, int size) unsigned short pgenndx = 0, pmodndx = 0; unsigned short i; - if (size % SF_BAG_SIZE || size == 0) /* size is multiple of SF_BAG_SIZE? */ + if(size % SF_BAG_SIZE || size == 0) /* size is multiple of SF_BAG_SIZE? */ { FLUID_LOG(FLUID_ERR, "Preset bag chunk size is invalid"); return FALSE; } p = sf->preset; - while (p) - { /* traverse through presets */ + + while(p) + { + /* traverse through presets */ p2 = ((SFPreset *)(p->data))->zone; - while (p2) - { /* traverse preset's zones */ - if ((size -= SF_BAG_SIZE) < 0) + + while(p2) + { + /* traverse preset's zones */ + if((size -= SF_BAG_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Preset bag chunk size mismatch"); return FALSE; } + z = FLUID_NEW(SFZone); p2->data = z; z->gen = NULL; /* Init gen and mod before possible failure, */ @@ -957,35 +1077,48 @@ static int load_pbag(SFData *sf, int size) READW(sf, modndx); z->instsamp = NULL; - if (pz) - { /* if not first zone */ - if (genndx < pgenndx) + if(pz) + { + /* if not first zone */ + if(genndx < pgenndx) { FLUID_LOG(FLUID_ERR, "Preset bag generator indices not monotonic"); return FALSE; } - if (modndx < pmodndx) + + if(modndx < pmodndx) { FLUID_LOG(FLUID_ERR, "Preset bag modulator indices not monotonic"); return FALSE; } + i = genndx - pgenndx; - while (i--) + + while(i--) + { pz->gen = fluid_list_prepend(pz->gen, NULL); + } + i = modndx - pmodndx; - while (i--) + + while(i--) + { pz->mod = fluid_list_prepend(pz->mod, NULL); + } } + pz = z; /* update previous zone ptr */ pgenndx = genndx; /* update previous zone gen index */ pmodndx = modndx; /* update previous zone mod index */ p2 = fluid_list_next(p2); } + p = fluid_list_next(p); } size -= SF_BAG_SIZE; - if (size != 0) + + if(size != 0) { FLUID_LOG(FLUID_ERR, "Preset bag chunk size mismatch"); return FALSE; @@ -994,31 +1127,46 @@ static int load_pbag(SFData *sf, int size) READW(sf, genndx); READW(sf, modndx); - if (!pz) + if(!pz) { - if (genndx > 0) + if(genndx > 0) + { FLUID_LOG(FLUID_WARN, "No preset generators and terminal index not 0"); - if (modndx > 0) + } + + if(modndx > 0) + { FLUID_LOG(FLUID_WARN, "No preset modulators and terminal index not 0"); + } + return TRUE; } - if (genndx < pgenndx) + if(genndx < pgenndx) { FLUID_LOG(FLUID_ERR, "Preset bag generator indices not monotonic"); return FALSE; } - if (modndx < pmodndx) + + if(modndx < pmodndx) { FLUID_LOG(FLUID_ERR, "Preset bag modulator indices not monotonic"); return FALSE; } + i = genndx - pgenndx; - while (i--) + + while(i--) + { pz->gen = fluid_list_prepend(pz->gen, NULL); + } + i = modndx - pmodndx; - while (i--) + + while(i--) + { pz->mod = fluid_list_prepend(pz->mod, NULL); + } return TRUE; } @@ -1030,19 +1178,26 @@ static int load_pmod(SFData *sf, int size) SFMod *m; p = sf->preset; - while (p) - { /* traverse through all presets */ + + while(p) + { + /* traverse through all presets */ p2 = ((SFPreset *)(p->data))->zone; - while (p2) - { /* traverse this preset's zones */ + + while(p2) + { + /* traverse this preset's zones */ p3 = ((SFZone *)(p2->data))->mod; - while (p3) - { /* load zone's modulators */ - if ((size -= SF_MOD_SIZE) < 0) + + while(p3) + { + /* load zone's modulators */ + if((size -= SF_MOD_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Preset modulator chunk size mismatch"); return FALSE; } + m = FLUID_NEW(SFMod); p3->data = m; READW(sf, m->src); @@ -1052,8 +1207,10 @@ static int load_pmod(SFData *sf, int size) READW(sf, m->trans); p3 = fluid_list_next(p3); } + p2 = fluid_list_next(p2); } + p = fluid_list_next(p); } @@ -1061,15 +1218,19 @@ static int load_pmod(SFData *sf, int size) If there isn't even a terminal record Hmmm, the specs say there should be one, but.. */ - if (size == 0) + if(size == 0) + { return TRUE; + } size -= SF_MOD_SIZE; - if (size != 0) + + if(size != 0) { FLUID_LOG(FLUID_ERR, "Preset modulator chunk size mismatch"); return FALSE; } + FSKIP(sf, SF_MOD_SIZE); /* terminal mod */ return TRUE; @@ -1097,24 +1258,34 @@ static int load_pgen(SFData *sf, int size) int level, skip, drop, gzone, discarded; p = sf->preset; - while (p) - { /* traverse through all presets */ + + while(p) + { + /* traverse through all presets */ gzone = FALSE; discarded = FALSE; p2 = ((SFPreset *)(p->data))->zone; - if (p2) + + if(p2) + { hz = &p2; - while (p2) - { /* traverse preset's zones */ + } + + while(p2) + { + /* traverse preset's zones */ level = 0; z = (SFZone *)(p2->data); p3 = z->gen; - while (p3) - { /* load zone's generators */ + + while(p3) + { + /* load zone's generators */ dup = NULL; skip = FALSE; drop = FALSE; - if ((size -= SF_GEN_SIZE) < 0) + + if((size -= SF_GEN_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Preset generator chunk size mismatch"); return FALSE; @@ -1122,30 +1293,37 @@ static int load_pgen(SFData *sf, int size) READW(sf, genid); - if (genid == Gen_KeyRange) - { /* nothing precedes */ - if (level == 0) + if(genid == Gen_KeyRange) + { + /* nothing precedes */ + if(level == 0) { level = 1; READB(sf, genval.range.lo); READB(sf, genval.range.hi); } else + { skip = TRUE; + } } - else if (genid == Gen_VelRange) - { /* only KeyRange precedes */ - if (level <= 1) + else if(genid == Gen_VelRange) + { + /* only KeyRange precedes */ + if(level <= 1) { level = 2; READB(sf, genval.range.lo); READB(sf, genval.range.hi); } else + { skip = TRUE; + } } - else if (genid == Gen_Instrument) - { /* inst is last gen */ + else if(genid == Gen_Instrument) + { + /* inst is last gen */ level = 3; READW(sf, genval.uword); ((SFZone *)(p2->data))->instsamp = FLUID_INT_TO_POINTER(genval.uword + 1); @@ -1154,19 +1332,24 @@ static int load_pgen(SFData *sf, int size) else { level = 2; - if (valid_preset_genid(genid)) - { /* generator valid? */ + + if(valid_preset_genid(genid)) + { + /* generator valid? */ READW(sf, genval.sword); dup = find_gen_by_id(genid, z->gen); } else + { skip = TRUE; + } } - if (!skip) + if(!skip) { - if (!dup) - { /* if gen ! dup alloc new */ + if(!dup) + { + /* if gen ! dup alloc new */ g = FLUID_NEW(SFGen); p3->data = g; g->id = genid; @@ -1176,32 +1359,42 @@ static int load_pgen(SFData *sf, int size) g = (SFGen *)(dup->data); /* ptr to orig gen */ drop = TRUE; } + g->amount = genval; } else - { /* Skip this generator */ + { + /* Skip this generator */ discarded = TRUE; drop = TRUE; FSKIPW(sf); } - if (!drop) - p3 = fluid_list_next(p3); /* next gen */ + if(!drop) + { + p3 = fluid_list_next(p3); /* next gen */ + } else - SLADVREM(z->gen, p3); /* drop place holder */ + { + SLADVREM(z->gen, p3); /* drop place holder */ + } } /* generator loop */ - if (level == 3) - SLADVREM(z->gen, p3); /* zone has inst? */ + if(level == 3) + { + SLADVREM(z->gen, p3); /* zone has inst? */ + } else - { /* congratulations its a global zone */ - if (!gzone) - { /* Prior global zones? */ + { + /* congratulations its a global zone */ + if(!gzone) + { + /* Prior global zones? */ gzone = TRUE; /* if global zone is not 1st zone, relocate */ - if (*hz != p2) + if(*hz != p2) { void *save = p2->data; FLUID_LOG(FLUID_WARN, "Preset '%s': Global zone is not first zone", @@ -1212,7 +1405,8 @@ static int load_pgen(SFData *sf, int size) } } else - { /* previous global zone exists, discard */ + { + /* previous global zone exists, discard */ FLUID_LOG(FLUID_WARN, "Preset '%s': Discarding invalid global zone", ((SFPreset *)(p->data))->name); *hz = fluid_list_remove(*hz, p2->data); @@ -1220,36 +1414,48 @@ static int load_pgen(SFData *sf, int size) } } - while (p3) - { /* Kill any zones following an instrument */ + while(p3) + { + /* Kill any zones following an instrument */ discarded = TRUE; - if ((size -= SF_GEN_SIZE) < 0) + + if((size -= SF_GEN_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Preset generator chunk size mismatch"); return FALSE; } + FSKIP(sf, SF_GEN_SIZE); SLADVREM(z->gen, p3); } p2 = fluid_list_next(p2); /* next zone */ } - if (discarded) - FLUID_LOG(FLUID_WARN, "Preset '%s': Some invalid generators were discarded", + + if(discarded) + { + FLUID_LOG(FLUID_WARN, + "Preset '%s': Some invalid generators were discarded", ((SFPreset *)(p->data))->name); + } + p = fluid_list_next(p); } /* in case there isn't a terminal record */ - if (size == 0) + if(size == 0) + { return TRUE; + } size -= SF_GEN_SIZE; - if (size != 0) + + if(size != 0) { FLUID_LOG(FLUID_ERR, "Preset generator chunk size mismatch"); return FALSE; } + FSKIP(sf, SF_GEN_SIZE); /* terminal gen */ return TRUE; @@ -1262,22 +1468,25 @@ static int load_ihdr(SFData *sf, int size) SFInst *p, *pr = NULL; /* ptr to current & previous instrument */ unsigned short zndx, pzndx = 0; - if (size % SF_IHDR_SIZE || size == 0) /* chunk size is valid? */ + if(size % SF_IHDR_SIZE || size == 0) /* chunk size is valid? */ { FLUID_LOG(FLUID_ERR, "Instrument header has invalid size"); return FALSE; } size = size / SF_IHDR_SIZE - 1; - if (size == 0) - { /* at least one preset + term record */ + + if(size == 0) + { + /* at least one preset + term record */ FLUID_LOG(FLUID_WARN, "File contains no instruments"); FSKIP(sf, SF_IHDR_SIZE); return TRUE; } - for (i = 0; i < size; i++) - { /* load all instrument headers */ + for(i = 0; i < size; i++) + { + /* load all instrument headers */ p = FLUID_NEW(SFInst); sf->inst = fluid_list_append(sf->inst, p); p->zone = NULL; /* For proper cleanup if fail (fluid_sffile_close) */ @@ -1285,19 +1494,27 @@ static int load_ihdr(SFData *sf, int size) READSTR(sf, &p->name); /* Possible read failure ^ */ READW(sf, zndx); - if (pr) - { /* not first instrument? */ - if (zndx < pzndx) + if(pr) + { + /* not first instrument? */ + if(zndx < pzndx) { FLUID_LOG(FLUID_ERR, "Instrument header indices not monotonic"); return FALSE; } + i2 = zndx - pzndx; - while (i2--) + + while(i2--) + { pr->zone = fluid_list_prepend(pr->zone, NULL); + } } - else if (zndx > 0) /* 1st inst, warn if ofs >0 */ + else if(zndx > 0) /* 1st inst, warn if ofs >0 */ + { FLUID_LOG(FLUID_WARN, "%d instrument zones not referenced, discarding", zndx); + } + pzndx = zndx; pr = p; /* update instrument ptr */ } @@ -1305,14 +1522,18 @@ static int load_ihdr(SFData *sf, int size) FSKIP(sf, 20); READW(sf, zndx); - if (zndx < pzndx) + if(zndx < pzndx) { FLUID_LOG(FLUID_ERR, "Instrument header indices not monotonic"); return FALSE; } + i2 = zndx - pzndx; - while (i2--) + + while(i2--) + { pr->zone = fluid_list_prepend(pr->zone, NULL); + } return TRUE; } @@ -1325,23 +1546,28 @@ static int load_ibag(SFData *sf, int size) unsigned short genndx, modndx, pgenndx = 0, pmodndx = 0; int i; - if (size % SF_BAG_SIZE || size == 0) /* size is multiple of SF_BAG_SIZE? */ + if(size % SF_BAG_SIZE || size == 0) /* size is multiple of SF_BAG_SIZE? */ { FLUID_LOG(FLUID_ERR, "Instrument bag chunk size is invalid"); return FALSE; } p = sf->inst; - while (p) - { /* traverse through inst */ + + while(p) + { + /* traverse through inst */ p2 = ((SFInst *)(p->data))->zone; - while (p2) - { /* load this inst's zones */ - if ((size -= SF_BAG_SIZE) < 0) + + while(p2) + { + /* load this inst's zones */ + if((size -= SF_BAG_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Instrument bag chunk size mismatch"); return FALSE; } + z = FLUID_NEW(SFZone); p2->data = z; z->gen = NULL; /* In case of failure, */ @@ -1350,35 +1576,48 @@ static int load_ibag(SFData *sf, int size) READW(sf, modndx); z->instsamp = NULL; - if (pz) - { /* if not first zone */ - if (genndx < pgenndx) + if(pz) + { + /* if not first zone */ + if(genndx < pgenndx) { FLUID_LOG(FLUID_ERR, "Instrument generator indices not monotonic"); return FALSE; } - if (modndx < pmodndx) + + if(modndx < pmodndx) { FLUID_LOG(FLUID_ERR, "Instrument modulator indices not monotonic"); return FALSE; } + i = genndx - pgenndx; - while (i--) + + while(i--) + { pz->gen = fluid_list_prepend(pz->gen, NULL); + } + i = modndx - pmodndx; - while (i--) + + while(i--) + { pz->mod = fluid_list_prepend(pz->mod, NULL); + } } + pz = z; /* update previous zone ptr */ pgenndx = genndx; pmodndx = modndx; p2 = fluid_list_next(p2); } + p = fluid_list_next(p); } size -= SF_BAG_SIZE; - if (size != 0) + + if(size != 0) { FLUID_LOG(FLUID_ERR, "Instrument chunk size mismatch"); return FALSE; @@ -1387,31 +1626,47 @@ static int load_ibag(SFData *sf, int size) READW(sf, genndx); READW(sf, modndx); - if (!pz) - { /* in case that all are no zoners */ - if (genndx > 0) + if(!pz) + { + /* in case that all are no zoners */ + if(genndx > 0) + { FLUID_LOG(FLUID_WARN, "No instrument generators and terminal index not 0"); - if (modndx > 0) + } + + if(modndx > 0) + { FLUID_LOG(FLUID_WARN, "No instrument modulators and terminal index not 0"); + } + return TRUE; } - if (genndx < pgenndx) + if(genndx < pgenndx) { FLUID_LOG(FLUID_ERR, "Instrument generator indices not monotonic"); return FALSE; } - if (modndx < pmodndx) + + if(modndx < pmodndx) { FLUID_LOG(FLUID_ERR, "Instrument modulator indices not monotonic"); return FALSE; } + i = genndx - pgenndx; - while (i--) + + while(i--) + { pz->gen = fluid_list_prepend(pz->gen, NULL); + } + i = modndx - pmodndx; - while (i--) + + while(i--) + { pz->mod = fluid_list_prepend(pz->mod, NULL); + } return TRUE; } @@ -1423,19 +1678,26 @@ static int load_imod(SFData *sf, int size) SFMod *m; p = sf->inst; - while (p) - { /* traverse through all inst */ + + while(p) + { + /* traverse through all inst */ p2 = ((SFInst *)(p->data))->zone; - while (p2) - { /* traverse this inst's zones */ + + while(p2) + { + /* traverse this inst's zones */ p3 = ((SFZone *)(p2->data))->mod; - while (p3) - { /* load zone's modulators */ - if ((size -= SF_MOD_SIZE) < 0) + + while(p3) + { + /* load zone's modulators */ + if((size -= SF_MOD_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Instrument modulator chunk size mismatch"); return FALSE; } + m = FLUID_NEW(SFMod); p3->data = m; READW(sf, m->src); @@ -1445,8 +1707,10 @@ static int load_imod(SFData *sf, int size) READW(sf, m->trans); p3 = fluid_list_next(p3); } + p2 = fluid_list_next(p2); } + p = fluid_list_next(p); } @@ -1454,15 +1718,19 @@ static int load_imod(SFData *sf, int size) If there isn't even a terminal record Hmmm, the specs say there should be one, but.. */ - if (size == 0) + if(size == 0) + { return TRUE; + } size -= SF_MOD_SIZE; - if (size != 0) + + if(size != 0) { FLUID_LOG(FLUID_ERR, "Instrument modulator chunk size mismatch"); return FALSE; } + FSKIP(sf, SF_MOD_SIZE); /* terminal mod */ return TRUE; @@ -1479,24 +1747,34 @@ static int load_igen(SFData *sf, int size) int level, skip, drop, gzone, discarded; p = sf->inst; - while (p) - { /* traverse through all instruments */ + + while(p) + { + /* traverse through all instruments */ gzone = FALSE; discarded = FALSE; p2 = ((SFInst *)(p->data))->zone; - if (p2) + + if(p2) + { hz = &p2; - while (p2) - { /* traverse this instrument's zones */ + } + + while(p2) + { + /* traverse this instrument's zones */ level = 0; z = (SFZone *)(p2->data); p3 = z->gen; - while (p3) - { /* load zone's generators */ + + while(p3) + { + /* load zone's generators */ dup = NULL; skip = FALSE; drop = FALSE; - if ((size -= SF_GEN_SIZE) < 0) + + if((size -= SF_GEN_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "IGEN chunk size mismatch"); return FALSE; @@ -1504,30 +1782,37 @@ static int load_igen(SFData *sf, int size) READW(sf, genid); - if (genid == Gen_KeyRange) - { /* nothing precedes */ - if (level == 0) + if(genid == Gen_KeyRange) + { + /* nothing precedes */ + if(level == 0) { level = 1; READB(sf, genval.range.lo); READB(sf, genval.range.hi); } else + { skip = TRUE; + } } - else if (genid == Gen_VelRange) - { /* only KeyRange precedes */ - if (level <= 1) + else if(genid == Gen_VelRange) + { + /* only KeyRange precedes */ + if(level <= 1) { level = 2; READB(sf, genval.range.lo); READB(sf, genval.range.hi); } else + { skip = TRUE; + } } - else if (genid == Gen_SampleId) - { /* sample is last gen */ + else if(genid == Gen_SampleId) + { + /* sample is last gen */ level = 3; READW(sf, genval.uword); ((SFZone *)(p2->data))->instsamp = FLUID_INT_TO_POINTER(genval.uword + 1); @@ -1536,19 +1821,24 @@ static int load_igen(SFData *sf, int size) else { level = 2; - if (valid_inst_genid(genid)) - { /* gen valid? */ + + if(valid_inst_genid(genid)) + { + /* gen valid? */ READW(sf, genval.sword); dup = find_gen_by_id(genid, z->gen); } else + { skip = TRUE; + } } - if (!skip) + if(!skip) { - if (!dup) - { /* if gen ! dup alloc new */ + if(!dup) + { + /* if gen ! dup alloc new */ g = FLUID_NEW(SFGen); p3->data = g; g->id = genid; @@ -1558,32 +1848,41 @@ static int load_igen(SFData *sf, int size) g = (SFGen *)(dup->data); drop = TRUE; } + g->amount = genval; } else - { /* skip this generator */ + { + /* skip this generator */ discarded = TRUE; drop = TRUE; FSKIPW(sf); } - if (!drop) - p3 = fluid_list_next(p3); /* next gen */ + if(!drop) + { + p3 = fluid_list_next(p3); /* next gen */ + } else + { SLADVREM(z->gen, p3); + } } /* generator loop */ - if (level == 3) - SLADVREM(z->gen, p3); /* zone has sample? */ + if(level == 3) + { + SLADVREM(z->gen, p3); /* zone has sample? */ + } else - { /* its a global zone */ - if (!gzone) + { + /* its a global zone */ + if(!gzone) { gzone = TRUE; /* if global zone is not 1st zone, relocate */ - if (*hz != p2) + if(*hz != p2) { void *save = p2->data; FLUID_LOG(FLUID_WARN, "Instrument '%s': Global zone is not first zone", @@ -1594,7 +1893,8 @@ static int load_igen(SFData *sf, int size) } } else - { /* previous global zone exists, discard */ + { + /* previous global zone exists, discard */ FLUID_LOG(FLUID_WARN, "Instrument '%s': Discarding invalid global zone", ((SFInst *)(p->data))->name); *hz = fluid_list_remove(*hz, p2->data); @@ -1602,36 +1902,48 @@ static int load_igen(SFData *sf, int size) } } - while (p3) - { /* Kill any zones following a sample */ + while(p3) + { + /* Kill any zones following a sample */ discarded = TRUE; - if ((size -= SF_GEN_SIZE) < 0) + + if((size -= SF_GEN_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Instrument generator chunk size mismatch"); return FALSE; } + FSKIP(sf, SF_GEN_SIZE); SLADVREM(z->gen, p3); } p2 = fluid_list_next(p2); /* next zone */ } - if (discarded) - FLUID_LOG(FLUID_WARN, "Instrument '%s': Some invalid generators were discarded", + + if(discarded) + { + FLUID_LOG(FLUID_WARN, + "Instrument '%s': Some invalid generators were discarded", ((SFInst *)(p->data))->name); + } + p = fluid_list_next(p); } /* for those non-terminal record cases, grr! */ - if (size == 0) + if(size == 0) + { return TRUE; + } size -= SF_GEN_SIZE; - if (size != 0) + + if(size != 0) { FLUID_LOG(FLUID_ERR, "IGEN chunk size mismatch"); return FALSE; } + FSKIP(sf, SF_GEN_SIZE); /* terminal gen */ return TRUE; @@ -1643,22 +1955,24 @@ static int load_shdr(SFData *sf, unsigned int size) unsigned int i; SFSample *p; - if (size % SF_SHDR_SIZE || size == 0) /* size is multiple of SHDR size? */ + if(size % SF_SHDR_SIZE || size == 0) /* size is multiple of SHDR size? */ { FLUID_LOG(FLUID_ERR, "Sample header has invalid size"); return FALSE; } size = size / SF_SHDR_SIZE - 1; - if (size == 0) - { /* at least one sample + term record? */ + + if(size == 0) + { + /* at least one sample + term record? */ FLUID_LOG(FLUID_WARN, "File contains no samples"); FSKIP(sf, SF_SHDR_SIZE); return TRUE; } /* load all sample headers */ - for (i = 0; i < size; i++) + for(i = 0; i < size; i++) { p = FLUID_NEW(SFSample); sf->sample = fluid_list_append(sf->sample, p); @@ -1688,27 +2002,38 @@ static int fixup_pgen(SFData *sf) int i; p = sf->preset; - while (p) + + while(p) { p2 = ((SFPreset *)(p->data))->zone; - while (p2) - { /* traverse this preset's zones */ + + while(p2) + { + /* traverse this preset's zones */ z = (SFZone *)(p2->data); - if ((i = FLUID_POINTER_TO_INT(z->instsamp))) - { /* load instrument # */ + + if((i = FLUID_POINTER_TO_INT(z->instsamp))) + { + /* load instrument # */ p3 = fluid_list_nth(sf->inst, i - 1); - if (!p3) + + if(!p3) { FLUID_LOG(FLUID_ERR, "Preset %03d %03d: Invalid instrument reference", - ((SFPreset *)(p->data))->bank, ((SFPreset *)(p->data))->prenum); + ((SFPreset *)(p->data))->bank, ((SFPreset *)(p->data))->prenum); return FALSE; } + z->instsamp = p3; } else + { z->instsamp = NULL; + } + p2 = fluid_list_next(p2); } + p = fluid_list_next(p); } @@ -1723,25 +2048,34 @@ static int fixup_igen(SFData *sf) int i; p = sf->inst; - while (p) + + while(p) { p2 = ((SFInst *)(p->data))->zone; - while (p2) - { /* traverse instrument's zones */ + + while(p2) + { + /* traverse instrument's zones */ z = (SFZone *)(p2->data); - if ((i = FLUID_POINTER_TO_INT(z->instsamp))) - { /* load sample # */ + + if((i = FLUID_POINTER_TO_INT(z->instsamp))) + { + /* load sample # */ p3 = fluid_list_nth(sf->sample, i - 1); - if (!p3) + + if(!p3) { FLUID_LOG(FLUID_ERR, "Instrument '%s': Invalid sample reference", - ((SFInst *)(p->data))->name); + ((SFInst *)(p->data))->name); return FALSE; } + z->instsamp = p3; } + p2 = fluid_list_next(p2); } + p = fluid_list_next(p); } @@ -1753,16 +2087,20 @@ static void delete_preset(SFPreset *preset) fluid_list_t *entry; SFZone *zone; - if (!preset) + if(!preset) + { return; + } entry = preset->zone; + while(entry) { zone = (SFZone *)fluid_list_get(entry); delete_zone(zone); entry = fluid_list_next(entry); } + delete_fluid_list(preset->zone); } @@ -1771,16 +2109,20 @@ static void delete_inst(SFInst *inst) fluid_list_t *entry; SFZone *zone; - if (!inst) + if(!inst) + { return; + } entry = inst->zone; + while(entry) { zone = (SFZone *)fluid_list_get(entry); delete_zone(zone); entry = fluid_list_next(entry); } + delete_fluid_list(inst->zone); } @@ -1790,23 +2132,29 @@ static void delete_zone(SFZone *zone) { fluid_list_t *entry; - if (!zone) + if(!zone) + { return; + } entry = zone->gen; + while(entry) { FLUID_FREE(fluid_list_get(entry)); entry = fluid_list_next(entry); } + delete_fluid_list(zone->gen); entry = zone->mod; + while(entry) { FLUID_FREE(fluid_list_get(entry)); entry = fluid_list_next(entry); } + delete_fluid_list(zone->mod); FLUID_FREE(zone); @@ -1828,18 +2176,27 @@ static int preset_compare_func(void *a, void *b) * @return pointer to SFGen if found, otherwise NULL */ static fluid_list_t *find_gen_by_id(int gen, fluid_list_t *genlist) -{ /* is generator in gen list? */ +{ + /* is generator in gen list? */ fluid_list_t *p; p = genlist; - while (p) + + while(p) { - if (p->data == NULL) + if(p->data == NULL) + { return NULL; - if (gen == ((SFGen *)p->data)->id) + } + + if(gen == ((SFGen *)p->data)->id) + { break; + } + p = fluid_list_next(p); } + return p; } @@ -1848,10 +2205,16 @@ static int valid_inst_genid(unsigned short genid) { int i = 0; - if (genid > Gen_MaxValid) + if(genid > Gen_MaxValid) + { return FALSE; - while (invalid_inst_gen[i] && invalid_inst_gen[i] != genid) + } + + while(invalid_inst_gen[i] && invalid_inst_gen[i] != genid) + { i++; + } + return (invalid_inst_gen[i] == 0); } @@ -1860,10 +2223,16 @@ static int valid_preset_genid(unsigned short genid) { int i = 0; - if (!valid_inst_genid(genid)) + if(!valid_inst_genid(genid)) + { return FALSE; - while (invalid_preset_gen[i] && invalid_preset_gen[i] != genid) + } + + while(invalid_preset_gen[i] && invalid_preset_gen[i] != genid) + { i++; + } + return (invalid_preset_gen[i] == 0); } @@ -1876,37 +2245,39 @@ static int fluid_sffile_read_wav(SFData *sf, unsigned int start, unsigned int en int num_samples = (end + 1) - start; fluid_return_val_if_fail(num_samples > 0, -1); - if ((start * sizeof(short) > sf->samplesize) || (end * sizeof(short) > sf->samplesize)) + if((start * sizeof(short) > sf->samplesize) || (end * sizeof(short) > sf->samplesize)) { FLUID_LOG(FLUID_ERR, "Sample offsets exceed sample data chunk"); goto error_exit; } /* Load 16-bit sample data */ - if (sf->fcbs->fseek(sf->sffd, sf->samplepos + (start * sizeof(short)), SEEK_SET) == FLUID_FAILED) + if(sf->fcbs->fseek(sf->sffd, sf->samplepos + (start * sizeof(short)), SEEK_SET) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Failed to seek to sample position"); goto error_exit; } loaded_data = FLUID_ARRAY(short, num_samples); - if (loaded_data == NULL) + + if(loaded_data == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_exit; } - if (sf->fcbs->fread(loaded_data, num_samples * sizeof(short), sf->sffd) == FLUID_FAILED) + if(sf->fcbs->fread(loaded_data, num_samples * sizeof(short), sf->sffd) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Failed to read sample data"); goto error_exit; } /* If this machine is big endian, byte swap the 16 bit samples */ - if (FLUID_IS_BIG_ENDIAN) + if(FLUID_IS_BIG_ENDIAN) { int i; - for (i = 0; i < num_samples; i++) + + for(i = 0; i < num_samples; i++) { loaded_data[i] = FLUID_LE16TOH(loaded_data[i]); } @@ -1917,28 +2288,29 @@ static int fluid_sffile_read_wav(SFData *sf, unsigned int start, unsigned int en /* Optionally load additional 8 bit sample data for 24-bit support. Any failures while loading * the 24-bit sample data will be logged as errors but won't prevent the sample reading to * fail, as sound output is still possible with the 16-bit sample data. */ - if (sf->sample24pos) + if(sf->sample24pos) { - if ((start > sf->sample24size) || (end > sf->sample24size)) + if((start > sf->sample24size) || (end > sf->sample24size)) { FLUID_LOG(FLUID_ERR, "Sample offsets exceed 24-bit sample data chunk"); goto error24_exit; } - if (sf->fcbs->fseek(sf->sffd, sf->sample24pos + start, SEEK_SET) == FLUID_FAILED) + if(sf->fcbs->fseek(sf->sffd, sf->sample24pos + start, SEEK_SET) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Failed to seek position for 24-bit sample data in data file"); goto error24_exit; } loaded_data24 = FLUID_ARRAY(char, num_samples); - if (loaded_data24 == NULL) + + if(loaded_data24 == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory reading 24-bit sample data"); goto error24_exit; } - if (sf->fcbs->fread(loaded_data24, num_samples, sf->sffd) == FLUID_FAILED) + if(sf->fcbs->fread(loaded_data24, num_samples, sf->sffd) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Failed to read 24-bit sample data"); goto error24_exit; @@ -1979,71 +2351,78 @@ typedef struct _sfvio_data_t static sf_count_t sfvio_get_filelen(void *user_data) { - sfvio_data_t *data = user_data; + sfvio_data_t *data = user_data; - return (data->end + 1) - data->start; + return (data->end + 1) - data->start; } static sf_count_t sfvio_seek(sf_count_t offset, int whence, void *user_data) { - sfvio_data_t *data = user_data; - SFData *sf = data->sffile; - sf_count_t new_offset; + sfvio_data_t *data = user_data; + SFData *sf = data->sffile; + sf_count_t new_offset; - switch (whence) - { + switch(whence) + { case SEEK_SET: - new_offset = offset; - break; - case SEEK_CUR: - new_offset = data->offset + offset; - break; - case SEEK_END: - new_offset = sfvio_get_filelen(user_data) + offset; - break; - default: - goto fail; /* proper error handling not possible?? */ - } + new_offset = offset; + break; - if (sf->fcbs->fseek(sf->sffd, sf->samplepos + data->start + new_offset, SEEK_SET) != FLUID_FAILED) { - data->offset = new_offset; - } + case SEEK_CUR: + new_offset = data->offset + offset; + break; + + case SEEK_END: + new_offset = sfvio_get_filelen(user_data) + offset; + break; + + default: + goto fail; /* proper error handling not possible?? */ + } + + if(sf->fcbs->fseek(sf->sffd, sf->samplepos + data->start + new_offset, SEEK_SET) != FLUID_FAILED) + { + data->offset = new_offset; + } fail: - return data->offset; + return data->offset; } -static sf_count_t sfvio_read(void* ptr, sf_count_t count, void* user_data) +static sf_count_t sfvio_read(void *ptr, sf_count_t count, void *user_data) { - sfvio_data_t *data = user_data; - SFData *sf = data->sffile; - sf_count_t remain; + sfvio_data_t *data = user_data; + SFData *sf = data->sffile; + sf_count_t remain; - remain = sfvio_get_filelen(user_data) - data->offset; - if (count > remain) - count = remain; + remain = sfvio_get_filelen(user_data) - data->offset; - if (count == 0) - { - return count; - } + if(count > remain) + { + count = remain; + } - if (sf->fcbs->fread(ptr, count, sf->sffd) == FLUID_FAILED) - { - FLUID_LOG(FLUID_ERR, "Failed to read compressed sample data"); - return 0; - } + if(count == 0) + { + return count; + } - data->offset += count; + if(sf->fcbs->fread(ptr, count, sf->sffd) == FLUID_FAILED) + { + FLUID_LOG(FLUID_ERR, "Failed to read compressed sample data"); + return 0; + } - return count; + data->offset += count; + + return count; } -static sf_count_t sfvio_tell(void* user_data) +static sf_count_t sfvio_tell(void *user_data) { - sfvio_data_t *data = user_data; + sfvio_data_t *data = user_data; - return data->offset; + return data->offset; } /** @@ -2060,17 +2439,18 @@ static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigne { SNDFILE *sndfile; SF_INFO sfinfo; - SF_VIRTUAL_IO sfvio = { - sfvio_get_filelen, - sfvio_seek, - sfvio_read, - NULL, - sfvio_tell + SF_VIRTUAL_IO sfvio = + { + sfvio_get_filelen, + sfvio_seek, + sfvio_read, + NULL, + sfvio_tell }; sfvio_data_t sfdata; short *wav_data = NULL; - if ((start_byte > sf->samplesize) || (end_byte > sf->samplesize)) + if((start_byte > sf->samplesize) || (end_byte > sf->samplesize)) { FLUID_LOG(FLUID_ERR, "Ogg Vorbis data offsets exceed sample data chunk"); return -1; @@ -2085,7 +2465,7 @@ static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigne memset(&sfinfo, 0, sizeof(sfinfo)); /* Seek to beginning of Ogg Vorbis data in Soundfont */ - if (sf->fcbs->fseek(sf->sffd, sf->samplepos + start_byte, SEEK_SET) == FLUID_FAILED) + if(sf->fcbs->fseek(sf->sffd, sf->samplepos + start_byte, SEEK_SET) == FLUID_FAILED) { FLUID_LOG(FLUID_ERR, "Failed to seek to compressd sample position"); return -1; @@ -2093,37 +2473,40 @@ static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigne // Open sample as a virtual file sndfile = sf_open_virtual(&sfvio, SFM_READ, &sfinfo, &sfdata); - if (!sndfile) + + if(!sndfile) { - FLUID_LOG(FLUID_ERR, sf_strerror(sndfile)); - return -1; + FLUID_LOG(FLUID_ERR, sf_strerror(sndfile)); + return -1; } // Empty sample - if (!sfinfo.frames || !sfinfo.channels) + if(!sfinfo.frames || !sfinfo.channels) { - FLUID_LOG(FLUID_DBG, "Empty decompressed sample"); - *data = NULL; - sf_close(sndfile); - return 0; + FLUID_LOG(FLUID_DBG, "Empty decompressed sample"); + *data = NULL; + sf_close(sndfile); + return 0; } /* FIXME: ensure that the decompressed WAV data is 16-bit mono? */ wav_data = FLUID_ARRAY(short, sfinfo.frames * sfinfo.channels); - if (!wav_data) + + if(!wav_data) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_exit; + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_exit; } /* Automatically decompresses the Ogg Vorbis data to 16-bit WAV */ - if (sf_readf_short(sndfile, wav_data, sfinfo.frames) < sfinfo.frames) + if(sf_readf_short(sndfile, wav_data, sfinfo.frames) < sfinfo.frames) { - FLUID_LOG(FLUID_DBG, "Decompression failed!"); - FLUID_LOG(FLUID_ERR, sf_strerror(sndfile)); - goto error_exit; + FLUID_LOG(FLUID_DBG, "Decompression failed!"); + FLUID_LOG(FLUID_ERR, sf_strerror(sndfile)); + goto error_exit; } + sf_close(sndfile); *data = wav_data; diff --git a/src/sfloader/fluid_sffile.h b/src/sfloader/fluid_sffile.h index 9a0e2126..0c315c73 100644 --- a/src/sfloader/fluid_sffile.h +++ b/src/sfloader/fluid_sffile.h @@ -52,13 +52,15 @@ typedef struct _SFShdr SFShdr; struct _SFVersion -{ /* version structure */ +{ + /* version structure */ unsigned short major; unsigned short minor; }; struct _SFMod -{ /* Modulator structure */ +{ + /* Modulator structure */ unsigned short src; /* source modulator */ unsigned short dest; /* destination generator */ signed short amount; /* signed, degree of modulation */ @@ -66,7 +68,8 @@ struct _SFMod unsigned short trans; /* transform applied to source */ }; -union _SFGenAmount { /* Generator amount structure */ +union _SFGenAmount /* Generator amount structure */ +{ signed short sword; /* signed 16 bit value */ unsigned short uword; /* unsigned 16 bit value */ struct @@ -77,20 +80,23 @@ union _SFGenAmount { /* Generator amount structure */ }; struct _SFGen -{ /* Generator structure */ +{ + /* Generator structure */ unsigned short id; /* generator ID */ SFGenAmount amount; /* generator value */ }; struct _SFZone -{ /* Sample/instrument zone structure */ +{ + /* Sample/instrument zone structure */ fluid_list_t *instsamp; /* instrument/sample pointer for zone */ fluid_list_t *gen; /* list of generators */ fluid_list_t *mod; /* list of modulators */ }; struct _SFSample -{ /* Sample structure */ +{ + /* Sample structure */ char name[21]; /* Name of sample */ unsigned char samfile; /* Loaded sfont/sample buffer = 0/1 */ unsigned int start; /* Offset in sample area to start of sample */ @@ -112,14 +118,16 @@ struct _SFSample }; struct _SFInst -{ /* Instrument structure */ +{ + /* Instrument structure */ char name[21]; /* Name of instrument */ int idx; /* Index of this instrument in the Soundfont */ fluid_list_t *zone; /* list of instrument zones */ }; struct _SFPreset -{ /* Preset structure */ +{ + /* Preset structure */ char name[21]; /* preset name */ unsigned short prenum; /* preset number */ unsigned short bank; /* bank number */ @@ -131,7 +139,8 @@ struct _SFPreset /* NOTE: sffd is also used to determine if sound font is new (NULL) */ struct _SFData -{ /* Sound font data structure */ +{ + /* Sound font data structure */ SFVersion version; /* sound font version */ SFVersion romver; /* ROM version */ @@ -167,7 +176,8 @@ struct _SFData /* sfont file data structures */ struct _SFChunk -{ /* RIFF file chunk structure */ +{ + /* RIFF file chunk structure */ unsigned int id; /* chunk id */ unsigned int size; /* size of the following chunk */ }; @@ -196,7 +206,8 @@ struct _SFIhdr }; struct _SFShdr -{ /* Sample header loading struct */ +{ + /* Sample header loading struct */ char name[20]; /* Sample name */ unsigned int start; /* Offset to start of sample */ unsigned int end; /* Offset to end of sample */ @@ -214,6 +225,6 @@ SFData *fluid_sffile_open(const char *fname, const fluid_file_callbacks_t *fcbs) void fluid_sffile_close(SFData *sf); int fluid_sffile_parse_presets(SFData *sf); int fluid_sffile_read_sample_data(SFData *sf, unsigned int sample_start, unsigned int sample_end, - int sample_type, short **data, char **data24); + int sample_type, short **data, char **data24); #endif /* _FLUID_SFFILE_H */ diff --git a/src/sfloader/fluid_sfont.c b/src/sfloader/fluid_sfont.c index 5159d11f..405bec6c 100644 --- a/src/sfloader/fluid_sfont.c +++ b/src/sfloader/fluid_sfont.c @@ -22,68 +22,77 @@ #include "fluid_sys.h" -void * default_fopen(const char * path) +void *default_fopen(const char *path) { return FLUID_FOPEN(path, "rb"); } -int default_fclose(void * handle) +int default_fclose(void *handle) { return FLUID_FCLOSE((FILE *)handle) == 0 ? FLUID_OK : FLUID_FAILED; } -long default_ftell(void * handle) +long default_ftell(void *handle) { return FLUID_FTELL((FILE *)handle); } -int safe_fread (void *buf, int count, void * fd) +int safe_fread(void *buf, int count, void *fd) { - if (FLUID_FREAD(buf, count, 1, (FILE *)fd) != 1) + if(FLUID_FREAD(buf, count, 1, (FILE *)fd) != 1) { - if (feof ((FILE *)fd)) - FLUID_LOG (FLUID_ERR, "EOF while attemping to read %d bytes", count); - else - FLUID_LOG (FLUID_ERR, "File read failed"); - - return FLUID_FAILED; + if(feof((FILE *)fd)) + { + FLUID_LOG(FLUID_ERR, "EOF while attemping to read %d bytes", count); + } + else + { + FLUID_LOG(FLUID_ERR, "File read failed"); + } + + return FLUID_FAILED; } - return FLUID_OK; + + return FLUID_OK; } -int safe_fseek (void * fd, long ofs, int whence) +int safe_fseek(void *fd, long ofs, int whence) { - if (FLUID_FSEEK((FILE *)fd, ofs, whence) != 0) { - FLUID_LOG (FLUID_ERR, "File seek failed with offset = %ld and whence = %d", ofs, whence); - return FLUID_FAILED; - } - return FLUID_OK; + if(FLUID_FSEEK((FILE *)fd, ofs, whence) != 0) + { + FLUID_LOG(FLUID_ERR, "File seek failed with offset = %ld and whence = %d", ofs, whence); + return FLUID_FAILED; + } + + return FLUID_OK; } /** * Creates a new SoundFont loader. - * + * * @param load Pointer to a function that provides a #fluid_sfont_t (see #fluid_sfloader_load_t). * @param free Pointer to a function that destroys this instance (see #fluid_sfloader_free_t). * Unless any private data needs to be freed it is sufficient to set this to delete_fluid_sfloader(). - * + * * @return the SoundFont loader instance on success, NULL otherwise. */ -fluid_sfloader_t* new_fluid_sfloader(fluid_sfloader_load_t load, fluid_sfloader_free_t free) +fluid_sfloader_t *new_fluid_sfloader(fluid_sfloader_load_t load, fluid_sfloader_free_t free) { fluid_sfloader_t *loader; - + fluid_return_val_if_fail(load != NULL, NULL); fluid_return_val_if_fail(free != NULL, NULL); - + loader = FLUID_NEW(fluid_sfloader_t); - if (loader == NULL) + + if(loader == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(loader, 0, sizeof(*loader)); - + loader->load = load; loader->free = free; fluid_sfloader_set_callbacks(loader, @@ -92,55 +101,55 @@ fluid_sfloader_t* new_fluid_sfloader(fluid_sfloader_load_t load, fluid_sfloader_ safe_fseek, default_ftell, default_fclose); - + return loader; } /** * Frees a SoundFont loader created with new_fluid_sfloader(). - * + * * @param loader The SoundFont loader instance to free. */ -void delete_fluid_sfloader(fluid_sfloader_t* loader) +void delete_fluid_sfloader(fluid_sfloader_t *loader) { fluid_return_if_fail(loader != NULL); - + FLUID_FREE(loader); } /** * Specify private data to be used by #fluid_sfloader_load_t. - * + * * @param loader The SoundFont loader instance. * @param data The private data to store. * @return #FLUID_OK on success, #FLUID_FAILED otherwise. */ -int fluid_sfloader_set_data(fluid_sfloader_t* loader, void* data) +int fluid_sfloader_set_data(fluid_sfloader_t *loader, void *data) { fluid_return_val_if_fail(loader != NULL, FLUID_FAILED); - + loader->data = data; return FLUID_OK; } /** * Obtain private data previously set with fluid_sfloader_set_data(). - * + * * @param loader The SoundFont loader instance. * @return The private data or NULL if none explicitly set before. */ -void* fluid_sfloader_get_data(fluid_sfloader_t* loader) +void *fluid_sfloader_get_data(fluid_sfloader_t *loader) { fluid_return_val_if_fail(loader != NULL, NULL); - + return loader->data; } /** * Set custom callbacks to be used upon soundfont loading. - * + * * Useful for loading a soundfont from memory, see \a doc/fluidsynth_sfload_mem.c as an example. - * + * * @param loader The SoundFont loader instance. * @param open A function implementing #fluid_sfloader_callback_open_t. * @param read A function implementing #fluid_sfloader_callback_read_t. @@ -149,30 +158,30 @@ void* fluid_sfloader_get_data(fluid_sfloader_t* loader) * @param close A function implementing #fluid_sfloader_callback_close_t. * @return #FLUID_OK if the callbacks have been successfully set, #FLUID_FAILED otherwise. */ -int fluid_sfloader_set_callbacks(fluid_sfloader_t* loader, - fluid_sfloader_callback_open_t open, - fluid_sfloader_callback_read_t read, - fluid_sfloader_callback_seek_t seek, - fluid_sfloader_callback_tell_t tell, - fluid_sfloader_callback_close_t close) +int fluid_sfloader_set_callbacks(fluid_sfloader_t *loader, + fluid_sfloader_callback_open_t open, + fluid_sfloader_callback_read_t read, + fluid_sfloader_callback_seek_t seek, + fluid_sfloader_callback_tell_t tell, + fluid_sfloader_callback_close_t close) { fluid_file_callbacks_t *cb; - + fluid_return_val_if_fail(loader != NULL, FLUID_FAILED); fluid_return_val_if_fail(open != NULL, FLUID_FAILED); fluid_return_val_if_fail(read != NULL, FLUID_FAILED); fluid_return_val_if_fail(seek != NULL, FLUID_FAILED); fluid_return_val_if_fail(tell != NULL, FLUID_FAILED); fluid_return_val_if_fail(close != NULL, FLUID_FAILED); - + cb = &loader->file_callbacks; - + cb->fopen = open; cb->fread = read; cb->fseek = seek; cb->ftell = tell; cb->fclose = close; - + return FLUID_OK; } @@ -185,24 +194,26 @@ int fluid_sfloader_set_callbacks(fluid_sfloader_t* loader, * @param free A function implementing #fluid_sfont_free_t. * @return The soundfont instance on success or NULL otherwise. */ -fluid_sfont_t* new_fluid_sfont(fluid_sfont_get_name_t get_name, +fluid_sfont_t *new_fluid_sfont(fluid_sfont_get_name_t get_name, fluid_sfont_get_preset_t get_preset, fluid_sfont_iteration_start_t iter_start, fluid_sfont_iteration_next_t iter_next, fluid_sfont_free_t free) { - fluid_sfont_t* sfont; - + fluid_sfont_t *sfont; + fluid_return_val_if_fail(get_name != NULL, NULL); fluid_return_val_if_fail(get_preset != NULL, NULL); fluid_return_val_if_fail(free != NULL, NULL); - + sfont = FLUID_NEW(fluid_sfont_t); - if (sfont == NULL) + + if(sfont == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(sfont, 0, sizeof(*sfont)); sfont->get_name = get_name; @@ -210,56 +221,56 @@ fluid_sfont_t* new_fluid_sfont(fluid_sfont_get_name_t get_name, sfont->iteration_start = iter_start; sfont->iteration_next = iter_next; sfont->free = free; - + return sfont; } /** * Set private data to use with a SoundFont instance. - * + * * @param sfont The SoundFont instance. * @param data The private data to store. * @return #FLUID_OK on success, #FLUID_FAILED otherwise. */ -int fluid_sfont_set_data(fluid_sfont_t* sfont, void* data) +int fluid_sfont_set_data(fluid_sfont_t *sfont, void *data) { fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED); - + sfont->data = data; return FLUID_OK; } /** * Retrieve the private data of a SoundFont instance. - * + * * @param sfont The SoundFont instance. * @return The private data or NULL if none explicitly set before. */ -void* fluid_sfont_get_data(fluid_sfont_t* sfont) +void *fluid_sfont_get_data(fluid_sfont_t *sfont) { fluid_return_val_if_fail(sfont != NULL, NULL); - + return sfont->data; } /** * Retrieve the unique ID of a SoundFont instance. - * + * * @param sfont The SoundFont instance. * @return The SoundFont ID. */ -int fluid_sfont_get_id(fluid_sfont_t* sfont) +int fluid_sfont_get_id(fluid_sfont_t *sfont) { return sfont->id; } /** * Retrieve the name of a SoundFont instance. - * + * * @param sfont The SoundFont instance. * @return The name of the SoundFont. */ -const char* fluid_sfont_get_name(fluid_sfont_t* sfont) +const char *fluid_sfont_get_name(fluid_sfont_t *sfont) { return sfont->get_name(sfont); } @@ -272,7 +283,7 @@ const char* fluid_sfont_get_name(fluid_sfont_t* sfont) * @param prenum program number of the preset * @return The preset instance or NULL if none found. */ -fluid_preset_t* fluid_sfont_get_preset(fluid_sfont_t* sfont, int bank, int prenum) +fluid_preset_t *fluid_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum) { return sfont->get_preset(sfont, bank, prenum); } @@ -282,49 +293,49 @@ fluid_preset_t* fluid_sfont_get_preset(fluid_sfont_t* sfont, int bank, int prenu * Starts / re-starts virtual preset iteration in a SoundFont. * @param sfont Virtual SoundFont instance */ -void fluid_sfont_iteration_start(fluid_sfont_t* sfont) +void fluid_sfont_iteration_start(fluid_sfont_t *sfont) { fluid_return_if_fail(sfont != NULL); fluid_return_if_fail(sfont->iteration_start != NULL); - + sfont->iteration_start(sfont); } /** * Virtual SoundFont preset iteration function. - * + * * Returns preset information to the caller and advances the * internal iteration state to the next preset for subsequent calls. * @param sfont The SoundFont instance. * @return NULL when no more presets are available, otherwise the a pointer to the current preset */ -fluid_preset_t* fluid_sfont_iteration_next(fluid_sfont_t* sfont) +fluid_preset_t *fluid_sfont_iteration_next(fluid_sfont_t *sfont) { fluid_return_val_if_fail(sfont != NULL, NULL); fluid_return_val_if_fail(sfont->iteration_next != NULL, NULL); - - return sfont->iteration_next(sfont); + + return sfont->iteration_next(sfont); } /** * Destroys a SoundFont instance created with new_fluid_sfont(). - * + * * Implements #fluid_sfont_free_t. - * + * * @param sfont The SoundFont instance to destroy. * @return Always returns 0. */ -int delete_fluid_sfont(fluid_sfont_t* sfont) +int delete_fluid_sfont(fluid_sfont_t *sfont) { fluid_return_val_if_fail(sfont != NULL, 0); - + FLUID_FREE(sfont); return 0; } /** * Create a virtual SoundFont preset instance. - * + * * @param parent_sfont The SoundFont instance this preset shall belong to * @param get_name A function implementing #fluid_preset_get_name_t * @param get_bank A function implementing #fluid_preset_get_banknum_t @@ -333,76 +344,78 @@ int delete_fluid_sfont(fluid_sfont_t* sfont) * @param free A function implementing #fluid_preset_free_t * @return The preset instance on success, NULL otherwise. */ -fluid_preset_t* new_fluid_preset(fluid_sfont_t* parent_sfont, +fluid_preset_t *new_fluid_preset(fluid_sfont_t *parent_sfont, fluid_preset_get_name_t get_name, fluid_preset_get_banknum_t get_bank, fluid_preset_get_num_t get_num, fluid_preset_noteon_t noteon, fluid_preset_free_t free) { - fluid_preset_t* preset; - + fluid_preset_t *preset; + fluid_return_val_if_fail(parent_sfont != NULL, NULL); fluid_return_val_if_fail(get_name != NULL, NULL); fluid_return_val_if_fail(get_bank != NULL, NULL); fluid_return_val_if_fail(get_num != NULL, NULL); fluid_return_val_if_fail(noteon != NULL, NULL); fluid_return_val_if_fail(free != NULL, NULL); - + preset = FLUID_NEW(fluid_preset_t); - if (preset == NULL) + + if(preset == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(preset, 0, sizeof(*preset)); - + preset->sfont = parent_sfont; preset->get_name = get_name; preset->get_banknum = get_bank; preset->get_num = get_num; preset->noteon = noteon; preset->free = free; - + return preset; } /** * Set private data to use with a SoundFont preset instance. - * + * * @param preset The SoundFont preset instance. * @param data The private data to store. * @return #FLUID_OK on success, #FLUID_FAILED otherwise. */ -int fluid_preset_set_data(fluid_preset_t* preset, void* data) +int fluid_preset_set_data(fluid_preset_t *preset, void *data) { fluid_return_val_if_fail(preset != NULL, FLUID_FAILED); - + preset->data = data; return FLUID_OK; } /** * Retrieve the private data of a SoundFont preset instance. - * + * * @param preset The SoundFont preset instance. * @return The private data or NULL if none explicitly set before. */ -void* fluid_preset_get_data(fluid_preset_t* preset) +void *fluid_preset_get_data(fluid_preset_t *preset) { fluid_return_val_if_fail(preset != NULL, NULL); - + return preset->data; } /** * Retrieves the presets name by executing the \p get_name function * provided on its creation. - * + * * @param preset The SoundFont preset instance. * @return Pointer to a NULL-terminated string containing the presets name. */ -const char* fluid_preset_get_name(fluid_preset_t* preset) +const char *fluid_preset_get_name(fluid_preset_t *preset) { return preset->get_name(preset); } @@ -410,11 +423,11 @@ const char* fluid_preset_get_name(fluid_preset_t* preset) /** * Retrieves the presets bank number by executing the \p get_bank function * provided on its creation. - * + * * @param preset The SoundFont preset instance. * @return The bank number of \p preset. */ -int fluid_preset_get_banknum(fluid_preset_t* preset) +int fluid_preset_get_banknum(fluid_preset_t *preset) { return preset->get_banknum(preset); } @@ -422,37 +435,37 @@ int fluid_preset_get_banknum(fluid_preset_t* preset) /** * Retrieves the presets (instrument) number by executing the \p get_num function * provided on its creation. - * + * * @param preset The SoundFont preset instance. * @return The number of \p preset. */ -int fluid_preset_get_num(fluid_preset_t* preset) +int fluid_preset_get_num(fluid_preset_t *preset) { return preset->get_num(preset); } /** * Retrieves the presets parent SoundFont instance. - * + * * @param preset The SoundFont preset instance. * @return The parent SoundFont of \p preset. */ -fluid_sfont_t* fluid_preset_get_sfont(fluid_preset_t* preset) +fluid_sfont_t *fluid_preset_get_sfont(fluid_preset_t *preset) { return preset->sfont; } /** * Destroys a SoundFont preset instance created with new_fluid_preset(). - * + * * Implements #fluid_preset_free_t. - * + * * @param preset The SoundFont preset instance to destroy. */ -void delete_fluid_preset(fluid_preset_t* preset) +void delete_fluid_preset(fluid_preset_t *preset) { fluid_return_if_fail(preset != NULL); - + FLUID_FREE(preset); } @@ -460,17 +473,19 @@ void delete_fluid_preset(fluid_preset_t* preset) * Create a new sample instance. * @return The sample on success, NULL otherwise. */ -fluid_sample_t* +fluid_sample_t * new_fluid_sample() { - fluid_sample_t* sample = NULL; + fluid_sample_t *sample = NULL; sample = FLUID_NEW(fluid_sample_t); - if (sample == NULL) + + if(sample == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } + FLUID_MEMSET(sample, 0, sizeof(*sample)); return sample; @@ -481,11 +496,11 @@ new_fluid_sample() * @param sample The sample to destroy. */ void -delete_fluid_sample(fluid_sample_t* sample) +delete_fluid_sample(fluid_sample_t *sample) { fluid_return_if_fail(sample != NULL); - - if (sample->auto_free) + + if(sample->auto_free) { FLUID_FREE(sample->data); FLUID_FREE(sample->data24); @@ -496,9 +511,9 @@ delete_fluid_sample(fluid_sample_t* sample) /** * Returns the size of the fluid_sample_t structure. - * + * * Useful in low latency scenarios e.g. to allocate a sample on the stack. - * + * * @return Size of fluid_sample_t in bytes */ size_t fluid_sample_sizeof() @@ -512,11 +527,11 @@ size_t fluid_sample_sizeof() * @param name Name to assign to sample (20 chars in length + zero terminator) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_sample_set_name(fluid_sample_t* sample, const char *name) +int fluid_sample_set_name(fluid_sample_t *sample, const char *name) { fluid_return_val_if_fail(sample != NULL, FLUID_FAILED); fluid_return_val_if_fail(name != NULL, FLUID_FAILED); - + FLUID_STRNCPY(sample->name, name, sizeof(sample->name)); return FLUID_OK; } @@ -535,23 +550,23 @@ int fluid_sample_set_name(fluid_sample_t* sample, const char *name) * and 8 unused frames at the end and \a nbframes should be >=48 */ int -fluid_sample_set_sound_data (fluid_sample_t* sample, - short *data, - char *data24, - unsigned int nbframes, - unsigned int sample_rate, - short copy_data - ) +fluid_sample_set_sound_data(fluid_sample_t *sample, + short *data, + char *data24, + unsigned int nbframes, + unsigned int sample_rate, + short copy_data + ) { /* the number of samples before the start and after the end */ - #define SAMPLE_LOOP_MARGIN 8U +#define SAMPLE_LOOP_MARGIN 8U fluid_return_val_if_fail(sample != NULL, FLUID_FAILED); fluid_return_val_if_fail(data != NULL, FLUID_FAILED); fluid_return_val_if_fail(nbframes == 0, FLUID_FAILED); - + /* in case we already have some data */ - if ((sample->data != NULL || sample->data24 != NULL) && sample->auto_free) + if((sample->data != NULL || sample->data24 != NULL) && sample->auto_free) { FLUID_FREE(sample->data); FLUID_FREE(sample->data24); @@ -559,35 +574,43 @@ fluid_sample_set_sound_data (fluid_sample_t* sample, sample->data24 = NULL; } - if (copy_data) + if(copy_data) { unsigned int storedNbFrames; /* nbframes should be >= 48 (SoundFont specs) */ storedNbFrames = nbframes; - if (storedNbFrames < 48) storedNbFrames = 48; - - storedNbFrames += 2*SAMPLE_LOOP_MARGIN; - + + if(storedNbFrames < 48) + { + storedNbFrames = 48; + } + + storedNbFrames += 2 * SAMPLE_LOOP_MARGIN; + sample->data = FLUID_ARRAY(short, storedNbFrames); - if (sample->data == NULL) + + if(sample->data == NULL) { goto error_rec; } + FLUID_MEMSET(sample->data, 0, storedNbFrames); - FLUID_MEMCPY(sample->data + SAMPLE_LOOP_MARGIN, data, nbframes*sizeof(short)); - + FLUID_MEMCPY(sample->data + SAMPLE_LOOP_MARGIN, data, nbframes * sizeof(short)); + if(data24 != NULL) { sample->data24 = FLUID_ARRAY(char, storedNbFrames); - if (sample->data24 == NULL) + + if(sample->data24 == NULL) { goto error_rec; } + FLUID_MEMSET(sample->data24, 0, storedNbFrames); - FLUID_MEMCPY(sample->data24 + SAMPLE_LOOP_MARGIN, data24, nbframes*sizeof(char)); + FLUID_MEMCPY(sample->data24 + SAMPLE_LOOP_MARGIN, data24, nbframes * sizeof(char)); } - + /* pointers */ /* all from the start of data */ sample->start = SAMPLE_LOOP_MARGIN; @@ -607,50 +630,50 @@ fluid_sample_set_sound_data (fluid_sample_t* sample, sample->auto_free = copy_data; return FLUID_OK; - + error_rec: FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_FREE(sample->data); FLUID_FREE(sample->data24); return FLUID_FAILED; - + #undef SAMPLE_LOOP_MARGIN } /** * Set the loop of a sample. - * + * * @param sample SoundFont sample * @param loop_start Start sample index of the loop. * @param loop_end End index of the loop (must be a valid sample as it marks the last sample to be played). * @return #FLUID_OK on success, #FLUID_FAILED otherwise. */ -int fluid_sample_set_loop(fluid_sample_t* sample, unsigned int loop_start, unsigned int loop_end) +int fluid_sample_set_loop(fluid_sample_t *sample, unsigned int loop_start, unsigned int loop_end) { fluid_return_val_if_fail(sample != NULL, FLUID_FAILED); - + sample->loopstart = loop_start; sample->loopend = loop_end; - + return FLUID_OK; } /** * Set the pitch of a sample. - * + * * @param sample SoundFont sample * @param root_key Root MIDI note of sample (0-127) * @param fine_tune Fine tune in cents * @return #FLUID_OK on success, #FLUID_FAILED otherwise. */ -int fluid_sample_set_pitch(fluid_sample_t* sample, int root_key, int fine_tune) +int fluid_sample_set_pitch(fluid_sample_t *sample, int root_key, int fine_tune) { fluid_return_val_if_fail(sample != NULL, FLUID_FAILED); - fluid_return_val_if_fail(0<=root_key && root_key<=127, FLUID_FAILED); - + fluid_return_val_if_fail(0 <= root_key && root_key <= 127, FLUID_FAILED); + sample->origpitch = root_key; sample->pitchadj = fine_tune; - + return FLUID_OK; } @@ -662,7 +685,7 @@ int fluid_sample_set_pitch(fluid_sample_t* sample, int root_key, int fine_tune) int fluid_sample_validate(fluid_sample_t *sample, unsigned int buffer_size) { /* ROM samples are unusable for us by definition */ - if (sample->sampletype & FLUID_SAMPLETYPE_ROM) + if(sample->sampletype & FLUID_SAMPLETYPE_ROM) { FLUID_LOG(FLUID_WARN, "Sample '%s': ROM sample ignored", sample->name); return FLUID_FAILED; @@ -672,17 +695,18 @@ int fluid_sample_validate(fluid_sample_t *sample, unsigned int buffer_size) * sample start and end pointers before decompression. Standard SF2 samples * use sample word indices for all pointers, so use half the buffer_size * for validation. */ - if (!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS)) + if(!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS)) { - if (buffer_size % 2) + if(buffer_size % 2) { FLUID_LOG(FLUID_WARN, "Sample '%s': invalid buffer size", sample->name); return FLUID_FAILED; } + buffer_size /= 2; } - if ((sample->end > buffer_size) || (sample->start >= sample->end)) + if((sample->end > buffer_size) || (sample->start >= sample->end)) { FLUID_LOG(FLUID_WARN, "Sample '%s': invalid start/end file positions", sample->name); return FLUID_FAILED; @@ -703,7 +727,7 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size) * to the data word after the last sample. FIXME: why? */ unsigned int sample_end = sample->end + 1; - if (sample->loopstart == sample->loopend) + if(sample->loopstart == sample->loopend) { /* Some SoundFonts disable loops by setting loopstart = loopend. While * technically invalid, we decided to accept those samples anyway. Just @@ -713,14 +737,14 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size) sample->loopstart = sample->loopend = 0; return FALSE; } - else if (sample->loopstart > sample->loopend) + else if(sample->loopstart > sample->loopend) { unsigned int tmp; /* If loop start and end are reversed, try to swap them around and * continue validation */ FLUID_LOG(FLUID_DBG, "Sample '%s': reversed loop pointers '%d' - '%d', trying to fix", - sample->name, sample->loopstart, sample->loopend); + sample->name, sample->loopstart, sample->loopend); tmp = sample->loopstart; sample->loopstart = sample->loopend; sample->loopend = tmp; @@ -734,26 +758,26 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size) * best practice to mangle with loops as little as necessary by only making * sure the pointers are within sample->start to max_end. Incorrect * soundfont shall preferably fail loudly. */ - if ((sample->loopstart < sample->start) || (sample->loopstart > max_end)) + if((sample->loopstart < sample->start) || (sample->loopstart > max_end)) { FLUID_LOG(FLUID_DBG, "Sample '%s': invalid loop start '%d', setting to sample start '%d'", - sample->name, sample->loopstart, sample->start); + sample->name, sample->loopstart, sample->start); sample->loopstart = sample->start; modified = TRUE; } - if ((sample->loopend < sample->start) || (sample->loopend > max_end)) + if((sample->loopend < sample->start) || (sample->loopend > max_end)) { FLUID_LOG(FLUID_DBG, "Sample '%s': invalid loop end '%d', setting to sample end '%d'", - sample->name, sample->loopend, sample_end); + sample->name, sample->loopend, sample_end); sample->loopend = sample_end; modified = TRUE; } - if ((sample->loopstart > sample_end) || (sample->loopend > sample_end)) + if((sample->loopstart > sample_end) || (sample->loopend > sample_end)) { FLUID_LOG(FLUID_DBG, "Sample '%s': loop range '%d - %d' after sample end '%d', using it anyway", - sample->name, sample->loopstart, sample->loopend, sample_end); + sample->name, sample->loopstart, sample->loopend, sample_end); } return modified; diff --git a/src/sfloader/fluid_sfont.h b/src/sfloader/fluid_sfont.h index bee46bd9..24773353 100644 --- a/src/sfloader/fluid_sfont.h +++ b/src/sfloader/fluid_sfont.h @@ -62,79 +62,82 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int max_end); */ struct _fluid_file_callbacks_t { - fluid_sfloader_callback_open_t fopen; - fluid_sfloader_callback_read_t fread; - fluid_sfloader_callback_seek_t fseek; - fluid_sfloader_callback_close_t fclose; - fluid_sfloader_callback_tell_t ftell; + fluid_sfloader_callback_open_t fopen; + fluid_sfloader_callback_read_t fread; + fluid_sfloader_callback_seek_t fseek; + fluid_sfloader_callback_close_t fclose; + fluid_sfloader_callback_tell_t ftell; }; /** * SoundFont loader structure. */ -struct _fluid_sfloader_t { - void* data; /**< User defined data pointer used by _fluid_sfloader_t::load() */ +struct _fluid_sfloader_t +{ + void *data; /**< User defined data pointer used by _fluid_sfloader_t::load() */ - /** Callback structure specifying file operations used during soundfont loading to allow custom loading, such as from memory */ - fluid_file_callbacks_t file_callbacks; + /** Callback structure specifying file operations used during soundfont loading to allow custom loading, such as from memory */ + fluid_file_callbacks_t file_callbacks; - fluid_sfloader_free_t free; + fluid_sfloader_free_t free; - fluid_sfloader_load_t load; + fluid_sfloader_load_t load; }; /** * Virtual SoundFont instance structure. */ -struct _fluid_sfont_t { - void* data; /**< User defined data */ - int id; /**< SoundFont ID */ - int refcount; /**< SoundFont reference count (1 if no presets referencing it) */ - int bankofs; /**< Bank offset */ +struct _fluid_sfont_t +{ + void *data; /**< User defined data */ + int id; /**< SoundFont ID */ + int refcount; /**< SoundFont reference count (1 if no presets referencing it) */ + int bankofs; /**< Bank offset */ - fluid_sfont_free_t free; + fluid_sfont_free_t free; - fluid_sfont_get_name_t get_name; + fluid_sfont_get_name_t get_name; - fluid_sfont_get_preset_t get_preset; + fluid_sfont_get_preset_t get_preset; - fluid_sfont_iteration_start_t iteration_start; + fluid_sfont_iteration_start_t iteration_start; - fluid_sfont_iteration_next_t iteration_next; + fluid_sfont_iteration_next_t iteration_next; }; /** * Virtual SoundFont preset. */ -struct _fluid_preset_t { - void* data; /**< User supplied data */ - fluid_sfont_t* sfont; /**< Parent virtual SoundFont */ +struct _fluid_preset_t +{ + void *data; /**< User supplied data */ + fluid_sfont_t *sfont; /**< Parent virtual SoundFont */ - fluid_preset_free_t free; + fluid_preset_free_t free; - fluid_preset_get_name_t get_name; + fluid_preset_get_name_t get_name; - fluid_preset_get_banknum_t get_banknum; + fluid_preset_get_banknum_t get_banknum; - fluid_preset_get_num_t get_num; + fluid_preset_get_num_t get_num; - fluid_preset_noteon_t noteon; + fluid_preset_noteon_t noteon; - /** - * Virtual SoundFont preset notify method. - * @param preset Virtual SoundFont preset - * @param reason #FLUID_PRESET_SELECTED or #FLUID_PRESET_UNSELECTED - * @param chan MIDI channel number - * @return Should return #FLUID_OK - * - * Implement this optional method if the preset needs to be notified about - * preset select and unselect events. - * - * This method may be called from within synthesis context and therefore - * should be as efficient as possible and not perform any operations considered - * bad for realtime audio output (memory allocations and other OS calls). - */ - int (*notify)(fluid_preset_t* preset, int reason, int chan); + /** + * Virtual SoundFont preset notify method. + * @param preset Virtual SoundFont preset + * @param reason #FLUID_PRESET_SELECTED or #FLUID_PRESET_UNSELECTED + * @param chan MIDI channel number + * @return Should return #FLUID_OK + * + * Implement this optional method if the preset needs to be notified about + * preset select and unselect events. + * + * This method may be called from within synthesis context and therefore + * should be as efficient as possible and not perform any operations considered + * bad for realtime audio output (memory allocations and other OS calls). + */ + int (*notify)(fluid_preset_t *preset, int reason, int chan); }; /** @@ -142,46 +145,46 @@ struct _fluid_preset_t { */ struct _fluid_sample_t { - char name[21]; /**< Sample name */ + char name[21]; /**< Sample name */ - /* The following for sample pointers store the original pointers from the Soundfont - * file. They are never changed after loading and are used to re-create the - * actual sample pointers after a sample has been unloaded and loaded again. The - * actual sample pointers get modified during loading for SF3 (compressed) samples - * and individually loaded SF2 samples. */ - unsigned int source_start; - unsigned int source_end; - unsigned int source_loopstart; - unsigned int source_loopend; + /* The following for sample pointers store the original pointers from the Soundfont + * file. They are never changed after loading and are used to re-create the + * actual sample pointers after a sample has been unloaded and loaded again. The + * actual sample pointers get modified during loading for SF3 (compressed) samples + * and individually loaded SF2 samples. */ + unsigned int source_start; + unsigned int source_end; + unsigned int source_loopstart; + unsigned int source_loopend; - unsigned int start; /**< Start index */ - unsigned int end; /**< End index, index of last valid sample point (contrary to SF spec) */ - unsigned int loopstart; /**< Loop start index */ - unsigned int loopend; /**< Loop end index, first point following the loop (superimposed on loopstart) */ + unsigned int start; /**< Start index */ + unsigned int end; /**< End index, index of last valid sample point (contrary to SF spec) */ + unsigned int loopstart; /**< Loop start index */ + unsigned int loopend; /**< Loop end index, first point following the loop (superimposed on loopstart) */ - unsigned int samplerate; /**< Sample rate */ - int origpitch; /**< Original pitch (MIDI note number, 0-127) */ - int pitchadj; /**< Fine pitch adjustment (+/- 99 cents) */ - int sampletype; /**< Specifies the type of this sample as indicated by the #fluid_sample_type enum */ - int auto_free; /**< TRUE if _fluid_sample_t::data and _fluid_sample_t::data24 should be freed upon sample destruction */ - short* data; /**< Pointer to the sample's 16 bit PCM data */ - char* data24; /**< If not NULL, pointer to the least significant byte counterparts of each sample data point in order to create 24 bit audio samples */ + unsigned int samplerate; /**< Sample rate */ + int origpitch; /**< Original pitch (MIDI note number, 0-127) */ + int pitchadj; /**< Fine pitch adjustment (+/- 99 cents) */ + int sampletype; /**< Specifies the type of this sample as indicated by the #fluid_sample_type enum */ + int auto_free; /**< TRUE if _fluid_sample_t::data and _fluid_sample_t::data24 should be freed upon sample destruction */ + short *data; /**< Pointer to the sample's 16 bit PCM data */ + char *data24; /**< If not NULL, pointer to the least significant byte counterparts of each sample data point in order to create 24 bit audio samples */ - int amplitude_that_reaches_noise_floor_is_valid; /**< Indicates if \a amplitude_that_reaches_noise_floor is valid (TRUE), set to FALSE initially to calculate. */ - double amplitude_that_reaches_noise_floor; /**< The amplitude at which the sample's loop will be below the noise floor. For voice off optimization, calculated automatically. */ + int amplitude_that_reaches_noise_floor_is_valid; /**< Indicates if \a amplitude_that_reaches_noise_floor is valid (TRUE), set to FALSE initially to calculate. */ + double amplitude_that_reaches_noise_floor; /**< The amplitude at which the sample's loop will be below the noise floor. For voice off optimization, calculated automatically. */ - unsigned int refcount; /**< Count of voices using this sample */ - int preset_count; /**< Count of selected presets using this sample (used for dynamic sample loading) */ + unsigned int refcount; /**< Count of voices using this sample */ + int preset_count; /**< Count of selected presets using this sample (used for dynamic sample loading) */ - /** - * Implement this function to receive notification when sample is no longer used. - * @param sample Virtual SoundFont sample - * @param reason #FLUID_SAMPLE_DONE only currently - * @return Should return #FLUID_OK - */ - int (*notify)(fluid_sample_t* sample, int reason); + /** + * Implement this function to receive notification when sample is no longer used. + * @param sample Virtual SoundFont sample + * @param reason #FLUID_SAMPLE_DONE only currently + * @return Should return #FLUID_OK + */ + int (*notify)(fluid_sample_t *sample, int reason); - void* userdata; /**< User defined data */ + void *userdata; /**< User defined data */ }; diff --git a/src/synth/fluid_chan.c b/src/synth/fluid_chan.c index 77c08490..49ef99ec 100644 --- a/src/synth/fluid_chan.c +++ b/src/synth/fluid_chan.c @@ -36,326 +36,374 @@ #define SFONT_MASKVAL 0xFFC00000 -static void fluid_channel_init(fluid_channel_t* chan); +static void fluid_channel_init(fluid_channel_t *chan); -fluid_channel_t* -new_fluid_channel(fluid_synth_t* synth, int num) +fluid_channel_t * +new_fluid_channel(fluid_synth_t *synth, int num) { - fluid_channel_t* chan; + fluid_channel_t *chan; - chan = FLUID_NEW(fluid_channel_t); - if (chan == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + chan = FLUID_NEW(fluid_channel_t); - chan->synth = synth; - chan->channum = num; - chan->preset = NULL; - chan->tuning = NULL; + if(chan == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - fluid_channel_init(chan); - fluid_channel_init_ctrl(chan, 0); + chan->synth = synth; + chan->channum = num; + chan->preset = NULL; + chan->tuning = NULL; - return chan; + fluid_channel_init(chan); + fluid_channel_init_ctrl(chan, 0); + + return chan; } static void -fluid_channel_init(fluid_channel_t* chan) +fluid_channel_init(fluid_channel_t *chan) { - fluid_preset_t *newpreset; - int i, prognum, banknum; + fluid_preset_t *newpreset; + int i, prognum, banknum; - chan->sostenuto_orderid = 0; - /*--- Init poly/mono modes variables --------------------------------------*/ - chan->mode = 0; - chan->mode_val = 0; - /* monophonic list initialization */ - for (i=0; i < FLUID_CHANNEL_SIZE_MONOLIST; i++) - { - chan->monolist[i].next = i+1; - } - chan->monolist[FLUID_CHANNEL_SIZE_MONOLIST -1].next = 0; /* ending element chained to the 1st */ - chan->i_last = chan->n_notes = 0; /* clears the list */ - chan->i_first = chan->monolist[chan->i_last].next; /* first note index in the list */ - fluid_channel_clear_prev_note(chan); /* Mark previous note invalid */ - /*---*/ - chan->key_mono_sustained = INVALID_NOTE; /* No previous mono note sustained */ - chan->legatomode = FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER; /* Default mode */ - chan->portamentomode = FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY; /* Default mode */ -/*--- End of poly/mono initialization --------------------------------------*/ - - chan->channel_type = (chan->channum == 9) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC; - prognum = 0; - banknum = (chan->channel_type == CHANNEL_TYPE_DRUM) ? DRUM_INST_BANK : 0; + chan->sostenuto_orderid = 0; + /*--- Init poly/mono modes variables --------------------------------------*/ + chan->mode = 0; + chan->mode_val = 0; - chan->sfont_bank_prog = 0 << SFONT_SHIFTVAL | banknum << BANK_SHIFTVAL - | prognum << PROG_SHIFTVAL; + /* monophonic list initialization */ + for(i = 0; i < FLUID_CHANNEL_SIZE_MONOLIST; i++) + { + chan->monolist[i].next = i + 1; + } - newpreset = fluid_synth_find_preset(chan->synth, banknum, prognum); - fluid_channel_set_preset(chan, newpreset); + chan->monolist[FLUID_CHANNEL_SIZE_MONOLIST - 1].next = 0; /* ending element chained to the 1st */ + chan->i_last = chan->n_notes = 0; /* clears the list */ + chan->i_first = chan->monolist[chan->i_last].next; /* first note index in the list */ + fluid_channel_clear_prev_note(chan); /* Mark previous note invalid */ + /*---*/ + chan->key_mono_sustained = INVALID_NOTE; /* No previous mono note sustained */ + chan->legatomode = FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER; /* Default mode */ + chan->portamentomode = FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY; /* Default mode */ + /*--- End of poly/mono initialization --------------------------------------*/ - chan->interp_method = FLUID_INTERP_DEFAULT; - chan->tuning_bank = 0; - chan->tuning_prog = 0; - chan->nrpn_select = 0; - chan->nrpn_active = 0; + chan->channel_type = (chan->channum == 9) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC; + prognum = 0; + banknum = (chan->channel_type == CHANNEL_TYPE_DRUM) ? DRUM_INST_BANK : 0; - if (chan->tuning) - { - fluid_tuning_unref (chan->tuning, 1); - chan->tuning = NULL; - } + chan->sfont_bank_prog = 0 << SFONT_SHIFTVAL | banknum << BANK_SHIFTVAL + | prognum << PROG_SHIFTVAL; + + newpreset = fluid_synth_find_preset(chan->synth, banknum, prognum); + fluid_channel_set_preset(chan, newpreset); + + chan->interp_method = FLUID_INTERP_DEFAULT; + chan->tuning_bank = 0; + chan->tuning_prog = 0; + chan->nrpn_select = 0; + chan->nrpn_active = 0; + + if(chan->tuning) + { + fluid_tuning_unref(chan->tuning, 1); + chan->tuning = NULL; + } } /* - @param is_all_ctrl_off if nonzero, only resets some controllers, according to - http://www.midi.org/techspecs/rp15.php + @param is_all_ctrl_off if nonzero, only resets some controllers, according to + http://www.midi.org/techspecs/rp15.php */ void -fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off) +fluid_channel_init_ctrl(fluid_channel_t *chan, int is_all_ctrl_off) { - int i; + int i; - chan->channel_pressure = 0; - chan->pitch_bend = 0x2000; /* Range is 0x4000, pitch bend wheel starts in centered position */ + chan->channel_pressure = 0; + chan->pitch_bend = 0x2000; /* Range is 0x4000, pitch bend wheel starts in centered position */ - for (i = 0; i < GEN_LAST; i++) { - chan->gen[i] = 0.0f; - chan->gen_abs[i] = 0; - } - - if (is_all_ctrl_off) { - for (i = 0; i < ALL_SOUND_OFF; i++) { - if (i >= EFFECTS_DEPTH1 && i <= EFFECTS_DEPTH5) { - continue; - } - if (i >= SOUND_CTRL1 && i <= SOUND_CTRL10) { - continue; - } - if (i == BANK_SELECT_MSB || i == BANK_SELECT_LSB || i == VOLUME_MSB || - i == VOLUME_LSB || i == PAN_MSB || i == PAN_LSB || - i == BALANCE_MSB || i == BALANCE_LSB - ) { - continue; - } - - fluid_channel_set_cc (chan, i, 0); - } - } - else { - for (i = 0; i < 128; i++) { - fluid_channel_set_cc (chan, i, 0); - } - fluid_channel_clear_portamento(chan); /* Clear PTC receive */ - chan->previous_cc_breath = 0;/* Reset previous breath */ - } - - /* Reset polyphonic key pressure on all voices */ - for (i = 0; i < 128; i++) { - fluid_channel_set_key_pressure(chan, i, 0); - } - - /* Set RPN controllers to NULL state */ - fluid_channel_set_cc (chan, RPN_LSB, 127); - fluid_channel_set_cc (chan, RPN_MSB, 127); - - /* Set NRPN controllers to NULL state */ - fluid_channel_set_cc (chan, NRPN_LSB, 127); - fluid_channel_set_cc (chan, NRPN_MSB, 127); - - /* Expression (MSB & LSB) */ - fluid_channel_set_cc (chan, EXPRESSION_MSB, 127); - fluid_channel_set_cc (chan, EXPRESSION_LSB, 127); - - if (!is_all_ctrl_off) { - - chan->pitch_wheel_sensitivity = 2; /* two semi-tones */ - - /* Just like panning, a value of 64 indicates no change for sound ctrls */ - for (i = SOUND_CTRL1; i <= SOUND_CTRL10; i++) { - fluid_channel_set_cc (chan, i, 64); + for(i = 0; i < GEN_LAST; i++) + { + chan->gen[i] = 0.0f; + chan->gen_abs[i] = 0; } - /* Volume / initial attenuation (MSB & LSB) */ - fluid_channel_set_cc (chan, VOLUME_MSB, 100); - fluid_channel_set_cc (chan, VOLUME_LSB, 0); + if(is_all_ctrl_off) + { + for(i = 0; i < ALL_SOUND_OFF; i++) + { + if(i >= EFFECTS_DEPTH1 && i <= EFFECTS_DEPTH5) + { + continue; + } - /* Pan (MSB & LSB) */ - fluid_channel_set_cc (chan, PAN_MSB, 64); - fluid_channel_set_cc (chan, PAN_LSB, 0); + if(i >= SOUND_CTRL1 && i <= SOUND_CTRL10) + { + continue; + } - /* Balance (MSB & LSB) */ - fluid_channel_set_cc (chan, BALANCE_MSB, 64); - fluid_channel_set_cc (chan, BALANCE_LSB, 0); + if(i == BANK_SELECT_MSB || i == BANK_SELECT_LSB || i == VOLUME_MSB || + i == VOLUME_LSB || i == PAN_MSB || i == PAN_LSB || + i == BALANCE_MSB || i == BALANCE_LSB + ) + { + continue; + } - /* Reverb */ - /* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */ - /* Note: although XG standard specifies the default amount of reverb to - be 40, most people preferred having it at zero. - See http://lists.gnu.org/archive/html/fluid-dev/2009-07/msg00016.html */ - } + fluid_channel_set_cc(chan, i, 0); + } + } + else + { + for(i = 0; i < 128; i++) + { + fluid_channel_set_cc(chan, i, 0); + } + + fluid_channel_clear_portamento(chan); /* Clear PTC receive */ + chan->previous_cc_breath = 0;/* Reset previous breath */ + } + + /* Reset polyphonic key pressure on all voices */ + for(i = 0; i < 128; i++) + { + fluid_channel_set_key_pressure(chan, i, 0); + } + + /* Set RPN controllers to NULL state */ + fluid_channel_set_cc(chan, RPN_LSB, 127); + fluid_channel_set_cc(chan, RPN_MSB, 127); + + /* Set NRPN controllers to NULL state */ + fluid_channel_set_cc(chan, NRPN_LSB, 127); + fluid_channel_set_cc(chan, NRPN_MSB, 127); + + /* Expression (MSB & LSB) */ + fluid_channel_set_cc(chan, EXPRESSION_MSB, 127); + fluid_channel_set_cc(chan, EXPRESSION_LSB, 127); + + if(!is_all_ctrl_off) + { + + chan->pitch_wheel_sensitivity = 2; /* two semi-tones */ + + /* Just like panning, a value of 64 indicates no change for sound ctrls */ + for(i = SOUND_CTRL1; i <= SOUND_CTRL10; i++) + { + fluid_channel_set_cc(chan, i, 64); + } + + /* Volume / initial attenuation (MSB & LSB) */ + fluid_channel_set_cc(chan, VOLUME_MSB, 100); + fluid_channel_set_cc(chan, VOLUME_LSB, 0); + + /* Pan (MSB & LSB) */ + fluid_channel_set_cc(chan, PAN_MSB, 64); + fluid_channel_set_cc(chan, PAN_LSB, 0); + + /* Balance (MSB & LSB) */ + fluid_channel_set_cc(chan, BALANCE_MSB, 64); + fluid_channel_set_cc(chan, BALANCE_LSB, 0); + + /* Reverb */ + /* fluid_channel_set_cc (chan, EFFECTS_DEPTH1, 40); */ + /* Note: although XG standard specifies the default amount of reverb to + be 40, most people preferred having it at zero. + See http://lists.gnu.org/archive/html/fluid-dev/2009-07/msg00016.html */ + } } /* Only called by delete_fluid_synth(), so no need to queue a preset free event */ void -delete_fluid_channel(fluid_channel_t* chan) +delete_fluid_channel(fluid_channel_t *chan) { - fluid_return_if_fail(chan != NULL); - - FLUID_FREE(chan); + fluid_return_if_fail(chan != NULL); + + FLUID_FREE(chan); } /* FIXME - Calls fluid_channel_init() potentially in synthesis context */ void -fluid_channel_reset(fluid_channel_t* chan) +fluid_channel_reset(fluid_channel_t *chan) { - fluid_channel_init(chan); - fluid_channel_init_ctrl(chan, 0); + fluid_channel_init(chan); + fluid_channel_init_ctrl(chan, 0); } /* Should only be called from synthesis context */ int -fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset) +fluid_channel_set_preset(fluid_channel_t *chan, fluid_preset_t *preset) { - fluid_sfont_t *sfont; + fluid_sfont_t *sfont; - if (chan->preset == preset) - { - return FLUID_OK; - } + if(chan->preset == preset) + { + return FLUID_OK; + } - if (chan->preset) { - sfont = chan->preset->sfont; - sfont->refcount--; - } + if(chan->preset) + { + sfont = chan->preset->sfont; + sfont->refcount--; + } - fluid_preset_notify (chan->preset, FLUID_PRESET_UNSELECTED, chan->channum); + fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum); - chan->preset = preset; + chan->preset = preset; - if (preset) { - sfont = preset->sfont; - sfont->refcount++; - } + if(preset) + { + sfont = preset->sfont; + sfont->refcount++; + } - fluid_preset_notify (preset, FLUID_PRESET_SELECTED, chan->channum); + fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum); - return FLUID_OK; + return FLUID_OK; } /* Set SoundFont ID, MIDI bank and/or program. Use -1 to use current value. */ void -fluid_channel_set_sfont_bank_prog(fluid_channel_t* chan, int sfontnum, +fluid_channel_set_sfont_bank_prog(fluid_channel_t *chan, int sfontnum, int banknum, int prognum) { - int oldval, newval, oldmask; + int oldval, newval, oldmask; - newval = ((sfontnum != -1) ? sfontnum << SFONT_SHIFTVAL : 0) - | ((banknum != -1) ? banknum << BANK_SHIFTVAL : 0) - | ((prognum != -1) ? prognum << PROG_SHIFTVAL : 0); + newval = ((sfontnum != -1) ? sfontnum << SFONT_SHIFTVAL : 0) + | ((banknum != -1) ? banknum << BANK_SHIFTVAL : 0) + | ((prognum != -1) ? prognum << PROG_SHIFTVAL : 0); - oldmask = ((sfontnum != -1) ? 0 : SFONT_MASKVAL) - | ((banknum != -1) ? 0 : BANK_MASKVAL) - | ((prognum != -1) ? 0 : PROG_MASKVAL); + oldmask = ((sfontnum != -1) ? 0 : SFONT_MASKVAL) + | ((banknum != -1) ? 0 : BANK_MASKVAL) + | ((prognum != -1) ? 0 : PROG_MASKVAL); - oldval = chan->sfont_bank_prog; - newval = (newval & ~oldmask) | (oldval & oldmask); - chan->sfont_bank_prog = newval; + oldval = chan->sfont_bank_prog; + newval = (newval & ~oldmask) | (oldval & oldmask); + chan->sfont_bank_prog = newval; } /* Set bank LSB 7 bits */ void -fluid_channel_set_bank_lsb(fluid_channel_t* chan, int banklsb) +fluid_channel_set_bank_lsb(fluid_channel_t *chan, int banklsb) { - int oldval, newval, style; + int oldval, newval, style; - style = chan->synth->bank_select; - if (style == FLUID_BANK_STYLE_GM || - style == FLUID_BANK_STYLE_GS) - return; /* ignored */ + style = chan->synth->bank_select; - oldval = chan->sfont_bank_prog; - if (style == FLUID_BANK_STYLE_XG) - newval = (oldval & ~BANK_MASKVAL) | (banklsb << BANK_SHIFTVAL); - else /* style == FLUID_BANK_STYLE_MMA */ - newval = (oldval & ~BANKLSB_MASKVAL) | (banklsb << BANK_SHIFTVAL); - chan->sfont_bank_prog = newval; + if(style == FLUID_BANK_STYLE_GM || + style == FLUID_BANK_STYLE_GS) + { + return; /* ignored */ + } + + oldval = chan->sfont_bank_prog; + + if(style == FLUID_BANK_STYLE_XG) + { + newval = (oldval & ~BANK_MASKVAL) | (banklsb << BANK_SHIFTVAL); + } + else /* style == FLUID_BANK_STYLE_MMA */ + { + newval = (oldval & ~BANKLSB_MASKVAL) | (banklsb << BANK_SHIFTVAL); + } + + chan->sfont_bank_prog = newval; } /* Set bank MSB 7 bits */ void -fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb) +fluid_channel_set_bank_msb(fluid_channel_t *chan, int bankmsb) { - int oldval, newval, style; + int oldval, newval, style; - style = chan->synth->bank_select; + style = chan->synth->bank_select; - if (style == FLUID_BANK_STYLE_XG) - { - /* XG bank, do drum-channel auto-switch */ - /* The number "120" was based on several keyboards having drums at 120 - 127, - reference: http://lists.nongnu.org/archive/html/fluid-dev/2011-02/msg00003.html */ - chan->channel_type = (120 <= bankmsb) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC; - return; - } + if(style == FLUID_BANK_STYLE_XG) + { + /* XG bank, do drum-channel auto-switch */ + /* The number "120" was based on several keyboards having drums at 120 - 127, + reference: http://lists.nongnu.org/archive/html/fluid-dev/2011-02/msg00003.html */ + chan->channel_type = (120 <= bankmsb) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC; + return; + } - if (style == FLUID_BANK_STYLE_GM || - chan->channel_type == CHANNEL_TYPE_DRUM) - return; /* ignored */ + if(style == FLUID_BANK_STYLE_GM || + chan->channel_type == CHANNEL_TYPE_DRUM) + { + return; /* ignored */ + } - oldval = chan->sfont_bank_prog; - if (style == FLUID_BANK_STYLE_GS) - newval = (oldval & ~BANK_MASKVAL) | (bankmsb << BANK_SHIFTVAL); - else /* style == FLUID_BANK_STYLE_MMA */ - newval = (oldval & ~BANKMSB_MASKVAL) | (bankmsb << (BANK_SHIFTVAL + 7)); - chan->sfont_bank_prog = newval; + oldval = chan->sfont_bank_prog; + + if(style == FLUID_BANK_STYLE_GS) + { + newval = (oldval & ~BANK_MASKVAL) | (bankmsb << BANK_SHIFTVAL); + } + else /* style == FLUID_BANK_STYLE_MMA */ + { + newval = (oldval & ~BANKMSB_MASKVAL) | (bankmsb << (BANK_SHIFTVAL + 7)); + } + + chan->sfont_bank_prog = newval; } /* Get SoundFont ID, MIDI bank and/or program. Use NULL to ignore a value. */ void -fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont, +fluid_channel_get_sfont_bank_prog(fluid_channel_t *chan, int *sfont, int *bank, int *prog) { - int sfont_bank_prog; + int sfont_bank_prog; - sfont_bank_prog = chan->sfont_bank_prog; + sfont_bank_prog = chan->sfont_bank_prog; - if (sfont) *sfont = (sfont_bank_prog & SFONT_MASKVAL) >> SFONT_SHIFTVAL; - if (bank) *bank = (sfont_bank_prog & BANK_MASKVAL) >> BANK_SHIFTVAL; - if (prog) *prog = (sfont_bank_prog & PROG_MASKVAL) >> PROG_SHIFTVAL; + if(sfont) + { + *sfont = (sfont_bank_prog & SFONT_MASKVAL) >> SFONT_SHIFTVAL; + } + + if(bank) + { + *bank = (sfont_bank_prog & BANK_MASKVAL) >> BANK_SHIFTVAL; + } + + if(prog) + { + *prog = (sfont_bank_prog & PROG_MASKVAL) >> PROG_SHIFTVAL; + } } /** - * Updates legato/ staccato playing state + * Updates legato/ staccato playing state * The function is called: * - on noteon before adding a note into the monolist. * - on noteoff after removing a note out of the monolist. * @param chan fluid_channel_t. */ -static void -fluid_channel_update_legato_staccato_state(fluid_channel_t* chan) +static void +fluid_channel_update_legato_staccato_state(fluid_channel_t *chan) { - /* Updates legato/ staccato playing state */ - if (chan->n_notes) - { - chan->mode |= FLUID_CHANNEL_LEGATO_PLAYING; /* Legato state */ - } - else - { - chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */ - } + /* Updates legato/ staccato playing state */ + if(chan->n_notes) + { + chan->mode |= FLUID_CHANNEL_LEGATO_PLAYING; /* Legato state */ + } + else + { + chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */ + } } /** - * Adds a note into the monophonic list. The function is part of the legato + * Adds a note into the monophonic list. The function is part of the legato * detector. fluid_channel_add_monolist() is intended to be called by * fluid_synth_noteon_mono_LOCAL(). * * When a note is added at noteOn each element is use in the forward direction - * and indexed by i_last variable. + * and indexed by i_last variable. * * @param chan fluid_channel_t. * @param key MIDI note number (0-127). @@ -365,45 +413,51 @@ fluid_channel_update_legato_staccato_state(fluid_channel_t* chan) * Note: i_last index keeps a trace of the most recent note added. * prev_note keeps a trace of the note prior i_last note. * FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing state. - * + * * More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices). */ void -fluid_channel_add_monolist(fluid_channel_t* chan, unsigned char key, - unsigned char vel, unsigned char onenote) +fluid_channel_add_monolist(fluid_channel_t *chan, unsigned char key, + unsigned char vel, unsigned char onenote) { - unsigned char i_last = chan->i_last; - /* Updates legato/ staccato playing state */ - fluid_channel_update_legato_staccato_state(chan); - if (chan->n_notes) - { - /* keeps trace of the note prior last note */ - chan->prev_note = chan->monolist[i_last].note; - } - /* moves i_last forward before writing new note */ - i_last = chan->monolist[i_last].next; - chan->i_last = i_last; /* now ilast indexes the last note */ - chan->monolist[i_last].note = key; /* we save note and velocity */ - chan->monolist[i_last].vel = vel; - if (onenote) - { /* clears monolist before one note addition */ - chan->i_first = i_last; - chan->n_notes = 0; - } - if(chan->n_notes < FLUID_CHANNEL_SIZE_MONOLIST) - { - chan->n_notes++; /* updates n_notes */ - } - else - { /* The end of buffer is reach. So circular motion for i_first */ - /* i_first index is moved forward */ - chan->i_first = chan->monolist[i_last].next; - } + unsigned char i_last = chan->i_last; + /* Updates legato/ staccato playing state */ + fluid_channel_update_legato_staccato_state(chan); + + if(chan->n_notes) + { + /* keeps trace of the note prior last note */ + chan->prev_note = chan->monolist[i_last].note; + } + + /* moves i_last forward before writing new note */ + i_last = chan->monolist[i_last].next; + chan->i_last = i_last; /* now ilast indexes the last note */ + chan->monolist[i_last].note = key; /* we save note and velocity */ + chan->monolist[i_last].vel = vel; + + if(onenote) + { + /* clears monolist before one note addition */ + chan->i_first = i_last; + chan->n_notes = 0; + } + + if(chan->n_notes < FLUID_CHANNEL_SIZE_MONOLIST) + { + chan->n_notes++; /* updates n_notes */ + } + else + { + /* The end of buffer is reach. So circular motion for i_first */ + /* i_first index is moved forward */ + chan->i_first = chan->monolist[i_last].next; + } } /** - * Searching a note in the monophonic list. The function is part of the legato - * detector. fluid_channel_search_monolist() is intended to be called by + * Searching a note in the monophonic list. The function is part of the legato + * detector. fluid_channel_search_monolist() is intended to be called by * fluid_synth_noteoff_mono_LOCAL(). * * The search starts from the first note in the list indexed by i_first @@ -412,49 +466,55 @@ fluid_channel_add_monolist(fluid_channel_t* chan, unsigned char key, * @param key MIDI note number (0-127) to search. * @param i_prev pointer on returned index of the note prior the note to search. * @return index of the note if find, FLUID_FAILED otherwise. - * + * */ int -fluid_channel_search_monolist(fluid_channel_t* chan, unsigned char key , int * i_prev) +fluid_channel_search_monolist(fluid_channel_t *chan, unsigned char key, int *i_prev) { - short n = chan->n_notes; /* number of notes in monophonic list */ - short j,i= chan->i_first; /* searching starts from i_first included */ - for (j=0 ; j < n ; j++) - { - if(chan->monolist[i].note == key) - { - if (i == chan->i_first) - { /* tracking index of the previous note (i_prev) */ - for (j = chan->i_last ; n < FLUID_CHANNEL_SIZE_MONOLIST; n++) - { - j =chan->monolist[j].next; - } - * i_prev = j; /* returns index of the previous note */ - } - return i; /* returns index of the note to search */ - } - * i_prev = i; /* tracking index of the previous note (i_prev) */ - i = chan->monolist[i].next; /* next element */ - } - return FLUID_FAILED; /* not found */ + short n = chan->n_notes; /* number of notes in monophonic list */ + short j, i = chan->i_first; /* searching starts from i_first included */ + + for(j = 0 ; j < n ; j++) + { + if(chan->monolist[i].note == key) + { + if(i == chan->i_first) + { + /* tracking index of the previous note (i_prev) */ + for(j = chan->i_last ; n < FLUID_CHANNEL_SIZE_MONOLIST; n++) + { + j = chan->monolist[j].next; + } + + * i_prev = j; /* returns index of the previous note */ + } + + return i; /* returns index of the note to search */ + } + + * i_prev = i; /* tracking index of the previous note (i_prev) */ + i = chan->monolist[i].next; /* next element */ + } + + return FLUID_FAILED; /* not found */ } /** - * removes a note from the monophonic list. The function is part of - * the legato detector. - * fluid_channel_remove_monolist() is intended to be called by + * removes a note from the monophonic list. The function is part of + * the legato detector. + * fluid_channel_remove_monolist() is intended to be called by * fluid_synth_noteoff_mono_LOCAL(). * * When a note is removed at noteOff the element concerned is fast unlinked * and relinked after the i_last element. * * @param chan fluid_channel_t. - * @param - * i, index of the note to remove. If i is invalid or the list is + * @param + * i, index of the note to remove. If i is invalid or the list is * empty, the function do nothing and returns FLUID_FAILED. - * @param + * @param * On input, i_prev is a pointer on index of the note previous i. - * On output i_prev is a pointer on index of the note previous i if i is the last note + * On output i_prev is a pointer on index of the note previous i if i is the last note * in the list,FLUID_FAILED otherwise. When the returned index is valid it means * a legato detection on noteoff. * @@ -463,49 +523,56 @@ fluid_channel_search_monolist(fluid_channel_t* chan, unsigned char key , int * i * the list is empty. * - prev_note keeps a trace of the note removed if it is i_last. * - FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing state. - * + * * More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices). */ void -fluid_channel_remove_monolist(fluid_channel_t* chan, int i, int * i_prev) +fluid_channel_remove_monolist(fluid_channel_t *chan, int i, int *i_prev) { - unsigned char i_last = chan->i_last; - /* checks if index is valid */ - if( i < 0 || i >= FLUID_CHANNEL_SIZE_MONOLIST || !chan->n_notes) - { - * i_prev = FLUID_FAILED; - } - /* The element is about to be removed and inserted between i_last and next */ - /* Note: when i is egal to i_last or egal to i_first, removing/inserting - isn't necessary */ - if (i == i_last) - { /* Removing/Inserting isn't necessary */ - /* keeps trace of the note prior last note */ - chan->prev_note= chan->monolist[i_last].note; - /* moves i_last backward to the previous */ - chan->i_last = *i_prev; /* i_last index is moved backward */ - } - else - { /* i is before i_last */ - if(i == chan->i_first) - { - /* Removing/inserting isn't necessary */ - /* i_first index is moved forward to the next element*/ - chan->i_first = chan->monolist[i].next; - } - else - { /* i is between i_first and i_last */ - /* Unlinks element i and inserts after i_last */ - chan->monolist[* i_prev].next = chan->monolist[i].next; /* unlinks i */ - /*inserts i after i_last */ - chan->monolist[i].next = chan->monolist[i_last].next; - chan->monolist[i_last].next = i; - } - * i_prev = FLUID_FAILED; - } - chan->n_notes--; /* updates the number of note in the list */ - /* Updates legato/ staccato playing state */ - fluid_channel_update_legato_staccato_state(chan); + unsigned char i_last = chan->i_last; + + /* checks if index is valid */ + if(i < 0 || i >= FLUID_CHANNEL_SIZE_MONOLIST || !chan->n_notes) + { + * i_prev = FLUID_FAILED; + } + + /* The element is about to be removed and inserted between i_last and next */ + /* Note: when i is egal to i_last or egal to i_first, removing/inserting + isn't necessary */ + if(i == i_last) + { + /* Removing/Inserting isn't necessary */ + /* keeps trace of the note prior last note */ + chan->prev_note = chan->monolist[i_last].note; + /* moves i_last backward to the previous */ + chan->i_last = *i_prev; /* i_last index is moved backward */ + } + else + { + /* i is before i_last */ + if(i == chan->i_first) + { + /* Removing/inserting isn't necessary */ + /* i_first index is moved forward to the next element*/ + chan->i_first = chan->monolist[i].next; + } + else + { + /* i is between i_first and i_last */ + /* Unlinks element i and inserts after i_last */ + chan->monolist[* i_prev].next = chan->monolist[i].next; /* unlinks i */ + /*inserts i after i_last */ + chan->monolist[i].next = chan->monolist[i_last].next; + chan->monolist[i_last].next = i; + } + + * i_prev = FLUID_FAILED; + } + + chan->n_notes--; /* updates the number of note in the list */ + /* Updates legato/ staccato playing state */ + fluid_channel_update_legato_staccato_state(chan); } /** @@ -517,41 +584,41 @@ fluid_channel_remove_monolist(fluid_channel_t* chan, int i, int * i_prev) * prev_note keeps a trace of the note i_last . * FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing. */ -void fluid_channel_clear_monolist(fluid_channel_t* chan) +void fluid_channel_clear_monolist(fluid_channel_t *chan) { - /* keeps trace off the most recent note played */ - chan->prev_note= chan->monolist[chan->i_last].note; + /* keeps trace off the most recent note played */ + chan->prev_note = chan->monolist[chan->i_last].note; - /* flushes the monolist */ - chan->i_first = chan->monolist[chan->i_last].next; - chan->n_notes = 0; - /* Update legato/ sataccato playing state */ - chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */ + /* flushes the monolist */ + chan->i_first = chan->monolist[chan->i_last].next; + chan->n_notes = 0; + /* Update legato/ sataccato playing state */ + chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */ } /** * On noteOn on a polyphonic channel,adds the note into the monophonic list * keeping only this note. - * @param + * @param * chan fluid_channel_t. * key, vel, note and velocity added in the monolist * Note: i_last index keeps a trace of the most recent note inserted. * prev_note keeps a trace of the note prior i_last note. * FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing. */ -void fluid_channel_set_onenote_monolist(fluid_channel_t* chan, unsigned char key, - unsigned char vel) +void fluid_channel_set_onenote_monolist(fluid_channel_t *chan, unsigned char key, + unsigned char vel) { - fluid_channel_add_monolist(chan, key, vel,1); + fluid_channel_add_monolist(chan, key, vel, 1); } /** * The function changes the state (Valid/Invalid) of the previous note played in * a staccato manner (fluid_channel_prev_note()). - * When potamento mode 'each note' or 'staccato only' is selected, on next - * noteOn a portamento will be started from the most recent note played + * When potamento mode 'each note' or 'staccato only' is selected, on next + * noteOn a portamento will be started from the most recent note played * staccato. - * It will be possible that it isn't appropriate. To give the musician the + * It will be possible that it isn't appropriate. To give the musician the * possibility to choose a portamento from this note , prev_note will be forced * to invalid state on noteOff if portamento pedal is Off. * @@ -560,16 +627,21 @@ void fluid_channel_set_onenote_monolist(fluid_channel_t* chan, unsigned char key * - On Portamento Off(in poly or mono mode), to mark prev_note invalid. * @param chan fluid_channel_t. */ -void fluid_channel_invalid_prev_note_staccato(fluid_channel_t* chan) +void fluid_channel_invalid_prev_note_staccato(fluid_channel_t *chan) { - /* checks if the playing is staccato */ - if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)) - /* checks if portamento pedal is off */ - if(! fluid_channel_portamento(chan)) - { /* forces prev_note invalid */ - fluid_channel_clear_prev_note(chan); - } - /* else prev_note still remains valid for next fromkey portamento */ + /* checks if the playing is staccato */ + if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)) + { + + /* checks if portamento pedal is off */ + if(! fluid_channel_portamento(chan)) + { + /* forces prev_note invalid */ + fluid_channel_clear_prev_note(chan); + } + } + + /* else prev_note still remains valid for next fromkey portamento */ } /** @@ -577,59 +649,64 @@ void fluid_channel_invalid_prev_note_staccato(fluid_channel_t* chan) * @param chan fluid_channel_t. * @param value, value of the CC legato. */ -void fluid_channel_cc_legato(fluid_channel_t* chan, int value) +void fluid_channel_cc_legato(fluid_channel_t *chan, int value) { - /* Special handling of the monophonic list */ - if (!(chan->mode & FLUID_CHANNEL_POLY_OFF) && chan->n_notes) /* The monophonic list have notes */ - { - if (value < 64 ) /* legato is released */ - { /* returns from monophonic to polyphonic with notes in the monophonic list */ - - /* The monophonic list is flushed keeping last note only - Note: i_last index keeps a trace of the most recent note played. - prev_note keeps a trace of the note i_last. - FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing. - */ - chan->i_first = chan->i_last; - chan->n_notes = 1; - } - else /* legato is depressed */ - { /* Inters in monophonic from polyphonic with note in monophonic list */ - /* Stops the running note to remain coherent with Breath Sync mode */ - if ((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && !fluid_channel_breath_msb(chan)) - { - fluid_synth_noteoff_monopoly(chan->synth,chan->channum, - fluid_channel_last_note(chan),1); - } - } - } + /* Special handling of the monophonic list */ + if(!(chan->mode & FLUID_CHANNEL_POLY_OFF) && chan->n_notes) /* The monophonic list have notes */ + { + if(value < 64) /* legato is released */ + { + /* returns from monophonic to polyphonic with notes in the monophonic list */ + + /* The monophonic list is flushed keeping last note only + Note: i_last index keeps a trace of the most recent note played. + prev_note keeps a trace of the note i_last. + FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing. + */ + chan->i_first = chan->i_last; + chan->n_notes = 1; + } + else /* legato is depressed */ + { + /* Inters in monophonic from polyphonic with note in monophonic list */ + /* Stops the running note to remain coherent with Breath Sync mode */ + if((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && !fluid_channel_breath_msb(chan)) + { + fluid_synth_noteoff_monopoly(chan->synth, chan->channum, + fluid_channel_last_note(chan), 1); + } + } + } } /** - * The function handles CC Breath On/Off detection. When a channel is in + * The function handles CC Breath On/Off detection. When a channel is in * Breath Sync mode and in monophonic playing, the breath controller allows * to trigger noteon/noteoff note when the musician starts to breath (noteon) and * stops to breath (noteoff). * @param chan fluid_channel_t. * @param value, value of the CC Breath.. */ -void fluid_channel_cc_breath_note_on_off(fluid_channel_t* chan, int value) -{ - if ((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && fluid_channel_is_playing_mono(chan) && - (chan->n_notes)) - { - /* The monophonic list isn't empty */ - if((value > 0) && (chan->previous_cc_breath == 0)) - { /* CC Breath On detection */ - fluid_synth_noteon_mono_staccato(chan->synth,chan->channum, - fluid_channel_last_note(chan), - fluid_channel_last_vel(chan)); - } - else if( (value == 0) && (chan->previous_cc_breath > 0)) - { /* CC Breath Off detection */ - fluid_synth_noteoff_monopoly(chan->synth, chan->channum, - fluid_channel_last_note(chan), 1); - } - } - chan->previous_cc_breath = value; +void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value) +{ + if((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && fluid_channel_is_playing_mono(chan) && + (chan->n_notes)) + { + /* The monophonic list isn't empty */ + if((value > 0) && (chan->previous_cc_breath == 0)) + { + /* CC Breath On detection */ + fluid_synth_noteon_mono_staccato(chan->synth, chan->channum, + fluid_channel_last_note(chan), + fluid_channel_last_vel(chan)); + } + else if((value == 0) && (chan->previous_cc_breath > 0)) + { + /* CC Breath Off detection */ + fluid_synth_noteoff_monopoly(chan->synth, chan->channum, + fluid_channel_last_note(chan), 1); + } + } + + chan->previous_cc_breath = value; } diff --git a/src/synth/fluid_chan.h b/src/synth/fluid_chan.h index 6fac7d68..42d73df7 100644 --- a/src/synth/fluid_chan.h +++ b/src/synth/fluid_chan.h @@ -27,8 +27,8 @@ /* The mononophonic list is part of the legato detector for monophonic mode */ /* see fluid_synth_monopoly.c about a description of the legato detector device */ -/* Size of the monophonic list - - 1 is the minimum. it allows playing legato passage of any number +/* Size of the monophonic list + - 1 is the minimum. it allows playing legato passage of any number of notes on noteon only. - Size above 1 allows playing legato on noteon but also on noteOff. This allows the musician to play fast trills. @@ -36,9 +36,9 @@ Choosing a size of 10 is sufficient (because most musicians have only 10 fingers when playing a monophonic instrument). */ -#define FLUID_CHANNEL_SIZE_MONOLIST 10 +#define FLUID_CHANNEL_SIZE_MONOLIST 10 -/* +/* The monophonic list +------------------------------------------------+ @@ -49,14 +49,14 @@ /|\ /|\ | | i_first i_last - + The monophonic list is a circular buffer of FLUID_CHANNEL_SIZE_MONOLIST elements. Each element is linked forward at initialisation time. - when a note is added at noteOn (see fluid_channel_add_monolist()) each - element is use in the forward direction and indexed by i_last variable. + element is use in the forward direction and indexed by i_last variable. - when a note is removed at noteOff (see fluid_channel_remove_monolist()), the element concerned is fast unlinked and relinked after the i_last element. - + The most recent note added is indexed by i_last. The most ancient note added is the first note indexed by i_first. i_first is moving in the forward direction in a circular manner. @@ -77,82 +77,82 @@ struct mononote */ struct _fluid_channel_t { - fluid_synth_t* synth; /**< Parent synthesizer instance */ - int channum; /**< MIDI channel number */ - - /* Poly Mono variables see macro access description */ - int mode; /**< Poly Mono mode */ - int mode_val; /**< number of channel in basic channel group */ - - /* monophonic list - legato detector */ - unsigned char i_first; /**< First note index */ - unsigned char i_last; /**< most recent note index since the most recent add */ - unsigned char prev_note; /**< previous note of the most recent add/remove */ - unsigned char n_notes; /**< actual number of notes in the list */ - struct mononote monolist[FLUID_CHANNEL_SIZE_MONOLIST]; /**< monophonic list */ - - unsigned char key_mono_sustained; /**< previous sustained monophonic note */ - unsigned char previous_cc_breath; /**< Previous Breath */ - enum fluid_channel_legato_mode legatomode; /**< legato mode */ - enum fluid_channel_portamento_mode portamentomode; /**< portamento mode */ - /*- End of Poly/mono variables description */ - - unsigned char cc[128]; /**< MIDI controller values from [0;127] */ - unsigned char key_pressure[128]; /**< MIDI polyphonic key pressure from [0;127] */ - - /* Drum channel flag, CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM. */ - enum fluid_midi_channel_type channel_type; - enum fluid_interp interp_method; /**< Interpolation method (enum fluid_interp) */ + fluid_synth_t *synth; /**< Parent synthesizer instance */ + int channum; /**< MIDI channel number */ - unsigned char channel_pressure; /**< MIDI channel pressure from [0;127] */ - unsigned char pitch_wheel_sensitivity; /**< Current pitch wheel sensitivity */ - short pitch_bend; /**< Current pitch bend value */ - /* Sostenuto order id gives the order of SostenutoOn event. - * This value is useful to known when the sostenuto pedal is depressed - * (before or after a key note). We need to compare SostenutoOrderId with voice id. - */ - unsigned int sostenuto_orderid; - - int tuning_bank; /**< Current tuning bank number */ - int tuning_prog; /**< Current tuning program number */ - fluid_tuning_t* tuning; /**< Micro tuning */ + /* Poly Mono variables see macro access description */ + int mode; /**< Poly Mono mode */ + int mode_val; /**< number of channel in basic channel group */ - fluid_preset_t* preset; /**< Selected preset */ - int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */ - - /* NRPN system */ - enum fluid_gen_type nrpn_select; /* Generator ID of SoundFont NRPN message */ - char nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */ + /* monophonic list - legato detector */ + unsigned char i_first; /**< First note index */ + unsigned char i_last; /**< most recent note index since the most recent add */ + unsigned char prev_note; /**< previous note of the most recent add/remove */ + unsigned char n_notes; /**< actual number of notes in the list */ + struct mononote monolist[FLUID_CHANNEL_SIZE_MONOLIST]; /**< monophonic list */ - /* The values of the generators, set by NRPN messages, or by - * fluid_synth_set_gen(), are cached in the channel so they can be - * applied to future notes. They are copied to a voice's generators - * in fluid_voice_init(), which calls fluid_gen_init(). */ - fluid_real_t gen[GEN_LAST]; + unsigned char key_mono_sustained; /**< previous sustained monophonic note */ + unsigned char previous_cc_breath; /**< Previous Breath */ + enum fluid_channel_legato_mode legatomode; /**< legato mode */ + enum fluid_channel_portamento_mode portamentomode; /**< portamento mode */ + /*- End of Poly/mono variables description */ - /* By default, the NRPN values are relative to the values of the - * generators set in the SoundFont. For example, if the NRPN - * specifies an attack of 100 msec then 100 msec will be added to the - * combined attack time of the sound font and the modulators. - * - * However, it is useful to be able to specify the generator value - * absolutely, completely ignoring the generators of the SoundFont - * and the values of modulators. The gen_abs field, is a boolean - * flag indicating whether the NRPN value is absolute or not. - */ - char gen_abs[GEN_LAST]; + unsigned char cc[128]; /**< MIDI controller values from [0;127] */ + unsigned char key_pressure[128]; /**< MIDI polyphonic key pressure from [0;127] */ + + /* Drum channel flag, CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM. */ + enum fluid_midi_channel_type channel_type; + enum fluid_interp interp_method; /**< Interpolation method (enum fluid_interp) */ + + unsigned char channel_pressure; /**< MIDI channel pressure from [0;127] */ + unsigned char pitch_wheel_sensitivity; /**< Current pitch wheel sensitivity */ + short pitch_bend; /**< Current pitch bend value */ + /* Sostenuto order id gives the order of SostenutoOn event. + * This value is useful to known when the sostenuto pedal is depressed + * (before or after a key note). We need to compare SostenutoOrderId with voice id. + */ + unsigned int sostenuto_orderid; + + int tuning_bank; /**< Current tuning bank number */ + int tuning_prog; /**< Current tuning program number */ + fluid_tuning_t *tuning; /**< Micro tuning */ + + fluid_preset_t *preset; /**< Selected preset */ + int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */ + + /* NRPN system */ + enum fluid_gen_type nrpn_select; /* Generator ID of SoundFont NRPN message */ + char nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */ + + /* The values of the generators, set by NRPN messages, or by + * fluid_synth_set_gen(), are cached in the channel so they can be + * applied to future notes. They are copied to a voice's generators + * in fluid_voice_init(), which calls fluid_gen_init(). */ + fluid_real_t gen[GEN_LAST]; + + /* By default, the NRPN values are relative to the values of the + * generators set in the SoundFont. For example, if the NRPN + * specifies an attack of 100 msec then 100 msec will be added to the + * combined attack time of the sound font and the modulators. + * + * However, it is useful to be able to specify the generator value + * absolutely, completely ignoring the generators of the SoundFont + * and the values of modulators. The gen_abs field, is a boolean + * flag indicating whether the NRPN value is absolute or not. + */ + char gen_abs[GEN_LAST]; }; -fluid_channel_t* new_fluid_channel(fluid_synth_t* synth, int num); -void fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off); -void delete_fluid_channel(fluid_channel_t* chan); -void fluid_channel_reset(fluid_channel_t* chan); -int fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset); -void fluid_channel_set_sfont_bank_prog(fluid_channel_t* chan, int sfont, +fluid_channel_t *new_fluid_channel(fluid_synth_t *synth, int num); +void fluid_channel_init_ctrl(fluid_channel_t *chan, int is_all_ctrl_off); +void delete_fluid_channel(fluid_channel_t *chan); +void fluid_channel_reset(fluid_channel_t *chan); +int fluid_channel_set_preset(fluid_channel_t *chan, fluid_preset_t *preset); +void fluid_channel_set_sfont_bank_prog(fluid_channel_t *chan, int sfont, int bank, int prog); -void fluid_channel_set_bank_lsb(fluid_channel_t* chan, int banklsb); -void fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb); -void fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont, +void fluid_channel_set_bank_lsb(fluid_channel_t *chan, int banklsb); +void fluid_channel_set_bank_msb(fluid_channel_t *chan, int bankmsb); +void fluid_channel_get_sfont_bank_prog(fluid_channel_t *chan, int *sfont, int *bank, int *prog); #define fluid_channel_get_preset(chan) ((chan)->preset) @@ -239,14 +239,14 @@ void fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont, /* Returns the most recent velocity from i_last entry of the monophonic list */ #define fluid_channel_last_vel(chan) (chan->monolist[chan->i_last].vel) -/* - prev_note is used to determine fromkey_portamento as well as +/* + prev_note is used to determine fromkey_portamento as well as fromkey_legato (see fluid_synth_get_fromkey_portamento_legato()). prev_note is updated on noteOn/noteOff mono by the legato detector as this: - On noteOn mono, before adding a new note into the monolist,the most recent note in the list (i.e at i_last position) is kept in prev_note. - - Similarly, on noteOff mono , before removing a note out of the monolist, + - Similarly, on noteOff mono , before removing a note out of the monolist, the most recent note (i.e those at i_last position) is kept in prev_note. */ #define fluid_channel_prev_note(chan) (chan->prev_note) @@ -256,33 +256,33 @@ enum fluid_channel_mode_flags_internal { FLUID_CHANNEL_BASIC = 0x04, /**< if flag set the corresponding midi channel is a basic channel */ FLUID_CHANNEL_ENABLED = 0x08, /**< if flag set the corresponding midi channel is enabled, else disabled, i.e. channel ignores any MIDI messages */ - -/* - FLUID_CHANNEL_LEGATO_PLAYING bit of channel mode keeps trace of the legato /staccato - state playing. - FLUID_CHANNEL_LEGATO_PLAYING bit is updated on noteOn/noteOff mono by the legato detector: - - On noteOn, before inserting a new note into the monolist. - - On noteOff, after removing a note out of the monolist. - - On noteOn, this state is used by fluid_synth_noteon_mono_LOCAL() - to play the current note legato or staccato. - - On noteOff, this state is used by fluid_synth_noteoff_mono_LOCAL() - to play the current noteOff legato with the most recent note. -*/ -/* bit7, 1: means legato playing , 0: means staccato playing */ + /* + FLUID_CHANNEL_LEGATO_PLAYING bit of channel mode keeps trace of the legato /staccato + state playing. + FLUID_CHANNEL_LEGATO_PLAYING bit is updated on noteOn/noteOff mono by the legato detector: + - On noteOn, before inserting a new note into the monolist. + - On noteOff, after removing a note out of the monolist. + + - On noteOn, this state is used by fluid_synth_noteon_mono_LOCAL() + to play the current note legato or staccato. + - On noteOff, this state is used by fluid_synth_noteoff_mono_LOCAL() + to play the current noteOff legato with the most recent note. + */ + /* bit7, 1: means legato playing , 0: means staccato playing */ FLUID_CHANNEL_LEGATO_PLAYING = 0x80 }; /* End of interface to monophonic list variables */ -void fluid_channel_add_monolist(fluid_channel_t* chan, unsigned char key, unsigned char vel, unsigned char onenote); -int fluid_channel_search_monolist(fluid_channel_t* chan, unsigned char key , int * i_prev); -void fluid_channel_remove_monolist(fluid_channel_t* chan, int i, int * i_prev); -void fluid_channel_clear_monolist(fluid_channel_t* chan); -void fluid_channel_set_onenote_monolist(fluid_channel_t* chan, unsigned char key, unsigned char vel); -void fluid_channel_invalid_prev_note_staccato(fluid_channel_t* chan); -void fluid_channel_cc_legato(fluid_channel_t* chan, int value); -void fluid_channel_cc_breath_note_on_off(fluid_channel_t* chan, int value); +void fluid_channel_add_monolist(fluid_channel_t *chan, unsigned char key, unsigned char vel, unsigned char onenote); +int fluid_channel_search_monolist(fluid_channel_t *chan, unsigned char key, int *i_prev); +void fluid_channel_remove_monolist(fluid_channel_t *chan, int i, int *i_prev); +void fluid_channel_clear_monolist(fluid_channel_t *chan); +void fluid_channel_set_onenote_monolist(fluid_channel_t *chan, unsigned char key, unsigned char vel); +void fluid_channel_invalid_prev_note_staccato(fluid_channel_t *chan); +void fluid_channel_cc_legato(fluid_channel_t *chan, int value); +void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value); #endif /* _FLUID_CHAN_H */ diff --git a/src/synth/fluid_event.c b/src/synth/fluid_event.c index 2161e6a9..f7bd11f4 100644 --- a/src/synth/fluid_event.c +++ b/src/synth/fluid_event.c @@ -39,33 +39,36 @@ /* Event alloc/free */ void -fluid_event_clear(fluid_event_t* evt) +fluid_event_clear(fluid_event_t *evt) { - FLUID_MEMSET(evt, 0, sizeof(fluid_event_t)); + FLUID_MEMSET(evt, 0, sizeof(fluid_event_t)); - // by default, no type - evt->dest = -1; - evt->src = -1; - evt->type = -1; + // by default, no type + evt->dest = -1; + evt->src = -1; + evt->type = -1; } /** * Create a new sequencer event structure. * @return New sequencer event structure or NULL if out of memory */ -fluid_event_t* +fluid_event_t * new_fluid_event() { - fluid_event_t* evt; + fluid_event_t *evt; - evt = FLUID_NEW(fluid_event_t); - if (evt == NULL) { - fluid_log(FLUID_PANIC, "event: Out of memory\n"); - return NULL; - } - fluid_event_clear(evt); + evt = FLUID_NEW(fluid_event_t); - return(evt); + if(evt == NULL) + { + fluid_log(FLUID_PANIC, "event: Out of memory\n"); + return NULL; + } + + fluid_event_clear(evt); + + return(evt); } /** @@ -73,11 +76,11 @@ new_fluid_event() * @param evt Sequencer event structure created by new_fluid_event(). */ void -delete_fluid_event(fluid_event_t* evt) +delete_fluid_event(fluid_event_t *evt) { - fluid_return_if_fail(evt != NULL); + fluid_return_if_fail(evt != NULL); - FLUID_FREE(evt); + FLUID_FREE(evt); } /** @@ -87,9 +90,9 @@ delete_fluid_event(fluid_event_t* evt) * @param time Time value to assign */ void -fluid_event_set_time(fluid_event_t* evt, unsigned int time) +fluid_event_set_time(fluid_event_t *evt, unsigned int time) { - evt->time = time; + evt->time = time; } /** @@ -98,9 +101,9 @@ fluid_event_set_time(fluid_event_t* evt, unsigned int time) * @param src Unique sequencer ID */ void -fluid_event_set_source(fluid_event_t* evt, fluid_seq_id_t src) +fluid_event_set_source(fluid_event_t *evt, fluid_seq_id_t src) { - evt->src = src; + evt->src = src; } /** @@ -109,9 +112,9 @@ fluid_event_set_source(fluid_event_t* evt, fluid_seq_id_t src) * @param dest The destination unique sequencer ID */ void -fluid_event_set_dest(fluid_event_t* evt, fluid_seq_id_t dest) +fluid_event_set_dest(fluid_event_t *evt, fluid_seq_id_t dest) { - evt->dest = dest; + evt->dest = dest; } /** @@ -120,10 +123,10 @@ fluid_event_set_dest(fluid_event_t* evt, fluid_seq_id_t dest) * @param data User supplied data pointer */ void -fluid_event_timer(fluid_event_t* evt, void* data) +fluid_event_timer(fluid_event_t *evt, void *data) { - evt->type = FLUID_SEQ_TIMER; - evt->data = data; + evt->type = FLUID_SEQ_TIMER; + evt->data = data; } /** @@ -134,12 +137,12 @@ fluid_event_timer(fluid_event_t* evt, void* data) * @param vel MIDI velocity value (0-127) */ void -fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel) +fluid_event_noteon(fluid_event_t *evt, int channel, short key, short vel) { - evt->type = FLUID_SEQ_NOTEON; - evt->channel = channel; - evt->key = key; - evt->vel = vel; + evt->type = FLUID_SEQ_NOTEON; + evt->channel = channel; + evt->key = key; + evt->vel = vel; } /** @@ -149,11 +152,11 @@ fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel) * @param key MIDI note number (0-127) */ void -fluid_event_noteoff(fluid_event_t* evt, int channel, short key) +fluid_event_noteoff(fluid_event_t *evt, int channel, short key) { - evt->type = FLUID_SEQ_NOTEOFF; - evt->channel = channel; - evt->key = key; + evt->type = FLUID_SEQ_NOTEOFF; + evt->channel = channel; + evt->key = key; } /** @@ -165,13 +168,13 @@ fluid_event_noteoff(fluid_event_t* evt, int channel, short key) * @param duration Duration of note in the time scale used by the sequencer (by default milliseconds) */ void -fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration) +fluid_event_note(fluid_event_t *evt, int channel, short key, short vel, unsigned int duration) { - evt->type = FLUID_SEQ_NOTE; - evt->channel = channel; - evt->key = key; - evt->vel = vel; - evt->duration = duration; + evt->type = FLUID_SEQ_NOTE; + evt->channel = channel; + evt->key = key; + evt->vel = vel; + evt->duration = duration; } /** @@ -180,10 +183,10 @@ fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned * @param channel MIDI channel number */ void -fluid_event_all_sounds_off(fluid_event_t* evt, int channel) +fluid_event_all_sounds_off(fluid_event_t *evt, int channel) { - evt->type = FLUID_SEQ_ALLSOUNDSOFF; - evt->channel = channel; + evt->type = FLUID_SEQ_ALLSOUNDSOFF; + evt->channel = channel; } /** @@ -192,10 +195,10 @@ fluid_event_all_sounds_off(fluid_event_t* evt, int channel) * @param channel MIDI channel number */ void -fluid_event_all_notes_off(fluid_event_t* evt, int channel) +fluid_event_all_notes_off(fluid_event_t *evt, int channel) { - evt->type = FLUID_SEQ_ALLNOTESOFF; - evt->channel = channel; + evt->type = FLUID_SEQ_ALLNOTESOFF; + evt->channel = channel; } /** @@ -205,11 +208,11 @@ fluid_event_all_notes_off(fluid_event_t* evt, int channel) * @param bank_num MIDI bank number (0-16383) */ void -fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num) +fluid_event_bank_select(fluid_event_t *evt, int channel, short bank_num) { - evt->type = FLUID_SEQ_BANKSELECT; - evt->channel = channel; - evt->control = bank_num; + evt->type = FLUID_SEQ_BANKSELECT; + evt->channel = channel; + evt->control = bank_num; } /** @@ -219,11 +222,11 @@ fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num) * @param val MIDI program number (0-127) */ void -fluid_event_program_change(fluid_event_t* evt, int channel, short val) +fluid_event_program_change(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_PROGRAMCHANGE; - evt->channel = channel; - evt->value = val; + evt->type = FLUID_SEQ_PROGRAMCHANGE; + evt->channel = channel; + evt->value = val; } /** @@ -235,14 +238,14 @@ fluid_event_program_change(fluid_event_t* evt, int channel, short val) * @param preset_num MIDI preset number (0-127) */ void -fluid_event_program_select(fluid_event_t* evt, int channel, - unsigned int sfont_id, short bank_num, short preset_num) +fluid_event_program_select(fluid_event_t *evt, int channel, + unsigned int sfont_id, short bank_num, short preset_num) { - evt->type = FLUID_SEQ_PROGRAMSELECT; - evt->channel = channel; - evt->duration = sfont_id; - evt->value = preset_num; - evt->control = bank_num; + evt->type = FLUID_SEQ_PROGRAMSELECT; + evt->channel = channel; + evt->duration = sfont_id; + evt->value = preset_num; + evt->control = bank_num; } /** @@ -251,10 +254,10 @@ fluid_event_program_select(fluid_event_t* evt, int channel, * @param channel MIDI channel number */ void -fluid_event_any_control_change(fluid_event_t* evt, int channel) +fluid_event_any_control_change(fluid_event_t *evt, int channel) { - evt->type = FLUID_SEQ_ANYCONTROLCHANGE; - evt->channel = channel; + evt->type = FLUID_SEQ_ANYCONTROLCHANGE; + evt->channel = channel; } /** @@ -264,13 +267,22 @@ fluid_event_any_control_change(fluid_event_t* evt, int channel) * @param pitch MIDI pitch bend value (0-16383, 8192 = no bend) */ void -fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch) +fluid_event_pitch_bend(fluid_event_t *evt, int channel, int pitch) { - evt->type = FLUID_SEQ_PITCHBEND; - evt->channel = channel; - if (pitch < 0) pitch = 0; - if (pitch > 16383) pitch = 16383; - evt->pitch = pitch; + evt->type = FLUID_SEQ_PITCHBEND; + evt->channel = channel; + + if(pitch < 0) + { + pitch = 0; + } + + if(pitch > 16383) + { + pitch = 16383; + } + + evt->pitch = pitch; } /** @@ -280,11 +292,11 @@ fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch) * @param value MIDI pitch wheel sensitivity value in semitones */ void -fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value) +fluid_event_pitch_wheelsens(fluid_event_t *evt, int channel, short value) { - evt->type = FLUID_SEQ_PITCHWHEELSENS; - evt->channel = channel; - evt->value = value; + evt->type = FLUID_SEQ_PITCHWHEELSENS; + evt->channel = channel; + evt->value = value; } /** @@ -294,13 +306,22 @@ fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value) * @param val MIDI modulation value (0-127) */ void -fluid_event_modulation(fluid_event_t* evt, int channel, short val) +fluid_event_modulation(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_MODULATION; - evt->channel = channel; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->value = val; + evt->type = FLUID_SEQ_MODULATION; + evt->channel = channel; + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->value = val; } /** @@ -310,13 +331,22 @@ fluid_event_modulation(fluid_event_t* evt, int channel, short val) * @param val MIDI sustain value (0-127) */ void -fluid_event_sustain(fluid_event_t* evt, int channel, short val) +fluid_event_sustain(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_SUSTAIN; - evt->channel = channel; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->value = val; + evt->type = FLUID_SEQ_SUSTAIN; + evt->channel = channel; + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->value = val; } /** @@ -327,12 +357,12 @@ fluid_event_sustain(fluid_event_t* evt, int channel, short val) * @param val MIDI control value (0-127) */ void -fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val) +fluid_event_control_change(fluid_event_t *evt, int channel, short control, short val) { - evt->type = FLUID_SEQ_CONTROLCHANGE; - evt->channel = channel; - evt->control = control; - evt->value = val; + evt->type = FLUID_SEQ_CONTROLCHANGE; + evt->channel = channel; + evt->control = control; + evt->value = val; } /** @@ -342,13 +372,22 @@ fluid_event_control_change(fluid_event_t* evt, int channel, short control, short * @param val MIDI panning value (0-127, 0=left, 64 = middle, 127 = right) */ void -fluid_event_pan(fluid_event_t* evt, int channel, short val) +fluid_event_pan(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_PAN; - evt->channel = channel; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->value = val; + evt->type = FLUID_SEQ_PAN; + evt->channel = channel; + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->value = val; } /** @@ -358,13 +397,22 @@ fluid_event_pan(fluid_event_t* evt, int channel, short val) * @param val Volume value (0-127) */ void -fluid_event_volume(fluid_event_t* evt, int channel, short val) +fluid_event_volume(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_VOLUME; - evt->channel = channel; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->value = val; + evt->type = FLUID_SEQ_VOLUME; + evt->channel = channel; + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->value = val; } /** @@ -374,13 +422,22 @@ fluid_event_volume(fluid_event_t* evt, int channel, short val) * @param val Reverb amount (0-127) */ void -fluid_event_reverb_send(fluid_event_t* evt, int channel, short val) +fluid_event_reverb_send(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_REVERBSEND; - evt->channel = channel; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->value = val; + evt->type = FLUID_SEQ_REVERBSEND; + evt->channel = channel; + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->value = val; } /** @@ -390,13 +447,22 @@ fluid_event_reverb_send(fluid_event_t* evt, int channel, short val) * @param val Chorus amount (0-127) */ void -fluid_event_chorus_send(fluid_event_t* evt, int channel, short val) +fluid_event_chorus_send(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_CHORUSSEND; - evt->channel = channel; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->value = val; + evt->type = FLUID_SEQ_CHORUSSEND; + evt->channel = channel; + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->value = val; } @@ -406,9 +472,9 @@ fluid_event_chorus_send(fluid_event_t* evt, int channel, short val) * @since 1.1.0 */ void -fluid_event_unregistering(fluid_event_t* evt) +fluid_event_unregistering(fluid_event_t *evt) { - evt->type = FLUID_SEQ_UNREGISTERING; + evt->type = FLUID_SEQ_UNREGISTERING; } /** @@ -418,14 +484,23 @@ fluid_event_unregistering(fluid_event_t* evt) * @param val Aftertouch amount (0-127) * @since 1.1.0 */ -void -fluid_event_channel_pressure(fluid_event_t* evt, int channel, short val) +void +fluid_event_channel_pressure(fluid_event_t *evt, int channel, short val) { - evt->type = FLUID_SEQ_CHANNELPRESSURE; - evt->channel = channel; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->value = val; + evt->type = FLUID_SEQ_CHANNELPRESSURE; + evt->channel = channel; + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->value = val; } /** @@ -437,16 +512,33 @@ fluid_event_channel_pressure(fluid_event_t* evt, int channel, short val) * @since 2.0.0 */ void -fluid_event_key_pressure(fluid_event_t* evt, int channel, short key, short val) +fluid_event_key_pressure(fluid_event_t *evt, int channel, short key, short val) { - evt->type = FLUID_SEQ_KEYPRESSURE; - evt->channel = channel; - if (key < 0) key = 0; - if (key > 127) key = 127; - if (val < 0) val = 0; - if (val > 127) val = 127; - evt->key = key; - evt->value = val; + evt->type = FLUID_SEQ_KEYPRESSURE; + evt->channel = channel; + + if(key < 0) + { + key = 0; + } + + if(key > 127) + { + key = 127; + } + + if(val < 0) + { + val = 0; + } + + if(val > 127) + { + val = 127; + } + + evt->key = key; + evt->value = val; } /** @@ -454,10 +546,10 @@ fluid_event_key_pressure(fluid_event_t* evt, int channel, short key, short val) * @param evt Sequencer event structure * @since 1.1.0 */ -void -fluid_event_system_reset(fluid_event_t* evt) +void +fluid_event_system_reset(fluid_event_t *evt) { - evt->type = FLUID_SEQ_SYSTEMRESET; + evt->type = FLUID_SEQ_SYSTEMRESET; } @@ -471,9 +563,9 @@ fluid_event_system_reset(fluid_event_t* evt) * @param evt Sequencer event structure * @return Event type (#fluid_seq_event_type). */ -int fluid_event_get_type(fluid_event_t* evt) +int fluid_event_get_type(fluid_event_t *evt) { - return evt->type; + return evt->type; } /** @@ -482,9 +574,9 @@ int fluid_event_get_type(fluid_event_t* evt) * @param evt Sequencer event structure * @return Time value */ -unsigned int fluid_event_get_time(fluid_event_t* evt) +unsigned int fluid_event_get_time(fluid_event_t *evt) { - return evt->time; + return evt->time; } /** @@ -492,9 +584,9 @@ unsigned int fluid_event_get_time(fluid_event_t* evt) * @param evt Sequencer event structure * @return source field of the sequencer event */ -fluid_seq_id_t fluid_event_get_source(fluid_event_t* evt) +fluid_seq_id_t fluid_event_get_source(fluid_event_t *evt) { - return evt->src; + return evt->src; } /** @@ -502,9 +594,9 @@ fluid_seq_id_t fluid_event_get_source(fluid_event_t* evt) * @param evt Sequencer event structure * @return dest field of the sequencer event */ -fluid_seq_id_t fluid_event_get_dest(fluid_event_t* evt) +fluid_seq_id_t fluid_event_get_dest(fluid_event_t *evt) { - return evt->dest; + return evt->dest; } /** @@ -512,9 +604,9 @@ fluid_seq_id_t fluid_event_get_dest(fluid_event_t* evt) * @param evt Sequencer event structure * @return MIDI zero-based channel number */ -int fluid_event_get_channel(fluid_event_t* evt) +int fluid_event_get_channel(fluid_event_t *evt) { - return evt->channel; + return evt->channel; } /** @@ -522,9 +614,9 @@ int fluid_event_get_channel(fluid_event_t* evt) * @param evt Sequencer event structure * @return MIDI note number (0-127) */ -short fluid_event_get_key(fluid_event_t* evt) +short fluid_event_get_key(fluid_event_t *evt) { - return evt->key; + return evt->key; } /** @@ -532,10 +624,10 @@ short fluid_event_get_key(fluid_event_t* evt) * @param evt Sequencer event structure * @return MIDI velocity value (0-127) */ -short fluid_event_get_velocity(fluid_event_t* evt) +short fluid_event_get_velocity(fluid_event_t *evt) { - return evt->vel; + return evt->vel; } /** @@ -543,9 +635,9 @@ short fluid_event_get_velocity(fluid_event_t* evt) * @param evt Sequencer event structure * @return MIDI control number (0-127) */ -short fluid_event_get_control(fluid_event_t* evt) +short fluid_event_get_control(fluid_event_t *evt) { - return evt->control; + return evt->control; } /** @@ -559,9 +651,9 @@ short fluid_event_get_control(fluid_event_t* evt) * #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME, * #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND. */ -short fluid_event_get_value(fluid_event_t* evt) +short fluid_event_get_value(fluid_event_t *evt) { - return evt->value; + return evt->value; } /** @@ -571,9 +663,9 @@ short fluid_event_get_value(fluid_event_t* evt) * * Used by the #FLUID_SEQ_TIMER event type. */ -void* fluid_event_get_data(fluid_event_t* evt) +void *fluid_event_get_data(fluid_event_t *evt) { - return evt->data; + return evt->data; } /** @@ -583,9 +675,9 @@ void* fluid_event_get_data(fluid_event_t* evt) * * Used by the #FLUID_SEQ_NOTE event type. */ -unsigned int fluid_event_get_duration(fluid_event_t* evt) +unsigned int fluid_event_get_duration(fluid_event_t *evt) { - return evt->duration; + return evt->duration; } /** @@ -596,9 +688,9 @@ unsigned int fluid_event_get_duration(fluid_event_t* evt) * Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT * event types. */ -short fluid_event_get_bank(fluid_event_t* evt) +short fluid_event_get_bank(fluid_event_t *evt) { - return evt->control; + return evt->control; } /** @@ -608,9 +700,9 @@ short fluid_event_get_bank(fluid_event_t* evt) * * Used by the #FLUID_SEQ_PITCHBEND event type. */ -int fluid_event_get_pitch(fluid_event_t* evt) +int fluid_event_get_pitch(fluid_event_t *evt) { - return evt->pitch; + return evt->pitch; } /** @@ -622,9 +714,9 @@ int fluid_event_get_pitch(fluid_event_t* evt) * event types. */ short -fluid_event_get_program(fluid_event_t* evt) +fluid_event_get_program(fluid_event_t *evt) { - return evt->value; + return evt->value; } /** @@ -635,9 +727,9 @@ fluid_event_get_program(fluid_event_t* evt) * Used by the #FLUID_SEQ_PROGRAMSELECT event type. */ unsigned int -fluid_event_get_sfont_id(fluid_event_t* evt) +fluid_event_get_sfont_id(fluid_event_t *evt) { - return evt->duration; + return evt->duration; } @@ -646,154 +738,176 @@ fluid_event_get_sfont_id(fluid_event_t* evt) /* heap management */ /********************/ -fluid_evt_heap_t* +fluid_evt_heap_t * _fluid_evt_heap_init(int nbEvents) { #ifdef HEAP_WITH_DYNALLOC - int i; - fluid_evt_heap_t* heap; - fluid_evt_entry *tmp; + int i; + fluid_evt_heap_t *heap; + fluid_evt_entry *tmp; - heap = FLUID_NEW(fluid_evt_heap_t); - if (heap == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return NULL; - } + heap = FLUID_NEW(fluid_evt_heap_t); - heap->freelist = NULL; - fluid_mutex_init(heap->mutex); + if(heap == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return NULL; + } - /* LOCK */ - fluid_mutex_lock(heap->mutex); + heap->freelist = NULL; + fluid_mutex_init(heap->mutex); - /* Allocate the event entries */ - for (i = 0; i < nbEvents; i++) { - tmp = FLUID_NEW(fluid_evt_entry); - tmp->next = heap->freelist; - heap->freelist = tmp; - } + /* LOCK */ + fluid_mutex_lock(heap->mutex); - /* UNLOCK */ - fluid_mutex_unlock(heap->mutex); + /* Allocate the event entries */ + for(i = 0; i < nbEvents; i++) + { + tmp = FLUID_NEW(fluid_evt_entry); + tmp->next = heap->freelist; + heap->freelist = tmp; + } + + /* UNLOCK */ + fluid_mutex_unlock(heap->mutex); #else - int i; - fluid_evt_heap_t* heap; - int siz = 2*sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry)*nbEvents; + int i; + fluid_evt_heap_t *heap; + int siz = 2 * sizeof(fluid_evt_entry *) + sizeof(fluid_evt_entry) * nbEvents; - heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz); - if (heap == NULL) { - fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return NULL; - } - FLUID_MEMSET(heap, 0, siz); + heap = (fluid_evt_heap_t *)FLUID_MALLOC(siz); - /* link all heap events */ - { - fluid_evt_entry *tmp = &(heap->pool); - for (i = 0 ; i < nbEvents - 1 ; i++) - tmp[i].next = &(tmp[i+1]); - tmp[nbEvents-1].next = NULL; + if(heap == NULL) + { + fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); + return NULL; + } - /* set head & tail */ - heap->tail = &(tmp[nbEvents-1]); - heap->head = &(heap->pool); - } + FLUID_MEMSET(heap, 0, siz); + + /* link all heap events */ + { + fluid_evt_entry *tmp = &(heap->pool); + + for(i = 0 ; i < nbEvents - 1 ; i++) + { + tmp[i].next = &(tmp[i + 1]); + } + + tmp[nbEvents - 1].next = NULL; + + /* set head & tail */ + heap->tail = &(tmp[nbEvents - 1]); + heap->head = &(heap->pool); + } #endif - return (heap); + return (heap); } void -_fluid_evt_heap_free(fluid_evt_heap_t* heap) +_fluid_evt_heap_free(fluid_evt_heap_t *heap) { #ifdef HEAP_WITH_DYNALLOC - fluid_evt_entry *tmp, *next; + fluid_evt_entry *tmp, *next; - /* LOCK */ - fluid_mutex_lock(heap->mutex); + /* LOCK */ + fluid_mutex_lock(heap->mutex); - tmp = heap->freelist; - while (tmp) { - next = tmp->next; - FLUID_FREE(tmp); - tmp = next; - } + tmp = heap->freelist; - /* UNLOCK */ - fluid_mutex_unlock(heap->mutex); - fluid_mutex_destroy(heap->mutex); + while(tmp) + { + next = tmp->next; + FLUID_FREE(tmp); + tmp = next; + } - FLUID_FREE(heap); + /* UNLOCK */ + fluid_mutex_unlock(heap->mutex); + fluid_mutex_destroy(heap->mutex); + + FLUID_FREE(heap); #else - FLUID_FREE(heap); + FLUID_FREE(heap); #endif } -fluid_evt_entry* -_fluid_seq_heap_get_free(fluid_evt_heap_t* heap) +fluid_evt_entry * +_fluid_seq_heap_get_free(fluid_evt_heap_t *heap) { #ifdef HEAP_WITH_DYNALLOC - fluid_evt_entry* evt = NULL; + fluid_evt_entry *evt = NULL; - /* LOCK */ - fluid_mutex_lock(heap->mutex); + /* LOCK */ + fluid_mutex_lock(heap->mutex); #if !defined(MACOS9) - if (heap->freelist == NULL) { - heap->freelist = FLUID_NEW(fluid_evt_entry); - if (heap->freelist != NULL) { - heap->freelist->next = NULL; + + if(heap->freelist == NULL) + { + heap->freelist = FLUID_NEW(fluid_evt_entry); + + if(heap->freelist != NULL) + { + heap->freelist->next = NULL; + } } - } + #endif - evt = heap->freelist; + evt = heap->freelist; - if (evt != NULL) { - heap->freelist = heap->freelist->next; - evt->next = NULL; - } + if(evt != NULL) + { + heap->freelist = heap->freelist->next; + evt->next = NULL; + } - /* UNLOCK */ - fluid_mutex_unlock(heap->mutex); + /* UNLOCK */ + fluid_mutex_unlock(heap->mutex); - return evt; + return evt; #else - fluid_evt_entry* evt; - if (heap->head == NULL) return NULL; + fluid_evt_entry *evt; - /* take from head of the heap */ - /* critical - should threadlock ? */ - evt = heap->head; - heap->head = heap->head->next; + if(heap->head == NULL) + { + return NULL; + } - return evt; + /* take from head of the heap */ + /* critical - should threadlock ? */ + evt = heap->head; + heap->head = heap->head->next; + + return evt; #endif } void -_fluid_seq_heap_set_free(fluid_evt_heap_t* heap, fluid_evt_entry* evt) +_fluid_seq_heap_set_free(fluid_evt_heap_t *heap, fluid_evt_entry *evt) { #ifdef HEAP_WITH_DYNALLOC - /* LOCK */ - fluid_mutex_lock(heap->mutex); + /* LOCK */ + fluid_mutex_lock(heap->mutex); - evt->next = heap->freelist; - heap->freelist = evt; + evt->next = heap->freelist; + heap->freelist = evt; - /* UNLOCK */ - fluid_mutex_unlock(heap->mutex); + /* UNLOCK */ + fluid_mutex_unlock(heap->mutex); #else - /* append to the end of the heap */ - /* critical - should threadlock ? */ - heap->tail->next = evt; - heap->tail = evt; - evt->next = NULL; + /* append to the end of the heap */ + /* critical - should threadlock ? */ + heap->tail->next = evt; + heap->tail = evt; + evt->next = NULL; #endif } diff --git a/src/synth/fluid_event_priv.h b/src/synth/fluid_event_priv.h index 87a0d755..4beb0147 100644 --- a/src/synth/fluid_event_priv.h +++ b/src/synth/fluid_event_priv.h @@ -27,57 +27,61 @@ /* Private data for event */ /* ?? should be optimized in size, using unions */ -struct _fluid_event_t { - unsigned int time; - int type; - fluid_seq_id_t src; - fluid_seq_id_t dest; - int channel; - short key; - short vel; - short control; - short value; - short id; //?? unused ? - int pitch; - unsigned int duration; - void* data; +struct _fluid_event_t +{ + unsigned int time; + int type; + fluid_seq_id_t src; + fluid_seq_id_t dest; + int channel; + short key; + short vel; + short control; + short value; + short id; //?? unused ? + int pitch; + unsigned int duration; + void *data; }; -unsigned int fluid_event_get_time(fluid_event_t* evt); -void fluid_event_set_time(fluid_event_t* evt, unsigned int time); +unsigned int fluid_event_get_time(fluid_event_t *evt); +void fluid_event_set_time(fluid_event_t *evt, unsigned int time); -void fluid_event_clear(fluid_event_t* evt); +void fluid_event_clear(fluid_event_t *evt); /* private data for sorter + heap */ -enum fluid_evt_entry_type { - FLUID_EVT_ENTRY_INSERT = 0, - FLUID_EVT_ENTRY_REMOVE +enum fluid_evt_entry_type +{ + FLUID_EVT_ENTRY_INSERT = 0, + FLUID_EVT_ENTRY_REMOVE }; typedef struct _fluid_evt_entry fluid_evt_entry; -struct _fluid_evt_entry { - fluid_evt_entry *next; - short entryType; - fluid_event_t evt; +struct _fluid_evt_entry +{ + fluid_evt_entry *next; + short entryType; + fluid_event_t evt; }; #define HEAP_WITH_DYNALLOC 1 /* #undef HEAP_WITH_DYNALLOC */ -typedef struct _fluid_evt_heap_t { +typedef struct _fluid_evt_heap_t +{ #ifdef HEAP_WITH_DYNALLOC - fluid_evt_entry* freelist; - fluid_mutex_t mutex; + fluid_evt_entry *freelist; + fluid_mutex_t mutex; #else - fluid_evt_entry* head; - fluid_evt_entry* tail; - fluid_evt_entry pool; + fluid_evt_entry *head; + fluid_evt_entry *tail; + fluid_evt_entry pool; #endif } fluid_evt_heap_t; -fluid_evt_heap_t* _fluid_evt_heap_init(int nbEvents); -void _fluid_evt_heap_free(fluid_evt_heap_t* heap); -fluid_evt_entry* _fluid_seq_heap_get_free(fluid_evt_heap_t* heap); -void _fluid_seq_heap_set_free(fluid_evt_heap_t* heap, fluid_evt_entry* evt); +fluid_evt_heap_t *_fluid_evt_heap_init(int nbEvents); +void _fluid_evt_heap_free(fluid_evt_heap_t *heap); +fluid_evt_entry *_fluid_seq_heap_get_free(fluid_evt_heap_t *heap); +void _fluid_seq_heap_set_free(fluid_evt_heap_t *heap, fluid_evt_entry *evt); #endif /* _FLUID_EVENT_PRIV_H */ diff --git a/src/synth/fluid_gen.c b/src/synth/fluid_gen.c index 275ac3f3..f01f9419 100644 --- a/src/synth/fluid_gen.c +++ b/src/synth/fluid_gen.c @@ -24,71 +24,72 @@ /* See SFSpec21 $8.1.3 */ -static const fluid_gen_info_t fluid_gen_info[] = { - /* number/name init scale min max def */ - { GEN_STARTADDROFS, 1, 1, 0.0f, 1e10f, 0.0f }, - { GEN_ENDADDROFS, 1, 1, -1e10f, 0.0f, 0.0f }, - { GEN_STARTLOOPADDROFS, 1, 1, -1e10f, 1e10f, 0.0f }, - { GEN_ENDLOOPADDROFS, 1, 1, -1e10f, 1e10f, 0.0f }, - { GEN_STARTADDRCOARSEOFS, 0, 1, 0.0f, 1e10f, 0.0f }, - { GEN_MODLFOTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f }, - { GEN_VIBLFOTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f }, - { GEN_MODENVTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f }, - { GEN_FILTERFC, 1, 2, 1500.0f, 13500.0f, 13500.0f }, - { GEN_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f }, - { GEN_MODLFOTOFILTERFC, 1, 2, -12000.0f, 12000.0f, 0.0f }, - { GEN_MODENVTOFILTERFC, 1, 2, -12000.0f, 12000.0f, 0.0f }, - { GEN_ENDADDRCOARSEOFS, 0, 1, -1e10f, 0.0f, 0.0f }, - { GEN_MODLFOTOVOL, 1, 1, -960.0f, 960.0f, 0.0f }, - { GEN_UNUSED1, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_CHORUSSEND, 1, 1, 0.0f, 1000.0f, 0.0f }, - { GEN_REVERBSEND, 1, 1, 0.0f, 1000.0f, 0.0f }, - { GEN_PAN, 1, 1, -500.0f, 500.0f, 0.0f }, - { GEN_UNUSED2, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_UNUSED3, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_UNUSED4, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_MODLFODELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, - { GEN_MODLFOFREQ, 1, 4, -16000.0f, 4500.0f, 0.0f }, - { GEN_VIBLFODELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, - { GEN_VIBLFOFREQ, 1, 4, -16000.0f, 4500.0f, 0.0f }, - { GEN_MODENVDELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, - { GEN_MODENVATTACK, 1, 2, -12000.0f, 8000.0f, -12000.0f }, - { GEN_MODENVHOLD, 1, 2, -12000.0f, 5000.0f, -12000.0f }, - { GEN_MODENVDECAY, 1, 2, -12000.0f, 8000.0f, -12000.0f }, - { GEN_MODENVSUSTAIN, 0, 1, 0.0f, 1000.0f, 0.0f }, - { GEN_MODENVRELEASE, 1, 2, -12000.0f, 8000.0f, -12000.0f }, - { GEN_KEYTOMODENVHOLD, 0, 1, -1200.0f, 1200.0f, 0.0f }, - { GEN_KEYTOMODENVDECAY, 0, 1, -1200.0f, 1200.0f, 0.0f }, - { GEN_VOLENVDELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, - { GEN_VOLENVATTACK, 1, 2, -12000.0f, 8000.0f, -12000.0f }, - { GEN_VOLENVHOLD, 1, 2, -12000.0f, 5000.0f, -12000.0f }, - { GEN_VOLENVDECAY, 1, 2, -12000.0f, 8000.0f, -12000.0f }, - { GEN_VOLENVSUSTAIN, 0, 1, 0.0f, 1440.0f, 0.0f }, - { GEN_VOLENVRELEASE, 1, 2, -12000.0f, 8000.0f, -12000.0f }, - { GEN_KEYTOVOLENVHOLD, 0, 1, -1200.0f, 1200.0f, 0.0f }, - { GEN_KEYTOVOLENVDECAY, 0, 1, -1200.0f, 1200.0f, 0.0f }, - { GEN_INSTRUMENT, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_RESERVED1, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_KEYRANGE, 0, 0, 0.0f, 127.0f, 0.0f }, - { GEN_VELRANGE, 0, 0, 0.0f, 127.0f, 0.0f }, - { GEN_STARTLOOPADDRCOARSEOFS, 0, 1, -1e10f, 1e10f, 0.0f }, - { GEN_KEYNUM, 1, 0, 0.0f, 127.0f, -1.0f }, - { GEN_VELOCITY, 1, 1, 0.0f, 127.0f, -1.0f }, - { GEN_ATTENUATION, 1, 1, 0.0f, 1440.0f, 0.0f }, - { GEN_RESERVED2, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_ENDLOOPADDRCOARSEOFS, 0, 1, -1e10f, 1e10f, 0.0f }, - { GEN_COARSETUNE, 0, 1, -120.0f, 120.0f, 0.0f }, - { GEN_FINETUNE, 0, 1, -99.0f, 99.0f, 0.0f }, - { GEN_SAMPLEID, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_SAMPLEMODE, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_RESERVED3, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_SCALETUNE, 0, 1, 0.0f, 1200.0f, 100.0f }, - { GEN_EXCLUSIVECLASS, 0, 0, 0.0f, 0.0f, 0.0f }, - { GEN_OVERRIDEROOTKEY, 1, 0, 0.0f, 127.0f, -1.0f }, - { GEN_PITCH, 1, 0, 0.0f, 127.0f, 0.0f }, - { GEN_CUSTOM_BALANCE, 1, 0, -960.0f, 960.0f, 0.0f }, - { GEN_CUSTOM_FILTERFC, 1, 2, 0.0f, 22050.0f, 0.0f }, - { GEN_CUSTOM_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f } +static const fluid_gen_info_t fluid_gen_info[] = +{ + /* number/name init scale min max def */ + { GEN_STARTADDROFS, 1, 1, 0.0f, 1e10f, 0.0f }, + { GEN_ENDADDROFS, 1, 1, -1e10f, 0.0f, 0.0f }, + { GEN_STARTLOOPADDROFS, 1, 1, -1e10f, 1e10f, 0.0f }, + { GEN_ENDLOOPADDROFS, 1, 1, -1e10f, 1e10f, 0.0f }, + { GEN_STARTADDRCOARSEOFS, 0, 1, 0.0f, 1e10f, 0.0f }, + { GEN_MODLFOTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f }, + { GEN_VIBLFOTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f }, + { GEN_MODENVTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f }, + { GEN_FILTERFC, 1, 2, 1500.0f, 13500.0f, 13500.0f }, + { GEN_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f }, + { GEN_MODLFOTOFILTERFC, 1, 2, -12000.0f, 12000.0f, 0.0f }, + { GEN_MODENVTOFILTERFC, 1, 2, -12000.0f, 12000.0f, 0.0f }, + { GEN_ENDADDRCOARSEOFS, 0, 1, -1e10f, 0.0f, 0.0f }, + { GEN_MODLFOTOVOL, 1, 1, -960.0f, 960.0f, 0.0f }, + { GEN_UNUSED1, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_CHORUSSEND, 1, 1, 0.0f, 1000.0f, 0.0f }, + { GEN_REVERBSEND, 1, 1, 0.0f, 1000.0f, 0.0f }, + { GEN_PAN, 1, 1, -500.0f, 500.0f, 0.0f }, + { GEN_UNUSED2, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_UNUSED3, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_UNUSED4, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_MODLFODELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, + { GEN_MODLFOFREQ, 1, 4, -16000.0f, 4500.0f, 0.0f }, + { GEN_VIBLFODELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, + { GEN_VIBLFOFREQ, 1, 4, -16000.0f, 4500.0f, 0.0f }, + { GEN_MODENVDELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, + { GEN_MODENVATTACK, 1, 2, -12000.0f, 8000.0f, -12000.0f }, + { GEN_MODENVHOLD, 1, 2, -12000.0f, 5000.0f, -12000.0f }, + { GEN_MODENVDECAY, 1, 2, -12000.0f, 8000.0f, -12000.0f }, + { GEN_MODENVSUSTAIN, 0, 1, 0.0f, 1000.0f, 0.0f }, + { GEN_MODENVRELEASE, 1, 2, -12000.0f, 8000.0f, -12000.0f }, + { GEN_KEYTOMODENVHOLD, 0, 1, -1200.0f, 1200.0f, 0.0f }, + { GEN_KEYTOMODENVDECAY, 0, 1, -1200.0f, 1200.0f, 0.0f }, + { GEN_VOLENVDELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f }, + { GEN_VOLENVATTACK, 1, 2, -12000.0f, 8000.0f, -12000.0f }, + { GEN_VOLENVHOLD, 1, 2, -12000.0f, 5000.0f, -12000.0f }, + { GEN_VOLENVDECAY, 1, 2, -12000.0f, 8000.0f, -12000.0f }, + { GEN_VOLENVSUSTAIN, 0, 1, 0.0f, 1440.0f, 0.0f }, + { GEN_VOLENVRELEASE, 1, 2, -12000.0f, 8000.0f, -12000.0f }, + { GEN_KEYTOVOLENVHOLD, 0, 1, -1200.0f, 1200.0f, 0.0f }, + { GEN_KEYTOVOLENVDECAY, 0, 1, -1200.0f, 1200.0f, 0.0f }, + { GEN_INSTRUMENT, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_RESERVED1, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_KEYRANGE, 0, 0, 0.0f, 127.0f, 0.0f }, + { GEN_VELRANGE, 0, 0, 0.0f, 127.0f, 0.0f }, + { GEN_STARTLOOPADDRCOARSEOFS, 0, 1, -1e10f, 1e10f, 0.0f }, + { GEN_KEYNUM, 1, 0, 0.0f, 127.0f, -1.0f }, + { GEN_VELOCITY, 1, 1, 0.0f, 127.0f, -1.0f }, + { GEN_ATTENUATION, 1, 1, 0.0f, 1440.0f, 0.0f }, + { GEN_RESERVED2, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_ENDLOOPADDRCOARSEOFS, 0, 1, -1e10f, 1e10f, 0.0f }, + { GEN_COARSETUNE, 0, 1, -120.0f, 120.0f, 0.0f }, + { GEN_FINETUNE, 0, 1, -99.0f, 99.0f, 0.0f }, + { GEN_SAMPLEID, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_SAMPLEMODE, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_RESERVED3, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_SCALETUNE, 0, 1, 0.0f, 1200.0f, 100.0f }, + { GEN_EXCLUSIVECLASS, 0, 0, 0.0f, 0.0f, 0.0f }, + { GEN_OVERRIDEROOTKEY, 1, 0, 0.0f, 127.0f, -1.0f }, + { GEN_PITCH, 1, 0, 0.0f, 127.0f, 0.0f }, + { GEN_CUSTOM_BALANCE, 1, 0, -960.0f, 960.0f, 0.0f }, + { GEN_CUSTOM_FILTERFC, 1, 2, 0.0f, 22050.0f, 0.0f }, + { GEN_CUSTOM_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f } }; @@ -98,18 +99,19 @@ static const fluid_gen_info_t fluid_gen_info[] = { * @return Always returns #FLUID_OK */ int -fluid_gen_set_default_values(fluid_gen_t* gen) +fluid_gen_set_default_values(fluid_gen_t *gen) { - int i; + int i; - for (i = 0; i < GEN_LAST; i++) { - gen[i].flags = GEN_UNUSED; - gen[i].mod = 0.0; - gen[i].nrpn = 0.0; - gen[i].val = fluid_gen_info[i].def; - } + for(i = 0; i < GEN_LAST; i++) + { + gen[i].flags = GEN_UNUSED; + gen[i].mod = 0.0; + gen[i].nrpn = 0.0; + gen[i].val = fluid_gen_info[i].def; + } - return FLUID_OK; + return FLUID_OK; } @@ -118,35 +120,37 @@ fluid_gen_set_default_values(fluid_gen_t* gen) * Set an array of generators to their initial value */ int -fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel) +fluid_gen_init(fluid_gen_t *gen, fluid_channel_t *channel) { - int i; + int i; - fluid_gen_set_default_values(gen); + fluid_gen_set_default_values(gen); - for (i = 0; i < GEN_LAST; i++) { - gen[i].nrpn = fluid_channel_get_gen(channel, i); + for(i = 0; i < GEN_LAST; i++) + { + gen[i].nrpn = fluid_channel_get_gen(channel, i); - /* This is an extension to the SoundFont standard. More - * documentation is available at the fluid_synth_set_gen2() - * function. */ - if (fluid_channel_get_gen_abs(channel, i)) { - gen[i].flags = GEN_ABS_NRPN; - } - } + /* This is an extension to the SoundFont standard. More + * documentation is available at the fluid_synth_set_gen2() + * function. */ + if(fluid_channel_get_gen_abs(channel, i)) + { + gen[i].flags = GEN_ABS_NRPN; + } + } - return FLUID_OK; + return FLUID_OK; } fluid_real_t fluid_gen_scale(int gen, float value) { - return (fluid_gen_info[gen].min - + value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min)); + return (fluid_gen_info[gen].min + + value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min)); } fluid_real_t fluid_gen_scale_nrpn(int gen, int data) { - fluid_real_t value = (float) data - 8192.0f; - fluid_clip(value, -8192, 8192); - return value * (float) fluid_gen_info[gen].nrpn_scale; + fluid_real_t value = (float) data - 8192.0f; + fluid_clip(value, -8192, 8192); + return value * (float) fluid_gen_info[gen].nrpn_scale; } diff --git a/src/synth/fluid_gen.h b/src/synth/fluid_gen.h index aa930672..d156b807 100644 --- a/src/synth/fluid_gen.h +++ b/src/synth/fluid_gen.h @@ -24,13 +24,14 @@ #include "fluidsynth_priv.h" -typedef struct _fluid_gen_info_t { - char num; /* Generator number */ - char init; /* Does the generator need to be initialized (cfr. fluid_voice_init()) */ - char nrpn_scale; /* The scale to convert from NRPN (cfr. fluid_gen_map_nrpn()) */ - float min; /* The minimum value */ - float max; /* The maximum value */ - float def; /* The default value (cfr. fluid_gen_set_default_values()) */ +typedef struct _fluid_gen_info_t +{ + char num; /* Generator number */ + char init; /* Does the generator need to be initialized (cfr. fluid_voice_init()) */ + char nrpn_scale; /* The scale to convert from NRPN (cfr. fluid_gen_map_nrpn()) */ + float min; /* The minimum value */ + float max; /* The maximum value */ + float def; /* The default value (cfr. fluid_gen_set_default_values()) */ } fluid_gen_info_t; /* @@ -38,10 +39,10 @@ typedef struct _fluid_gen_info_t { */ typedef struct _fluid_gen_t { - unsigned char flags; /**< Is the generator set or not (#fluid_gen_flags) */ - double val; /**< The nominal value */ - double mod; /**< Change by modulators */ - double nrpn; /**< Change by NRPN messages */ + unsigned char flags; /**< Is the generator set or not (#fluid_gen_flags) */ + double val; /**< The nominal value */ + double mod; /**< Change by modulators */ + double nrpn; /**< Change by NRPN messages */ } fluid_gen_t; /* @@ -49,9 +50,9 @@ typedef struct _fluid_gen_t */ enum fluid_gen_flags { - GEN_UNUSED, /**< Generator value is not set */ - GEN_SET, /**< Generator value is set */ - GEN_ABS_NRPN /**< Generator is an absolute value */ + GEN_UNUSED, /**< Generator value is not set */ + GEN_SET, /**< Generator value is set */ + GEN_ABS_NRPN /**< Generator is an absolute value */ }; #define fluid_gen_set_mod(_gen, _val) { (_gen)->mod = (double) (_val); } @@ -59,8 +60,8 @@ enum fluid_gen_flags fluid_real_t fluid_gen_scale(int gen, float value); fluid_real_t fluid_gen_scale_nrpn(int gen, int nrpn); -int fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel); -int fluid_gen_set_default_values(fluid_gen_t* gen); +int fluid_gen_init(fluid_gen_t *gen, fluid_channel_t *channel); +int fluid_gen_set_default_values(fluid_gen_t *gen); #endif /* _FLUID_GEN_H */ diff --git a/src/synth/fluid_mod.c b/src/synth/fluid_mod.c index 4c06c827..e186ea8a 100644 --- a/src/synth/fluid_mod.c +++ b/src/synth/fluid_mod.c @@ -29,14 +29,14 @@ * @note The \c next member of \c mod will be left unchanged. */ void -fluid_mod_clone(fluid_mod_t* mod, const fluid_mod_t* src) +fluid_mod_clone(fluid_mod_t *mod, const fluid_mod_t *src) { - mod->dest = src->dest; - mod->src1 = src->src1; - mod->flags1 = src->flags1; - mod->src2 = src->src2; - mod->flags2 = src->flags2; - mod->amount = src->amount; + mod->dest = src->dest; + mod->src1 = src->src1; + mod->flags1 = src->flags1; + mod->src2 = src->src2; + mod->flags2 = src->flags2; + mod->amount = src->amount; } /** @@ -48,10 +48,10 @@ fluid_mod_clone(fluid_mod_t* mod, const fluid_mod_t* src) * (#FLUID_MOD_CC), see #fluid_mod_flags. */ void -fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags) +fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags) { - mod->src1 = src; - mod->flags1 = flags; + mod->src1 = src; + mod->flags1 = flags; } /** @@ -63,10 +63,10 @@ fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags) * (#FLUID_MOD_CC), see #fluid_mod_flags. */ void -fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags) +fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags) { - mod->src2 = src; - mod->flags2 = flags; + mod->src2 = src; + mod->flags2 = flags; } /** @@ -75,9 +75,9 @@ fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags) * @param dest Destination generator (#fluid_gen_type) */ void -fluid_mod_set_dest(fluid_mod_t* mod, int dest) +fluid_mod_set_dest(fluid_mod_t *mod, int dest) { - mod->dest = dest; + mod->dest = dest; } /** @@ -86,9 +86,9 @@ fluid_mod_set_dest(fluid_mod_t* mod, int dest) * @param amount Scale amount to assign */ void -fluid_mod_set_amount(fluid_mod_t* mod, double amount) +fluid_mod_set_amount(fluid_mod_t *mod, double amount) { - mod->amount = (double) amount; + mod->amount = (double) amount; } /** @@ -97,9 +97,9 @@ fluid_mod_set_amount(fluid_mod_t* mod, double amount) * @return The primary source value (#fluid_mod_src or a MIDI CC controller value). */ int -fluid_mod_get_source1(const fluid_mod_t* mod) +fluid_mod_get_source1(const fluid_mod_t *mod) { - return mod->src1; + return mod->src1; } /** @@ -108,9 +108,9 @@ fluid_mod_get_source1(const fluid_mod_t* mod) * @return The primary source flags (#fluid_mod_flags). */ int -fluid_mod_get_flags1(const fluid_mod_t* mod) +fluid_mod_get_flags1(const fluid_mod_t *mod) { - return mod->flags1; + return mod->flags1; } /** @@ -119,9 +119,9 @@ fluid_mod_get_flags1(const fluid_mod_t* mod) * @return The secondary source value (#fluid_mod_src or a MIDI CC controller value). */ int -fluid_mod_get_source2(const fluid_mod_t* mod) +fluid_mod_get_source2(const fluid_mod_t *mod) { - return mod->src2; + return mod->src2; } /** @@ -130,9 +130,9 @@ fluid_mod_get_source2(const fluid_mod_t* mod) * @return The secondary source flags (#fluid_mod_flags). */ int -fluid_mod_get_flags2(const fluid_mod_t* mod) +fluid_mod_get_flags2(const fluid_mod_t *mod) { - return mod->flags2; + return mod->flags2; } /** @@ -141,9 +141,9 @@ fluid_mod_get_flags2(const fluid_mod_t* mod) * @return Destination generator (#fluid_gen_type) */ int -fluid_mod_get_dest(const fluid_mod_t* mod) +fluid_mod_get_dest(const fluid_mod_t *mod) { - return mod->dest; + return mod->dest; } /** @@ -152,9 +152,9 @@ fluid_mod_get_dest(const fluid_mod_t* mod) * @return Scale amount */ double -fluid_mod_get_amount(const fluid_mod_t* mod) +fluid_mod_get_amount(const fluid_mod_t *mod) { - return (double) mod->amount; + return (double) mod->amount; } /* @@ -163,67 +163,79 @@ fluid_mod_get_amount(const fluid_mod_t* mod) static fluid_real_t fluid_mod_get_source_value(const unsigned char mod_src, const unsigned char mod_flags, - fluid_real_t* range, - const fluid_channel_t* chan, - const fluid_voice_t* voice + fluid_real_t *range, + const fluid_channel_t *chan, + const fluid_voice_t *voice ) { fluid_real_t val; - - if (mod_flags & FLUID_MOD_CC) + + if(mod_flags & FLUID_MOD_CC) { /* From MIDI Recommended Practice (RP-036) Default Pan Formula: * "Since MIDI controller values range from 0 to 127, the exact center * of the range, 63.5, cannot be represented. Therefore, the effective * range for CC#10 is modified to be 1 to 127, and values 0 and 1 both - * pan hard left. The recommended method is to subtract 1 from the + * pan hard left. The recommended method is to subtract 1 from the * value of CC#10, and saturate the result to be non-negative." * * We treat the balance control in exactly the same way, as the same * problem applies here as well. */ - if (mod_src == PAN_MSB || mod_src == BALANCE_MSB) { + if(mod_src == PAN_MSB || mod_src == BALANCE_MSB) + { *range = 126; val = fluid_channel_get_cc(chan, mod_src) - 1; - if (val < 0) { + + if(val < 0) + { val = 0; } } - else { + else + { val = fluid_channel_get_cc(chan, mod_src); } } else { - switch (mod_src) + switch(mod_src) { case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */ val = *range; break; + case FLUID_MOD_VELOCITY: val = fluid_voice_get_actual_velocity(voice); break; + case FLUID_MOD_KEY: val = fluid_voice_get_actual_key(voice); break; + case FLUID_MOD_KEYPRESSURE: val = fluid_channel_get_key_pressure(chan, voice->key); break; + case FLUID_MOD_CHANNELPRESSURE: - val = fluid_channel_get_channel_pressure (chan); + val = fluid_channel_get_channel_pressure(chan); break; + case FLUID_MOD_PITCHWHEEL: - val = fluid_channel_get_pitch_bend (chan); + val = fluid_channel_get_pitch_bend(chan); *range = 0x4000; break; + case FLUID_MOD_PITCHWHEELSENS: - val = fluid_channel_get_pitch_wheel_sensitivity (chan); + val = fluid_channel_get_pitch_wheel_sensitivity(chan); break; + default: - FLUID_LOG(FLUID_ERR, "Unknown modulator source '%d', disabling modulator.", mod_src); + FLUID_LOG(FLUID_ERR, "Unknown modulator source '%d', disabling modulator.", mod_src); val = 0.0; } } + return val; } @@ -234,102 +246,120 @@ static fluid_real_t fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, const fluid_real_t range) { /* normalized value, i.e. usually in the range [0;1] - * + * * if val was retrieved from pitch_bend then [-0.5;0.5] */ const fluid_real_t val_norm = val / range; - + /* we could also only switch case the lower nibble of mod_flags, however * this would keep us from adding further mod types in the future - * + * * instead just remove the flag(s) we already took care of */ mod_flags &= ~FLUID_MOD_CC; - - switch (mod_flags/* & 0x0f*/) + + switch(mod_flags/* & 0x0f*/) { case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =0 */ - val = val_norm; - break; + val = val_norm; + break; + case FLUID_MOD_LINEAR | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =1 */ - val = 1.0f - val_norm; - break; + val = 1.0f - val_norm; + break; + case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =2 */ - val = -1.0f + 2.0f * val_norm; - break; + val = -1.0f + 2.0f * val_norm; + break; + case FLUID_MOD_LINEAR | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =3 */ - val = 1.0f - 2.0f * val_norm; - break; + val = 1.0f - 2.0f * val_norm; + break; + case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =4 */ - val = fluid_concave(127 * (val_norm)); - break; + val = fluid_concave(127 * (val_norm)); + break; + case FLUID_MOD_CONCAVE | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =5 */ - val = fluid_concave(127 * (1.0f - val_norm)); - break; + val = fluid_concave(127 * (1.0f - val_norm)); + break; + case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =6 */ - val = (val_norm > 0.5f) ? fluid_concave(127 * 2 * (val_norm - 0.5f)) - : -fluid_concave(127 * 2 * (0.5f - val_norm)); - break; + val = (val_norm > 0.5f) ? fluid_concave(127 * 2 * (val_norm - 0.5f)) + : -fluid_concave(127 * 2 * (0.5f - val_norm)); + break; + case FLUID_MOD_CONCAVE | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =7 */ - val = (val_norm > 0.5f) ? -fluid_concave(127 * 2 * (val_norm - 0.5f)) - : fluid_concave(127 * 2 * (0.5f - val_norm)); - break; + val = (val_norm > 0.5f) ? -fluid_concave(127 * 2 * (val_norm - 0.5f)) + : fluid_concave(127 * 2 * (0.5f - val_norm)); + break; + case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =8 */ - val = fluid_convex(127 * (val_norm)); - break; + val = fluid_convex(127 * (val_norm)); + break; + case FLUID_MOD_CONVEX | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =9 */ - val = fluid_convex(127 * (1.0f - val_norm)); - break; + val = fluid_convex(127 * (1.0f - val_norm)); + break; + case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =10 */ - val = (val_norm > 0.5f) ? fluid_convex(127 * 2 * (val_norm - 0.5f)) - : -fluid_convex(127 * 2 * (0.5f - val_norm)); - break; + val = (val_norm > 0.5f) ? fluid_convex(127 * 2 * (val_norm - 0.5f)) + : -fluid_convex(127 * 2 * (0.5f - val_norm)); + break; + case FLUID_MOD_CONVEX | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =11 */ - val = (val_norm > 0.5f) ? -fluid_convex(127 * 2 * (val_norm - 0.5f)) - : fluid_convex(127 * 2 * (0.5f - val_norm)); - break; + val = (val_norm > 0.5f) ? -fluid_convex(127 * 2 * (val_norm - 0.5f)) + : fluid_convex(127 * 2 * (0.5f - val_norm)); + break; + case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* =12 */ - val = (val_norm >= 0.5f)? 1.0f : 0.0f; - break; + val = (val_norm >= 0.5f) ? 1.0f : 0.0f; + break; + case FLUID_MOD_SWITCH | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* =13 */ - val = (val_norm >= 0.5f)? 0.0f : 1.0f; - break; + val = (val_norm >= 0.5f) ? 0.0f : 1.0f; + break; + case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* =14 */ - val = (val_norm >= 0.5f)? 1.0f : -1.0f; - break; + val = (val_norm >= 0.5f) ? 1.0f : -1.0f; + break; + case FLUID_MOD_SWITCH | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* =15 */ - val = (val_norm >= 0.5f)? -1.0f : 1.0f; - break; - - /* - * MIDI CCs only have a resolution of 7 bits. The closer val_norm gets to 1, - * the less will be the resulting change of the sinus. When using this sin() - * for scaling the cutoff frequency, there will be no audible difference between - * MIDI CCs 118 to 127. To avoid this waste of CCs multiply with 0.87 - * (at least for unipolar) which makes sin() never get to 1.0 but to 0.98 which - * is close enough. - */ + val = (val_norm >= 0.5f) ? -1.0f : 1.0f; + break; + + /* + * MIDI CCs only have a resolution of 7 bits. The closer val_norm gets to 1, + * the less will be the resulting change of the sinus. When using this sin() + * for scaling the cutoff frequency, there will be no audible difference between + * MIDI CCs 118 to 127. To avoid this waste of CCs multiply with 0.87 + * (at least for unipolar) which makes sin() never get to 1.0 but to 0.98 which + * is close enough. + */ case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE: /* custom sin(x) */ - val = sin(M_PI/2 * val_norm * 0.87); - break; + val = sin(M_PI / 2 * val_norm * 0.87); + break; + case FLUID_MOD_SIN | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE: /* custom */ - val = sin(M_PI/2 * (1.0f - val_norm) * 0.87); - break; + val = sin(M_PI / 2 * (1.0f - val_norm) * 0.87); + break; + case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE: /* custom */ - val = (val_norm > 0.5f) ? sin(M_PI/2 * 2 * (val_norm - 0.5f)) - : -sin(M_PI/2 * 2 * (0.5f - val_norm)); - break; + val = (val_norm > 0.5f) ? sin(M_PI / 2 * 2 * (val_norm - 0.5f)) + : -sin(M_PI / 2 * 2 * (0.5f - val_norm)); + break; + case FLUID_MOD_SIN | FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE: /* custom */ - val = (val_norm > 0.5f) ? -sin(M_PI/2 * 2 * (val_norm - 0.5f)) - : sin(M_PI/2 * 2 * (0.5f - val_norm)); - break; - + val = (val_norm > 0.5f) ? -sin(M_PI / 2 * 2 * (val_norm - 0.5f)) + : sin(M_PI / 2 * 2 * (0.5f - val_norm)); + break; + default: - FLUID_LOG(FLUID_ERR, "Unknown modulator type '%d', disabling modulator.", mod_flags); - val = 0.0f; - break; + FLUID_LOG(FLUID_ERR, "Unknown modulator type '%d', disabling modulator.", mod_flags); + val = 0.0f; + break; } - + return val; } @@ -337,99 +367,106 @@ fluid_mod_transform_source_value(fluid_real_t val, unsigned char mod_flags, cons * fluid_mod_get_value */ fluid_real_t -fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice) +fluid_mod_get_value(fluid_mod_t *mod, fluid_channel_t *chan, fluid_voice_t *voice) { - extern fluid_mod_t default_vel2filter_mod; - - fluid_real_t v1 = 0.0, v2 = 1.0; - fluid_real_t range1 = 127.0, range2 = 127.0; + extern fluid_mod_t default_vel2filter_mod; - if (chan == NULL) { - return 0.0f; - } + fluid_real_t v1 = 0.0, v2 = 1.0; + fluid_real_t range1 = 127.0, range2 = 127.0; - /* 'special treatment' for default controller - * - * Reference: SF2.01 section 8.4.2 - * - * The GM default controller 'vel-to-filter cut off' is not clearly - * defined: If implemented according to the specs, the filter - * frequency jumps between vel=63 and vel=64. To maintain - * compatibility with existing sound fonts, the implementation is - * 'hardcoded', it is impossible to implement using only one - * modulator otherwise. - * - * I assume here, that the 'intention' of the paragraph is one - * octave (1200 cents) filter frequency shift between vel=127 and - * vel=64. 'amount' is (-2400), at least as long as the controller - * is set to default. - * - * Further, the 'appearance' of the modulator (source enumerator, - * destination enumerator, flags etc) is different from that - * described in section 8.4.2, but it matches the definition used in - * several SF2.1 sound fonts (where it is used only to turn it off). - * */ - if (fluid_mod_test_identity(mod, &default_vel2filter_mod)) { -// S. Christian Collins' mod, to stop forcing velocity based filtering -/* - if (voice->vel < 64){ - return (fluid_real_t) mod->amount / 2.0; - } else { - return (fluid_real_t) mod->amount * (127 - voice->vel) / 127; + if(chan == NULL) + { + return 0.0f; } -*/ - return 0; // (fluid_real_t) mod->amount / 2.0; - } + + /* 'special treatment' for default controller + * + * Reference: SF2.01 section 8.4.2 + * + * The GM default controller 'vel-to-filter cut off' is not clearly + * defined: If implemented according to the specs, the filter + * frequency jumps between vel=63 and vel=64. To maintain + * compatibility with existing sound fonts, the implementation is + * 'hardcoded', it is impossible to implement using only one + * modulator otherwise. + * + * I assume here, that the 'intention' of the paragraph is one + * octave (1200 cents) filter frequency shift between vel=127 and + * vel=64. 'amount' is (-2400), at least as long as the controller + * is set to default. + * + * Further, the 'appearance' of the modulator (source enumerator, + * destination enumerator, flags etc) is different from that + * described in section 8.4.2, but it matches the definition used in + * several SF2.1 sound fonts (where it is used only to turn it off). + * */ + if(fluid_mod_test_identity(mod, &default_vel2filter_mod)) + { +// S. Christian Collins' mod, to stop forcing velocity based filtering + /* + if (voice->vel < 64){ + return (fluid_real_t) mod->amount / 2.0; + } else { + return (fluid_real_t) mod->amount * (127 - voice->vel) / 127; + } + */ + return 0; // (fluid_real_t) mod->amount / 2.0; + } + // end S. Christian Collins' mod - /* get the initial value of the first source */ - if (mod->src1 > 0) - { - v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, chan, voice); + /* get the initial value of the first source */ + if(mod->src1 > 0) + { + v1 = fluid_mod_get_source_value(mod->src1, mod->flags1, &range1, chan, voice); - /* transform the input value */ - v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1); - } - else - { - return 0.0; - } + /* transform the input value */ + v1 = fluid_mod_transform_source_value(v1, mod->flags1, range1); + } + else + { + return 0.0; + } - /* no need to go further */ - if (v1 == 0.0f) { - return 0.0f; - } + /* no need to go further */ + if(v1 == 0.0f) + { + return 0.0f; + } - /* get the second input source */ - if (mod->src2 > 0) - { - v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, chan, voice); + /* get the second input source */ + if(mod->src2 > 0) + { + v2 = fluid_mod_get_source_value(mod->src2, mod->flags2, &range2, chan, voice); - /* transform the second input value */ - v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2); - } - else - { - v2 = 1.0f; - } + /* transform the second input value */ + v2 = fluid_mod_transform_source_value(v2, mod->flags2, range2); + } + else + { + v2 = 1.0f; + } - /* it's as simple as that: */ - return (fluid_real_t) mod->amount * v1 * v2; + /* it's as simple as that: */ + return (fluid_real_t) mod->amount * v1 * v2; } /** * Create a new uninitialized modulator structure. * @return New allocated modulator or NULL if out of memory */ -fluid_mod_t* +fluid_mod_t * new_fluid_mod() { - fluid_mod_t* mod = FLUID_NEW (fluid_mod_t); - if (mod == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - return mod; + fluid_mod_t *mod = FLUID_NEW(fluid_mod_t); + + if(mod == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + return mod; } /** @@ -437,16 +474,16 @@ new_fluid_mod() * @param mod Modulator to free */ void -delete_fluid_mod (fluid_mod_t *mod) +delete_fluid_mod(fluid_mod_t *mod) { - FLUID_FREE(mod); + FLUID_FREE(mod); } /** * Returns the size of the fluid_mod_t structure. - * + * * Useful in low latency scenarios e.g. to allocate a modulator on the stack. - * + * * @return Size of fluid_mod_t in bytes */ size_t fluid_mod_sizeof() @@ -463,38 +500,38 @@ size_t fluid_mod_sizeof() * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'. */ int -fluid_mod_test_identity (const fluid_mod_t *mod1, const fluid_mod_t *mod2) +fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2) { - return mod1->dest == mod2->dest - && mod1->src1 == mod2->src1 - && mod1->src2 == mod2->src2 - && mod1->flags1 == mod2->flags1 - && mod1->flags2 == mod2->flags2; + return mod1->dest == mod2->dest + && mod1->src1 == mod2->src1 + && mod1->src2 == mod2->src2 + && mod1->flags1 == mod2->flags1 + && mod1->flags2 == mod2->flags2; } /** * Check if the modulator has the given source. - * + * * @param mod The modulator instance * @param cc Boolean value indicating if ctrl is a CC controller or not * @param ctrl The source to check for (if \c cc == FALSE : a value of type #fluid_mod_src, else the value of the MIDI CC to check for) - * + * * @return TRUE if the modulator has the given source, FALSE otherwise. */ -int fluid_mod_has_source(const fluid_mod_t * mod, int cc, int ctrl) +int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl) { return - ( ( - ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) != 0) && (cc != 0)) - || ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) == 0) && (cc == 0)) - ) - || - ( - ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) != 0) && (cc != 0)) - || ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) == 0) && (cc == 0)) - ) - ); + ( + ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) != 0) && (cc != 0)) + || ((mod->src1 == ctrl) && ((mod->flags1 & FLUID_MOD_CC) == 0) && (cc == 0)) + ) + || + ( + ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) != 0) && (cc != 0)) + || ((mod->src2 == ctrl) && ((mod->flags2 & FLUID_MOD_CC) == 0) && (cc == 0)) + ) + ); } /** @@ -503,7 +540,7 @@ int fluid_mod_has_source(const fluid_mod_t * mod, int cc, int ctrl) * @param gen The destination generator of type #fluid_gen_type to check for * @return TRUE if the modulator has the given destination, FALSE otherwise. */ -int fluid_mod_has_dest(const fluid_mod_t * mod, int gen) +int fluid_mod_has_dest(const fluid_mod_t *mod, int gen) { return mod->dest == gen; } @@ -511,56 +548,133 @@ int fluid_mod_has_dest(const fluid_mod_t * mod, int gen) /* debug function: Prints the contents of a modulator */ #ifdef DEBUG -void fluid_dump_modulator(fluid_mod_t * mod){ - int src1=mod->src1; - int dest=mod->dest; - int src2=mod->src2; - int flags1=mod->flags1; - int flags2=mod->flags2; - fluid_real_t amount=(fluid_real_t)mod->amount; +void fluid_dump_modulator(fluid_mod_t *mod) +{ + int src1 = mod->src1; + int dest = mod->dest; + int src2 = mod->src2; + int flags1 = mod->flags1; + int flags2 = mod->flags2; + fluid_real_t amount = (fluid_real_t)mod->amount; - printf("Src: "); - if (flags1 & FLUID_MOD_CC){ - printf("MIDI CC=%i",src1); - } else { - switch(src1){ - case FLUID_MOD_NONE: - printf("None"); break; - case FLUID_MOD_VELOCITY: - printf("note-on velocity"); break; - case FLUID_MOD_KEY: - printf("Key nr"); break; - case FLUID_MOD_KEYPRESSURE: - printf("Poly pressure"); break; - case FLUID_MOD_CHANNELPRESSURE: - printf("Chan pressure"); break; - case FLUID_MOD_PITCHWHEEL: - printf("Pitch Wheel"); break; - case FLUID_MOD_PITCHWHEELSENS: - printf("Pitch Wheel sens"); break; - default: - printf("(unknown: %i)", src1); - }; /* switch src1 */ - }; /* if not CC */ - if (flags1 & FLUID_MOD_NEGATIVE){printf("- ");} else {printf("+ ");}; - if (flags1 & FLUID_MOD_BIPOLAR){printf("bip ");} else {printf("unip ");}; - printf("-> "); - switch(dest){ - case GEN_FILTERQ: printf("Q"); break; - case GEN_FILTERFC: printf("fc"); break; - case GEN_CUSTOM_FILTERQ: printf("custom-Q"); break; - case GEN_CUSTOM_FILTERFC: printf("custom-fc"); break; - case GEN_VIBLFOTOPITCH: printf("VibLFO-to-pitch"); break; - case GEN_MODENVTOPITCH: printf("ModEnv-to-pitch"); break; - case GEN_MODLFOTOPITCH: printf("ModLFO-to-pitch"); break; - case GEN_CHORUSSEND: printf("Chorus send"); break; - case GEN_REVERBSEND: printf("Reverb send"); break; - case GEN_PAN: printf("pan"); break; - case GEN_CUSTOM_BALANCE: printf("balance"); break; - case GEN_ATTENUATION: printf("att"); break; - default: printf("dest %i",dest); - }; /* switch dest */ - printf(", amount %f flags %i src2 %i flags2 %i\n",amount, flags1, src2, flags2); + printf("Src: "); + + if(flags1 & FLUID_MOD_CC) + { + printf("MIDI CC=%i", src1); + } + else + { + switch(src1) + { + case FLUID_MOD_NONE: + printf("None"); + break; + + case FLUID_MOD_VELOCITY: + printf("note-on velocity"); + break; + + case FLUID_MOD_KEY: + printf("Key nr"); + break; + + case FLUID_MOD_KEYPRESSURE: + printf("Poly pressure"); + break; + + case FLUID_MOD_CHANNELPRESSURE: + printf("Chan pressure"); + break; + + case FLUID_MOD_PITCHWHEEL: + printf("Pitch Wheel"); + break; + + case FLUID_MOD_PITCHWHEELSENS: + printf("Pitch Wheel sens"); + break; + + default: + printf("(unknown: %i)", src1); + }; /* switch src1 */ + }; /* if not CC */ + + if(flags1 & FLUID_MOD_NEGATIVE) + { + printf("- "); + } + else + { + printf("+ "); + }; + + if(flags1 & FLUID_MOD_BIPOLAR) + { + printf("bip "); + } + else + { + printf("unip "); + }; + + printf("-> "); + + switch(dest) + { + case GEN_FILTERQ: + printf("Q"); + break; + + case GEN_FILTERFC: + printf("fc"); + break; + + case GEN_CUSTOM_FILTERQ: + printf("custom-Q"); + break; + + case GEN_CUSTOM_FILTERFC: + printf("custom-fc"); + break; + + case GEN_VIBLFOTOPITCH: + printf("VibLFO-to-pitch"); + break; + + case GEN_MODENVTOPITCH: + printf("ModEnv-to-pitch"); + break; + + case GEN_MODLFOTOPITCH: + printf("ModLFO-to-pitch"); + break; + + case GEN_CHORUSSEND: + printf("Chorus send"); + break; + + case GEN_REVERBSEND: + printf("Reverb send"); + break; + + case GEN_PAN: + printf("pan"); + break; + + case GEN_CUSTOM_BALANCE: + printf("balance"); + break; + + case GEN_ATTENUATION: + printf("att"); + break; + + default: + printf("dest %i", dest); + }; /* switch dest */ + + printf(", amount %f flags %i src2 %i flags2 %i\n", amount, flags1, src2, flags2); }; #endif diff --git a/src/synth/fluid_mod.h b/src/synth/fluid_mod.h index 7018a9e3..4a0dca5b 100644 --- a/src/synth/fluid_mod.h +++ b/src/synth/fluid_mod.h @@ -29,24 +29,24 @@ */ struct _fluid_mod_t { - unsigned char dest; /**< Destination generator to control */ - unsigned char src1; /**< Source controller 1 */ - unsigned char flags1; /**< Source controller 1 flags */ - unsigned char src2; /**< Source controller 2 */ - unsigned char flags2; /**< Source controller 2 flags */ - double amount; /**< Multiplier amount */ - /* The 'next' field allows to link modulators into a list. It is - * not used in fluid_voice.c, there each voice allocates memory for a - * fixed number of modulators. Since there may be a huge number of - * different zones, this is more efficient. - */ - fluid_mod_t * next; + unsigned char dest; /**< Destination generator to control */ + unsigned char src1; /**< Source controller 1 */ + unsigned char flags1; /**< Source controller 1 flags */ + unsigned char src2; /**< Source controller 2 */ + unsigned char flags2; /**< Source controller 2 flags */ + double amount; /**< Multiplier amount */ + /* The 'next' field allows to link modulators into a list. It is + * not used in fluid_voice.c, there each voice allocates memory for a + * fixed number of modulators. Since there may be a huge number of + * different zones, this is more efficient. + */ + fluid_mod_t *next; }; -fluid_real_t fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice); +fluid_real_t fluid_mod_get_value(fluid_mod_t *mod, fluid_channel_t *chan, fluid_voice_t *voice); #ifdef DEBUG -void fluid_dump_modulator(fluid_mod_t * mod); +void fluid_dump_modulator(fluid_mod_t *mod); #endif diff --git a/src/synth/fluid_synth.c b/src/synth/fluid_synth.c index 523645ec..a779ba48 100644 --- a/src/synth/fluid_synth.c +++ b/src/synth/fluid_synth.c @@ -31,13 +31,13 @@ #include /* seems to not be declared in fenv.h */ -extern int feenableexcept (int excepts); +extern int feenableexcept(int excepts); #endif #define FLUID_API_RETURN(return_value) \ do { fluid_synth_api_exit(synth); \ return return_value; } while (0) - + #define FLUID_API_RETURN_IF_CHAN_DISABLED(return_value) \ do { if (FLUID_LIKELY(synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED)) \ {} \ @@ -54,65 +54,65 @@ extern int feenableexcept (int excepts); } \ static void fluid_synth_init(void); -static void fluid_synth_api_enter(fluid_synth_t* synth); -static void fluid_synth_api_exit(fluid_synth_t* synth); +static void fluid_synth_api_enter(fluid_synth_t *synth); +static void fluid_synth_api_exit(fluid_synth_t *synth); -static int fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key, - int vel); -static int fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key); -static int fluid_synth_cc_LOCAL(fluid_synth_t* synth, int channum, int num); -static int fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data, - int len, char *response, - int *response_len, int avail_response, - int *handled, int dryrun); -int fluid_synth_all_notes_off_LOCAL(fluid_synth_t* synth, int chan); -static int fluid_synth_all_sounds_off_LOCAL(fluid_synth_t* synth, int chan); -static int fluid_synth_system_reset_LOCAL(fluid_synth_t* synth); -static int fluid_synth_modulate_voices_LOCAL(fluid_synth_t* synth, int chan, - int is_cc, int ctrl); -static int fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t* synth, int chan); -static int fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t* synth, int channum); -static int fluid_synth_update_key_pressure_LOCAL(fluid_synth_t* synth, int chan, int key); -static int fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t* synth, int chan); -static int fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t* synth, int chan); -static int fluid_synth_set_preset (fluid_synth_t *synth, int chan, - fluid_preset_t *preset); -static fluid_preset_t* -fluid_synth_get_preset(fluid_synth_t* synth, int sfontnum, +static int fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key, + int vel); +static int fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key); +static int fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num); +static int fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, + int len, char *response, + int *response_len, int avail_response, + int *handled, int dryrun); +int fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan); +static int fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan); +static int fluid_synth_system_reset_LOCAL(fluid_synth_t *synth); +static int fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan, + int is_cc, int ctrl); +static int fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan); +static int fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int channum); +static int fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key); +static int fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan); +static int fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan); +static int fluid_synth_set_preset(fluid_synth_t *synth, int chan, + fluid_preset_t *preset); +static fluid_preset_t * +fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum, int banknum, int prognum); -static fluid_preset_t* -fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname, +static fluid_preset_t * +fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname, int banknum, int prognum); -static void fluid_synth_update_presets(fluid_synth_t* synth); -static void fluid_synth_update_gain_LOCAL(fluid_synth_t* synth); -static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth, int new_polyphony); +static void fluid_synth_update_presets(fluid_synth_t *synth); +static void fluid_synth_update_gain_LOCAL(fluid_synth_t *synth); +static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony); static void init_dither(void); -static FLUID_INLINE int roundi (float x); -static int fluid_synth_render_blocks(fluid_synth_t* synth, int blockcount); +static FLUID_INLINE int roundi(float x); +static int fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount); -static fluid_voice_t* fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t* synth); -static void fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t* synth, - fluid_voice_t* new_voice); -static int fluid_synth_sfunload_callback(void* data, unsigned int msec); -void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth, - int chan, int key); -static fluid_tuning_t* fluid_synth_get_tuning(fluid_synth_t* synth, - int bank, int prog); -static int fluid_synth_replace_tuning_LOCK (fluid_synth_t* synth, - fluid_tuning_t *tuning, - int bank, int prog, int apply); -static void fluid_synth_replace_tuning_LOCAL (fluid_synth_t *synth, - fluid_tuning_t *old_tuning, - fluid_tuning_t *new_tuning, - int apply, int unref_new); -static void fluid_synth_update_voice_tuning_LOCAL (fluid_synth_t *synth, - fluid_channel_t *channel); -static int fluid_synth_set_tuning_LOCAL (fluid_synth_t *synth, int chan, - fluid_tuning_t *tuning, int apply); -static void fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan, - int param, float value, int absolute); -static void fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id); +static fluid_voice_t *fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth); +static void fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth, + fluid_voice_t *new_voice); +static int fluid_synth_sfunload_callback(void *data, unsigned int msec); +void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, + int chan, int key); +static fluid_tuning_t *fluid_synth_get_tuning(fluid_synth_t *synth, + int bank, int prog); +static int fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth, + fluid_tuning_t *tuning, + int bank, int prog, int apply); +static void fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth, + fluid_tuning_t *old_tuning, + fluid_tuning_t *new_tuning, + int apply, int unref_new); +static void fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth, + fluid_channel_t *channel); +static int fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan, + fluid_tuning_t *tuning, int apply); +static void fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan, + int param, float value, int absolute); +static void fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id); static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels); @@ -126,18 +126,18 @@ static void fluid_synth_handle_device_id(void *data, const char *name, int value static void fluid_synth_handle_overflow(void *data, const char *name, double value); static void fluid_synth_handle_important_channels(void *data, const char *name, const char *value); -static void fluid_synth_handle_reverb_chorus_num (void *data, const char *name, double value); -static void fluid_synth_handle_reverb_chorus_int (void *data, const char *name, int value); +static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value); +static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value); -static void fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t* synth, int chan, int nbr_chan); -static int fluid_synth_check_next_basic_channel(fluid_synth_t* synth, int basicchan, int mode, int val); -static void fluid_synth_set_basic_channel_LOCAL(fluid_synth_t* synth, int basicchan, int mode, int val); -static int fluid_synth_set_reverb_full_LOCAL(fluid_synth_t* synth, int set, double roomsize, - double damping, double width, double level); +static void fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan); +static int fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val); +static void fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val); +static int fluid_synth_set_reverb_full_LOCAL(fluid_synth_t *synth, int set, double roomsize, + double damping, double width, double level); -static int fluid_synth_set_chorus_full_LOCAL(fluid_synth_t* synth, int set, int nr, double level, - double speed, double depth_ms, int type); +static int fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int nr, double level, + double speed, double depth_ms, int type); /*************************************************************** * @@ -177,13 +177,14 @@ API fluid_set_breath_mode() or command shell setbreathmode. static fluid_mod_t custom_breath2att_mod; /* reverb presets */ -static const fluid_revmodel_presets_t revmodel_preset[] = { - /* name */ /* roomsize */ /* damp */ /* width */ /* level */ - { "Test 1", 0.2f, 0.0f, 0.5f, 0.9f }, - { "Test 2", 0.4f, 0.2f, 0.5f, 0.8f }, - { "Test 3", 0.6f, 0.4f, 0.5f, 0.7f }, - { "Test 4", 0.8f, 0.7f, 0.5f, 0.6f }, - { "Test 5", 0.8f, 1.0f, 0.5f, 0.5f }, +static const fluid_revmodel_presets_t revmodel_preset[] = +{ + /* name */ /* roomsize */ /* damp */ /* width */ /* level */ + { "Test 1", 0.2f, 0.0f, 0.5f, 0.9f }, + { "Test 2", 0.4f, 0.2f, 0.5f, 0.8f }, + { "Test 3", 0.6f, 0.4f, 0.5f, 0.7f }, + { "Test 4", 0.8f, 0.7f, 0.5f, 0.6f }, + { "Test 5", 0.8f, 1.0f, 0.5f, 0.5f }, }; @@ -192,59 +193,59 @@ static const fluid_revmodel_presets_t revmodel_preset[] = { * INITIALIZATION & UTILITIES */ -void fluid_synth_settings(fluid_settings_t* settings) +void fluid_synth_settings(fluid_settings_t *settings) { - fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1, FLUID_HINT_TOGGLED); - - fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1, FLUID_HINT_TOGGLED); - fluid_settings_register_num(settings, "synth.reverb.room-size", FLUID_REVERB_DEFAULT_ROOMSIZE, 0.0f, 1.0f, 0); - fluid_settings_register_num(settings, "synth.reverb.damp", FLUID_REVERB_DEFAULT_DAMP, 0.0f, 1.0f, 0); - fluid_settings_register_num(settings, "synth.reverb.width", FLUID_REVERB_DEFAULT_WIDTH, 0.0f, 100.0f, 0); - fluid_settings_register_num(settings, "synth.reverb.level", FLUID_REVERB_DEFAULT_LEVEL, 0.0f, 1.0f, 0); - - fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1, FLUID_HINT_TOGGLED); - fluid_settings_register_int(settings, "synth.chorus.nr", FLUID_CHORUS_DEFAULT_N, 0, 99, 0); - fluid_settings_register_num(settings, "synth.chorus.level", FLUID_CHORUS_DEFAULT_LEVEL, 0.0f, 10.0f, 0); - fluid_settings_register_num(settings, "synth.chorus.speed", FLUID_CHORUS_DEFAULT_SPEED, 0.29f, 5.0f, 0); - fluid_settings_register_num(settings, "synth.chorus.depth", FLUID_CHORUS_DEFAULT_DEPTH, 0.0f, 21.0f, 0); - - fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1, FLUID_HINT_TOGGLED); - fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1, FLUID_HINT_TOGGLED); - fluid_settings_register_str(settings, "midi.portname", "", 0); + fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1, FLUID_HINT_TOGGLED); + + fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_num(settings, "synth.reverb.room-size", FLUID_REVERB_DEFAULT_ROOMSIZE, 0.0f, 1.0f, 0); + fluid_settings_register_num(settings, "synth.reverb.damp", FLUID_REVERB_DEFAULT_DAMP, 0.0f, 1.0f, 0); + fluid_settings_register_num(settings, "synth.reverb.width", FLUID_REVERB_DEFAULT_WIDTH, 0.0f, 100.0f, 0); + fluid_settings_register_num(settings, "synth.reverb.level", FLUID_REVERB_DEFAULT_LEVEL, 0.0f, 1.0f, 0); + + fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_int(settings, "synth.chorus.nr", FLUID_CHORUS_DEFAULT_N, 0, 99, 0); + fluid_settings_register_num(settings, "synth.chorus.level", FLUID_CHORUS_DEFAULT_LEVEL, 0.0f, 10.0f, 0); + fluid_settings_register_num(settings, "synth.chorus.speed", FLUID_CHORUS_DEFAULT_SPEED, 0.29f, 5.0f, 0); + fluid_settings_register_num(settings, "synth.chorus.depth", FLUID_CHORUS_DEFAULT_DEPTH, 0.0f, 21.0f, 0); + + fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_str(settings, "midi.portname", "", 0); #ifdef DEFAULT_SOUNDFONT - fluid_settings_register_str(settings, "synth.default-soundfont", DEFAULT_SOUNDFONT, 0); + fluid_settings_register_str(settings, "synth.default-soundfont", DEFAULT_SOUNDFONT, 0); #endif - - fluid_settings_register_int(settings, "synth.polyphony", 256, 1, 65535, 0); - fluid_settings_register_int(settings, "synth.midi-channels", 16, 16, 256, 0); - fluid_settings_register_num(settings, "synth.gain", 0.2f, 0.0f, 10.0f, 0); - fluid_settings_register_int(settings, "synth.audio-channels", 1, 1, 128, 0); - fluid_settings_register_int(settings, "synth.audio-groups", 1, 1, 128, 0); - fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0); - fluid_settings_register_num(settings, "synth.sample-rate", 44100.0f, 8000.0f, 96000.0f, 0); - fluid_settings_register_int(settings, "synth.device-id", 0, 0, 126, 0); - fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0); - fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0); - - fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_int(settings, "synth.polyphony", 256, 1, 65535, 0); + fluid_settings_register_int(settings, "synth.midi-channels", 16, 16, 256, 0); + fluid_settings_register_num(settings, "synth.gain", 0.2f, 0.0f, 10.0f, 0); + fluid_settings_register_int(settings, "synth.audio-channels", 1, 1, 128, 0); + fluid_settings_register_int(settings, "synth.audio-groups", 1, 1, 128, 0); + fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0); + fluid_settings_register_num(settings, "synth.sample-rate", 44100.0f, 8000.0f, 96000.0f, 0); + fluid_settings_register_int(settings, "synth.device-id", 0, 0, 126, 0); + fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0); - fluid_settings_register_num(settings, "synth.overflow.percussion", 4000, -10000, 10000, 0); - fluid_settings_register_num(settings, "synth.overflow.sustained", -1000, -10000, 10000, 0); - fluid_settings_register_num(settings, "synth.overflow.released", -2000, -10000, 10000, 0); - fluid_settings_register_num(settings, "synth.overflow.age", 1000, -10000, 10000, 0); - fluid_settings_register_num(settings, "synth.overflow.volume", 500, -10000, 10000, 0); - fluid_settings_register_num(settings, "synth.overflow.important", 5000, -50000, 50000, 0); - fluid_settings_register_str(settings, "synth.overflow.important-channels", "", 0); + fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0); - fluid_settings_register_str(settings, "synth.midi-bank-select", "gs", 0); - fluid_settings_add_option(settings, "synth.midi-bank-select", "gm"); - fluid_settings_add_option(settings, "synth.midi-bank-select", "gs"); - fluid_settings_add_option(settings, "synth.midi-bank-select", "xg"); - fluid_settings_add_option(settings, "synth.midi-bank-select", "mma"); + fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1, FLUID_HINT_TOGGLED); - fluid_settings_register_int(settings, "synth.dynamic-sample-loading", 0, 0, 1, FLUID_HINT_TOGGLED); + fluid_settings_register_num(settings, "synth.overflow.percussion", 4000, -10000, 10000, 0); + fluid_settings_register_num(settings, "synth.overflow.sustained", -1000, -10000, 10000, 0); + fluid_settings_register_num(settings, "synth.overflow.released", -2000, -10000, 10000, 0); + fluid_settings_register_num(settings, "synth.overflow.age", 1000, -10000, 10000, 0); + fluid_settings_register_num(settings, "synth.overflow.volume", 500, -10000, 10000, 0); + fluid_settings_register_num(settings, "synth.overflow.important", 5000, -50000, 50000, 0); + fluid_settings_register_str(settings, "synth.overflow.important-channels", "", 0); + + fluid_settings_register_str(settings, "synth.midi-bank-select", "gs", 0); + fluid_settings_add_option(settings, "synth.midi-bank-select", "gm"); + fluid_settings_add_option(settings, "synth.midi-bank-select", "gs"); + fluid_settings_add_option(settings, "synth.midi-bank-select", "xg"); + fluid_settings_add_option(settings, "synth.midi-bank-select", "mma"); + + fluid_settings_register_int(settings, "synth.dynamic-sample-loading", 0, 0, 1, FLUID_HINT_TOGGLED); } /** @@ -255,9 +256,9 @@ void fluid_synth_settings(fluid_settings_t* settings) */ void fluid_version(int *major, int *minor, int *micro) { - *major = FLUIDSYNTH_VERSION_MAJOR; - *minor = FLUIDSYNTH_VERSION_MINOR; - *micro = FLUIDSYNTH_VERSION_MICRO; + *major = FLUIDSYNTH_VERSION_MAJOR; + *minor = FLUIDSYNTH_VERSION_MINOR; + *micro = FLUIDSYNTH_VERSION_MICRO; } /** @@ -266,9 +267,9 @@ void fluid_version(int *major, int *minor, int *micro) * modified or freed. */ char * -fluid_version_str (void) +fluid_version_str(void) { - return FLUIDSYNTH_VERSION; + return FLUIDSYNTH_VERSION; } /* @@ -280,275 +281,287 @@ static void fluid_synth_init(void) { #ifdef TRAP_ON_FPE - /* Turn on floating point exception traps */ - feenableexcept (FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID); + /* Turn on floating point exception traps */ + feenableexcept(FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID); #endif - fluid_conversion_config(); + fluid_conversion_config(); - fluid_rvoice_dsp_config(); + fluid_rvoice_dsp_config(); - fluid_sys_config(); + fluid_sys_config(); - init_dither(); + init_dither(); - /* custom_breath2att_mod is not a default modulator specified in SF2.01. - it is intended to replace default_vel2att_mod on demand using - API fluid_set_breath_mode() or command shell setbreathmode. - */ - fluid_mod_set_source1(&custom_breath2att_mod, /* The modulator we are programming here */ - BREATH_MSB, /* Source. breath MSB corresponds to 2. */ - FLUID_MOD_CC /* MIDI continuous controller */ - | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */ - | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */ - | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */ - ); - fluid_mod_set_source2(&custom_breath2att_mod, 0, 0); /* No 2nd source */ - fluid_mod_set_dest(&custom_breath2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&custom_breath2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */ + /* custom_breath2att_mod is not a default modulator specified in SF2.01. + it is intended to replace default_vel2att_mod on demand using + API fluid_set_breath_mode() or command shell setbreathmode. + */ + fluid_mod_set_source1(&custom_breath2att_mod, /* The modulator we are programming here */ + BREATH_MSB, /* Source. breath MSB corresponds to 2. */ + FLUID_MOD_CC /* MIDI continuous controller */ + | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */ + | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */ + | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */ + ); + fluid_mod_set_source2(&custom_breath2att_mod, 0, 0); /* No 2nd source */ + fluid_mod_set_dest(&custom_breath2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ + fluid_mod_set_amount(&custom_breath2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */ - /* SF2.01 page 53 section 8.4.1: MIDI Note-On Velocity to Initial Attenuation */ - fluid_mod_set_source1(&default_vel2att_mod, /* The modulator we are programming here */ - FLUID_MOD_VELOCITY, /* Source. VELOCITY corresponds to 'index=2'. */ - FLUID_MOD_GC /* Not a MIDI continuous controller */ - | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */ - | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */ - | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */ - ); - fluid_mod_set_source2(&default_vel2att_mod, 0, 0); /* No 2nd source */ - fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&default_vel2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */ + /* SF2.01 page 53 section 8.4.1: MIDI Note-On Velocity to Initial Attenuation */ + fluid_mod_set_source1(&default_vel2att_mod, /* The modulator we are programming here */ + FLUID_MOD_VELOCITY, /* Source. VELOCITY corresponds to 'index=2'. */ + FLUID_MOD_GC /* Not a MIDI continuous controller */ + | FLUID_MOD_CONCAVE /* Curve shape. Corresponds to 'type=1' */ + | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */ + | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */ + ); + fluid_mod_set_source2(&default_vel2att_mod, 0, 0); /* No 2nd source */ + fluid_mod_set_dest(&default_vel2att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ + fluid_mod_set_amount(&default_vel2att_mod, FLUID_PEAK_ATTENUATION); /* Modulation amount: 960 */ - /* SF2.01 page 53 section 8.4.2: MIDI Note-On Velocity to Filter Cutoff - * Have to make a design decision here. The specs don't make any sense this way or another. - * One sound font, 'Kingston Piano', which has been praised for its quality, tries to - * override this modulator with an amount of 0 and positive polarity (instead of what - * the specs say, D=1) for the secondary source. - * So if we change the polarity to 'positive', one of the best free sound fonts works... - */ - fluid_mod_set_source1(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */ - FLUID_MOD_GC /* CC=0 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_NEGATIVE /* D=1 */ - ); - fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */ - FLUID_MOD_GC /* CC=0 */ - | FLUID_MOD_SWITCH /* type=3 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - // do not remove | FLUID_MOD_NEGATIVE /* D=1 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_dest(&default_vel2filter_mod, GEN_FILTERFC); /* Target: Initial filter cutoff */ - fluid_mod_set_amount(&default_vel2filter_mod, -2400); + /* SF2.01 page 53 section 8.4.2: MIDI Note-On Velocity to Filter Cutoff + * Have to make a design decision here. The specs don't make any sense this way or another. + * One sound font, 'Kingston Piano', which has been praised for its quality, tries to + * override this modulator with an amount of 0 and positive polarity (instead of what + * the specs say, D=1) for the secondary source. + * So if we change the polarity to 'positive', one of the best free sound fonts works... + */ + fluid_mod_set_source1(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */ + FLUID_MOD_GC /* CC=0 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_NEGATIVE /* D=1 */ + ); + fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */ + FLUID_MOD_GC /* CC=0 */ + | FLUID_MOD_SWITCH /* type=3 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + // do not remove | FLUID_MOD_NEGATIVE /* D=1 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_dest(&default_vel2filter_mod, GEN_FILTERFC); /* Target: Initial filter cutoff */ + fluid_mod_set_amount(&default_vel2filter_mod, -2400); - /* SF2.01 page 53 section 8.4.3: MIDI Channel pressure to Vibrato LFO pitch depth */ - fluid_mod_set_source1(&default_at2viblfo_mod, FLUID_MOD_CHANNELPRESSURE, /* Index=13 */ - FLUID_MOD_GC /* CC=0 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_source2(&default_at2viblfo_mod, 0,0); /* no second source */ - fluid_mod_set_dest(&default_at2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */ - fluid_mod_set_amount(&default_at2viblfo_mod, 50); + /* SF2.01 page 53 section 8.4.3: MIDI Channel pressure to Vibrato LFO pitch depth */ + fluid_mod_set_source1(&default_at2viblfo_mod, FLUID_MOD_CHANNELPRESSURE, /* Index=13 */ + FLUID_MOD_GC /* CC=0 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_source2(&default_at2viblfo_mod, 0, 0); /* no second source */ + fluid_mod_set_dest(&default_at2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */ + fluid_mod_set_amount(&default_at2viblfo_mod, 50); - /* SF2.01 page 53 section 8.4.4: Mod wheel (Controller 1) to Vibrato LFO pitch depth */ - fluid_mod_set_source1(&default_mod2viblfo_mod, MODULATION_MSB, /* Index=1 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_source2(&default_mod2viblfo_mod, 0,0); /* no second source */ - fluid_mod_set_dest(&default_mod2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */ - fluid_mod_set_amount(&default_mod2viblfo_mod, 50); + /* SF2.01 page 53 section 8.4.4: Mod wheel (Controller 1) to Vibrato LFO pitch depth */ + fluid_mod_set_source1(&default_mod2viblfo_mod, MODULATION_MSB, /* Index=1 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_source2(&default_mod2viblfo_mod, 0, 0); /* no second source */ + fluid_mod_set_dest(&default_mod2viblfo_mod, GEN_VIBLFOTOPITCH); /* Target: Vib. LFO => pitch */ + fluid_mod_set_amount(&default_mod2viblfo_mod, 50); - /* SF2.01 page 55 section 8.4.5: MIDI continuous controller 7 to initial attenuation*/ - fluid_mod_set_source1(&default_att_mod, VOLUME_MSB, /* index=7 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_CONCAVE /* type=1 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_NEGATIVE /* D=1 */ - ); - fluid_mod_set_source2(&default_att_mod, 0, 0); /* No second source */ - fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&default_att_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ + /* SF2.01 page 55 section 8.4.5: MIDI continuous controller 7 to initial attenuation*/ + fluid_mod_set_source1(&default_att_mod, VOLUME_MSB, /* index=7 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_CONCAVE /* type=1 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_NEGATIVE /* D=1 */ + ); + fluid_mod_set_source2(&default_att_mod, 0, 0); /* No second source */ + fluid_mod_set_dest(&default_att_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ + fluid_mod_set_amount(&default_att_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ - /* SF2.01 page 55 section 8.4.6 MIDI continuous controller 10 to Pan Position */ - fluid_mod_set_source1(&default_pan_mod, PAN_MSB, /* index=10 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_BIPOLAR /* P=1 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_source2(&default_pan_mod, 0, 0); /* No second source */ - fluid_mod_set_dest(&default_pan_mod, GEN_PAN); /* Target: pan */ - /* Amount: 500. The SF specs $8.4.6, p. 55 syas: "Amount = 1000 - tenths of a percent". The center value (64) corresponds to 50%, - so it follows that amount = 50% x 1000/% = 500. */ - fluid_mod_set_amount(&default_pan_mod, 500.0); + /* SF2.01 page 55 section 8.4.6 MIDI continuous controller 10 to Pan Position */ + fluid_mod_set_source1(&default_pan_mod, PAN_MSB, /* index=10 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_BIPOLAR /* P=1 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_source2(&default_pan_mod, 0, 0); /* No second source */ + fluid_mod_set_dest(&default_pan_mod, GEN_PAN); /* Target: pan */ + /* Amount: 500. The SF specs $8.4.6, p. 55 syas: "Amount = 1000 + tenths of a percent". The center value (64) corresponds to 50%, + so it follows that amount = 50% x 1000/% = 500. */ + fluid_mod_set_amount(&default_pan_mod, 500.0); - /* SF2.01 page 55 section 8.4.7: MIDI continuous controller 11 to initial attenuation*/ - fluid_mod_set_source1(&default_expr_mod, EXPRESSION_MSB, /* index=11 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_CONCAVE /* type=1 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_NEGATIVE /* D=1 */ - ); - fluid_mod_set_source2(&default_expr_mod, 0, 0); /* No second source */ - fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ - fluid_mod_set_amount(&default_expr_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ + /* SF2.01 page 55 section 8.4.7: MIDI continuous controller 11 to initial attenuation*/ + fluid_mod_set_source1(&default_expr_mod, EXPRESSION_MSB, /* index=11 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_CONCAVE /* type=1 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_NEGATIVE /* D=1 */ + ); + fluid_mod_set_source2(&default_expr_mod, 0, 0); /* No second source */ + fluid_mod_set_dest(&default_expr_mod, GEN_ATTENUATION); /* Target: Initial attenuation */ + fluid_mod_set_amount(&default_expr_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ - /* SF2.01 page 55 section 8.4.8: MIDI continuous controller 91 to Reverb send */ - fluid_mod_set_source1(&default_reverb_mod, EFFECTS_DEPTH1, /* index=91 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_source2(&default_reverb_mod, 0, 0); /* No second source */ - fluid_mod_set_dest(&default_reverb_mod, GEN_REVERBSEND); /* Target: Reverb send */ - fluid_mod_set_amount(&default_reverb_mod, 200); /* Amount: 200 ('tenths of a percent') */ + /* SF2.01 page 55 section 8.4.8: MIDI continuous controller 91 to Reverb send */ + fluid_mod_set_source1(&default_reverb_mod, EFFECTS_DEPTH1, /* index=91 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_source2(&default_reverb_mod, 0, 0); /* No second source */ + fluid_mod_set_dest(&default_reverb_mod, GEN_REVERBSEND); /* Target: Reverb send */ + fluid_mod_set_amount(&default_reverb_mod, 200); /* Amount: 200 ('tenths of a percent') */ - /* SF2.01 page 55 section 8.4.9: MIDI continuous controller 93 to Chorus send */ - fluid_mod_set_source1(&default_chorus_mod, EFFECTS_DEPTH3, /* index=93 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_source2(&default_chorus_mod, 0, 0); /* No second source */ - fluid_mod_set_dest(&default_chorus_mod, GEN_CHORUSSEND); /* Target: Chorus */ - fluid_mod_set_amount(&default_chorus_mod, 200); /* Amount: 200 ('tenths of a percent') */ + /* SF2.01 page 55 section 8.4.9: MIDI continuous controller 93 to Chorus send */ + fluid_mod_set_source1(&default_chorus_mod, EFFECTS_DEPTH3, /* index=93 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_source2(&default_chorus_mod, 0, 0); /* No second source */ + fluid_mod_set_dest(&default_chorus_mod, GEN_CHORUSSEND); /* Target: Chorus */ + fluid_mod_set_amount(&default_chorus_mod, 200); /* Amount: 200 ('tenths of a percent') */ - /* SF2.01 page 57 section 8.4.10 MIDI Pitch Wheel to Initial Pitch ... */ - fluid_mod_set_source1(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEEL, /* Index=14 */ - FLUID_MOD_GC /* CC =0 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_BIPOLAR /* P=1 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS, /* Index = 16 */ - FLUID_MOD_GC /* CC=0 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_UNIPOLAR /* P=0 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_dest(&default_pitch_bend_mod, GEN_PITCH); /* Destination: Initial pitch */ - fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0); /* Amount: 12700 cents */ + /* SF2.01 page 57 section 8.4.10 MIDI Pitch Wheel to Initial Pitch ... */ + fluid_mod_set_source1(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEEL, /* Index=14 */ + FLUID_MOD_GC /* CC =0 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_BIPOLAR /* P=1 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS, /* Index = 16 */ + FLUID_MOD_GC /* CC=0 */ + | FLUID_MOD_LINEAR /* type=0 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_dest(&default_pitch_bend_mod, GEN_PITCH); /* Destination: Initial pitch */ + fluid_mod_set_amount(&default_pitch_bend_mod, 12700.0); /* Amount: 12700 cents */ - /* Non-standard MIDI continuous controller 8 to channel stereo balance */ - fluid_mod_set_source1(&custom_balance_mod, BALANCE_MSB, /* Index=8 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_CONCAVE /* type=1 */ - | FLUID_MOD_BIPOLAR /* P=1 */ - | FLUID_MOD_POSITIVE /* D=0 */ - ); - fluid_mod_set_source2(&custom_balance_mod, 0, 0); - fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */ - /* Amount: 96 dB of attenuation (on the opposite channel) */ - fluid_mod_set_amount(&custom_balance_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ + /* Non-standard MIDI continuous controller 8 to channel stereo balance */ + fluid_mod_set_source1(&custom_balance_mod, BALANCE_MSB, /* Index=8 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_CONCAVE /* type=1 */ + | FLUID_MOD_BIPOLAR /* P=1 */ + | FLUID_MOD_POSITIVE /* D=0 */ + ); + fluid_mod_set_source2(&custom_balance_mod, 0, 0); + fluid_mod_set_dest(&custom_balance_mod, GEN_CUSTOM_BALANCE); /* Destination: stereo balance */ + /* Amount: 96 dB of attenuation (on the opposite channel) */ + fluid_mod_set_amount(&custom_balance_mod, FLUID_PEAK_ATTENUATION); /* Amount: 960 */ } -static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t* synth) +static FLUID_INLINE unsigned int fluid_synth_get_ticks(fluid_synth_t *synth) { - return fluid_atomic_int_get(&synth->ticks_since_start); + return fluid_atomic_int_get(&synth->ticks_since_start); } -static FLUID_INLINE void fluid_synth_add_ticks(fluid_synth_t* synth, int val) +static FLUID_INLINE void fluid_synth_add_ticks(fluid_synth_t *synth, int val) { - fluid_atomic_int_add(&synth->ticks_since_start, val); + fluid_atomic_int_add(&synth->ticks_since_start, val); } /*************************************************************** - * FLUID SAMPLE TIMERS - * Timers that use written audio data as timing reference + * FLUID SAMPLE TIMERS + * Timers that use written audio data as timing reference */ struct _fluid_sample_timer_t { - fluid_sample_timer_t* next; /* Single linked list of timers */ - unsigned long starttick; - fluid_timer_callback_t callback; - void* data; - int isfinished; + fluid_sample_timer_t *next; /* Single linked list of timers */ + unsigned long starttick; + fluid_timer_callback_t callback; + void *data; + int isfinished; }; /* * fluid_sample_timer_process - called when synth->ticks is updated */ -static void fluid_sample_timer_process(fluid_synth_t* synth) +static void fluid_sample_timer_process(fluid_synth_t *synth) { - fluid_sample_timer_t* st, *stnext; - long msec; - int cont; - unsigned int ticks = fluid_synth_get_ticks(synth); - - for (st=synth->sample_timers; st; st=stnext) { - /* st may be freed in the callback below. cache it's successor now to avoid use after free */ - stnext = st->next; - - if (st->isfinished) { - continue; - } - msec = (long) (1000.0*((double) (ticks - st->starttick))/synth->sample_rate); - cont = (*st->callback)(st->data, msec); - if (cont == 0) { - st->isfinished = 1; - } - } + fluid_sample_timer_t *st, *stnext; + long msec; + int cont; + unsigned int ticks = fluid_synth_get_ticks(synth); + + for(st = synth->sample_timers; st; st = stnext) + { + /* st may be freed in the callback below. cache it's successor now to avoid use after free */ + stnext = st->next; + + if(st->isfinished) + { + continue; + } + + msec = (long)(1000.0 * ((double)(ticks - st->starttick)) / synth->sample_rate); + cont = (*st->callback)(st->data, msec); + + if(cont == 0) + { + st->isfinished = 1; + } + } } -fluid_sample_timer_t* new_fluid_sample_timer(fluid_synth_t* synth, fluid_timer_callback_t callback, void* data) +fluid_sample_timer_t *new_fluid_sample_timer(fluid_synth_t *synth, fluid_timer_callback_t callback, void *data) { - fluid_sample_timer_t* result = FLUID_NEW(fluid_sample_timer_t); - if (result == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - result->starttick = fluid_synth_get_ticks(synth); - result->isfinished = 0; - result->data = data; - result->callback = callback; - result->next = synth->sample_timers; - synth->sample_timers = result; - return result; + fluid_sample_timer_t *result = FLUID_NEW(fluid_sample_timer_t); + + if(result == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + result->starttick = fluid_synth_get_ticks(synth); + result->isfinished = 0; + result->data = data; + result->callback = callback; + result->next = synth->sample_timers; + synth->sample_timers = result; + return result; } -void delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t* timer) +void delete_fluid_sample_timer(fluid_synth_t *synth, fluid_sample_timer_t *timer) { - fluid_sample_timer_t** ptr; + fluid_sample_timer_t **ptr; fluid_return_if_fail(synth != NULL); fluid_return_if_fail(timer != NULL); - - ptr = &synth->sample_timers; - while (*ptr) { - if (*ptr == timer) { - *ptr = timer->next; - FLUID_FREE(timer); + + ptr = &synth->sample_timers; + + while(*ptr) + { + if(*ptr == timer) + { + *ptr = timer->next; + FLUID_FREE(timer); return; - } - ptr = &((*ptr)->next); - } + } + + ptr = &((*ptr)->next); + } } @@ -558,21 +571,21 @@ void delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t* timer */ static FLUID_INLINE void -fluid_synth_update_mixer(fluid_synth_t* synth, fluid_rvoice_function_t method, int intparam, - fluid_real_t realparam) +fluid_synth_update_mixer(fluid_synth_t *synth, fluid_rvoice_function_t method, int intparam, + fluid_real_t realparam) { - fluid_return_if_fail(synth != NULL && synth->eventhandler != NULL); - fluid_return_if_fail(synth->eventhandler->mixer != NULL); - fluid_rvoice_eventhandler_push_int_real(synth->eventhandler, method, - synth->eventhandler->mixer, - intparam, realparam); + fluid_return_if_fail(synth != NULL && synth->eventhandler != NULL); + fluid_return_if_fail(synth->eventhandler->mixer != NULL); + fluid_rvoice_eventhandler_push_int_real(synth->eventhandler, method, + synth->eventhandler->mixer, + intparam, realparam); } -static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_synth_t* synth) +static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_synth_t *synth) { int i; fluid_settings_getint(synth->settings, "synth.min-note-length", &i); - return (unsigned int) (i*synth->sample_rate/1000.0f); + return (unsigned int)(i * synth->sample_rate / 1000.0f); } /** @@ -583,317 +596,362 @@ static FLUID_INLINE unsigned int fluid_synth_get_min_note_length_LOCAL(fluid_syn * @note The settings parameter is used directly and should not be modified * or freed independently. */ -fluid_synth_t* +fluid_synth_t * new_fluid_synth(fluid_settings_t *settings) { - fluid_synth_t* synth; - fluid_sfloader_t* loader; - char *important_channels; - int i, nbuf, prio_level = 0; - int with_ladspa = 0; - - /* initialize all the conversion tables and other stuff */ - if (fluid_atomic_int_compare_and_exchange(&fluid_synth_initialized, 0, 1)) - { - fluid_synth_init(); - } + fluid_synth_t *synth; + fluid_sfloader_t *loader; + char *important_channels; + int i, nbuf, prio_level = 0; + int with_ladspa = 0; - /* allocate a new synthesizer object */ - synth = FLUID_NEW(fluid_synth_t); - if (synth == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t)); + /* initialize all the conversion tables and other stuff */ + if(fluid_atomic_int_compare_and_exchange(&fluid_synth_initialized, 0, 1)) + { + fluid_synth_init(); + } - fluid_rec_mutex_init(synth->mutex); - fluid_settings_getint(settings, "synth.threadsafe-api", &synth->use_mutex); - synth->public_api_count = 0; - - synth->settings = settings; + /* allocate a new synthesizer object */ + synth = FLUID_NEW(fluid_synth_t); - fluid_settings_getint(settings, "synth.reverb.active", &synth->with_reverb); - fluid_settings_getint(settings, "synth.chorus.active", &synth->with_chorus); - fluid_settings_getint(settings, "synth.verbose", &synth->verbose); + if(synth == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony); - fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate); - fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels); - fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels); - fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups); - fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels); - fluid_settings_getnum_float(settings, "synth.gain", &synth->gain); - fluid_settings_getint(settings, "synth.device-id", &synth->device_id); - fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores); + FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t)); - fluid_settings_getnum_float(settings, "synth.overflow.percussion", &synth->overflow.percussion); - fluid_settings_getnum_float(settings, "synth.overflow.released", &synth->overflow.released); - fluid_settings_getnum_float(settings, "synth.overflow.sustained", &synth->overflow.sustained); - fluid_settings_getnum_float(settings, "synth.overflow.volume", &synth->overflow.volume); - fluid_settings_getnum_float(settings, "synth.overflow.age", &synth->overflow.age); - fluid_settings_getnum_float(settings, "synth.overflow.important", &synth->overflow.important); + fluid_rec_mutex_init(synth->mutex); + fluid_settings_getint(settings, "synth.threadsafe-api", &synth->use_mutex); + synth->public_api_count = 0; - /* register the callbacks */ - fluid_settings_callback_num(settings, "synth.sample-rate", - fluid_synth_handle_sample_rate, synth); - fluid_settings_callback_num(settings, "synth.gain", - fluid_synth_handle_gain, synth); - fluid_settings_callback_int(settings, "synth.polyphony", - fluid_synth_handle_polyphony, synth); - fluid_settings_callback_int(settings, "synth.device-id", - fluid_synth_handle_device_id, synth); - fluid_settings_callback_num(settings, "synth.overflow.percussion", - fluid_synth_handle_overflow, synth); - fluid_settings_callback_num(settings, "synth.overflow.sustained", - fluid_synth_handle_overflow, synth); - fluid_settings_callback_num(settings, "synth.overflow.released", - fluid_synth_handle_overflow, synth); - fluid_settings_callback_num(settings, "synth.overflow.age", - fluid_synth_handle_overflow, synth); - fluid_settings_callback_num(settings, "synth.overflow.volume", - fluid_synth_handle_overflow, synth); - fluid_settings_callback_num(settings, "synth.overflow.important", - fluid_synth_handle_overflow, synth); - fluid_settings_callback_str(settings, "synth.overflow.important-channels", - fluid_synth_handle_important_channels, synth); - fluid_settings_callback_num(settings, "synth.reverb.room-size", - fluid_synth_handle_reverb_chorus_num, synth); - fluid_settings_callback_num(settings, "synth.reverb.damp", - fluid_synth_handle_reverb_chorus_num, synth); - fluid_settings_callback_num(settings, "synth.reverb.width", - fluid_synth_handle_reverb_chorus_num, synth); - fluid_settings_callback_num(settings, "synth.reverb.level", - fluid_synth_handle_reverb_chorus_num, synth); - fluid_settings_callback_int(settings, "synth.reverb.active", - fluid_synth_handle_reverb_chorus_int, synth); - fluid_settings_callback_int(settings, "synth.chorus.active", - fluid_synth_handle_reverb_chorus_int, synth); - fluid_settings_callback_int(settings, "synth.chorus.nr", - fluid_synth_handle_reverb_chorus_int, synth); - fluid_settings_callback_num(settings, "synth.chorus.level", - fluid_synth_handle_reverb_chorus_num, synth); - fluid_settings_callback_num(settings, "synth.chorus.depth", - fluid_synth_handle_reverb_chorus_num, synth); - fluid_settings_callback_num(settings, "synth.chorus.speed", - fluid_synth_handle_reverb_chorus_num, synth); + synth->settings = settings; - /* do some basic sanity checking on the settings */ + fluid_settings_getint(settings, "synth.reverb.active", &synth->with_reverb); + fluid_settings_getint(settings, "synth.chorus.active", &synth->with_chorus); + fluid_settings_getint(settings, "synth.verbose", &synth->verbose); - if (synth->midi_channels % 16 != 0) { - int n = synth->midi_channels / 16; - synth->midi_channels = (n + 1) * 16; - fluid_settings_setint(settings, "synth.midi-channels", synth->midi_channels); - FLUID_LOG(FLUID_WARN, "Requested number of MIDI channels is not a multiple of 16. " - "I'll increase the number of channels to the next multiple."); - } + fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony); + fluid_settings_getnum(settings, "synth.sample-rate", &synth->sample_rate); + fluid_settings_getint(settings, "synth.midi-channels", &synth->midi_channels); + fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels); + fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups); + fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels); + fluid_settings_getnum_float(settings, "synth.gain", &synth->gain); + fluid_settings_getint(settings, "synth.device-id", &synth->device_id); + fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores); - if (synth->audio_channels < 1) { - FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. " - "Changing this setting to 1."); - synth->audio_channels = 1; - } else if (synth->audio_channels > 128) { - FLUID_LOG(FLUID_WARN, "Requested number of audio channels is too big (%d). " - "Limiting this setting to 128.", synth->audio_channels); - synth->audio_channels = 128; - } + fluid_settings_getnum_float(settings, "synth.overflow.percussion", &synth->overflow.percussion); + fluid_settings_getnum_float(settings, "synth.overflow.released", &synth->overflow.released); + fluid_settings_getnum_float(settings, "synth.overflow.sustained", &synth->overflow.sustained); + fluid_settings_getnum_float(settings, "synth.overflow.volume", &synth->overflow.volume); + fluid_settings_getnum_float(settings, "synth.overflow.age", &synth->overflow.age); + fluid_settings_getnum_float(settings, "synth.overflow.important", &synth->overflow.important); - if (synth->audio_groups < 1) { - FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. " - "Changing this setting to 1."); - synth->audio_groups = 1; - } else if (synth->audio_groups > 128) { - FLUID_LOG(FLUID_WARN, "Requested number of audio groups is too big (%d). " - "Limiting this setting to 128.", synth->audio_groups); - synth->audio_groups = 128; - } + /* register the callbacks */ + fluid_settings_callback_num(settings, "synth.sample-rate", + fluid_synth_handle_sample_rate, synth); + fluid_settings_callback_num(settings, "synth.gain", + fluid_synth_handle_gain, synth); + fluid_settings_callback_int(settings, "synth.polyphony", + fluid_synth_handle_polyphony, synth); + fluid_settings_callback_int(settings, "synth.device-id", + fluid_synth_handle_device_id, synth); + fluid_settings_callback_num(settings, "synth.overflow.percussion", + fluid_synth_handle_overflow, synth); + fluid_settings_callback_num(settings, "synth.overflow.sustained", + fluid_synth_handle_overflow, synth); + fluid_settings_callback_num(settings, "synth.overflow.released", + fluid_synth_handle_overflow, synth); + fluid_settings_callback_num(settings, "synth.overflow.age", + fluid_synth_handle_overflow, synth); + fluid_settings_callback_num(settings, "synth.overflow.volume", + fluid_synth_handle_overflow, synth); + fluid_settings_callback_num(settings, "synth.overflow.important", + fluid_synth_handle_overflow, synth); + fluid_settings_callback_str(settings, "synth.overflow.important-channels", + fluid_synth_handle_important_channels, synth); + fluid_settings_callback_num(settings, "synth.reverb.room-size", + fluid_synth_handle_reverb_chorus_num, synth); + fluid_settings_callback_num(settings, "synth.reverb.damp", + fluid_synth_handle_reverb_chorus_num, synth); + fluid_settings_callback_num(settings, "synth.reverb.width", + fluid_synth_handle_reverb_chorus_num, synth); + fluid_settings_callback_num(settings, "synth.reverb.level", + fluid_synth_handle_reverb_chorus_num, synth); + fluid_settings_callback_int(settings, "synth.reverb.active", + fluid_synth_handle_reverb_chorus_int, synth); + fluid_settings_callback_int(settings, "synth.chorus.active", + fluid_synth_handle_reverb_chorus_int, synth); + fluid_settings_callback_int(settings, "synth.chorus.nr", + fluid_synth_handle_reverb_chorus_int, synth); + fluid_settings_callback_num(settings, "synth.chorus.level", + fluid_synth_handle_reverb_chorus_num, synth); + fluid_settings_callback_num(settings, "synth.chorus.depth", + fluid_synth_handle_reverb_chorus_num, synth); + fluid_settings_callback_num(settings, "synth.chorus.speed", + fluid_synth_handle_reverb_chorus_num, synth); - if (synth->effects_channels < 2) { - FLUID_LOG(FLUID_WARN, "Invalid number of effects channels (%d)." - "Setting effects channels to 2.", synth->effects_channels); - synth->effects_channels = 2; - } + /* do some basic sanity checking on the settings */ - /* The number of buffers is determined by the higher number of nr - * groups / nr audio channels. If LADSPA is unused, they should be - * the same. */ - nbuf = synth->audio_channels; - if (synth->audio_groups > nbuf) { - nbuf = synth->audio_groups; - } + if(synth->midi_channels % 16 != 0) + { + int n = synth->midi_channels / 16; + synth->midi_channels = (n + 1) * 16; + fluid_settings_setint(settings, "synth.midi-channels", synth->midi_channels); + FLUID_LOG(FLUID_WARN, "Requested number of MIDI channels is not a multiple of 16. " + "I'll increase the number of channels to the next multiple."); + } - if (fluid_settings_dupstr(settings, "synth.overflow.important-channels", - &important_channels) == FLUID_OK) - { - if (fluid_synth_set_important_channels(synth, important_channels) != FLUID_OK) - { - FLUID_LOG(FLUID_WARN, "Failed to set overflow important channels"); - } - FLUID_FREE(important_channels); - } + if(synth->audio_channels < 1) + { + FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. " + "Changing this setting to 1."); + synth->audio_channels = 1; + } + else if(synth->audio_channels > 128) + { + FLUID_LOG(FLUID_WARN, "Requested number of audio channels is too big (%d). " + "Limiting this setting to 128.", synth->audio_channels); + synth->audio_channels = 128; + } - /* as soon as the synth is created it starts playing. */ - synth->state = FLUID_SYNTH_PLAYING; - - synth->fromkey_portamento = INVALID_NOTE; /* disable portamento */ + if(synth->audio_groups < 1) + { + FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. " + "Changing this setting to 1."); + synth->audio_groups = 1; + } + else if(synth->audio_groups > 128) + { + FLUID_LOG(FLUID_WARN, "Requested number of audio groups is too big (%d). " + "Limiting this setting to 128.", synth->audio_groups); + synth->audio_groups = 128; + } - fluid_atomic_int_set(&synth->ticks_since_start, 0); - synth->tuning = NULL; - fluid_private_init(synth->tuning_iter); - - /* Initialize multi-core variables if multiple cores enabled */ - if (synth->cores > 1) - { - fluid_settings_getint (synth->settings, "audio.realtime-prio", &prio_level); - } - - /* Allocate event queue for rvoice mixer */ - /* In an overflow situation, a new voice takes about 50 spaces in the queue! */ - synth->eventhandler = new_fluid_rvoice_eventhandler(synth->polyphony*64, - synth->polyphony, nbuf, synth->effects_channels, synth->sample_rate, synth->cores-1, prio_level); + if(synth->effects_channels < 2) + { + FLUID_LOG(FLUID_WARN, "Invalid number of effects channels (%d)." + "Setting effects channels to 2.", synth->effects_channels); + synth->effects_channels = 2; + } - if (synth->eventhandler == NULL) - goto error_recovery; + /* The number of buffers is determined by the higher number of nr + * groups / nr audio channels. If LADSPA is unused, they should be + * the same. */ + nbuf = synth->audio_channels; - /* Setup the list of default modulators. - * Needs to happen after eventhandler has been set up, as fluid_synth_enter_api is called in the process */ - synth->default_mod = NULL; - fluid_synth_add_default_mod(synth, &default_vel2att_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_vel2filter_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_at2viblfo_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_mod2viblfo_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_att_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_pan_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_expr_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_reverb_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_chorus_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &default_pitch_bend_mod, FLUID_SYNTH_ADD); - fluid_synth_add_default_mod(synth, &custom_balance_mod, FLUID_SYNTH_ADD); + if(synth->audio_groups > nbuf) + { + nbuf = synth->audio_groups; + } - /* Create and initialize the Fx unit.*/ - fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa); - if (with_ladspa) { + if(fluid_settings_dupstr(settings, "synth.overflow.important-channels", + &important_channels) == FLUID_OK) + { + if(fluid_synth_set_important_channels(synth, important_channels) != FLUID_OK) + { + FLUID_LOG(FLUID_WARN, "Failed to set overflow important channels"); + } + + FLUID_FREE(important_channels); + } + + /* as soon as the synth is created it starts playing. */ + synth->state = FLUID_SYNTH_PLAYING; + + synth->fromkey_portamento = INVALID_NOTE; /* disable portamento */ + + fluid_atomic_int_set(&synth->ticks_since_start, 0); + synth->tuning = NULL; + fluid_private_init(synth->tuning_iter); + + /* Initialize multi-core variables if multiple cores enabled */ + if(synth->cores > 1) + { + fluid_settings_getint(synth->settings, "audio.realtime-prio", &prio_level); + } + + /* Allocate event queue for rvoice mixer */ + /* In an overflow situation, a new voice takes about 50 spaces in the queue! */ + synth->eventhandler = new_fluid_rvoice_eventhandler(synth->polyphony * 64, + synth->polyphony, nbuf, synth->effects_channels, synth->sample_rate, synth->cores - 1, prio_level); + + if(synth->eventhandler == NULL) + { + goto error_recovery; + } + + /* Setup the list of default modulators. + * Needs to happen after eventhandler has been set up, as fluid_synth_enter_api is called in the process */ + synth->default_mod = NULL; + fluid_synth_add_default_mod(synth, &default_vel2att_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_vel2filter_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_at2viblfo_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_mod2viblfo_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_att_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_pan_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_expr_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_reverb_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_chorus_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &default_pitch_bend_mod, FLUID_SYNTH_ADD); + fluid_synth_add_default_mod(synth, &custom_balance_mod, FLUID_SYNTH_ADD); + + /* Create and initialize the Fx unit.*/ + fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa); + + if(with_ladspa) + { #ifdef LADSPA - synth->ladspa_fx = new_fluid_ladspa_fx(synth->sample_rate, - FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE); - if(synth->ladspa_fx == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } - fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->ladspa_fx, - synth->audio_groups); + synth->ladspa_fx = new_fluid_ladspa_fx(synth->sample_rate, + FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE); + + if(synth->ladspa_fx == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + + fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->ladspa_fx, + synth->audio_groups); #else /* LADSPA */ - FLUID_LOG(FLUID_WARN, "FluidSynth has not been compiled with LADSPA support"); + FLUID_LOG(FLUID_WARN, "FluidSynth has not been compiled with LADSPA support"); #endif /* LADSPA */ - } - - /* allocate and add the default sfont loader */ - loader = new_fluid_defsfloader(settings); - - if (loader == NULL) { - FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader"); - } else { - fluid_synth_add_sfloader(synth, loader); - } - - /* allocate all channel objects */ - synth->channel = FLUID_ARRAY(fluid_channel_t*, synth->midi_channels); - if (synth->channel == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - goto error_recovery; - } - for (i = 0; i < synth->midi_channels; i++) { - synth->channel[i] = new_fluid_channel(synth, i); - if (synth->channel[i] == NULL) { - goto error_recovery; } - } - /* allocate all synthesis processes */ - synth->nvoice = synth->polyphony; - synth->voice = FLUID_ARRAY(fluid_voice_t*, synth->nvoice); - if (synth->voice == NULL) { - goto error_recovery; - } - for (i = 0; i < synth->nvoice; i++) { - synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate); - if (synth->voice[i] == NULL) { - goto error_recovery; + /* allocate and add the default sfont loader */ + loader = new_fluid_defsfloader(settings); + + if(loader == NULL) + { + FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader"); + } + else + { + fluid_synth_add_sfloader(synth, loader); } - } - /* sets a default basic channel */ - /* Sets one basic channel: basic channel 0, mode 0 (Omni On - Poly) */ - /* (i.e all channels are polyphonic) */ - /* Must be called after channel objects allocation */ - fluid_synth_set_basic_channel_LOCAL(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY, - synth->midi_channels); + /* allocate all channel objects */ + synth->channel = FLUID_ARRAY(fluid_channel_t *, synth->midi_channels); - synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth); - - - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony, - synth->polyphony, 0.0f); - fluid_synth_set_reverb_on(synth, synth->with_reverb); - fluid_synth_set_chorus_on(synth, synth->with_chorus); - - synth->cur = FLUID_BUFSIZE; - synth->curmax = 0; - synth->dither_index = 0; + if(synth->channel == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } - { - double room, damp, width, level; - - fluid_settings_getnum(settings, "synth.reverb.room-size", &room); - fluid_settings_getnum(settings, "synth.reverb.damp", &damp); - fluid_settings_getnum(settings, "synth.reverb.width", &width); - fluid_settings_getnum(settings, "synth.reverb.level", &level); - - fluid_synth_set_reverb_full_LOCAL(synth, - FLUID_REVMODEL_SET_ALL, - room, - damp, - width, - level); - } - - { - double level, speed, depth; - - fluid_settings_getint(settings, "synth.chorus.nr", &i); - fluid_settings_getnum(settings, "synth.chorus.level", &level); - fluid_settings_getnum(settings, "synth.chorus.speed", &speed); - fluid_settings_getnum(settings, "synth.chorus.depth", &depth); + for(i = 0; i < synth->midi_channels; i++) + { + synth->channel[i] = new_fluid_channel(synth, i); - fluid_synth_set_chorus_full_LOCAL(synth, - FLUID_CHORUS_SET_ALL, - i, - level, - speed, - depth, - FLUID_CHORUS_DEFAULT_TYPE); - } + if(synth->channel[i] == NULL) + { + goto error_recovery; + } + } + + /* allocate all synthesis processes */ + synth->nvoice = synth->polyphony; + synth->voice = FLUID_ARRAY(fluid_voice_t *, synth->nvoice); + + if(synth->voice == NULL) + { + goto error_recovery; + } + + for(i = 0; i < synth->nvoice; i++) + { + synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate); + + if(synth->voice[i] == NULL) + { + goto error_recovery; + } + } + + /* sets a default basic channel */ + /* Sets one basic channel: basic channel 0, mode 0 (Omni On - Poly) */ + /* (i.e all channels are polyphonic) */ + /* Must be called after channel objects allocation */ + fluid_synth_set_basic_channel_LOCAL(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY, + synth->midi_channels); + + synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth); + + + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony, + synth->polyphony, 0.0f); + fluid_synth_set_reverb_on(synth, synth->with_reverb); + fluid_synth_set_chorus_on(synth, synth->with_chorus); + + synth->cur = FLUID_BUFSIZE; + synth->curmax = 0; + synth->dither_index = 0; + + { + double room, damp, width, level; + + fluid_settings_getnum(settings, "synth.reverb.room-size", &room); + fluid_settings_getnum(settings, "synth.reverb.damp", &damp); + fluid_settings_getnum(settings, "synth.reverb.width", &width); + fluid_settings_getnum(settings, "synth.reverb.level", &level); + + fluid_synth_set_reverb_full_LOCAL(synth, + FLUID_REVMODEL_SET_ALL, + room, + damp, + width, + level); + } + + { + double level, speed, depth; + + fluid_settings_getint(settings, "synth.chorus.nr", &i); + fluid_settings_getnum(settings, "synth.chorus.level", &level); + fluid_settings_getnum(settings, "synth.chorus.speed", &speed); + fluid_settings_getnum(settings, "synth.chorus.depth", &depth); + + fluid_synth_set_chorus_full_LOCAL(synth, + FLUID_CHORUS_SET_ALL, + i, + level, + speed, + depth, + FLUID_CHORUS_DEFAULT_TYPE); + } - synth->bank_select = FLUID_BANK_STYLE_GS; - if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "gm")) - synth->bank_select = FLUID_BANK_STYLE_GM; - else if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "gs")) synth->bank_select = FLUID_BANK_STYLE_GS; - else if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "xg")) - synth->bank_select = FLUID_BANK_STYLE_XG; - else if (fluid_settings_str_equal (settings, "synth.midi-bank-select", "mma")) - synth->bank_select = FLUID_BANK_STYLE_MMA; - fluid_synth_process_event_queue(synth); + if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gm")) + { + synth->bank_select = FLUID_BANK_STYLE_GM; + } + else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "gs")) + { + synth->bank_select = FLUID_BANK_STYLE_GS; + } + else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "xg")) + { + synth->bank_select = FLUID_BANK_STYLE_XG; + } + else if(fluid_settings_str_equal(settings, "synth.midi-bank-select", "mma")) + { + synth->bank_select = FLUID_BANK_STYLE_MMA; + } - /* FIXME */ - synth->start = fluid_curtime(); + fluid_synth_process_event_queue(synth); - return synth; + /* FIXME */ + synth->start = fluid_curtime(); - error_recovery: - delete_fluid_synth(synth); - return NULL; + return synth; + +error_recovery: + delete_fluid_synth(synth); + return NULL; } @@ -905,114 +963,143 @@ new_fluid_synth(fluid_settings_t *settings) * should be deleted prior to freeing the FluidSynth instance. */ void -delete_fluid_synth(fluid_synth_t* synth) +delete_fluid_synth(fluid_synth_t *synth) { - int i, k; - fluid_list_t *list; - fluid_sfont_t* sfont; - fluid_sfloader_t* loader; - fluid_mod_t* default_mod; - fluid_mod_t* mod; + int i, k; + fluid_list_t *list; + fluid_sfont_t *sfont; + fluid_sfloader_t *loader; + fluid_mod_t *default_mod; + fluid_mod_t *mod; - fluid_return_if_fail(synth != NULL); + fluid_return_if_fail(synth != NULL); - fluid_profiling_print(); + fluid_profiling_print(); - /* turn off all voices, needed to unload SoundFont data */ - if (synth->voice != NULL) { - for (i = 0; i < synth->nvoice; i++) { - fluid_voice_t* voice = synth->voice[i]; - if (!voice) - continue; - fluid_voice_unlock_rvoice(voice); - fluid_voice_overflow_rvoice_finished(voice); - if (fluid_voice_is_playing(voice)) { - fluid_voice_off(voice); - /* If we only use fluid_voice_off(voice) it will trigger a delayed - * fluid_voice_stop(voice) via fluid_synth_check_finished_voices(). - * But here, we are deleting the fluid_synth_t instance so - * fluid_voice_stop() will be never triggered resulting in - * SoundFont data never unloaded (i.e a serious memory leak). - * So, fluid_voice_stop() must be explicitly called to insure - * unloading SoundFont data - */ - fluid_voice_stop(voice); - } + /* turn off all voices, needed to unload SoundFont data */ + if(synth->voice != NULL) + { + for(i = 0; i < synth->nvoice; i++) + { + fluid_voice_t *voice = synth->voice[i]; + + if(!voice) + { + continue; + } + + fluid_voice_unlock_rvoice(voice); + fluid_voice_overflow_rvoice_finished(voice); + + if(fluid_voice_is_playing(voice)) + { + fluid_voice_off(voice); + /* If we only use fluid_voice_off(voice) it will trigger a delayed + * fluid_voice_stop(voice) via fluid_synth_check_finished_voices(). + * But here, we are deleting the fluid_synth_t instance so + * fluid_voice_stop() will be never triggered resulting in + * SoundFont data never unloaded (i.e a serious memory leak). + * So, fluid_voice_stop() must be explicitly called to insure + * unloading SoundFont data + */ + fluid_voice_stop(voice); + } + } } - } - /* also unset all presets for clean SoundFont unload */ - if (synth->channel != NULL) - for (i = 0; i < synth->midi_channels; i++) - fluid_channel_set_preset(synth->channel[i], NULL); - - delete_fluid_rvoice_eventhandler(synth->eventhandler); - - /* delete all the SoundFonts */ - for (list = synth->sfont; list; list = fluid_list_next (list)) { - sfont = fluid_list_get (list); - fluid_sfont_delete_internal (sfont); - } - delete_fluid_list(synth->sfont); - - /* delete all the SoundFont loaders */ - - for (list = synth->loaders; list; list = fluid_list_next(list)) { - loader = (fluid_sfloader_t*) fluid_list_get(list); - fluid_sfloader_delete(loader); - } - - delete_fluid_list(synth->loaders); - - - if (synth->channel != NULL) { - for (i = 0; i < synth->midi_channels; i++) { - delete_fluid_channel(synth->channel[i]); + /* also unset all presets for clean SoundFont unload */ + if(synth->channel != NULL) + { + for(i = 0; i < synth->midi_channels; i++) + { + fluid_channel_set_preset(synth->channel[i], NULL); + } } - FLUID_FREE(synth->channel); - } - if (synth->voice != NULL) { - for (i = 0; i < synth->nvoice; i++) { - delete_fluid_voice(synth->voice[i]); + delete_fluid_rvoice_eventhandler(synth->eventhandler); + + /* delete all the SoundFonts */ + for(list = synth->sfont; list; list = fluid_list_next(list)) + { + sfont = fluid_list_get(list); + fluid_sfont_delete_internal(sfont); } - FLUID_FREE(synth->voice); - } + delete_fluid_list(synth->sfont); - /* free the tunings, if any */ - if (synth->tuning != NULL) { - for (i = 0; i < 128; i++) { - if (synth->tuning[i] != NULL) { - for (k = 0; k < 128; k++) { - delete_fluid_tuning(synth->tuning[i][k]); - } - FLUID_FREE(synth->tuning[i]); - } + /* delete all the SoundFont loaders */ + + for(list = synth->loaders; list; list = fluid_list_next(list)) + { + loader = (fluid_sfloader_t *) fluid_list_get(list); + fluid_sfloader_delete(loader); } - FLUID_FREE(synth->tuning); - } - fluid_private_free (synth->tuning_iter); + delete_fluid_list(synth->loaders); + + + if(synth->channel != NULL) + { + for(i = 0; i < synth->midi_channels; i++) + { + delete_fluid_channel(synth->channel[i]); + } + + FLUID_FREE(synth->channel); + } + + if(synth->voice != NULL) + { + for(i = 0; i < synth->nvoice; i++) + { + delete_fluid_voice(synth->voice[i]); + } + + FLUID_FREE(synth->voice); + } + + + /* free the tunings, if any */ + if(synth->tuning != NULL) + { + for(i = 0; i < 128; i++) + { + if(synth->tuning[i] != NULL) + { + for(k = 0; k < 128; k++) + { + delete_fluid_tuning(synth->tuning[i][k]); + } + + FLUID_FREE(synth->tuning[i]); + } + } + + FLUID_FREE(synth->tuning); + } + + fluid_private_free(synth->tuning_iter); #ifdef LADSPA - /* Release the LADSPA effects unit */ + /* Release the LADSPA effects unit */ delete_fluid_ladspa_fx(synth->ladspa_fx); #endif - /* delete all default modulators */ - default_mod = synth->default_mod; - while (default_mod != NULL) { - mod = default_mod; - default_mod = mod->next; - delete_fluid_mod(mod); - } + /* delete all default modulators */ + default_mod = synth->default_mod; - FLUID_FREE(synth->overflow.important_channels); + while(default_mod != NULL) + { + mod = default_mod; + default_mod = mod->next; + delete_fluid_mod(mod); + } - fluid_rec_mutex_destroy(synth->mutex); + FLUID_FREE(synth->overflow.important_channels); - FLUID_FREE(synth); + fluid_rec_mutex_destroy(synth->mutex); + + FLUID_FREE(synth); } /** @@ -1024,10 +1111,10 @@ delete_fluid_synth(fluid_synth_t* synth) */ /* FIXME - The error messages are not thread-safe, yet. They are still stored * in a global message buffer (see fluid_sys.c). */ -const char* -fluid_synth_error(fluid_synth_t* synth) +const char * +fluid_synth_error(fluid_synth_t *synth) { - return fluid_error(); + return fluid_error(); } /** @@ -1039,72 +1126,79 @@ fluid_synth_error(fluid_synth_t* synth) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel) +fluid_synth_noteon(fluid_synth_t *synth, int chan, int key, int vel) { - int result; - fluid_return_val_if_fail (key >= 0 && key <= 127, FLUID_FAILED); - fluid_return_val_if_fail (vel >= 0 && vel <= 127, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - result = fluid_synth_noteon_LOCAL (synth, chan, key, vel); - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED); + fluid_return_val_if_fail(vel >= 0 && vel <= 127, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + result = fluid_synth_noteon_LOCAL(synth, chan, key, vel); + FLUID_API_RETURN(result); } /* Local synthesis thread variant of fluid_synth_noteon */ static int -fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key, int vel) +fluid_synth_noteon_LOCAL(fluid_synth_t *synth, int chan, int key, int vel) { - fluid_channel_t* channel ; - /* notes with velocity zero go to noteoff */ - if (vel == 0) return fluid_synth_noteoff_LOCAL(synth, chan, key); + fluid_channel_t *channel ; - channel = synth->channel[chan]; - - /* makes sure this channel has a preset */ - if (channel->preset == NULL) - { - if (synth->verbose) + /* notes with velocity zero go to noteoff */ + if(vel == 0) { - FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s", - chan, key, vel, 0, - fluid_synth_get_ticks(synth) / 44100.0f, - (fluid_curtime() - synth->start) / 1000.0f, - 0.0f, 0, "channel has no preset"); + return fluid_synth_noteoff_LOCAL(synth, chan, key); } - return FLUID_FAILED; - } - - if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */ - { /* play the noteOn in monophonic */ - return fluid_synth_noteon_mono_LOCAL(synth, chan, key, vel); - } - else - { /* channel is poly and legato CC is Off) */ - /* plays the noteOn in polyphonic */ - /* Sets the note at first position in monophonic list */ - /* In the case where the musician intends to inter the channel in monophonic - (by depressing the CC legato on), the next noteOn mono could be played legato - with the previous note poly (if the musician choose this). - */ - fluid_channel_set_onenote_monolist(channel, (unsigned char) key, - (unsigned char) vel); + channel = synth->channel[chan]; - /* If there is another voice process on the same channel and key, - advance it to the release phase. */ - fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, key); - - /* a noteon poly is passed to fluid_synth_noteon_monopoly_legato(). - This allows an opportunity to get this note played legato with a previous - note if a CC PTC have been received before this noteon. This behavior is - a MIDI specification (see FluidPolymono-0004.pdf chapter 4.3-a ,3.4.11 - for details). - */ - return fluid_synth_noteon_monopoly_legato(synth, chan, INVALID_NOTE, key, vel); - } + /* makes sure this channel has a preset */ + if(channel->preset == NULL) + { + if(synth->verbose) + { + FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d\t%s", + chan, key, vel, 0, + fluid_synth_get_ticks(synth) / 44100.0f, + (fluid_curtime() - synth->start) / 1000.0f, + 0.0f, 0, "channel has no preset"); + } + + return FLUID_FAILED; + } + + if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */ + { + /* play the noteOn in monophonic */ + return fluid_synth_noteon_mono_LOCAL(synth, chan, key, vel); + } + else + { + /* channel is poly and legato CC is Off) */ + + /* plays the noteOn in polyphonic */ + /* Sets the note at first position in monophonic list */ + /* In the case where the musician intends to inter the channel in monophonic + (by depressing the CC legato on), the next noteOn mono could be played legato + with the previous note poly (if the musician choose this). + */ + fluid_channel_set_onenote_monolist(channel, (unsigned char) key, + (unsigned char) vel); + + /* If there is another voice process on the same channel and key, + advance it to the release phase. */ + fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, key); + + /* a noteon poly is passed to fluid_synth_noteon_monopoly_legato(). + This allows an opportunity to get this note played legato with a previous + note if a CC PTC have been received before this noteon. This behavior is + a MIDI specification (see FluidPolymono-0004.pdf chapter 4.3-a ,3.4.11 + for details). + */ + return fluid_synth_noteon_monopoly_legato(synth, chan, INVALID_NOTE, key, vel); + } } /** @@ -1116,97 +1210,107 @@ fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key, int vel) * voices matched the note off event) */ int -fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key) +fluid_synth_noteoff(fluid_synth_t *synth, int chan, int key) { - int result; - fluid_return_val_if_fail (key >= 0 && key <= 127, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - result = fluid_synth_noteoff_LOCAL (synth, chan, key); - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + result = fluid_synth_noteoff_LOCAL(synth, chan, key); + FLUID_API_RETURN(result); } /* Local synthesis thread variant of fluid_synth_noteoff */ static int -fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key) +fluid_synth_noteoff_LOCAL(fluid_synth_t *synth, int chan, int key) { - int status; - fluid_channel_t* channel = synth->channel[chan]; - if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */ - { /* play the noteOff in monophonic */ - status = fluid_synth_noteoff_mono_LOCAL(synth, chan, key); - } - else - { /* channel is poly and legato CC is Off) */ - /* removes the note from the monophonic list */ - if(key == fluid_channel_last_note(channel)) - { - fluid_channel_clear_monolist(channel); - } - status = fluid_synth_noteoff_monopoly(synth, chan, key, 0); - } - /* Changes the state (Valid/Invalid) of the most recent note played in a - staccato manner */ - fluid_channel_invalid_prev_note_staccato(channel); - return status; + int status; + fluid_channel_t *channel = synth->channel[chan]; + + if(fluid_channel_is_playing_mono(channel)) /* channel is mono or legato CC is On) */ + { + /* play the noteOff in monophonic */ + status = fluid_synth_noteoff_mono_LOCAL(synth, chan, key); + } + else + { + /* channel is poly and legato CC is Off) */ + /* removes the note from the monophonic list */ + if(key == fluid_channel_last_note(channel)) + { + fluid_channel_clear_monolist(channel); + } + + status = fluid_synth_noteoff_monopoly(synth, chan, key, 0); + } + + /* Changes the state (Valid/Invalid) of the most recent note played in a + staccato manner */ + fluid_channel_invalid_prev_note_staccato(channel); + return status; } /* Damps voices on a channel (turn notes off), if they're sustained by sustain pedal */ static int -fluid_synth_damp_voices_by_sustain_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_damp_voices_by_sustain_LOCAL(fluid_synth_t *synth, int chan) { - fluid_channel_t* channel = synth->channel[chan]; - fluid_voice_t* voice; - int i; + fluid_channel_t *channel = synth->channel[chan]; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) - { - voice = synth->voice[i]; - if ((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sustained(voice)) + for(i = 0; i < synth->polyphony; i++) { - if(voice->key == channel->key_mono_sustained) - { - /* key_mono_sustained is a possible mono note sustainted - (by sustain or sostenuto pedal). It must be marked released - (INVALID_NOTE) here because it is released only by sustain pedal */ - channel->key_mono_sustained = INVALID_NOTE; - } - fluid_voice_release(voice); + voice = synth->voice[i]; + + if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sustained(voice)) + { + if(voice->key == channel->key_mono_sustained) + { + /* key_mono_sustained is a possible mono note sustainted + (by sustain or sostenuto pedal). It must be marked released + (INVALID_NOTE) here because it is released only by sustain pedal */ + channel->key_mono_sustained = INVALID_NOTE; + } + + fluid_voice_release(voice); + } } - } - return FLUID_OK; + + return FLUID_OK; } /* Damps voices on a channel (turn notes off), if they're sustained by sostenuto pedal */ static int -fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t *synth, int chan) { - fluid_channel_t* channel = synth->channel[chan]; - fluid_voice_t* voice; - int i; + fluid_channel_t *channel = synth->channel[chan]; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) - { - voice = synth->voice[i]; - - if ((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sostenuto(voice)) + for(i = 0; i < synth->polyphony; i++) { - if(voice->key == channel->key_mono_sustained) + voice = synth->voice[i]; + + if((fluid_voice_get_channel(voice) == chan) && fluid_voice_is_sostenuto(voice)) { - /* key_mono_sustained is a possible mono note sustainted - (by sustain or sostenuto pedal). It must be marked released - (INVALID_NOTE) here because it is released only by sostenuto pedal */ - channel->key_mono_sustained = INVALID_NOTE; + if(voice->key == channel->key_mono_sustained) + { + /* key_mono_sustained is a possible mono note sustainted + (by sustain or sostenuto pedal). It must be marked released + (INVALID_NOTE) here because it is released only by sostenuto pedal */ + channel->key_mono_sustained = INVALID_NOTE; + } + + fluid_voice_release(voice); } - fluid_voice_release(voice); } - } - return FLUID_OK; + + return FLUID_OK; } /** @@ -1219,46 +1323,63 @@ fluid_synth_damp_voices_by_sostenuto_LOCAL(fluid_synth_t* synth, int chan) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_add_default_mod(fluid_synth_t* synth, fluid_mod_t* mod, int mode) +fluid_synth_add_default_mod(fluid_synth_t *synth, fluid_mod_t *mod, int mode) { - fluid_mod_t* default_mod; - fluid_mod_t* last_mod = NULL; - fluid_mod_t* new_mod; + fluid_mod_t *default_mod; + fluid_mod_t *last_mod = NULL; + fluid_mod_t *new_mod; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (mod != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(mod != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - default_mod = synth->default_mod; + default_mod = synth->default_mod; - while (default_mod != NULL) { - if (fluid_mod_test_identity(default_mod, mod)) { - if (mode == FLUID_SYNTH_ADD) - default_mod->amount += mod->amount; - else if (mode == FLUID_SYNTH_OVERWRITE) - default_mod->amount = mod->amount; - else - FLUID_API_RETURN(FLUID_FAILED); - FLUID_API_RETURN(FLUID_OK); + while(default_mod != NULL) + { + if(fluid_mod_test_identity(default_mod, mod)) + { + if(mode == FLUID_SYNTH_ADD) + { + default_mod->amount += mod->amount; + } + else if(mode == FLUID_SYNTH_OVERWRITE) + { + default_mod->amount = mod->amount; + } + else + { + FLUID_API_RETURN(FLUID_FAILED); + } + + FLUID_API_RETURN(FLUID_OK); + } + + last_mod = default_mod; + default_mod = default_mod->next; } - last_mod = default_mod; - default_mod = default_mod->next; - } - /* Add a new modulator (no existing modulator to add / overwrite). */ - new_mod = new_fluid_mod(); - if (new_mod == NULL) - FLUID_API_RETURN(FLUID_FAILED); + /* Add a new modulator (no existing modulator to add / overwrite). */ + new_mod = new_fluid_mod(); - fluid_mod_clone(new_mod, mod); - new_mod->next = NULL; + if(new_mod == NULL) + { + FLUID_API_RETURN(FLUID_FAILED); + } - if (last_mod == NULL) - synth->default_mod = new_mod; - else - last_mod->next = new_mod; + fluid_mod_clone(new_mod, mod); + new_mod->next = NULL; - FLUID_API_RETURN(FLUID_OK); + if(last_mod == NULL) + { + synth->default_mod = new_mod; + } + else + { + last_mod->next = new_mod; + } + + FLUID_API_RETURN(FLUID_OK); } /** @@ -1269,36 +1390,39 @@ fluid_synth_add_default_mod(fluid_synth_t* synth, fluid_mod_t* mod, int mode) * @return #FLUID_OK if a matching modulator was found and successfully removed, #FLUID_FAILED otherwise */ int -fluid_synth_remove_default_mod(fluid_synth_t* synth, const fluid_mod_t* mod) +fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod) { - fluid_mod_t* default_mod; - fluid_mod_t* last_mod; + fluid_mod_t *default_mod; + fluid_mod_t *last_mod; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (mod != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(mod != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - last_mod = default_mod = synth->default_mod; + last_mod = default_mod = synth->default_mod; - while (default_mod != NULL) { - if (fluid_mod_test_identity(default_mod, mod)) + while(default_mod != NULL) { - if(synth->default_mod == default_mod) + if(fluid_mod_test_identity(default_mod, mod)) { - synth->default_mod = synth->default_mod->next; - } - else - { - last_mod->next = default_mod->next; - } - delete_fluid_mod(default_mod); - FLUID_API_RETURN(FLUID_OK); - } - last_mod = default_mod; - default_mod = default_mod->next; - } + if(synth->default_mod == default_mod) + { + synth->default_mod = synth->default_mod->next; + } + else + { + last_mod->next = default_mod->next; + } - FLUID_API_RETURN(FLUID_FAILED); + delete_fluid_mod(default_mod); + FLUID_API_RETURN(FLUID_OK); + } + + last_mod = default_mod; + default_mod = default_mod->next; + } + + FLUID_API_RETURN(FLUID_FAILED); } @@ -1311,248 +1435,313 @@ fluid_synth_remove_default_mod(fluid_synth_t* synth, const fluid_mod_t* mod) * @return #FLUID_OK on success, #FLUID_FAILED otherwise * @note This function supports MIDI Global Controllers which will be sent to * all channels of the basic channel if this basic channel is in mode OmniOff/Mono. - * This is accomplished by sending the CC one MIDI channel below the basic + * This is accomplished by sending the CC one MIDI channel below the basic * channel of the receiver. * Examples: let a synthesizer with 16 MIDI channels: * - Let a basic channel 7 in mode 3 (Omni Off, Mono). If MIDI channel 6 is disabled it * could be used as CC global for all channels belonging to basic channel 7. - * - Let a basic channel 0 in mode 3. If MIDI channel 15 is disabled it could be used + * - Let a basic channel 0 in mode 3. If MIDI channel 15 is disabled it could be used * as CC global for all channels belonging to basic channel 0. */ int -fluid_synth_cc(fluid_synth_t* synth, int chan, int num, int val) +fluid_synth_cc(fluid_synth_t *synth, int chan, int num, int val) { - int result = FLUID_FAILED; - fluid_channel_t* channel; - fluid_return_val_if_fail (num >= 0 && num <= 127, FLUID_FAILED); - fluid_return_val_if_fail (val >= 0 && val <= 127, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + int result = FLUID_FAILED; + fluid_channel_t *channel; + fluid_return_val_if_fail(num >= 0 && num <= 127, FLUID_FAILED); + fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - channel = synth->channel[chan]; - if(channel->mode & FLUID_CHANNEL_ENABLED) - { /* chan is enabled */ - if (synth->verbose) - FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val); - fluid_channel_set_cc (channel, num, val); - result = fluid_synth_cc_LOCAL (synth, chan, num); - } - else /* chan is disabled so it is a candidate for global channel */ - { /* looks for next basic channel */ - int n_chan = synth->midi_channels; /* MIDI Channels number */ - int basicchan ; - if (chan < n_chan-1) basicchan = chan + 1; /* next channel */ - else basicchan = 0; /* wrap to 0 */ - channel = synth->channel[basicchan]; - /* Channel must be a basicchan in mode OMNIOFF_MONO */ - if ((channel->mode & FLUID_CHANNEL_BASIC) && - ((channel->mode & FLUID_CHANNEL_MODE_MASK) == FLUID_CHANNEL_MODE_OMNIOFF_MONO)) - { /* sends cc to all channels in this basic channel */ - int i,nbr = channel->mode_val; - for (i = basicchan; i < basicchan+nbr; i++) - { - if (synth->verbose) - FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", i, num, val); - fluid_channel_set_cc (synth->channel[i], num, val); - result = fluid_synth_cc_LOCAL (synth, i, num); - } - } - /* The channel chan is not a valid 'global channel' */ - else result = FLUID_FAILED; - } - FLUID_API_RETURN(result); + channel = synth->channel[chan]; + + if(channel->mode & FLUID_CHANNEL_ENABLED) + { + /* chan is enabled */ + if(synth->verbose) + { + FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", chan, num, val); + } + + fluid_channel_set_cc(channel, num, val); + result = fluid_synth_cc_LOCAL(synth, chan, num); + } + else /* chan is disabled so it is a candidate for global channel */ + { + /* looks for next basic channel */ + int n_chan = synth->midi_channels; /* MIDI Channels number */ + int basicchan ; + + if(chan < n_chan - 1) + { + basicchan = chan + 1; /* next channel */ + } + else + { + basicchan = 0; /* wrap to 0 */ + } + + channel = synth->channel[basicchan]; + + /* Channel must be a basicchan in mode OMNIOFF_MONO */ + if((channel->mode & FLUID_CHANNEL_BASIC) && + ((channel->mode & FLUID_CHANNEL_MODE_MASK) == FLUID_CHANNEL_MODE_OMNIOFF_MONO)) + { + /* sends cc to all channels in this basic channel */ + int i, nbr = channel->mode_val; + + for(i = basicchan; i < basicchan + nbr; i++) + { + if(synth->verbose) + { + FLUID_LOG(FLUID_INFO, "cc\t%d\t%d\t%d", i, num, val); + } + + fluid_channel_set_cc(synth->channel[i], num, val); + result = fluid_synth_cc_LOCAL(synth, i, num); + } + } + /* The channel chan is not a valid 'global channel' */ + else + { + result = FLUID_FAILED; + } + } + + FLUID_API_RETURN(result); } /* Local synthesis thread variant of MIDI CC set function. */ static int -fluid_synth_cc_LOCAL (fluid_synth_t* synth, int channum, int num) +fluid_synth_cc_LOCAL(fluid_synth_t *synth, int channum, int num) { - fluid_channel_t* chan = synth->channel[channum]; - int nrpn_select; - int value; + fluid_channel_t *chan = synth->channel[channum]; + int nrpn_select; + int value; - value = fluid_channel_get_cc (chan, num); + value = fluid_channel_get_cc(chan, num); - switch (num) { + switch(num) + { - /* CC omnioff, omnion, mono, poly */ - case POLY_OFF: - case POLY_ON: - case OMNI_OFF: - case OMNI_ON: - /* allowed only if channum is a basic channel */ - if (chan->mode & FLUID_CHANNEL_BASIC) - { - /* Construction of new_mode from current channel mode and this CC mode */ - int new_mode = chan->mode & FLUID_CHANNEL_MODE_MASK; - switch(num) + /* CC omnioff, omnion, mono, poly */ + case POLY_OFF: + case POLY_ON: + case OMNI_OFF: + case OMNI_ON: + + /* allowed only if channum is a basic channel */ + if(chan->mode & FLUID_CHANNEL_BASIC) { + /* Construction of new_mode from current channel mode and this CC mode */ + int new_mode = chan->mode & FLUID_CHANNEL_MODE_MASK; + + switch(num) + { case POLY_OFF: new_mode |= FLUID_CHANNEL_POLY_OFF; break; - + case POLY_ON: new_mode &= ~FLUID_CHANNEL_POLY_OFF; break; - + case OMNI_OFF: new_mode |= FLUID_CHANNEL_OMNI_OFF; break; - + case OMNI_ON: new_mode &= ~FLUID_CHANNEL_OMNI_OFF; break; - + default: /* should never happen */ return FLUID_FAILED; + } + + /* MIDI specs: if value is 0 it means all channels from channum to next + basic channel minus 1 (if any) or to MIDI channel count minus 1. + However, if value is > 0 (e.g. 4), the group of channels will be be + limited to 4. + value is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY as this mode + implies a group of only one channel. + */ + /* Checks value range and changes this existing basic channel group */ + value = fluid_synth_check_next_basic_channel(synth, channum, new_mode, value); + + if(value != FLUID_FAILED) + { + /* reset the current basic channel before changing it */ + fluid_synth_reset_basic_channel_LOCAL(synth, channum, chan->mode_val); + fluid_synth_set_basic_channel_LOCAL(synth, channum, new_mode, value); + break; /* FLUID_OK */ + } } - /* MIDI specs: if value is 0 it means all channels from channum to next - basic channel minus 1 (if any) or to MIDI channel count minus 1. - However, if value is > 0 (e.g. 4), the group of channels will be be - limited to 4. - value is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY as this mode - implies a group of only one channel. - */ - /* Checks value range and changes this existing basic channel group */ - value = fluid_synth_check_next_basic_channel(synth, channum, new_mode, value); - if( value != FLUID_FAILED ) - { - /* reset the current basic channel before changing it */ - fluid_synth_reset_basic_channel_LOCAL(synth, channum, chan->mode_val); - fluid_synth_set_basic_channel_LOCAL(synth, channum, new_mode, value); - break; /* FLUID_OK */ - } - } - return FLUID_FAILED; - case LEGATO_SWITCH: - /* handles Poly/mono commutation on Legato pedal On/Off.*/ - fluid_channel_cc_legato(chan,value); - break; + return FLUID_FAILED; - case PORTAMENTO_SWITCH: - /* Special handling of the monophonic list */ - /* Invalids the most recent note played in a staccato manner */ - fluid_channel_invalid_prev_note_staccato(chan); - break; + case LEGATO_SWITCH: + /* handles Poly/mono commutation on Legato pedal On/Off.*/ + fluid_channel_cc_legato(chan, value); + break; - case SUSTAIN_SWITCH: - /* Release voices if Sustain switch is released */ - if (value < 64) /* Sustain is released */ - fluid_synth_damp_voices_by_sustain_LOCAL (synth, channum); - break; + case PORTAMENTO_SWITCH: + /* Special handling of the monophonic list */ + /* Invalids the most recent note played in a staccato manner */ + fluid_channel_invalid_prev_note_staccato(chan); + break; - case SOSTENUTO_SWITCH: - /* Release voices if Sostetuno switch is released */ - if (value < 64) /* Sostenuto is released */ - fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum); - else /* Sostenuto is depressed */ - /* Update sostenuto order id when pedaling on Sostenuto */ - chan->sostenuto_orderid = synth->noteid; /* future voice id value */ - break; + case SUSTAIN_SWITCH: - case BANK_SELECT_MSB: - fluid_channel_set_bank_msb (chan, value & 0x7F); - break; - case BANK_SELECT_LSB: - fluid_channel_set_bank_lsb (chan, value & 0x7F); - break; - case ALL_NOTES_OFF: - fluid_synth_all_notes_off_LOCAL (synth, channum); - break; - case ALL_SOUND_OFF: - fluid_synth_all_sounds_off_LOCAL (synth, channum); - break; - case ALL_CTRL_OFF: - fluid_channel_init_ctrl (chan, 1); - fluid_synth_modulate_voices_all_LOCAL (synth, channum); - break; - case DATA_ENTRY_MSB: + /* Release voices if Sustain switch is released */ + if(value < 64) /* Sustain is released */ + { + fluid_synth_damp_voices_by_sustain_LOCAL(synth, channum); + } + + break; + + case SOSTENUTO_SWITCH: + + /* Release voices if Sostetuno switch is released */ + if(value < 64) /* Sostenuto is released */ + { + fluid_synth_damp_voices_by_sostenuto_LOCAL(synth, channum); + } + else /* Sostenuto is depressed */ + /* Update sostenuto order id when pedaling on Sostenuto */ + { + chan->sostenuto_orderid = synth->noteid; /* future voice id value */ + } + + break; + + case BANK_SELECT_MSB: + fluid_channel_set_bank_msb(chan, value & 0x7F); + break; + + case BANK_SELECT_LSB: + fluid_channel_set_bank_lsb(chan, value & 0x7F); + break; + + case ALL_NOTES_OFF: + fluid_synth_all_notes_off_LOCAL(synth, channum); + break; + + case ALL_SOUND_OFF: + fluid_synth_all_sounds_off_LOCAL(synth, channum); + break; + + case ALL_CTRL_OFF: + fluid_channel_init_ctrl(chan, 1); + fluid_synth_modulate_voices_all_LOCAL(synth, channum); + break; + + case DATA_ENTRY_MSB: { - int data = (value << 7) + fluid_channel_get_cc (chan, DATA_ENTRY_LSB); + int data = (value << 7) + fluid_channel_get_cc(chan, DATA_ENTRY_LSB); - if (chan->nrpn_active) /* NRPN is active? */ - { /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */ - if ((fluid_channel_get_cc (chan, NRPN_MSB) == 120) - && (fluid_channel_get_cc (chan, NRPN_LSB) < 100)) + if(chan->nrpn_active) /* NRPN is active? */ { - nrpn_select = chan->nrpn_select; + /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */ + if((fluid_channel_get_cc(chan, NRPN_MSB) == 120) + && (fluid_channel_get_cc(chan, NRPN_LSB) < 100)) + { + nrpn_select = chan->nrpn_select; - if (nrpn_select < GEN_LAST) - { - float val = fluid_gen_scale_nrpn (nrpn_select, data); - fluid_synth_set_gen_LOCAL (synth, channum, nrpn_select, val, FALSE); - } + if(nrpn_select < GEN_LAST) + { + float val = fluid_gen_scale_nrpn(nrpn_select, data); + fluid_synth_set_gen_LOCAL(synth, channum, nrpn_select, val, FALSE); + } - chan->nrpn_select = 0; /* Reset to 0 */ + chan->nrpn_select = 0; /* Reset to 0 */ + } } - } - else if (fluid_channel_get_cc (chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */ - { - switch (fluid_channel_get_cc (chan, RPN_LSB)) + else if(fluid_channel_get_cc(chan, RPN_MSB) == 0) /* RPN is active: MSB = 0? */ { - case RPN_PITCH_BEND_RANGE: /* Set bend range in semitones */ - fluid_channel_set_pitch_wheel_sensitivity (synth->channel[channum], value); - fluid_synth_update_pitch_wheel_sens_LOCAL (synth, channum); /* Update bend range */ - /* FIXME - Handle LSB? (Fine bend range in cents) */ - break; - case RPN_CHANNEL_FINE_TUNE: /* Fine tune is 14 bit over +/-1 semitone (+/- 100 cents, 8192 = center) */ - fluid_synth_set_gen_LOCAL (synth, channum, GEN_FINETUNE, - (data - 8192) / 8192.0 * 100.0, FALSE); - break; - case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */ - fluid_synth_set_gen_LOCAL (synth, channum, GEN_COARSETUNE, - value - 64, FALSE); - break; - case RPN_TUNING_PROGRAM_CHANGE: - fluid_channel_set_tuning_prog (chan, value); - fluid_synth_activate_tuning (synth, channum, - fluid_channel_get_tuning_bank (chan), - value, TRUE); - break; - case RPN_TUNING_BANK_SELECT: - fluid_channel_set_tuning_bank (chan, value); - break; - case RPN_MODULATION_DEPTH_RANGE: - break; + switch(fluid_channel_get_cc(chan, RPN_LSB)) + { + case RPN_PITCH_BEND_RANGE: /* Set bend range in semitones */ + fluid_channel_set_pitch_wheel_sensitivity(synth->channel[channum], value); + fluid_synth_update_pitch_wheel_sens_LOCAL(synth, channum); /* Update bend range */ + /* FIXME - Handle LSB? (Fine bend range in cents) */ + break; + + case RPN_CHANNEL_FINE_TUNE: /* Fine tune is 14 bit over +/-1 semitone (+/- 100 cents, 8192 = center) */ + fluid_synth_set_gen_LOCAL(synth, channum, GEN_FINETUNE, + (data - 8192) / 8192.0 * 100.0, FALSE); + break; + + case RPN_CHANNEL_COARSE_TUNE: /* Coarse tune is 7 bit and in semitones (64 is center) */ + fluid_synth_set_gen_LOCAL(synth, channum, GEN_COARSETUNE, + value - 64, FALSE); + break; + + case RPN_TUNING_PROGRAM_CHANGE: + fluid_channel_set_tuning_prog(chan, value); + fluid_synth_activate_tuning(synth, channum, + fluid_channel_get_tuning_bank(chan), + value, TRUE); + break; + + case RPN_TUNING_BANK_SELECT: + fluid_channel_set_tuning_bank(chan, value); + break; + + case RPN_MODULATION_DEPTH_RANGE: + break; + } } - } - break; - } - case NRPN_MSB: - fluid_channel_set_cc (chan, NRPN_LSB, 0); - chan->nrpn_select = 0; - chan->nrpn_active = 1; - break; - case NRPN_LSB: - /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */ - if (fluid_channel_get_cc (chan, NRPN_MSB) == 120) { - if (value == 100) { - chan->nrpn_select += 100; - } else if (value == 101) { - chan->nrpn_select += 1000; - } else if (value == 102) { - chan->nrpn_select += 10000; - } else if (value < 100) { - chan->nrpn_select += value; - } + + break; } - chan->nrpn_active = 1; - break; - case RPN_MSB: - case RPN_LSB: - chan->nrpn_active = 0; - break; - - case BREATH_MSB: - /* handles CC Breath On/Off noteOn/noteOff mode */ - fluid_channel_cc_breath_note_on_off(chan, value); + case NRPN_MSB: + fluid_channel_set_cc(chan, NRPN_LSB, 0); + chan->nrpn_select = 0; + chan->nrpn_active = 1; + break; + + case NRPN_LSB: + + /* SontFont 2.01 NRPN Message (Sect. 9.6, p. 74) */ + if(fluid_channel_get_cc(chan, NRPN_MSB) == 120) + { + if(value == 100) + { + chan->nrpn_select += 100; + } + else if(value == 101) + { + chan->nrpn_select += 1000; + } + else if(value == 102) + { + chan->nrpn_select += 10000; + } + else if(value < 100) + { + chan->nrpn_select += value; + } + } + + chan->nrpn_active = 1; + break; + + case RPN_MSB: + case RPN_LSB: + chan->nrpn_active = 0; + break; + + case BREATH_MSB: + /* handles CC Breath On/Off noteOn/noteOff mode */ + fluid_channel_cc_breath_note_on_off(chan, value); + /* fall-through */ - default: - return fluid_synth_modulate_voices_LOCAL (synth, channum, 1, num); - } + default: + return fluid_synth_modulate_voices_LOCAL(synth, channum, 1, num); + } - return FLUID_OK; + return FLUID_OK; } /** @@ -1564,32 +1753,32 @@ fluid_synth_cc_LOCAL (fluid_synth_t* synth, int channum, int num) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_get_cc(fluid_synth_t* synth, int chan, int num, int* pval) +fluid_synth_get_cc(fluid_synth_t *synth, int chan, int num, int *pval) { - fluid_return_val_if_fail (num >= 0 && num < 128, FLUID_FAILED); - fluid_return_val_if_fail (pval != NULL, FLUID_FAILED); + fluid_return_val_if_fail(num >= 0 && num < 128, FLUID_FAILED); + fluid_return_val_if_fail(pval != NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - *pval = fluid_channel_get_cc (synth->channel[chan], num); - FLUID_API_RETURN(FLUID_OK); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + *pval = fluid_channel_get_cc(synth->channel[chan], num); + FLUID_API_RETURN(FLUID_OK); } /* * Handler for synth.device-id setting. */ static void -fluid_synth_handle_device_id (void *data, const char *name, int value) +fluid_synth_handle_device_id(void *data, const char *name, int value) { - fluid_synth_t *synth = (fluid_synth_t *)data; - fluid_return_if_fail(synth != NULL); + fluid_synth_t *synth = (fluid_synth_t *)data; + fluid_return_if_fail(synth != NULL); - fluid_synth_api_enter(synth); - synth->device_id = value; - fluid_synth_api_exit(synth); + fluid_synth_api_enter(synth); + synth->device_id = value; + fluid_synth_api_exit(synth); } /** @@ -1617,254 +1806,335 @@ int fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len, char *response, int *response_len, int *handled, int dryrun) { - int avail_response = 0; + int avail_response = 0; - if (handled) *handled = FALSE; + if(handled) + { + *handled = FALSE; + } - if (response_len) - { - avail_response = *response_len; - *response_len = 0; - } + if(response_len) + { + avail_response = *response_len; + *response_len = 0; + } - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (data != NULL, FLUID_FAILED); - fluid_return_val_if_fail (len > 0, FLUID_FAILED); - fluid_return_val_if_fail (!response || response_len, FLUID_FAILED); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(data != NULL, FLUID_FAILED); + fluid_return_val_if_fail(len > 0, FLUID_FAILED); + fluid_return_val_if_fail(!response || response_len, FLUID_FAILED); - if (len < 4) return FLUID_OK; + if(len < 4) + { + return FLUID_OK; + } - /* MIDI tuning SYSEX message? */ - if ((data[0] == MIDI_SYSEX_UNIV_NON_REALTIME || data[0] == MIDI_SYSEX_UNIV_REALTIME) - && (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL) - && data[2] == MIDI_SYSEX_MIDI_TUNING_ID) - { - int result; - fluid_synth_api_enter(synth); - result = fluid_synth_sysex_midi_tuning (synth, data, len, response, - response_len, avail_response, - handled, dryrun); + /* MIDI tuning SYSEX message? */ + if((data[0] == MIDI_SYSEX_UNIV_NON_REALTIME || data[0] == MIDI_SYSEX_UNIV_REALTIME) + && (data[1] == synth->device_id || data[1] == MIDI_SYSEX_DEVICE_ID_ALL) + && data[2] == MIDI_SYSEX_MIDI_TUNING_ID) + { + int result; + fluid_synth_api_enter(synth); + result = fluid_synth_sysex_midi_tuning(synth, data, len, response, + response_len, avail_response, + handled, dryrun); - FLUID_API_RETURN(result); - } - return FLUID_OK; + FLUID_API_RETURN(result); + } + + return FLUID_OK; } /* Handler for MIDI tuning SYSEX messages */ static int -fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data, int len, - char *response, int *response_len, int avail_response, - int *handled, int dryrun) +fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, int len, + char *response, int *response_len, int avail_response, + int *handled, int dryrun) { - int realtime, msgid; - int bank = 0, prog, channels; - double tunedata[128]; - int keys[128]; - char name[17]; - int note, frac, frac2; - uint8_t chksum; - int i, count, index; - const char *dataptr; - char *resptr;; + int realtime, msgid; + int bank = 0, prog, channels; + double tunedata[128]; + int keys[128]; + char name[17]; + int note, frac, frac2; + uint8_t chksum; + int i, count, index; + const char *dataptr; + char *resptr;; - realtime = data[0] == MIDI_SYSEX_UNIV_REALTIME; - msgid = data[3]; + realtime = data[0] == MIDI_SYSEX_UNIV_REALTIME; + msgid = data[3]; - switch (msgid) - { + switch(msgid) + { case MIDI_SYSEX_TUNING_BULK_DUMP_REQ: case MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK: - if (data[3] == MIDI_SYSEX_TUNING_BULK_DUMP_REQ) - { - if (len != 5 || data[4] & 0x80 || !response) - return FLUID_OK; + if(data[3] == MIDI_SYSEX_TUNING_BULK_DUMP_REQ) + { + if(len != 5 || data[4] & 0x80 || !response) + { + return FLUID_OK; + } - *response_len = 406; - prog = data[4]; - } - else - { - if (len != 6 || data[4] & 0x80 || data[5] & 0x80 || !response) - return FLUID_OK; + *response_len = 406; + prog = data[4]; + } + else + { + if(len != 6 || data[4] & 0x80 || data[5] & 0x80 || !response) + { + return FLUID_OK; + } - *response_len = 407; - bank = data[4]; - prog = data[5]; - } + *response_len = 407; + bank = data[4]; + prog = data[5]; + } - if (dryrun) - { - if (handled) *handled = TRUE; - return FLUID_OK; - } + if(dryrun) + { + if(handled) + { + *handled = TRUE; + } - if (avail_response < *response_len) return FLUID_FAILED; + return FLUID_OK; + } - /* Get tuning data, return if tuning not found */ - if (fluid_synth_tuning_dump (synth, bank, prog, name, 17, tunedata) == FLUID_FAILED) - { - *response_len = 0; - return FLUID_OK; - } + if(avail_response < *response_len) + { + return FLUID_FAILED; + } - resptr = response; + /* Get tuning data, return if tuning not found */ + if(fluid_synth_tuning_dump(synth, bank, prog, name, 17, tunedata) == FLUID_FAILED) + { + *response_len = 0; + return FLUID_OK; + } - *resptr++ = MIDI_SYSEX_UNIV_NON_REALTIME; - *resptr++ = synth->device_id; - *resptr++ = MIDI_SYSEX_MIDI_TUNING_ID; - *resptr++ = MIDI_SYSEX_TUNING_BULK_DUMP; + resptr = response; - if (msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK) - *resptr++ = bank; + *resptr++ = MIDI_SYSEX_UNIV_NON_REALTIME; + *resptr++ = synth->device_id; + *resptr++ = MIDI_SYSEX_MIDI_TUNING_ID; + *resptr++ = MIDI_SYSEX_TUNING_BULK_DUMP; - *resptr++ = prog; - FLUID_STRNCPY (resptr, name, 16); - resptr += 16; + if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK) + { + *resptr++ = bank; + } - for (i = 0; i < 128; i++) - { - note = tunedata[i] / 100.0; - fluid_clip (note, 0, 127); + *resptr++ = prog; + FLUID_STRNCPY(resptr, name, 16); + resptr += 16; - frac = ((tunedata[i] - note * 100.0) * 16384.0 + 50.0) / 100.0; - fluid_clip (frac, 0, 16383); + for(i = 0; i < 128; i++) + { + note = tunedata[i] / 100.0; + fluid_clip(note, 0, 127); - *resptr++ = note; - *resptr++ = frac >> 7; - *resptr++ = frac & 0x7F; - } + frac = ((tunedata[i] - note * 100.0) * 16384.0 + 50.0) / 100.0; + fluid_clip(frac, 0, 16383); - if (msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ) - { /* NOTE: Checksum is not as straight forward as the bank based messages */ - chksum = MIDI_SYSEX_UNIV_NON_REALTIME ^ MIDI_SYSEX_MIDI_TUNING_ID - ^ MIDI_SYSEX_TUNING_BULK_DUMP ^ prog; + *resptr++ = note; + *resptr++ = frac >> 7; + *resptr++ = frac & 0x7F; + } - for (i = 21; i < 128 * 3 + 21; i++) - chksum ^= response[i]; - } - else - { - for (i = 1, chksum = 0; i < 406; i++) - chksum ^= response[i]; - } + if(msgid == MIDI_SYSEX_TUNING_BULK_DUMP_REQ) + { + /* NOTE: Checksum is not as straight forward as the bank based messages */ + chksum = MIDI_SYSEX_UNIV_NON_REALTIME ^ MIDI_SYSEX_MIDI_TUNING_ID + ^ MIDI_SYSEX_TUNING_BULK_DUMP ^ prog; - *resptr++ = chksum & 0x7F; + for(i = 21; i < 128 * 3 + 21; i++) + { + chksum ^= response[i]; + } + } + else + { + for(i = 1, chksum = 0; i < 406; i++) + { + chksum ^= response[i]; + } + } + + *resptr++ = chksum & 0x7F; + + if(handled) + { + *handled = TRUE; + } + + break; - if (handled) *handled = TRUE; - break; case MIDI_SYSEX_TUNING_NOTE_TUNE: case MIDI_SYSEX_TUNING_NOTE_TUNE_BANK: - dataptr = data + 4; + dataptr = data + 4; - if (msgid == MIDI_SYSEX_TUNING_NOTE_TUNE) - { - if (len < 10 || data[4] & 0x80 || data[5] & 0x80 || len != data[5] * 4 + 6) - return FLUID_OK; - } - else - { - if (len < 11 || data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80 - || len != data[6] * 4 + 7) - return FLUID_OK; + if(msgid == MIDI_SYSEX_TUNING_NOTE_TUNE) + { + if(len < 10 || data[4] & 0x80 || data[5] & 0x80 || len != data[5] * 4 + 6) + { + return FLUID_OK; + } + } + else + { + if(len < 11 || data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80 + || len != data[6] * 4 + 7) + { + return FLUID_OK; + } - bank = *dataptr++; - } + bank = *dataptr++; + } - if (dryrun) - { - if (handled) *handled = TRUE; - return FLUID_OK; - } + if(dryrun) + { + if(handled) + { + *handled = TRUE; + } - prog = *dataptr++; - count = *dataptr++; + return FLUID_OK; + } - for (i = 0, index = 0; i < count; i++) - { - note = *dataptr++; - if (note & 0x80) return FLUID_OK; - keys[index] = note; + prog = *dataptr++; + count = *dataptr++; - note = *dataptr++; - frac = *dataptr++; - frac2 = *dataptr++; + for(i = 0, index = 0; i < count; i++) + { + note = *dataptr++; - if (note & 0x80 || frac & 0x80 || frac2 & 0x80) - return FLUID_OK; + if(note & 0x80) + { + return FLUID_OK; + } - frac = frac << 7 | frac2; + keys[index] = note; - /* No change pitch value? Doesn't really make sense to send that, but.. */ - if (note == 0x7F && frac == 16383) continue; + note = *dataptr++; + frac = *dataptr++; + frac2 = *dataptr++; - tunedata[index] = note * 100.0 + (frac * 100.0 / 16384.0); - index++; - } + if(note & 0x80 || frac & 0x80 || frac2 & 0x80) + { + return FLUID_OK; + } - if (index > 0) - { - if (fluid_synth_tune_notes (synth, bank, prog, index, keys, tunedata, - realtime) == FLUID_FAILED) - return FLUID_FAILED; - } + frac = frac << 7 | frac2; + + /* No change pitch value? Doesn't really make sense to send that, but.. */ + if(note == 0x7F && frac == 16383) + { + continue; + } + + tunedata[index] = note * 100.0 + (frac * 100.0 / 16384.0); + index++; + } + + if(index > 0) + { + if(fluid_synth_tune_notes(synth, bank, prog, index, keys, tunedata, + realtime) == FLUID_FAILED) + { + return FLUID_FAILED; + } + } + + if(handled) + { + *handled = TRUE; + } + + break; - if (handled) *handled = TRUE; - break; case MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE: case MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE: - if ((msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE && len != 19) - || (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE && len != 31)) - return FLUID_OK; - - if (data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80) - return FLUID_OK; - - if (dryrun) - { - if (handled) *handled = TRUE; - return FLUID_OK; - } - - channels = (data[4] & 0x03) << 14 | data[5] << 7 | data[6]; - - if (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE) - { - for (i = 0; i < 12; i++) + if((msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE && len != 19) + || (msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE && len != 31)) { - frac = data[i + 7]; - if (frac & 0x80) return FLUID_OK; - tunedata[i] = (int)frac - 64; + return FLUID_OK; } - } - else - { - for (i = 0; i < 12; i++) - { - frac = data[i * 2 + 7]; - frac2 = data[i * 2 + 8]; - if (frac & 0x80 || frac2 & 0x80) return FLUID_OK; - tunedata[i] = (((int)frac << 7 | (int)frac2) - 8192) * (200.0 / 16384.0); - } - } - if (fluid_synth_activate_octave_tuning (synth, 0, 0, "SYSEX", + if(data[4] & 0x80 || data[5] & 0x80 || data[6] & 0x80) + { + return FLUID_OK; + } + + if(dryrun) + { + if(handled) + { + *handled = TRUE; + } + + return FLUID_OK; + } + + channels = (data[4] & 0x03) << 14 | data[5] << 7 | data[6]; + + if(msgid == MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE) + { + for(i = 0; i < 12; i++) + { + frac = data[i + 7]; + + if(frac & 0x80) + { + return FLUID_OK; + } + + tunedata[i] = (int)frac - 64; + } + } + else + { + for(i = 0; i < 12; i++) + { + frac = data[i * 2 + 7]; + frac2 = data[i * 2 + 8]; + + if(frac & 0x80 || frac2 & 0x80) + { + return FLUID_OK; + } + + tunedata[i] = (((int)frac << 7 | (int)frac2) - 8192) * (200.0 / 16384.0); + } + } + + if(fluid_synth_activate_octave_tuning(synth, 0, 0, "SYSEX", tunedata, realtime) == FLUID_FAILED) - return FLUID_FAILED; - - if (channels) - { - for (i = 0; i < 16; i++) { - if (channels & (1 << i)) - fluid_synth_activate_tuning (synth, i, 0, 0, realtime); + return FLUID_FAILED; } - } - if (handled) *handled = TRUE; - break; - } + if(channels) + { + for(i = 0; i < 16; i++) + { + if(channels & (1 << i)) + { + fluid_synth_activate_tuning(synth, i, 0, 0, realtime); + } + } + } - return FLUID_OK; + if(handled) + { + *handled = TRUE; + } + + break; + } + + return FLUID_OK; } /** @@ -1875,38 +2145,46 @@ fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data, int len, * @since 1.1.4 */ int -fluid_synth_all_notes_off(fluid_synth_t* synth, int chan) +fluid_synth_all_notes_off(fluid_synth_t *synth, int chan) { - int result; + int result; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (chan >= -1, FLUID_FAILED); - fluid_synth_api_enter(synth); - if (chan >= synth->midi_channels) - result = FLUID_FAILED; - else - { - /* Allowed (even for channel disabled) as chan = -1 selects all channels */ - result = fluid_synth_all_notes_off_LOCAL (synth, chan); - } - FLUID_API_RETURN(result); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(chan >= -1, FLUID_FAILED); + fluid_synth_api_enter(synth); + + if(chan >= synth->midi_channels) + { + result = FLUID_FAILED; + } + else + { + /* Allowed (even for channel disabled) as chan = -1 selects all channels */ + result = fluid_synth_all_notes_off_LOCAL(synth, chan); + } + + FLUID_API_RETURN(result); } /* Local synthesis thread variant of all notes off, (chan=-1 selects all channels) */ //static int int -fluid_synth_all_notes_off_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_all_notes_off_LOCAL(fluid_synth_t *synth, int chan) { - fluid_voice_t* voice; - int i; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; - if (fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice)))) - fluid_voice_noteoff(voice); - } - return FLUID_OK; + if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice)))) + { + fluid_voice_noteoff(voice); + } + } + + return FLUID_OK; } /** @@ -1917,37 +2195,45 @@ fluid_synth_all_notes_off_LOCAL(fluid_synth_t* synth, int chan) * @since 1.1.4 */ int -fluid_synth_all_sounds_off(fluid_synth_t* synth, int chan) +fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan) { - int result; + int result; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (chan >= -1, FLUID_FAILED); - fluid_synth_api_enter(synth); - if (chan >= synth->midi_channels) - result = FLUID_FAILED; - else - { - /* Allowed (even for channel disabled) as chan = -1 selects all channels */ - result = fluid_synth_all_sounds_off_LOCAL (synth, chan); - } - FLUID_API_RETURN(result); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(chan >= -1, FLUID_FAILED); + fluid_synth_api_enter(synth); + + if(chan >= synth->midi_channels) + { + result = FLUID_FAILED; + } + else + { + /* Allowed (even for channel disabled) as chan = -1 selects all channels */ + result = fluid_synth_all_sounds_off_LOCAL(synth, chan); + } + + FLUID_API_RETURN(result); } /* Local synthesis thread variant of all sounds off, (chan=-1 selects all channels) */ static int -fluid_synth_all_sounds_off_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_all_sounds_off_LOCAL(fluid_synth_t *synth, int chan) { - fluid_voice_t* voice; - int i; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; - if (fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice)))) - fluid_voice_off(voice); - } - return FLUID_OK; + if(fluid_voice_is_playing(voice) && ((-1 == chan) || (chan == fluid_voice_get_channel(voice)))) + { + fluid_voice_off(voice); + } + } + + return FLUID_OK; } /** @@ -1956,12 +2242,12 @@ fluid_synth_all_sounds_off_LOCAL(fluid_synth_t* synth, int chan) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_reset_reverb(fluid_synth_t* synth) +fluid_synth_reset_reverb(fluid_synth_t *synth) { - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f); - FLUID_API_RETURN(FLUID_OK); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f); + FLUID_API_RETURN(FLUID_OK); } /** @@ -1970,50 +2256,52 @@ fluid_synth_reset_reverb(fluid_synth_t* synth) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_reset_chorus(fluid_synth_t* synth) +fluid_synth_reset_chorus(fluid_synth_t *synth) { - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f); - FLUID_API_RETURN(FLUID_OK); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f); + FLUID_API_RETURN(FLUID_OK); } /** - * Send MIDI system reset command (big red 'panic' button), turns off notes, resets + * Send MIDI system reset command (big red 'panic' button), turns off notes, resets * controllers and restores initial basic channel configuration. * @param synth FluidSynth instance * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_system_reset(fluid_synth_t* synth) +fluid_synth_system_reset(fluid_synth_t *synth) { - int result; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - result = fluid_synth_system_reset_LOCAL (synth); - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + result = fluid_synth_system_reset_LOCAL(synth); + FLUID_API_RETURN(result); } /* Local variant of the system reset command */ static int -fluid_synth_system_reset_LOCAL(fluid_synth_t* synth) +fluid_synth_system_reset_LOCAL(fluid_synth_t *synth) { - int i; + int i; - fluid_synth_all_sounds_off_LOCAL(synth, -1); + fluid_synth_all_sounds_off_LOCAL(synth, -1); - for (i = 0; i < synth->midi_channels; i++) - fluid_channel_reset(synth->channel[i]); + for(i = 0; i < synth->midi_channels; i++) + { + fluid_channel_reset(synth->channel[i]); + } - /* Basic channel 0, Mode Omni On Poly */ - fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY, - synth->midi_channels); + /* Basic channel 0, Mode Omni On Poly */ + fluid_synth_set_basic_channel(synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY, + synth->midi_channels); - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f); - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f); + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_reverb, 0, 0.0f); + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_reset_chorus, 0, 0.0f); - return FLUID_OK; + return FLUID_OK; } /** @@ -2025,18 +2313,22 @@ fluid_synth_system_reset_LOCAL(fluid_synth_t* synth) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ static int -fluid_synth_modulate_voices_LOCAL(fluid_synth_t* synth, int chan, int is_cc, int ctrl) +fluid_synth_modulate_voices_LOCAL(fluid_synth_t *synth, int chan, int is_cc, int ctrl) { - fluid_voice_t* voice; - int i; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; - if (fluid_voice_get_channel(voice) == chan) - fluid_voice_modulate(voice, is_cc, ctrl); - } - return FLUID_OK; + if(fluid_voice_get_channel(voice) == chan) + { + fluid_voice_modulate(voice, is_cc, ctrl); + } + } + + return FLUID_OK; } /** @@ -2046,18 +2338,22 @@ fluid_synth_modulate_voices_LOCAL(fluid_synth_t* synth, int chan, int is_cc, int * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ static int -fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t *synth, int chan) { - fluid_voice_t* voice; - int i; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; - if (fluid_voice_get_channel(voice) == chan) - fluid_voice_modulate_all(voice); - } - return FLUID_OK; + if(fluid_voice_get_channel(voice) == chan) + { + fluid_voice_modulate_all(voice); + } + } + + return FLUID_OK; } /** @@ -2068,30 +2364,32 @@ fluid_synth_modulate_voices_all_LOCAL(fluid_synth_t* synth, int chan) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_channel_pressure(fluid_synth_t* synth, int chan, int val) +fluid_synth_channel_pressure(fluid_synth_t *synth, int chan, int val) { - int result; - fluid_return_val_if_fail (val >= 0 && val <= 127, FLUID_FAILED); + int result; + fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - if (synth->verbose) - FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - fluid_channel_set_channel_pressure (synth->channel[chan], val); - result = fluid_synth_update_channel_pressure_LOCAL (synth, chan); + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - FLUID_API_RETURN(result); + if(synth->verbose) + { + FLUID_LOG(FLUID_INFO, "channelpressure\t%d\t%d", chan, val); + } + + fluid_channel_set_channel_pressure(synth->channel[chan], val); + result = fluid_synth_update_channel_pressure_LOCAL(synth, chan); + + FLUID_API_RETURN(result); } /* Updates channel pressure from within synthesis thread */ static int -fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t *synth, int chan) { - return fluid_synth_modulate_voices_LOCAL (synth, chan, 0, FLUID_MOD_CHANNELPRESSURE); + return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_CHANNELPRESSURE); } /** @@ -2104,44 +2402,52 @@ fluid_synth_update_channel_pressure_LOCAL(fluid_synth_t* synth, int chan) * @since 2.0.0 */ int -fluid_synth_key_pressure(fluid_synth_t* synth, int chan, int key, int val) +fluid_synth_key_pressure(fluid_synth_t *synth, int chan, int key, int val) { - int result; - fluid_return_val_if_fail (key >= 0 && key <= 127, FLUID_FAILED); - fluid_return_val_if_fail (val >= 0 && val <= 127, FLUID_FAILED); + int result; + fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED); + fluid_return_val_if_fail(val >= 0 && val <= 127, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - if (synth->verbose) - FLUID_LOG(FLUID_INFO, "keypressure\t%d\t%d\t%d", chan, key, val); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - fluid_channel_set_key_pressure (synth->channel[chan], key, val); - result = fluid_synth_update_key_pressure_LOCAL (synth, chan, key); + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - FLUID_API_RETURN(result); + if(synth->verbose) + { + FLUID_LOG(FLUID_INFO, "keypressure\t%d\t%d\t%d", chan, key, val); + } + + fluid_channel_set_key_pressure(synth->channel[chan], key, val); + result = fluid_synth_update_key_pressure_LOCAL(synth, chan, key); + + FLUID_API_RETURN(result); } /* Updates key pressure from within synthesis thread */ static int -fluid_synth_update_key_pressure_LOCAL(fluid_synth_t* synth, int chan, int key) +fluid_synth_update_key_pressure_LOCAL(fluid_synth_t *synth, int chan, int key) { - fluid_voice_t* voice; - int i; - int result = FLUID_OK; + fluid_voice_t *voice; + int i; + int result = FLUID_OK; - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; - if (voice->chan == chan && voice->key == key) { - result = fluid_voice_modulate(voice, 0, FLUID_MOD_KEYPRESSURE); - if (result != FLUID_OK) - return result; + if(voice->chan == chan && voice->key == key) + { + result = fluid_voice_modulate(voice, 0, FLUID_MOD_KEYPRESSURE); + + if(result != FLUID_OK) + { + return result; + } + } } - } - return result; + + return result; } /** @@ -2152,29 +2458,31 @@ fluid_synth_update_key_pressure_LOCAL(fluid_synth_t* synth, int chan, int key) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val) +fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val) { - int result; - fluid_return_val_if_fail (val >= 0 && val <= 16383, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - if (synth->verbose) - FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val); + int result; + fluid_return_val_if_fail(val >= 0 && val <= 16383, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - fluid_channel_set_pitch_bend (synth->channel[chan], val); - result = fluid_synth_update_pitch_bend_LOCAL (synth, chan); - - FLUID_API_RETURN(result); + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + if(synth->verbose) + { + FLUID_LOG(FLUID_INFO, "pitchb\t%d\t%d", chan, val); + } + + fluid_channel_set_pitch_bend(synth->channel[chan], val); + result = fluid_synth_update_pitch_bend_LOCAL(synth, chan); + + FLUID_API_RETURN(result); } /* Local synthesis thread variant of pitch bend */ static int -fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t *synth, int chan) { - return fluid_synth_modulate_voices_LOCAL (synth, chan, 0, FLUID_MOD_PITCHWHEEL); + return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEEL); } /** @@ -2186,19 +2494,19 @@ fluid_synth_update_pitch_bend_LOCAL(fluid_synth_t* synth, int chan) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend) +fluid_synth_get_pitch_bend(fluid_synth_t *synth, int chan, int *ppitch_bend) { - int result; - fluid_return_val_if_fail (ppitch_bend != NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - *ppitch_bend = fluid_channel_get_pitch_bend (synth->channel[chan]); - result = FLUID_OK; - - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(ppitch_bend != NULL, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + *ppitch_bend = fluid_channel_get_pitch_bend(synth->channel[chan]); + result = FLUID_OK; + + FLUID_API_RETURN(result); } /** @@ -2209,29 +2517,31 @@ fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_pitch_wheel_sens(fluid_synth_t* synth, int chan, int val) +fluid_synth_pitch_wheel_sens(fluid_synth_t *synth, int chan, int val) { - int result; - fluid_return_val_if_fail (val >= 0 && val <= 72, FLUID_FAILED); /* 6 octaves!? Better than no limit.. */ - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - if (synth->verbose) - FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val); + int result; + fluid_return_val_if_fail(val >= 0 && val <= 72, FLUID_FAILED); /* 6 octaves!? Better than no limit.. */ + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - fluid_channel_set_pitch_wheel_sensitivity (synth->channel[chan], val); - result = fluid_synth_update_pitch_wheel_sens_LOCAL (synth, chan); - - FLUID_API_RETURN(result); + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + if(synth->verbose) + { + FLUID_LOG(FLUID_INFO, "pitchsens\t%d\t%d", chan, val); + } + + fluid_channel_set_pitch_wheel_sensitivity(synth->channel[chan], val); + result = fluid_synth_update_pitch_wheel_sens_LOCAL(synth, chan); + + FLUID_API_RETURN(result); } /* Local synthesis thread variant of set pitch wheel sensitivity */ static int -fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t* synth, int chan) +fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t *synth, int chan) { - return fluid_synth_modulate_voices_LOCAL (synth, chan, 0, FLUID_MOD_PITCHWHEELSENS); + return fluid_synth_modulate_voices_LOCAL(synth, chan, 0, FLUID_MOD_PITCHWHEELSENS); } /** @@ -2243,19 +2553,19 @@ fluid_synth_update_pitch_wheel_sens_LOCAL(fluid_synth_t* synth, int chan) * @since Sometime AFTER v1.0 API freeze. */ int -fluid_synth_get_pitch_wheel_sens(fluid_synth_t* synth, int chan, int* pval) +fluid_synth_get_pitch_wheel_sens(fluid_synth_t *synth, int chan, int *pval) { - int result; - fluid_return_val_if_fail (pval != NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - *pval = fluid_channel_get_pitch_wheel_sensitivity (synth->channel[chan]); - result = FLUID_OK; - - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(pval != NULL, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + *pval = fluid_channel_get_pitch_wheel_sensitivity(synth->channel[chan]); + result = FLUID_OK; + + FLUID_API_RETURN(result); } /** @@ -2266,87 +2576,94 @@ fluid_synth_get_pitch_wheel_sens(fluid_synth_t* synth, int chan, int* pval) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ static int -fluid_synth_set_preset (fluid_synth_t *synth, int chan, fluid_preset_t *preset) +fluid_synth_set_preset(fluid_synth_t *synth, int chan, fluid_preset_t *preset) { - fluid_channel_t *channel; + fluid_channel_t *channel; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(chan >= 0 && chan < synth->midi_channels, FLUID_FAILED); - channel = synth->channel[chan]; + channel = synth->channel[chan]; - return fluid_channel_set_preset (channel, preset); + return fluid_channel_set_preset(channel, preset); } /* Get a preset by SoundFont, bank and program numbers. * Returns preset pointer or NULL. */ -static fluid_preset_t* -fluid_synth_get_preset(fluid_synth_t* synth, int sfontnum, +static fluid_preset_t * +fluid_synth_get_preset(fluid_synth_t *synth, int sfontnum, int banknum, int prognum) { - fluid_sfont_t *sfont; - fluid_list_t *list; + fluid_sfont_t *sfont; + fluid_list_t *list; - /* 128 indicates an "unset" operation" */ - if (prognum == FLUID_UNSET_PROGRAM) return NULL; - - for (list = synth->sfont; list; list = fluid_list_next (list)) { - sfont = fluid_list_get (list); - - if (fluid_sfont_get_id (sfont) == sfontnum) + /* 128 indicates an "unset" operation" */ + if(prognum == FLUID_UNSET_PROGRAM) { - return fluid_sfont_get_preset (sfont, banknum - sfont->bankofs, prognum); + return NULL; } - } - return NULL; + for(list = synth->sfont; list; list = fluid_list_next(list)) + { + sfont = fluid_list_get(list); + + if(fluid_sfont_get_id(sfont) == sfontnum) + { + return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum); + } + } + + return NULL; } /* Get a preset by SoundFont name, bank and program. * Returns preset pointer or NULL. */ -static fluid_preset_t* -fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname, +static fluid_preset_t * +fluid_synth_get_preset_by_sfont_name(fluid_synth_t *synth, const char *sfontname, int banknum, int prognum) { - fluid_sfont_t *sfont; - fluid_list_t *list; + fluid_sfont_t *sfont; + fluid_list_t *list; - for (list = synth->sfont; list; list = fluid_list_next (list)) { - sfont = fluid_list_get (list); - - if (FLUID_STRCMP (fluid_sfont_get_name (sfont), sfontname) == 0) + for(list = synth->sfont; list; list = fluid_list_next(list)) { - return fluid_sfont_get_preset (sfont, banknum - sfont->bankofs, prognum); - } - } + sfont = fluid_list_get(list); - return NULL; + if(FLUID_STRCMP(fluid_sfont_get_name(sfont), sfontname) == 0) + { + return fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum); + } + } + + return NULL; } /* Find a preset by bank and program numbers. * Returns preset pointer or NULL. */ -fluid_preset_t* -fluid_synth_find_preset(fluid_synth_t* synth, int banknum, +fluid_preset_t * +fluid_synth_find_preset(fluid_synth_t *synth, int banknum, int prognum) { - fluid_preset_t *preset; - fluid_sfont_t *sfont; - fluid_list_t *list; + fluid_preset_t *preset; + fluid_sfont_t *sfont; + fluid_list_t *list; - for (list = synth->sfont; list; list = fluid_list_next (list)) { - sfont = fluid_list_get (list); - - preset = fluid_sfont_get_preset (sfont, banknum - sfont->bankofs, prognum); - if (preset) + for(list = synth->sfont; list; list = fluid_list_next(list)) { - return preset; - } - } + sfont = fluid_list_get(list); - return NULL; + preset = fluid_sfont_get_preset(sfont, banknum - sfont->bankofs, prognum); + + if(preset) + { + return preset; + } + } + + return NULL; } /** @@ -2362,78 +2679,90 @@ fluid_synth_find_preset(fluid_synth_t* synth, int banknum, /* As of 1.1.1 prognum can be set to 128 to unset the preset. Not documented * since fluid_synth_unset_program() should be used instead. */ int -fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum) +fluid_synth_program_change(fluid_synth_t *synth, int chan, int prognum) { - fluid_preset_t* preset = NULL; - fluid_channel_t* channel; - int subst_bank, subst_prog, banknum = 0, result = FLUID_FAILED; + fluid_preset_t *preset = NULL; + fluid_channel_t *channel; + int subst_bank, subst_prog, banknum = 0, result = FLUID_FAILED; - fluid_return_val_if_fail (prognum >= 0 && prognum <= 128, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - channel = synth->channel[chan]; - - if (channel->channel_type == CHANNEL_TYPE_DRUM) + fluid_return_val_if_fail(prognum >= 0 && prognum <= 128, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + channel = synth->channel[chan]; + + if(channel->channel_type == CHANNEL_TYPE_DRUM) + { banknum = DRUM_INST_BANK; + } else + { fluid_channel_get_sfont_bank_prog(channel, NULL, &banknum, NULL); + } - if (synth->verbose) + if(synth->verbose) + { FLUID_LOG(FLUID_INFO, "prog\t%d\t%d\t%d", chan, banknum, prognum); + } - /* I think this is a hack for MIDI files that do bank changes in GM mode. - * Proper way to handle this would probably be to ignore bank changes when in + /* I think this is a hack for MIDI files that do bank changes in GM mode. + * Proper way to handle this would probably be to ignore bank changes when in * GM mode. - JG * This is now possible by setting synth.midi-bank-select=gm, but let the hack * stay for the time being. - DH */ - if (prognum != FLUID_UNSET_PROGRAM) + if(prognum != FLUID_UNSET_PROGRAM) { subst_bank = banknum; subst_prog = prognum; - + preset = fluid_synth_find_preset(synth, subst_bank, subst_prog); - + /* Fallback to another preset if not found */ - if (!preset) { - /* Percussion: Fallback to preset 0 in percussion bank */ - if (channel->channel_type == CHANNEL_TYPE_DRUM) { - subst_prog = 0; - subst_bank = DRUM_INST_BANK; - preset = fluid_synth_find_preset(synth, subst_bank, subst_prog); - } - /* Melodic instrument */ - else { - /* Fallback first to bank 0:prognum */ - subst_bank = 0; - preset = fluid_synth_find_preset(synth, subst_bank, subst_prog); - - /* Fallback to first preset in bank 0 (usually piano...) */ - if (!preset) + if(!preset) + { + /* Percussion: Fallback to preset 0 in percussion bank */ + if(channel->channel_type == CHANNEL_TYPE_DRUM) { - subst_prog = 0; - preset = fluid_synth_find_preset(synth, subst_bank, subst_prog); + subst_prog = 0; + subst_bank = DRUM_INST_BANK; + preset = fluid_synth_find_preset(synth, subst_bank, subst_prog); } - } + /* Melodic instrument */ + else + { + /* Fallback first to bank 0:prognum */ + subst_bank = 0; + preset = fluid_synth_find_preset(synth, subst_bank, subst_prog); - if (preset) - FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]", - chan, banknum, prognum, subst_bank, subst_prog); - else - FLUID_LOG(FLUID_WARN, "No preset found on channel %d [bank=%d prog=%d]", - chan, banknum, prognum); + /* Fallback to first preset in bank 0 (usually piano...) */ + if(!preset) + { + subst_prog = 0; + preset = fluid_synth_find_preset(synth, subst_bank, subst_prog); + } + } + + if(preset) + { + FLUID_LOG(FLUID_WARN, "Instrument not found on channel %d [bank=%d prog=%d], substituted [bank=%d prog=%d]", + chan, banknum, prognum, subst_bank, subst_prog); + } + else + { + FLUID_LOG(FLUID_WARN, "No preset found on channel %d [bank=%d prog=%d]", chan, banknum, prognum); + } } } /* Assign the SoundFont ID and program number to the channel */ - fluid_channel_set_sfont_bank_prog (channel, preset ? fluid_sfont_get_id (preset->sfont) : 0, - -1, prognum); - result = fluid_synth_set_preset (synth, chan, preset); - - FLUID_API_RETURN(result); + fluid_channel_set_sfont_bank_prog(channel, preset ? fluid_sfont_get_id(preset->sfont) : 0, + -1, prognum); + result = fluid_synth_set_preset(synth, chan, preset); + + FLUID_API_RETURN(result); } /** @@ -2446,23 +2775,23 @@ fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum) * as it is usually called prior to fluid_synth_program_change(). If you still want * instrument changes to take effect immediately, call fluid_synth_program_reset() * after having set up the bank configuration. - * + * */ int -fluid_synth_bank_select(fluid_synth_t* synth, int chan, int bank) +fluid_synth_bank_select(fluid_synth_t *synth, int chan, int bank) { - int result; - fluid_return_val_if_fail (bank <= 16383, FLUID_FAILED); - fluid_return_val_if_fail (bank >= 0, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - fluid_channel_set_sfont_bank_prog (synth->channel[chan], -1, bank, -1); - result = FLUID_OK; - - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(bank <= 16383, FLUID_FAILED); + fluid_return_val_if_fail(bank >= 0, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + + fluid_channel_set_sfont_bank_prog(synth->channel[chan], -1, bank, -1); + result = FLUID_OK; + + FLUID_API_RETURN(result); } /** @@ -2477,18 +2806,18 @@ fluid_synth_bank_select(fluid_synth_t* synth, int chan, int bank) * after having selected the soundfont. */ int -fluid_synth_sfont_select(fluid_synth_t* synth, int chan, int sfont_id) +fluid_synth_sfont_select(fluid_synth_t *synth, int chan, int sfont_id) { - int result; - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); + int result; + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); fluid_channel_set_sfont_bank_prog(synth->channel[chan], sfont_id, -1, -1); - result = FLUID_OK; - - FLUID_API_RETURN(result); + result = FLUID_OK; + + FLUID_API_RETURN(result); } /** @@ -2503,10 +2832,10 @@ fluid_synth_sfont_select(fluid_synth_t* synth, int chan, int sfont_id) * preset if one matches. */ int -fluid_synth_unset_program (fluid_synth_t *synth, int chan) +fluid_synth_unset_program(fluid_synth_t *synth, int chan) { - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - FLUID_API_RETURN(fluid_synth_program_change (synth, chan, FLUID_UNSET_PROGRAM)); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + FLUID_API_RETURN(fluid_synth_program_change(synth, chan, FLUID_UNSET_PROGRAM)); } /** @@ -2519,28 +2848,32 @@ fluid_synth_unset_program (fluid_synth_t *synth, int chan) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_get_program(fluid_synth_t* synth, int chan, int* sfont_id, - int* bank_num, int* preset_num) +fluid_synth_get_program(fluid_synth_t *synth, int chan, int *sfont_id, + int *bank_num, int *preset_num) { - int result; - fluid_channel_t* channel; + int result; + fluid_channel_t *channel; - fluid_return_val_if_fail (sfont_id != NULL, FLUID_FAILED); - fluid_return_val_if_fail (bank_num != NULL, FLUID_FAILED); - fluid_return_val_if_fail (preset_num != NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + fluid_return_val_if_fail(sfont_id != NULL, FLUID_FAILED); + fluid_return_val_if_fail(bank_num != NULL, FLUID_FAILED); + fluid_return_val_if_fail(preset_num != NULL, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - channel = synth->channel[chan]; - fluid_channel_get_sfont_bank_prog(channel, sfont_id, bank_num, preset_num); + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - /* 128 indicates that the preset is unset. Set to 0 to be backwards compatible. */ - if (*preset_num == FLUID_UNSET_PROGRAM) *preset_num = 0; - result = FLUID_OK; - - FLUID_API_RETURN(result); + channel = synth->channel[chan]; + fluid_channel_get_sfont_bank_prog(channel, sfont_id, bank_num, preset_num); + + /* 128 indicates that the preset is unset. Set to 0 to be backwards compatible. */ + if(*preset_num == FLUID_UNSET_PROGRAM) + { + *preset_num = 0; + } + + result = FLUID_OK; + + FLUID_API_RETURN(result); } /** @@ -2553,36 +2886,37 @@ fluid_synth_get_program(fluid_synth_t* synth, int chan, int* sfont_id, * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_program_select(fluid_synth_t* synth, int chan, int sfont_id, - int bank_num, int preset_num) +fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id, + int bank_num, int preset_num) { - fluid_preset_t* preset = NULL; - fluid_channel_t* channel; - int result; - fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED); - fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED); - - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + fluid_preset_t *preset = NULL; + fluid_channel_t *channel; + int result; + fluid_return_val_if_fail(bank_num >= 0, FLUID_FAILED); + fluid_return_val_if_fail(preset_num >= 0, FLUID_FAILED); - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - channel = synth->channel[chan]; - - preset = fluid_synth_get_preset (synth, sfont_id, bank_num, preset_num); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - if (preset == NULL) { - FLUID_LOG(FLUID_ERR, - "There is no preset with bank number %d and preset number %d in SoundFont %d", - bank_num, preset_num, sfont_id); - FLUID_API_RETURN(FLUID_FAILED); - } + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - /* Assign the new SoundFont ID, bank and program number to the channel */ - fluid_channel_set_sfont_bank_prog (channel, sfont_id, bank_num, preset_num); - result = fluid_synth_set_preset (synth, chan, preset); - - FLUID_API_RETURN(result); + channel = synth->channel[chan]; + + preset = fluid_synth_get_preset(synth, sfont_id, bank_num, preset_num); + + if(preset == NULL) + { + FLUID_LOG(FLUID_ERR, + "There is no preset with bank number %d and preset number %d in SoundFont %d", + bank_num, preset_num, sfont_id); + FLUID_API_RETURN(FLUID_FAILED); + } + + /* Assign the new SoundFont ID, bank and program number to the channel */ + fluid_channel_set_sfont_bank_prog(channel, sfont_id, bank_num, preset_num); + result = fluid_synth_set_preset(synth, chan, preset); + + FLUID_API_RETURN(result); } /** @@ -2596,36 +2930,38 @@ fluid_synth_program_select(fluid_synth_t* synth, int chan, int sfont_id, * @since 1.1.0 */ int -fluid_synth_program_select_by_sfont_name (fluid_synth_t* synth, int chan, - const char *sfont_name, int bank_num, - int preset_num) +fluid_synth_program_select_by_sfont_name(fluid_synth_t *synth, int chan, + const char *sfont_name, int bank_num, + int preset_num) { - fluid_preset_t* preset = NULL; - fluid_channel_t* channel; - int result; - fluid_return_val_if_fail (sfont_name != NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + fluid_preset_t *preset = NULL; + fluid_channel_t *channel; + int result; + fluid_return_val_if_fail(sfont_name != NULL, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /* Allowed only on MIDI channel enabled */ - FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - - channel = synth->channel[chan]; - - preset = fluid_synth_get_preset_by_sfont_name (synth, sfont_name, bank_num, - preset_num); - if (preset == NULL) { - FLUID_LOG(FLUID_ERR, - "There is no preset with bank number %d and preset number %d in SoundFont %s", - bank_num, preset_num, sfont_name); - FLUID_API_RETURN(FLUID_FAILED); - } + /* Allowed only on MIDI channel enabled */ + FLUID_API_RETURN_IF_CHAN_DISABLED(FLUID_FAILED); - /* Assign the new SoundFont ID, bank and program number to the channel */ - fluid_channel_set_sfont_bank_prog (channel, fluid_sfont_get_id (preset->sfont), - bank_num, preset_num); - result = fluid_synth_set_preset (synth, chan, preset); - - FLUID_API_RETURN(result); + channel = synth->channel[chan]; + + preset = fluid_synth_get_preset_by_sfont_name(synth, sfont_name, bank_num, + preset_num); + + if(preset == NULL) + { + FLUID_LOG(FLUID_ERR, + "There is no preset with bank number %d and preset number %d in SoundFont %s", + bank_num, preset_num, sfont_name); + FLUID_API_RETURN(FLUID_FAILED); + } + + /* Assign the new SoundFont ID, bank and program number to the channel */ + fluid_channel_set_sfont_bank_prog(channel, fluid_sfont_get_id(preset->sfont), + bank_num, preset_num); + result = fluid_synth_set_preset(synth, chan, preset); + + FLUID_API_RETURN(result); } /* @@ -2634,63 +2970,67 @@ fluid_synth_program_select_by_sfont_name (fluid_synth_t* synth, int chan, * unloaded or reloaded. */ static void -fluid_synth_update_presets(fluid_synth_t* synth) +fluid_synth_update_presets(fluid_synth_t *synth) { - fluid_channel_t *channel; - fluid_preset_t *preset; - int sfont, bank, prog; - int chan; + fluid_channel_t *channel; + fluid_preset_t *preset; + int sfont, bank, prog; + int chan; - for (chan = 0; chan < synth->midi_channels; chan++) { - channel = synth->channel[chan]; - fluid_channel_get_sfont_bank_prog (channel, &sfont, &bank, &prog); - preset = fluid_synth_get_preset (synth, sfont, bank, prog); - fluid_synth_set_preset (synth, chan, preset); - } + for(chan = 0; chan < synth->midi_channels; chan++) + { + channel = synth->channel[chan]; + fluid_channel_get_sfont_bank_prog(channel, &sfont, &bank, &prog); + preset = fluid_synth_get_preset(synth, sfont, bank, prog); + fluid_synth_set_preset(synth, chan, preset); + } } /* Handler for synth.sample-rate setting. */ static void -fluid_synth_handle_sample_rate(void *data, const char* name, double value) +fluid_synth_handle_sample_rate(void *data, const char *name, double value) { - fluid_synth_t *synth = (fluid_synth_t *)data; - fluid_synth_set_sample_rate(synth, (float) value); + fluid_synth_t *synth = (fluid_synth_t *)data; + fluid_synth_set_sample_rate(synth, (float) value); } /** - * Set sample rate of the synth. - * @note This function is currently experimental and should only be + * Set sample rate of the synth. + * @note This function is currently experimental and should only be * used when no voices or notes are active, and before any rendering calls. * @param synth FluidSynth instance * @param sample_rate New sample rate (Hz) * @since 1.1.2 */ -void -fluid_synth_set_sample_rate(fluid_synth_t* synth, float sample_rate) +void +fluid_synth_set_sample_rate(fluid_synth_t *synth, float sample_rate) { - int i; - fluid_return_if_fail (synth != NULL); - fluid_synth_api_enter(synth); - fluid_clip (sample_rate, 8000.0f, 96000.0f); - synth->sample_rate = sample_rate; - - synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth); - - for (i=0; i < synth->polyphony; i++) - fluid_voice_set_output_rate(synth->voice[i], sample_rate); - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_samplerate, - 0, sample_rate); - fluid_synth_api_exit(synth); + int i; + fluid_return_if_fail(synth != NULL); + fluid_synth_api_enter(synth); + fluid_clip(sample_rate, 8000.0f, 96000.0f); + synth->sample_rate = sample_rate; + + synth->min_note_length_ticks = fluid_synth_get_min_note_length_LOCAL(synth); + + for(i = 0; i < synth->polyphony; i++) + { + fluid_voice_set_output_rate(synth->voice[i], sample_rate); + } + + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_samplerate, + 0, sample_rate); + fluid_synth_api_exit(synth); } /* Handler for synth.gain setting. */ static void -fluid_synth_handle_gain(void *data, const char* name, double value) +fluid_synth_handle_gain(void *data, const char *name, double value) { - fluid_synth_t *synth = (fluid_synth_t *)data; - fluid_synth_set_gain(synth, (float) value); + fluid_synth_t *synth = (fluid_synth_t *)data; + fluid_synth_set_gain(synth, (float) value); } /** @@ -2699,33 +3039,37 @@ fluid_synth_handle_gain(void *data, const char* name, double value) * @param gain Gain value (function clamps value to the range 0.0 to 10.0) */ void -fluid_synth_set_gain(fluid_synth_t* synth, float gain) +fluid_synth_set_gain(fluid_synth_t *synth, float gain) { - fluid_return_if_fail (synth != NULL); - fluid_synth_api_enter(synth); - - fluid_clip (gain, 0.0f, 10.0f); + fluid_return_if_fail(synth != NULL); + fluid_synth_api_enter(synth); - synth->gain = gain; - fluid_synth_update_gain_LOCAL (synth); - fluid_synth_api_exit(synth); + fluid_clip(gain, 0.0f, 10.0f); + + synth->gain = gain; + fluid_synth_update_gain_LOCAL(synth); + fluid_synth_api_exit(synth); } /* Called by synthesis thread to update the gain in all voices */ static void -fluid_synth_update_gain_LOCAL(fluid_synth_t* synth) +fluid_synth_update_gain_LOCAL(fluid_synth_t *synth) { - fluid_voice_t *voice; - float gain; - int i; + fluid_voice_t *voice; + float gain; + int i; - gain = synth->gain; + gain = synth->gain; - for (i = 0; i < synth->polyphony; i++) - { - voice = synth->voice[i]; - if (fluid_voice_is_playing(voice)) fluid_voice_set_gain (voice, gain); - } + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; + + if(fluid_voice_is_playing(voice)) + { + fluid_voice_set_gain(voice, gain); + } + } } /** @@ -2734,24 +3078,24 @@ fluid_synth_update_gain_LOCAL(fluid_synth_t* synth) * @return Synth gain value (0.0 to 10.0) */ float -fluid_synth_get_gain(fluid_synth_t* synth) +fluid_synth_get_gain(fluid_synth_t *synth) { - float result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + float result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->gain; - FLUID_API_RETURN(result); + result = synth->gain; + FLUID_API_RETURN(result); } /* * Handler for synth.polyphony setting. */ static void -fluid_synth_handle_polyphony(void *data, const char* name, int value) +fluid_synth_handle_polyphony(void *data, const char *name, int value) { - fluid_synth_t *synth = (fluid_synth_t *)data; - fluid_synth_set_polyphony(synth, value); + fluid_synth_t *synth = (fluid_synth_t *)data; + fluid_synth_set_polyphony(synth, value); } /** @@ -2762,54 +3106,70 @@ fluid_synth_handle_polyphony(void *data, const char* name, int value) * @since 1.0.6 */ int -fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony) +fluid_synth_set_polyphony(fluid_synth_t *synth, int polyphony) { - int result; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (polyphony >= 1 && polyphony <= 65535, FLUID_FAILED); - fluid_synth_api_enter(synth); + int result; + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(polyphony >= 1 && polyphony <= 65535, FLUID_FAILED); + fluid_synth_api_enter(synth); - result = fluid_synth_update_polyphony_LOCAL(synth, polyphony); + result = fluid_synth_update_polyphony_LOCAL(synth, polyphony); - FLUID_API_RETURN(result); + FLUID_API_RETURN(result); } /* Called by synthesis thread to update the polyphony value */ static int -fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth, int new_polyphony) +fluid_synth_update_polyphony_LOCAL(fluid_synth_t *synth, int new_polyphony) { - fluid_voice_t *voice; - int i; + fluid_voice_t *voice; + int i; - if (new_polyphony > synth->nvoice) { - /* Create more voices */ - fluid_voice_t** new_voices = FLUID_REALLOC(synth->voice, - sizeof(fluid_voice_t*) * new_polyphony); - if (new_voices == NULL) - return FLUID_FAILED; - synth->voice = new_voices; - for (i = synth->nvoice; i < new_polyphony; i++) { - synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate); - if (synth->voice[i] == NULL) - return FLUID_FAILED; - - fluid_voice_set_custom_filter(synth->voice[i], synth->custom_filter_type, synth->custom_filter_flags); + if(new_polyphony > synth->nvoice) + { + /* Create more voices */ + fluid_voice_t **new_voices = FLUID_REALLOC(synth->voice, + sizeof(fluid_voice_t *) * new_polyphony); + + if(new_voices == NULL) + { + return FLUID_FAILED; + } + + synth->voice = new_voices; + + for(i = synth->nvoice; i < new_polyphony; i++) + { + synth->voice[i] = new_fluid_voice(synth->eventhandler, synth->sample_rate); + + if(synth->voice[i] == NULL) + { + return FLUID_FAILED; + } + + fluid_voice_set_custom_filter(synth->voice[i], synth->custom_filter_type, synth->custom_filter_flags); + } + + synth->nvoice = new_polyphony; } - synth->nvoice = new_polyphony; - } - - synth->polyphony = new_polyphony; - /* turn off any voices above the new limit */ - for (i = synth->polyphony; i < synth->nvoice; i++) - { - voice = synth->voice[i]; - if (fluid_voice_is_playing(voice)) fluid_voice_off (voice); - } - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony, - synth->polyphony, 0.0f); + synth->polyphony = new_polyphony; - return FLUID_OK; + /* turn off any voices above the new limit */ + for(i = synth->polyphony; i < synth->nvoice; i++) + { + voice = synth->voice[i]; + + if(fluid_voice_is_playing(voice)) + { + fluid_voice_off(voice); + } + } + + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony, + synth->polyphony, 0.0f); + + return FLUID_OK; } /** @@ -2819,14 +3179,14 @@ fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth, int new_polyphony) * @since 1.0.6 */ int -fluid_synth_get_polyphony(fluid_synth_t* synth) +fluid_synth_get_polyphony(fluid_synth_t *synth) { - int result; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - - result = synth->polyphony; - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + + result = synth->polyphony; + FLUID_API_RETURN(result); } /** @@ -2834,7 +3194,7 @@ fluid_synth_get_polyphony(fluid_synth_t* synth) * * I.e. the no. of voices that have been * started and have not yet finished. Unless called from synthesis context, - * this number does not necessarily have to be equal to the number of voices + * this number does not necessarily have to be equal to the number of voices * currently processed by the DSP loop, see below. * @param synth FluidSynth instance * @return Number of currently active voices. @@ -2848,14 +3208,14 @@ fluid_synth_get_polyphony(fluid_synth_t* synth) * e.g. an audio driver or the applications audio rendering thread. */ int -fluid_synth_get_active_voice_count(fluid_synth_t* synth) +fluid_synth_get_active_voice_count(fluid_synth_t *synth) { - int result; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); + int result; + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - result = synth->active_voice_count; - FLUID_API_RETURN(result); + result = synth->active_voice_count; + FLUID_API_RETURN(result); } /** @@ -2866,9 +3226,9 @@ fluid_synth_get_active_voice_count(fluid_synth_t* synth) * Audio is synthesized this number of frames at a time. Defaults to 64 frames. */ int -fluid_synth_get_internal_bufsize(fluid_synth_t* synth) +fluid_synth_get_internal_bufsize(fluid_synth_t *synth) { - return FLUID_BUFSIZE; + return FLUID_BUFSIZE; } /** @@ -2880,17 +3240,20 @@ fluid_synth_get_internal_bufsize(fluid_synth_t* synth) * unloaded or reloaded. */ int -fluid_synth_program_reset(fluid_synth_t* synth) +fluid_synth_program_reset(fluid_synth_t *synth) { - int i, prog; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - /* try to set the correct presets */ - for (i = 0; i < synth->midi_channels; i++){ - fluid_channel_get_sfont_bank_prog (synth->channel[i], NULL, NULL, &prog); - fluid_synth_program_change(synth, i, prog); - } - FLUID_API_RETURN(FLUID_OK); + int i, prog; + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + + /* try to set the correct presets */ + for(i = 0; i < synth->midi_channels; i++) + { + fluid_channel_get_sfont_bank_prog(synth->channel[i], NULL, NULL, &prog); + fluid_synth_program_change(synth, i, prog); + } + + FLUID_API_RETURN(FLUID_OK); } /** @@ -2904,24 +3267,24 @@ fluid_synth_program_reset(fluid_synth_t* synth) * @return #FLUID_OK on success, #FLUID_FAILED otherwise * * @note Should only be called from synthesis thread. - * + * * Usage example: * @code{.cpp} const int FramesToRender = 64; int channels; // retrieve number of stereo audio channels fluid_settings_getint(settings, "synth.audio-channels", &channels); - + // we need twice as many (mono-)buffers channels *= 2; - + // fluid_synth_nwrite_float renders planar audio, e.g. if synth.audio-channels==16: each midi channel gets rendered to its own stereo buffer, rather than having one buffer and interleaved PCM float** mix_buf = new float*[channels]; for(int i = 0; i < channels; i++) { mix_buf[i] = new float[FramesToRender]; } - + // retrieve number of (stereo) effect channels (internally hardcoded to reverb (first chan) and chrous (second chan)) fluid_settings_getint(settings, "synth.effects-channels", &channels); channels *= 2; @@ -2931,139 +3294,178 @@ fluid_synth_program_reset(fluid_synth_t* synth) { fx_buf[i] = new float[FramesToRender]; } - + float** mix_buf_l = mix_buf; float** mix_buf_r = &mix_buf[channels/2]; - + float** fx_buf_l = fx_buf; float** fx_buf_r = &fx_buf[channels/2]; - + fluid_synth_nwrite_float(synth, FramesToRender, mix_buf_l, mix_buf_r, fx_buf_l, fx_buf_r) * @endcode */ int -fluid_synth_nwrite_float(fluid_synth_t* synth, int len, - float** left, float** right, - float** fx_left, float** fx_right) +fluid_synth_nwrite_float(fluid_synth_t *synth, int len, + float **left, float **right, + float **fx_left, float **fx_right) { - fluid_real_t* left_in, *fx_left_in; - fluid_real_t* right_in, *fx_right_in; - double time = fluid_utime(); - int i, num, available, count; + fluid_real_t *left_in, *fx_left_in; + fluid_real_t *right_in, *fx_right_in; + double time = fluid_utime(); + int i, num, available, count; #ifdef WITH_FLOAT - int bytes; + int bytes; #endif - float cpu_load; - - /* First, take what's still available in the buffer */ - count = 0; - num = synth->cur; - if (synth->cur < FLUID_BUFSIZE) { - available = FLUID_BUFSIZE - synth->cur; - fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); - fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in); + float cpu_load; - num = (available > len)? len : available; -#ifdef WITH_FLOAT - bytes = num * sizeof(float); -#endif + /* First, take what's still available in the buffer */ + count = 0; + num = synth->cur; - for (i = 0; i < synth->audio_channels; i++) { -#ifdef WITH_FLOAT - FLUID_MEMCPY(left[i], &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); - FLUID_MEMCPY(right[i], &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); -#else //WITH_FLOAT - int j; - for (j = 0; j < num; j++) { - left[i][j] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; - right[i][j] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; - } -#endif //WITH_FLOAT - } - - for (i = 0; i < synth->effects_channels; i++) + if(synth->cur < FLUID_BUFSIZE) { -#ifdef WITH_FLOAT - if(fx_left != NULL) - FLUID_MEMCPY(fx_left[i], &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); - - if(fx_right != NULL) - FLUID_MEMCPY(fx_right[i], &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); -#else //WITH_FLOAT - int j; - if(fx_left != NULL) { - for (j = 0; j < num; j++) - fx_left[i][j] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; - } - - if(fx_right != NULL) { - for (j = 0; j < num; j++) - fx_right[i][j] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; - } -#endif //WITH_FLOAT - } - - count += num; - num += synth->cur; /* if we're now done, num becomes the new synth->cur below */ - } + available = FLUID_BUFSIZE - synth->cur; + fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); + fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in); - /* Then, run one_block() and copy till we have 'len' samples */ - while (count < len) { - fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0); - fluid_synth_render_blocks(synth, 1); // TODO: - fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); - fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in); - - num = (FLUID_BUFSIZE > len - count)? len - count : FLUID_BUFSIZE; + num = (available > len) ? len : available; #ifdef WITH_FLOAT - bytes = num * sizeof(float); + bytes = num * sizeof(float); #endif - for (i = 0; i < synth->audio_channels; i++) { + for(i = 0; i < synth->audio_channels; i++) + { #ifdef WITH_FLOAT - FLUID_MEMCPY(left[i] + count, &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); - FLUID_MEMCPY(right[i] + count, &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); + FLUID_MEMCPY(left[i], &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); + FLUID_MEMCPY(right[i], &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); #else //WITH_FLOAT - int j; - for (j = 0; j < num; j++) { - left[i][j + count] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; - right[i][j + count] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; - } + int j; + + for(j = 0; j < num; j++) + { + left[i][j] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; + right[i][j] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; + } + #endif //WITH_FLOAT + } + + for(i = 0; i < synth->effects_channels; i++) + { +#ifdef WITH_FLOAT + + if(fx_left != NULL) + { + FLUID_MEMCPY(fx_left[i], &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); + } + + if(fx_right != NULL) + { + FLUID_MEMCPY(fx_right[i], &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + synth->cur], bytes); + } + +#else //WITH_FLOAT + int j; + + if(fx_left != NULL) + { + for(j = 0; j < num; j++) + { + fx_left[i][j] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; + } + } + + if(fx_right != NULL) + { + for(j = 0; j < num; j++) + { + fx_right[i][j] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j + synth->cur]; + } + } + +#endif //WITH_FLOAT + } + + count += num; + num += synth->cur; /* if we're now done, num becomes the new synth->cur below */ } - for (i = 0; i < synth->effects_channels; i++) + /* Then, run one_block() and copy till we have 'len' samples */ + while(count < len) { + fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 0); + fluid_synth_render_blocks(synth, 1); // TODO: + fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); + fluid_rvoice_mixer_get_fx_bufs(synth->eventhandler->mixer, &fx_left_in, &fx_right_in); + + num = (FLUID_BUFSIZE > len - count) ? len - count : FLUID_BUFSIZE; #ifdef WITH_FLOAT - if(fx_left != NULL) - FLUID_MEMCPY(fx_left[i] + count, &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); - - if(fx_right != NULL) - FLUID_MEMCPY(fx_right[i] + count, &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); + bytes = num * sizeof(float); +#endif + + for(i = 0; i < synth->audio_channels; i++) + { +#ifdef WITH_FLOAT + FLUID_MEMCPY(left[i] + count, &left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); + FLUID_MEMCPY(right[i] + count, &right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); #else //WITH_FLOAT - int j; - if(fx_left != NULL) { - for (j = 0; j < num; j++) - fx_left[i][j + count] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; - } - - if(fx_right != NULL) { - for (j = 0; j < num; j++) - fx_right[i][j + count] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; - } + int j; + + for(j = 0; j < num; j++) + { + left[i][j + count] = (float) left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; + right[i][j + count] = (float) right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; + } + #endif //WITH_FLOAT + } + + for(i = 0; i < synth->effects_channels; i++) + { +#ifdef WITH_FLOAT + + if(fx_left != NULL) + { + FLUID_MEMCPY(fx_left[i] + count, &fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); + } + + if(fx_right != NULL) + { + FLUID_MEMCPY(fx_right[i] + count, &fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT], bytes); + } + +#else //WITH_FLOAT + int j; + + if(fx_left != NULL) + { + for(j = 0; j < num; j++) + { + fx_left[i][j + count] = (float) fx_left_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; + } + } + + if(fx_right != NULL) + { + for(j = 0; j < num; j++) + { + fx_right[i][j + count] = (float) fx_right_in[i * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + j]; + } + } + +#endif //WITH_FLOAT + } + + count += num; } - count += num; - } + synth->cur = num; - synth->cur = num; + time = fluid_utime() - time; + cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0); + fluid_atomic_float_set(&synth->cpu_load, cpu_load); - time = fluid_utime() - time; - cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0); - fluid_atomic_float_set (&synth->cpu_load, cpu_load); - - return FLUID_OK; + return FLUID_OK; } /** @@ -3123,32 +3525,39 @@ alias with buffers of \c fx. * @endparblock */ int -fluid_synth_process(fluid_synth_t* synth, int len, int nfx, float* fx[], - int nout, float* out[]) +fluid_synth_process(fluid_synth_t *synth, int len, int nfx, float *fx[], + int nout, float *out[]) { - if (nout==2) { - return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1); - } - else { - float **left, **right; - int i; - left = FLUID_ARRAY(float*, nout/2); - right = FLUID_ARRAY(float*, nout/2); - if ((left == NULL) || (right == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory."); - FLUID_FREE(left); - FLUID_FREE(right); - return FLUID_FAILED; + if(nout == 2) + { + return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1); } - for(i=0; ieventhandler->mixer, 1); - l = synth->cur; - fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); + fluid_profile_ref_var(prof_ref); - for (i = 0, j = loff, k = roff; i < len; i++, l++, j += lincr, k += rincr) { - /* fill up the buffers as needed */ - if (l >= synth->curmax) { - int blocksleft = (len-i+FLUID_BUFSIZE-1) / FLUID_BUFSIZE; - synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft); - fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); + fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1); + l = synth->cur; + fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); - l = 0; - } + for(i = 0, j = loff, k = roff; i < len; i++, l++, j += lincr, k += rincr) + { + /* fill up the buffers as needed */ + if(l >= synth->curmax) + { + int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE; + synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft); + fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); - left_out[j] = (float) left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l]; - right_out[k] = (float) right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l]; - } + l = 0; + } - synth->cur = l; + left_out[j] = (float) left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l]; + right_out[k] = (float) right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + l]; + } - time = fluid_utime() - time; - cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0); - fluid_atomic_float_set (&synth->cpu_load, cpu_load); - - fluid_profile_write(FLUID_PROF_WRITE, prof_ref, - fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer), - len); - return FLUID_OK; + synth->cur = l; + + time = fluid_utime() - time; + cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0); + fluid_atomic_float_set(&synth->cpu_load, cpu_load); + + fluid_profile_write(FLUID_PROF_WRITE, prof_ref, + fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer), + len); + return FLUID_OK; } #define DITHER_SIZE 48000 @@ -3220,31 +3631,39 @@ fluid_synth_write_float(fluid_synth_t* synth, int len, static float rand_table[DITHER_CHANNELS][DITHER_SIZE]; /* Init dither table */ -static void +static void init_dither(void) { - float d, dp; - int c, i; + float d, dp; + int c, i; - for (c = 0; c < DITHER_CHANNELS; c++) { - dp = 0; - for (i = 0; i < DITHER_SIZE-1; i++) { - d = rand() / (float)RAND_MAX - 0.5f; - rand_table[c][i] = d - dp; - dp = d; + for(c = 0; c < DITHER_CHANNELS; c++) + { + dp = 0; + + for(i = 0; i < DITHER_SIZE - 1; i++) + { + d = rand() / (float)RAND_MAX - 0.5f; + rand_table[c][i] = d - dp; + dp = d; + } + + rand_table[c][DITHER_SIZE - 1] = 0 - dp; } - rand_table[c][DITHER_SIZE-1] = 0 - dp; - } } /* A portable replacement for roundf(), seems it may actually be faster too! */ static FLUID_INLINE int -roundi (float x) +roundi(float x) { - if (x >= 0.0f) - return (int)(x+0.5f); - else - return (int)(x-0.5f); + if(x >= 0.0f) + { + return (int)(x + 0.5f); + } + else + { + return (int)(x - 0.5f); + } } /** @@ -3268,66 +3687,87 @@ roundi (float x) * 16 bit audio. */ int -fluid_synth_write_s16(fluid_synth_t* synth, int len, - void* lout, int loff, int lincr, - void* rout, int roff, int rincr) +fluid_synth_write_s16(fluid_synth_t *synth, int len, + void *lout, int loff, int lincr, + void *rout, int roff, int rincr) { - int i, j, k, cur; - signed short* left_out = (signed short*) lout; - signed short* right_out = (signed short*) rout; - fluid_real_t* left_in; - fluid_real_t* right_in; - fluid_real_t left_sample; - fluid_real_t right_sample; - double time = fluid_utime(); - int di; - float cpu_load; + int i, j, k, cur; + signed short *left_out = (signed short *) lout; + signed short *right_out = (signed short *) rout; + fluid_real_t *left_in; + fluid_real_t *right_in; + fluid_real_t left_sample; + fluid_real_t right_sample; + double time = fluid_utime(); + int di; + float cpu_load; - fluid_profile_ref_var (prof_ref); - - fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1); - fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); + fluid_profile_ref_var(prof_ref); - cur = synth->cur; - di = synth->dither_index; + fluid_rvoice_mixer_set_mix_fx(synth->eventhandler->mixer, 1); + fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); - for (i = 0, j = loff, k = roff; i < len; i++, cur++, j += lincr, k += rincr) { + cur = synth->cur; + di = synth->dither_index; - /* fill up the buffers as needed */ - if (cur >= synth->curmax) { - int blocksleft = (len-i+FLUID_BUFSIZE-1) / FLUID_BUFSIZE; - synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft); - fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); - cur = 0; + for(i = 0, j = loff, k = roff; i < len; i++, cur++, j += lincr, k += rincr) + { + + /* fill up the buffers as needed */ + if(cur >= synth->curmax) + { + int blocksleft = (len - i + FLUID_BUFSIZE - 1) / FLUID_BUFSIZE; + synth->curmax = FLUID_BUFSIZE * fluid_synth_render_blocks(synth, blocksleft); + fluid_rvoice_mixer_get_bufs(synth->eventhandler->mixer, &left_in, &right_in); + cur = 0; + } + + left_sample = roundi(left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]); + right_sample = roundi(right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]); + + di++; + + if(di >= DITHER_SIZE) + { + di = 0; + } + + /* digital clipping */ + if(left_sample > 32767.0f) + { + left_sample = 32767.0f; + } + + if(left_sample < -32768.0f) + { + left_sample = -32768.0f; + } + + if(right_sample > 32767.0f) + { + right_sample = 32767.0f; + } + + if(right_sample < -32768.0f) + { + right_sample = -32768.0f; + } + + left_out[j] = (signed short) left_sample; + right_out[k] = (signed short) right_sample; } - left_sample = roundi (left_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[0][di]); - right_sample = roundi (right_in[0 * FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT + cur] * 32766.0f + rand_table[1][di]); + synth->cur = cur; + synth->dither_index = di; /* keep dither buffer continous */ - di++; - if (di >= DITHER_SIZE) di = 0; + time = fluid_utime() - time; + cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0); + fluid_atomic_float_set(&synth->cpu_load, cpu_load); - /* digital clipping */ - if (left_sample > 32767.0f) left_sample = 32767.0f; - if (left_sample < -32768.0f) left_sample = -32768.0f; - if (right_sample > 32767.0f) right_sample = 32767.0f; - if (right_sample < -32768.0f) right_sample = -32768.0f; - - left_out[j] = (signed short) left_sample; - right_out[k] = (signed short) right_sample; - } - - synth->cur = cur; - synth->dither_index = di; /* keep dither buffer continous */ - - time = fluid_utime() - time; - cpu_load = 0.5 * (fluid_atomic_float_get(&synth->cpu_load) + time * synth->sample_rate / len / 10000.0); - fluid_atomic_float_set (&synth->cpu_load, cpu_load); - - fluid_profile_write(FLUID_PROF_WRITE, prof_ref, - fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer), - len); - return 0; + fluid_profile_write(FLUID_PROF_WRITE, prof_ref, + fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer), + len); + return 0; } /** @@ -3348,60 +3788,84 @@ fluid_synth_write_s16(fluid_synth_t* synth, int len, * @note Currently private to libfluidsynth. */ void -fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin, - void* lout, int loff, int lincr, - void* rout, int roff, int rincr) +fluid_synth_dither_s16(int *dither_index, int len, float *lin, float *rin, + void *lout, int loff, int lincr, + void *rout, int roff, int rincr) { - int i, j, k; - signed short* left_out = (signed short*) lout; - signed short* right_out = (signed short*) rout; - fluid_real_t left_sample; - fluid_real_t right_sample; - int di = *dither_index; - fluid_profile_ref_var (prof_ref); + int i, j, k; + signed short *left_out = (signed short *) lout; + signed short *right_out = (signed short *) rout; + fluid_real_t left_sample; + fluid_real_t right_sample; + int di = *dither_index; + fluid_profile_ref_var(prof_ref); - for (i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr) { + for(i = 0, j = loff, k = roff; i < len; i++, j += lincr, k += rincr) + { - left_sample = roundi (lin[i] * 32766.0f + rand_table[0][di]); - right_sample = roundi (rin[i] * 32766.0f + rand_table[1][di]); + left_sample = roundi(lin[i] * 32766.0f + rand_table[0][di]); + right_sample = roundi(rin[i] * 32766.0f + rand_table[1][di]); - di++; - if (di >= DITHER_SIZE) di = 0; + di++; - /* digital clipping */ - if (left_sample > 32767.0f) left_sample = 32767.0f; - if (left_sample < -32768.0f) left_sample = -32768.0f; - if (right_sample > 32767.0f) right_sample = 32767.0f; - if (right_sample < -32768.0f) right_sample = -32768.0f; + if(di >= DITHER_SIZE) + { + di = 0; + } - left_out[j] = (signed short) left_sample; - right_out[k] = (signed short) right_sample; - } + /* digital clipping */ + if(left_sample > 32767.0f) + { + left_sample = 32767.0f; + } - *dither_index = di; /* keep dither buffer continous */ + if(left_sample < -32768.0f) + { + left_sample = -32768.0f; + } - fluid_profile(FLUID_PROF_WRITE, prof_ref,0,len); + if(right_sample > 32767.0f) + { + right_sample = 32767.0f; + } + + if(right_sample < -32768.0f) + { + right_sample = -32768.0f; + } + + left_out[j] = (signed short) left_sample; + right_out[k] = (signed short) right_sample; + } + + *dither_index = di; /* keep dither buffer continous */ + + fluid_profile(FLUID_PROF_WRITE, prof_ref, 0, len); } static void -fluid_synth_check_finished_voices(fluid_synth_t* synth) +fluid_synth_check_finished_voices(fluid_synth_t *synth) { - int j; - fluid_rvoice_t* fv; - - while (NULL != (fv = fluid_rvoice_eventhandler_get_finished_voice(synth->eventhandler))) { - for (j=0; j < synth->polyphony; j++) { - if (synth->voice[j]->rvoice == fv) { - fluid_voice_unlock_rvoice(synth->voice[j]); - fluid_voice_stop(synth->voice[j]); - break; - } - else if (synth->voice[j]->overflow_rvoice == fv) { - fluid_voice_overflow_rvoice_finished(synth->voice[j]); - break; - } + int j; + fluid_rvoice_t *fv; + + while(NULL != (fv = fluid_rvoice_eventhandler_get_finished_voice(synth->eventhandler))) + { + for(j = 0; j < synth->polyphony; j++) + { + if(synth->voice[j]->rvoice == fv) + { + fluid_voice_unlock_rvoice(synth->voice[j]); + fluid_voice_stop(synth->voice[j]); + break; + } + else if(synth->voice[j]->overflow_rvoice == fv) + { + fluid_voice_overflow_rvoice_finished(synth->voice[j]); + break; + } + } } - } } /** @@ -3409,9 +3873,9 @@ fluid_synth_check_finished_voices(fluid_synth_t* synth) * Make sure no (other) rendering is running in parallel when * you call this function! */ -void fluid_synth_process_event_queue(fluid_synth_t* synth) +void fluid_synth_process_event_queue(fluid_synth_t *synth) { - fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler); + fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler); } @@ -3421,98 +3885,120 @@ void fluid_synth_process_event_queue(fluid_synth_t* synth) * @return number of blocks rendered. Might (often) return less than requested */ static int -fluid_synth_render_blocks(fluid_synth_t* synth, int blockcount) +fluid_synth_render_blocks(fluid_synth_t *synth, int blockcount) { - int i, maxblocks; - fluid_profile_ref_var (prof_ref); + int i, maxblocks; + fluid_profile_ref_var(prof_ref); - /* Assign ID of synthesis thread */ + /* Assign ID of synthesis thread */ // synth->synth_thread_id = fluid_thread_get_id (); - fluid_check_fpe("??? Just starting up ???"); - - fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler); - - /* do not render more blocks than we can store internally */ - maxblocks = fluid_rvoice_mixer_get_bufcount(synth->eventhandler->mixer); - if (blockcount > maxblocks) - blockcount = maxblocks; - - for (i=0; i < blockcount; i++) { - fluid_sample_timer_process(synth); - fluid_synth_add_ticks(synth, FLUID_BUFSIZE); - - /* If events have been queued waiting for fluid_rvoice_eventhandler_dispatch_all() - * (should only happen with parallel render) stop processing and go for rendering - */ - if (fluid_rvoice_eventhandler_dispatch_count(synth->eventhandler)) { - // Something has happened, we can't process more - blockcount = i+1; - break; + fluid_check_fpe("??? Just starting up ???"); + + fluid_rvoice_eventhandler_dispatch_all(synth->eventhandler); + + /* do not render more blocks than we can store internally */ + maxblocks = fluid_rvoice_mixer_get_bufcount(synth->eventhandler->mixer); + + if(blockcount > maxblocks) + { + blockcount = maxblocks; } - } - fluid_check_fpe("fluid_sample_timer_process"); + for(i = 0; i < blockcount; i++) + { + fluid_sample_timer_process(synth); + fluid_synth_add_ticks(synth, FLUID_BUFSIZE); - blockcount = fluid_rvoice_mixer_render(synth->eventhandler->mixer, blockcount); + /* If events have been queued waiting for fluid_rvoice_eventhandler_dispatch_all() + * (should only happen with parallel render) stop processing and go for rendering + */ + if(fluid_rvoice_eventhandler_dispatch_count(synth->eventhandler)) + { + // Something has happened, we can't process more + blockcount = i + 1; + break; + } + } - /* Testcase, that provokes a denormal floating point error */ + fluid_check_fpe("fluid_sample_timer_process"); + + blockcount = fluid_rvoice_mixer_render(synth->eventhandler->mixer, blockcount); + + /* Testcase, that provokes a denormal floating point error */ #if 0 - {float num=1;while (num != 0){num*=0.5;};}; + { + float num = 1; + + while(num != 0) + { + num *= 0.5; + }; + }; #endif - fluid_check_fpe("??? Remainder of synth_one_block ???"); - fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref, - fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer), - blockcount * FLUID_BUFSIZE); - return blockcount; + fluid_check_fpe("??? Remainder of synth_one_block ???"); + fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref, + fluid_rvoice_mixer_get_active_voices(synth->eventhandler->mixer), + blockcount * FLUID_BUFSIZE); + return blockcount; } /* * Handler for synth.reverb.* and synth.chorus.* double settings. */ -static void fluid_synth_handle_reverb_chorus_num (void *data, const char *name, double value) +static void fluid_synth_handle_reverb_chorus_num(void *data, const char *name, double value) { - fluid_synth_t *synth = (fluid_synth_t *)data; - fluid_return_if_fail(synth != NULL); + fluid_synth_t *synth = (fluid_synth_t *)data; + fluid_return_if_fail(synth != NULL); - if (FLUID_STRCMP(name, "synth.reverb.room-size") == 0) { - fluid_synth_set_reverb_roomsize(synth, value); - } - else if (FLUID_STRCMP(name, "synth.reverb.damp") == 0) { - fluid_synth_set_reverb_damp(synth, value); - } - else if (FLUID_STRCMP(name, "synth.reverb.width") == 0) { - fluid_synth_set_reverb_width(synth, value); - } - else if (FLUID_STRCMP(name, "synth.reverb.level") == 0) { - fluid_synth_set_reverb_level(synth, value); - } - else if (FLUID_STRCMP(name, "synth.chorus.depth") == 0) { - fluid_synth_set_chorus_depth(synth, value); - } - else if (FLUID_STRCMP(name, "synth.chorus.speed") == 0) { - fluid_synth_set_chorus_speed(synth, value); - } - else if (FLUID_STRCMP(name, "synth.chorus.level") == 0) { - fluid_synth_set_chorus_level(synth, value); - } + if(FLUID_STRCMP(name, "synth.reverb.room-size") == 0) + { + fluid_synth_set_reverb_roomsize(synth, value); + } + else if(FLUID_STRCMP(name, "synth.reverb.damp") == 0) + { + fluid_synth_set_reverb_damp(synth, value); + } + else if(FLUID_STRCMP(name, "synth.reverb.width") == 0) + { + fluid_synth_set_reverb_width(synth, value); + } + else if(FLUID_STRCMP(name, "synth.reverb.level") == 0) + { + fluid_synth_set_reverb_level(synth, value); + } + else if(FLUID_STRCMP(name, "synth.chorus.depth") == 0) + { + fluid_synth_set_chorus_depth(synth, value); + } + else if(FLUID_STRCMP(name, "synth.chorus.speed") == 0) + { + fluid_synth_set_chorus_speed(synth, value); + } + else if(FLUID_STRCMP(name, "synth.chorus.level") == 0) + { + fluid_synth_set_chorus_level(synth, value); + } } /* * Handler for synth.reverb.* and synth.chorus.* integer settings. */ -static void fluid_synth_handle_reverb_chorus_int (void *data, const char *name, int value) +static void fluid_synth_handle_reverb_chorus_int(void *data, const char *name, int value) { fluid_synth_t *synth = (fluid_synth_t *)data; fluid_return_if_fail(synth != NULL); - if (FLUID_STRCMP(name, "synth.reverb.active") == 0) { + if(FLUID_STRCMP(name, "synth.reverb.active") == 0) + { fluid_synth_set_reverb_on(synth, value); } - else if (FLUID_STRCMP(name, "synth.chorus.active") == 0) { + else if(FLUID_STRCMP(name, "synth.chorus.active") == 0) + { fluid_synth_set_chorus_on(synth, value); } - else if (FLUID_STRCMP(name, "synth.chorus.nr") == 0) { + else if(FLUID_STRCMP(name, "synth.chorus.nr") == 0) + { fluid_synth_set_chorus_nr(synth, value); } } @@ -3520,74 +4006,85 @@ static void fluid_synth_handle_reverb_chorus_int (void *data, const char *name, /* * Handler for synth.overflow.* settings. */ -static void fluid_synth_handle_overflow (void *data, const char *name, double value) +static void fluid_synth_handle_overflow(void *data, const char *name, double value) { - fluid_synth_t *synth = (fluid_synth_t *)data; - fluid_return_if_fail(synth != NULL); + fluid_synth_t *synth = (fluid_synth_t *)data; + fluid_return_if_fail(synth != NULL); - fluid_synth_api_enter(synth); + fluid_synth_api_enter(synth); - if (FLUID_STRCMP(name, "synth.overflow.percussion") == 0) { - synth->overflow.percussion = value; - } - else if (FLUID_STRCMP(name, "synth.overflow.released") == 0) { - synth->overflow.released = value; - } - else if (FLUID_STRCMP(name, "synth.overflow.sustained") == 0) { - synth->overflow.sustained = value; - } - else if (FLUID_STRCMP(name, "synth.overflow.volume") == 0) { - synth->overflow.volume = value; - } - else if (FLUID_STRCMP(name, "synth.overflow.age") == 0) { - synth->overflow.age = value; - } - else if (FLUID_STRCMP(name, "synth.overflow.important") == 0) { - synth->overflow.important = value; - } - - fluid_synth_api_exit(synth); + if(FLUID_STRCMP(name, "synth.overflow.percussion") == 0) + { + synth->overflow.percussion = value; + } + else if(FLUID_STRCMP(name, "synth.overflow.released") == 0) + { + synth->overflow.released = value; + } + else if(FLUID_STRCMP(name, "synth.overflow.sustained") == 0) + { + synth->overflow.sustained = value; + } + else if(FLUID_STRCMP(name, "synth.overflow.volume") == 0) + { + synth->overflow.volume = value; + } + else if(FLUID_STRCMP(name, "synth.overflow.age") == 0) + { + synth->overflow.age = value; + } + else if(FLUID_STRCMP(name, "synth.overflow.important") == 0) + { + synth->overflow.important = value; + } + + fluid_synth_api_exit(synth); } /* Selects a voice for killing. */ -static fluid_voice_t* -fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t* synth) +static fluid_voice_t * +fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t *synth) { - int i; - float best_prio = OVERFLOW_PRIO_CANNOT_KILL-1; - float this_voice_prio; - fluid_voice_t* voice; - int best_voice_index=-1; - unsigned int ticks = fluid_synth_get_ticks(synth); - - for (i = 0; i < synth->polyphony; i++) { + int i; + float best_prio = OVERFLOW_PRIO_CANNOT_KILL - 1; + float this_voice_prio; + fluid_voice_t *voice; + int best_voice_index = -1; + unsigned int ticks = fluid_synth_get_ticks(synth); - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { - /* safeguard against an available voice. */ - if (_AVAILABLE(voice)) { - return voice; + voice = synth->voice[i]; + + /* safeguard against an available voice. */ + if(_AVAILABLE(voice)) + { + return voice; + } + + this_voice_prio = fluid_voice_get_overflow_prio(voice, &synth->overflow, + ticks); + + /* check if this voice has less priority than the previous candidate. */ + if(this_voice_prio < best_prio) + { + best_voice_index = i; + best_prio = this_voice_prio; + } } - this_voice_prio = fluid_voice_get_overflow_prio(voice, &synth->overflow, - ticks); - /* check if this voice has less priority than the previous candidate. */ - if (this_voice_prio < best_prio) { - best_voice_index = i; - best_prio = this_voice_prio; + if(best_voice_index < 0) + { + return NULL; } - } - if (best_voice_index < 0) { - return NULL; - } + voice = synth->voice[best_voice_index]; + FLUID_LOG(FLUID_DBG, "Killing voice %d, index %d, chan %d, key %d ", + fluid_voice_get_id(voice), best_voice_index, fluid_voice_get_channel(voice), fluid_voice_get_key(voice)); + fluid_voice_off(voice); - voice = synth->voice[best_voice_index]; - FLUID_LOG(FLUID_DBG, "Killing voice %d, index %d, chan %d, key %d ", - fluid_voice_get_id(voice), best_voice_index, fluid_voice_get_channel(voice), fluid_voice_get_key(voice)); - fluid_voice_off(voice); - - return voice; + return voice; } @@ -3607,130 +4104,147 @@ fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t* synth) * @note Should only be called from within synthesis thread, which includes * SoundFont loader preset noteon method. */ -fluid_voice_t* -fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, - int chan, int key, int vel) +fluid_voice_t * +fluid_synth_alloc_voice(fluid_synth_t *synth, fluid_sample_t *sample, + int chan, int key, int vel) { - fluid_return_val_if_fail (sample != NULL, NULL); - FLUID_API_ENTRY_CHAN(NULL); - FLUID_API_RETURN (fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, NULL)); + fluid_return_val_if_fail(sample != NULL, NULL); + FLUID_API_ENTRY_CHAN(NULL); + FLUID_API_RETURN(fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, NULL)); } -fluid_voice_t* -fluid_synth_alloc_voice_LOCAL(fluid_synth_t* synth, fluid_sample_t* sample, int chan, int key, int vel, fluid_zone_range_t* zone_range) +fluid_voice_t * +fluid_synth_alloc_voice_LOCAL(fluid_synth_t *synth, fluid_sample_t *sample, int chan, int key, int vel, fluid_zone_range_t *zone_range) { - int i, k; - fluid_voice_t* voice = NULL; - fluid_channel_t* channel = NULL; - unsigned int ticks; + int i, k; + fluid_voice_t *voice = NULL; + fluid_channel_t *channel = NULL; + unsigned int ticks; - /* check if there's an available synthesis process */ - for (i = 0; i < synth->polyphony; i++) { - if (_AVAILABLE(synth->voice[i])) { - voice = synth->voice[i]; - break; - } - } - - /* No success yet? Then stop a running voice. */ - if (voice == NULL) { - FLUID_LOG(FLUID_DBG, "Polyphony exceeded, trying to kill a voice"); - voice = fluid_synth_free_voice_by_kill_LOCAL(synth); - } - - if (voice == NULL) { - FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key); - return NULL; - } - ticks = fluid_synth_get_ticks(synth); - - if (synth->verbose) { - k = 0; - for (i = 0; i < synth->polyphony; i++) { - if (!_AVAILABLE(synth->voice[i])) { - k++; - } - } - - FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d", - chan, key, vel, synth->storeid, - (float) ticks / 44100.0f, - (fluid_curtime() - synth->start) / 1000.0f, - 0.0f, - k); - } - - channel = synth->channel[chan]; - - if (fluid_voice_init (voice, sample, zone_range, channel, key, vel, - synth->storeid, ticks, synth->gain) != FLUID_OK) { - FLUID_LOG(FLUID_WARN, "Failed to initialize voice"); - return NULL; - } - - /* add the default modulators to the synthesis process. */ - /* custom_breath2att_modulator is not a default modulator specified in SF - it is intended to replace default_vel2att_mod for this channel on demand using - API fluid_synth_set_breath_mode() or shell command setbreathmode for this channel. - */ - { - int mono = fluid_channel_is_playing_mono(channel); - fluid_mod_t* default_mod =synth->default_mod; - while (default_mod != NULL) + /* check if there's an available synthesis process */ + for(i = 0; i < synth->polyphony; i++) { - if( - /* See if default_mod is the velocity_to_attenuation modulator */ - fluid_mod_test_identity(default_mod, &default_vel2att_mod) && - // See if a replacement by custom_breath2att_modulator has been demanded - // for this channel - ((!mono && (channel->mode & FLUID_CHANNEL_BREATH_POLY)) || - (mono && (channel->mode & FLUID_CHANNEL_BREATH_MONO))) - ) + if(_AVAILABLE(synth->voice[i])) { - // Replacement of default_vel2att modulator by custom_breath2att_modulator - fluid_voice_add_mod(voice, &custom_breath2att_mod, FLUID_VOICE_DEFAULT); + voice = synth->voice[i]; + break; } - else - { - fluid_voice_add_mod(voice, default_mod, FLUID_VOICE_DEFAULT); - } - - // Next default modulator to add to the voice - default_mod = default_mod->next; } - } - return voice; + /* No success yet? Then stop a running voice. */ + if(voice == NULL) + { + FLUID_LOG(FLUID_DBG, "Polyphony exceeded, trying to kill a voice"); + voice = fluid_synth_free_voice_by_kill_LOCAL(synth); + } + + if(voice == NULL) + { + FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key); + return NULL; + } + + ticks = fluid_synth_get_ticks(synth); + + if(synth->verbose) + { + k = 0; + + for(i = 0; i < synth->polyphony; i++) + { + if(!_AVAILABLE(synth->voice[i])) + { + k++; + } + } + + FLUID_LOG(FLUID_INFO, "noteon\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d", + chan, key, vel, synth->storeid, + (float) ticks / 44100.0f, + (fluid_curtime() - synth->start) / 1000.0f, + 0.0f, + k); + } + + channel = synth->channel[chan]; + + if(fluid_voice_init(voice, sample, zone_range, channel, key, vel, + synth->storeid, ticks, synth->gain) != FLUID_OK) + { + FLUID_LOG(FLUID_WARN, "Failed to initialize voice"); + return NULL; + } + + /* add the default modulators to the synthesis process. */ + /* custom_breath2att_modulator is not a default modulator specified in SF + it is intended to replace default_vel2att_mod for this channel on demand using + API fluid_synth_set_breath_mode() or shell command setbreathmode for this channel. + */ + { + int mono = fluid_channel_is_playing_mono(channel); + fluid_mod_t *default_mod = synth->default_mod; + + while(default_mod != NULL) + { + if( + /* See if default_mod is the velocity_to_attenuation modulator */ + fluid_mod_test_identity(default_mod, &default_vel2att_mod) && + // See if a replacement by custom_breath2att_modulator has been demanded + // for this channel + ((!mono && (channel->mode & FLUID_CHANNEL_BREATH_POLY)) || + (mono && (channel->mode & FLUID_CHANNEL_BREATH_MONO))) + ) + { + // Replacement of default_vel2att modulator by custom_breath2att_modulator + fluid_voice_add_mod(voice, &custom_breath2att_mod, FLUID_VOICE_DEFAULT); + } + else + { + fluid_voice_add_mod(voice, default_mod, FLUID_VOICE_DEFAULT); + } + + // Next default modulator to add to the voice + default_mod = default_mod->next; + } + } + + return voice; } /* Kill all voices on a given channel, which have the same exclusive class * generator as new_voice. */ static void -fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t* synth, - fluid_voice_t* new_voice) +fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t *synth, + fluid_voice_t *new_voice) { - int excl_class = fluid_voice_gen_value(new_voice, GEN_EXCLUSIVECLASS); - int i; + int excl_class = fluid_voice_gen_value(new_voice, GEN_EXCLUSIVECLASS); + int i; - /* Excl. class 0: No exclusive class */ - if (excl_class == 0) return; + /* Excl. class 0: No exclusive class */ + if(excl_class == 0) + { + return; + } - /* Kill all notes on the same channel with the same exclusive class */ - for (i = 0; i < synth->polyphony; i++) { - fluid_voice_t* existing_voice = synth->voice[i]; - int existing_excl_class = fluid_voice_gen_value(existing_voice, GEN_EXCLUSIVECLASS); + /* Kill all notes on the same channel with the same exclusive class */ + for(i = 0; i < synth->polyphony; i++) + { + fluid_voice_t *existing_voice = synth->voice[i]; + int existing_excl_class = fluid_voice_gen_value(existing_voice, GEN_EXCLUSIVECLASS); - /* If voice is playing, on the same channel, has same exclusive - * class and is not part of the same noteon event (voice group), then kill it */ + /* If voice is playing, on the same channel, has same exclusive + * class and is not part of the same noteon event (voice group), then kill it */ - if (fluid_voice_is_playing(existing_voice) - && fluid_voice_get_channel(existing_voice) == fluid_voice_get_channel(new_voice) - && existing_excl_class == excl_class - && fluid_voice_get_id (existing_voice) != fluid_voice_get_id(new_voice)) - fluid_voice_kill_excl(existing_voice); - } + if(fluid_voice_is_playing(existing_voice) + && fluid_voice_get_channel(existing_voice) == fluid_voice_get_channel(new_voice) + && existing_excl_class == excl_class + && fluid_voice_get_id(existing_voice) != fluid_voice_get_id(new_voice)) + { + fluid_voice_kill_excl(existing_voice); + } + } } /** @@ -3745,22 +4259,22 @@ fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t* synth, * SoundFont loader preset noteon method. */ void -fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* voice) +fluid_synth_start_voice(fluid_synth_t *synth, fluid_voice_t *voice) { - fluid_return_if_fail (synth != NULL); - fluid_return_if_fail (voice != NULL); + fluid_return_if_fail(synth != NULL); + fluid_return_if_fail(voice != NULL); // fluid_return_if_fail (fluid_synth_is_synth_thread (synth)); - fluid_synth_api_enter(synth); + fluid_synth_api_enter(synth); - /* Find the exclusive class of this voice. If set, kill all voices - * that match the exclusive class and are younger than the first - * voice process created by this noteon event. */ - fluid_synth_kill_by_exclusive_class_LOCAL(synth, voice); + /* Find the exclusive class of this voice. If set, kill all voices + * that match the exclusive class and are younger than the first + * voice process created by this noteon event. */ + fluid_synth_kill_by_exclusive_class_LOCAL(synth, voice); - fluid_voice_start(voice); /* Start the new voice */ - fluid_voice_lock_rvoice(voice); - fluid_rvoice_eventhandler_add_rvoice(synth->eventhandler, voice->rvoice); - fluid_synth_api_exit(synth); + fluid_voice_start(voice); /* Start the new voice */ + fluid_voice_lock_rvoice(voice); + fluid_rvoice_eventhandler_add_rvoice(synth->eventhandler, voice->rvoice); + fluid_synth_api_exit(synth); } /** @@ -3778,16 +4292,19 @@ fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* voice) * @note Should only be called before any SoundFont files are loaded. */ void -fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader) +fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader) { - fluid_return_if_fail (synth != NULL); - fluid_return_if_fail (loader != NULL); - fluid_synth_api_enter(synth); + fluid_return_if_fail(synth != NULL); + fluid_return_if_fail(loader != NULL); + fluid_synth_api_enter(synth); - /* Test if sfont is already loaded */ - if (synth->sfont == NULL) - synth->loaders = fluid_list_prepend(synth->loaders, loader); - fluid_synth_api_exit(synth); + /* Test if sfont is already loaded */ + if(synth->sfont == NULL) + { + synth->loaders = fluid_list_prepend(synth->loaders, loader); + } + + fluid_synth_api_exit(synth); } /** @@ -3802,42 +4319,49 @@ fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader) * @return SoundFont ID on success, #FLUID_FAILED on error */ int -fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets) +fluid_synth_sfload(fluid_synth_t *synth, const char *filename, int reset_presets) { - fluid_sfont_t *sfont; - fluid_list_t *list; - fluid_sfloader_t *loader; - int sfont_id; + fluid_sfont_t *sfont; + fluid_list_t *list; + fluid_sfloader_t *loader; + int sfont_id; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (filename != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - - sfont_id = synth->sfont_id; - if(++sfont_id != FLUID_FAILED) - { - /* MT NOTE: Loaders list should not change. */ + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(filename != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - for (list = synth->loaders; list; list = fluid_list_next(list)) { - loader = (fluid_sfloader_t*) fluid_list_get(list); + sfont_id = synth->sfont_id; - sfont = fluid_sfloader_load(loader, filename); + if(++sfont_id != FLUID_FAILED) + { + /* MT NOTE: Loaders list should not change. */ - if (sfont != NULL) { - sfont->refcount++; - synth->sfont_id = sfont->id = sfont_id; - - synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */ + for(list = synth->loaders; list; list = fluid_list_next(list)) + { + loader = (fluid_sfloader_t *) fluid_list_get(list); - /* reset the presets for all channels if requested */ - if (reset_presets) fluid_synth_program_reset(synth); + sfont = fluid_sfloader_load(loader, filename); - FLUID_API_RETURN(sfont_id); + if(sfont != NULL) + { + sfont->refcount++; + synth->sfont_id = sfont->id = sfont_id; + + synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */ + + /* reset the presets for all channels if requested */ + if(reset_presets) + { + fluid_synth_program_reset(synth); + } + + FLUID_API_RETURN(sfont_id); + } + } } - } - } - FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); - FLUID_API_RETURN(FLUID_FAILED); + + FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); + FLUID_API_RETURN(FLUID_FAILED); } /** @@ -3848,71 +4372,85 @@ fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets * @return #FLUID_OK on success, #FLUID_FAILED on error */ int -fluid_synth_sfunload(fluid_synth_t* synth, int id, int reset_presets) +fluid_synth_sfunload(fluid_synth_t *synth, int id, int reset_presets) { - fluid_sfont_t *sfont = NULL; - fluid_list_t *list; + fluid_sfont_t *sfont = NULL; + fluid_list_t *list; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - - /* remove the SoundFont from the list */ - for (list = synth->sfont; list; list = fluid_list_next(list)) { - sfont = fluid_list_get(list); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - if (fluid_sfont_get_id (sfont) == id) + /* remove the SoundFont from the list */ + for(list = synth->sfont; list; list = fluid_list_next(list)) { - synth->sfont = fluid_list_remove (synth->sfont, sfont); - break; + sfont = fluid_list_get(list); + + if(fluid_sfont_get_id(sfont) == id) + { + synth->sfont = fluid_list_remove(synth->sfont, sfont); + break; + } } - } - if (!list) { - FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); - FLUID_API_RETURN(FLUID_FAILED); - } + if(!list) + { + FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); + FLUID_API_RETURN(FLUID_FAILED); + } - /* reset the presets for all channels (SoundFont will be freed when there are no more references) */ - if (reset_presets) fluid_synth_program_reset (synth); - else fluid_synth_update_presets (synth); + /* reset the presets for all channels (SoundFont will be freed when there are no more references) */ + if(reset_presets) + { + fluid_synth_program_reset(synth); + } + else + { + fluid_synth_update_presets(synth); + } - /* -- Remove synth->sfont list's reference to SoundFont */ - fluid_synth_sfont_unref (synth, sfont); + /* -- Remove synth->sfont list's reference to SoundFont */ + fluid_synth_sfont_unref(synth, sfont); - FLUID_API_RETURN(FLUID_OK); + FLUID_API_RETURN(FLUID_OK); } /* Unref a SoundFont and destroy if no more references */ void -fluid_synth_sfont_unref (fluid_synth_t *synth, fluid_sfont_t *sfont) -{ - fluid_return_if_fail (sfont != NULL); /* Shouldn't happen, programming error if so */ +fluid_synth_sfont_unref(fluid_synth_t *synth, fluid_sfont_t *sfont) +{ + fluid_return_if_fail(sfont != NULL); /* Shouldn't happen, programming error if so */ - sfont->refcount--; /* -- Remove the sfont list's reference */ - - if (sfont->refcount == 0) /* No more references? - Attempt delete */ - { - if (fluid_sfont_delete_internal (sfont) == 0) /* SoundFont loader can block SoundFont unload */ + sfont->refcount--; /* -- Remove the sfont list's reference */ + + if(sfont->refcount == 0) /* No more references? - Attempt delete */ { - FLUID_LOG (FLUID_DBG, "Unloaded SoundFont"); - } /* spin off a timer thread to unload the sfont later (SoundFont loader blocked unload) */ - else new_fluid_timer (100, fluid_synth_sfunload_callback, sfont, TRUE, TRUE, FALSE); - } + if(fluid_sfont_delete_internal(sfont) == 0) /* SoundFont loader can block SoundFont unload */ + { + FLUID_LOG(FLUID_DBG, "Unloaded SoundFont"); + } /* spin off a timer thread to unload the sfont later (SoundFont loader blocked unload) */ + else + { + new_fluid_timer(100, fluid_synth_sfunload_callback, sfont, TRUE, TRUE, FALSE); + } + } } /* Callback to continually attempt to unload a SoundFont, * only if a SoundFont loader blocked the unload operation */ static int -fluid_synth_sfunload_callback(void* data, unsigned int msec) +fluid_synth_sfunload_callback(void *data, unsigned int msec) { - fluid_sfont_t *sfont = data; + fluid_sfont_t *sfont = data; - if (fluid_sfont_delete_internal (sfont) == 0) - { - FLUID_LOG (FLUID_DBG, "Unloaded SoundFont"); - return FALSE; - } - else return TRUE; + if(fluid_sfont_delete_internal(sfont) == 0) + { + FLUID_LOG(FLUID_DBG, "Unloaded SoundFont"); + return FALSE; + } + else + { + return TRUE; + } } /** @@ -3922,59 +4460,69 @@ fluid_synth_sfunload_callback(void* data, unsigned int msec) * @return SoundFont ID on success, #FLUID_FAILED on error */ int -fluid_synth_sfreload(fluid_synth_t* synth, int id) +fluid_synth_sfreload(fluid_synth_t *synth, int id) { - char *filename = NULL; - fluid_sfont_t *sfont; - fluid_sfloader_t* loader; - fluid_list_t *list; - int index, ret = FLUID_FAILED; + char *filename = NULL; + fluid_sfont_t *sfont; + fluid_sfloader_t *loader; + fluid_list_t *list; + int index, ret = FLUID_FAILED; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - /* Search for SoundFont and get its index */ - for (list = synth->sfont, index = 0; list; list = fluid_list_next (list), index++) { - sfont = fluid_list_get (list); - if (fluid_sfont_get_id (sfont) == id) break; - } + /* Search for SoundFont and get its index */ + for(list = synth->sfont, index = 0; list; list = fluid_list_next(list), index++) + { + sfont = fluid_list_get(list); - if (!list) { - FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); - goto exit; - } - - /* keep a copy of the SoundFont's filename */ - filename = FLUID_STRDUP(fluid_sfont_get_name (sfont)); - - if (filename == NULL || fluid_synth_sfunload (synth, id, FALSE) != FLUID_OK) - goto exit; - - /* MT Note: SoundFont loader list will not change */ - - for (list = synth->loaders; list; list = fluid_list_next(list)) { - loader = (fluid_sfloader_t*) fluid_list_get(list); - - sfont = fluid_sfloader_load(loader, filename); - - if (sfont != NULL) { - sfont->id = id; - sfont->refcount++; - - synth->sfont = fluid_list_insert_at(synth->sfont, index, sfont); /* insert the sfont at the same index */ - - /* reset the presets for all channels */ - fluid_synth_update_presets(synth); - ret = id; - goto exit; + if(fluid_sfont_get_id(sfont) == id) + { + break; + } } - } - FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); - + if(!list) + { + FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); + goto exit; + } + + /* keep a copy of the SoundFont's filename */ + filename = FLUID_STRDUP(fluid_sfont_get_name(sfont)); + + if(filename == NULL || fluid_synth_sfunload(synth, id, FALSE) != FLUID_OK) + { + goto exit; + } + + /* MT Note: SoundFont loader list will not change */ + + for(list = synth->loaders; list; list = fluid_list_next(list)) + { + loader = (fluid_sfloader_t *) fluid_list_get(list); + + sfont = fluid_sfloader_load(loader, filename); + + if(sfont != NULL) + { + sfont->id = id; + sfont->refcount++; + + synth->sfont = fluid_list_insert_at(synth->sfont, index, sfont); /* insert the sfont at the same index */ + + /* reset the presets for all channels */ + fluid_synth_update_presets(synth); + ret = id; + goto exit; + } + } + + FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); + exit: - FLUID_FREE(filename); - FLUID_API_RETURN(ret); + FLUID_FREE(filename); + FLUID_API_RETURN(ret); } /** @@ -3984,25 +4532,26 @@ exit: * @return New assigned SoundFont ID or #FLUID_FAILED on error */ int -fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) +fluid_synth_add_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont) { - int sfont_id; + int sfont_id; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (sfont != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - - sfont_id = synth->sfont_id; - if(++sfont_id != FLUID_FAILED) - { - synth->sfont_id = sfont->id = sfont_id; - synth->sfont = fluid_list_prepend (synth->sfont, sfont); /* prepend to list */ + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - /* reset the presets for all channels */ - fluid_synth_program_reset (synth); - } + sfont_id = synth->sfont_id; - FLUID_API_RETURN(sfont_id); + if(++sfont_id != FLUID_FAILED) + { + synth->sfont_id = sfont->id = sfont_id; + synth->sfont = fluid_list_prepend(synth->sfont, sfont); /* prepend to list */ + + /* reset the presets for all channels */ + fluid_synth_program_reset(synth); + } + + FLUID_API_RETURN(sfont_id); } /** @@ -4018,32 +4567,33 @@ fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) * therefore this function should not normally be used. */ int -fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) +fluid_synth_remove_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont) { - fluid_sfont_t *sfont_tmp; - fluid_list_t *list; - int ret = FLUID_FAILED; + fluid_sfont_t *sfont_tmp; + fluid_list_t *list; + int ret = FLUID_FAILED; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (sfont != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - - /* remove the SoundFont from the list */ - for (list = synth->sfont; list; list = fluid_list_next(list)) { - sfont_tmp = fluid_list_get(list); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(sfont != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - if (sfont_tmp == sfont) + /* remove the SoundFont from the list */ + for(list = synth->sfont; list; list = fluid_list_next(list)) { - synth->sfont = fluid_list_remove (synth->sfont, sfont_tmp); - ret = FLUID_OK; - break; - } - } + sfont_tmp = fluid_list_get(list); - /* reset the presets for all channels */ - fluid_synth_program_reset (synth); - - FLUID_API_RETURN(ret); + if(sfont_tmp == sfont) + { + synth->sfont = fluid_list_remove(synth->sfont, sfont_tmp); + ret = FLUID_OK; + break; + } + } + + /* reset the presets for all channels */ + fluid_synth_program_reset(synth); + + FLUID_API_RETURN(ret); } /** @@ -4052,14 +4602,14 @@ fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) * @return Count of loaded SoundFont files. */ int -fluid_synth_sfcount(fluid_synth_t* synth) +fluid_synth_sfcount(fluid_synth_t *synth) { - int count; - - fluid_return_val_if_fail (synth != NULL, 0); - fluid_synth_api_enter(synth); - count = fluid_list_size (synth->sfont); - FLUID_API_RETURN(count); + int count; + + fluid_return_val_if_fail(synth != NULL, 0); + fluid_synth_api_enter(synth); + count = fluid_list_size(synth->sfont); + FLUID_API_RETURN(count); } /** @@ -4072,16 +4622,21 @@ fluid_synth_sfcount(fluid_synth_t* synth) * the duration of use of the returned pointer. */ fluid_sfont_t * -fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num) +fluid_synth_get_sfont(fluid_synth_t *synth, unsigned int num) { - fluid_sfont_t *sfont = NULL; - fluid_list_t *list; + fluid_sfont_t *sfont = NULL; + fluid_list_t *list; - fluid_return_val_if_fail (synth != NULL, NULL); - fluid_synth_api_enter(synth); - list = fluid_list_nth (synth->sfont, num); - if (list) sfont = fluid_list_get (list); - FLUID_API_RETURN(sfont); + fluid_return_val_if_fail(synth != NULL, NULL); + fluid_synth_api_enter(synth); + list = fluid_list_nth(synth->sfont, num); + + if(list) + { + sfont = fluid_list_get(list); + } + + FLUID_API_RETURN(sfont); } /** @@ -4094,21 +4649,25 @@ fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num) * the duration of use of the returned pointer. */ fluid_sfont_t * -fluid_synth_get_sfont_by_id(fluid_synth_t* synth, int id) +fluid_synth_get_sfont_by_id(fluid_synth_t *synth, int id) { - fluid_sfont_t* sfont = NULL; - fluid_list_t* list; + fluid_sfont_t *sfont = NULL; + fluid_list_t *list; - fluid_return_val_if_fail (synth != NULL, NULL); - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, NULL); + fluid_synth_api_enter(synth); - for (list = synth->sfont; list; list = fluid_list_next(list)) { - sfont = fluid_list_get (list); - if (fluid_sfont_get_id (sfont) == id) - break; - } + for(list = synth->sfont; list; list = fluid_list_next(list)) + { + sfont = fluid_list_get(list); - FLUID_API_RETURN(list ? sfont : NULL); + if(fluid_sfont_get_id(sfont) == id) + { + break; + } + } + + FLUID_API_RETURN(list ? sfont : NULL); } /** @@ -4122,22 +4681,26 @@ fluid_synth_get_sfont_by_id(fluid_synth_t* synth, int id) * the duration of use of the returned pointer. */ fluid_sfont_t * -fluid_synth_get_sfont_by_name(fluid_synth_t* synth, const char *name) +fluid_synth_get_sfont_by_name(fluid_synth_t *synth, const char *name) { - fluid_sfont_t* sfont = NULL; - fluid_list_t* list; + fluid_sfont_t *sfont = NULL; + fluid_list_t *list; - fluid_return_val_if_fail (synth != NULL, NULL); - fluid_return_val_if_fail (name != NULL, NULL); - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, NULL); + fluid_return_val_if_fail(name != NULL, NULL); + fluid_synth_api_enter(synth); - for (list = synth->sfont; list; list = fluid_list_next(list)) { - sfont = fluid_list_get (list); - if (FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0) - break; - } + for(list = synth->sfont; list; list = fluid_list_next(list)) + { + sfont = fluid_list_get(list); - FLUID_API_RETURN(list ? sfont : NULL); + if(FLUID_STRCMP(fluid_sfont_get_name(sfont), name) == 0) + { + break; + } + } + + FLUID_API_RETURN(list ? sfont : NULL); } /** @@ -4150,16 +4713,16 @@ fluid_synth_get_sfont_by_name(fluid_synth_t* synth, const char *name) * SoundFont loader preset noteon methods. Not thread safe otherwise. */ fluid_preset_t * -fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan) +fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan) { - fluid_preset_t* result; - fluid_channel_t *channel; - FLUID_API_ENTRY_CHAN(NULL); + fluid_preset_t *result; + fluid_channel_t *channel; + FLUID_API_ENTRY_CHAN(NULL); - channel = synth->channel[chan]; - result = channel->preset; - fluid_synth_api_exit(synth); - return result; + channel = synth->channel[chan]; + result = channel->preset; + fluid_synth_api_exit(synth); + return result; } /** @@ -4174,25 +4737,32 @@ fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan) * unchanged until next synthesis process iteration. */ void -fluid_synth_get_voicelist(fluid_synth_t* synth, fluid_voice_t* buf[], int bufsize, +fluid_synth_get_voicelist(fluid_synth_t *synth, fluid_voice_t *buf[], int bufsize, int id) { - int count = 0; - int i; + int count = 0; + int i; - fluid_return_if_fail (synth != NULL); - fluid_return_if_fail (buf != NULL); - fluid_synth_api_enter(synth); + fluid_return_if_fail(synth != NULL); + fluid_return_if_fail(buf != NULL); + fluid_synth_api_enter(synth); - for (i = 0; i < synth->polyphony && count < bufsize; i++) { - fluid_voice_t* voice = synth->voice[i]; + for(i = 0; i < synth->polyphony && count < bufsize; i++) + { + fluid_voice_t *voice = synth->voice[i]; - if (fluid_voice_is_playing(voice) && (id < 0 || (int)voice->id == id)) - buf[count++] = voice; - } + if(fluid_voice_is_playing(voice) && (id < 0 || (int)voice->id == id)) + { + buf[count++] = voice; + } + } - if (count < bufsize) buf[count] = NULL; - fluid_synth_api_exit(synth); + if(count < bufsize) + { + buf[count] = NULL; + } + + fluid_synth_api_exit(synth); } /** @@ -4201,16 +4771,16 @@ fluid_synth_get_voicelist(fluid_synth_t* synth, fluid_voice_t* buf[], int bufsiz * @param on TRUE to enable reverb, FALSE to disable */ void -fluid_synth_set_reverb_on(fluid_synth_t* synth, int on) +fluid_synth_set_reverb_on(fluid_synth_t *synth, int on) { - fluid_return_if_fail (synth != NULL); + fluid_return_if_fail(synth != NULL); - fluid_synth_api_enter(synth); + fluid_synth_api_enter(synth); - synth->with_reverb = (on != 0); - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled, - on != 0, 0.0f); - fluid_synth_api_exit(synth); + synth->with_reverb = (on != 0); + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled, + on != 0, 0.0f); + fluid_synth_api_exit(synth); } /** @@ -4222,17 +4792,17 @@ fluid_synth_set_reverb_on(fluid_synth_t* synth, int on) * @note Currently private to libfluidsynth. */ int -fluid_synth_set_reverb_preset(fluid_synth_t* synth, unsigned int num) +fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num) { - fluid_return_val_if_fail ( - num < FLUID_N_ELEMENTS(revmodel_preset), - FLUID_FAILED - ); + fluid_return_val_if_fail( + num < FLUID_N_ELEMENTS(revmodel_preset), + FLUID_FAILED + ); - fluid_synth_set_reverb (synth, revmodel_preset[num].roomsize, - revmodel_preset[num].damp, revmodel_preset[num].width, - revmodel_preset[num].level); - return FLUID_OK; + fluid_synth_set_reverb(synth, revmodel_preset[num].roomsize, + revmodel_preset[num].damp, revmodel_preset[num].width, + revmodel_preset[num].level); + return FLUID_OK; } /** @@ -4248,18 +4818,18 @@ fluid_synth_set_reverb_preset(fluid_synth_t* synth, unsigned int num) * context at the risk of stalling audio output. */ int -fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize, double damping, +fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize, double damping, double width, double level) { - return fluid_synth_set_reverb_full (synth, FLUID_REVMODEL_SET_ALL, - roomsize, damping, width, level); + return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ALL, + roomsize, damping, width, level); } /** * Set reverb roomsize. See fluid_synth_set_reverb() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_reverb_roomsize(fluid_synth_t* synth, double roomsize) +int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize) { return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_ROOMSIZE, roomsize, 0, 0, 0); } @@ -4268,7 +4838,7 @@ int fluid_synth_set_reverb_roomsize(fluid_synth_t* synth, double roomsize) * Set reverb damping. See fluid_synth_set_reverb() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_reverb_damp(fluid_synth_t* synth, double damping) +int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping) { return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_DAMPING, 0, damping, 0, 0); } @@ -4277,7 +4847,7 @@ int fluid_synth_set_reverb_damp(fluid_synth_t* synth, double damping) * Set reverb width. See fluid_synth_set_reverb() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_reverb_width(fluid_synth_t* synth, double width) +int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width) { return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_WIDTH, 0, 0, width, 0); } @@ -4286,7 +4856,7 @@ int fluid_synth_set_reverb_width(fluid_synth_t* synth, double width) * Set reverb level. See fluid_synth_set_reverb() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_reverb_level(fluid_synth_t* synth, double level) +int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level) { return fluid_synth_set_reverb_full(synth, FLUID_REVMODEL_SET_LEVEL, 0, 0, 0, level); } @@ -4305,52 +4875,60 @@ int fluid_synth_set_reverb_level(fluid_synth_t* synth, double level) * context at the risk of stalling audio output. */ int -fluid_synth_set_reverb_full(fluid_synth_t* synth, int set, double roomsize, +fluid_synth_set_reverb_full(fluid_synth_t *synth, int set, double roomsize, double damping, double width, double level) { - int ret; - - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - /* if non of the flags is set, fail */ - fluid_return_val_if_fail (set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED); + int ret; - /* Synth shadow values are set here so that they will be returned if querried */ + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + /* if non of the flags is set, fail */ + fluid_return_val_if_fail(set & FLUID_REVMODEL_SET_ALL, FLUID_FAILED); - fluid_synth_api_enter(synth); - ret = fluid_synth_set_reverb_full_LOCAL(synth, set, roomsize, damping, width, level); - FLUID_API_RETURN(ret); + /* Synth shadow values are set here so that they will be returned if querried */ + + fluid_synth_api_enter(synth); + ret = fluid_synth_set_reverb_full_LOCAL(synth, set, roomsize, damping, width, level); + FLUID_API_RETURN(ret); } static int -fluid_synth_set_reverb_full_LOCAL(fluid_synth_t* synth, int set, double roomsize, - double damping, double width, double level) +fluid_synth_set_reverb_full_LOCAL(fluid_synth_t *synth, int set, double roomsize, + double damping, double width, double level) { - int ret; - fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - - if (set & FLUID_REVMODEL_SET_ROOMSIZE) - synth->reverb_roomsize = roomsize; + int ret; + fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - if (set & FLUID_REVMODEL_SET_DAMPING) - synth->reverb_damping = damping; + if(set & FLUID_REVMODEL_SET_ROOMSIZE) + { + synth->reverb_roomsize = roomsize; + } - if (set & FLUID_REVMODEL_SET_WIDTH) - synth->reverb_width = width; + if(set & FLUID_REVMODEL_SET_DAMPING) + { + synth->reverb_damping = damping; + } - if (set & FLUID_REVMODEL_SET_LEVEL) - synth->reverb_level = level; + if(set & FLUID_REVMODEL_SET_WIDTH) + { + synth->reverb_width = width; + } - param[0].i = set; - param[1].real = roomsize; - param[2].real = damping; - param[3].real = width; - param[4].real = level; - /* finally enqueue an rvoice event to the mixer to actual update reverb */ - ret = fluid_rvoice_eventhandler_push(synth->eventhandler, - fluid_rvoice_mixer_set_reverb_params, - synth->eventhandler->mixer, - param); - return ret; + if(set & FLUID_REVMODEL_SET_LEVEL) + { + synth->reverb_level = level; + } + + param[0].i = set; + param[1].real = roomsize; + param[2].real = damping; + param[3].real = width; + param[4].real = level; + /* finally enqueue an rvoice event to the mixer to actual update reverb */ + ret = fluid_rvoice_eventhandler_push(synth->eventhandler, + fluid_rvoice_mixer_set_reverb_params, + synth->eventhandler->mixer, + param); + return ret; } /** @@ -4359,13 +4937,13 @@ fluid_synth_set_reverb_full_LOCAL(fluid_synth_t* synth, int set, double roomsize * @return Reverb room size (0.0-1.2) */ double -fluid_synth_get_reverb_roomsize(fluid_synth_t* synth) +fluid_synth_get_reverb_roomsize(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); - result = synth->reverb_roomsize; - FLUID_API_RETURN(result); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); + result = synth->reverb_roomsize; + FLUID_API_RETURN(result); } /** @@ -4374,14 +4952,14 @@ fluid_synth_get_reverb_roomsize(fluid_synth_t* synth) * @return Reverb damping value (0.0-1.0) */ double -fluid_synth_get_reverb_damp(fluid_synth_t* synth) +fluid_synth_get_reverb_damp(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->reverb_damping; - FLUID_API_RETURN(result); + result = synth->reverb_damping; + FLUID_API_RETURN(result); } /** @@ -4390,14 +4968,14 @@ fluid_synth_get_reverb_damp(fluid_synth_t* synth) * @return Reverb level value (0.0-1.0) */ double -fluid_synth_get_reverb_level(fluid_synth_t* synth) +fluid_synth_get_reverb_level(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->reverb_level; - FLUID_API_RETURN(result); + result = synth->reverb_level; + FLUID_API_RETURN(result); } /** @@ -4406,14 +4984,14 @@ fluid_synth_get_reverb_level(fluid_synth_t* synth) * @return Reverb width value (0.0-100.0) */ double -fluid_synth_get_reverb_width(fluid_synth_t* synth) +fluid_synth_get_reverb_width(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->reverb_width; - FLUID_API_RETURN(result); + result = synth->reverb_width; + FLUID_API_RETURN(result); } /** @@ -4421,16 +4999,16 @@ fluid_synth_get_reverb_width(fluid_synth_t* synth) * @param synth FluidSynth instance * @param on TRUE to enable chorus, FALSE to disable */ -void -fluid_synth_set_chorus_on(fluid_synth_t* synth, int on) +void +fluid_synth_set_chorus_on(fluid_synth_t *synth, int on) { - fluid_return_if_fail (synth != NULL); - fluid_synth_api_enter(synth); + fluid_return_if_fail(synth != NULL); + fluid_synth_api_enter(synth); - synth->with_chorus = (on != 0); - fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled, - on != 0, 0.0f); - fluid_synth_api_exit(synth); + synth->with_chorus = (on != 0); + fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled, + on != 0, 0.0f); + fluid_synth_api_exit(synth); } /** @@ -4446,56 +5024,56 @@ fluid_synth_set_chorus_on(fluid_synth_t* synth, int on) * @param type Chorus waveform type (#fluid_chorus_mod) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level, - double speed, double depth_ms, int type) +int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level, + double speed, double depth_ms, int type) { - return fluid_synth_set_chorus_full (synth, FLUID_CHORUS_SET_ALL, nr, level, speed, - depth_ms, type); + return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_ALL, nr, level, speed, + depth_ms, type); } /** * Set the chorus voice count. See fluid_synth_set_chorus() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_chorus_nr(fluid_synth_t* synth, int nr) +int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr) { - return fluid_synth_set_chorus_full (synth, FLUID_CHORUS_SET_NR, nr, 0, 0, 0, 0); + return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_NR, nr, 0, 0, 0, 0); } /** * Set the chorus level. See fluid_synth_set_chorus() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_chorus_level(fluid_synth_t* synth, double level) +int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level) { - return fluid_synth_set_chorus_full (synth, FLUID_CHORUS_SET_LEVEL, 0, level, 0, 0, 0); + return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_LEVEL, 0, level, 0, 0, 0); } /** * Set the chorus speed. See fluid_synth_set_chorus() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_chorus_speed(fluid_synth_t* synth, double speed) +int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed) { - return fluid_synth_set_chorus_full (synth, FLUID_CHORUS_SET_SPEED, 0, 0, speed, 0, 0); + return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_SPEED, 0, 0, speed, 0, 0); } /** * Set the chorus depth. See fluid_synth_set_chorus() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_chorus_depth(fluid_synth_t* synth, double depth_ms) +int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms) { - return fluid_synth_set_chorus_full (synth, FLUID_CHORUS_SET_DEPTH, 0, 0, 0, depth_ms, 0); + return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_DEPTH, 0, 0, 0, depth_ms, 0); } /** * Set the chorus type. See fluid_synth_set_chorus() for further info. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ -int fluid_synth_set_chorus_type(fluid_synth_t* synth, int type) +int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type) { - return fluid_synth_set_chorus_full (synth, FLUID_CHORUS_SET_TYPE, 0, 0, 0, 0, type); + return fluid_synth_set_chorus_full(synth, FLUID_CHORUS_SET_TYPE, 0, 0, 0, 0, type); } /** @@ -4512,57 +5090,67 @@ int fluid_synth_set_chorus_type(fluid_synth_t* synth, int type) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_set_chorus_full(fluid_synth_t* synth, int set, int nr, double level, +fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level, double speed, double depth_ms, int type) { - int ret; - - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - /* if non of the flags is set, fail */ - fluid_return_val_if_fail (set & FLUID_CHORUS_SET_ALL, FLUID_FAILED); + int ret; - /* Synth shadow values are set here so that they will be returned if queried */ - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + /* if non of the flags is set, fail */ + fluid_return_val_if_fail(set & FLUID_CHORUS_SET_ALL, FLUID_FAILED); - ret = fluid_synth_set_chorus_full_LOCAL(synth, set, nr, level, speed, depth_ms, type); - - FLUID_API_RETURN(ret); + /* Synth shadow values are set here so that they will be returned if queried */ + fluid_synth_api_enter(synth); + + ret = fluid_synth_set_chorus_full_LOCAL(synth, set, nr, level, speed, depth_ms, type); + + FLUID_API_RETURN(ret); } static int -fluid_synth_set_chorus_full_LOCAL(fluid_synth_t* synth, int set, int nr, double level, - double speed, double depth_ms, int type) +fluid_synth_set_chorus_full_LOCAL(fluid_synth_t *synth, int set, int nr, double level, + double speed, double depth_ms, int type) { - int ret; - fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - - if (set & FLUID_CHORUS_SET_NR) - synth->chorus_nr = nr; + int ret; + fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - if (set & FLUID_CHORUS_SET_LEVEL) - synth->chorus_level = level; + if(set & FLUID_CHORUS_SET_NR) + { + synth->chorus_nr = nr; + } - if (set & FLUID_CHORUS_SET_SPEED) - synth->chorus_speed = speed; + if(set & FLUID_CHORUS_SET_LEVEL) + { + synth->chorus_level = level; + } - if (set & FLUID_CHORUS_SET_DEPTH) - synth->chorus_depth = depth_ms; + if(set & FLUID_CHORUS_SET_SPEED) + { + synth->chorus_speed = speed; + } - if (set & FLUID_CHORUS_SET_TYPE) - synth->chorus_type = type; - - param[0].i = set; - param[1].i = nr; - param[2].real = level; - param[3].real = speed; - param[4].real = depth_ms; - param[5].i = type; - ret = fluid_rvoice_eventhandler_push(synth->eventhandler, - fluid_rvoice_mixer_set_chorus_params, - synth->eventhandler->mixer, - param); + if(set & FLUID_CHORUS_SET_DEPTH) + { + synth->chorus_depth = depth_ms; + } - return (ret); + if(set & FLUID_CHORUS_SET_TYPE) + { + synth->chorus_type = type; + } + + param[0].i = set; + param[1].i = nr; + param[2].real = level; + param[3].real = speed; + param[4].real = depth_ms; + param[5].i = type; + ret = fluid_rvoice_eventhandler_push(synth->eventhandler, + fluid_rvoice_mixer_set_chorus_params, + synth->eventhandler->mixer, + param); + + return (ret); } /** @@ -4571,14 +5159,14 @@ fluid_synth_set_chorus_full_LOCAL(fluid_synth_t* synth, int set, int nr, double * @return Chorus voice count (0-99) */ int -fluid_synth_get_chorus_nr(fluid_synth_t* synth) +fluid_synth_get_chorus_nr(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->chorus_nr; - FLUID_API_RETURN(result); + result = synth->chorus_nr; + FLUID_API_RETURN(result); } /** @@ -4587,14 +5175,14 @@ fluid_synth_get_chorus_nr(fluid_synth_t* synth) * @return Chorus level value (0.0-10.0) */ double -fluid_synth_get_chorus_level(fluid_synth_t* synth) +fluid_synth_get_chorus_level(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->chorus_level; - FLUID_API_RETURN(result); + result = synth->chorus_level; + FLUID_API_RETURN(result); } /** @@ -4603,14 +5191,14 @@ fluid_synth_get_chorus_level(fluid_synth_t* synth) * @return Chorus speed in Hz (0.29-5.0) */ double -fluid_synth_get_chorus_speed(fluid_synth_t* synth) +fluid_synth_get_chorus_speed(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->chorus_speed; - FLUID_API_RETURN(result); + result = synth->chorus_speed; + FLUID_API_RETURN(result); } /** @@ -4619,14 +5207,14 @@ fluid_synth_get_chorus_speed(fluid_synth_t* synth) * @return Chorus depth */ double -fluid_synth_get_chorus_depth(fluid_synth_t* synth) +fluid_synth_get_chorus_depth(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->chorus_depth; - FLUID_API_RETURN(result); + result = synth->chorus_depth; + FLUID_API_RETURN(result); } /** @@ -4635,14 +5223,14 @@ fluid_synth_get_chorus_depth(fluid_synth_t* synth) * @return Chorus waveform type (#fluid_chorus_mod) */ int -fluid_synth_get_chorus_type(fluid_synth_t* synth) +fluid_synth_get_chorus_type(fluid_synth_t *synth) { - double result; - fluid_return_val_if_fail (synth != NULL, 0.0); - fluid_synth_api_enter(synth); + double result; + fluid_return_val_if_fail(synth != NULL, 0.0); + fluid_synth_api_enter(synth); - result = synth->chorus_type; - FLUID_API_RETURN(result); + result = synth->chorus_type; + FLUID_API_RETURN(result); } /* @@ -4655,32 +5243,41 @@ fluid_synth_get_chorus_type(fluid_synth_t* synth) * release those... */ void -fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth, int chan, - int key) +fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, int chan, + int key) { - int i; - fluid_voice_t* voice; + int i; + fluid_voice_t *voice; - /* storeid is a parameter for fluid_voice_init() */ - synth->storeid = synth->noteid++; + /* storeid is a parameter for fluid_voice_init() */ + synth->storeid = synth->noteid++; - /* for "monophonic playing" key is the previous sustained note - if it exists (0 to 127) or INVALID_NOTE otherwise */ - if(key == INVALID_NOTE) return; - - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; - if (fluid_voice_is_playing(voice) - && (fluid_voice_get_channel(voice) == chan) - && (fluid_voice_get_key(voice) == key) - && (fluid_voice_get_id(voice) != synth->noteid)) { - /* Id of voices that was sustained by sostenuto */ - if(fluid_voice_is_sostenuto(voice)) - synth->storeid = fluid_voice_get_id(voice); - /* Force the voice into release stage (pedaling is ignored) */ - fluid_voice_release(voice); + /* for "monophonic playing" key is the previous sustained note + if it exists (0 to 127) or INVALID_NOTE otherwise */ + if(key == INVALID_NOTE) + { + return; + } + + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; + + if(fluid_voice_is_playing(voice) + && (fluid_voice_get_channel(voice) == chan) + && (fluid_voice_get_key(voice) == key) + && (fluid_voice_get_id(voice) != synth->noteid)) + { + /* Id of voices that was sustained by sostenuto */ + if(fluid_voice_is_sostenuto(voice)) + { + synth->storeid = fluid_voice_get_id(voice); + } + + /* Force the voice into release stage (pedaling is ignored) */ + fluid_voice_release(voice); + } } - } } /** @@ -4691,26 +5288,33 @@ fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth, int chan, * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_set_interp_method(fluid_synth_t* synth, int chan, int interp_method) +fluid_synth_set_interp_method(fluid_synth_t *synth, int chan, int interp_method) { - int i; - - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - if (chan < -1 || chan >= synth->midi_channels) - FLUID_API_RETURN(FLUID_FAILED); + int i; - if (synth->channel[0] == NULL) { - FLUID_LOG (FLUID_ERR, "Channels don't exist (yet)!"); - FLUID_API_RETURN(FLUID_FAILED); - } + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - for (i = 0; i < synth->midi_channels; i++) { - if (chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan) - fluid_channel_set_interp_method(synth->channel[i], interp_method); - } + if(chan < -1 || chan >= synth->midi_channels) + { + FLUID_API_RETURN(FLUID_FAILED); + } - FLUID_API_RETURN(FLUID_OK); + if(synth->channel[0] == NULL) + { + FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!"); + FLUID_API_RETURN(FLUID_FAILED); + } + + for(i = 0; i < synth->midi_channels; i++) + { + if(chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan) + { + fluid_channel_set_interp_method(synth->channel[i], interp_method); + } + } + + FLUID_API_RETURN(FLUID_OK); }; /** @@ -4719,14 +5323,14 @@ fluid_synth_set_interp_method(fluid_synth_t* synth, int chan, int interp_method) * @return Count of MIDI channels */ int -fluid_synth_count_midi_channels(fluid_synth_t* synth) +fluid_synth_count_midi_channels(fluid_synth_t *synth) { - int result; - fluid_return_val_if_fail (synth != NULL, 0); - fluid_synth_api_enter(synth); + int result; + fluid_return_val_if_fail(synth != NULL, 0); + fluid_synth_api_enter(synth); - result = synth->midi_channels; - FLUID_API_RETURN(result); + result = synth->midi_channels; + FLUID_API_RETURN(result); } /** @@ -4735,14 +5339,14 @@ fluid_synth_count_midi_channels(fluid_synth_t* synth) * @return Count of audio channel stereo pairs (1 = 2 channels, 2 = 4, etc) */ int -fluid_synth_count_audio_channels(fluid_synth_t* synth) +fluid_synth_count_audio_channels(fluid_synth_t *synth) { - int result; - fluid_return_val_if_fail (synth != NULL, 0); - fluid_synth_api_enter(synth); + int result; + fluid_return_val_if_fail(synth != NULL, 0); + fluid_synth_api_enter(synth); - result = synth->audio_channels; - FLUID_API_RETURN(result); + result = synth->audio_channels; + FLUID_API_RETURN(result); } /** @@ -4753,14 +5357,14 @@ fluid_synth_count_audio_channels(fluid_synth_t* synth) * @return Count of audio group stereo pairs (1 = 2 channels, 2 = 4, etc) */ int -fluid_synth_count_audio_groups(fluid_synth_t* synth) +fluid_synth_count_audio_groups(fluid_synth_t *synth) { - int result; - fluid_return_val_if_fail (synth != NULL, 0); - fluid_synth_api_enter(synth); + int result; + fluid_return_val_if_fail(synth != NULL, 0); + fluid_synth_api_enter(synth); - result = synth->audio_groups; - FLUID_API_RETURN(result); + result = synth->audio_groups; + FLUID_API_RETURN(result); } /** @@ -4769,14 +5373,14 @@ fluid_synth_count_audio_groups(fluid_synth_t* synth) * @return Count of allocated effects channels */ int -fluid_synth_count_effects_channels(fluid_synth_t* synth) +fluid_synth_count_effects_channels(fluid_synth_t *synth) { - int result; - fluid_return_val_if_fail (synth != NULL, 0); - fluid_synth_api_enter(synth); + int result; + fluid_return_val_if_fail(synth != NULL, 0); + fluid_synth_api_enter(synth); - result = synth->effects_channels; - FLUID_API_RETURN(result); + result = synth->effects_channels; + FLUID_API_RETURN(result); } /** @@ -4785,113 +5389,139 @@ fluid_synth_count_effects_channels(fluid_synth_t* synth) * @return Estimated CPU load value in percent (0-100) */ double -fluid_synth_get_cpu_load(fluid_synth_t* synth) +fluid_synth_get_cpu_load(fluid_synth_t *synth) { - fluid_return_val_if_fail (synth != NULL, 0); - return fluid_atomic_float_get (&synth->cpu_load); + fluid_return_val_if_fail(synth != NULL, 0); + return fluid_atomic_float_get(&synth->cpu_load); } /* Get tuning for a given bank:program */ static fluid_tuning_t * -fluid_synth_get_tuning(fluid_synth_t* synth, int bank, int prog) +fluid_synth_get_tuning(fluid_synth_t *synth, int bank, int prog) { - if ((synth->tuning == NULL) || - (synth->tuning[bank] == NULL) || - (synth->tuning[bank][prog] == NULL)) - return NULL; + if((synth->tuning == NULL) || + (synth->tuning[bank] == NULL) || + (synth->tuning[bank][prog] == NULL)) + { + return NULL; + } - return synth->tuning[bank][prog]; + return synth->tuning[bank][prog]; } /* Replace tuning on a given bank:program (need not already exist). * Synth mutex should already be locked by caller. */ static int -fluid_synth_replace_tuning_LOCK (fluid_synth_t* synth, fluid_tuning_t *tuning, - int bank, int prog, int apply) +fluid_synth_replace_tuning_LOCK(fluid_synth_t *synth, fluid_tuning_t *tuning, + int bank, int prog, int apply) { - fluid_tuning_t *old_tuning; + fluid_tuning_t *old_tuning; - if (synth->tuning == NULL) { - synth->tuning = FLUID_ARRAY(fluid_tuning_t**, 128); - if (synth->tuning == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; + if(synth->tuning == NULL) + { + synth->tuning = FLUID_ARRAY(fluid_tuning_t **, 128); + + if(synth->tuning == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + + FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t **)); } - FLUID_MEMSET(synth->tuning, 0, 128 * sizeof(fluid_tuning_t**)); - } - if (synth->tuning[bank] == NULL) { - synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t*, 128); - if (synth->tuning[bank] == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return FLUID_FAILED; + if(synth->tuning[bank] == NULL) + { + synth->tuning[bank] = FLUID_ARRAY(fluid_tuning_t *, 128); + + if(synth->tuning[bank] == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return FLUID_FAILED; + } + + FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t *)); } - FLUID_MEMSET(synth->tuning[bank], 0, 128 * sizeof(fluid_tuning_t*)); - } - old_tuning = synth->tuning[bank][prog]; - synth->tuning[bank][prog] = tuning; + old_tuning = synth->tuning[bank][prog]; + synth->tuning[bank][prog] = tuning; - if (old_tuning) { - if (!fluid_tuning_unref (old_tuning, 1)) /* -- unref old tuning */ - { /* Replace old tuning if present */ - fluid_synth_replace_tuning_LOCAL (synth, old_tuning, tuning, apply, FALSE); + if(old_tuning) + { + if(!fluid_tuning_unref(old_tuning, 1)) /* -- unref old tuning */ + { + /* Replace old tuning if present */ + fluid_synth_replace_tuning_LOCAL(synth, old_tuning, tuning, apply, FALSE); + } } - } - return FLUID_OK; + return FLUID_OK; } /* Replace a tuning with a new one in all MIDI channels. new_tuning can be * NULL, in which case channels are reset to default equal tempered scale. */ static void -fluid_synth_replace_tuning_LOCAL (fluid_synth_t *synth, fluid_tuning_t *old_tuning, - fluid_tuning_t *new_tuning, int apply, int unref_new) +fluid_synth_replace_tuning_LOCAL(fluid_synth_t *synth, fluid_tuning_t *old_tuning, + fluid_tuning_t *new_tuning, int apply, int unref_new) { - fluid_channel_t *channel; - int old_tuning_unref = 0; - int i; + fluid_channel_t *channel; + int old_tuning_unref = 0; + int i; - for (i = 0; i < synth->midi_channels; i++) - { - channel = synth->channel[i]; - - if (fluid_channel_get_tuning (channel) == old_tuning) + for(i = 0; i < synth->midi_channels; i++) { - old_tuning_unref++; - if (new_tuning) fluid_tuning_ref (new_tuning); /* ++ ref new tuning for channel */ - fluid_channel_set_tuning (channel, new_tuning); + channel = synth->channel[i]; - if (apply) fluid_synth_update_voice_tuning_LOCAL (synth, channel); + if(fluid_channel_get_tuning(channel) == old_tuning) + { + old_tuning_unref++; + + if(new_tuning) + { + fluid_tuning_ref(new_tuning); /* ++ ref new tuning for channel */ + } + + fluid_channel_set_tuning(channel, new_tuning); + + if(apply) + { + fluid_synth_update_voice_tuning_LOCAL(synth, channel); + } + } } - } - /* Send unref old tuning event if any unrefs */ - if (old_tuning && old_tuning_unref) - fluid_tuning_unref (old_tuning, old_tuning_unref); - if (!unref_new || !new_tuning) return; + /* Send unref old tuning event if any unrefs */ + if(old_tuning && old_tuning_unref) + { + fluid_tuning_unref(old_tuning, old_tuning_unref); + } - fluid_tuning_unref (new_tuning, 1); + if(!unref_new || !new_tuning) + { + return; + } + + fluid_tuning_unref(new_tuning, 1); } /* Update voice tunings in realtime */ static void -fluid_synth_update_voice_tuning_LOCAL (fluid_synth_t *synth, fluid_channel_t *channel) +fluid_synth_update_voice_tuning_LOCAL(fluid_synth_t *synth, fluid_channel_t *channel) { - fluid_voice_t *voice; - int i; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) - { - voice = synth->voice[i]; - - if (fluid_voice_is_on(voice) && (voice->channel == channel)) + for(i = 0; i < synth->polyphony; i++) { - fluid_voice_calculate_gen_pitch (voice); - fluid_voice_update_param (voice, GEN_PITCH); + voice = synth->voice[i]; + + if(fluid_voice_is_on(voice) && (voice->channel == channel)) + { + fluid_voice_calculate_gen_pitch(voice); + fluid_voice_update_param(voice, GEN_PITCH); + } } - } } /** @@ -4909,29 +5539,41 @@ fluid_synth_update_voice_tuning_LOCAL (fluid_synth_t *synth, fluid_channel_t *ch * @since 1.1.0 */ int -fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog, - const char* name, const double* pitch, int apply) +fluid_synth_activate_key_tuning(fluid_synth_t *synth, int bank, int prog, + const char *name, const double *pitch, int apply) { - fluid_tuning_t* tuning; - int retval = FLUID_OK; + fluid_tuning_t *tuning; + int retval = FLUID_OK; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED); - fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED); + fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); + fluid_synth_api_enter(synth); - tuning = new_fluid_tuning (name, bank, prog); + tuning = new_fluid_tuning(name, bank, prog); - if (tuning) - { - if (pitch) fluid_tuning_set_all (tuning, pitch); - retval = fluid_synth_replace_tuning_LOCK (synth, tuning, bank, prog, apply); - if (retval == FLUID_FAILED) fluid_tuning_unref (tuning, 1); - } - else retval = FLUID_FAILED; - FLUID_API_RETURN(retval); + if(tuning) + { + if(pitch) + { + fluid_tuning_set_all(tuning, pitch); + } + + retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply); + + if(retval == FLUID_FAILED) + { + fluid_tuning_unref(tuning, 1); + } + } + else + { + retval = FLUID_FAILED; + } + + FLUID_API_RETURN(retval); } /** @@ -4949,30 +5591,37 @@ fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog, * @since 1.1.0 */ int -fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog, - const char* name, const double* pitch, int apply) +fluid_synth_activate_octave_tuning(fluid_synth_t *synth, int bank, int prog, + const char *name, const double *pitch, int apply) { - fluid_tuning_t* tuning; - int retval = FLUID_OK; + fluid_tuning_t *tuning; + int retval = FLUID_OK; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED); - fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (pitch != NULL, FLUID_FAILED); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED); + fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - tuning = new_fluid_tuning (name, bank, prog); + fluid_synth_api_enter(synth); + tuning = new_fluid_tuning(name, bank, prog); - if (tuning) - { - fluid_tuning_set_octave (tuning, pitch); - retval = fluid_synth_replace_tuning_LOCK (synth, tuning, bank, prog, apply); - if (retval == FLUID_FAILED) fluid_tuning_unref (tuning, 1); - } - else retval = FLUID_FAILED; + if(tuning) + { + fluid_tuning_set_octave(tuning, pitch); + retval = fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, apply); - FLUID_API_RETURN(retval); + if(retval == FLUID_FAILED) + { + fluid_tuning_unref(tuning, 1); + } + } + else + { + retval = FLUID_FAILED; + } + + FLUID_API_RETURN(retval); } /** @@ -4993,39 +5642,53 @@ fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog, * used as a basis, if no tuning exists for the given bank and prog. */ int -fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog, - int len, const int *key, const double* pitch, int apply) +fluid_synth_tune_notes(fluid_synth_t *synth, int bank, int prog, + int len, const int *key, const double *pitch, int apply) { - fluid_tuning_t* old_tuning, *new_tuning; - int retval = FLUID_OK; - int i; + fluid_tuning_t *old_tuning, *new_tuning; + int retval = FLUID_OK; + int i; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED); - fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED); - fluid_return_val_if_fail (len > 0, FLUID_FAILED); - fluid_return_val_if_fail (key != NULL, FLUID_FAILED); - fluid_return_val_if_fail (pitch != NULL, FLUID_FAILED); - - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED); + fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED); + fluid_return_val_if_fail(len > 0, FLUID_FAILED); + fluid_return_val_if_fail(key != NULL, FLUID_FAILED); + fluid_return_val_if_fail(pitch != NULL, FLUID_FAILED); - old_tuning = fluid_synth_get_tuning (synth, bank, prog); + fluid_synth_api_enter(synth); - if (old_tuning) - new_tuning = fluid_tuning_duplicate (old_tuning); - else new_tuning = new_fluid_tuning ("Unnamed", bank, prog); + old_tuning = fluid_synth_get_tuning(synth, bank, prog); - if (new_tuning) - { - for (i = 0; i < len; i++) - fluid_tuning_set_pitch (new_tuning, key[i], pitch[i]); + if(old_tuning) + { + new_tuning = fluid_tuning_duplicate(old_tuning); + } + else + { + new_tuning = new_fluid_tuning("Unnamed", bank, prog); + } - retval = fluid_synth_replace_tuning_LOCK (synth, new_tuning, bank, prog, apply); - if (retval == FLUID_FAILED) fluid_tuning_unref (new_tuning, 1); - } - else retval = FLUID_FAILED; + if(new_tuning) + { + for(i = 0; i < len; i++) + { + fluid_tuning_set_pitch(new_tuning, key[i], pitch[i]); + } - FLUID_API_RETURN(retval); + retval = fluid_synth_replace_tuning_LOCK(synth, new_tuning, bank, prog, apply); + + if(retval == FLUID_FAILED) + { + fluid_tuning_unref(new_tuning, 1); + } + } + else + { + retval = FLUID_FAILED; + } + + FLUID_API_RETURN(retval); } /** @@ -5042,65 +5705,77 @@ fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog, * on the given bank and prog. */ int -fluid_synth_activate_tuning(fluid_synth_t* synth, int chan, int bank, int prog, +fluid_synth_activate_tuning(fluid_synth_t *synth, int chan, int bank, int prog, int apply) { - fluid_tuning_t* tuning; - int retval = FLUID_OK; + fluid_tuning_t *tuning; + int retval = FLUID_OK; - //fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - //fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED); - fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED); - fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED); + //fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); + //fluid_return_val_if_fail (chan >= 0 && chan < synth->midi_channels, FLUID_FAILED); + fluid_return_val_if_fail(bank >= 0 && bank < 128, FLUID_FAILED); + fluid_return_val_if_fail(prog >= 0 && prog < 128, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - tuning = fluid_synth_get_tuning (synth, bank, prog); + tuning = fluid_synth_get_tuning(synth, bank, prog); - /* If no tuning exists, create a new default tuning. We do this, so that - * it can be replaced later, if any changes are made. */ - if (!tuning) - { - tuning = new_fluid_tuning ("Unnamed", bank, prog); - if (tuning) fluid_synth_replace_tuning_LOCK (synth, tuning, bank, prog, FALSE); - } + /* If no tuning exists, create a new default tuning. We do this, so that + * it can be replaced later, if any changes are made. */ + if(!tuning) + { + tuning = new_fluid_tuning("Unnamed", bank, prog); - if (tuning) fluid_tuning_ref (tuning); /* ++ ref for outside of lock */ + if(tuning) + { + fluid_synth_replace_tuning_LOCK(synth, tuning, bank, prog, FALSE); + } + } - if (!tuning) - FLUID_API_RETURN(FLUID_FAILED); + if(tuning) + { + fluid_tuning_ref(tuning); /* ++ ref for outside of lock */ + } - fluid_tuning_ref (tuning); /* ++ ref new tuning for following function */ - retval = fluid_synth_set_tuning_LOCAL (synth, chan, tuning, apply); + if(!tuning) + { + FLUID_API_RETURN(FLUID_FAILED); + } - fluid_tuning_unref (tuning, 1); /* -- unref for outside of lock */ + fluid_tuning_ref(tuning); /* ++ ref new tuning for following function */ + retval = fluid_synth_set_tuning_LOCAL(synth, chan, tuning, apply); - FLUID_API_RETURN(retval); + fluid_tuning_unref(tuning, 1); /* -- unref for outside of lock */ + + FLUID_API_RETURN(retval); } /* Local synthesis thread set tuning function (takes over tuning reference) */ static int -fluid_synth_set_tuning_LOCAL (fluid_synth_t *synth, int chan, - fluid_tuning_t *tuning, int apply) +fluid_synth_set_tuning_LOCAL(fluid_synth_t *synth, int chan, + fluid_tuning_t *tuning, int apply) { - fluid_tuning_t *old_tuning; - fluid_channel_t *channel; + fluid_tuning_t *old_tuning; + fluid_channel_t *channel; - channel = synth->channel[chan]; + channel = synth->channel[chan]; - old_tuning = fluid_channel_get_tuning (channel); - fluid_channel_set_tuning (channel, tuning); /* !! Takes over callers reference */ + old_tuning = fluid_channel_get_tuning(channel); + fluid_channel_set_tuning(channel, tuning); /* !! Takes over callers reference */ - if (apply) fluid_synth_update_voice_tuning_LOCAL (synth, channel); + if(apply) + { + fluid_synth_update_voice_tuning_LOCAL(synth, channel); + } - /* Send unref old tuning event */ - if (old_tuning) - { - fluid_tuning_unref (old_tuning, 1); - } + /* Send unref old tuning event */ + if(old_tuning) + { + fluid_tuning_unref(old_tuning, 1); + } - return FLUID_OK; + return FLUID_OK; } /** @@ -5112,15 +5787,15 @@ fluid_synth_set_tuning_LOCAL (fluid_synth_t *synth, int chan, * @since 1.1.0 */ int -fluid_synth_deactivate_tuning(fluid_synth_t* synth, int chan, int apply) +fluid_synth_deactivate_tuning(fluid_synth_t *synth, int chan, int apply) { - int retval = FLUID_OK; + int retval = FLUID_OK; - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - retval = fluid_synth_set_tuning_LOCAL (synth, chan, NULL, apply); + retval = fluid_synth_set_tuning_LOCAL(synth, chan, NULL, apply); - FLUID_API_RETURN(retval); + FLUID_API_RETURN(retval); } /** @@ -5128,12 +5803,12 @@ fluid_synth_deactivate_tuning(fluid_synth_t* synth, int chan, int apply) * @param synth FluidSynth instance */ void -fluid_synth_tuning_iteration_start(fluid_synth_t* synth) +fluid_synth_tuning_iteration_start(fluid_synth_t *synth) { - fluid_return_if_fail (synth != NULL); - fluid_synth_api_enter(synth); - fluid_private_set (synth->tuning_iter, FLUID_INT_TO_POINTER (0)); - fluid_synth_api_exit(synth); + fluid_return_if_fail(synth != NULL); + fluid_synth_api_enter(synth); + fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER(0)); + fluid_synth_api_exit(synth); } /** @@ -5144,48 +5819,59 @@ fluid_synth_tuning_iteration_start(fluid_synth_t* synth) * @return 1 if tuning iteration advanced, 0 if no more tunings */ int -fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog) +fluid_synth_tuning_iteration_next(fluid_synth_t *synth, int *bank, int *prog) { - void *pval; - int b = 0, p = 0; + void *pval; + int b = 0, p = 0; - fluid_return_val_if_fail (synth != NULL, 0); - fluid_return_val_if_fail (bank != NULL, 0); - fluid_return_val_if_fail (prog != NULL, 0); - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, 0); + fluid_return_val_if_fail(bank != NULL, 0); + fluid_return_val_if_fail(prog != NULL, 0); + fluid_synth_api_enter(synth); - /* Current tuning iteration stored as: bank << 8 | program */ - pval = fluid_private_get (synth->tuning_iter); - p = FLUID_POINTER_TO_INT (pval); - b = (p >> 8) & 0xFF; - p &= 0xFF; + /* Current tuning iteration stored as: bank << 8 | program */ + pval = fluid_private_get(synth->tuning_iter); + p = FLUID_POINTER_TO_INT(pval); + b = (p >> 8) & 0xFF; + p &= 0xFF; - if (!synth->tuning) - { - FLUID_API_RETURN(0); - } - - for (; b < 128; b++, p = 0) - { - if (synth->tuning[b] == NULL) continue; - - for (; p < 128; p++) + if(!synth->tuning) { - if (synth->tuning[b][p] == NULL) continue; - - *bank = b; - *prog = p; - - if (p < 127) fluid_private_set (synth->tuning_iter, - FLUID_INT_TO_POINTER (b << 8 | (p + 1))); - else fluid_private_set (synth->tuning_iter, - FLUID_INT_TO_POINTER ((b + 1) << 8)); - - FLUID_API_RETURN(1); + FLUID_API_RETURN(0); } - } - FLUID_API_RETURN(0); + for(; b < 128; b++, p = 0) + { + if(synth->tuning[b] == NULL) + { + continue; + } + + for(; p < 128; p++) + { + if(synth->tuning[b][p] == NULL) + { + continue; + } + + *bank = b; + *prog = p; + + if(p < 127) + { + fluid_private_set(synth->tuning_iter, + FLUID_INT_TO_POINTER(b << 8 | (p + 1))); + } + else + { + fluid_private_set(synth->tuning_iter, FLUID_INT_TO_POINTER((b + 1) << 8)); + } + + FLUID_API_RETURN(1); + } + } + + FLUID_API_RETURN(0); } /** @@ -5199,29 +5885,31 @@ fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog) * @return #FLUID_OK if matching tuning was found, #FLUID_FAILED otherwise */ int -fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog, - char* name, int len, double* pitch) +fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int prog, + char *name, int len, double *pitch) { - fluid_tuning_t* tuning; + fluid_tuning_t *tuning; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - - tuning = fluid_synth_get_tuning (synth, bank, prog); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - if (tuning) - { - if (name) + tuning = fluid_synth_get_tuning(synth, bank, prog); + + if(tuning) { - FLUID_SNPRINTF (name, len - 1, "%s", fluid_tuning_get_name (tuning)); - name[len - 1] = 0; /* make sure the string is null terminated */ + if(name) + { + FLUID_SNPRINTF(name, len - 1, "%s", fluid_tuning_get_name(tuning)); + name[len - 1] = 0; /* make sure the string is null terminated */ + } + + if(pitch) + { + FLUID_MEMCPY(pitch, fluid_tuning_get_all(tuning), 128 * sizeof(double)); + } } - if (pitch) - FLUID_MEMCPY (pitch, fluid_tuning_get_all (tuning), 128 * sizeof (double)); - } - - FLUID_API_RETURN(tuning ? FLUID_OK : FLUID_FAILED); + FLUID_API_RETURN(tuning ? FLUID_OK : FLUID_FAILED); } /** @@ -5230,11 +5918,11 @@ fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog, * @return FluidSynth settings which are assigned to the synth */ fluid_settings_t * -fluid_synth_get_settings(fluid_synth_t* synth) +fluid_synth_get_settings(fluid_synth_t *synth) { - fluid_return_val_if_fail (synth != NULL, NULL); + fluid_return_val_if_fail(synth != NULL, NULL); - return synth->settings; + return synth->settings; } /** @@ -5251,7 +5939,7 @@ fluid_synth_get_settings(fluid_synth_t* synth) * See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont * generator parameters and valid ranges. */ -int fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value) +int fluid_synth_set_gen(fluid_synth_t *synth, int chan, int param, float value) { return fluid_synth_set_gen2(synth, chan, param, value, FALSE, FALSE); } @@ -5275,36 +5963,39 @@ int fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value) * generator parameters and valid ranges. */ int -fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param, - float value, int absolute, int normalized) +fluid_synth_set_gen2(fluid_synth_t *synth, int chan, int param, + float value, int absolute, int normalized) { - float v; - fluid_return_val_if_fail (param >= 0 && param < GEN_LAST, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + float v; + fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - v = normalized ? fluid_gen_scale(param, value) : value; + v = normalized ? fluid_gen_scale(param, value) : value; - fluid_synth_set_gen_LOCAL (synth, chan, param, v, absolute); + fluid_synth_set_gen_LOCAL(synth, chan, param, v, absolute); - FLUID_API_RETURN(FLUID_OK); + FLUID_API_RETURN(FLUID_OK); } /* Synthesis thread local set gen function */ static void -fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan, int param, float value, - int absolute) +fluid_synth_set_gen_LOCAL(fluid_synth_t *synth, int chan, int param, float value, + int absolute) { - fluid_voice_t* voice; - int i; + fluid_voice_t *voice; + int i; - fluid_channel_set_gen (synth->channel[chan], param, value, absolute); + fluid_channel_set_gen(synth->channel[chan], param, value, absolute); - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; - if (fluid_voice_get_channel(voice) == chan) - fluid_voice_set_param (voice, param, value, absolute); - } + if(fluid_voice_get_channel(voice) == chan) + { + fluid_voice_set_param(voice, param, value, absolute); + } + } } /** @@ -5315,14 +6006,14 @@ fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan, int param, float valu * @return Current generator value assigned to MIDI channel */ float -fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param) +fluid_synth_get_gen(fluid_synth_t *synth, int chan, int param) { - float result; - fluid_return_val_if_fail (param >= 0 && param < GEN_LAST, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); + float result; + fluid_return_val_if_fail(param >= 0 && param < GEN_LAST, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - result = fluid_channel_get_gen(synth->channel[chan], param); - FLUID_API_RETURN(result); + result = fluid_channel_get_gen(synth->channel[chan], param); + FLUID_API_RETURN(result); } /** @@ -5332,51 +6023,54 @@ fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param) * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int -fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event) +fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event) { - fluid_synth_t* synth = (fluid_synth_t*) data; - int type = fluid_midi_event_get_type(event); - int chan = fluid_midi_event_get_channel(event); + fluid_synth_t *synth = (fluid_synth_t *) data; + int type = fluid_midi_event_get_type(event); + int chan = fluid_midi_event_get_channel(event); - switch(type) { - case NOTE_ON: - return fluid_synth_noteon(synth, chan, + switch(type) + { + case NOTE_ON: + return fluid_synth_noteon(synth, chan, fluid_midi_event_get_key(event), fluid_midi_event_get_velocity(event)); - case NOTE_OFF: - return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event)); + case NOTE_OFF: + return fluid_synth_noteoff(synth, chan, fluid_midi_event_get_key(event)); - case CONTROL_CHANGE: - return fluid_synth_cc(synth, chan, + case CONTROL_CHANGE: + return fluid_synth_cc(synth, chan, fluid_midi_event_get_control(event), fluid_midi_event_get_value(event)); - case PROGRAM_CHANGE: - return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event)); + case PROGRAM_CHANGE: + return fluid_synth_program_change(synth, chan, fluid_midi_event_get_program(event)); - case CHANNEL_PRESSURE: - return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event)); + case CHANNEL_PRESSURE: + return fluid_synth_channel_pressure(synth, chan, fluid_midi_event_get_program(event)); - case KEY_PRESSURE: - return fluid_synth_key_pressure(synth, chan, - fluid_midi_event_get_key(event), - fluid_midi_event_get_value(event)); + case KEY_PRESSURE: + return fluid_synth_key_pressure(synth, chan, + fluid_midi_event_get_key(event), + fluid_midi_event_get_value(event)); - case PITCH_BEND: - return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event)); + case PITCH_BEND: + return fluid_synth_pitch_bend(synth, chan, fluid_midi_event_get_pitch(event)); - case MIDI_SYSTEM_RESET: - return fluid_synth_system_reset(synth); - case MIDI_SYSEX: - return fluid_synth_sysex (synth, event->paramptr, event->param1, NULL, NULL, NULL, FALSE); - - case MIDI_TEXT: - case MIDI_LYRIC: - case MIDI_SET_TEMPO: - return FLUID_OK; - } - return FLUID_FAILED; + case MIDI_SYSTEM_RESET: + return fluid_synth_system_reset(synth); + + case MIDI_SYSEX: + return fluid_synth_sysex(synth, event->paramptr, event->param1, NULL, NULL, NULL, FALSE); + + case MIDI_TEXT: + case MIDI_LYRIC: + case MIDI_SET_TEMPO: + return FLUID_OK; + } + + return FLUID_FAILED; } /** @@ -5394,17 +6088,17 @@ fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event) * SoundFont loader preset noteon method. */ int -fluid_synth_start(fluid_synth_t* synth, unsigned int id, fluid_preset_t* preset, - int audio_chan, int chan, int key, int vel) +fluid_synth_start(fluid_synth_t *synth, unsigned int id, fluid_preset_t *preset, + int audio_chan, int chan, int key, int vel) { - int result; - fluid_return_val_if_fail (preset != NULL, FLUID_FAILED); - fluid_return_val_if_fail (key >= 0 && key <= 127, FLUID_FAILED); - fluid_return_val_if_fail (vel >= 1 && vel <= 127, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - synth->storeid = id; - result = fluid_preset_noteon (preset, synth, chan, key, vel); - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(preset != NULL, FLUID_FAILED); + fluid_return_val_if_fail(key >= 0 && key <= 127, FLUID_FAILED); + fluid_return_val_if_fail(vel >= 1 && vel <= 127, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + synth->storeid = id; + result = fluid_preset_noteon(preset, synth, chan, key, vel); + FLUID_API_RETURN(result); } /** @@ -5418,66 +6112,70 @@ fluid_synth_start(fluid_synth_t* synth, unsigned int id, fluid_preset_t* preset, * return #FLUID_FAILED if an error occurs. */ int -fluid_synth_stop(fluid_synth_t* synth, unsigned int id) +fluid_synth_stop(fluid_synth_t *synth, unsigned int id) { - int result; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - fluid_synth_stop_LOCAL (synth, id); - result = FLUID_OK; - FLUID_API_RETURN(result); + int result; + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + fluid_synth_stop_LOCAL(synth, id); + result = FLUID_OK; + FLUID_API_RETURN(result); } /* Local synthesis thread variant of fluid_synth_stop */ static void -fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id) +fluid_synth_stop_LOCAL(fluid_synth_t *synth, unsigned int id) { - fluid_voice_t* voice; - int i; + fluid_voice_t *voice; + int i; - for (i = 0; i < synth->polyphony; i++) { - voice = synth->voice[i]; + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; - if (fluid_voice_is_on(voice) && (fluid_voice_get_id (voice) == id)) - fluid_voice_noteoff(voice); - } + if(fluid_voice_is_on(voice) && (fluid_voice_get_id(voice) == id)) + { + fluid_voice_noteoff(voice); + } + } } /** * Offset the bank numbers of a loaded SoundFont, i.e.\ subtract * \c offset from any bank number when assigning instruments. - * + * * @param synth FluidSynth instance * @param sfont_id ID of a loaded SoundFont * @param offset Bank offset value to apply to all instruments * @return #FLUID_OK if the offset was set successfully, #FLUID_FAILED otherwise */ int -fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset) +fluid_synth_set_bank_offset(fluid_synth_t *synth, int sfont_id, int offset) { - fluid_sfont_t *sfont; - fluid_list_t *list; + fluid_sfont_t *sfont; + fluid_list_t *list; - fluid_return_val_if_fail (synth != NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - - for (list = synth->sfont; list; list = fluid_list_next(list)) { - sfont = fluid_list_get (list); + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); - if (fluid_sfont_get_id (sfont) == sfont_id) + for(list = synth->sfont; list; list = fluid_list_next(list)) { - sfont->bankofs = offset; - break; + sfont = fluid_list_get(list); + + if(fluid_sfont_get_id(sfont) == sfont_id) + { + sfont->bankofs = offset; + break; + } } - } - if (!list) - { - FLUID_LOG (FLUID_ERR, "No SoundFont with id = %d", sfont_id); - FLUID_API_RETURN(FLUID_FAILED); - } + if(!list) + { + FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id); + FLUID_API_RETURN(FLUID_FAILED); + } - FLUID_API_RETURN(FLUID_OK); + FLUID_API_RETURN(FLUID_OK); } /** @@ -5487,75 +6185,83 @@ fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset) * @return SoundFont bank offset value */ int -fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id) +fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_id) { - fluid_sfont_t *sfont; - fluid_list_t *list; - int offset = 0; + fluid_sfont_t *sfont; + fluid_list_t *list; + int offset = 0; - fluid_return_val_if_fail (synth != NULL, 0); - fluid_synth_api_enter(synth); + fluid_return_val_if_fail(synth != NULL, 0); + fluid_synth_api_enter(synth); - for (list = synth->sfont; list; list = fluid_list_next(list)) { - sfont = fluid_list_get (list); - - if (fluid_sfont_get_id (sfont) == sfont_id) + for(list = synth->sfont; list; list = fluid_list_next(list)) { - offset = sfont->bankofs; - break; + sfont = fluid_list_get(list); + + if(fluid_sfont_get_id(sfont) == sfont_id) + { + offset = sfont->bankofs; + break; + } } - } - if (!list) - { - FLUID_LOG (FLUID_ERR, "No SoundFont with id = %d", sfont_id); - FLUID_API_RETURN(0); - } + if(!list) + { + FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", sfont_id); + FLUID_API_RETURN(0); + } - FLUID_API_RETURN(offset); + FLUID_API_RETURN(offset); } -void -fluid_synth_api_enter(fluid_synth_t* synth) +void +fluid_synth_api_enter(fluid_synth_t *synth) { - if (synth->use_mutex) { - fluid_rec_mutex_lock(synth->mutex); - } - if (!synth->public_api_count) { - fluid_synth_check_finished_voices(synth); - } - synth->public_api_count++; + if(synth->use_mutex) + { + fluid_rec_mutex_lock(synth->mutex); + } + + if(!synth->public_api_count) + { + fluid_synth_check_finished_voices(synth); + } + + synth->public_api_count++; } -void fluid_synth_api_exit(fluid_synth_t* synth) +void fluid_synth_api_exit(fluid_synth_t *synth) { - synth->public_api_count--; - if (!synth->public_api_count) { - fluid_rvoice_eventhandler_flush(synth->eventhandler); - } + synth->public_api_count--; + + if(!synth->public_api_count) + { + fluid_rvoice_eventhandler_flush(synth->eventhandler); + } + + if(synth->use_mutex) + { + fluid_rec_mutex_unlock(synth->mutex); + } - if (synth->use_mutex) { - fluid_rec_mutex_unlock(synth->mutex); - } - } /** - * Set midi channel type + * Set midi channel type * @param synth FluidSynth instance * @param chan MIDI channel number (0 to MIDI channel count - 1) * @param type MIDI channel type (#fluid_midi_channel_type) * @return #FLUID_OK on success, #FLUID_FAILED otherwise * @since 1.1.4 */ -int fluid_synth_set_channel_type(fluid_synth_t* synth, int chan, int type) +int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type) { - fluid_return_val_if_fail ((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - synth->channel[chan]->channel_type = type; + fluid_return_val_if_fail((type >= CHANNEL_TYPE_MELODIC) && (type <= CHANNEL_TYPE_DRUM), FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); - FLUID_API_RETURN(FLUID_OK); + synth->channel[chan]->channel_type = type; + + FLUID_API_RETURN(FLUID_OK); } /** @@ -5573,36 +6279,36 @@ fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth) /** * Configure a general-purpose IIR biquad filter. - * + * * This is an optional, additional filter that operates independently from the default low-pass filter required by the Soundfont2 standard. * By default this filter is off (#FLUID_IIR_DISABLED). - * + * * @param synth FluidSynth instance * @param type Type of the IIR filter to use (see #fluid_iir_filter_type) * @param flags Additional flags to customize this filter or zero to stay with the default (see #fluid_iir_filter_flags) - * + * * @return #FLUID_OK if the settings have been successfully applied, otherwise #FLUID_FAILED */ -int fluid_synth_set_custom_filter(fluid_synth_t* synth, int type, int flags) +int fluid_synth_set_custom_filter(fluid_synth_t *synth, int type, int flags) { int i; fluid_voice_t *voice; - + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); fluid_return_val_if_fail(type >= FLUID_IIR_DISABLED && type < FLUID_IIR_LAST, FLUID_FAILED); - + fluid_synth_api_enter(synth); - + synth->custom_filter_type = type; synth->custom_filter_flags = flags; - - for (i = 0; i < synth->polyphony; i++) + + for(i = 0; i < synth->polyphony; i++) { voice = synth->voice[i]; - + fluid_voice_set_custom_filter(voice, type, flags); } - + FLUID_API_RETURN(FLUID_OK); } @@ -5624,36 +6330,42 @@ static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char * fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); scores = &synth->overflow; - if (scores->num_important_channels < synth->midi_channels) + + if(scores->num_important_channels < synth->midi_channels) { scores->important_channels = FLUID_REALLOC(scores->important_channels, - sizeof(*scores->important_channels) * synth->midi_channels); - if (scores->important_channels == NULL) + sizeof(*scores->important_channels) * synth->midi_channels); + + if(scores->important_channels == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); goto exit; } + scores->num_important_channels = synth->midi_channels; } FLUID_MEMSET(scores->important_channels, FALSE, - sizeof(*scores->important_channels) * scores->num_important_channels); + sizeof(*scores->important_channels) * scores->num_important_channels); - if (channels != NULL) + if(channels != NULL) { values = FLUID_ARRAY(int, synth->midi_channels); - if (values == NULL) + + if(values == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); goto exit; } + /* Every channel given in the comma-separated list of channel numbers * is set to TRUE, i.e. flagging it as "important". Channel numbers are * 1-based. */ num_values = fluid_settings_split_csv(channels, values, synth->midi_channels); - for (i = 0; i < num_values; i++) + + for(i = 0; i < num_values; i++) { - if (values[i] > 0 && values[i] <= synth->midi_channels) + if(values[i] > 0 && values[i] <= synth->midi_channels) { scores->important_channels[values[i] - 1] = TRUE; } @@ -5685,28 +6397,28 @@ static void fluid_synth_handle_important_channels(void *data, const char *name, /** * Sets the legato mode of a channel. - * + * * @param synth the synth instance. * @param chan MIDI channel number (0 to MIDI channel count - 1). * @param legatomode The legato mode as indicated by #fluid_channel_legato_mode. * * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. * - \a legatomode is invalid. */ -int fluid_synth_set_legato_mode(fluid_synth_t* synth, int chan, int legatomode) +int fluid_synth_set_legato_mode(fluid_synth_t *synth, int chan, int legatomode) { - /* checks parameters first */ - fluid_return_val_if_fail (legatomode >= 0, FLUID_FAILED); - fluid_return_val_if_fail (legatomode < FLUID_CHANNEL_LEGATO_MODE_LAST, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /**/ - synth->channel[chan]->legatomode = legatomode; - /**/ - FLUID_API_RETURN(FLUID_OK); + /* checks parameters first */ + fluid_return_val_if_fail(legatomode >= 0, FLUID_FAILED); + fluid_return_val_if_fail(legatomode < FLUID_CHANNEL_LEGATO_MODE_LAST, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + /**/ + synth->channel[chan]->legatomode = legatomode; + /**/ + FLUID_API_RETURN(FLUID_OK); } /** @@ -5718,20 +6430,20 @@ int fluid_synth_set_legato_mode(fluid_synth_t* synth, int chan, int legatomode) * * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. * - \a legatomode is NULL. */ -int fluid_synth_get_legato_mode(fluid_synth_t* synth, int chan, int *legatomode) +int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode) { - /* checks parameters first */ - fluid_return_val_if_fail (legatomode!= NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /**/ - * legatomode = synth->channel[chan]->legatomode; - /**/ - FLUID_API_RETURN(FLUID_OK); + /* checks parameters first */ + fluid_return_val_if_fail(legatomode != NULL, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + /**/ + * legatomode = synth->channel[chan]->legatomode; + /**/ + FLUID_API_RETURN(FLUID_OK); } /** API portamento mode *********************************************************/ @@ -5744,22 +6456,22 @@ int fluid_synth_get_legato_mode(fluid_synth_t* synth, int chan, int *legatomode) * @param portamentomode The portamento mode as indicated by #fluid_channel_portamento_mode. * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. * - \a portamentomode is invalid. */ -int fluid_synth_set_portamento_mode(fluid_synth_t* synth, int chan, - int portamentomode) +int fluid_synth_set_portamento_mode(fluid_synth_t *synth, int chan, + int portamentomode) { - /* checks parameters first */ - fluid_return_val_if_fail (portamentomode >= 0, FLUID_FAILED); - fluid_return_val_if_fail (portamentomode < FLUID_CHANNEL_PORTAMENTO_MODE_LAST, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /**/ - synth->channel[chan]->portamentomode = portamentomode; - /**/ - FLUID_API_RETURN(FLUID_OK); + /* checks parameters first */ + fluid_return_val_if_fail(portamentomode >= 0, FLUID_FAILED); + fluid_return_val_if_fail(portamentomode < FLUID_CHANNEL_PORTAMENTO_MODE_LAST, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + /**/ + synth->channel[chan]->portamentomode = portamentomode; + /**/ + FLUID_API_RETURN(FLUID_OK); } /** @@ -5770,21 +6482,21 @@ int fluid_synth_set_portamento_mode(fluid_synth_t* synth, int chan, * @param portamentomode Pointer to the portamento mode as indicated by #fluid_channel_portamento_mode. * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. * - \a portamentomode is NULL. */ -int fluid_synth_get_portamento_mode(fluid_synth_t* synth, int chan, - int *portamentomode) +int fluid_synth_get_portamento_mode(fluid_synth_t *synth, int chan, + int *portamentomode) { - /* checks parameters first */ - fluid_return_val_if_fail (portamentomode!= NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /**/ - * portamentomode = synth->channel[chan]->portamentomode; - /**/ - FLUID_API_RETURN(FLUID_OK); + /* checks parameters first */ + fluid_return_val_if_fail(portamentomode != NULL, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + /**/ + * portamentomode = synth->channel[chan]->portamentomode; + /**/ + FLUID_API_RETURN(FLUID_OK); } /** API breath mode *********************************************************/ @@ -5798,18 +6510,18 @@ int fluid_synth_get_portamento_mode(fluid_synth_t* synth, int chan, * * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. */ -int fluid_synth_set_breath_mode(fluid_synth_t* synth, int chan, int breathmode) +int fluid_synth_set_breath_mode(fluid_synth_t *synth, int chan, int breathmode) { - /* checks parameters first */ - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /**/ - fluid_channel_set_breath_info(synth->channel[chan],breathmode); - /**/ - FLUID_API_RETURN(FLUID_OK); + /* checks parameters first */ + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + /**/ + fluid_channel_set_breath_info(synth->channel[chan], breathmode); + /**/ + FLUID_API_RETURN(FLUID_OK); } /** @@ -5821,20 +6533,20 @@ int fluid_synth_set_breath_mode(fluid_synth_t* synth, int chan, int breathmode) * * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. * - \a breathmode is NULL. */ -int fluid_synth_get_breath_mode(fluid_synth_t* synth, int chan, int *breathmode) +int fluid_synth_get_breath_mode(fluid_synth_t *synth, int chan, int *breathmode) { - /* checks parameters first */ - fluid_return_val_if_fail (breathmode!= NULL, FLUID_FAILED); - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /**/ - * breathmode = fluid_channel_get_breath_info(synth->channel[chan]); - /**/ - FLUID_API_RETURN(FLUID_OK); + /* checks parameters first */ + fluid_return_val_if_fail(breathmode != NULL, FLUID_FAILED); + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + /**/ + * breathmode = fluid_channel_get_breath_info(synth->channel[chan]); + /**/ + FLUID_API_RETURN(FLUID_OK); } /** API Poly/mono mode ******************************************************/ @@ -5843,17 +6555,18 @@ int fluid_synth_get_breath_mode(fluid_synth_t* synth, int chan, int *breathmode) * Resets a basic channel group of MIDI channels. * @param synth the synth instance. * @param chan the beginning channel of the group. - * @param nbr_chan the number of channel in the group. + * @param nbr_chan the number of channel in the group. */ static void -fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t* synth, int chan, int nbr_chan) +fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t *synth, int chan, int nbr_chan) { - int i; - for (i = chan; i < chan + nbr_chan; i++) - { - fluid_channel_reset_basic_channel_info(synth->channel[i]); - synth->channel[i]->mode_val = 0; - } + int i; + + for(i = chan; i < chan + nbr_chan; i++) + { + fluid_channel_reset_basic_channel_info(synth->channel[i]); + synth->channel[i]->mode_val = 0; + } } /** @@ -5865,52 +6578,55 @@ fluid_synth_reset_basic_channel_LOCAL(fluid_synth_t* synth, int chan, int nbr_ch * a synth instance has one basic channel at channel 0 in mode #FLUID_CHANNEL_MODE_OMNION_POLY. * All other channels belong to this basic channel group. Make sure to call this function before * setting any custom basic channel setup. - * + * * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. - * - \a chan isn't a basic channel. + * - \a chan isn't a basic channel. */ -int fluid_synth_reset_basic_channel(fluid_synth_t* synth, int chan) +int fluid_synth_reset_basic_channel(fluid_synth_t *synth, int chan) { int nbr_chan; - + /* checks parameters first */ - if (chan < 0) - { - fluid_return_val_if_fail (synth!= NULL, FLUID_FAILED); - fluid_synth_api_enter(synth); - /* The range is all MIDI channels from 0 to MIDI channel count -1 */ - chan = 0; /* beginning chan */ - nbr_chan = synth->midi_channels; /* MIDI Channels number */ - } - else - { - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /* checks if chan is a basic channel */ - if ( ! (synth->channel[chan]->mode & FLUID_CHANNEL_BASIC) ) - { - FLUID_API_RETURN(FLUID_FAILED); - } - /* The range is all MIDI channels in the group from chan */ - nbr_chan = synth->channel[chan]->mode_val; /* nbr of channels in the group */ - } - /* resets the range of MIDI channels */ - fluid_synth_reset_basic_channel_LOCAL(synth, chan, nbr_chan); + if(chan < 0) + { + fluid_return_val_if_fail(synth != NULL, FLUID_FAILED); + fluid_synth_api_enter(synth); + /* The range is all MIDI channels from 0 to MIDI channel count -1 */ + chan = 0; /* beginning chan */ + nbr_chan = synth->midi_channels; /* MIDI Channels number */ + } + else + { + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + /* checks if chan is a basic channel */ + if(!(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC)) + { + FLUID_API_RETURN(FLUID_FAILED); + } + + /* The range is all MIDI channels in the group from chan */ + nbr_chan = synth->channel[chan]->mode_val; /* nbr of channels in the group */ + } + + /* resets the range of MIDI channels */ + fluid_synth_reset_basic_channel_LOCAL(synth, chan, nbr_chan); FLUID_API_RETURN(FLUID_OK); } /** * Checks if a new basic channel group overlaps the next basic channel group. - * + * * On success the function returns the possible number of channel for this * new basic channel group. * The function fails if the new group overlaps the next basic channel group. - * + * * @param see fluid_synth_set_basic_channel. - * @return + * @return * - On success, the effective number of channels for this new basic channel group, * #FLUID_FAILED otherwise. * - #FLUID_FAILED @@ -5918,66 +6634,70 @@ int fluid_synth_reset_basic_channel(fluid_synth_t* synth, int chan) * above MIDI channel count. */ static int -fluid_synth_check_next_basic_channel(fluid_synth_t* synth, int basicchan, int mode, int val) +fluid_synth_check_next_basic_channel(fluid_synth_t *synth, int basicchan, int mode, int val) { - int i, n_chan = synth->midi_channels; /* MIDI Channels count */ - int real_val = val; /* real number of channels in the group */ + int i, n_chan = synth->midi_channels; /* MIDI Channels count */ + int real_val = val; /* real number of channels in the group */ - /* adjusts val range */ - if (mode == FLUID_CHANNEL_MODE_OMNIOFF_POLY) - { - real_val = 1; /* mode poly omnioff implies a group of only one channel.*/ - } - else if (val == 0) - { - /* mode poly omnion (0), mono omnion (1), mono omni off (3) */ - /* value 0 means all possible channels from basicchan to MIDI channel count -1.*/ - real_val = n_chan - basicchan; - } - /* checks if val range is above MIDI channel count */ - else if ( basicchan + val > n_chan) - { - return FLUID_FAILED; - } - /* checks if this basic channel group overlaps next basic channel group */ - for (i = basicchan + 1; i < basicchan + real_val; i++) - { - if (synth->channel[i]->mode & FLUID_CHANNEL_BASIC) - { - /* A value of 0 for val means all possible channels from basicchan to - to the next basic channel -1 (if any). - When i reachs the next basic channel group, real_val will be - limited if it is possible */ - if (val == 0) - { /* limitation of real_val */ - real_val = i - basicchan; - break; - } - /* overlap with the next basic channel group */ - return FLUID_FAILED; - } - } - return real_val; + /* adjusts val range */ + if(mode == FLUID_CHANNEL_MODE_OMNIOFF_POLY) + { + real_val = 1; /* mode poly omnioff implies a group of only one channel.*/ + } + else if(val == 0) + { + /* mode poly omnion (0), mono omnion (1), mono omni off (3) */ + /* value 0 means all possible channels from basicchan to MIDI channel count -1.*/ + real_val = n_chan - basicchan; + } + /* checks if val range is above MIDI channel count */ + else if(basicchan + val > n_chan) + { + return FLUID_FAILED; + } + + /* checks if this basic channel group overlaps next basic channel group */ + for(i = basicchan + 1; i < basicchan + real_val; i++) + { + if(synth->channel[i]->mode & FLUID_CHANNEL_BASIC) + { + /* A value of 0 for val means all possible channels from basicchan to + to the next basic channel -1 (if any). + When i reachs the next basic channel group, real_val will be + limited if it is possible */ + if(val == 0) + { + /* limitation of real_val */ + real_val = i - basicchan; + break; + } + + /* overlap with the next basic channel group */ + return FLUID_FAILED; + } + } + + return real_val; } /** * Sets a new basic channel group only. The function doesn't allow to change an * existing basic channel. * - * The function fails if any channel overlaps any existing basic channel group. + * The function fails if any channel overlaps any existing basic channel group. * To make room if necessary, basic channel groups can be cleared using * fluid_synth_reset_basic_channel(). - * + * * @param synth the synth instance. * @param chan the basic Channel number (0 to MIDI channel count-1). * @param mode the MIDI mode to use for chan (see #fluid_basic_channel_modes). * @param val number of channels in the group. - * @note \a val is only relevant for mode #FLUID_CHANNEL_MODE_OMNION_POLY, + * @note \a val is only relevant for mode #FLUID_CHANNEL_MODE_OMNION_POLY, * #FLUID_CHANNEL_MODE_OMNION_MONO and #FLUID_CHANNEL_MODE_OMNIOFF_MONO. A value * of 0 means all possible channels from \a chan to to next basic channel minus 1 (if any) * or to MIDI channel count minus 1. Val is ignored for #FLUID_CHANNEL_MODE_OMNIOFF_POLY - * as this mode implies a group of only one channel. - * @return + * as this mode implies a group of only one channel. + * @return * - #FLUID_OK on success. * - #FLUID_FAILED * - \a synth is NULL. @@ -5987,29 +6707,31 @@ fluid_synth_check_next_basic_channel(fluid_synth_t* synth, int basicchan, int mo * above MIDI channel count. * - When the function fails, any existing basic channels aren't modified. */ -int fluid_synth_set_basic_channel(fluid_synth_t* synth, int chan, int mode, int val) +int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val) { - /* check parameters */ - fluid_return_val_if_fail (mode >= 0, FLUID_FAILED); - fluid_return_val_if_fail (mode < FLUID_CHANNEL_MODE_LAST, FLUID_FAILED); - fluid_return_val_if_fail (val >= 0, FLUID_FAILED); + /* check parameters */ + fluid_return_val_if_fail(mode >= 0, FLUID_FAILED); + fluid_return_val_if_fail(mode < FLUID_CHANNEL_MODE_LAST, FLUID_FAILED); + fluid_return_val_if_fail(val >= 0, FLUID_FAILED); FLUID_API_ENTRY_CHAN(FLUID_FAILED); - /**/ - if (val > 0 && chan + val > synth->midi_channels) - { - FLUID_API_RETURN(FLUID_FAILED); - } - - /* Checks if there is an overlap with the next basic channel */ - val = fluid_synth_check_next_basic_channel(synth, chan, mode, val); - if( val == FLUID_FAILED || synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) - { - /* overlap with the next or previous channel group */ - FLUID_LOG(FLUID_INFO, "basic channel %d overlaps another group", chan); - FLUID_API_RETURN(FLUID_FAILED); - } - /* sets a new basic channel group */ + /**/ + if(val > 0 && chan + val > synth->midi_channels) + { + FLUID_API_RETURN(FLUID_FAILED); + } + + /* Checks if there is an overlap with the next basic channel */ + val = fluid_synth_check_next_basic_channel(synth, chan, mode, val); + + if(val == FLUID_FAILED || synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) + { + /* overlap with the next or previous channel group */ + FLUID_LOG(FLUID_INFO, "basic channel %d overlaps another group", chan); + FLUID_API_RETURN(FLUID_FAILED); + } + + /* sets a new basic channel group */ fluid_synth_set_basic_channel_LOCAL(synth, chan, mode, val); /**/ FLUID_API_RETURN(FLUID_OK); @@ -6024,52 +6746,56 @@ int fluid_synth_set_basic_channel(fluid_synth_t* synth, int chan, int mode, int * @param see fluid_synth_set_basic_channel() */ static void -fluid_synth_set_basic_channel_LOCAL(fluid_synth_t* synth, int basicchan, int mode, int val) +fluid_synth_set_basic_channel_LOCAL(fluid_synth_t *synth, int basicchan, int mode, int val) { - int i; + int i; - /* sets the basic channel group */ - for (i = basicchan; i < basicchan + val; i++) - { - int new_mode = mode; /* OMNI_OFF/ON, MONO/POLY ,others bits are zero */ - int new_val; - /* MIDI specs: when mode is changed, channel must receive ALL_NOTES_OFF */ - fluid_synth_all_notes_off_LOCAL (synth, i); + /* sets the basic channel group */ + for(i = basicchan; i < basicchan + val; i++) + { + int new_mode = mode; /* OMNI_OFF/ON, MONO/POLY ,others bits are zero */ + int new_val; + /* MIDI specs: when mode is changed, channel must receive ALL_NOTES_OFF */ + fluid_synth_all_notes_off_LOCAL(synth, i); - if (i == basicchan) - { - new_mode |= FLUID_CHANNEL_BASIC; /* First channel in the group */ - new_val = val; /* number of channels in the group */ - } - else - { - new_val =0; /* val is 0 for other channel than basic channel */ - } - /* Channel is enabled */ - new_mode |= FLUID_CHANNEL_ENABLED; - /* Now new_mode is OMNI OFF/ON,MONO/POLY, BASIC_CHANNEL or not and enabled */ - fluid_channel_set_basic_channel_info(synth->channel[i],new_mode); - synth->channel[i]->mode_val = new_val; - } + if(i == basicchan) + { + new_mode |= FLUID_CHANNEL_BASIC; /* First channel in the group */ + new_val = val; /* number of channels in the group */ + } + else + { + new_val = 0; /* val is 0 for other channel than basic channel */ + } + + /* Channel is enabled */ + new_mode |= FLUID_CHANNEL_ENABLED; + /* Now new_mode is OMNI OFF/ON,MONO/POLY, BASIC_CHANNEL or not and enabled */ + fluid_channel_set_basic_channel_info(synth->channel[i], new_mode); + synth->channel[i]->mode_val = new_val; + } } /** * Searchs a previous basic channel starting from chan. - * + * * @param synth the synth instance. * @param chan starting index of the search (including chan). * @return index of the basic channel if found , FLUID_FAILED otherwise. */ -static int fluid_synth_get_previous_basic_channel(fluid_synth_t* synth, int chan) +static int fluid_synth_get_previous_basic_channel(fluid_synth_t *synth, int chan) { - for (; chan >=0; chan--) - { /* searchs previous basic channel */ - if (synth->channel[chan]->mode & FLUID_CHANNEL_BASIC) - { /* chan is the previous basic channel */ - return chan; - } - } - return FLUID_FAILED; + for(; chan >= 0; chan--) + { + /* searchs previous basic channel */ + if(synth->channel[chan]->mode & FLUID_CHANNEL_BASIC) + { + /* chan is the previous basic channel */ + return chan; + } + } + + return FLUID_FAILED; } /** @@ -6082,48 +6808,48 @@ static int fluid_synth_get_previous_basic_channel(fluid_synth_t* synth, int chan * @param val_out Buffer to store the total number of channels in this basic channel group or #FLUID_FAILED if \a chan is disabled. * @note If any of \a basic_chan_out, \a mode_out, \a val_out pointer is NULL * the corresponding information isn't returned. - * + * * @return * - #FLUID_OK on success. - * - #FLUID_FAILED + * - #FLUID_FAILED * - \a synth is NULL. * - \a chan is outside MIDI channel count. */ -int fluid_synth_get_basic_channel(fluid_synth_t* synth, int chan, - int *basic_chan_out, - int *mode_out, - int *val_out ) +int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan, + int *basic_chan_out, + int *mode_out, + int *val_out) { int basic_chan = FLUID_FAILED; int mode = FLUID_FAILED; int val = FLUID_FAILED; - - /* checks parameters first */ - FLUID_API_ENTRY_CHAN(FLUID_FAILED); - - if ((synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) && - /* chan is enabled , we search the basic channel chan belongs to */ - (basic_chan = fluid_synth_get_previous_basic_channel(synth, chan)) != FLUID_FAILED) - { + + /* checks parameters first */ + FLUID_API_ENTRY_CHAN(FLUID_FAILED); + + if((synth->channel[chan]->mode & FLUID_CHANNEL_ENABLED) && + /* chan is enabled , we search the basic channel chan belongs to */ + (basic_chan = fluid_synth_get_previous_basic_channel(synth, chan)) != FLUID_FAILED) + { mode = synth->channel[chan]->mode & FLUID_CHANNEL_MODE_MASK; val = synth->channel[basic_chan]->mode_val; - } - - /* returns the informations if they are requested */ - if (basic_chan_out) - { - * basic_chan_out = basic_chan; - } - - if (mode_out) - { - * mode_out = mode; - } - - if (val_out) - { - * val_out = val; - } - - FLUID_API_RETURN(FLUID_OK); + } + + /* returns the informations if they are requested */ + if(basic_chan_out) + { + * basic_chan_out = basic_chan; + } + + if(mode_out) + { + * mode_out = mode; + } + + if(val_out) + { + * val_out = val; + } + + FLUID_API_RETURN(FLUID_OK); } diff --git a/src/synth/fluid_synth.h b/src/synth/fluid_synth.h index 30ebb4b1..ab3527e9 100644 --- a/src/synth/fluid_synth.h +++ b/src/synth/fluid_synth.h @@ -75,10 +75,10 @@ enum fluid_midi_bank_select enum fluid_synth_status { - FLUID_SYNTH_CLEAN, - FLUID_SYNTH_PLAYING, - FLUID_SYNTH_QUIET, - FLUID_SYNTH_STOPPED + FLUID_SYNTH_CLEAN, + FLUID_SYNTH_PLAYING, + FLUID_SYNTH_QUIET, + FLUID_SYNTH_STOPPED }; #define SYNTH_REVERB_CHANNEL 0 @@ -101,72 +101,72 @@ enum fluid_synth_status struct _fluid_synth_t { - fluid_rec_mutex_t mutex; /**< Lock for public API */ - int use_mutex; /**< Use mutex for all public API functions? */ - int public_api_count; /**< How many times the mutex is currently locked */ + fluid_rec_mutex_t mutex; /**< Lock for public API */ + int use_mutex; /**< Use mutex for all public API functions? */ + int public_api_count; /**< How many times the mutex is currently locked */ - fluid_settings_t* settings; /**< the synthesizer settings */ - int device_id; /**< Device ID used for SYSEX messages */ - int polyphony; /**< Maximum polyphony */ - int with_reverb; /**< Should the synth use the built-in reverb unit? */ - int with_chorus; /**< Should the synth use the built-in chorus unit? */ - int verbose; /**< Turn verbose mode on? */ - double sample_rate; /**< The sample rate */ - int midi_channels; /**< the number of MIDI channels (>= 16) */ - int bank_select; /**< the style of Bank Select MIDI messages */ - int audio_channels; /**< the number of audio channels (1 channel=left+right) */ - int audio_groups; /**< the number of (stereo) 'sub'groups from the synth. + fluid_settings_t *settings; /**< the synthesizer settings */ + int device_id; /**< Device ID used for SYSEX messages */ + int polyphony; /**< Maximum polyphony */ + int with_reverb; /**< Should the synth use the built-in reverb unit? */ + int with_chorus; /**< Should the synth use the built-in chorus unit? */ + int verbose; /**< Turn verbose mode on? */ + double sample_rate; /**< The sample rate */ + int midi_channels; /**< the number of MIDI channels (>= 16) */ + int bank_select; /**< the style of Bank Select MIDI messages */ + int audio_channels; /**< the number of audio channels (1 channel=left+right) */ + int audio_groups; /**< the number of (stereo) 'sub'groups from the synth. Typically equal to audio_channels. */ - int effects_channels; /**< the number of effects channels (>= 2) */ - int state; /**< the synthesizer state */ - fluid_atomic_uint_t ticks_since_start; /**< the number of audio samples since the start */ - unsigned int start; /**< the start in msec, as returned by system clock */ - fluid_overflow_prio_t overflow; /**< parameters for overflow priority (aka voice-stealing) */ + int effects_channels; /**< the number of effects channels (>= 2) */ + int state; /**< the synthesizer state */ + fluid_atomic_uint_t ticks_since_start; /**< the number of audio samples since the start */ + unsigned int start; /**< the start in msec, as returned by system clock */ + fluid_overflow_prio_t overflow; /**< parameters for overflow priority (aka voice-stealing) */ - fluid_list_t *loaders; /**< the SoundFont loaders */ - fluid_list_t *sfont; /**< List of fluid_sfont_info_t for each loaded SoundFont (remains until SoundFont is unloaded) */ - int sfont_id; /**< Incrementing ID assigned to each loaded SoundFont */ + fluid_list_t *loaders; /**< the SoundFont loaders */ + fluid_list_t *sfont; /**< List of fluid_sfont_info_t for each loaded SoundFont (remains until SoundFont is unloaded) */ + int sfont_id; /**< Incrementing ID assigned to each loaded SoundFont */ - float gain; /**< master gain */ - fluid_channel_t** channel; /**< the channels */ - int nvoice; /**< the length of the synthesis process array (max polyphony allowed) */ - fluid_voice_t** voice; /**< the synthesis voices */ - int active_voice_count; /**< count of active voices */ - unsigned int noteid; /**< the id is incremented for every new note. it's used for noteoff's */ - unsigned int storeid; - int fromkey_portamento; /**< fromkey portamento */ - fluid_rvoice_eventhandler_t* eventhandler; + float gain; /**< master gain */ + fluid_channel_t **channel; /**< the channels */ + int nvoice; /**< the length of the synthesis process array (max polyphony allowed) */ + fluid_voice_t **voice; /**< the synthesis voices */ + int active_voice_count; /**< count of active voices */ + unsigned int noteid; /**< the id is incremented for every new note. it's used for noteoff's */ + unsigned int storeid; + int fromkey_portamento; /**< fromkey portamento */ + fluid_rvoice_eventhandler_t *eventhandler; - double reverb_roomsize; /**< Shadow of reverb roomsize */ - double reverb_damping; /**< Shadow of reverb damping */ - double reverb_width; /**< Shadow of reverb width */ - double reverb_level; /**< Shadow of reverb level */ + double reverb_roomsize; /**< Shadow of reverb roomsize */ + double reverb_damping; /**< Shadow of reverb damping */ + double reverb_width; /**< Shadow of reverb width */ + double reverb_level; /**< Shadow of reverb level */ - int chorus_nr; /**< Shadow of chorus number */ - double chorus_level; /**< Shadow of chorus level */ - double chorus_speed; /**< Shadow of chorus speed */ - double chorus_depth; /**< Shadow of chorus depth */ - int chorus_type; /**< Shadow of chorus type */ + int chorus_nr; /**< Shadow of chorus number */ + double chorus_level; /**< Shadow of chorus level */ + double chorus_speed; /**< Shadow of chorus speed */ + double chorus_depth; /**< Shadow of chorus depth */ + int chorus_type; /**< Shadow of chorus type */ - int cur; /**< the current sample in the audio buffers to be output */ - int curmax; /**< current amount of samples present in the audio buffers */ - int dither_index; /**< current index in random dither value buffer: fluid_synth_(write_s16|dither_s16) */ + int cur; /**< the current sample in the audio buffers to be output */ + int curmax; /**< current amount of samples present in the audio buffers */ + int dither_index; /**< current index in random dither value buffer: fluid_synth_(write_s16|dither_s16) */ - fluid_atomic_float_t cpu_load; /**< CPU load in percent (CPU time required / audio synthesized time * 100) */ + fluid_atomic_float_t cpu_load; /**< CPU load in percent (CPU time required / audio synthesized time * 100) */ - fluid_tuning_t*** tuning; /**< 128 banks of 128 programs for the tunings */ - fluid_private_t tuning_iter; /**< Tuning iterators per each thread */ + fluid_tuning_t ***tuning; /**< 128 banks of 128 programs for the tunings */ + fluid_private_t tuning_iter; /**< Tuning iterators per each thread */ - fluid_sample_timer_t* sample_timers; /**< List of timers triggered before a block is processed */ - unsigned int min_note_length_ticks; /**< If note-offs are triggered just after a note-on, they will be delayed */ + fluid_sample_timer_t *sample_timers; /**< List of timers triggered before a block is processed */ + unsigned int min_note_length_ticks; /**< If note-offs are triggered just after a note-on, they will be delayed */ - int cores; /**< Number of CPU cores (1 by default) */ + int cores; /**< Number of CPU cores (1 by default) */ - fluid_mod_t* default_mod; /**< the (dynamic) list of default modulators */ + fluid_mod_t *default_mod; /**< the (dynamic) list of default modulators */ - fluid_ladspa_fx_t* ladspa_fx; /**< Effects unit for LADSPA support */ - enum fluid_iir_filter_type custom_filter_type; /**< filter type of the user-defined filter currently used for all voices */ - enum fluid_iir_filter_flags custom_filter_flags; /**< filter type of the user-defined filter currently used for all voices */ + fluid_ladspa_fx_t *ladspa_fx; /**< Effects unit for LADSPA support */ + enum fluid_iir_filter_type custom_filter_type; /**< filter type of the user-defined filter currently used for all voices */ + enum fluid_iir_filter_flags custom_filter_flags; /**< filter type of the user-defined filter currently used for all voices */ }; /** @@ -180,53 +180,53 @@ struct _fluid_synth_t * @param roff Offset index in 'out2' for first sample * @param rincr Increment between samples stored to 'out2' */ -typedef int (*fluid_audio_callback_t)(fluid_synth_t* synth, int len, - void* out1, int loff, int lincr, - void* out2, int roff, int rincr); +typedef int (*fluid_audio_callback_t)(fluid_synth_t *synth, int len, + void *out1, int loff, int lincr, + void *out2, int roff, int rincr); -fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, - int banknum, - int prognum); -void fluid_synth_sfont_unref (fluid_synth_t *synth, fluid_sfont_t *sfont); +fluid_preset_t *fluid_synth_find_preset(fluid_synth_t *synth, + int banknum, + int prognum); +void fluid_synth_sfont_unref(fluid_synth_t *synth, fluid_sfont_t *sfont); -void fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin, - void* lout, int loff, int lincr, - void* rout, int roff, int rincr); +void fluid_synth_dither_s16(int *dither_index, int len, float *lin, float *rin, + void *lout, int loff, int lincr, + void *rout, int roff, int rincr); -int fluid_synth_reset_reverb(fluid_synth_t* synth); -int fluid_synth_set_reverb_preset(fluid_synth_t* synth, unsigned int num); -int fluid_synth_set_reverb_full(fluid_synth_t* synth, int set, double roomsize, +int fluid_synth_reset_reverb(fluid_synth_t *synth); +int fluid_synth_set_reverb_preset(fluid_synth_t *synth, unsigned int num); +int fluid_synth_set_reverb_full(fluid_synth_t *synth, int set, double roomsize, double damping, double width, double level); -int fluid_synth_reset_chorus(fluid_synth_t* synth); -int fluid_synth_set_chorus_full(fluid_synth_t* synth, int set, int nr, double level, +int fluid_synth_reset_chorus(fluid_synth_t *synth); +int fluid_synth_set_chorus_full(fluid_synth_t *synth, int set, int nr, double level, double speed, double depth_ms, int type); -fluid_sample_timer_t* new_fluid_sample_timer(fluid_synth_t* synth, fluid_timer_callback_t callback, void* data); -void delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t* timer); +fluid_sample_timer_t *new_fluid_sample_timer(fluid_synth_t *synth, fluid_timer_callback_t callback, void *data); +void delete_fluid_sample_timer(fluid_synth_t *synth, fluid_sample_timer_t *timer); -void fluid_synth_process_event_queue(fluid_synth_t* synth); +void fluid_synth_process_event_queue(fluid_synth_t *synth); -int fluid_synth_set_gen2 (fluid_synth_t* synth, int chan, - int param, float value, - int absolute, int normalized); +int fluid_synth_set_gen2(fluid_synth_t *synth, int chan, + int param, float value, + int absolute, int normalized); /* * misc */ -void fluid_synth_settings(fluid_settings_t* settings); +void fluid_synth_settings(fluid_settings_t *settings); /* extern declared in fluid_synth_monopoly.c */ -int fluid_synth_noteon_mono_staccato(fluid_synth_t* synth,int chan,int key,int vel); -int fluid_synth_noteon_mono_LOCAL(fluid_synth_t* synth, int chan, int key, int vel); -int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key); -int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan, int fromkey, int tokey, int vel); -int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key, char Mono); +int fluid_synth_noteon_mono_staccato(fluid_synth_t *synth, int chan, int key, int vel); +int fluid_synth_noteon_mono_LOCAL(fluid_synth_t *synth, int chan, int key, int vel); +int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t *synth, int chan, int key); +int fluid_synth_noteon_monopoly_legato(fluid_synth_t *synth, int chan, int fromkey, int tokey, int vel); +int fluid_synth_noteoff_monopoly(fluid_synth_t *synth, int chan, int key, char Mono); -fluid_voice_t* -fluid_synth_alloc_voice_LOCAL(fluid_synth_t* synth, fluid_sample_t* sample, int chan, int key, int vel, fluid_zone_range_t* zone_range); +fluid_voice_t * +fluid_synth_alloc_voice_LOCAL(fluid_synth_t *synth, fluid_sample_t *sample, int chan, int key, int vel, fluid_zone_range_t *zone_range); -void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth, int chan, int key); +void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t *synth, int chan, int key); #endif /* _FLUID_SYNTH_H */ diff --git a/src/synth/fluid_synth_monopoly.c b/src/synth/fluid_synth_monopoly.c index 400187b6..b7828af5 100644 --- a/src/synth/fluid_synth_monopoly.c +++ b/src/synth/fluid_synth_monopoly.c @@ -23,7 +23,7 @@ #include "fluid_defsfont.h" -/****************************************************************************** +/****************************************************************************** The legato detector is composed as this, variables: - monolist: monophonic list variable. @@ -46,36 +46,36 @@ /|\ /|\ | | i_first i_last - + The list allows an easy automatic detection of a legato passage when it is played on a MIDI keyboard input device. It is useful also when the input device is an ewi (electronic wind instrument) or evi (electronic valve instrument) and these instruments are unable to send MIDI CC legato on/off. - - The list memorizes the notes in playing order. + + The list memorizes the notes in playing order. - (a) On noteOn n2, if a previous note n1 exists, there is a legato detection with n1 (with or without portamento from n1 to n2 See note below). - (b) On noteOff of the running note n2, if a previous note n1 exists, there is a legato detection from n2 to n1, allowing fast trills playing (with or without portamento from n2 to n1. See note below). - Notes in the list are inserted to the end of the list that works like a - circular buffer.The features are: - + Notes in the list are inserted to the end of the list that works like a + circular buffer.The features are: + 1) It is always possible to play an infinite legato passage in direct order (n1_On,n2_On,n3_On,....). - + 2) Playing legato in the reverse order (n10_Off, n9_Off,,...) helps in fast trills playing as the list memorizes 10 most recent notes. - - 3) Playing an infinite lagato passage in ascendant or descendant order, + + 3) Playing an infinite lagato passage in ascendant or descendant order, without playing trills is always possible using the usual way like this: First we begin with an ascendant passage, n1On, (n2On,n1Off), (n3On,n2Off) , (n4On,n3Off), then we continue with a descendant passage (n3On,n4off), (n2On,n3off), (n1On,n2off), n1Off...and so on - + Each MIDI channel have a legato detector. Note: @@ -85,7 +85,7 @@ situation it is usual to have a portamento from a note 'fromkey' to another note 'tokey'. Portamento fromkey note choice is determined at noteOn by fluid_synth_get_fromkey_portamento_legato() (see below). - + More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices). ******************************************************************************/ @@ -99,32 +99,32 @@ * - fromkey note for portamento. * - fromkey note for legato. * +-----> fromkey_portamento - * ______|________ - * portamento modes >------->| | - * | get_fromkey | - * Porta.on/off >------------------------->|_______________| - * (PTC) | + * ______|________ + * portamento modes >------->| | + * | get_fromkey | + * Porta.on/off >------------------------->|_______________| + * (PTC) | * +-----> fromkey_legato * * The functions is intended to be call on noteOn mono * see fluid_synth_noteon_mono_staccato(), fluid_synth_noteon_monopoly_legato() * ------- - * 1)The function determines if a portamento must occur on next noteOn. - * The value returned is 'fromkey portamento' which is the pitchstart key + * 1)The function determines if a portamento must occur on next noteOn. + * The value returned is 'fromkey portamento' which is the pitchstart key * of a portamento, as function of PTC or (default_fromkey, prev_note) both * if Portamento On. By order of precedence the result is: * 1.1) PTC have precedence over Portamento On. * If CC PTC has been received, its value supersedes and any * portamento pedal On, default_fromkey,prev_note or portamento mode. * 1.2) Otherwise ,when Portamento On the function takes the following value: - * - default_fromkey if valid + * - default_fromkey if valid * - otherwise prev_note(prev_note is the note prior the most recent * note played). * Then portamento mode is applied to validate the value choosen. - * Where portamento mode is: + * Where portamento mode is: * - each note, a portamento occurs on each note. - * - legato only, portamento only on notes played legato. - * - staccato only, portamento only on notes played staccato. + * - legato only, portamento only on notes played legato. + * - staccato only, portamento only on notes played staccato. * 1.3) Otherwise, portamento is off,INVALID_NOTE is returned (portamento is disabled). * ------ * 2)The function determines if a legato playing must occur on next noteOn. @@ -145,7 +145,7 @@ * @param chan fluid_channel_t. * @param defaultFromkey, the defaut 'fromkey portamento' note or 'fromkey legato' * note (see description above). - * + * * @return * 1)'fromkey portamento' is returned in fluid_synth_t.fromkey_portamento. * If valid,it means that portamento is enabled . @@ -158,73 +158,88 @@ * - On noteOff(mono legato playing). In this case, default_fromkey must be valid. * * Typical calling usage: - * - In poly, default_fromkey must be INVALID_NOTE. + * - In poly, default_fromkey must be INVALID_NOTE. * - In mono staccato playing,default_fromkey must be INVALID_NOTE. * - In mono legato playing,default_fromkey must be valid. */ -static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan, - int default_fromkey) +static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t *chan, + int default_fromkey) { - unsigned char ptc = fluid_channel_get_cc(chan, PORTAMENTO_CTRL); - if(fluid_channel_is_valid_note(ptc)) - { /* CC PTC has been received */ - fluid_channel_clear_portamento(chan); /* clears the CC PTC receive */ - chan->synth->fromkey_portamento = ptc;/* returns fromkey portamento */ - /* returns fromkey legato */ - if(!fluid_channel_is_valid_note(default_fromkey)) - { - default_fromkey= ptc; - } - } - else - { /* determines and returns fromkey portamento */ - unsigned char fromkey_portamento = INVALID_NOTE; - if(fluid_channel_portamento(chan)) - { /* Portamento when Portamento pedal is On */ - /* 'fromkey portamento'is determined from the portamento mode - and the most recent note played (prev_note)*/ - enum fluid_channel_portamento_mode portamentomode = chan->portamentomode; - if(fluid_channel_is_valid_note(default_fromkey)) - { - fromkey_portamento = default_fromkey; /* on each note */ - } - else - { - fromkey_portamento = fluid_channel_prev_note(chan); /* on each note */ - } - if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY) - { /* Mode portamento:legato only */ - if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)) - { - fromkey_portamento = INVALID_NOTE; - } - } - else if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY) - { /* Mode portamento:staccato only */ - if(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING) - { - fromkey_portamento = INVALID_NOTE; - } - } - /* else Mode portamento: on each note (staccato/legato) */ - } - /* Returns fromkey portamento */ - chan->synth->fromkey_portamento = fromkey_portamento; - /* Determines and returns fromkey legato */ - if(!fluid_channel_is_valid_note(default_fromkey)) - { - /* in staccato (poly/Mono) returns INVALID_NOTE */ - /* In mono mode legato playing returns the note prior most - recent note played */ - if (fluid_channel_is_playing_mono(chan) && (chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)) - { - default_fromkey = fluid_channel_prev_note(chan); /* note prior last note */ - } - /* In poly mode legato playing, actually we don't want playing legato. - So returns INVALID_NOTE */ - } - } - return default_fromkey; /* Returns legato fromkey */ + unsigned char ptc = fluid_channel_get_cc(chan, PORTAMENTO_CTRL); + + if(fluid_channel_is_valid_note(ptc)) + { + /* CC PTC has been received */ + fluid_channel_clear_portamento(chan); /* clears the CC PTC receive */ + chan->synth->fromkey_portamento = ptc;/* returns fromkey portamento */ + + /* returns fromkey legato */ + if(!fluid_channel_is_valid_note(default_fromkey)) + { + default_fromkey = ptc; + } + } + else + { + /* determines and returns fromkey portamento */ + unsigned char fromkey_portamento = INVALID_NOTE; + + if(fluid_channel_portamento(chan)) + { + /* Portamento when Portamento pedal is On */ + /* 'fromkey portamento'is determined from the portamento mode + and the most recent note played (prev_note)*/ + enum fluid_channel_portamento_mode portamentomode = chan->portamentomode; + + if(fluid_channel_is_valid_note(default_fromkey)) + { + fromkey_portamento = default_fromkey; /* on each note */ + } + else + { + fromkey_portamento = fluid_channel_prev_note(chan); /* on each note */ + } + + if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY) + { + /* Mode portamento:legato only */ + if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)) + { + fromkey_portamento = INVALID_NOTE; + } + } + else if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY) + { + /* Mode portamento:staccato only */ + if(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING) + { + fromkey_portamento = INVALID_NOTE; + } + } + + /* else Mode portamento: on each note (staccato/legato) */ + } + + /* Returns fromkey portamento */ + chan->synth->fromkey_portamento = fromkey_portamento; + + /* Determines and returns fromkey legato */ + if(!fluid_channel_is_valid_note(default_fromkey)) + { + /* in staccato (poly/Mono) returns INVALID_NOTE */ + /* In mono mode legato playing returns the note prior most + recent note played */ + if(fluid_channel_is_playing_mono(chan) && (chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)) + { + default_fromkey = fluid_channel_prev_note(chan); /* note prior last note */ + } + + /* In poly mode legato playing, actually we don't want playing legato. + So returns INVALID_NOTE */ + } + } + + return default_fromkey; /* Returns legato fromkey */ } /***************************************************************************** @@ -232,7 +247,7 @@ static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan, ******************************************************************************/ /* * noteon - noteoff on a channel in "monophonic playing". - * + * * A channel needs to be played monophonic if this channel has been set in * monophonic mode by basic channel API.(see fluid_synth_polymono.c). * A channel needs also to be played monophonic if it has been set in @@ -240,7 +255,7 @@ static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan, * When a channel is in "monophonic playing" state, only one note at a time can be * played in a staccato or legato manner (with or without portamento). * More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices). - * _______________ + * _______________ * ________________ | noteon | * | legato detector| O-->| mono_staccato |--*-> preset_noteon * noteon_mono ->| (add_monolist) |--O-- |_______________| | (with or without) @@ -248,11 +263,11 @@ static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan, * /|\ set_onenote | | fromkey | * | | | portamento| * noteOn poly >---*------------------* | | - * | | | + * | | | * | _____ |________ | * portamento modes >--- | ->| | | * | | get_fromkey | | - * Porta.on/off >--------------------- | ->|_______________| | + * Porta.on/off >--------------------- | ->|_______________| | * (PTC) | | | * | fromkey | fromkey | * | legato | portamento| @@ -263,47 +278,47 @@ static char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan, * legato modes >------- | ->|_______________| triggering * | (with or without) * | (portamento) - * | + * | * | * noteOff poly >---*----------------- | ---------+ * | clear | | * _\|/_____________ | | * | legato detector | O | * noteoff_mono->|(search_monolist)|-O-- _____\|/_______ - * LOCAL |(remove_monolist)| O-->| noteoff | + * LOCAL |(remove_monolist)| O-->| noteoff | * |_________________| | monopoly |----> noteoff * Sust.on/off >------------------------->|_______________| - * Sost.on/off + * Sost.on/off ------------------------------------------------------------------------------*/ -int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key, - char Mono); +int fluid_synth_noteoff_monopoly(fluid_synth_t *synth, int chan, int key, + char Mono); -int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan, - int fromkey, int tokey, int vel); +int fluid_synth_noteon_monopoly_legato(fluid_synth_t *synth, int chan, + int fromkey, int tokey, int vel); /** * Plays a noteon event for a Synth instance in "monophonic playing" state. * Please see the description above about "monophonic playing". - * _______________ + * _______________ * ________________ | noteon | * | legato detector| O-->| mono_staccato |--->preset_noteon - * noteon_mono ->| (add_monolist) |--O-- |_______________| - * LOCAL |________________| O - * | - * | - * | - * | - * | - * | - * | - * | - * | - * | _______________ + * noteon_mono ->| (add_monolist) |--O-- |_______________| + * LOCAL |________________| O + * | + * | + * | + * | + * | + * | + * | + * | + * | + * | _______________ * | | noteon | * +-->| monopoly | * | legato |---> voices * |_______________| triggering - * + * * The function uses the legato detector (see above) to determine if the note must * be played staccato or legato. * @@ -313,57 +328,62 @@ int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan, * @param vel MIDI velocity (0-127). * @return FLUID_OK on success, FLUID_FAILED otherwise. */ -int fluid_synth_noteon_mono_LOCAL(fluid_synth_t* synth, int chan, - int key, int vel) +int fluid_synth_noteon_mono_LOCAL(fluid_synth_t *synth, int chan, + int key, int vel) { - fluid_channel_t* channel = synth->channel[chan]; + fluid_channel_t *channel = synth->channel[chan]; - /* Adds the note into the monophonic list */ - fluid_channel_add_monolist(channel, key, vel, 0); + /* Adds the note into the monophonic list */ + fluid_channel_add_monolist(channel, key, vel, 0); - /* in Breath Sync mode, the noteon triggering is postponed - until the musician starts blowing in the breath controller */ - if (!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) || - fluid_channel_breath_msb(channel) ) - { - /* legato/staccato playing detection */ - if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING) - { /* legato playing */ - /* legato from prev_note to key */ - /* the voices from prev_note key number are to be used to play key number */ - /* fromkey must be valid */ - return fluid_synth_noteon_monopoly_legato(synth, chan, - fluid_channel_prev_note(channel), key, vel); - } - else - { /* staccato playing */ - return fluid_synth_noteon_mono_staccato(synth, chan, key, vel); - } - } - else return FLUID_OK; + /* in Breath Sync mode, the noteon triggering is postponed + until the musician starts blowing in the breath controller */ + if(!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) || + fluid_channel_breath_msb(channel)) + { + /* legato/staccato playing detection */ + if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING) + { + /* legato playing */ + /* legato from prev_note to key */ + /* the voices from prev_note key number are to be used to play key number */ + /* fromkey must be valid */ + return fluid_synth_noteon_monopoly_legato(synth, chan, + fluid_channel_prev_note(channel), key, vel); + } + else + { + /* staccato playing */ + return fluid_synth_noteon_mono_staccato(synth, chan, key, vel); + } + } + else + { + return FLUID_OK; + } } /** * Plays a noteoff event for a Synth instance in "monophonic playing" state. * Please see the description above about "monophonic playing" * - * _______________ + * _______________ * | noteon | * +-->| monopoly | * | | legato |----> voices * | |_______________| triggering * | (with or without) * | (portamento) - * | - * | * | * | - * | - * | - * _________________ | - * | legato detector | O + * | + * | + * | + * | + * _________________ | + * | legato detector | O * noteoff_mono->|(search_monolist)|-O-- _______________ - * LOCAL |(remove_monolist)| O-->| noteoff | + * LOCAL |(remove_monolist)| O-->| noteoff | * |_________________| | monopoly |----> noteoff * |_______________| * @@ -375,61 +395,67 @@ int fluid_synth_noteon_mono_LOCAL(fluid_synth_t* synth, int chan, * @param key MIDI note number (0-127). * @return FLUID_OK on success, FLUID_FAILED otherwise. */ -int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key) +int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t *synth, int chan, int key) { - int status; - int i,i_prev; - fluid_channel_t* channel = synth->channel[chan]; - /* searching the note in the monophonic list */ - i=fluid_channel_search_monolist(channel, key , &i_prev); + int status; + int i, i_prev; + fluid_channel_t *channel = synth->channel[chan]; + /* searching the note in the monophonic list */ + i = fluid_channel_search_monolist(channel, key, &i_prev); - if (i >= 0) - { /* the note is in the monophonic list */ - /* Removes the note from the monophonic list */ - fluid_channel_remove_monolist(channel,i , &i_prev); + if(i >= 0) + { + /* the note is in the monophonic list */ + /* Removes the note from the monophonic list */ + fluid_channel_remove_monolist(channel, i, &i_prev); - /* in Breath Sync mode, the noteoff triggering is done - if the musician is blowing in the breath controller */ - if (!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) || - fluid_channel_breath_msb(channel) ) - { - /* legato playing detection */ - if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING) - { /* the list contains others notes */ - if(i_prev >= 0) - { /* legato playing detection on noteoff */ - /* legato from key to i_prev key */ - /* the voices from key number are to be used to - play i_prev key number. */ - status = fluid_synth_noteon_monopoly_legato(synth, chan, - key, channel->monolist[i_prev].note, - channel->monolist[i_prev].vel); - } - /* else the note doesn't need to be played off */ - else - { - status = FLUID_OK; - } - } - else - { /* the monophonic list is empty */ - /* plays the monophonic note noteoff and eventually held - by sustain/sostenuto */ - status = fluid_synth_noteoff_monopoly(synth, chan, key, 1); - } - } - else - { - status = FLUID_OK; - } - } - else - { /* the note is not found in the list so the note was - played On when the channel was in polyphonic playing */ - /* plays the noteoff as for polyphonic */ - status = fluid_synth_noteoff_monopoly(synth, chan, key, 0); - } - return status; + /* in Breath Sync mode, the noteoff triggering is done + if the musician is blowing in the breath controller */ + if(!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) || + fluid_channel_breath_msb(channel)) + { + /* legato playing detection */ + if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING) + { + /* the list contains others notes */ + if(i_prev >= 0) + { + /* legato playing detection on noteoff */ + /* legato from key to i_prev key */ + /* the voices from key number are to be used to + play i_prev key number. */ + status = fluid_synth_noteon_monopoly_legato(synth, chan, + key, channel->monolist[i_prev].note, + channel->monolist[i_prev].vel); + } + /* else the note doesn't need to be played off */ + else + { + status = FLUID_OK; + } + } + else + { + /* the monophonic list is empty */ + /* plays the monophonic note noteoff and eventually held + by sustain/sostenuto */ + status = fluid_synth_noteoff_monopoly(synth, chan, key, 1); + } + } + else + { + status = FLUID_OK; + } + } + else + { + /* the note is not found in the list so the note was + played On when the channel was in polyphonic playing */ + /* plays the noteoff as for polyphonic */ + status = fluid_synth_noteoff_monopoly(synth, chan, key, 0); + } + + return status; } /*---------------------------------------------------------------------------- @@ -438,26 +464,26 @@ int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key) /** * Plays noteon for a monophonic note in staccato manner. * Please see the description above about "monophonic playing". - * _______________ + * _______________ * | noteon | * noteon_mono >------------------------>| mono_staccato |----> preset_noteon - * |_______________| (with or without) + * |_______________| (with or without) * LOCAL /|\ (portamento) - * | fromkey - * | portamento - * | - * | - * ______|________ - * portamento modes >----->| | - * | get_fromkey | - * Porta.on/off >----------------------->|_______________| - * Portamento - * (PTC) + * | fromkey + * | portamento + * | + * | + * ______|________ + * portamento modes >----->| | + * | get_fromkey | + * Porta.on/off >----------------------->|_______________| + * Portamento + * (PTC) * * We are in staccato situation (where no previous note have been depressed). * Before the note been passed to fluid_preset_noteon(), the function must determine * the from_key_portamento parameter used by fluid_preset_noteon(). - * + * * from_key_portamento is returned by fluid_synth_get_fromkey_portamento_legato() function. * fromkey_portamento is set to valid/invalid key value depending of the portamento * modes (see portamento mode API) , CC portamento On/Off , and CC portamento control @@ -470,38 +496,38 @@ int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key) * @return FLUID_OK on success, FLUID_FAILED otherwise. */ int -fluid_synth_noteon_mono_staccato(fluid_synth_t* synth,int chan,int key,int vel) +fluid_synth_noteon_mono_staccato(fluid_synth_t *synth, int chan, int key, int vel) { - fluid_channel_t* channel = synth->channel[chan]; - - /* Before playing a new note, if a previous monophonic note is currently - sustained it needs to be released */ - fluid_synth_release_voice_on_same_note_LOCAL(synth,chan, channel->key_mono_sustained); - /* Get possible 'fromkey portamento' */ - fluid_synth_get_fromkey_portamento_legato( channel, INVALID_NOTE); - /* The note needs to be played by voices allocation */ - return fluid_preset_noteon(channel->preset, synth, chan, key, vel); + fluid_channel_t *channel = synth->channel[chan]; + + /* Before playing a new note, if a previous monophonic note is currently + sustained it needs to be released */ + fluid_synth_release_voice_on_same_note_LOCAL(synth, chan, channel->key_mono_sustained); + /* Get possible 'fromkey portamento' */ + fluid_synth_get_fromkey_portamento_legato(channel, INVALID_NOTE); + /* The note needs to be played by voices allocation */ + return fluid_preset_noteon(channel->preset, synth, chan, key, vel); } /** * Plays noteoff for a polyphonic or monophonic note * Please see the description above about "monophonic playing". * - * + * * noteOff poly >---------------------------------+ * | * | * | * noteoff_mono _____\|/_______ - * LOCAL >------------------------->| noteoff | + * LOCAL >------------------------->| noteoff | * | monopoly |----> noteoff * Sust.on/off >------------------------->|_______________| - * Sost.on/off + * Sost.on/off * * The function has the same behaviour when the noteoff is poly of mono, except * that for mono noteoff, if any pedal (sustain or sostenuto ) is depressed, the * key is memorized. This is neccessary when the next mono note will be played - * staccato, as any current mono note currently sustained will need to be released + * staccato, as any current mono note currently sustained will need to be released * (see fluid_synth_noteon_mono_staccato()). * Note also that for a monophonic legato passage, the function is called only when * the last noteoff of the passage occurs. That means that if sustain or sostenuto @@ -517,56 +543,64 @@ fluid_synth_noteon_mono_staccato(fluid_synth_t* synth,int chan,int key,int vel) * Note: On return, on monophonic, possible sustained note is memorized in * key_mono_sustained. Memorization is done here on noteOff. */ -int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key, - char Mono) +int fluid_synth_noteoff_monopoly(fluid_synth_t *synth, int chan, int key, + char Mono) { - int status = FLUID_FAILED; - fluid_voice_t* voice; - int i; - fluid_channel_t* channel = synth->channel[chan]; - /* Key_sustained is prepared to return no note sustained (INVALID_NOTE) */ - if (Mono) - { - channel->key_mono_sustained = INVALID_NOTE; /* no mono note sustained */ - } - /* noteoff for all voices with same chan and same key */ - for (i = 0; i < synth->polyphony; i++) - { - voice = synth->voice[i]; - if (fluid_voice_is_on(voice) && - fluid_voice_get_channel(voice) == chan && - fluid_voice_get_key(voice) == key) - { - if (synth->verbose) - { - int used_voices = 0; - int k; - for (k = 0; k < synth->polyphony; k++) - { - if (!_AVAILABLE(synth->voice[k])) - { - used_voices++; - } - } - FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%d", - fluid_voice_get_channel(voice), fluid_voice_get_key(voice), 0, - fluid_voice_get_id(voice), - (fluid_curtime() - synth->start) / 1000.0f, - used_voices); - } /* if verbose */ - - fluid_voice_noteoff(voice); - /* noteoff on monophonic note */ - /* Key memorization if the note is sustained */ - if(Mono && - (fluid_voice_is_sustained(voice) || fluid_voice_is_sostenuto(voice))) - { - channel->key_mono_sustained = key; - } - status = FLUID_OK; - } /* if voice on */ - } /* for all voices */ - return status; + int status = FLUID_FAILED; + fluid_voice_t *voice; + int i; + fluid_channel_t *channel = synth->channel[chan]; + + /* Key_sustained is prepared to return no note sustained (INVALID_NOTE) */ + if(Mono) + { + channel->key_mono_sustained = INVALID_NOTE; /* no mono note sustained */ + } + + /* noteoff for all voices with same chan and same key */ + for(i = 0; i < synth->polyphony; i++) + { + voice = synth->voice[i]; + + if(fluid_voice_is_on(voice) && + fluid_voice_get_channel(voice) == chan && + fluid_voice_get_key(voice) == key) + { + if(synth->verbose) + { + int used_voices = 0; + int k; + + for(k = 0; k < synth->polyphony; k++) + { + if(!_AVAILABLE(synth->voice[k])) + { + used_voices++; + } + } + + FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%d", + fluid_voice_get_channel(voice), fluid_voice_get_key(voice), 0, + fluid_voice_get_id(voice), + (fluid_curtime() - synth->start) / 1000.0f, + used_voices); + } /* if verbose */ + + fluid_voice_noteoff(voice); + + /* noteoff on monophonic note */ + /* Key memorization if the note is sustained */ + if(Mono && + (fluid_voice_is_sustained(voice) || fluid_voice_is_sostenuto(voice))) + { + channel->key_mono_sustained = key; + } + + status = FLUID_OK; + } /* if voice on */ + } /* for all voices */ + + return status; } /*---------------------------------------------------------------------------- @@ -576,29 +610,29 @@ int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key, * Plays noteon for a monophonic note played legato. * Please see the description above about "monophonic playing". * - * - * _______________ - * portamento modes >----->| | + * + * _______________ + * portamento modes >----->| | * | get_fromkey | - * Porta.on/off >----------------------->|_______________| - * Portamento | + * Porta.on/off >----------------------->|_______________| + * Portamento | * (PTC) | +-->preset_noteon * fromkey | fromkey | (with or without) - * legato | portamento| (portamento) + * legato | portamento| (portamento) * _____\|/_______ | - * | noteon |--+ + * | noteon |--+ * noteon_mono >------------------------>| monopoly | * LOCAL | legato |----->voices * |_______________| triggering * /|\ (with or without) * | (portamento) - * legato modes >-----------------+ + * legato modes >-----------------+ * * We are in legato situation (where a previous note has been depressed). * The function must determine the from_key_portamento and from_key_legato parameters * used respectively by fluid_preset_noteon() function and voices triggering functions. * - * from_key_portamento and from_key_legato are returned by + * from_key_portamento and from_key_legato are returned by * fluid_synth_get_fromkey_portamento_legato() function. * fromkey_portamento is set to valid/invalid key value depending of the portamento * modes (see portamento mode API), CC portamento On/Off, and CC portamento control @@ -615,71 +649,79 @@ int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key, * Note: The voices with key 'fromkey' are to be used to play key 'tokey'. * The function is able to play legato through Preset Zone(s) (PZ) and * Instrument Zone(s) (IZ) as far as possible. - * When key tokey is outside the current Instrument Zone, Preset Zone, + * When key tokey is outside the current Instrument Zone, Preset Zone, * current 'fromkey' voices are released. If necessary new voices * are restarted when tokey enters inside new Instrument(s) Zones,Preset Zone(s). * More informations in FluidPolyMono-0004.pdf chapter 4.7 (Appendices). */ -int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan, - int fromkey, int tokey, int vel) +int fluid_synth_noteon_monopoly_legato(fluid_synth_t *synth, int chan, + int fromkey, int tokey, int vel) { - fluid_channel_t* channel = synth->channel[chan]; - enum fluid_channel_legato_mode legatomode = channel->legatomode; - fluid_voice_t* voice; - int i ; - /* Gets possible 'fromkey portamento' and possible 'fromkey legato' note */ - fromkey = fluid_synth_get_fromkey_portamento_legato( channel, fromkey); + fluid_channel_t *channel = synth->channel[chan]; + enum fluid_channel_legato_mode legatomode = channel->legatomode; + fluid_voice_t *voice; + int i ; + /* Gets possible 'fromkey portamento' and possible 'fromkey legato' note */ + fromkey = fluid_synth_get_fromkey_portamento_legato(channel, fromkey); - if (fluid_channel_is_valid_note(fromkey)) for (i = 0; i < synth->polyphony; i++) - { - /* searching fromkey voices: only those who don't have 'note off' */ - voice = synth->voice[i]; - if (fluid_voice_is_on(voice) && + if(fluid_channel_is_valid_note(fromkey)) + { + for(i = 0; i < synth->polyphony; i++) + { + /* searching fromkey voices: only those who don't have 'note off' */ + voice = synth->voice[i]; + + if(fluid_voice_is_on(voice) && fluid_voice_get_channel(voice) == chan && fluid_voice_get_key(voice) == fromkey) - { - fluid_zone_range_t * zone_range = voice->zone_range; - /* Ignores voice when there is no instrument zone (i.e no zone_range). Otherwise - checks if tokey is inside the range of the running voice */ - if (zone_range && fluid_zone_inside_range(zone_range, tokey, vel)) - { - switch (legatomode) - { - case FLUID_CHANNEL_LEGATO_MODE_RETRIGGER: /* mode 0 */ - fluid_voice_release(voice); /* normal release */ - break; + { + fluid_zone_range_t *zone_range = voice->zone_range; - case FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER: /* mode 1 */ - /* Skip in attack section */ - fluid_voice_update_multi_retrigger_attack(voice,tokey,vel); - - /* Starts portamento if enabled */ - if(fluid_channel_is_valid_note(synth->fromkey_portamento)) - { - /* Sends portamento parameters to the voice dsp */ - fluid_voice_update_portamento(voice, - synth->fromkey_portamento, - tokey); - } - /* The voice is now used to play tokey in legato manner */ - /* Marks this Instrument Zone to be ignored during next - fluid_preset_noteon() */ - zone_range->ignore = TRUE; - break; + /* Ignores voice when there is no instrument zone (i.e no zone_range). Otherwise + checks if tokey is inside the range of the running voice */ + if(zone_range && fluid_zone_inside_range(zone_range, tokey, vel)) + { + switch(legatomode) + { + case FLUID_CHANNEL_LEGATO_MODE_RETRIGGER: /* mode 0 */ + fluid_voice_release(voice); /* normal release */ + break; - default: /* Invalid mode: this should never happen */ - FLUID_LOG(FLUID_WARN, "Failed to execute legato mode: %d", - legatomode); - return FLUID_FAILED; - } - } - else - { /* tokey note is outside the voice range, so the voice is released */ - fluid_voice_release(voice); - } - } - } - /* May be,tokey will enter in new others Insrument Zone(s),Preset Zone(s), in - this case it needs to be played by voices allocation */ - return fluid_preset_noteon(channel->preset,synth,chan,tokey,vel); + case FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER: /* mode 1 */ + /* Skip in attack section */ + fluid_voice_update_multi_retrigger_attack(voice, tokey, vel); + + /* Starts portamento if enabled */ + if(fluid_channel_is_valid_note(synth->fromkey_portamento)) + { + /* Sends portamento parameters to the voice dsp */ + fluid_voice_update_portamento(voice, + synth->fromkey_portamento, + tokey); + } + + /* The voice is now used to play tokey in legato manner */ + /* Marks this Instrument Zone to be ignored during next + fluid_preset_noteon() */ + zone_range->ignore = TRUE; + break; + + default: /* Invalid mode: this should never happen */ + FLUID_LOG(FLUID_WARN, "Failed to execute legato mode: %d", + legatomode); + return FLUID_FAILED; + } + } + else + { + /* tokey note is outside the voice range, so the voice is released */ + fluid_voice_release(voice); + } + } + } + } + + /* May be,tokey will enter in new others Insrument Zone(s),Preset Zone(s), in + this case it needs to be played by voices allocation */ + return fluid_preset_noteon(channel->preset, synth, chan, tokey, vel); } diff --git a/src/synth/fluid_tuning.c b/src/synth/fluid_tuning.c index 54bfc7a9..ee083116 100644 --- a/src/synth/fluid_tuning.c +++ b/src/synth/fluid_tuning.c @@ -24,146 +24,168 @@ #include "fluid_sys.h" -fluid_tuning_t* new_fluid_tuning(const char* name, int bank, int prog) +fluid_tuning_t *new_fluid_tuning(const char *name, int bank, int prog) { - fluid_tuning_t* tuning; - int i; + fluid_tuning_t *tuning; + int i; - tuning = FLUID_NEW(fluid_tuning_t); - if (tuning == NULL) { - FLUID_LOG(FLUID_PANIC, "Out of memory"); - return NULL; - } - FLUID_MEMSET(tuning, 0, sizeof(fluid_tuning_t)); + tuning = FLUID_NEW(fluid_tuning_t); - if (fluid_tuning_set_name(tuning, name) != FLUID_OK) { - delete_fluid_tuning(tuning); - return NULL; - } + if(tuning == NULL) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return NULL; + } - tuning->bank = bank; - tuning->prog = prog; + FLUID_MEMSET(tuning, 0, sizeof(fluid_tuning_t)); - for (i = 0; i < 128; i++) { - tuning->pitch[i] = i * 100.0; - } + if(fluid_tuning_set_name(tuning, name) != FLUID_OK) + { + delete_fluid_tuning(tuning); + return NULL; + } - fluid_atomic_int_set(&tuning->refcount, 1); /* Start with a refcount of 1 */ + tuning->bank = bank; + tuning->prog = prog; - return tuning; + for(i = 0; i < 128; i++) + { + tuning->pitch[i] = i * 100.0; + } + + fluid_atomic_int_set(&tuning->refcount, 1); /* Start with a refcount of 1 */ + + return tuning; } /* Duplicate a tuning */ fluid_tuning_t * -fluid_tuning_duplicate (fluid_tuning_t *tuning) +fluid_tuning_duplicate(fluid_tuning_t *tuning) { - fluid_tuning_t *new_tuning; - int i; + fluid_tuning_t *new_tuning; + int i; - new_tuning = FLUID_NEW (fluid_tuning_t); + new_tuning = FLUID_NEW(fluid_tuning_t); - if (!new_tuning) { - FLUID_LOG (FLUID_PANIC, "Out of memory"); - return NULL; - } - FLUID_MEMSET(new_tuning, 0, sizeof(fluid_tuning_t)); + if(!new_tuning) + { + FLUID_LOG(FLUID_PANIC, "Out of memory"); + return NULL; + } - if (fluid_tuning_set_name(new_tuning, tuning->name) != FLUID_OK) { - delete_fluid_tuning(new_tuning); - return NULL; - } + FLUID_MEMSET(new_tuning, 0, sizeof(fluid_tuning_t)); - new_tuning->bank = tuning->bank; - new_tuning->prog = tuning->prog; + if(fluid_tuning_set_name(new_tuning, tuning->name) != FLUID_OK) + { + delete_fluid_tuning(new_tuning); + return NULL; + } - for (i = 0; i < 128; i++) - new_tuning->pitch[i] = tuning->pitch[i]; + new_tuning->bank = tuning->bank; + new_tuning->prog = tuning->prog; - fluid_atomic_int_set(&new_tuning->refcount, 1); /* Start with a refcount of 1 */ + for(i = 0; i < 128; i++) + { + new_tuning->pitch[i] = tuning->pitch[i]; + } - return new_tuning; + fluid_atomic_int_set(&new_tuning->refcount, 1); /* Start with a refcount of 1 */ + + return new_tuning; } void -delete_fluid_tuning (fluid_tuning_t *tuning) +delete_fluid_tuning(fluid_tuning_t *tuning) { fluid_return_if_fail(tuning != NULL); - - FLUID_FREE (tuning->name); - FLUID_FREE (tuning); + + FLUID_FREE(tuning->name); + FLUID_FREE(tuning); } /* Add a reference to a tuning object */ void -fluid_tuning_ref (fluid_tuning_t *tuning) +fluid_tuning_ref(fluid_tuning_t *tuning) { - fluid_return_if_fail (tuning != NULL); + fluid_return_if_fail(tuning != NULL); - fluid_atomic_int_inc (&tuning->refcount); + fluid_atomic_int_inc(&tuning->refcount); } /* Unref a tuning object, when it reaches 0 it is deleted, returns TRUE if deleted */ int -fluid_tuning_unref (fluid_tuning_t *tuning, int count) +fluid_tuning_unref(fluid_tuning_t *tuning, int count) { - fluid_return_val_if_fail (tuning != NULL, FALSE); + fluid_return_val_if_fail(tuning != NULL, FALSE); - /* Add and compare are separate, but that is OK, since refcount will only - * reach 0 when there are no references and therefore no possibility of - * another thread adding a reference in between */ - fluid_atomic_int_add (&tuning->refcount, -count); + /* Add and compare are separate, but that is OK, since refcount will only + * reach 0 when there are no references and therefore no possibility of + * another thread adding a reference in between */ + fluid_atomic_int_add(&tuning->refcount, -count); - /* Delete when refcount reaches 0 */ - if (!fluid_atomic_int_get (&tuning->refcount)) - { - delete_fluid_tuning (tuning); - return TRUE; - } - else return FALSE; -} - -int fluid_tuning_set_name(fluid_tuning_t* tuning, const char* name) -{ - if (tuning->name != NULL) { - FLUID_FREE(tuning->name); - tuning->name = NULL; - } - if (name != NULL) { - tuning->name = FLUID_STRDUP(name); - if (tuning->name == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; + /* Delete when refcount reaches 0 */ + if(!fluid_atomic_int_get(&tuning->refcount)) + { + delete_fluid_tuning(tuning); + return TRUE; + } + else + { + return FALSE; } - } - return FLUID_OK; } -char* fluid_tuning_get_name(fluid_tuning_t* tuning) +int fluid_tuning_set_name(fluid_tuning_t *tuning, const char *name) { - return tuning->name; + if(tuning->name != NULL) + { + FLUID_FREE(tuning->name); + tuning->name = NULL; + } + + if(name != NULL) + { + tuning->name = FLUID_STRDUP(name); + + if(tuning->name == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } + } + + return FLUID_OK; } -void fluid_tuning_set_octave(fluid_tuning_t* tuning, const double* pitch_deriv) +char *fluid_tuning_get_name(fluid_tuning_t *tuning) { - int i; - - for (i = 0; i < 128; i++) { - tuning->pitch[i] = i * 100.0 + pitch_deriv[i % 12]; - } + return tuning->name; } -void fluid_tuning_set_all(fluid_tuning_t* tuning, const double* pitch) +void fluid_tuning_set_octave(fluid_tuning_t *tuning, const double *pitch_deriv) { - int i; + int i; - for (i = 0; i < 128; i++) { - tuning->pitch[i] = pitch[i]; - } + for(i = 0; i < 128; i++) + { + tuning->pitch[i] = i * 100.0 + pitch_deriv[i % 12]; + } } -void fluid_tuning_set_pitch(fluid_tuning_t* tuning, int key, double pitch) +void fluid_tuning_set_all(fluid_tuning_t *tuning, const double *pitch) { - if ((key >= 0) && (key < 128)) { - tuning->pitch[key] = pitch; - } + int i; + + for(i = 0; i < 128; i++) + { + tuning->pitch[i] = pitch[i]; + } +} + +void fluid_tuning_set_pitch(fluid_tuning_t *tuning, int key, double pitch) +{ + if((key >= 0) && (key < 128)) + { + tuning->pitch[key] = pitch; + } } diff --git a/src/synth/fluid_tuning.h b/src/synth/fluid_tuning.h index 5558dc6e..3afe2c65 100644 --- a/src/synth/fluid_tuning.h +++ b/src/synth/fluid_tuning.h @@ -34,32 +34,33 @@ #include "fluidsynth_priv.h" -struct _fluid_tuning_t { - char* name; - int bank; - int prog; - double pitch[128]; /* the pitch of every key, in cents */ - fluid_atomic_int_t refcount; /* Tuning reference count */ +struct _fluid_tuning_t +{ + char *name; + int bank; + int prog; + double pitch[128]; /* the pitch of every key, in cents */ + fluid_atomic_int_t refcount; /* Tuning reference count */ }; -fluid_tuning_t* new_fluid_tuning(const char* name, int bank, int prog); -void delete_fluid_tuning (fluid_tuning_t *tuning); -fluid_tuning_t *fluid_tuning_duplicate (fluid_tuning_t *tuning); -void fluid_tuning_ref (fluid_tuning_t *tuning); -int fluid_tuning_unref (fluid_tuning_t *tuning, int count); +fluid_tuning_t *new_fluid_tuning(const char *name, int bank, int prog); +void delete_fluid_tuning(fluid_tuning_t *tuning); +fluid_tuning_t *fluid_tuning_duplicate(fluid_tuning_t *tuning); +void fluid_tuning_ref(fluid_tuning_t *tuning); +int fluid_tuning_unref(fluid_tuning_t *tuning, int count); -int fluid_tuning_set_name(fluid_tuning_t* tuning, const char* name); -char* fluid_tuning_get_name(fluid_tuning_t* tuning); +int fluid_tuning_set_name(fluid_tuning_t *tuning, const char *name); +char *fluid_tuning_get_name(fluid_tuning_t *tuning); #define fluid_tuning_get_bank(_t) ((_t)->bank) #define fluid_tuning_get_prog(_t) ((_t)->prog) -void fluid_tuning_set_pitch(fluid_tuning_t* tuning, int key, double pitch); +void fluid_tuning_set_pitch(fluid_tuning_t *tuning, int key, double pitch); #define fluid_tuning_get_pitch(_t, _key) ((_t)->pitch[_key]) -void fluid_tuning_set_octave(fluid_tuning_t* tuning, const double* pitch_deriv); +void fluid_tuning_set_octave(fluid_tuning_t *tuning, const double *pitch_deriv); -void fluid_tuning_set_all(fluid_tuning_t* tuning, const double* pitch); +void fluid_tuning_set_all(fluid_tuning_t *tuning, const double *pitch); #define fluid_tuning_get_all(_t) (&(_t)->pitch[0]) diff --git a/src/synth/fluid_voice.c b/src/synth/fluid_voice.c index c073391b..8cd2e1e4 100644 --- a/src/synth/fluid_voice.c +++ b/src/synth/fluid_voice.c @@ -38,13 +38,13 @@ #define FLUID_MIN_VOLENVRELEASE -7200.0f /* ~16ms */ -static const int32_t INT24_MAX = (1 << (16+8-1)); +static const int32_t INT24_MAX = (1 << (16 + 8 - 1)); -static int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice); -static int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, +static int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t *voice); +static int calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base, int gen_key2base, int is_decay); static fluid_real_t -fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice); +fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice); #define UPDATE_RVOICE0(proc) \ do { \ @@ -65,7 +65,7 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice); param[0].i = iarg; \ fluid_rvoice_eventhandler_push(voice->eventhandler, proc, obj, param); \ } while (0) - + #define UPDATE_RVOICE_GENERIC_I2(proc, obj, iarg1, iarg2) \ do { \ fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; \ @@ -87,11 +87,11 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice); #define UPDATE_RVOICE_I1(proc, arg1) UPDATE_RVOICE_GENERIC_I1(proc, voice->rvoice, arg1) #define UPDATE_RVOICE_BUFFERS_AMP(proc, iarg, rarg) UPDATE_RVOICE_GENERIC_IR(proc, &voice->rvoice->buffers, iarg, rarg) -#define UPDATE_RVOICE_ENVLFO_R1(proc, envp, rarg) UPDATE_RVOICE_GENERIC_R1(proc, &voice->rvoice->envlfo.envp, rarg) -#define UPDATE_RVOICE_ENVLFO_I1(proc, envp, iarg) UPDATE_RVOICE_GENERIC_I1(proc, &voice->rvoice->envlfo.envp, iarg) +#define UPDATE_RVOICE_ENVLFO_R1(proc, envp, rarg) UPDATE_RVOICE_GENERIC_R1(proc, &voice->rvoice->envlfo.envp, rarg) +#define UPDATE_RVOICE_ENVLFO_I1(proc, envp, iarg) UPDATE_RVOICE_GENERIC_I1(proc, &voice->rvoice->envlfo.envp, iarg) static FLUID_INLINE void -fluid_voice_update_volenv(fluid_voice_t* voice, +fluid_voice_update_volenv(fluid_voice_t *voice, int enqueue, fluid_adsr_env_section_t section, unsigned int count, @@ -101,20 +101,20 @@ fluid_voice_update_volenv(fluid_voice_t* voice, fluid_real_t max) { fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - + param[0].i = section; param[1].i = count; param[2].real = coeff; param[3].real = increment; param[4].real = min; param[5].real = max; - + if(enqueue) { - fluid_rvoice_eventhandler_push(voice->eventhandler, - fluid_adsr_env_set_data, - &voice->rvoice->envlfo.volenv, - param); + fluid_rvoice_eventhandler_push(voice->eventhandler, + fluid_adsr_env_set_data, + &voice->rvoice->envlfo.volenv, + param); } else { @@ -123,7 +123,7 @@ fluid_voice_update_volenv(fluid_voice_t* voice, } static FLUID_INLINE void -fluid_voice_update_modenv(fluid_voice_t* voice, +fluid_voice_update_modenv(fluid_voice_t *voice, int enqueue, fluid_adsr_env_section_t section, unsigned int count, @@ -133,233 +133,252 @@ fluid_voice_update_modenv(fluid_voice_t* voice, fluid_real_t max) { fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - + param[0].i = section; param[1].i = count; param[2].real = coeff; param[3].real = increment; param[4].real = min; param[5].real = max; - + if(enqueue) { - fluid_rvoice_eventhandler_push(voice->eventhandler, - fluid_adsr_env_set_data, - &voice->rvoice->envlfo.modenv, - param); + fluid_rvoice_eventhandler_push(voice->eventhandler, + fluid_adsr_env_set_data, + &voice->rvoice->envlfo.modenv, + param); } else { - fluid_adsr_env_set_data(&voice->rvoice->envlfo.modenv, param); + fluid_adsr_env_set_data(&voice->rvoice->envlfo.modenv, param); } } -static FLUID_INLINE void fluid_voice_sample_unref(fluid_sample_t** sample) +static FLUID_INLINE void fluid_voice_sample_unref(fluid_sample_t **sample) { - if (*sample != NULL) { - fluid_sample_decr_ref(*sample); - *sample = NULL; - } + if(*sample != NULL) + { + fluid_sample_decr_ref(*sample); + *sample = NULL; + } } /* * Swaps the current rvoice with the current overflow_rvoice */ -static void fluid_voice_swap_rvoice(fluid_voice_t* voice) +static void fluid_voice_swap_rvoice(fluid_voice_t *voice) { - fluid_rvoice_t* rtemp = voice->rvoice; - int ctemp = voice->can_access_rvoice; - voice->rvoice = voice->overflow_rvoice; - voice->can_access_rvoice = voice->can_access_overflow_rvoice; - voice->overflow_rvoice = rtemp; - voice->can_access_overflow_rvoice = ctemp; + fluid_rvoice_t *rtemp = voice->rvoice; + int ctemp = voice->can_access_rvoice; + voice->rvoice = voice->overflow_rvoice; + voice->can_access_rvoice = voice->can_access_overflow_rvoice; + voice->overflow_rvoice = rtemp; + voice->can_access_overflow_rvoice = ctemp; } -static void fluid_voice_initialize_rvoice(fluid_voice_t* voice, fluid_real_t output_rate) +static void fluid_voice_initialize_rvoice(fluid_voice_t *voice, fluid_real_t output_rate) { - fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - - FLUID_MEMSET(voice->rvoice, 0, sizeof(fluid_rvoice_t)); + fluid_rvoice_param_t param[MAX_EVENT_PARAMS]; - /* The 'sustain' and 'finished' segments of the volume / modulation - * envelope are constant. They are never affected by any modulator - * or generator. Therefore it is enough to initialize them once - * during the lifetime of the synth. - */ - fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN, - 0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f); - fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVFINISHED, - 0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f); - fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN, - 0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f); - fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVFINISHED, - 0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f); - - param[0].i = FLUID_IIR_LOWPASS; - param[1].i = 0; - fluid_iir_filter_init(&voice->rvoice->resonant_filter, param); - - param[0].i = FLUID_IIR_DISABLED; - fluid_iir_filter_init(&voice->rvoice->resonant_custom_filter, param); - - param[0].real = output_rate; - fluid_rvoice_set_output_rate(voice->rvoice, param); + FLUID_MEMSET(voice->rvoice, 0, sizeof(fluid_rvoice_t)); + + /* The 'sustain' and 'finished' segments of the volume / modulation + * envelope are constant. They are never affected by any modulator + * or generator. Therefore it is enough to initialize them once + * during the lifetime of the synth. + */ + fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN, + 0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f); + fluid_voice_update_volenv(voice, FALSE, FLUID_VOICE_ENVFINISHED, + 0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f); + fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVSUSTAIN, + 0xffffffff, 1.0f, 0.0f, -1.0f, 2.0f); + fluid_voice_update_modenv(voice, FALSE, FLUID_VOICE_ENVFINISHED, + 0xffffffff, 0.0f, 0.0f, -1.0f, 1.0f); + + param[0].i = FLUID_IIR_LOWPASS; + param[1].i = 0; + fluid_iir_filter_init(&voice->rvoice->resonant_filter, param); + + param[0].i = FLUID_IIR_DISABLED; + fluid_iir_filter_init(&voice->rvoice->resonant_custom_filter, param); + + param[0].real = output_rate; + fluid_rvoice_set_output_rate(voice->rvoice, param); } /* * new_fluid_voice */ -fluid_voice_t* -new_fluid_voice(fluid_rvoice_eventhandler_t* handler, fluid_real_t output_rate) +fluid_voice_t * +new_fluid_voice(fluid_rvoice_eventhandler_t *handler, fluid_real_t output_rate) { - fluid_voice_t* voice; - voice = FLUID_NEW(fluid_voice_t); - if (voice == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - - voice->can_access_rvoice = TRUE; - voice->can_access_overflow_rvoice = TRUE; - - voice->rvoice = FLUID_NEW(fluid_rvoice_t); - voice->overflow_rvoice = FLUID_NEW(fluid_rvoice_t); - if (voice->rvoice == NULL || voice->overflow_rvoice == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - delete_fluid_voice(voice); - return NULL; - } + fluid_voice_t *voice; + voice = FLUID_NEW(fluid_voice_t); - voice->status = FLUID_VOICE_CLEAN; - voice->chan = NO_CHANNEL; - voice->key = 0; - voice->vel = 0; - voice->eventhandler = handler; - voice->channel = NULL; - voice->sample = NULL; - voice->output_rate = output_rate; + if(voice == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - /* Initialize both the rvoice and overflow_rvoice */ - fluid_voice_initialize_rvoice(voice, output_rate); - fluid_voice_swap_rvoice(voice); - fluid_voice_initialize_rvoice(voice, output_rate); + voice->can_access_rvoice = TRUE; + voice->can_access_overflow_rvoice = TRUE; - return voice; + voice->rvoice = FLUID_NEW(fluid_rvoice_t); + voice->overflow_rvoice = FLUID_NEW(fluid_rvoice_t); + + if(voice->rvoice == NULL || voice->overflow_rvoice == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + delete_fluid_voice(voice); + return NULL; + } + + voice->status = FLUID_VOICE_CLEAN; + voice->chan = NO_CHANNEL; + voice->key = 0; + voice->vel = 0; + voice->eventhandler = handler; + voice->channel = NULL; + voice->sample = NULL; + voice->output_rate = output_rate; + + /* Initialize both the rvoice and overflow_rvoice */ + fluid_voice_initialize_rvoice(voice, output_rate); + fluid_voice_swap_rvoice(voice); + fluid_voice_initialize_rvoice(voice, output_rate); + + return voice; } /* * delete_fluid_voice */ void -delete_fluid_voice(fluid_voice_t* voice) +delete_fluid_voice(fluid_voice_t *voice) { - fluid_return_if_fail(voice != NULL); - - if (!voice->can_access_rvoice || !voice->can_access_overflow_rvoice) { - FLUID_LOG(FLUID_WARN, "Deleting voice %u which has locked rvoices!", voice->id); - } - FLUID_FREE(voice->overflow_rvoice); - FLUID_FREE(voice->rvoice); - FLUID_FREE(voice); + fluid_return_if_fail(voice != NULL); + + if(!voice->can_access_rvoice || !voice->can_access_overflow_rvoice) + { + FLUID_LOG(FLUID_WARN, "Deleting voice %u which has locked rvoices!", voice->id); + } + + FLUID_FREE(voice->overflow_rvoice); + FLUID_FREE(voice->rvoice); + FLUID_FREE(voice); } /* fluid_voice_init * * Initialize the synthesis process * inst_zone, the Instrument Zone contains the sample, Keyrange,Velrange - * of the voice. - * When playing legato (n1,n2) in mono mode, n2 will use n1 voices + * of the voice. + * When playing legato (n1,n2) in mono mode, n2 will use n1 voices * as far as n2 still enters in Keyrange,Velrange of n1. */ int -fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, - fluid_zone_range_t *inst_zone_range, - fluid_channel_t* channel, int key, int vel, unsigned int id, - unsigned int start_time, fluid_real_t gain) +fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample, + fluid_zone_range_t *inst_zone_range, + fluid_channel_t *channel, int key, int vel, unsigned int id, + unsigned int start_time, fluid_real_t gain) { - /* Note: The voice parameters will be initialized later, when the - * generators have been retrieved from the sound font. Here, only - * the 'working memory' of the voice (position in envelopes, history - * of IIR filters, position in sample etc) is initialized. */ - int i; + /* Note: The voice parameters will be initialized later, when the + * generators have been retrieved from the sound font. Here, only + * the 'working memory' of the voice (position in envelopes, history + * of IIR filters, position in sample etc) is initialized. */ + int i; - if (!voice->can_access_rvoice) { - if (voice->can_access_overflow_rvoice) - fluid_voice_swap_rvoice(voice); - else { - FLUID_LOG(FLUID_ERR, "Internal error: Cannot access an rvoice in fluid_voice_init!"); - return FLUID_FAILED; + if(!voice->can_access_rvoice) + { + if(voice->can_access_overflow_rvoice) + { + fluid_voice_swap_rvoice(voice); + } + else + { + FLUID_LOG(FLUID_ERR, "Internal error: Cannot access an rvoice in fluid_voice_init!"); + return FLUID_FAILED; + } } - } - /* We are now guaranteed to have access to the rvoice */ - if (voice->sample) - fluid_voice_off(voice); + /* We are now guaranteed to have access to the rvoice */ - voice->zone_range = inst_zone_range; /* Instrument zone range for legato */ - voice->id = id; - voice->chan = fluid_channel_get_num(channel); - voice->key = (unsigned char) key; - voice->vel = (unsigned char) vel; - voice->channel = channel; - voice->mod_count = 0; - voice->start_time = start_time; - voice->has_noteoff = 0; - UPDATE_RVOICE0(fluid_rvoice_reset); + if(voice->sample) + { + fluid_voice_off(voice); + } - /* Increment the reference count of the sample to prevent the - unloading of the soundfont while this voice is playing, - once for us and once for the rvoice. */ - fluid_sample_incr_ref(sample); - fluid_rvoice_eventhandler_push_ptr(voice->eventhandler, fluid_rvoice_set_sample, voice->rvoice, sample); - fluid_sample_incr_ref(sample); - voice->sample = sample; + voice->zone_range = inst_zone_range; /* Instrument zone range for legato */ + voice->id = id; + voice->chan = fluid_channel_get_num(channel); + voice->key = (unsigned char) key; + voice->vel = (unsigned char) vel; + voice->channel = channel; + voice->mod_count = 0; + voice->start_time = start_time; + voice->has_noteoff = 0; + UPDATE_RVOICE0(fluid_rvoice_reset); - i = fluid_channel_get_interp_method(channel); - UPDATE_RVOICE_I1(fluid_rvoice_set_interp_method, i); + /* Increment the reference count of the sample to prevent the + unloading of the soundfont while this voice is playing, + once for us and once for the rvoice. */ + fluid_sample_incr_ref(sample); + fluid_rvoice_eventhandler_push_ptr(voice->eventhandler, fluid_rvoice_set_sample, voice->rvoice, sample); + fluid_sample_incr_ref(sample); + voice->sample = sample; - /* Set all the generators to their default value, according to SF - * 2.01 section 8.1.3 (page 48). The value of NRPN messages are - * copied from the channel to the voice's generators. The sound font - * loader overwrites them. The generator values are later converted - * into voice parameters in - * fluid_voice_calculate_runtime_synthesis_parameters. */ - fluid_gen_init(&voice->gen[0], channel); - UPDATE_RVOICE_I1(fluid_rvoice_set_samplemode, _SAMPLEMODE(voice)); + i = fluid_channel_get_interp_method(channel); + UPDATE_RVOICE_I1(fluid_rvoice_set_interp_method, i); - voice->synth_gain = gain; - /* avoid division by zero later*/ - if (voice->synth_gain < 0.0000001){ - voice->synth_gain = 0.0000001; - } - UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, voice->synth_gain); + /* Set all the generators to their default value, according to SF + * 2.01 section 8.1.3 (page 48). The value of NRPN messages are + * copied from the channel to the voice's generators. The sound font + * loader overwrites them. The generator values are later converted + * into voice parameters in + * fluid_voice_calculate_runtime_synthesis_parameters. */ + fluid_gen_init(&voice->gen[0], channel); + UPDATE_RVOICE_I1(fluid_rvoice_set_samplemode, _SAMPLEMODE(voice)); - /* Set up buffer mapping, should be done more flexible in the future. */ - i = channel->synth->audio_groups; - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 2, i*2 + SYNTH_REVERB_CHANNEL); - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 3, i*2 + SYNTH_CHORUS_CHANNEL); - - i = 2 * (voice->chan % i); - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 0, i); - UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 1, i+1); + voice->synth_gain = gain; - return FLUID_OK; + /* avoid division by zero later*/ + if(voice->synth_gain < 0.0000001) + { + voice->synth_gain = 0.0000001; + } + + UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, voice->synth_gain); + + /* Set up buffer mapping, should be done more flexible in the future. */ + i = channel->synth->audio_groups; + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 2, i * 2 + SYNTH_REVERB_CHANNEL); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 3, i * 2 + SYNTH_CHORUS_CHANNEL); + + i = 2 * (voice->chan % i); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 0, i); + UPDATE_RVOICE_GENERIC_I2(fluid_rvoice_buffers_set_mapping, &voice->rvoice->buffers, 1, i + 1); + + return FLUID_OK; } /** - * Update sample rate. + * Update sample rate. * @note If the voice is active, it will be turned off. */ -void -fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value) +void +fluid_voice_set_output_rate(fluid_voice_t *voice, fluid_real_t value) { - if (fluid_voice_is_playing(voice)) - fluid_voice_off(voice); - - voice->output_rate = value; - UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->rvoice, value); - UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->overflow_rvoice, value); + if(fluid_voice_is_playing(voice)) + { + fluid_voice_off(voice); + } + + voice->output_rate = value; + UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->rvoice, value); + UPDATE_RVOICE_GENERIC_R1(fluid_rvoice_set_output_rate, voice->overflow_rvoice, value); } @@ -370,12 +389,15 @@ fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value) * @param val Generator value */ void -fluid_voice_gen_set(fluid_voice_t* voice, int i, float val) +fluid_voice_gen_set(fluid_voice_t *voice, int i, float val) { - voice->gen[i].val = val; - voice->gen[i].flags = GEN_SET; - if (i == GEN_SAMPLEMODE) - UPDATE_RVOICE_I1(fluid_rvoice_set_samplemode, (int) val); + voice->gen[i].val = val; + voice->gen[i].flags = GEN_SET; + + if(i == GEN_SAMPLEMODE) + { + UPDATE_RVOICE_I1(fluid_rvoice_set_samplemode, (int) val); + } } /** @@ -385,10 +407,10 @@ fluid_voice_gen_set(fluid_voice_t* voice, int i, float val) * @param val Value to add to the existing value */ void -fluid_voice_gen_incr(fluid_voice_t* voice, int i, float val) +fluid_voice_gen_incr(fluid_voice_t *voice, int i, float val) { - voice->gen[i].val += val; - voice->gen[i].flags = GEN_SET; + voice->gen[i].val += val; + voice->gen[i].flags = GEN_SET; } /** @@ -398,52 +420,55 @@ fluid_voice_gen_incr(fluid_voice_t* voice, int i, float val) * @return Current generator value */ float -fluid_voice_gen_get(fluid_voice_t* voice, int gen) +fluid_voice_gen_get(fluid_voice_t *voice, int gen) { - return voice->gen[gen].val; + return voice->gen[gen].val; } -fluid_real_t fluid_voice_gen_value(const fluid_voice_t* voice, int num) +fluid_real_t fluid_voice_gen_value(const fluid_voice_t *voice, int num) { - /* This is an extension to the SoundFont standard. More - * documentation is available at the fluid_synth_set_gen2() - * function. */ - if (voice->gen[num].flags == GEN_ABS_NRPN) { - return (fluid_real_t) voice->gen[num].nrpn; - } else { - return (fluid_real_t) (voice->gen[num].val + voice->gen[num].mod + voice->gen[num].nrpn); - } + /* This is an extension to the SoundFont standard. More + * documentation is available at the fluid_synth_set_gen2() + * function. */ + if(voice->gen[num].flags == GEN_ABS_NRPN) + { + return (fluid_real_t) voice->gen[num].nrpn; + } + else + { + return (fluid_real_t)(voice->gen[num].val + voice->gen[num].mod + voice->gen[num].nrpn); + } } /* * fluid_voice_start */ -void fluid_voice_start(fluid_voice_t* voice) +void fluid_voice_start(fluid_voice_t *voice) { - /* The maximum volume of the loop is calculated and cached once for each - * sample with its nominal loop settings. This happens, when the sample is used - * for the first time.*/ + /* The maximum volume of the loop is calculated and cached once for each + * sample with its nominal loop settings. This happens, when the sample is used + * for the first time.*/ - fluid_voice_calculate_runtime_synthesis_parameters(voice); + fluid_voice_calculate_runtime_synthesis_parameters(voice); #ifdef WITH_PROFILING - voice->ref = fluid_profile_ref(); + voice->ref = fluid_profile_ref(); #endif - voice->status = FLUID_VOICE_ON; + voice->status = FLUID_VOICE_ON; - /* Increment voice count */ - voice->channel->synth->active_voice_count++; + /* Increment voice count */ + voice->channel->synth->active_voice_count++; } /** * Calculate the amplitude of a voice. - * + * * @param gain The gain value in the range [0.0 ; 1.0] * @return An amplitude used by rvoice_mixer's buffers */ static FLUID_INLINE fluid_real_t -fluid_voice_calculate_gain_amplitude(const fluid_voice_t* voice, fluid_real_t gain) +fluid_voice_calculate_gain_amplitude(const fluid_voice_t *voice, fluid_real_t gain) { /* we use 24bit samples in fluid_rvoice_dsp. in order to normalize float * samples to [0.0;1.0] divide samples by the max. value of an int24 and @@ -457,33 +482,37 @@ fluid_voice_calculate_gain_amplitude(const fluid_voice_t* voice, fluid_real_t ga This is useful to set the value of GEN_PITCH generator on noteOn. This is useful to get the beginning/ending pitch for portamento. */ -fluid_real_t fluid_voice_calculate_pitch(fluid_voice_t* voice, int key) +fluid_real_t fluid_voice_calculate_pitch(fluid_voice_t *voice, int key) { - fluid_tuning_t* tuning; - fluid_real_t x,pitch; + fluid_tuning_t *tuning; + fluid_real_t x, pitch; - /* Now the nominal pitch of the key is returned. - * Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a - * non-realtime parameter. So we don't allow modulation (as opposed - * to fluid_voice_gen_value(voice, GEN_SCALETUNE) When the scale tuning is varied, - * one key remains fixed. Here C3 (MIDI number 60) is used. - */ - if (fluid_channel_has_tuning(voice->channel)) { - tuning = fluid_channel_get_tuning (voice->channel); - x = fluid_tuning_get_pitch (tuning, (int)(voice->root_pitch / 100.0f)); - pitch = voice->gen[GEN_SCALETUNE].val / 100.0f * - (fluid_tuning_get_pitch (tuning, key) - x) + x; - } else { - pitch = voice->gen[GEN_SCALETUNE].val - * (key - voice->root_pitch / 100.0f) + voice->root_pitch; - } - return pitch; - } + /* Now the nominal pitch of the key is returned. + * Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a + * non-realtime parameter. So we don't allow modulation (as opposed + * to fluid_voice_gen_value(voice, GEN_SCALETUNE) When the scale tuning is varied, + * one key remains fixed. Here C3 (MIDI number 60) is used. + */ + if(fluid_channel_has_tuning(voice->channel)) + { + tuning = fluid_channel_get_tuning(voice->channel); + x = fluid_tuning_get_pitch(tuning, (int)(voice->root_pitch / 100.0f)); + pitch = voice->gen[GEN_SCALETUNE].val / 100.0f * + (fluid_tuning_get_pitch(tuning, key) - x) + x; + } + else + { + pitch = voice->gen[GEN_SCALETUNE].val + * (key - voice->root_pitch / 100.0f) + voice->root_pitch; + } + + return pitch; +} void -fluid_voice_calculate_gen_pitch(fluid_voice_t* voice) +fluid_voice_calculate_gen_pitch(fluid_voice_t *voice) { - voice->gen[GEN_PITCH].val = fluid_voice_calculate_pitch(voice, fluid_voice_get_actual_key(voice)); + voice->gen[GEN_PITCH].val = fluid_voice_calculate_pitch(voice, fluid_voice_get_actual_key(voice)); } @@ -498,191 +527,206 @@ fluid_voice_calculate_gen_pitch(fluid_voice_t* voice) * example, for the pitch since it is modulated by the controllers in * cents. */ static int -fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice) +fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t *voice) { - int i; - unsigned int n; + int i; + unsigned int n; - static int const list_of_generators_to_initialize[] = { - GEN_STARTADDROFS, /* SF2.01 page 48 #0 */ - GEN_ENDADDROFS, /* #1 */ - GEN_STARTLOOPADDROFS, /* #2 */ - GEN_ENDLOOPADDROFS, /* #3 */ - /* GEN_STARTADDRCOARSEOFS see comment below [1] #4 */ - GEN_MODLFOTOPITCH, /* #5 */ - GEN_VIBLFOTOPITCH, /* #6 */ - GEN_MODENVTOPITCH, /* #7 */ - GEN_FILTERFC, /* #8 */ - GEN_FILTERQ, /* #9 */ - GEN_MODLFOTOFILTERFC, /* #10 */ - GEN_MODENVTOFILTERFC, /* #11 */ - /* GEN_ENDADDRCOARSEOFS [1] #12 */ - GEN_MODLFOTOVOL, /* #13 */ - /* not defined #14 */ - GEN_CHORUSSEND, /* #15 */ - GEN_REVERBSEND, /* #16 */ - GEN_PAN, /* #17 */ - /* not defined #18 */ - /* not defined #19 */ - /* not defined #20 */ - GEN_MODLFODELAY, /* #21 */ - GEN_MODLFOFREQ, /* #22 */ - GEN_VIBLFODELAY, /* #23 */ - GEN_VIBLFOFREQ, /* #24 */ - GEN_MODENVDELAY, /* #25 */ - GEN_MODENVATTACK, /* #26 */ - GEN_MODENVHOLD, /* #27 */ - GEN_MODENVDECAY, /* #28 */ - /* GEN_MODENVSUSTAIN [1] #29 */ - GEN_MODENVRELEASE, /* #30 */ - /* GEN_KEYTOMODENVHOLD [1] #31 */ - /* GEN_KEYTOMODENVDECAY [1] #32 */ - GEN_VOLENVDELAY, /* #33 */ - GEN_VOLENVATTACK, /* #34 */ - GEN_VOLENVHOLD, /* #35 */ - GEN_VOLENVDECAY, /* #36 */ - /* GEN_VOLENVSUSTAIN [1] #37 */ - GEN_VOLENVRELEASE, /* #38 */ - /* GEN_KEYTOVOLENVHOLD [1] #39 */ - /* GEN_KEYTOVOLENVDECAY [1] #40 */ - /* GEN_STARTLOOPADDRCOARSEOFS [1] #45 */ - GEN_KEYNUM, /* #46 */ - GEN_VELOCITY, /* #47 */ - GEN_ATTENUATION, /* #48 */ - /* GEN_ENDLOOPADDRCOARSEOFS [1] #50 */ - /* GEN_COARSETUNE [1] #51 */ - /* GEN_FINETUNE [1] #52 */ - GEN_OVERRIDEROOTKEY, /* #58 */ - GEN_PITCH, /* --- */ - GEN_CUSTOM_BALANCE, /* --- */ - GEN_CUSTOM_FILTERFC, /* --- */ - GEN_CUSTOM_FILTERQ /* --- */ - }; + static int const list_of_generators_to_initialize[] = + { + GEN_STARTADDROFS, /* SF2.01 page 48 #0 */ + GEN_ENDADDROFS, /* #1 */ + GEN_STARTLOOPADDROFS, /* #2 */ + GEN_ENDLOOPADDROFS, /* #3 */ + /* GEN_STARTADDRCOARSEOFS see comment below [1] #4 */ + GEN_MODLFOTOPITCH, /* #5 */ + GEN_VIBLFOTOPITCH, /* #6 */ + GEN_MODENVTOPITCH, /* #7 */ + GEN_FILTERFC, /* #8 */ + GEN_FILTERQ, /* #9 */ + GEN_MODLFOTOFILTERFC, /* #10 */ + GEN_MODENVTOFILTERFC, /* #11 */ + /* GEN_ENDADDRCOARSEOFS [1] #12 */ + GEN_MODLFOTOVOL, /* #13 */ + /* not defined #14 */ + GEN_CHORUSSEND, /* #15 */ + GEN_REVERBSEND, /* #16 */ + GEN_PAN, /* #17 */ + /* not defined #18 */ + /* not defined #19 */ + /* not defined #20 */ + GEN_MODLFODELAY, /* #21 */ + GEN_MODLFOFREQ, /* #22 */ + GEN_VIBLFODELAY, /* #23 */ + GEN_VIBLFOFREQ, /* #24 */ + GEN_MODENVDELAY, /* #25 */ + GEN_MODENVATTACK, /* #26 */ + GEN_MODENVHOLD, /* #27 */ + GEN_MODENVDECAY, /* #28 */ + /* GEN_MODENVSUSTAIN [1] #29 */ + GEN_MODENVRELEASE, /* #30 */ + /* GEN_KEYTOMODENVHOLD [1] #31 */ + /* GEN_KEYTOMODENVDECAY [1] #32 */ + GEN_VOLENVDELAY, /* #33 */ + GEN_VOLENVATTACK, /* #34 */ + GEN_VOLENVHOLD, /* #35 */ + GEN_VOLENVDECAY, /* #36 */ + /* GEN_VOLENVSUSTAIN [1] #37 */ + GEN_VOLENVRELEASE, /* #38 */ + /* GEN_KEYTOVOLENVHOLD [1] #39 */ + /* GEN_KEYTOVOLENVDECAY [1] #40 */ + /* GEN_STARTLOOPADDRCOARSEOFS [1] #45 */ + GEN_KEYNUM, /* #46 */ + GEN_VELOCITY, /* #47 */ + GEN_ATTENUATION, /* #48 */ + /* GEN_ENDLOOPADDRCOARSEOFS [1] #50 */ + /* GEN_COARSETUNE [1] #51 */ + /* GEN_FINETUNE [1] #52 */ + GEN_OVERRIDEROOTKEY, /* #58 */ + GEN_PITCH, /* --- */ + GEN_CUSTOM_BALANCE, /* --- */ + GEN_CUSTOM_FILTERFC, /* --- */ + GEN_CUSTOM_FILTERQ /* --- */ + }; - /* When the voice is made ready for the synthesis process, a lot of - * voice-internal parameters have to be calculated. - * - * At this point, the sound font has already set the -nominal- value - * for all generators (excluding GEN_PITCH). Most generators can be - * modulated - they include a nominal value and an offset (which - * changes with velocity, note number, channel parameters like - * aftertouch, mod wheel...) Now this offset will be calculated as - * follows: - * - * - Process each modulator once. - * - Calculate its output value. - * - Find the target generator. - * - Add the output value to the modulation value of the generator. - * - * Note: The generators have been initialized with - * fluid_gen_set_default_values. - */ + /* When the voice is made ready for the synthesis process, a lot of + * voice-internal parameters have to be calculated. + * + * At this point, the sound font has already set the -nominal- value + * for all generators (excluding GEN_PITCH). Most generators can be + * modulated - they include a nominal value and an offset (which + * changes with velocity, note number, channel parameters like + * aftertouch, mod wheel...) Now this offset will be calculated as + * follows: + * + * - Process each modulator once. + * - Calculate its output value. + * - Find the target generator. + * - Add the output value to the modulation value of the generator. + * + * Note: The generators have been initialized with + * fluid_gen_set_default_values. + */ - for (i = 0; i < voice->mod_count; i++) { - fluid_mod_t* mod = &voice->mod[i]; - fluid_real_t modval = fluid_mod_get_value(mod, voice->channel, voice); - int dest_gen_index = mod->dest; - fluid_gen_t* dest_gen = &voice->gen[dest_gen_index]; - dest_gen->mod += modval; - /* fluid_dump_modulator(mod); */ - } + for(i = 0; i < voice->mod_count; i++) + { + fluid_mod_t *mod = &voice->mod[i]; + fluid_real_t modval = fluid_mod_get_value(mod, voice->channel, voice); + int dest_gen_index = mod->dest; + fluid_gen_t *dest_gen = &voice->gen[dest_gen_index]; + dest_gen->mod += modval; + /* fluid_dump_modulator(mod); */ + } - /* Now the generators are initialized, nominal and modulation value. - * The voice parameters (which depend on generators) are calculated - * with fluid_voice_update_param. Processing the list of generator - * changes will calculate each voice parameter once. - * - * Note [1]: Some voice parameters depend on several generators. For - * example, the pitch depends on GEN_COARSETUNE, GEN_FINETUNE and - * GEN_PITCH. voice->pitch. Unnecessary recalculation is avoided - * by removing all but one generator from the list of voice - * parameters. Same with GEN_XXX and GEN_XXXCOARSE: the - * initialisation list contains only GEN_XXX. - */ + /* Now the generators are initialized, nominal and modulation value. + * The voice parameters (which depend on generators) are calculated + * with fluid_voice_update_param. Processing the list of generator + * changes will calculate each voice parameter once. + * + * Note [1]: Some voice parameters depend on several generators. For + * example, the pitch depends on GEN_COARSETUNE, GEN_FINETUNE and + * GEN_PITCH. voice->pitch. Unnecessary recalculation is avoided + * by removing all but one generator from the list of voice + * parameters. Same with GEN_XXX and GEN_XXXCOARSE: the + * initialisation list contains only GEN_XXX. + */ - /* Calculate the voice parameter(s) dependent on each generator. */ - for (n = 0; n < FLUID_N_ELEMENTS(list_of_generators_to_initialize); n++) { - fluid_voice_update_param(voice, list_of_generators_to_initialize[n]); - } + /* Calculate the voice parameter(s) dependent on each generator. */ + for(n = 0; n < FLUID_N_ELEMENTS(list_of_generators_to_initialize); n++) + { + fluid_voice_update_param(voice, list_of_generators_to_initialize[n]); + } - /* Start portamento if enabled */ - { /* fromkey note comes from "GetFromKeyPortamentoLegato()" detector. - When fromkey is set to ValidNote , portamento is started */ - /* Return fromkey portamento */ - int fromkey = voice->channel->synth->fromkey_portamento; - if(fluid_channel_is_valid_note(fromkey)) - { /* Send portamento parameters to the voice dsp */ - fluid_voice_update_portamento(voice,fromkey, fluid_voice_get_actual_key(voice)); - } - } + /* Start portamento if enabled */ + { + /* fromkey note comes from "GetFromKeyPortamentoLegato()" detector. + When fromkey is set to ValidNote , portamento is started */ + /* Return fromkey portamento */ + int fromkey = voice->channel->synth->fromkey_portamento; - /* Make an estimate on how loud this voice can get at any time (attenuation). */ - UPDATE_RVOICE_R1(fluid_rvoice_set_min_attenuation_cB, - fluid_voice_get_lower_boundary_for_attenuation(voice)); - return FLUID_OK; + if(fluid_channel_is_valid_note(fromkey)) + { + /* Send portamento parameters to the voice dsp */ + fluid_voice_update_portamento(voice, fromkey, fluid_voice_get_actual_key(voice)); + } + } + + /* Make an estimate on how loud this voice can get at any time (attenuation). */ + UPDATE_RVOICE_R1(fluid_rvoice_set_min_attenuation_cB, + fluid_voice_get_lower_boundary_for_attenuation(voice)); + return FLUID_OK; } /* * calculate_hold_decay_buffers */ static int -calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, +calculate_hold_decay_buffers(fluid_voice_t *voice, int gen_base, int gen_key2base, int is_decay) { - /* Purpose: - * - * Returns the number of DSP loops, that correspond to the hold - * (is_decay=0) or decay (is_decay=1) time. - * gen_base=GEN_VOLENVHOLD, GEN_VOLENVDECAY, GEN_MODENVHOLD, - * GEN_MODENVDECAY gen_key2base=GEN_KEYTOVOLENVHOLD, - * GEN_KEYTOVOLENVDECAY, GEN_KEYTOMODENVHOLD, GEN_KEYTOMODENVDECAY - */ - - fluid_real_t timecents; - fluid_real_t seconds; - int buffers; - - /* SF2.01 section 8.4.3 # 31, 32, 39, 40 - * GEN_KEYTOxxxENVxxx uses key 60 as 'origin'. - * The unit of the generator is timecents per key number. - * If KEYTOxxxENVxxx is 100, a key one octave over key 60 (72) - * will cause (60-72)*100=-1200 timecents of time variation. - * The time is cut in half. - */ - timecents = (fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * (60.0 - fluid_voice_get_actual_key(voice))); - - /* Range checking */ - if (is_decay){ - /* SF 2.01 section 8.1.3 # 28, 36 */ - if (timecents > 8000.0) { - timecents = 8000.0; - } - } else { - /* SF 2.01 section 8.1.3 # 27, 35 */ - if (timecents > 5000) { - timecents = 5000.0; - } - /* SF 2.01 section 8.1.2 # 27, 35: - * The most negative number indicates no hold time + /* Purpose: + * + * Returns the number of DSP loops, that correspond to the hold + * (is_decay=0) or decay (is_decay=1) time. + * gen_base=GEN_VOLENVHOLD, GEN_VOLENVDECAY, GEN_MODENVHOLD, + * GEN_MODENVDECAY gen_key2base=GEN_KEYTOVOLENVHOLD, + * GEN_KEYTOVOLENVDECAY, GEN_KEYTOMODENVHOLD, GEN_KEYTOMODENVDECAY */ - if (timecents <= -32768.) { - return 0; + + fluid_real_t timecents; + fluid_real_t seconds; + int buffers; + + /* SF2.01 section 8.4.3 # 31, 32, 39, 40 + * GEN_KEYTOxxxENVxxx uses key 60 as 'origin'. + * The unit of the generator is timecents per key number. + * If KEYTOxxxENVxxx is 100, a key one octave over key 60 (72) + * will cause (60-72)*100=-1200 timecents of time variation. + * The time is cut in half. + */ + timecents = (fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * (60.0 - fluid_voice_get_actual_key(voice))); + + /* Range checking */ + if(is_decay) + { + /* SF 2.01 section 8.1.3 # 28, 36 */ + if(timecents > 8000.0) + { + timecents = 8000.0; + } } - } - /* SF 2.01 section 8.1.3 # 27, 28, 35, 36 */ - if (timecents < -12000.0) { - timecents = -12000.0; - } + else + { + /* SF 2.01 section 8.1.3 # 27, 35 */ + if(timecents > 5000) + { + timecents = 5000.0; + } - seconds = fluid_tc2sec(timecents); - /* Each DSP loop processes FLUID_BUFSIZE samples. */ + /* SF 2.01 section 8.1.2 # 27, 35: + * The most negative number indicates no hold time + */ + if(timecents <= -32768.) + { + return 0; + } + } - /* round to next full number of buffers */ - buffers = (int)(((fluid_real_t)voice->output_rate * seconds) - / (fluid_real_t)FLUID_BUFSIZE - +0.5); + /* SF 2.01 section 8.1.3 # 27, 28, 35, 36 */ + if(timecents < -12000.0) + { + timecents = -12000.0; + } - return buffers; + seconds = fluid_tc2sec(timecents); + /* Each DSP loop processes FLUID_BUFSIZE samples. */ + + /* round to next full number of buffers */ + buffers = (int)(((fluid_real_t)voice->output_rate * seconds) + / (fluid_real_t)FLUID_BUFSIZE + + 0.5); + + return buffers; } /* @@ -709,223 +753,245 @@ calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, * Most applications will not need this function. */ void -fluid_voice_update_param(fluid_voice_t* voice, int gen) +fluid_voice_update_param(fluid_voice_t *voice, int gen) { - unsigned int count, z; - fluid_real_t x = fluid_voice_gen_value(voice, gen); - - switch (gen) { + unsigned int count, z; + fluid_real_t x = fluid_voice_gen_value(voice, gen); - case GEN_PAN: - case GEN_CUSTOM_BALANCE: - /* range checking is done in the fluid_pan and fluid_balance functions */ - voice->pan = fluid_voice_gen_value(voice, GEN_PAN); - voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE); + switch(gen) + { - /* left amp */ - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, - fluid_voice_calculate_gain_amplitude(voice, - fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1))); - - /* right amp */ - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, - fluid_voice_calculate_gain_amplitude(voice, - fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0))); - break; + case GEN_PAN: + case GEN_CUSTOM_BALANCE: + /* range checking is done in the fluid_pan and fluid_balance functions */ + voice->pan = fluid_voice_gen_value(voice, GEN_PAN); + voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE); - case GEN_ATTENUATION: - voice->attenuation = x; + /* left amp */ + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, + fluid_voice_calculate_gain_amplitude(voice, + fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1))); - /* Range: SF2.01 section 8.1.3 # 48 - * Motivation for range checking: - * OHPiano.SF2 sets initial attenuation to a whooping -96 dB */ - fluid_clip(voice->attenuation, 0.0, 1440.0); - UPDATE_RVOICE_R1(fluid_rvoice_set_attenuation, voice->attenuation); - break; + /* right amp */ + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, + fluid_voice_calculate_gain_amplitude(voice, + fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0))); + break; + + case GEN_ATTENUATION: + voice->attenuation = x; + + /* Range: SF2.01 section 8.1.3 # 48 + * Motivation for range checking: + * OHPiano.SF2 sets initial attenuation to a whooping -96 dB */ + fluid_clip(voice->attenuation, 0.0, 1440.0); + UPDATE_RVOICE_R1(fluid_rvoice_set_attenuation, voice->attenuation); + break; /* The pitch is calculated from three different generators. * Read comment in fluidsynth.h about GEN_PITCH. */ - case GEN_PITCH: - case GEN_COARSETUNE: - case GEN_FINETUNE: - /* The testing for allowed range is done in 'fluid_ct2hz' */ - voice->pitch = (fluid_voice_gen_value(voice, GEN_PITCH) - + 100.0f * fluid_voice_gen_value(voice, GEN_COARSETUNE) - + fluid_voice_gen_value(voice, GEN_FINETUNE)); - UPDATE_RVOICE_R1(fluid_rvoice_set_pitch, voice->pitch); - break; + case GEN_PITCH: + case GEN_COARSETUNE: + case GEN_FINETUNE: + /* The testing for allowed range is done in 'fluid_ct2hz' */ + voice->pitch = (fluid_voice_gen_value(voice, GEN_PITCH) + + 100.0f * fluid_voice_gen_value(voice, GEN_COARSETUNE) + + fluid_voice_gen_value(voice, GEN_FINETUNE)); + UPDATE_RVOICE_R1(fluid_rvoice_set_pitch, voice->pitch); + break; - case GEN_REVERBSEND: - /* The generator unit is 'tenths of a percent'. */ - voice->reverb_send = x / 1000.0f; - fluid_clip(voice->reverb_send, 0.0, 1.0); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send)); - break; + case GEN_REVERBSEND: + /* The generator unit is 'tenths of a percent'. */ + voice->reverb_send = x / 1000.0f; + fluid_clip(voice->reverb_send, 0.0, 1.0); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send)); + break; - case GEN_CHORUSSEND: - /* The generator unit is 'tenths of a percent'. */ - voice->chorus_send = x / 1000.0f; - fluid_clip(voice->chorus_send, 0.0, 1.0); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send)); - break; + case GEN_CHORUSSEND: + /* The generator unit is 'tenths of a percent'. */ + voice->chorus_send = x / 1000.0f; + fluid_clip(voice->chorus_send, 0.0, 1.0); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send)); + break; - case GEN_OVERRIDEROOTKEY: - /* This is a non-realtime parameter. Therefore the .mod part of the generator - * can be neglected. - * NOTE: origpitch sets MIDI root note while pitchadj is a fine tuning amount - * which offsets the original rate. This means that the fine tuning is - * inverted with respect to the root note (so subtract it, not add). - */ - if (voice->sample != NULL) { - if (voice->gen[GEN_OVERRIDEROOTKEY].val > -1) //FIXME: use flag instead of -1 - voice->root_pitch = voice->gen[GEN_OVERRIDEROOTKEY].val * 100.0f - - voice->sample->pitchadj; - else - voice->root_pitch = voice->sample->origpitch * 100.0f - voice->sample->pitchadj; - x = (fluid_ct2hz(voice->root_pitch) * ((fluid_real_t) voice->output_rate / voice->sample->samplerate)); - } else { - if (voice->gen[GEN_OVERRIDEROOTKEY].val > -1) //FIXME: use flag instead of -1 - voice->root_pitch = voice->gen[GEN_OVERRIDEROOTKEY].val * 100.0f; - else - voice->root_pitch = 0; - x = fluid_ct2hz(voice->root_pitch); - } - /* voice->pitch depends on voice->root_pitch, so calculate voice->pitch now */ - fluid_voice_calculate_gen_pitch(voice); - UPDATE_RVOICE_R1(fluid_rvoice_set_root_pitch_hz, x); + case GEN_OVERRIDEROOTKEY: - break; + /* This is a non-realtime parameter. Therefore the .mod part of the generator + * can be neglected. + * NOTE: origpitch sets MIDI root note while pitchadj is a fine tuning amount + * which offsets the original rate. This means that the fine tuning is + * inverted with respect to the root note (so subtract it, not add). + */ + if(voice->sample != NULL) + { + if(voice->gen[GEN_OVERRIDEROOTKEY].val > -1) //FIXME: use flag instead of -1 + { + voice->root_pitch = voice->gen[GEN_OVERRIDEROOTKEY].val * 100.0f + - voice->sample->pitchadj; + } + else + { + voice->root_pitch = voice->sample->origpitch * 100.0f - voice->sample->pitchadj; + } - case GEN_FILTERFC: - /* The resonance frequency is converted from absolute cents to - * midicents .val and .mod are both used, this permits real-time - * modulation. The allowed range is tested in the 'fluid_ct2hz' - * function [PH,20021214] - */ - UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_filter, x); - break; + x = (fluid_ct2hz(voice->root_pitch) * ((fluid_real_t) voice->output_rate / voice->sample->samplerate)); + } + else + { + if(voice->gen[GEN_OVERRIDEROOTKEY].val > -1) //FIXME: use flag instead of -1 + { + voice->root_pitch = voice->gen[GEN_OVERRIDEROOTKEY].val * 100.0f; + } + else + { + voice->root_pitch = 0; + } - case GEN_FILTERQ: - UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_filter, x); - break; + x = fluid_ct2hz(voice->root_pitch); + } - /* same as the two above, only for the custom filter */ - case GEN_CUSTOM_FILTERFC: - UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_custom_filter, x); - break; + /* voice->pitch depends on voice->root_pitch, so calculate voice->pitch now */ + fluid_voice_calculate_gen_pitch(voice); + UPDATE_RVOICE_R1(fluid_rvoice_set_root_pitch_hz, x); - case GEN_CUSTOM_FILTERQ: - UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_custom_filter, x); - break; - - case GEN_MODLFOTOPITCH: - fluid_clip(x, -12000.0, 12000.0); - UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_pitch, x); - break; + break; - case GEN_MODLFOTOVOL: - fluid_clip(x, -960.0, 960.0); - UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_vol, x); - break; + case GEN_FILTERFC: + /* The resonance frequency is converted from absolute cents to + * midicents .val and .mod are both used, this permits real-time + * modulation. The allowed range is tested in the 'fluid_ct2hz' + * function [PH,20021214] + */ + UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_filter, x); + break; - case GEN_MODLFOTOFILTERFC: - fluid_clip(x, -12000, 12000); - UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_fc, x); - break; + case GEN_FILTERQ: + UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_filter, x); + break; - case GEN_MODLFODELAY: - fluid_clip(x, -12000.0f, 5000.0f); - z = (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x)); - UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, modlfo, z); - break; + /* same as the two above, only for the custom filter */ + case GEN_CUSTOM_FILTERFC: + UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_fres, &voice->rvoice->resonant_custom_filter, x); + break; - case GEN_MODLFOFREQ: - /* - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples - * - the delay into a sample delay - */ - fluid_clip(x, -16000.0f, 4500.0f); - x = (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate); - UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, modlfo, x); - break; + case GEN_CUSTOM_FILTERQ: + UPDATE_RVOICE_GENERIC_R1(fluid_iir_filter_set_q, &voice->rvoice->resonant_custom_filter, x); + break; - case GEN_VIBLFOFREQ: - /* vib lfo - * - * - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples - * - the delay into a sample delay - */ - fluid_clip(x, -16000.0f, 4500.0f); - x = 4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate; - UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, viblfo, x); - break; + case GEN_MODLFOTOPITCH: + fluid_clip(x, -12000.0, 12000.0); + UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_pitch, x); + break; - case GEN_VIBLFODELAY: - fluid_clip(x, -12000.0f, 5000.0f); - z = (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x)); - UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, viblfo, z); - break; + case GEN_MODLFOTOVOL: + fluid_clip(x, -960.0, 960.0); + UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_vol, x); + break; - case GEN_VIBLFOTOPITCH: - fluid_clip(x, -12000.0, 12000.0); - UPDATE_RVOICE_R1(fluid_rvoice_set_viblfo_to_pitch, x); - break; + case GEN_MODLFOTOFILTERFC: + fluid_clip(x, -12000, 12000); + UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_fc, x); + break; - case GEN_KEYNUM: - /* GEN_KEYNUM: SF2.01 page 46, item 46 - * - * If this generator is active, it forces the key number to its - * value. Non-realtime controller. - * - * There is a flag, which should indicate, whether a generator is - * enabled or not. But here we rely on the default value of -1. - */ - - /* 2017-09-02: do not change the voice's key here, otherwise it will - * never be released on a noteoff event - */ + case GEN_MODLFODELAY: + fluid_clip(x, -12000.0f, 5000.0f); + z = (unsigned int)(voice->output_rate * fluid_tc2sec_delay(x)); + UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, modlfo, z); + break; + + case GEN_MODLFOFREQ: + /* - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples + * - the delay into a sample delay + */ + fluid_clip(x, -16000.0f, 4500.0f); + x = (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate); + UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, modlfo, x); + break; + + case GEN_VIBLFOFREQ: + /* vib lfo + * + * - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples + * - the delay into a sample delay + */ + fluid_clip(x, -16000.0f, 4500.0f); + x = 4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate; + UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, viblfo, x); + break; + + case GEN_VIBLFODELAY: + fluid_clip(x, -12000.0f, 5000.0f); + z = (unsigned int)(voice->output_rate * fluid_tc2sec_delay(x)); + UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, viblfo, z); + break; + + case GEN_VIBLFOTOPITCH: + fluid_clip(x, -12000.0, 12000.0); + UPDATE_RVOICE_R1(fluid_rvoice_set_viblfo_to_pitch, x); + break; + + case GEN_KEYNUM: + /* GEN_KEYNUM: SF2.01 page 46, item 46 + * + * If this generator is active, it forces the key number to its + * value. Non-realtime controller. + * + * There is a flag, which should indicate, whether a generator is + * enabled or not. But here we rely on the default value of -1. + */ + + /* 2017-09-02: do not change the voice's key here, otherwise it will + * never be released on a noteoff event + */ #if 0 - x = fluid_voice_gen_value(voice, GEN_KEYNUM); - if (x >= 0){ - voice->key = x; - } -#endif - break; + x = fluid_voice_gen_value(voice, GEN_KEYNUM); - case GEN_VELOCITY: - /* GEN_VELOCITY: SF2.01 page 46, item 47 - * - * If this generator is active, it forces the velocity to its - * value. Non-realtime controller. - * - * There is a flag, which should indicate, whether a generator is - * enabled or not. But here we rely on the default value of -1. - */ - /* 2017-09-02: do not change the voice's velocity here, use - * fluid_voice_get_actual_velocity() to get the value of this generator - * if active. - */ + if(x >= 0) + { + voice->key = x; + } + +#endif + break; + + case GEN_VELOCITY: + /* GEN_VELOCITY: SF2.01 page 46, item 47 + * + * If this generator is active, it forces the velocity to its + * value. Non-realtime controller. + * + * There is a flag, which should indicate, whether a generator is + * enabled or not. But here we rely on the default value of -1. + */ + /* 2017-09-02: do not change the voice's velocity here, use + * fluid_voice_get_actual_velocity() to get the value of this generator + * if active. + */ #if 0 - x = fluid_voice_gen_value(voice, GEN_VELOCITY); - if (x > 0) { - voice->vel = x; - } + x = fluid_voice_gen_value(voice, GEN_VELOCITY); + + if(x > 0) + { + voice->vel = x; + } + #endif - break; + break; - case GEN_MODENVTOPITCH: - fluid_clip(x, -12000.0, 12000.0); - UPDATE_RVOICE_R1(fluid_rvoice_set_modenv_to_pitch, x); - break; + case GEN_MODENVTOPITCH: + fluid_clip(x, -12000.0, 12000.0); + UPDATE_RVOICE_R1(fluid_rvoice_set_modenv_to_pitch, x); + break; - case GEN_MODENVTOFILTERFC: - /* Range: SF2.01 section 8.1.3 # 1 - * Motivation for range checking: - * Filter is reported to make funny noises now and then - */ - fluid_clip(x, -12000.0, 12000.0); - UPDATE_RVOICE_R1(fluid_rvoice_set_modenv_to_fc, x); - break; + case GEN_MODENVTOFILTERFC: + /* Range: SF2.01 section 8.1.3 # 1 + * Motivation for range checking: + * Filter is reported to make funny noises now and then + */ + fluid_clip(x, -12000.0, 12000.0); + UPDATE_RVOICE_R1(fluid_rvoice_set_modenv_to_fc, x); + break; /* sample start and ends points @@ -939,53 +1005,59 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) * end point ahead of the loop start point => invalid, then * move the loop start point forward => valid again. */ - case GEN_STARTADDROFS: /* SF2.01 section 8.1.3 # 0 */ - case GEN_STARTADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 4 */ - if (voice->sample != NULL) - { - fluid_real_t start_fine = fluid_voice_gen_value(voice, GEN_STARTADDROFS); - fluid_real_t start_coar = fluid_voice_gen_value(voice, GEN_STARTADDRCOARSEOFS); - - z = voice->sample->start + (int)start_fine + 32768 * (int)start_coar; - UPDATE_RVOICE_I1(fluid_rvoice_set_start, z); - } - break; - case GEN_ENDADDROFS: /* SF2.01 section 8.1.3 # 1 */ - case GEN_ENDADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 12 */ - if (voice->sample != NULL) - { - fluid_real_t end_fine = fluid_voice_gen_value(voice, GEN_ENDADDROFS); - fluid_real_t end_coar = fluid_voice_gen_value(voice, GEN_ENDADDRCOARSEOFS); - - z = voice->sample->end + (int)end_fine + 32768 * (int)end_coar; - UPDATE_RVOICE_I1(fluid_rvoice_set_end, z); - } - break; - case GEN_STARTLOOPADDROFS: /* SF2.01 section 8.1.3 # 2 */ - case GEN_STARTLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 45 */ - if (voice->sample != NULL) - { - fluid_real_t lstart_fine = fluid_voice_gen_value(voice, GEN_STARTLOOPADDROFS); - fluid_real_t lstart_coar = fluid_voice_gen_value(voice, GEN_STARTLOOPADDRCOARSEOFS); - - z = voice->sample->loopstart + (int)lstart_fine + 32768 * (int)lstart_coar; - UPDATE_RVOICE_I1(fluid_rvoice_set_loopstart, z); - } - break; + case GEN_STARTADDROFS: /* SF2.01 section 8.1.3 # 0 */ + case GEN_STARTADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 4 */ + if(voice->sample != NULL) + { + fluid_real_t start_fine = fluid_voice_gen_value(voice, GEN_STARTADDROFS); + fluid_real_t start_coar = fluid_voice_gen_value(voice, GEN_STARTADDRCOARSEOFS); - case GEN_ENDLOOPADDROFS: /* SF2.01 section 8.1.3 # 3 */ - case GEN_ENDLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 50 */ - if (voice->sample != NULL) - { - fluid_real_t lend_fine = fluid_voice_gen_value(voice, GEN_ENDLOOPADDROFS); - fluid_real_t lend_coar = fluid_voice_gen_value(voice, GEN_ENDLOOPADDRCOARSEOFS); - - z = voice->sample->loopend + (int)lend_fine + 32768 * (int)lend_coar; - UPDATE_RVOICE_I1(fluid_rvoice_set_loopend, z); - } - break; + z = voice->sample->start + (int)start_fine + 32768 * (int)start_coar; + UPDATE_RVOICE_I1(fluid_rvoice_set_start, z); + } - /* Conversion functions differ in range limit */ + break; + + case GEN_ENDADDROFS: /* SF2.01 section 8.1.3 # 1 */ + case GEN_ENDADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 12 */ + if(voice->sample != NULL) + { + fluid_real_t end_fine = fluid_voice_gen_value(voice, GEN_ENDADDROFS); + fluid_real_t end_coar = fluid_voice_gen_value(voice, GEN_ENDADDRCOARSEOFS); + + z = voice->sample->end + (int)end_fine + 32768 * (int)end_coar; + UPDATE_RVOICE_I1(fluid_rvoice_set_end, z); + } + + break; + + case GEN_STARTLOOPADDROFS: /* SF2.01 section 8.1.3 # 2 */ + case GEN_STARTLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 45 */ + if(voice->sample != NULL) + { + fluid_real_t lstart_fine = fluid_voice_gen_value(voice, GEN_STARTLOOPADDROFS); + fluid_real_t lstart_coar = fluid_voice_gen_value(voice, GEN_STARTLOOPADDRCOARSEOFS); + + z = voice->sample->loopstart + (int)lstart_fine + 32768 * (int)lstart_coar; + UPDATE_RVOICE_I1(fluid_rvoice_set_loopstart, z); + } + + break; + + case GEN_ENDLOOPADDROFS: /* SF2.01 section 8.1.3 # 3 */ + case GEN_ENDLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 50 */ + if(voice->sample != NULL) + { + fluid_real_t lend_fine = fluid_voice_gen_value(voice, GEN_ENDLOOPADDROFS); + fluid_real_t lend_coar = fluid_voice_gen_value(voice, GEN_ENDLOOPADDRCOARSEOFS); + + z = voice->sample->loopend + (int)lend_fine + 32768 * (int)lend_coar; + UPDATE_RVOICE_I1(fluid_rvoice_set_loopend, z); + } + + break; + + /* Conversion functions differ in range limit */ #define NUM_BUFFERS_DELAY(_v) (unsigned int) (voice->output_rate * fluid_tc2sec_delay(_v) / FLUID_BUFSIZE) #define NUM_BUFFERS_ATTACK(_v) (unsigned int) (voice->output_rate * fluid_tc2sec_attack(_v) / FLUID_BUFSIZE) #define NUM_BUFFERS_RELEASE(_v) (unsigned int) (voice->output_rate * fluid_tc2sec_release(_v) / FLUID_BUFSIZE) @@ -996,84 +1068,84 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) * - sustain is converted to its absolute value * - attack, decay and release are converted to their increment per sample */ - case GEN_VOLENVDELAY: /* SF2.01 section 8.1.3 # 33 */ - fluid_clip(x, -12000.0f, 5000.0f); - count = NUM_BUFFERS_DELAY(x); - fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDELAY, - count, 0.0f, 0.0f, -1.0f, 1.0f); - break; + case GEN_VOLENVDELAY: /* SF2.01 section 8.1.3 # 33 */ + fluid_clip(x, -12000.0f, 5000.0f); + count = NUM_BUFFERS_DELAY(x); + fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDELAY, + count, 0.0f, 0.0f, -1.0f, 1.0f); + break; - case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */ - fluid_clip(x, -12000.0f, 8000.0f); - count = 1 + NUM_BUFFERS_ATTACK(x); - fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVATTACK, - count, 1.0f, 1.0f / count, -1.0f, 1.0f); - break; + case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */ + fluid_clip(x, -12000.0f, 8000.0f); + count = 1 + NUM_BUFFERS_ATTACK(x); + fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVATTACK, + count, 1.0f, 1.0f / count, -1.0f, 1.0f); + break; - case GEN_VOLENVHOLD: /* SF2.01 section 8.1.3 # 35 */ - case GEN_KEYTOVOLENVHOLD: /* SF2.01 section 8.1.3 # 39 */ - count = calculate_hold_decay_buffers(voice, GEN_VOLENVHOLD, GEN_KEYTOVOLENVHOLD, 0); /* 0 means: hold */ - fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVHOLD, - count, 1.0f, 0.0f, -1.0f, 2.0f); - break; + case GEN_VOLENVHOLD: /* SF2.01 section 8.1.3 # 35 */ + case GEN_KEYTOVOLENVHOLD: /* SF2.01 section 8.1.3 # 39 */ + count = calculate_hold_decay_buffers(voice, GEN_VOLENVHOLD, GEN_KEYTOVOLENVHOLD, 0); /* 0 means: hold */ + fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVHOLD, + count, 1.0f, 0.0f, -1.0f, 2.0f); + break; - case GEN_VOLENVDECAY: /* SF2.01 section 8.1.3 # 36 */ - case GEN_VOLENVSUSTAIN: /* SF2.01 section 8.1.3 # 37 */ - case GEN_KEYTOVOLENVDECAY: /* SF2.01 section 8.1.3 # 40 */ - x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_VOLENVSUSTAIN); - fluid_clip(x , 0.0f, 1.0f); - count = calculate_hold_decay_buffers(voice, GEN_VOLENVDECAY, GEN_KEYTOVOLENVDECAY, 1); /* 1 for decay */ - fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDECAY, - count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f); - break; + case GEN_VOLENVDECAY: /* SF2.01 section 8.1.3 # 36 */ + case GEN_VOLENVSUSTAIN: /* SF2.01 section 8.1.3 # 37 */ + case GEN_KEYTOVOLENVDECAY: /* SF2.01 section 8.1.3 # 40 */ + x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_VOLENVSUSTAIN); + fluid_clip(x, 0.0f, 1.0f); + count = calculate_hold_decay_buffers(voice, GEN_VOLENVDECAY, GEN_KEYTOVOLENVDECAY, 1); /* 1 for decay */ + fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVDECAY, + count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f); + break; - case GEN_VOLENVRELEASE: /* SF2.01 section 8.1.3 # 38 */ - fluid_clip(x, FLUID_MIN_VOLENVRELEASE, 8000.0f); - count = 1 + NUM_BUFFERS_RELEASE(x); - fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVRELEASE, - count, 1.0f, -1.0f / count, 0.0f, 1.0f); - break; + case GEN_VOLENVRELEASE: /* SF2.01 section 8.1.3 # 38 */ + fluid_clip(x, FLUID_MIN_VOLENVRELEASE, 8000.0f); + count = 1 + NUM_BUFFERS_RELEASE(x); + fluid_voice_update_volenv(voice, TRUE, FLUID_VOICE_ENVRELEASE, + count, 1.0f, -1.0f / count, 0.0f, 1.0f); + break; /* Modulation envelope */ - case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */ - fluid_clip(x, -12000.0f, 5000.0f); - fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDELAY, - NUM_BUFFERS_DELAY(x), 0.0f, 0.0f, -1.0f, 1.0f); - break; + case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */ + fluid_clip(x, -12000.0f, 5000.0f); + fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDELAY, + NUM_BUFFERS_DELAY(x), 0.0f, 0.0f, -1.0f, 1.0f); + break; - case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */ - fluid_clip(x, -12000.0f, 8000.0f); - count = 1 + NUM_BUFFERS_ATTACK(x); - fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVATTACK, - count, 1.0f, 1.0f / count, -1.0f, 1.0f); - break; + case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */ + fluid_clip(x, -12000.0f, 8000.0f); + count = 1 + NUM_BUFFERS_ATTACK(x); + fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVATTACK, + count, 1.0f, 1.0f / count, -1.0f, 1.0f); + break; - case GEN_MODENVHOLD: /* SF2.01 section 8.1.3 # 27 */ - case GEN_KEYTOMODENVHOLD: /* SF2.01 section 8.1.3 # 31 */ - count = calculate_hold_decay_buffers(voice, GEN_MODENVHOLD, GEN_KEYTOMODENVHOLD, 0); /* 1 means: hold */ - fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVHOLD, - count, 1.0f, 0.0f, -1.0f, 2.0f); - break; + case GEN_MODENVHOLD: /* SF2.01 section 8.1.3 # 27 */ + case GEN_KEYTOMODENVHOLD: /* SF2.01 section 8.1.3 # 31 */ + count = calculate_hold_decay_buffers(voice, GEN_MODENVHOLD, GEN_KEYTOMODENVHOLD, 0); /* 1 means: hold */ + fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVHOLD, + count, 1.0f, 0.0f, -1.0f, 2.0f); + break; - case GEN_MODENVDECAY: /* SF 2.01 section 8.1.3 # 28 */ - case GEN_MODENVSUSTAIN: /* SF 2.01 section 8.1.3 # 29 */ - case GEN_KEYTOMODENVDECAY: /* SF 2.01 section 8.1.3 # 32 */ - count = calculate_hold_decay_buffers(voice, GEN_MODENVDECAY, GEN_KEYTOMODENVDECAY, 1); /* 1 for decay */ - x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_MODENVSUSTAIN); - fluid_clip(x, 0.0f, 1.0f); - fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDECAY, - count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f); - break; + case GEN_MODENVDECAY: /* SF 2.01 section 8.1.3 # 28 */ + case GEN_MODENVSUSTAIN: /* SF 2.01 section 8.1.3 # 29 */ + case GEN_KEYTOMODENVDECAY: /* SF 2.01 section 8.1.3 # 32 */ + count = calculate_hold_decay_buffers(voice, GEN_MODENVDECAY, GEN_KEYTOMODENVDECAY, 1); /* 1 for decay */ + x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_MODENVSUSTAIN); + fluid_clip(x, 0.0f, 1.0f); + fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVDECAY, + count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f); + break; - case GEN_MODENVRELEASE: /* SF 2.01 section 8.1.3 # 30 */ - fluid_clip(x, -12000.0f, 8000.0f); - count = 1 + NUM_BUFFERS_RELEASE(x); - fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVRELEASE, - count, 1.0f, -1.0f / count, 0.0f, 2.0f); + case GEN_MODENVRELEASE: /* SF 2.01 section 8.1.3 # 30 */ + fluid_clip(x, -12000.0f, 8000.0f); + count = 1 + NUM_BUFFERS_RELEASE(x); + fluid_voice_update_modenv(voice, TRUE, FLUID_VOICE_ENVRELEASE, + count, 1.0f, -1.0f / count, 0.0f, 2.0f); - break; + break; - } /* switch gen */ + } /* switch gen */ } /** @@ -1101,43 +1173,48 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) * - For every changed generator, convert its value to the correct * unit of the corresponding DSP parameter */ -int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl) +int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl) { - int i, k; - fluid_mod_t* mod; - int gen; - fluid_real_t modval; + int i, k; + fluid_mod_t *mod; + int gen; + fluid_real_t modval; -/* printf("Chan=%d, CC=%d, Src=%d, Val=%d\n", voice->channel->channum, cc, ctrl, val); */ + /* printf("Chan=%d, CC=%d, Src=%d, Val=%d\n", voice->channel->channum, cc, ctrl, val); */ - for (i = 0; i < voice->mod_count; i++) { + for(i = 0; i < voice->mod_count; i++) + { - mod = &voice->mod[i]; + mod = &voice->mod[i]; - /* step 1: find all the modulators that have the changed controller - * as input source. */ - if (fluid_mod_has_source(mod, cc, ctrl)) { + /* step 1: find all the modulators that have the changed controller + * as input source. */ + if(fluid_mod_has_source(mod, cc, ctrl)) + { - gen = fluid_mod_get_dest(mod); - modval = 0.0; + gen = fluid_mod_get_dest(mod); + modval = 0.0; - /* step 2: for every changed modulator, calculate the modulation - * value of its associated generator */ - for (k = 0; k < voice->mod_count; k++) { - if (fluid_mod_has_dest(&voice->mod[k], gen)) { - modval += fluid_mod_get_value(&voice->mod[k], voice->channel, voice); - } - } + /* step 2: for every changed modulator, calculate the modulation + * value of its associated generator */ + for(k = 0; k < voice->mod_count; k++) + { + if(fluid_mod_has_dest(&voice->mod[k], gen)) + { + modval += fluid_mod_get_value(&voice->mod[k], voice->channel, voice); + } + } - fluid_gen_set_mod(&voice->gen[gen], modval); + fluid_gen_set_mod(&voice->gen[gen], modval); - /* step 3: now that we have the new value of the generator, - * recalculate the parameter values that are derived from the - * generator */ - fluid_voice_update_param(voice, gen); + /* step 3: now that we have the new value of the generator, + * recalculate the parameter values that are derived from the + * generator */ + fluid_voice_update_param(voice, gen); + } } - } - return FLUID_OK; + + return FLUID_OK; } /** @@ -1145,43 +1222,46 @@ int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl) * ALL_CTRL_OFF MIDI message has been received (CC 121). * */ -int fluid_voice_modulate_all(fluid_voice_t* voice) +int fluid_voice_modulate_all(fluid_voice_t *voice) { - fluid_mod_t* mod; - int i, k, gen; - fluid_real_t modval; + fluid_mod_t *mod; + int i, k, gen; + fluid_real_t modval; - /* Loop through all the modulators. + /* Loop through all the modulators. - FIXME: we should loop through the set of generators instead of - the set of modulators. We risk to call 'fluid_voice_update_param' - several times for the same generator if several modulators have - that generator as destination. It's not an error, just a wast of - energy (think polution, global warming, unhappy musicians, - ...) */ + FIXME: we should loop through the set of generators instead of + the set of modulators. We risk to call 'fluid_voice_update_param' + several times for the same generator if several modulators have + that generator as destination. It's not an error, just a wast of + energy (think polution, global warming, unhappy musicians, + ...) */ - for (i = 0; i < voice->mod_count; i++) { + for(i = 0; i < voice->mod_count; i++) + { - mod = &voice->mod[i]; - gen = fluid_mod_get_dest(mod); - modval = 0.0; + mod = &voice->mod[i]; + gen = fluid_mod_get_dest(mod); + modval = 0.0; - /* Accumulate the modulation values of all the modulators with - * destination generator 'gen' */ - for (k = 0; k < voice->mod_count; k++) { - if (fluid_mod_has_dest(&voice->mod[k], gen)) { - modval += fluid_mod_get_value(&voice->mod[k], voice->channel, voice); - } + /* Accumulate the modulation values of all the modulators with + * destination generator 'gen' */ + for(k = 0; k < voice->mod_count; k++) + { + if(fluid_mod_has_dest(&voice->mod[k], gen)) + { + modval += fluid_mod_get_value(&voice->mod[k], voice->channel, voice); + } + } + + fluid_gen_set_mod(&voice->gen[gen], modval); + + /* Update the parameter values that are depend on the generator + * 'gen' */ + fluid_voice_update_param(voice, gen); } - fluid_gen_set_mod(&voice->gen[gen], modval); - - /* Update the parameter values that are depend on the generator - * 'gen' */ - fluid_voice_update_param(voice, gen); - } - - return FLUID_OK; + return FLUID_OK; } /** legato update functions --------------------------------------------------*/ @@ -1194,25 +1274,25 @@ int fluid_voice_modulate_all(fluid_voice_t* voice) * The function calculates pitch offset and increment, then these parameters * are send to the dsp. */ -void fluid_voice_update_portamento (fluid_voice_t* voice, int fromkey,int tokey) - +void fluid_voice_update_portamento(fluid_voice_t *voice, int fromkey, int tokey) + { - fluid_channel_t* channel= voice->channel; + fluid_channel_t *channel = voice->channel; - /* calculates pitch offset */ - fluid_real_t PitchBeg = fluid_voice_calculate_pitch(voice,fromkey); - fluid_real_t PitchEnd = fluid_voice_calculate_pitch(voice,tokey); - fluid_real_t pitchoffset = PitchBeg - PitchEnd; + /* calculates pitch offset */ + fluid_real_t PitchBeg = fluid_voice_calculate_pitch(voice, fromkey); + fluid_real_t PitchEnd = fluid_voice_calculate_pitch(voice, tokey); + fluid_real_t pitchoffset = PitchBeg - PitchEnd; - /* Calculates increment countinc */ - /* Increment is function of PortamentoTime (ms)*/ - unsigned int countinc = (unsigned int)(((fluid_real_t)voice->output_rate * - 0.001f * - (fluid_real_t)fluid_channel_portamentotime(channel)) / - (fluid_real_t)FLUID_BUFSIZE +0.5); + /* Calculates increment countinc */ + /* Increment is function of PortamentoTime (ms)*/ + unsigned int countinc = (unsigned int)(((fluid_real_t)voice->output_rate * + 0.001f * + (fluid_real_t)fluid_channel_portamentotime(channel)) / + (fluid_real_t)FLUID_BUFSIZE + 0.5); - /* Send portamento parameters to the voice dsp */ - UPDATE_RVOICE_GENERIC_IR(fluid_rvoice_set_portamento, voice->rvoice, countinc, pitchoffset); + /* Send portamento parameters to the voice dsp */ + UPDATE_RVOICE_GENERIC_IR(fluid_rvoice_set_portamento, voice->rvoice, countinc, pitchoffset); } /*---------------------------------------------------------------*/ @@ -1225,28 +1305,28 @@ void fluid_voice_update_portamento (fluid_voice_t* voice, int fromkey,int tokey) * @tokey the new key to be applied to this voice. * @vel the new velocity to be applied to this voice. */ -void fluid_voice_update_multi_retrigger_attack(fluid_voice_t* voice, - int tokey, int vel) +void fluid_voice_update_multi_retrigger_attack(fluid_voice_t *voice, + int tokey, int vel) { - voice->key = tokey; /* new note */ - voice->vel = vel; /* new velocity */ - /* Updates generators dependent of velocity */ - /* Modulates GEN_ATTENUATION (and others ) before calling - fluid_rvoice_multi_retrigger_attack().*/ - fluid_voice_modulate(voice, FALSE, FLUID_MOD_VELOCITY); - - /* Updates generator dependent of voice->key */ - fluid_voice_update_param(voice, GEN_KEYTOMODENVHOLD); - fluid_voice_update_param(voice, GEN_KEYTOMODENVDECAY); - fluid_voice_update_param(voice, GEN_KEYTOVOLENVHOLD); - fluid_voice_update_param(voice, GEN_KEYTOVOLENVDECAY); + voice->key = tokey; /* new note */ + voice->vel = vel; /* new velocity */ + /* Updates generators dependent of velocity */ + /* Modulates GEN_ATTENUATION (and others ) before calling + fluid_rvoice_multi_retrigger_attack().*/ + fluid_voice_modulate(voice, FALSE, FLUID_MOD_VELOCITY); - /* Updates pitch generator */ - fluid_voice_calculate_gen_pitch(voice); - fluid_voice_update_param(voice, GEN_PITCH); + /* Updates generator dependent of voice->key */ + fluid_voice_update_param(voice, GEN_KEYTOMODENVHOLD); + fluid_voice_update_param(voice, GEN_KEYTOMODENVDECAY); + fluid_voice_update_param(voice, GEN_KEYTOVOLENVHOLD); + fluid_voice_update_param(voice, GEN_KEYTOVOLENVDECAY); - /* updates adsr generator */ - UPDATE_RVOICE0(fluid_rvoice_multi_retrigger_attack); + /* Updates pitch generator */ + fluid_voice_calculate_gen_pitch(voice); + fluid_voice_update_param(voice, GEN_PITCH); + + /* updates adsr generator */ + UPDATE_RVOICE0(fluid_rvoice_multi_retrigger_attack); } /** end of legato update functions */ @@ -1258,41 +1338,45 @@ void fluid_voice_update_multi_retrigger_attack(fluid_voice_t* voice, fluid_voice_noteoff(). */ void -fluid_voice_release(fluid_voice_t* voice) +fluid_voice_release(fluid_voice_t *voice) { - unsigned int at_tick = fluid_channel_get_min_note_length_ticks (voice->channel); + unsigned int at_tick = fluid_channel_get_min_note_length_ticks(voice->channel); UPDATE_RVOICE_I1(fluid_rvoice_noteoff, at_tick); voice->has_noteoff = 1; // voice is marked as noteoff occured } /* * fluid_voice_noteoff - * + * * Sending a noteoff event will advance the envelopes to section 5 (release). * The function is convenient for polyphonic or monophonic note */ void -fluid_voice_noteoff(fluid_voice_t* voice) +fluid_voice_noteoff(fluid_voice_t *voice) { - fluid_channel_t* channel; + fluid_channel_t *channel; - fluid_profile(FLUID_PROF_VOICE_NOTE, voice->ref, 0, 0); + fluid_profile(FLUID_PROF_VOICE_NOTE, voice->ref, 0, 0); - channel = voice->channel; + channel = voice->channel; - /* Sustain a note under Sostenuto pedal */ - if (fluid_channel_sostenuto(channel) && - channel->sostenuto_orderid > voice->id) - { // Sostenuto depressed after note - voice->status = FLUID_VOICE_HELD_BY_SOSTENUTO; - } - /* Or sustain a note under Sustain pedal */ - else if (fluid_channel_sustained(channel)) { - voice->status = FLUID_VOICE_SUSTAINED; - } - /* Or force the voice to release stage */ - else - fluid_voice_release(voice); + /* Sustain a note under Sostenuto pedal */ + if(fluid_channel_sostenuto(channel) && + channel->sostenuto_orderid > voice->id) + { + // Sostenuto depressed after note + voice->status = FLUID_VOICE_HELD_BY_SOSTENUTO; + } + /* Or sustain a note under Sustain pedal */ + else if(fluid_channel_sustained(channel)) + { + voice->status = FLUID_VOICE_SUSTAINED; + } + /* Or force the voice to release stage */ + else + { + fluid_voice_release(voice); + } } /* @@ -1308,53 +1392,55 @@ fluid_voice_noteoff(fluid_voice_t* voice) */ int -fluid_voice_kill_excl(fluid_voice_t* voice){ +fluid_voice_kill_excl(fluid_voice_t *voice) +{ + + unsigned int at_tick; + + if(!fluid_voice_is_playing(voice)) + { + return FLUID_OK; + } + + /* Turn off the exclusive class information for this voice, + so that it doesn't get killed twice + */ + fluid_voice_gen_set(voice, GEN_EXCLUSIVECLASS, 0); + + /* Speed up the volume envelope */ + /* The value was found through listening tests with hi-hat samples. */ + fluid_voice_gen_set(voice, GEN_VOLENVRELEASE, -200); + fluid_voice_update_param(voice, GEN_VOLENVRELEASE); + + /* Speed up the modulation envelope */ + fluid_voice_gen_set(voice, GEN_MODENVRELEASE, -200); + fluid_voice_update_param(voice, GEN_MODENVRELEASE); + + at_tick = fluid_channel_get_min_note_length_ticks(voice->channel); + UPDATE_RVOICE_I1(fluid_rvoice_noteoff, at_tick); - unsigned int at_tick; - if (!fluid_voice_is_playing(voice)) { return FLUID_OK; - } - - /* Turn off the exclusive class information for this voice, - so that it doesn't get killed twice - */ - fluid_voice_gen_set(voice, GEN_EXCLUSIVECLASS, 0); - - /* Speed up the volume envelope */ - /* The value was found through listening tests with hi-hat samples. */ - fluid_voice_gen_set(voice, GEN_VOLENVRELEASE, -200); - fluid_voice_update_param(voice, GEN_VOLENVRELEASE); - - /* Speed up the modulation envelope */ - fluid_voice_gen_set(voice, GEN_MODENVRELEASE, -200); - fluid_voice_update_param(voice, GEN_MODENVRELEASE); - - at_tick = fluid_channel_get_min_note_length_ticks (voice->channel); - UPDATE_RVOICE_I1(fluid_rvoice_noteoff, at_tick); - - - return FLUID_OK; } /* - * Called by fluid_synth when the overflow rvoice can be reclaimed. + * Called by fluid_synth when the overflow rvoice can be reclaimed. */ -void fluid_voice_overflow_rvoice_finished(fluid_voice_t* voice) +void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice) { - voice->can_access_overflow_rvoice = 1; - fluid_voice_sample_unref(&voice->overflow_rvoice->dsp.sample); + voice->can_access_overflow_rvoice = 1; + fluid_voice_sample_unref(&voice->overflow_rvoice->dsp.sample); } /* * fluid_voice_off - * + * * Force the voice into finished stage. Useful anywhere a voice * needs to be cancelled from MIDI API. */ -void fluid_voice_off(fluid_voice_t* voice) +void fluid_voice_off(fluid_voice_t *voice) { - UPDATE_RVOICE0(fluid_rvoice_voiceoff); /* request to finish the voice */ + UPDATE_RVOICE0(fluid_rvoice_voiceoff); /* request to finish the voice */ } /* @@ -1365,23 +1451,25 @@ void fluid_voice_off(fluid_voice_t* voice) * DSP loop, i.e. contrary part to fluid_voice_start(). */ void -fluid_voice_stop(fluid_voice_t* voice) +fluid_voice_stop(fluid_voice_t *voice) { - fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref, 0, 0); + fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref, 0, 0); - voice->chan = NO_CHANNEL; - - if (voice->can_access_rvoice) - fluid_voice_sample_unref(&voice->rvoice->dsp.sample); + voice->chan = NO_CHANNEL; - voice->status = FLUID_VOICE_OFF; - voice->has_noteoff = 1; + if(voice->can_access_rvoice) + { + fluid_voice_sample_unref(&voice->rvoice->dsp.sample); + } - /* Decrement the reference count of the sample. */ - fluid_voice_sample_unref(&voice->sample); + voice->status = FLUID_VOICE_OFF; + voice->has_noteoff = 1; - /* Decrement voice count */ - voice->channel->synth->active_voice_count--; + /* Decrement the reference count of the sample. */ + fluid_voice_sample_unref(&voice->sample); + + /* Decrement voice count */ + voice->channel->synth->active_voice_count--; } /** @@ -1395,62 +1483,70 @@ fluid_voice_stop(fluid_voice_t* voice) * exist so don't check. */ void -fluid_voice_add_mod(fluid_voice_t* voice, fluid_mod_t* mod, int mode) +fluid_voice_add_mod(fluid_voice_t *voice, fluid_mod_t *mod, int mode) { - int i; + int i; - /* - * Some soundfonts come with a huge number of non-standard - * controllers, because they have been designed for one particular - * sound card. Discard them, maybe print a warning. - */ + /* + * Some soundfonts come with a huge number of non-standard + * controllers, because they have been designed for one particular + * sound card. Discard them, maybe print a warning. + */ - if (((mod->flags1 & FLUID_MOD_CC) == 0) - && ((mod->src1 != FLUID_MOD_NONE) /* SF2.01 section 8.2.1: Constant value */ - && (mod->src1 != FLUID_MOD_VELOCITY) /* Note-on velocity */ - && (mod->src1 != FLUID_MOD_KEY) /* Note-on key number */ - && (mod->src1 != FLUID_MOD_KEYPRESSURE) /* Poly pressure */ - && (mod->src1 != FLUID_MOD_CHANNELPRESSURE) /* Channel pressure */ - && (mod->src1 != FLUID_MOD_PITCHWHEEL) /* Pitch wheel */ - && (mod->src1 != FLUID_MOD_PITCHWHEELSENS)))/* Pitch wheel sensitivity */ - { - FLUID_LOG(FLUID_WARN, "Ignoring invalid controller, using non-CC source %i.", mod->src1); - return; - } - - if (mode == FLUID_VOICE_ADD) { - - /* if identical modulator exists, add them */ - for (i = 0; i < voice->mod_count; i++) { - if (fluid_mod_test_identity(&voice->mod[i], mod)) { - // printf("Adding modulator...\n"); - voice->mod[i].amount += mod->amount; - return; - } + if(((mod->flags1 & FLUID_MOD_CC) == 0) + && ((mod->src1 != FLUID_MOD_NONE) /* SF2.01 section 8.2.1: Constant value */ + && (mod->src1 != FLUID_MOD_VELOCITY) /* Note-on velocity */ + && (mod->src1 != FLUID_MOD_KEY) /* Note-on key number */ + && (mod->src1 != FLUID_MOD_KEYPRESSURE) /* Poly pressure */ + && (mod->src1 != FLUID_MOD_CHANNELPRESSURE) /* Channel pressure */ + && (mod->src1 != FLUID_MOD_PITCHWHEEL) /* Pitch wheel */ + && (mod->src1 != FLUID_MOD_PITCHWHEELSENS)))/* Pitch wheel sensitivity */ + { + FLUID_LOG(FLUID_WARN, "Ignoring invalid controller, using non-CC source %i.", mod->src1); + return; } - } else if (mode == FLUID_VOICE_OVERWRITE) { + if(mode == FLUID_VOICE_ADD) + { + + /* if identical modulator exists, add them */ + for(i = 0; i < voice->mod_count; i++) + { + if(fluid_mod_test_identity(&voice->mod[i], mod)) + { + // printf("Adding modulator...\n"); + voice->mod[i].amount += mod->amount; + return; + } + } - /* if identical modulator exists, replace it (only the amount has to be changed) */ - for (i = 0; i < voice->mod_count; i++) { - if (fluid_mod_test_identity(&voice->mod[i], mod)) { - // printf("Replacing modulator...amount is %f\n",mod->amount); - voice->mod[i].amount = mod->amount; - return; - } } - } + else if(mode == FLUID_VOICE_OVERWRITE) + { - /* Add a new modulator (No existing modulator to add / overwrite). - Also, default modulators (FLUID_VOICE_DEFAULT) are added without - checking, if the same modulator already exists. */ - if (voice->mod_count < FLUID_NUM_MOD) { - fluid_mod_clone(&voice->mod[voice->mod_count++], mod); - } - else - { - FLUID_LOG(FLUID_WARN, "Voice %i has more modulators than supported, ignoring.", voice->id); - } + /* if identical modulator exists, replace it (only the amount has to be changed) */ + for(i = 0; i < voice->mod_count; i++) + { + if(fluid_mod_test_identity(&voice->mod[i], mod)) + { + // printf("Replacing modulator...amount is %f\n",mod->amount); + voice->mod[i].amount = mod->amount; + return; + } + } + } + + /* Add a new modulator (No existing modulator to add / overwrite). + Also, default modulators (FLUID_VOICE_DEFAULT) are added without + checking, if the same modulator already exists. */ + if(voice->mod_count < FLUID_NUM_MOD) + { + fluid_mod_clone(&voice->mod[voice->mod_count++], mod); + } + else + { + FLUID_LOG(FLUID_WARN, "Voice %i has more modulators than supported, ignoring.", voice->id); + } } /** @@ -1469,9 +1565,9 @@ fluid_voice_add_mod(fluid_voice_t* voice, fluid_mod_t* mod, int mode) * * Otherwise the voice has finished playing. */ -unsigned int fluid_voice_get_id(const fluid_voice_t* voice) +unsigned int fluid_voice_get_id(const fluid_voice_t *voice) { - return voice->id; + return voice->id; } /** @@ -1479,11 +1575,11 @@ unsigned int fluid_voice_get_id(const fluid_voice_t* voice) * @param voice Voice instance * @return TRUE if playing, FALSE otherwise */ -int fluid_voice_is_playing(const fluid_voice_t* voice) +int fluid_voice_is_playing(const fluid_voice_t *voice) { - return (voice->status == FLUID_VOICE_ON) - || fluid_voice_is_sustained(voice) - || fluid_voice_is_sostenuto(voice); + return (voice->status == FLUID_VOICE_ON) + || fluid_voice_is_sustained(voice) + || fluid_voice_is_sostenuto(voice); } @@ -1493,9 +1589,9 @@ int fluid_voice_is_playing(const fluid_voice_t* voice) * @return TRUE if on, FALSE otherwise * @since 1.1.7 */ -int fluid_voice_is_on(const fluid_voice_t* voice) +int fluid_voice_is_on(const fluid_voice_t *voice) { - return (voice->status == FLUID_VOICE_ON && !voice->has_noteoff); + return (voice->status == FLUID_VOICE_ON && !voice->has_noteoff); } /** @@ -1504,9 +1600,9 @@ int fluid_voice_is_on(const fluid_voice_t* voice) * @return TRUE if sustained, FALSE otherwise * @since 1.1.7 */ -int fluid_voice_is_sustained(const fluid_voice_t* voice) +int fluid_voice_is_sustained(const fluid_voice_t *voice) { - return (voice->status == FLUID_VOICE_SUSTAINED); + return (voice->status == FLUID_VOICE_SUSTAINED); } /** @@ -1515,9 +1611,9 @@ int fluid_voice_is_sustained(const fluid_voice_t* voice) * @return TRUE if sostenuto, FALSE otherwise * @since 1.1.7 */ -int fluid_voice_is_sostenuto(const fluid_voice_t* voice) +int fluid_voice_is_sostenuto(const fluid_voice_t *voice) { - return (voice->status == FLUID_VOICE_HELD_BY_SOSTENUTO); + return (voice->status == FLUID_VOICE_HELD_BY_SOSTENUTO); } /** @@ -1526,9 +1622,9 @@ int fluid_voice_is_sostenuto(const fluid_voice_t* voice) * @return The channel assigned to this voice * @since 1.1.7 */ -int fluid_voice_get_channel(const fluid_voice_t* voice) +int fluid_voice_get_channel(const fluid_voice_t *voice) { - return voice->chan; + return voice->chan; } /** @@ -1539,10 +1635,11 @@ int fluid_voice_get_channel(const fluid_voice_t* voice) * @return The midi key this voice is playing at * @since 1.1.7 */ -int fluid_voice_get_actual_key(const fluid_voice_t* voice) +int fluid_voice_get_actual_key(const fluid_voice_t *voice) { fluid_real_t x = fluid_voice_gen_value(voice, GEN_KEYNUM); - if (x >= 0) + + if(x >= 0) { return (int)x; } @@ -1559,9 +1656,9 @@ int fluid_voice_get_actual_key(const fluid_voice_t* voice) * @return The midi key of the noteon event that originally turned on this voice * @since 1.1.7 */ -int fluid_voice_get_key(const fluid_voice_t* voice) +int fluid_voice_get_key(const fluid_voice_t *voice) { - return voice->key; + return voice->key; } /** @@ -1572,10 +1669,11 @@ int fluid_voice_get_key(const fluid_voice_t* voice) * @return The midi velocity this voice is playing at * @since 1.1.7 */ -int fluid_voice_get_actual_velocity(const fluid_voice_t* voice) +int fluid_voice_get_actual_velocity(const fluid_voice_t *voice) { fluid_real_t x = fluid_voice_gen_value(voice, GEN_VELOCITY); - if (x > 0) + + if(x > 0) { return (int)x; } @@ -1592,9 +1690,9 @@ int fluid_voice_get_actual_velocity(const fluid_voice_t* voice) * @return The midi velocity which originally turned on this voice * @since 1.1.7 */ -int fluid_voice_get_velocity(const fluid_voice_t* voice) +int fluid_voice_get_velocity(const fluid_voice_t *voice) { - return voice->vel; + return voice->vel; } /* @@ -1610,18 +1708,19 @@ int fluid_voice_get_velocity(const fluid_voice_t* voice) * voice->attenuation has to be initialized. */ static fluid_real_t -fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice) +fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t *voice) { int i; - fluid_mod_t* mod; - fluid_real_t possible_att_reduction_cB=0; + fluid_mod_t *mod; + fluid_real_t possible_att_reduction_cB = 0; fluid_real_t lower_bound; - for (i = 0; i < voice->mod_count; i++) { + for(i = 0; i < voice->mod_count; i++) + { mod = &voice->mod[i]; /* Modulator has attenuation as target and can change over time? */ - if ((mod->dest == GEN_ATTENUATION) + if((mod->dest == GEN_ATTENUATION) && ((mod->flags1 & FLUID_MOD_CC) || (mod->flags2 & FLUID_MOD_CC) || (mod->src1 == FLUID_MOD_CHANNELPRESSURE) @@ -1629,18 +1728,22 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice) || (mod->src1 == FLUID_MOD_PITCHWHEEL) || (mod->src2 == FLUID_MOD_CHANNELPRESSURE) || (mod->src2 == FLUID_MOD_KEYPRESSURE) - || (mod->src2 == FLUID_MOD_PITCHWHEEL))) { + || (mod->src2 == FLUID_MOD_PITCHWHEEL))) + { fluid_real_t current_val = fluid_mod_get_value(mod, voice->channel, voice); fluid_real_t v = fabs(mod->amount); - if ((mod->src1 == FLUID_MOD_PITCHWHEEL) + if((mod->src1 == FLUID_MOD_PITCHWHEEL) || (mod->flags1 & FLUID_MOD_BIPOLAR) || (mod->flags2 & FLUID_MOD_BIPOLAR) - || (mod->amount < 0)) { + || (mod->amount < 0)) + { /* Can this modulator produce a negative contribution? */ v *= -1.0; - } else { + } + else + { /* No negative value possible. But still, the minimum contribution is 0. */ v = 0; } @@ -1650,56 +1753,60 @@ fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice) * - min_val=-4000 * - possible_att_reduction_cB += 4100 */ - if (current_val > v){ + if(current_val > v) + { possible_att_reduction_cB += (current_val - v); } } } - lower_bound = voice->attenuation-possible_att_reduction_cB; + lower_bound = voice->attenuation - possible_att_reduction_cB; /* SF2.01 specs do not allow negative attenuation */ - if (lower_bound < 0) { + if(lower_bound < 0) + { lower_bound = 0; } + return lower_bound; } -int fluid_voice_set_param(fluid_voice_t* voice, int gen, fluid_real_t nrpn_value, int abs) +int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t nrpn_value, int abs) { - voice->gen[gen].nrpn = nrpn_value; - voice->gen[gen].flags = (abs)? GEN_ABS_NRPN : GEN_SET; - fluid_voice_update_param(voice, gen); - return FLUID_OK; + voice->gen[gen].nrpn = nrpn_value; + voice->gen[gen].flags = (abs) ? GEN_ABS_NRPN : GEN_SET; + fluid_voice_update_param(voice, gen); + return FLUID_OK; } -int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain) +int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain) { - fluid_real_t left, right, reverb, chorus; - - /* avoid division by zero*/ - if (gain < 0.0000001){ - gain = 0.0000001; - } + fluid_real_t left, right, reverb, chorus; - voice->synth_gain = gain; - left = fluid_voice_calculate_gain_amplitude(voice, - fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)); - right = fluid_voice_calculate_gain_amplitude(voice, - fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)); - reverb = fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send); - chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send); + /* avoid division by zero*/ + if(gain < 0.0000001) + { + gain = 0.0000001; + } - UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, gain); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, left); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, right); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, reverb); - UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, chorus); + voice->synth_gain = gain; + left = fluid_voice_calculate_gain_amplitude(voice, + fluid_pan(voice->pan, 1) * fluid_balance(voice->balance, 1)); + right = fluid_voice_calculate_gain_amplitude(voice, + fluid_pan(voice->pan, 0) * fluid_balance(voice->balance, 0)); + reverb = fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send); + chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send); - return FLUID_OK; + UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, gain); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 0, left); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 1, right); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 2, reverb); + UPDATE_RVOICE_BUFFERS_AMP(fluid_rvoice_buffers_set_amp, 3, chorus); + + return FLUID_OK; } /* - Scan the loop @@ -1719,129 +1826,161 @@ int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain) * fluid_voice_optimize_sample() on each sample once. */ int -fluid_voice_optimize_sample(fluid_sample_t* s) +fluid_voice_optimize_sample(fluid_sample_t *s) { - int32_t peak_max = 0; - int32_t peak_min = 0; - int32_t peak; - fluid_real_t normalized_amplitude_during_loop; - double result; - unsigned int i; + int32_t peak_max = 0; + int32_t peak_min = 0; + int32_t peak; + fluid_real_t normalized_amplitude_during_loop; + double result; + unsigned int i; - /* ignore disabled samples */ - if (s->start == s->end) return (FLUID_OK); - - if (!s->amplitude_that_reaches_noise_floor_is_valid) { /* Only once */ - /* Scan the loop */ - for (i = s->loopstart; i < s->loopend; i++){ - int32_t val = fluid_rvoice_get_sample(s->data, s->data24, i); - - if (val > peak_max) { - peak_max = val; - } else if (val < peak_min) { - peak_min = val; - } + /* ignore disabled samples */ + if(s->start == s->end) + { + return (FLUID_OK); } - /* Determine the peak level */ - if (peak_max > -peak_min) { - peak = peak_max; - } else { - peak = -peak_min; - } - if (peak == 0){ - /* Avoid division by zero */ - peak = 1; - } + if(!s->amplitude_that_reaches_noise_floor_is_valid) /* Only once */ + { + /* Scan the loop */ + for(i = s->loopstart; i < s->loopend; i++) + { + int32_t val = fluid_rvoice_get_sample(s->data, s->data24, i); - /* Calculate what factor will make the loop inaudible - * For example: Take a peak of 3277 (10 % of 32768). The - * normalized amplitude is 0.1 (10 % of 32768). An amplitude - * factor of 0.0001 (as opposed to the default 0.00001) will - * drop this sample to the noise floor. - */ + if(val > peak_max) + { + peak_max = val; + } + else if(val < peak_min) + { + peak_min = val; + } + } - /* 16 bits => 96+4=100 dB dynamic range => 0.00001 */ - normalized_amplitude_during_loop = ((fluid_real_t)peak)/ (INT24_MAX * 1.0f); - result = FLUID_NOISE_FLOOR / normalized_amplitude_during_loop; + /* Determine the peak level */ + if(peak_max > -peak_min) + { + peak = peak_max; + } + else + { + peak = -peak_min; + } - /* Store in sample */ - s->amplitude_that_reaches_noise_floor = (double)result; - s->amplitude_that_reaches_noise_floor_is_valid = 1; + if(peak == 0) + { + /* Avoid division by zero */ + peak = 1; + } + + /* Calculate what factor will make the loop inaudible + * For example: Take a peak of 3277 (10 % of 32768). The + * normalized amplitude is 0.1 (10 % of 32768). An amplitude + * factor of 0.0001 (as opposed to the default 0.00001) will + * drop this sample to the noise floor. + */ + + /* 16 bits => 96+4=100 dB dynamic range => 0.00001 */ + normalized_amplitude_during_loop = ((fluid_real_t)peak) / (INT24_MAX * 1.0f); + result = FLUID_NOISE_FLOOR / normalized_amplitude_during_loop; + + /* Store in sample */ + s->amplitude_that_reaches_noise_floor = (double)result; + s->amplitude_that_reaches_noise_floor_is_valid = 1; #if 0 - printf("Sample peak detection: factor %f\n", (double)result); + printf("Sample peak detection: factor %f\n", (double)result); #endif - } - return FLUID_OK; + } + + return FLUID_OK; } float -fluid_voice_get_overflow_prio(fluid_voice_t* voice, - fluid_overflow_prio_t* score, - unsigned int cur_time) +fluid_voice_get_overflow_prio(fluid_voice_t *voice, + fluid_overflow_prio_t *score, + unsigned int cur_time) { - float this_voice_prio = 0; - int channel; + float this_voice_prio = 0; + int channel; - /* Are we already overflowing? */ - if (!voice->can_access_overflow_rvoice) { - return OVERFLOW_PRIO_CANNOT_KILL; - } + /* Are we already overflowing? */ + if(!voice->can_access_overflow_rvoice) + { + return OVERFLOW_PRIO_CANNOT_KILL; + } - /* Is this voice on the drum channel? - * Then it is very important. - * Also skip the released and sustained scores. - */ - if (voice->channel->channel_type == CHANNEL_TYPE_DRUM) { - this_voice_prio += score->percussion; - } else if (voice->has_noteoff) { - /* Noteoff has */ - this_voice_prio += score->released; - } else if (fluid_voice_is_sustained(voice) || fluid_voice_is_sostenuto(voice)) { - /* This voice is still active, since the sustain pedal is held down. - * Consider it less important than non-sustained channels. - * This decision is somehow subjective. But usually the sustain pedal - * is used to play 'more-voices-than-fingers', so it shouldn't hurt - * if we kill one voice. + /* Is this voice on the drum channel? + * Then it is very important. + * Also skip the released and sustained scores. */ - this_voice_prio += score->sustained; - } - - /* We are not enthusiastic about releasing voices, which have just been started. - * Otherwise hitting a chord may result in killing notes belonging to that very same - * chord. So give newer voices a higher score. */ - if (score->age) { - cur_time -= voice->start_time; - if (cur_time < 1) { - cur_time = 1; // Avoid div by zero + if(voice->channel->channel_type == CHANNEL_TYPE_DRUM) + { + this_voice_prio += score->percussion; } - this_voice_prio += (score->age * voice->output_rate) / cur_time; - } - - /* take a rough estimate of loudness into account. Louder voices are more important. */ - if (score->volume) { - fluid_real_t a = voice->attenuation; - if (voice->has_noteoff) { - // FIXME: Should take into account where on the envelope we are...? + else if(voice->has_noteoff) + { + /* Noteoff has */ + this_voice_prio += score->released; } - if (a < 0.1) { - a = 0.1; // Avoid div by zero + else if(fluid_voice_is_sustained(voice) || fluid_voice_is_sostenuto(voice)) + { + /* This voice is still active, since the sustain pedal is held down. + * Consider it less important than non-sustained channels. + * This decision is somehow subjective. But usually the sustain pedal + * is used to play 'more-voices-than-fingers', so it shouldn't hurt + * if we kill one voice. + */ + this_voice_prio += score->sustained; } - this_voice_prio += score->volume / a; - } - /* Check if this voice is on an important channel. If so, then add the - * score for important channels */ - channel = fluid_voice_get_channel(voice); - if (channel < score->num_important_channels && score->important_channels[channel]) { - this_voice_prio += score->important; - } - - return this_voice_prio; + /* We are not enthusiastic about releasing voices, which have just been started. + * Otherwise hitting a chord may result in killing notes belonging to that very same + * chord. So give newer voices a higher score. */ + if(score->age) + { + cur_time -= voice->start_time; + + if(cur_time < 1) + { + cur_time = 1; // Avoid div by zero + } + + this_voice_prio += (score->age * voice->output_rate) / cur_time; + } + + /* take a rough estimate of loudness into account. Louder voices are more important. */ + if(score->volume) + { + fluid_real_t a = voice->attenuation; + + if(voice->has_noteoff) + { + // FIXME: Should take into account where on the envelope we are...? + } + + if(a < 0.1) + { + a = 0.1; // Avoid div by zero + } + + this_voice_prio += score->volume / a; + } + + /* Check if this voice is on an important channel. If so, then add the + * score for important channels */ + channel = fluid_voice_get_channel(voice); + + if(channel < score->num_important_channels && score->important_channels[channel]) + { + this_voice_prio += score->important; + } + + return this_voice_prio; } -void fluid_voice_set_custom_filter(fluid_voice_t* voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags) +void fluid_voice_set_custom_filter(fluid_voice_t *voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags) { UPDATE_RVOICE_GENERIC_I2(fluid_iir_filter_init, &voice->rvoice->resonant_custom_filter, type, flags); } diff --git a/src/synth/fluid_voice.h b/src/synth/fluid_voice.h index 2e96e4a3..6038a1a9 100644 --- a/src/synth/fluid_voice.h +++ b/src/synth/fluid_voice.h @@ -36,25 +36,25 @@ typedef struct _fluid_overflow_prio_t fluid_overflow_prio_t; -struct _fluid_overflow_prio_t +struct _fluid_overflow_prio_t { - float percussion; /**< Is this voice on the drum channel? Then add this score */ - float released; /**< Is this voice in release stage? Then add this score (usually negative) */ - float sustained; /**< Is this voice sustained? Then add this score (usually negative) */ - float volume; /**< Multiply current (or future) volume (a value between 0 and 1) */ - float age; /**< This score will be divided by the number of seconds the voice has lasted */ - float important; /**< This score will be added to all important channels */ - char *important_channels; /**< "important" flags indexed by MIDI channel number */ - int num_important_channels; /**< Number of elements in the important_channels array */ + float percussion; /**< Is this voice on the drum channel? Then add this score */ + float released; /**< Is this voice in release stage? Then add this score (usually negative) */ + float sustained; /**< Is this voice sustained? Then add this score (usually negative) */ + float volume; /**< Multiply current (or future) volume (a value between 0 and 1) */ + float age; /**< This score will be divided by the number of seconds the voice has lasted */ + float important; /**< This score will be added to all important channels */ + char *important_channels; /**< "important" flags indexed by MIDI channel number */ + int num_important_channels; /**< Number of elements in the important_channels array */ }; enum fluid_voice_status { - FLUID_VOICE_CLEAN, - FLUID_VOICE_ON, - FLUID_VOICE_SUSTAINED, /* Sustained by Sustain pedal */ - FLUID_VOICE_HELD_BY_SOSTENUTO, /* Sustained by Sostenuto pedal */ - FLUID_VOICE_OFF + FLUID_VOICE_CLEAN, + FLUID_VOICE_ON, + FLUID_VOICE_SUSTAINED, /* Sustained by Sustain pedal */ + FLUID_VOICE_HELD_BY_SOSTENUTO, /* Sustained by Sostenuto pedal */ + FLUID_VOICE_OFF }; @@ -63,125 +63,125 @@ enum fluid_voice_status */ struct _fluid_voice_t { - unsigned int id; /* the id is incremented for every new noteon. + unsigned int id; /* the id is incremented for every new noteon. it's used for noteoff's */ - unsigned char status; - unsigned char chan; /* the channel number, quick access for channel messages */ - unsigned char key; /* the key of the noteon event, quick access for noteoff */ - unsigned char vel; /* the velocity of the noteon event */ - fluid_channel_t* channel; - fluid_rvoice_eventhandler_t* eventhandler; - fluid_zone_range_t * zone_range; /* instrument zone range*/ - fluid_sample_t* sample; /* Pointer to sample (dupe in rvoice) */ - - unsigned int start_time; - int mod_count; - fluid_mod_t mod[FLUID_NUM_MOD]; - fluid_gen_t gen[GEN_LAST]; + unsigned char status; + unsigned char chan; /* the channel number, quick access for channel messages */ + unsigned char key; /* the key of the noteon event, quick access for noteoff */ + unsigned char vel; /* the velocity of the noteon event */ + fluid_channel_t *channel; + fluid_rvoice_eventhandler_t *eventhandler; + fluid_zone_range_t *zone_range; /* instrument zone range*/ + fluid_sample_t *sample; /* Pointer to sample (dupe in rvoice) */ - /* basic parameters */ - fluid_real_t output_rate; /* the sample rate of the synthesizer (dupe in rvoice) */ + unsigned int start_time; + int mod_count; + fluid_mod_t mod[FLUID_NUM_MOD]; + fluid_gen_t gen[GEN_LAST]; - /* basic parameters */ - fluid_real_t pitch; /* the pitch in midicents (dupe in rvoice) */ - fluid_real_t attenuation; /* the attenuation in centibels (dupe in rvoice) */ - fluid_real_t root_pitch; + /* basic parameters */ + fluid_real_t output_rate; /* the sample rate of the synthesizer (dupe in rvoice) */ - /* master gain (dupe in rvoice) */ - fluid_real_t synth_gain; + /* basic parameters */ + fluid_real_t pitch; /* the pitch in midicents (dupe in rvoice) */ + fluid_real_t attenuation; /* the attenuation in centibels (dupe in rvoice) */ + fluid_real_t root_pitch; - /* pan */ - fluid_real_t pan; + /* master gain (dupe in rvoice) */ + fluid_real_t synth_gain; + + /* pan */ + fluid_real_t pan; /* balance */ fluid_real_t balance; - /* reverb */ - fluid_real_t reverb_send; + /* reverb */ + fluid_real_t reverb_send; - /* chorus */ - fluid_real_t chorus_send; + /* chorus */ + fluid_real_t chorus_send; - /* rvoice control */ - fluid_rvoice_t* rvoice; - fluid_rvoice_t* overflow_rvoice; /* Used temporarily and only in overflow situations */ - char can_access_rvoice; /* False if rvoice is being rendered in separate thread */ - char can_access_overflow_rvoice; /* False if overflow_rvoice is being rendered in separate thread */ - char has_noteoff; /* Flag set when noteoff has been sent */ + /* rvoice control */ + fluid_rvoice_t *rvoice; + fluid_rvoice_t *overflow_rvoice; /* Used temporarily and only in overflow situations */ + char can_access_rvoice; /* False if rvoice is being rendered in separate thread */ + char can_access_overflow_rvoice; /* False if overflow_rvoice is being rendered in separate thread */ + char has_noteoff; /* Flag set when noteoff has been sent */ #ifdef WITH_PROFILING - /* for debugging */ - double ref; + /* for debugging */ + double ref; #endif }; -fluid_voice_t* new_fluid_voice(fluid_rvoice_eventhandler_t* handler, fluid_real_t output_rate); -void delete_fluid_voice(fluid_voice_t* voice); +fluid_voice_t *new_fluid_voice(fluid_rvoice_eventhandler_t *handler, fluid_real_t output_rate); +void delete_fluid_voice(fluid_voice_t *voice); -void fluid_voice_start(fluid_voice_t* voice); -void fluid_voice_calculate_gen_pitch(fluid_voice_t* voice); +void fluid_voice_start(fluid_voice_t *voice); +void fluid_voice_calculate_gen_pitch(fluid_voice_t *voice); -int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, - fluid_zone_range_t *inst_zone_range, - fluid_channel_t* channel, int key, int vel, - unsigned int id, unsigned int time, fluid_real_t gain); +int fluid_voice_init(fluid_voice_t *voice, fluid_sample_t *sample, + fluid_zone_range_t *inst_zone_range, + fluid_channel_t *channel, int key, int vel, + unsigned int id, unsigned int time, fluid_real_t gain); -int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl); -int fluid_voice_modulate_all(fluid_voice_t* voice); +int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl); +int fluid_voice_modulate_all(fluid_voice_t *voice); /** Set the NRPN value of a generator. */ -int fluid_voice_set_param(fluid_voice_t* voice, int gen, fluid_real_t value, int abs); +int fluid_voice_set_param(fluid_voice_t *voice, int gen, fluid_real_t value, int abs); /** Set the gain. */ -int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain); +int fluid_voice_set_gain(fluid_voice_t *voice, fluid_real_t gain); -void fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value); +void fluid_voice_set_output_rate(fluid_voice_t *voice, fluid_real_t value); /** Update all the synthesis parameters, which depend on generator 'gen'. This is only necessary after changing a generator of an already operating voice. Most applications will not need this function.*/ -void fluid_voice_update_param(fluid_voice_t* voice, int gen); +void fluid_voice_update_param(fluid_voice_t *voice, int gen); /** legato modes */ /* force in the attack section for legato mode multi_retrigger: 1 */ -void fluid_voice_update_multi_retrigger_attack(fluid_voice_t* voice,int tokey, int vel); +void fluid_voice_update_multi_retrigger_attack(fluid_voice_t *voice, int tokey, int vel); /* Update portamento parameter */ -void fluid_voice_update_portamento (fluid_voice_t* voice, int fromkey, int tokey); +void fluid_voice_update_portamento(fluid_voice_t *voice, int fromkey, int tokey); -void fluid_voice_release(fluid_voice_t* voice); -void fluid_voice_noteoff(fluid_voice_t* voice); -void fluid_voice_off(fluid_voice_t* voice); -void fluid_voice_stop(fluid_voice_t* voice); -void fluid_voice_overflow_rvoice_finished(fluid_voice_t* voice); +void fluid_voice_release(fluid_voice_t *voice); +void fluid_voice_noteoff(fluid_voice_t *voice); +void fluid_voice_off(fluid_voice_t *voice); +void fluid_voice_stop(fluid_voice_t *voice); +void fluid_voice_overflow_rvoice_finished(fluid_voice_t *voice); -int fluid_voice_kill_excl(fluid_voice_t* voice); -float fluid_voice_get_overflow_prio(fluid_voice_t* voice, - fluid_overflow_prio_t* score, - unsigned int cur_time); +int fluid_voice_kill_excl(fluid_voice_t *voice); +float fluid_voice_get_overflow_prio(fluid_voice_t *voice, + fluid_overflow_prio_t *score, + unsigned int cur_time); #define OVERFLOW_PRIO_CANNOT_KILL 999999. /** * Locks the rvoice for rendering, so it can't be modified directly */ -static FLUID_INLINE void -fluid_voice_lock_rvoice(fluid_voice_t* voice) +static FLUID_INLINE void +fluid_voice_lock_rvoice(fluid_voice_t *voice) { - voice->can_access_rvoice = 0; + voice->can_access_rvoice = 0; } /** * Unlocks the rvoice for rendering, so it can be modified directly */ -static FLUID_INLINE void -fluid_voice_unlock_rvoice(fluid_voice_t* voice) +static FLUID_INLINE void +fluid_voice_unlock_rvoice(fluid_voice_t *voice) { - voice->can_access_rvoice = 1; + voice->can_access_rvoice = 1; } #define _AVAILABLE(voice) ((voice)->can_access_rvoice && \ @@ -190,8 +190,8 @@ fluid_voice_unlock_rvoice(fluid_voice_t* voice) #define _SAMPLEMODE(voice) ((int)(voice)->gen[GEN_SAMPLEMODE].val) -fluid_real_t fluid_voice_gen_value(const fluid_voice_t* voice, int num); -void fluid_voice_set_custom_filter(fluid_voice_t* voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags); +fluid_real_t fluid_voice_gen_value(const fluid_voice_t *voice, int num); +void fluid_voice_set_custom_filter(fluid_voice_t *voice, enum fluid_iir_filter_type type, enum fluid_iir_filter_flags flags); #endif /* _FLUID_VOICE_H */ diff --git a/src/utils/fluid_conv.c b/src/utils/fluid_conv.c index fbf61da6..555dd613 100644 --- a/src/utils/fluid_conv.c +++ b/src/utils/fluid_conv.c @@ -40,47 +40,52 @@ static fluid_real_t fluid_pan_tab[FLUID_PAN_SIZE]; void fluid_conversion_config(void) { - int i; - double x; + int i; + double x; - for (i = 0; i < FLUID_CENTS_HZ_SIZE; i++) { - fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0); - } + for(i = 0; i < FLUID_CENTS_HZ_SIZE; i++) + { + fluid_ct2hz_tab[i] = (fluid_real_t) pow(2.0, (double) i / 1200.0); + } - /* centibels to amplitude conversion - * Note: SF2.01 section 8.1.3: Initial attenuation range is - * between 0 and 144 dB. Therefore a negative attenuation is - * not allowed. - */ - for (i = 0; i < FLUID_CB_AMP_SIZE; i++) { - fluid_cb2amp_tab[i] = (fluid_real_t) pow(10.0, (double) i / -200.0); - } + /* centibels to amplitude conversion + * Note: SF2.01 section 8.1.3: Initial attenuation range is + * between 0 and 144 dB. Therefore a negative attenuation is + * not allowed. + */ + for(i = 0; i < FLUID_CB_AMP_SIZE; i++) + { + fluid_cb2amp_tab[i] = (fluid_real_t) pow(10.0, (double) i / -200.0); + } - /* initialize the conversion tables (see fluid_mod.c - fluid_mod_get_value cases 4 and 8) */ + /* initialize the conversion tables (see fluid_mod.c + fluid_mod_get_value cases 4 and 8) */ - /* concave unipolar positive transform curve */ - fluid_concave_tab[0] = 0.0; - fluid_concave_tab[FLUID_VEL_CB_SIZE - 1] = 1.0; + /* concave unipolar positive transform curve */ + fluid_concave_tab[0] = 0.0; + fluid_concave_tab[FLUID_VEL_CB_SIZE - 1] = 1.0; - /* convex unipolar positive transform curve */ - fluid_convex_tab[0] = 0; - fluid_convex_tab[FLUID_VEL_CB_SIZE - 1] = 1.0; + /* convex unipolar positive transform curve */ + fluid_convex_tab[0] = 0; + fluid_convex_tab[FLUID_VEL_CB_SIZE - 1] = 1.0; - /* There seems to be an error in the specs. The equations are - implemented according to the pictures on SF2.01 page 73. */ + /* There seems to be an error in the specs. The equations are + implemented according to the pictures on SF2.01 page 73. */ - for (i = 1; i < FLUID_VEL_CB_SIZE - 1; i++) { - x = (-200.0 / FLUID_PEAK_ATTENUATION) * log((i * i) / (fluid_real_t)((FLUID_VEL_CB_SIZE-1) * (FLUID_VEL_CB_SIZE-1))) / M_LN10; - fluid_convex_tab[i] = (fluid_real_t) (1.0 - x); - fluid_concave_tab[(FLUID_VEL_CB_SIZE-1) - i] = (fluid_real_t) x; - } + for(i = 1; i < FLUID_VEL_CB_SIZE - 1; i++) + { + x = (-200.0 / FLUID_PEAK_ATTENUATION) * log((i * i) / (fluid_real_t)((FLUID_VEL_CB_SIZE - 1) * (FLUID_VEL_CB_SIZE - 1))) / M_LN10; + fluid_convex_tab[i] = (fluid_real_t)(1.0 - x); + fluid_concave_tab[(FLUID_VEL_CB_SIZE - 1) - i] = (fluid_real_t) x; + } - /* initialize the pan conversion table */ - x = M_PI / 2.0 / (FLUID_PAN_SIZE - 1.0); - for (i = 0; i < FLUID_PAN_SIZE; i++) { - fluid_pan_tab[i] = (fluid_real_t) sin(i * x); - } + /* initialize the pan conversion table */ + x = M_PI / 2.0 / (FLUID_PAN_SIZE - 1.0); + + for(i = 0; i < FLUID_PAN_SIZE; i++) + { + fluid_pan_tab[i] = (fluid_real_t) sin(i * x); + } } /* @@ -89,35 +94,62 @@ fluid_conversion_config(void) fluid_real_t fluid_ct2hz_real(fluid_real_t cents) { - if (cents < 0) - return (fluid_real_t) 1.0; - else if (cents < 900) { - return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int) (cents + 300)]; - } else if (cents < 2100) { - return (fluid_real_t) 13.75 * fluid_ct2hz_tab[(int) (cents - 900)]; - } else if (cents < 3300) { - return (fluid_real_t) 27.5 * fluid_ct2hz_tab[(int) (cents - 2100)]; - } else if (cents < 4500) { - return (fluid_real_t) 55.0 * fluid_ct2hz_tab[(int) (cents - 3300)]; - } else if (cents < 5700) { - return (fluid_real_t) 110.0 * fluid_ct2hz_tab[(int) (cents - 4500)]; - } else if (cents < 6900) { - return (fluid_real_t) 220.0 * fluid_ct2hz_tab[(int) (cents - 5700)]; - } else if (cents < 8100) { - return (fluid_real_t) 440.0 * fluid_ct2hz_tab[(int) (cents - 6900)]; - } else if (cents < 9300) { - return (fluid_real_t) 880.0 * fluid_ct2hz_tab[(int) (cents - 8100)]; - } else if (cents < 10500) { - return (fluid_real_t) 1760.0 * fluid_ct2hz_tab[(int) (cents - 9300)]; - } else if (cents < 11700) { - return (fluid_real_t) 3520.0 * fluid_ct2hz_tab[(int) (cents - 10500)]; - } else if (cents < 12900) { - return (fluid_real_t) 7040.0 * fluid_ct2hz_tab[(int) (cents - 11700)]; - } else if (cents < 14100) { - return (fluid_real_t) 14080.0 * fluid_ct2hz_tab[(int) (cents - 12900)]; - } else { - return (fluid_real_t) 1.0; /* some loony trying to make you deaf */ - } + if(cents < 0) + { + return (fluid_real_t) 1.0; + } + else if(cents < 900) + { + return (fluid_real_t) 6.875 * fluid_ct2hz_tab[(int)(cents + 300)]; + } + else if(cents < 2100) + { + return (fluid_real_t) 13.75 * fluid_ct2hz_tab[(int)(cents - 900)]; + } + else if(cents < 3300) + { + return (fluid_real_t) 27.5 * fluid_ct2hz_tab[(int)(cents - 2100)]; + } + else if(cents < 4500) + { + return (fluid_real_t) 55.0 * fluid_ct2hz_tab[(int)(cents - 3300)]; + } + else if(cents < 5700) + { + return (fluid_real_t) 110.0 * fluid_ct2hz_tab[(int)(cents - 4500)]; + } + else if(cents < 6900) + { + return (fluid_real_t) 220.0 * fluid_ct2hz_tab[(int)(cents - 5700)]; + } + else if(cents < 8100) + { + return (fluid_real_t) 440.0 * fluid_ct2hz_tab[(int)(cents - 6900)]; + } + else if(cents < 9300) + { + return (fluid_real_t) 880.0 * fluid_ct2hz_tab[(int)(cents - 8100)]; + } + else if(cents < 10500) + { + return (fluid_real_t) 1760.0 * fluid_ct2hz_tab[(int)(cents - 9300)]; + } + else if(cents < 11700) + { + return (fluid_real_t) 3520.0 * fluid_ct2hz_tab[(int)(cents - 10500)]; + } + else if(cents < 12900) + { + return (fluid_real_t) 7040.0 * fluid_ct2hz_tab[(int)(cents - 11700)]; + } + else if(cents < 14100) + { + return (fluid_real_t) 14080.0 * fluid_ct2hz_tab[(int)(cents - 12900)]; + } + else + { + return (fluid_real_t) 1.0; /* some loony trying to make you deaf */ + } } /* @@ -126,13 +158,17 @@ fluid_ct2hz_real(fluid_real_t cents) fluid_real_t fluid_ct2hz(fluid_real_t cents) { - /* Filter fc limit: SF2.01 page 48 # 8 */ - if (cents >= 13500){ - cents = 13500; /* 20 kHz */ - } else if (cents < 1500){ - cents = 1500; /* 20 Hz */ - } - return fluid_ct2hz_real(cents); + /* Filter fc limit: SF2.01 page 48 # 8 */ + if(cents >= 13500) + { + cents = 13500; /* 20 kHz */ + } + else if(cents < 1500) + { + cents = 1500; /* 20 Hz */ + } + + return fluid_ct2hz_real(cents); } /* @@ -144,20 +180,24 @@ fluid_ct2hz(fluid_real_t cents) fluid_real_t fluid_cb2amp(fluid_real_t cb) { - /* - * cb: an attenuation in 'centibels' (1/10 dB) - * SF2.01 page 49 # 48 limits it to 144 dB. - * 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit. - */ + /* + * cb: an attenuation in 'centibels' (1/10 dB) + * SF2.01 page 49 # 48 limits it to 144 dB. + * 96 dB is reasonable for 16 bit systems, 144 would make sense for 24 bit. + */ - /* minimum attenuation: 0 dB */ - if (cb < 0) { - return 1.0; - } - if (cb >= FLUID_CB_AMP_SIZE) { - return 0.0; - } - return fluid_cb2amp_tab[(int) cb]; + /* minimum attenuation: 0 dB */ + if(cb < 0) + { + return 1.0; + } + + if(cb >= FLUID_CB_AMP_SIZE) + { + return 0.0; + } + + return fluid_cb2amp_tab[(int) cb]; } /* @@ -166,21 +206,27 @@ fluid_cb2amp(fluid_real_t cb) fluid_real_t fluid_tc2sec_delay(fluid_real_t tc) { - /* SF2.01 section 8.1.2 items 21, 23, 25, 33 - * SF2.01 section 8.1.3 items 21, 23, 25, 33 - * - * The most negative number indicates a delay of 0. Range is limited - * from -12000 to 5000 */ - if (tc <= -32768.0f) { - return (fluid_real_t) 0.0f; - }; - if (tc < -12000.) { - tc = (fluid_real_t) -12000.0f; - } - if (tc > 5000.0f) { - tc = (fluid_real_t) 5000.0f; - } - return (fluid_real_t) pow(2.0, (double) tc / 1200.0); + /* SF2.01 section 8.1.2 items 21, 23, 25, 33 + * SF2.01 section 8.1.3 items 21, 23, 25, 33 + * + * The most negative number indicates a delay of 0. Range is limited + * from -12000 to 5000 */ + if(tc <= -32768.0f) + { + return (fluid_real_t) 0.0f; + }; + + if(tc < -12000.) + { + tc = (fluid_real_t) -12000.0f; + } + + if(tc > 5000.0f) + { + tc = (fluid_real_t) 5000.0f; + } + + return (fluid_real_t) pow(2.0, (double) tc / 1200.0); } /* @@ -189,14 +235,26 @@ fluid_tc2sec_delay(fluid_real_t tc) fluid_real_t fluid_tc2sec_attack(fluid_real_t tc) { - /* SF2.01 section 8.1.2 items 26, 34 - * SF2.01 section 8.1.3 items 26, 34 - * The most negative number indicates a delay of 0 - * Range is limited from -12000 to 8000 */ - if (tc<=-32768.){return (fluid_real_t) 0.0;}; - if (tc<-12000.){tc=(fluid_real_t) -12000.0;}; - if (tc>8000.){tc=(fluid_real_t) 8000.0;}; - return (fluid_real_t) pow(2.0, (double) tc / 1200.0); + /* SF2.01 section 8.1.2 items 26, 34 + * SF2.01 section 8.1.3 items 26, 34 + * The most negative number indicates a delay of 0 + * Range is limited from -12000 to 8000 */ + if(tc <= -32768.) + { + return (fluid_real_t) 0.0; + }; + + if(tc < -12000.) + { + tc = (fluid_real_t) -12000.0; + }; + + if(tc > 8000.) + { + tc = (fluid_real_t) 8000.0; + }; + + return (fluid_real_t) pow(2.0, (double) tc / 1200.0); } /* @@ -205,8 +263,8 @@ fluid_tc2sec_attack(fluid_real_t tc) fluid_real_t fluid_tc2sec(fluid_real_t tc) { - /* No range checking here! */ - return (fluid_real_t) pow(2.0, (double) tc / 1200.0); + /* No range checking here! */ + return (fluid_real_t) pow(2.0, (double) tc / 1200.0); } /* @@ -215,14 +273,26 @@ fluid_tc2sec(fluid_real_t tc) fluid_real_t fluid_tc2sec_release(fluid_real_t tc) { - /* SF2.01 section 8.1.2 items 30, 38 - * SF2.01 section 8.1.3 items 30, 38 - * No 'most negative number' rule here! - * Range is limited from -12000 to 8000 */ - if (tc<=-32768.){return (fluid_real_t) 0.0;}; - if (tc<-12000.){tc=(fluid_real_t) -12000.0;}; - if (tc>8000.){tc=(fluid_real_t) 8000.0;}; - return (fluid_real_t) pow(2.0, (double) tc / 1200.0); + /* SF2.01 section 8.1.2 items 30, 38 + * SF2.01 section 8.1.3 items 30, 38 + * No 'most negative number' rule here! + * Range is limited from -12000 to 8000 */ + if(tc <= -32768.) + { + return (fluid_real_t) 0.0; + }; + + if(tc < -12000.) + { + tc = (fluid_real_t) -12000.0; + }; + + if(tc > 8000.) + { + tc = (fluid_real_t) 8000.0; + }; + + return (fluid_real_t) pow(2.0, (double) tc / 1200.0); } /* @@ -233,7 +303,7 @@ fluid_tc2sec_release(fluid_real_t tc) fluid_real_t fluid_act2hz(fluid_real_t c) { - return (fluid_real_t) (8.176 * pow(2.0, (double) c / 1200.0)); + return (fluid_real_t)(8.176 * pow(2.0, (double) c / 1200.0)); } /* @@ -244,7 +314,7 @@ fluid_act2hz(fluid_real_t c) fluid_real_t fluid_hz2ct(fluid_real_t f) { - return (fluid_real_t) (6900 + 1200 * log(f / 440.0) / M_LN2); + return (fluid_real_t)(6900 + 1200 * log(f / 440.0) / M_LN2); } /* @@ -253,16 +323,23 @@ fluid_hz2ct(fluid_real_t f) fluid_real_t fluid_pan(fluid_real_t c, int left) { - if (left) { - c = -c; - } - if (c <= -500) { - return (fluid_real_t) 0.0; - } else if (c >= 500) { - return (fluid_real_t) 1.0; - } else { - return fluid_pan_tab[(int) (c + 500)]; - } + if(left) + { + c = -c; + } + + if(c <= -500) + { + return (fluid_real_t) 0.0; + } + else if(c >= 500) + { + return (fluid_real_t) 1.0; + } + else + { + return fluid_pan_tab[(int)(c + 500)]; + } } /* @@ -277,17 +354,17 @@ fluid_pan(fluid_real_t c, int left) fluid_real_t fluid_balance(fluid_real_t balance, int left) { /* This is the most common case */ - if (balance == 0) + if(balance == 0) { return 1.0f; } - if ((left && balance < 0) || (!left && balance > 0)) + if((left && balance < 0) || (!left && balance > 0)) { return 1.0f; } - if (balance < 0) + if(balance < 0) { balance = -balance; } @@ -301,12 +378,16 @@ fluid_real_t fluid_balance(fluid_real_t balance, int left) fluid_real_t fluid_concave(fluid_real_t val) { - if (val < 0) { - return 0; - } else if (val >= FLUID_VEL_CB_SIZE) { - return 1; - } - return fluid_concave_tab[(int) val]; + if(val < 0) + { + return 0; + } + else if(val >= FLUID_VEL_CB_SIZE) + { + return 1; + } + + return fluid_concave_tab[(int) val]; } /* @@ -315,10 +396,14 @@ fluid_concave(fluid_real_t val) fluid_real_t fluid_convex(fluid_real_t val) { - if (val < 0) { - return 0; - } else if (val >= FLUID_VEL_CB_SIZE) { - return 1; - } - return fluid_convex_tab[(int) val]; + if(val < 0) + { + return 0; + } + else if(val >= FLUID_VEL_CB_SIZE) + { + return 1; + } + + return fluid_convex_tab[(int) val]; } diff --git a/src/utils/fluid_conv.h b/src/utils/fluid_conv.h index 6049cfd3..d84a321c 100644 --- a/src/utils/fluid_conv.h +++ b/src/utils/fluid_conv.h @@ -29,14 +29,14 @@ from 0 to the end of attack segment. fluidsynth is a 24 bit synth, it could (should??) be 144 dB of attenuation. However the spec makes no distinction between 16 or 24 bit synths, so use - 96 dB here. - + 96 dB here. + Note about usefulness of 24 bits: 1)Even fluidsynth is a 24 bit synth, this format is only relevant if the sample format coming from the soundfont is 24 bits and the audio sample format choosen by the application (audio.sample.format) is not 16 bits. - 2)When the sample soundfont is 16 bits, the internal 24 bits number have + 2)When the sample soundfont is 16 bits, the internal 24 bits number have 16 bits msb and lsb to 0. Consequently, at the DAC output, the dynamic range of this 24 bit sample is reduced to the the dynamic of a 16 bits sample (ie 90 db) even if this sample is produced by the audio driver using an audio sample format diff --git a/src/utils/fluid_hash.c b/src/utils/fluid_hash.c index c6d5aead..c04c5143 100644 --- a/src/utils/fluid_hash.c +++ b/src/utils/fluid_hash.c @@ -42,12 +42,12 @@ typedef struct { - fluid_hashtable_t *hashtable; - fluid_hashnode_t *prev_node; - fluid_hashnode_t *node; - int position; - int pre_advanced; // Boolean - int version; + fluid_hashtable_t *hashtable; + fluid_hashnode_t *prev_node; + fluid_hashnode_t *node; + int position; + int pre_advanced; // Boolean + int version; } RealIter; @@ -55,54 +55,58 @@ typedef struct static const unsigned int primes[] = { - 11, - 19, - 37, - 73, - 109, - 163, - 251, - 367, - 557, - 823, - 1237, - 1861, - 2777, - 4177, - 6247, - 9371, - 14057, - 21089, - 31627, - 47431, - 71143, - 106721, - 160073, - 240101, - 360163, - 540217, - 810343, - 1215497, - 1823231, - 2734867, - 4102283, - 6153409, - 9230113, - 13845163, + 11, + 19, + 37, + 73, + 109, + 163, + 251, + 367, + 557, + 823, + 1237, + 1861, + 2777, + 4177, + 6247, + 9371, + 14057, + 21089, + 31627, + 47431, + 71143, + 106721, + 160073, + 240101, + 360163, + 540217, + 810343, + 1215497, + 1823231, + 2734867, + 4102283, + 6153409, + 9230113, + 13845163, }; static const unsigned int nprimes = FLUID_N_ELEMENTS(primes); static unsigned int -spaced_primes_closest (unsigned int num) +spaced_primes_closest(unsigned int num) { - unsigned int i; + unsigned int i; - for (i = 0; i < nprimes; i++) - if (primes[i] > num) - return primes[i]; + for(i = 0; i < nprimes; i++) + { + if(primes[i] > num) + { + return primes[i]; + } + } - return primes[nprimes - 1]; + return primes[nprimes - 1]; } /* End excerpt from glib gprimes.c */ @@ -137,50 +141,56 @@ spaced_primes_closest (unsigned int num) * the new record. */ static FLUID_INLINE fluid_hashnode_t ** -fluid_hashtable_lookup_node (fluid_hashtable_t *hashtable, const void *key, - unsigned int *hash_return) +fluid_hashtable_lookup_node(fluid_hashtable_t *hashtable, const void *key, + unsigned int *hash_return) { - fluid_hashnode_t **node_ptr, *node; - unsigned int hash_value; + fluid_hashnode_t **node_ptr, *node; + unsigned int hash_value; - hash_value = (* hashtable->hash_func)(key); - node_ptr = &hashtable->nodes[hash_value % hashtable->size]; + hash_value = (* hashtable->hash_func)(key); + node_ptr = &hashtable->nodes[hash_value % hashtable->size]; - if (hash_return) - *hash_return = hash_value; - - /* Hash table lookup needs to be fast. - * We therefore remove the extra conditional of testing - * whether to call the key_equal_func or not from - * the inner loop. - * - * Additional optimisation: first check if our full hash - * values are equal so we can avoid calling the full-blown - * key equality function in most cases. - */ - if (hashtable->key_equal_func) + if(hash_return) { - while ((node = *node_ptr)) - { - if (node->key_hash == hash_value && - hashtable->key_equal_func (node->key, key)) - break; + *hash_return = hash_value; + } - node_ptr = &(*node_ptr)->next; + /* Hash table lookup needs to be fast. + * We therefore remove the extra conditional of testing + * whether to call the key_equal_func or not from + * the inner loop. + * + * Additional optimisation: first check if our full hash + * values are equal so we can avoid calling the full-blown + * key equality function in most cases. + */ + if(hashtable->key_equal_func) + { + while((node = *node_ptr)) + { + if(node->key_hash == hash_value && + hashtable->key_equal_func(node->key, key)) + { + break; + } + + node_ptr = &(*node_ptr)->next; } } - else + else { - while ((node = *node_ptr)) + while((node = *node_ptr)) { - if (node->key == key) - break; + if(node->key == key) + { + break; + } - node_ptr = &(*node_ptr)->next; + node_ptr = &(*node_ptr)->next; } } - return node_ptr; + return node_ptr; } /* @@ -213,25 +223,29 @@ fluid_hashtable_lookup_node (fluid_hashtable_t *hashtable, const void *key, * modified at all. Stay tuned. :) */ static void -fluid_hashtable_remove_node (fluid_hashtable_t *hashtable, - fluid_hashnode_t ***node_ptr_ptr, int notify) +fluid_hashtable_remove_node(fluid_hashtable_t *hashtable, + fluid_hashnode_t ***node_ptr_ptr, int notify) { - fluid_hashnode_t **node_ptr, *node; + fluid_hashnode_t **node_ptr, *node; - node_ptr = *node_ptr_ptr; - node = *node_ptr; + node_ptr = *node_ptr_ptr; + node = *node_ptr; - *node_ptr = node->next; + *node_ptr = node->next; - if (notify && hashtable->key_destroy_func) - hashtable->key_destroy_func (node->key); + if(notify && hashtable->key_destroy_func) + { + hashtable->key_destroy_func(node->key); + } - if (notify && hashtable->value_destroy_func) - hashtable->value_destroy_func (node->value); + if(notify && hashtable->value_destroy_func) + { + hashtable->value_destroy_func(node->value); + } - FLUID_FREE (node); + FLUID_FREE(node); - hashtable->nnodes--; + hashtable->nnodes--; } /* @@ -246,16 +260,20 @@ fluid_hashtable_remove_node (fluid_hashtable_t *hashtable, * for the key and value of the hash node. */ static void -fluid_hashtable_remove_all_nodes (fluid_hashtable_t *hashtable, int notify) +fluid_hashtable_remove_all_nodes(fluid_hashtable_t *hashtable, int notify) { - fluid_hashnode_t **node_ptr; - int i; + fluid_hashnode_t **node_ptr; + int i; - for (i = 0; i < hashtable->size; i++) - for (node_ptr = &hashtable->nodes[i]; *node_ptr != NULL;) - fluid_hashtable_remove_node (hashtable, &node_ptr, notify); + for(i = 0; i < hashtable->size; i++) + { + for(node_ptr = &hashtable->nodes[i]; *node_ptr != NULL;) + { + fluid_hashtable_remove_node(hashtable, &node_ptr, notify); + } + } - hashtable->nnodes = 0; + hashtable->nnodes = 0; } /* @@ -268,43 +286,45 @@ fluid_hashtable_remove_all_nodes (fluid_hashtable_t *hashtable, int notify) * fluid_hashtable_maybe_resize() instead. */ static void -fluid_hashtable_resize (fluid_hashtable_t *hashtable) +fluid_hashtable_resize(fluid_hashtable_t *hashtable) { - fluid_hashnode_t **new_nodes; - fluid_hashnode_t *node; - fluid_hashnode_t *next; - unsigned int hash_val; - int new_size; - int i; + fluid_hashnode_t **new_nodes; + fluid_hashnode_t *node; + fluid_hashnode_t *next; + unsigned int hash_val; + int new_size; + int i; - new_size = spaced_primes_closest (hashtable->nnodes); - new_size = (new_size < HASH_TABLE_MIN_SIZE) ? HASH_TABLE_MIN_SIZE : - ((new_size > HASH_TABLE_MAX_SIZE) ? HASH_TABLE_MAX_SIZE : new_size); + new_size = spaced_primes_closest(hashtable->nnodes); + new_size = (new_size < HASH_TABLE_MIN_SIZE) ? HASH_TABLE_MIN_SIZE : + ((new_size > HASH_TABLE_MAX_SIZE) ? HASH_TABLE_MAX_SIZE : new_size); - new_nodes = FLUID_ARRAY (fluid_hashnode_t *, new_size); + new_nodes = FLUID_ARRAY(fluid_hashnode_t *, new_size); - if (!new_nodes) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return; - } + if(!new_nodes) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return; + } - FLUID_MEMSET (new_nodes, 0, new_size * sizeof (fluid_hashnode_t *)); + FLUID_MEMSET(new_nodes, 0, new_size * sizeof(fluid_hashnode_t *)); - for (i = 0; i < hashtable->size; i++) - for (node = hashtable->nodes[i]; node; node = next) - { - next = node->next; + for(i = 0; i < hashtable->size; i++) + { + for(node = hashtable->nodes[i]; node; node = next) + { + next = node->next; - hash_val = node->key_hash % new_size; + hash_val = node->key_hash % new_size; - node->next = new_nodes[hash_val]; - new_nodes[hash_val] = node; - } + node->next = new_nodes[hash_val]; + new_nodes[hash_val] = node; + } + } - FLUID_FREE (hashtable->nodes); - hashtable->nodes = new_nodes; - hashtable->size = new_size; + FLUID_FREE(hashtable->nodes); + hashtable->nodes = new_nodes; + hashtable->size = new_size; } /* @@ -317,14 +337,16 @@ fluid_hashtable_resize (fluid_hashtable_t *hashtable) * too far from its ideal size for its number of nodes. */ static FLUID_INLINE void -fluid_hashtable_maybe_resize (fluid_hashtable_t *hashtable) +fluid_hashtable_maybe_resize(fluid_hashtable_t *hashtable) { - int nnodes = hashtable->nnodes; - int size = hashtable->size; + int nnodes = hashtable->nnodes; + int size = hashtable->size; - if ((size >= 3 * nnodes && size > HASH_TABLE_MIN_SIZE) || - (3 * size <= nnodes && size < HASH_TABLE_MAX_SIZE)) - fluid_hashtable_resize (hashtable); + if((size >= 3 * nnodes && size > HASH_TABLE_MIN_SIZE) || + (3 * size <= nnodes && size < HASH_TABLE_MAX_SIZE)) + { + fluid_hashtable_resize(hashtable); + } } /** @@ -345,10 +367,10 @@ fluid_hashtable_maybe_resize (fluid_hashtable_t *hashtable) * * Return value: a new #fluid_hashtable_t. **/ -fluid_hashtable_t* -new_fluid_hashtable (fluid_hash_func_t hash_func, fluid_equal_func_t key_equal_func) +fluid_hashtable_t * +new_fluid_hashtable(fluid_hash_func_t hash_func, fluid_equal_func_t key_equal_func) { - return new_fluid_hashtable_full (hash_func, key_equal_func, NULL, NULL); + return new_fluid_hashtable_full(hash_func, key_equal_func, NULL, NULL); } @@ -369,33 +391,33 @@ new_fluid_hashtable (fluid_hash_func_t hash_func, fluid_equal_func_t key_equal_f * * Return value: a new #fluid_hashtable_t. **/ -fluid_hashtable_t* -new_fluid_hashtable_full (fluid_hash_func_t hash_func, - fluid_equal_func_t key_equal_func, - fluid_destroy_notify_t key_destroy_func, - fluid_destroy_notify_t value_destroy_func) +fluid_hashtable_t * +new_fluid_hashtable_full(fluid_hash_func_t hash_func, + fluid_equal_func_t key_equal_func, + fluid_destroy_notify_t key_destroy_func, + fluid_destroy_notify_t value_destroy_func) { - fluid_hashtable_t *hashtable; + fluid_hashtable_t *hashtable; - hashtable = FLUID_NEW (fluid_hashtable_t); + hashtable = FLUID_NEW(fluid_hashtable_t); - if (!hashtable) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return NULL; - } + if(!hashtable) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - hashtable->size = HASH_TABLE_MIN_SIZE; - hashtable->nnodes = 0; - hashtable->hash_func = hash_func ? hash_func : fluid_direct_hash; - hashtable->key_equal_func = key_equal_func; - fluid_atomic_int_set(&hashtable->ref_count, 1); - hashtable->key_destroy_func = key_destroy_func; - hashtable->value_destroy_func = value_destroy_func; - hashtable->nodes = FLUID_ARRAY (fluid_hashnode_t*, hashtable->size); - FLUID_MEMSET (hashtable->nodes, 0, hashtable->size * sizeof (fluid_hashnode_t *)); + hashtable->size = HASH_TABLE_MIN_SIZE; + hashtable->nnodes = 0; + hashtable->hash_func = hash_func ? hash_func : fluid_direct_hash; + hashtable->key_equal_func = key_equal_func; + fluid_atomic_int_set(&hashtable->ref_count, 1); + hashtable->key_destroy_func = key_destroy_func; + hashtable->value_destroy_func = value_destroy_func; + hashtable->nodes = FLUID_ARRAY(fluid_hashnode_t *, hashtable->size); + FLUID_MEMSET(hashtable->nodes, 0, hashtable->size * sizeof(fluid_hashnode_t *)); - return hashtable; + return hashtable; } /** @@ -411,7 +433,7 @@ new_fluid_hashtable_full (fluid_hash_func_t hash_func, * gpointer key, value; * * fluid_hashtable_iter_init (&iter, hashtable); - * while (fluid_hashtable_iter_next (&iter, &key, &value)) + * while (fluid_hashtable_iter_next (&iter, &key, &value)) * { * /* do something with key and value */ * } @@ -420,19 +442,19 @@ new_fluid_hashtable_full (fluid_hash_func_t hash_func, * Since: 2.16 **/ void -fluid_hashtable_iter_init (fluid_hashtable_iter_t *iter, - fluid_hashtable_t *hashtable) +fluid_hashtable_iter_init(fluid_hashtable_iter_t *iter, + fluid_hashtable_t *hashtable) { - RealIter *ri = (RealIter *) iter; + RealIter *ri = (RealIter *) iter; - fluid_return_if_fail (iter != NULL); - fluid_return_if_fail (hashtable != NULL); + fluid_return_if_fail(iter != NULL); + fluid_return_if_fail(hashtable != NULL); - ri->hashtable = hashtable; - ri->prev_node = NULL; - ri->node = NULL; - ri->position = -1; - ri->pre_advanced = FALSE; + ri->hashtable = hashtable; + ri->prev_node = NULL; + ri->node = NULL; + ri->position = -1; + ri->pre_advanced = FALSE; } /** @@ -450,45 +472,55 @@ fluid_hashtable_iter_init (fluid_hashtable_iter_t *iter, * Since: 2.16 **/ int -fluid_hashtable_iter_next (fluid_hashtable_iter_t *iter, void **key, - void **value) +fluid_hashtable_iter_next(fluid_hashtable_iter_t *iter, void **key, + void **value) { - RealIter *ri = (RealIter *) iter; + RealIter *ri = (RealIter *) iter; - fluid_return_val_if_fail (iter != NULL, FALSE); + fluid_return_val_if_fail(iter != NULL, FALSE); - if (ri->pre_advanced) + if(ri->pre_advanced) { - ri->pre_advanced = FALSE; + ri->pre_advanced = FALSE; - if (ri->node == NULL) - return FALSE; + if(ri->node == NULL) + { + return FALSE; + } } - else + else { - if (ri->node != NULL) - { - ri->prev_node = ri->node; - ri->node = ri->node->next; - } + if(ri->node != NULL) + { + ri->prev_node = ri->node; + ri->node = ri->node->next; + } - while (ri->node == NULL) - { - ri->position++; - if (ri->position >= ri->hashtable->size) - return FALSE; + while(ri->node == NULL) + { + ri->position++; - ri->prev_node = NULL; - ri->node = ri->hashtable->nodes[ri->position]; - } + if(ri->position >= ri->hashtable->size) + { + return FALSE; + } + + ri->prev_node = NULL; + ri->node = ri->hashtable->nodes[ri->position]; + } } - if (key != NULL) - *key = ri->node->key; - if (value != NULL) - *value = ri->node->value; + if(key != NULL) + { + *key = ri->node->key; + } - return TRUE; + if(value != NULL) + { + *value = ri->node->value; + } + + return TRUE; } /** @@ -502,62 +534,74 @@ fluid_hashtable_iter_next (fluid_hashtable_iter_t *iter, void **key, * Since: 2.16 **/ fluid_hashtable_t * -fluid_hashtable_iter_get_hash_table (fluid_hashtable_iter_t *iter) +fluid_hashtable_iter_get_hash_table(fluid_hashtable_iter_t *iter) { - fluid_return_val_if_fail (iter != NULL, NULL); + fluid_return_val_if_fail(iter != NULL, NULL); - return ((RealIter *) iter)->hashtable; + return ((RealIter *) iter)->hashtable; } static void -iter_remove_or_steal (RealIter *ri, int notify) +iter_remove_or_steal(RealIter *ri, int notify) { - fluid_hashnode_t *prev; - fluid_hashnode_t *node; - int position; + fluid_hashnode_t *prev; + fluid_hashnode_t *node; + int position; - fluid_return_if_fail (ri != NULL); - fluid_return_if_fail (ri->node != NULL); + fluid_return_if_fail(ri != NULL); + fluid_return_if_fail(ri->node != NULL); - prev = ri->prev_node; - node = ri->node; - position = ri->position; + prev = ri->prev_node; + node = ri->node; + position = ri->position; - /* pre-advance the iterator since we will remove the node */ + /* pre-advance the iterator since we will remove the node */ - ri->node = ri->node->next; - /* ri->prev_node is still the correct previous node */ + ri->node = ri->node->next; + /* ri->prev_node is still the correct previous node */ - while (ri->node == NULL) + while(ri->node == NULL) { - ri->position++; - if (ri->position >= ri->hashtable->size) - break; + ri->position++; - ri->prev_node = NULL; - ri->node = ri->hashtable->nodes[ri->position]; + if(ri->position >= ri->hashtable->size) + { + break; + } + + ri->prev_node = NULL; + ri->node = ri->hashtable->nodes[ri->position]; } - ri->pre_advanced = TRUE; + ri->pre_advanced = TRUE; - /* remove the node */ + /* remove the node */ - if (prev != NULL) - prev->next = node->next; - else - ri->hashtable->nodes[position] = node->next; - - if (notify) + if(prev != NULL) { - if (ri->hashtable->key_destroy_func) - ri->hashtable->key_destroy_func(node->key); - if (ri->hashtable->value_destroy_func) - ri->hashtable->value_destroy_func(node->value); + prev->next = node->next; + } + else + { + ri->hashtable->nodes[position] = node->next; } - FLUID_FREE (node); + if(notify) + { + if(ri->hashtable->key_destroy_func) + { + ri->hashtable->key_destroy_func(node->key); + } - ri->hashtable->nnodes--; + if(ri->hashtable->value_destroy_func) + { + ri->hashtable->value_destroy_func(node->value); + } + } + + FLUID_FREE(node); + + ri->hashtable->nnodes--; } /** @@ -571,15 +615,15 @@ iter_remove_or_steal (RealIter *ri, int notify) * * If the #fluid_hashtable_t was created using fluid_hashtable_new_full(), the * key and value are freed using the supplied destroy functions, otherwise - * you have to make sure that any dynamically allocated values are freed + * you have to make sure that any dynamically allocated values are freed * yourself. * * Since: 2.16 **/ void -fluid_hashtable_iter_remove (fluid_hashtable_iter_t *iter) +fluid_hashtable_iter_remove(fluid_hashtable_iter_t *iter) { - iter_remove_or_steal ((RealIter *) iter, TRUE); + iter_remove_or_steal((RealIter *) iter, TRUE); } /** @@ -595,9 +639,9 @@ fluid_hashtable_iter_remove (fluid_hashtable_iter_t *iter) * Since: 2.16 **/ void -fluid_hashtable_iter_steal (fluid_hashtable_iter_t *iter) +fluid_hashtable_iter_steal(fluid_hashtable_iter_t *iter) { - iter_remove_or_steal ((RealIter *) iter, FALSE); + iter_remove_or_steal((RealIter *) iter, FALSE); } @@ -612,14 +656,14 @@ fluid_hashtable_iter_steal (fluid_hashtable_iter_t *iter) * * Since: 2.10 **/ -fluid_hashtable_t* -fluid_hashtable_ref (fluid_hashtable_t *hashtable) +fluid_hashtable_t * +fluid_hashtable_ref(fluid_hashtable_t *hashtable) { - fluid_return_val_if_fail (hashtable != NULL, NULL); - fluid_return_val_if_fail (fluid_atomic_int_get(&hashtable->ref_count) > 0, hashtable); + fluid_return_val_if_fail(hashtable != NULL, NULL); + fluid_return_val_if_fail(fluid_atomic_int_get(&hashtable->ref_count) > 0, hashtable); - fluid_atomic_int_add (&hashtable->ref_count, 1); - return hashtable; + fluid_atomic_int_add(&hashtable->ref_count, 1); + return hashtable; } /** @@ -634,16 +678,16 @@ fluid_hashtable_ref (fluid_hashtable_t *hashtable) * Since: 2.10 **/ void -fluid_hashtable_unref (fluid_hashtable_t *hashtable) +fluid_hashtable_unref(fluid_hashtable_t *hashtable) { - fluid_return_if_fail (hashtable != NULL); - fluid_return_if_fail (fluid_atomic_int_get(&hashtable->ref_count) > 0); + fluid_return_if_fail(hashtable != NULL); + fluid_return_if_fail(fluid_atomic_int_get(&hashtable->ref_count) > 0); - if (fluid_atomic_int_exchange_and_add (&hashtable->ref_count, -1) - 1 == 0) + if(fluid_atomic_int_exchange_and_add(&hashtable->ref_count, -1) - 1 == 0) { - fluid_hashtable_remove_all_nodes (hashtable, TRUE); - FLUID_FREE (hashtable->nodes); - FLUID_FREE (hashtable); + fluid_hashtable_remove_all_nodes(hashtable, TRUE); + FLUID_FREE(hashtable->nodes); + FLUID_FREE(hashtable); } } @@ -659,13 +703,13 @@ fluid_hashtable_unref (fluid_hashtable_t *hashtable) * destruction phase. **/ void -delete_fluid_hashtable (fluid_hashtable_t *hashtable) +delete_fluid_hashtable(fluid_hashtable_t *hashtable) { - fluid_return_if_fail (hashtable != NULL); - fluid_return_if_fail (fluid_atomic_int_get(&hashtable->ref_count) > 0); + fluid_return_if_fail(hashtable != NULL); + fluid_return_if_fail(fluid_atomic_int_get(&hashtable->ref_count) > 0); - fluid_hashtable_remove_all (hashtable); - fluid_hashtable_unref (hashtable); + fluid_hashtable_remove_all(hashtable); + fluid_hashtable_unref(hashtable); } /** @@ -681,15 +725,15 @@ delete_fluid_hashtable (fluid_hashtable_t *hashtable) * Return value: the associated value, or %NULL if the key is not found. **/ void * -fluid_hashtable_lookup (fluid_hashtable_t *hashtable, const void *key) +fluid_hashtable_lookup(fluid_hashtable_t *hashtable, const void *key) { - fluid_hashnode_t *node; + fluid_hashnode_t *node; - fluid_return_val_if_fail (hashtable != NULL, NULL); + fluid_return_val_if_fail(hashtable != NULL, NULL); - node = *fluid_hashtable_lookup_node (hashtable, key, NULL); + node = *fluid_hashtable_lookup_node(hashtable, key, NULL); - return node ? node->value : NULL; + return node ? node->value : NULL; } /** @@ -707,26 +751,32 @@ fluid_hashtable_lookup (fluid_hashtable_t *hashtable, const void *key) * Return value: %TRUE if the key was found in the #fluid_hashtable_t. **/ int -fluid_hashtable_lookup_extended (fluid_hashtable_t *hashtable, - const void *lookup_key, - void **orig_key, void **value) +fluid_hashtable_lookup_extended(fluid_hashtable_t *hashtable, + const void *lookup_key, + void **orig_key, void **value) { - fluid_hashnode_t *node; + fluid_hashnode_t *node; - fluid_return_val_if_fail (hashtable != NULL, FALSE); + fluid_return_val_if_fail(hashtable != NULL, FALSE); - node = *fluid_hashtable_lookup_node (hashtable, lookup_key, NULL); + node = *fluid_hashtable_lookup_node(hashtable, lookup_key, NULL); - if (node == NULL) - return FALSE; + if(node == NULL) + { + return FALSE; + } - if (orig_key) - *orig_key = node->key; + if(orig_key) + { + *orig_key = node->key; + } - if (value) - *value = node->value; + if(value) + { + *value = node->value; + } - return TRUE; + return TRUE; } /* @@ -746,54 +796,61 @@ fluid_hashtable_lookup_extended (fluid_hashtable_t *hashtable, * new node. */ static void -fluid_hashtable_insert_internal (fluid_hashtable_t *hashtable, void *key, - void *value, int keep_new_key) +fluid_hashtable_insert_internal(fluid_hashtable_t *hashtable, void *key, + void *value, int keep_new_key) { - fluid_hashnode_t **node_ptr, *node; - unsigned int key_hash; + fluid_hashnode_t **node_ptr, *node; + unsigned int key_hash; - fluid_return_if_fail (hashtable != NULL); - fluid_return_if_fail (fluid_atomic_int_get(&hashtable->ref_count) > 0); + fluid_return_if_fail(hashtable != NULL); + fluid_return_if_fail(fluid_atomic_int_get(&hashtable->ref_count) > 0); - node_ptr = fluid_hashtable_lookup_node (hashtable, key, &key_hash); + node_ptr = fluid_hashtable_lookup_node(hashtable, key, &key_hash); - if ((node = *node_ptr)) + if((node = *node_ptr)) { - if (keep_new_key) + if(keep_new_key) { - if (hashtable->key_destroy_func) - hashtable->key_destroy_func (node->key); - node->key = key; + if(hashtable->key_destroy_func) + { + hashtable->key_destroy_func(node->key); + } + + node->key = key; } - else + else { - if (hashtable->key_destroy_func) - hashtable->key_destroy_func (key); + if(hashtable->key_destroy_func) + { + hashtable->key_destroy_func(key); + } } - if (hashtable->value_destroy_func) - hashtable->value_destroy_func (node->value); + if(hashtable->value_destroy_func) + { + hashtable->value_destroy_func(node->value); + } - node->value = value; + node->value = value; } - else + else { - node = FLUID_NEW (fluid_hashnode_t); + node = FLUID_NEW(fluid_hashnode_t); - if (!node) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return; - } + if(!node) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return; + } - node->key = key; - node->value = value; - node->key_hash = key_hash; - node->next = NULL; + node->key = key; + node->value = value; + node->key_hash = key_hash; + node->next = NULL; - *node_ptr = node; - hashtable->nnodes++; - fluid_hashtable_maybe_resize (hashtable); + *node_ptr = node; + hashtable->nnodes++; + fluid_hashtable_maybe_resize(hashtable); } } @@ -812,9 +869,9 @@ fluid_hashtable_insert_internal (fluid_hashtable_t *hashtable, void *key, * using that function. **/ void -fluid_hashtable_insert (fluid_hashtable_t *hashtable, void *key, void *value) +fluid_hashtable_insert(fluid_hashtable_t *hashtable, void *key, void *value) { - fluid_hashtable_insert_internal (hashtable, key, value, FALSE); + fluid_hashtable_insert_internal(hashtable, key, value, FALSE); } /** @@ -831,9 +888,9 @@ fluid_hashtable_insert (fluid_hashtable_t *hashtable, void *key, void *value) * #fluid_hashtable_t, the old key is freed using that function. **/ void -fluid_hashtable_replace (fluid_hashtable_t *hashtable, void *key, void *value) +fluid_hashtable_replace(fluid_hashtable_t *hashtable, void *key, void *value) { - fluid_hashtable_insert_internal (hashtable, key, value, TRUE); + fluid_hashtable_insert_internal(hashtable, key, value, TRUE); } /* @@ -850,21 +907,24 @@ fluid_hashtable_replace (fluid_hashtable_t *hashtable, void *key, void *value) * destroy notify handlers only if @notify is %TRUE. */ static int -fluid_hashtable_remove_internal (fluid_hashtable_t *hashtable, const void *key, - int notify) +fluid_hashtable_remove_internal(fluid_hashtable_t *hashtable, const void *key, + int notify) { - fluid_hashnode_t **node_ptr; + fluid_hashnode_t **node_ptr; - fluid_return_val_if_fail (hashtable != NULL, FALSE); + fluid_return_val_if_fail(hashtable != NULL, FALSE); - node_ptr = fluid_hashtable_lookup_node (hashtable, key, NULL); - if (*node_ptr == NULL) - return FALSE; + node_ptr = fluid_hashtable_lookup_node(hashtable, key, NULL); - fluid_hashtable_remove_node (hashtable, &node_ptr, notify); - fluid_hashtable_maybe_resize (hashtable); + if(*node_ptr == NULL) + { + return FALSE; + } - return TRUE; + fluid_hashtable_remove_node(hashtable, &node_ptr, notify); + fluid_hashtable_maybe_resize(hashtable); + + return TRUE; } /** @@ -882,9 +942,9 @@ fluid_hashtable_remove_internal (fluid_hashtable_t *hashtable, const void *key, * Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t. **/ int -fluid_hashtable_remove (fluid_hashtable_t *hashtable, const void *key) +fluid_hashtable_remove(fluid_hashtable_t *hashtable, const void *key) { - return fluid_hashtable_remove_internal (hashtable, key, TRUE); + return fluid_hashtable_remove_internal(hashtable, key, TRUE); } /** @@ -898,9 +958,9 @@ fluid_hashtable_remove (fluid_hashtable_t *hashtable, const void *key) * Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t. **/ int -fluid_hashtable_steal (fluid_hashtable_t *hashtable, const void *key) +fluid_hashtable_steal(fluid_hashtable_t *hashtable, const void *key) { - return fluid_hashtable_remove_internal (hashtable, key, FALSE); + return fluid_hashtable_remove_internal(hashtable, key, FALSE); } /** @@ -917,12 +977,12 @@ fluid_hashtable_steal (fluid_hashtable_t *hashtable, const void *key) * Since: 2.12 **/ void -fluid_hashtable_remove_all (fluid_hashtable_t *hashtable) +fluid_hashtable_remove_all(fluid_hashtable_t *hashtable) { - fluid_return_if_fail (hashtable != NULL); + fluid_return_if_fail(hashtable != NULL); - fluid_hashtable_remove_all_nodes (hashtable, TRUE); - fluid_hashtable_maybe_resize (hashtable); + fluid_hashtable_remove_all_nodes(hashtable, TRUE); + fluid_hashtable_maybe_resize(hashtable); } /** @@ -935,12 +995,12 @@ fluid_hashtable_remove_all (fluid_hashtable_t *hashtable) * Since: 2.12 **/ void -fluid_hashtable_steal_all (fluid_hashtable_t *hashtable) +fluid_hashtable_steal_all(fluid_hashtable_t *hashtable) { - fluid_return_if_fail (hashtable != NULL); + fluid_return_if_fail(hashtable != NULL); - fluid_hashtable_remove_all_nodes (hashtable, FALSE); - fluid_hashtable_maybe_resize (hashtable); + fluid_hashtable_remove_all_nodes(hashtable, FALSE); + fluid_hashtable_maybe_resize(hashtable); } /* @@ -961,27 +1021,33 @@ fluid_hashtable_steal_all (fluid_hashtable_t *hashtable) * for each removed node. */ static unsigned int -fluid_hashtable_foreach_remove_or_steal (fluid_hashtable_t *hashtable, - fluid_hr_func_t func, void *user_data, - int notify) +fluid_hashtable_foreach_remove_or_steal(fluid_hashtable_t *hashtable, + fluid_hr_func_t func, void *user_data, + int notify) { - fluid_hashnode_t *node, **node_ptr; - unsigned int deleted = 0; - int i; + fluid_hashnode_t *node, **node_ptr; + unsigned int deleted = 0; + int i; - for (i = 0; i < hashtable->size; i++) - for (node_ptr = &hashtable->nodes[i]; (node = *node_ptr) != NULL;) - if ((* func) (node->key, node->value, user_data)) + for(i = 0; i < hashtable->size; i++) + { + for(node_ptr = &hashtable->nodes[i]; (node = *node_ptr) != NULL;) { - fluid_hashtable_remove_node (hashtable, &node_ptr, notify); - deleted++; + if((* func)(node->key, node->value, user_data)) + { + fluid_hashtable_remove_node(hashtable, &node_ptr, notify); + deleted++; + } + else + { + node_ptr = &node->next; + } } - else - node_ptr = &node->next; + } - fluid_hashtable_maybe_resize (hashtable); + fluid_hashtable_maybe_resize(hashtable); - return deleted; + return deleted; } #if 0 @@ -997,19 +1063,19 @@ fluid_hashtable_foreach_remove_or_steal (fluid_hashtable_t *hashtable, * the #fluid_hashtable_t, they are used to free the memory allocated for the removed * keys and values. * - * See #fluid_hashtable_iter_t for an alternative way to loop over the + * See #fluid_hashtable_iter_t for an alternative way to loop over the * key/value pairs in the hash table. * * Return value: the number of key/value pairs removed. **/ static unsigned int -fluid_hashtable_foreach_remove (fluid_hashtable_t *hashtable, - fluid_hr_func_t func, void *user_data) +fluid_hashtable_foreach_remove(fluid_hashtable_t *hashtable, + fluid_hr_func_t func, void *user_data) { - fluid_return_val_if_fail (hashtable != NULL, 0); - fluid_return_val_if_fail (func != NULL, 0); + fluid_return_val_if_fail(hashtable != NULL, 0); + fluid_return_val_if_fail(func != NULL, 0); - return fluid_hashtable_foreach_remove_or_steal (hashtable, func, user_data, TRUE); + return fluid_hashtable_foreach_remove_or_steal(hashtable, func, user_data, TRUE); } #endif @@ -1023,19 +1089,19 @@ fluid_hashtable_foreach_remove (fluid_hashtable_t *hashtable, * If the function returns %TRUE, then the key/value pair is removed from the * #fluid_hashtable_t, but no key or value destroy functions are called. * - * See #fluid_hashtable_iter_t for an alternative way to loop over the + * See #fluid_hashtable_iter_t for an alternative way to loop over the * key/value pairs in the hash table. * * Return value: the number of key/value pairs removed. **/ unsigned int -fluid_hashtable_foreach_steal (fluid_hashtable_t *hashtable, - fluid_hr_func_t func, void *user_data) +fluid_hashtable_foreach_steal(fluid_hashtable_t *hashtable, + fluid_hr_func_t func, void *user_data) { - fluid_return_val_if_fail (hashtable != NULL, 0); - fluid_return_val_if_fail (func != NULL, 0); + fluid_return_val_if_fail(hashtable != NULL, 0); + fluid_return_val_if_fail(func != NULL, 0); - return fluid_hashtable_foreach_remove_or_steal (hashtable, func, user_data, FALSE); + return fluid_hashtable_foreach_remove_or_steal(hashtable, func, user_data, FALSE); } /** @@ -1055,18 +1121,22 @@ fluid_hashtable_foreach_steal (fluid_hashtable_t *hashtable, * order searches in contrast to fluid_hashtable_lookup(). **/ void -fluid_hashtable_foreach (fluid_hashtable_t *hashtable, fluid_hr_func_t func, - void *user_data) +fluid_hashtable_foreach(fluid_hashtable_t *hashtable, fluid_hr_func_t func, + void *user_data) { - fluid_hashnode_t *node; - int i; + fluid_hashnode_t *node; + int i; - fluid_return_if_fail (hashtable != NULL); - fluid_return_if_fail (func != NULL); + fluid_return_if_fail(hashtable != NULL); + fluid_return_if_fail(func != NULL); - for (i = 0; i < hashtable->size; i++) - for (node = hashtable->nodes[i]; node; node = node->next) - (* func) (node->key, node->value, user_data); + for(i = 0; i < hashtable->size; i++) + { + for(node = hashtable->nodes[i]; node; node = node->next) + { + (* func)(node->key, node->value, user_data); + } + } } /** @@ -1096,20 +1166,27 @@ fluid_hashtable_foreach (fluid_hashtable_t *hashtable, fluid_hr_func_t func, * Since: 2.4 **/ void * -fluid_hashtable_find (fluid_hashtable_t *hashtable, fluid_hr_func_t predicate, - void *user_data) +fluid_hashtable_find(fluid_hashtable_t *hashtable, fluid_hr_func_t predicate, + void *user_data) { - fluid_hashnode_t *node; - int i; + fluid_hashnode_t *node; + int i; - fluid_return_val_if_fail (hashtable != NULL, NULL); - fluid_return_val_if_fail (predicate != NULL, NULL); + fluid_return_val_if_fail(hashtable != NULL, NULL); + fluid_return_val_if_fail(predicate != NULL, NULL); - for (i = 0; i < hashtable->size; i++) - for (node = hashtable->nodes[i]; node; node = node->next) - if (predicate (node->key, node->value, user_data)) - return node->value; - return NULL; + for(i = 0; i < hashtable->size; i++) + { + for(node = hashtable->nodes[i]; node; node = node->next) + { + if(predicate(node->key, node->value, user_data)) + { + return node->value; + } + } + } + + return NULL; } /** @@ -1121,11 +1198,11 @@ fluid_hashtable_find (fluid_hashtable_t *hashtable, fluid_hr_func_t predicate, * Return value: the number of key/value pairs in the #fluid_hashtable_t. **/ unsigned int -fluid_hashtable_size (fluid_hashtable_t *hashtable) +fluid_hashtable_size(fluid_hashtable_t *hashtable) { - fluid_return_val_if_fail (hashtable != NULL, 0); + fluid_return_val_if_fail(hashtable != NULL, 0); - return hashtable->nnodes; + return hashtable->nnodes; } /** @@ -1143,20 +1220,25 @@ fluid_hashtable_size (fluid_hashtable_t *hashtable) * Since: 2.14 */ fluid_list_t * -fluid_hashtable_get_keys (fluid_hashtable_t *hashtable) +fluid_hashtable_get_keys(fluid_hashtable_t *hashtable) { - fluid_hashnode_t *node; - int i; - fluid_list_t *retval; + fluid_hashnode_t *node; + int i; + fluid_list_t *retval; - fluid_return_val_if_fail (hashtable != NULL, NULL); + fluid_return_val_if_fail(hashtable != NULL, NULL); - retval = NULL; - for (i = 0; i < hashtable->size; i++) - for (node = hashtable->nodes[i]; node; node = node->next) - retval = fluid_list_prepend (retval, node->key); + retval = NULL; - return retval; + for(i = 0; i < hashtable->size; i++) + { + for(node = hashtable->nodes[i]; node; node = node->next) + { + retval = fluid_list_prepend(retval, node->key); + } + } + + return retval; } /** @@ -1174,20 +1256,25 @@ fluid_hashtable_get_keys (fluid_hashtable_t *hashtable) * Since: 2.14 */ fluid_list_t * -fluid_hashtable_get_values (fluid_hashtable_t *hashtable) +fluid_hashtable_get_values(fluid_hashtable_t *hashtable) { - fluid_hashnode_t *node; - int i; - fluid_list_t *retval; + fluid_hashnode_t *node; + int i; + fluid_list_t *retval; - fluid_return_val_if_fail (hashtable != NULL, NULL); + fluid_return_val_if_fail(hashtable != NULL, NULL); - retval = NULL; - for (i = 0; i < hashtable->size; i++) - for (node = hashtable->nodes[i]; node; node = node->next) - retval = fluid_list_prepend (retval, node->value); + retval = NULL; - return retval; + for(i = 0; i < hashtable->size; i++) + { + for(node = hashtable->nodes[i]; node; node = node->next) + { + retval = fluid_list_prepend(retval, node->value); + } + } + + return retval; } @@ -1198,20 +1285,20 @@ fluid_hashtable_get_values (fluid_hashtable_t *hashtable) * fluid_str_equal: * @v1: a key * @v2: a key to compare with @v1 - * - * Compares two strings for byte-by-byte equality and returns %TRUE - * if they are equal. It can be passed to new_fluid_hashtable() as the + * + * Compares two strings for byte-by-byte equality and returns %TRUE + * if they are equal. It can be passed to new_fluid_hashtable() as the * @key_equal_func parameter, when using strings as keys in a #Ghashtable. * * Returns: %TRUE if the two keys match */ int -fluid_str_equal (const void *v1, const void *v2) +fluid_str_equal(const void *v1, const void *v2) { - const char *string1 = v1; - const char *string2 = v2; - - return FLUID_STRCMP (string1, string2) == 0; + const char *string1 = v1; + const char *string2 = v2; + + return FLUID_STRCMP(string1, string2) == 0; } /** @@ -1219,23 +1306,27 @@ fluid_str_equal (const void *v1, const void *v2) * @v: a string key * * Converts a string to a hash value. - * It can be passed to new_fluid_hashtable() as the @hash_func + * It can be passed to new_fluid_hashtable() as the @hash_func * parameter, when using strings as keys in a #fluid_hashtable_t. * * Returns: a hash value corresponding to the key */ unsigned int -fluid_str_hash (const void *v) +fluid_str_hash(const void *v) { - /* 31 bit hash function */ - const signed char *p = v; - uint32_t h = *p; + /* 31 bit hash function */ + const signed char *p = v; + uint32_t h = *p; - if (h) - for (p += 1; *p != '\0'; p++) - h = (h << 5) - h + *p; + if(h) + { + for(p += 1; *p != '\0'; p++) + { + h = (h << 5) - h + *p; + } + } - return h; + return h; } @@ -1250,13 +1341,13 @@ fluid_str_hash (const void *v) * Compares two #gpointer arguments and returns %TRUE if they are equal. * It can be passed to new_fluid_hashtable() as the @key_equal_func * parameter, when using pointers as keys in a #fluid_hashtable_t. - * + * * Returns: %TRUE if the two keys match. */ int -fluid_direct_equal (const void *v1, const void *v2) +fluid_direct_equal(const void *v1, const void *v2) { - return v1 == v2; + return v1 == v2; } /** @@ -1264,15 +1355,15 @@ fluid_direct_equal (const void *v1, const void *v2) * @v: a void * key * * Converts a gpointer to a hash value. - * It can be passed to g_hashtable_new() as the @hash_func parameter, + * It can be passed to g_hashtable_new() as the @hash_func parameter, * when using pointers as keys in a #fluid_hashtable_t. * * Returns: a hash value corresponding to the key. */ unsigned int -fluid_direct_hash (const void *v) +fluid_direct_hash(const void *v) { - return FLUID_POINTER_TO_UINT (v); + return FLUID_POINTER_TO_UINT(v); } /** @@ -1280,17 +1371,17 @@ fluid_direct_hash (const void *v) * @v1: a pointer to a int key. * @v2: a pointer to a int key to compare with @v1. * - * Compares the two #gint values being pointed to and returns + * Compares the two #gint values being pointed to and returns * %TRUE if they are equal. * It can be passed to g_hashtable_new() as the @key_equal_func * parameter, when using pointers to integers as keys in a #fluid_hashtable_t. - * + * * Returns: %TRUE if the two keys match. */ int -fluid_int_equal (const void *v1, const void *v2) +fluid_int_equal(const void *v1, const void *v2) { - return *((const int*) v1) == *((const int*) v2); + return *((const int *) v1) == *((const int *) v2); } /** @@ -1298,13 +1389,13 @@ fluid_int_equal (const void *v1, const void *v2) * @v: a pointer to a int key * * Converts a pointer to a #gint to a hash value. - * It can be passed to g_hashtable_new() as the @hash_func parameter, + * It can be passed to g_hashtable_new() as the @hash_func parameter, * when using pointers to integers values as keys in a #fluid_hashtable_t. * * Returns: a hash value corresponding to the key. */ unsigned int -fluid_int_hash (const void *v) +fluid_int_hash(const void *v) { - return *(const int*) v; + return *(const int *) v; } diff --git a/src/utils/fluid_hash.h b/src/utils/fluid_hash.h index 4fd398cf..96b2471b 100644 --- a/src/utils/fluid_hash.h +++ b/src/utils/fluid_hash.h @@ -27,7 +27,7 @@ /* * Adapted for FluidSynth use by Josh Green * September 8, 2009 from glib 2.18.4 - * + * * - Self contained (no dependencies on glib) * - changed names to fluid_hashtable_... */ @@ -52,80 +52,80 @@ typedef struct _fluid_hashnode_t fluid_hashnode_t; struct _fluid_hashnode_t { - void *key; - void *value; - fluid_hashnode_t *next; - unsigned int key_hash; + void *key; + void *value; + fluid_hashnode_t *next; + unsigned int key_hash; }; struct _fluid_hashtable_t { - int size; - int nnodes; - fluid_hashnode_t **nodes; - fluid_hash_func_t hash_func; - fluid_equal_func_t key_equal_func; - fluid_atomic_int_t ref_count; - fluid_destroy_notify_t key_destroy_func; - fluid_destroy_notify_t value_destroy_func; - fluid_rec_mutex_t mutex; // Optionally used in other modules (fluid_settings.c for example) + int size; + int nnodes; + fluid_hashnode_t **nodes; + fluid_hash_func_t hash_func; + fluid_equal_func_t key_equal_func; + fluid_atomic_int_t ref_count; + fluid_destroy_notify_t key_destroy_func; + fluid_destroy_notify_t value_destroy_func; + fluid_rec_mutex_t mutex; // Optionally used in other modules (fluid_settings.c for example) }; struct _fluid_hashtable_iter_t { - /*< private >*/ - void * dummy1; - void * dummy2; - void * dummy3; - int dummy4; - int dummy5; // Bool - void * dummy6; + /*< private >*/ + void *dummy1; + void *dummy2; + void *dummy3; + int dummy4; + int dummy5; // Bool + void *dummy6; }; -fluid_hashtable_t* new_fluid_hashtable (fluid_hash_func_t hash_func, - fluid_equal_func_t key_equal_func); -fluid_hashtable_t* new_fluid_hashtable_full (fluid_hash_func_t hash_func, - fluid_equal_func_t key_equal_func, - fluid_destroy_notify_t key_destroy_func, - fluid_destroy_notify_t value_destroy_func); +fluid_hashtable_t *new_fluid_hashtable(fluid_hash_func_t hash_func, + fluid_equal_func_t key_equal_func); +fluid_hashtable_t *new_fluid_hashtable_full(fluid_hash_func_t hash_func, + fluid_equal_func_t key_equal_func, + fluid_destroy_notify_t key_destroy_func, + fluid_destroy_notify_t value_destroy_func); void delete_fluid_hashtable(fluid_hashtable_t *hashtable); -void fluid_hashtable_iter_init (fluid_hashtable_iter_t *iter, fluid_hashtable_t *hashtable); -int fluid_hashtable_iter_next (fluid_hashtable_iter_t *iter, void **key, void **value); -fluid_hashtable_t *fluid_hashtable_iter_get_hash_table (fluid_hashtable_iter_t *iter); -void fluid_hashtable_iter_remove (fluid_hashtable_iter_t *iter); -void fluid_hashtable_iter_steal (fluid_hashtable_iter_t *iter); +void fluid_hashtable_iter_init(fluid_hashtable_iter_t *iter, fluid_hashtable_t *hashtable); +int fluid_hashtable_iter_next(fluid_hashtable_iter_t *iter, void **key, void **value); +fluid_hashtable_t *fluid_hashtable_iter_get_hash_table(fluid_hashtable_iter_t *iter); +void fluid_hashtable_iter_remove(fluid_hashtable_iter_t *iter); +void fluid_hashtable_iter_steal(fluid_hashtable_iter_t *iter); -fluid_hashtable_t* fluid_hashtable_ref (fluid_hashtable_t *hashtable); -void fluid_hashtable_unref (fluid_hashtable_t *hashtable); +fluid_hashtable_t *fluid_hashtable_ref(fluid_hashtable_t *hashtable); +void fluid_hashtable_unref(fluid_hashtable_t *hashtable); -void *fluid_hashtable_lookup (fluid_hashtable_t *hashtable, const void *key); -int fluid_hashtable_lookup_extended (fluid_hashtable_t *hashtable, const void *lookup_key, - void **orig_key, void **value); +void *fluid_hashtable_lookup(fluid_hashtable_t *hashtable, const void *key); +int fluid_hashtable_lookup_extended(fluid_hashtable_t *hashtable, const void *lookup_key, + void **orig_key, void **value); -void fluid_hashtable_insert (fluid_hashtable_t *hashtable, void *key, void *value); -void fluid_hashtable_replace (fluid_hashtable_t *hashtable, void *key, void *value); +void fluid_hashtable_insert(fluid_hashtable_t *hashtable, void *key, void *value); +void fluid_hashtable_replace(fluid_hashtable_t *hashtable, void *key, void *value); -int fluid_hashtable_remove (fluid_hashtable_t *hashtable, const void *key); -int fluid_hashtable_steal (fluid_hashtable_t *hashtable, const void *key); -void fluid_hashtable_remove_all (fluid_hashtable_t *hashtable); -void fluid_hashtable_steal_all (fluid_hashtable_t *hashtable); -unsigned int fluid_hashtable_foreach_steal (fluid_hashtable_t *hashtable, - fluid_hr_func_t func, void *user_data); -void fluid_hashtable_foreach (fluid_hashtable_t *hashtable, fluid_hr_func_t func, - void *user_data); -void *fluid_hashtable_find (fluid_hashtable_t *hashtable, fluid_hr_func_t predicate, +int fluid_hashtable_remove(fluid_hashtable_t *hashtable, const void *key); +int fluid_hashtable_steal(fluid_hashtable_t *hashtable, const void *key); +void fluid_hashtable_remove_all(fluid_hashtable_t *hashtable); +void fluid_hashtable_steal_all(fluid_hashtable_t *hashtable); +unsigned int fluid_hashtable_foreach_steal(fluid_hashtable_t *hashtable, + fluid_hr_func_t func, void *user_data); +void fluid_hashtable_foreach(fluid_hashtable_t *hashtable, fluid_hr_func_t func, void *user_data); -unsigned int fluid_hashtable_size (fluid_hashtable_t *hashtable); -fluid_list_t *fluid_hashtable_get_keys (fluid_hashtable_t *hashtable); -fluid_list_t *fluid_hashtable_get_values (fluid_hashtable_t *hashtable); +void *fluid_hashtable_find(fluid_hashtable_t *hashtable, fluid_hr_func_t predicate, + void *user_data); +unsigned int fluid_hashtable_size(fluid_hashtable_t *hashtable); +fluid_list_t *fluid_hashtable_get_keys(fluid_hashtable_t *hashtable); +fluid_list_t *fluid_hashtable_get_values(fluid_hashtable_t *hashtable); -int fluid_str_equal (const void *v1, const void *v2); -unsigned int fluid_str_hash (const void *v); -int fluid_direct_equal (const void *v1, const void *v2); -unsigned int fluid_direct_hash (const void *v); -int fluid_int_equal (const void *v1, const void *v2); -unsigned int fluid_int_hash (const void *v); +int fluid_str_equal(const void *v1, const void *v2); +unsigned int fluid_str_hash(const void *v); +int fluid_direct_equal(const void *v1, const void *v2); +unsigned int fluid_direct_hash(const void *v); +int fluid_int_equal(const void *v1, const void *v2); +unsigned int fluid_int_hash(const void *v); #endif /* _FLUID_HASH_H */ diff --git a/src/utils/fluid_list.c b/src/utils/fluid_list.c index 19d3b36e..c92d731f 100644 --- a/src/utils/fluid_list.c +++ b/src/utils/fluid_list.c @@ -30,27 +30,28 @@ #include "fluid_list.h" -fluid_list_t* +fluid_list_t * new_fluid_list(void) { - fluid_list_t* list; - list = (fluid_list_t*) FLUID_MALLOC(sizeof(fluid_list_t)); - list->data = NULL; - list->next = NULL; - return list; + fluid_list_t *list; + list = (fluid_list_t *) FLUID_MALLOC(sizeof(fluid_list_t)); + list->data = NULL; + list->next = NULL; + return list; } void delete_fluid_list(fluid_list_t *list) { - fluid_list_t *next; - fluid_return_if_fail(list != NULL); + fluid_list_t *next; + fluid_return_if_fail(list != NULL); - while (list) { - next = list->next; - FLUID_FREE(list); - list = next; - } + while(list) + { + next = list->next; + FLUID_FREE(list); + list = next; + } } void @@ -59,211 +60,262 @@ delete1_fluid_list(fluid_list_t *list) FLUID_FREE(list); } -fluid_list_t* -fluid_list_append(fluid_list_t *list, void* data) +fluid_list_t * +fluid_list_append(fluid_list_t *list, void *data) { - fluid_list_t *new_list; - fluid_list_t *last; + fluid_list_t *new_list; + fluid_list_t *last; - new_list = new_fluid_list(); - new_list->data = data; + new_list = new_fluid_list(); + new_list->data = data; - if (list) + if(list) { - last = fluid_list_last(list); - /* g_assert (last != NULL); */ - last->next = new_list; + last = fluid_list_last(list); + /* g_assert (last != NULL); */ + last->next = new_list; - return list; + return list; + } + else + { + return new_list; } - else - return new_list; } -fluid_list_t* -fluid_list_prepend(fluid_list_t *list, void* data) +fluid_list_t * +fluid_list_prepend(fluid_list_t *list, void *data) { - fluid_list_t *new_list; + fluid_list_t *new_list; - new_list = new_fluid_list(); - new_list->data = data; - new_list->next = list; + new_list = new_fluid_list(); + new_list->data = data; + new_list->next = list; - return new_list; + return new_list; } -fluid_list_t* +fluid_list_t * fluid_list_nth(fluid_list_t *list, int n) { - while ((n-- > 0) && list) { - list = list->next; - } - - return list; -} - -fluid_list_t* -fluid_list_remove(fluid_list_t *list, void* data) -{ - fluid_list_t *tmp; - fluid_list_t *prev; - - prev = NULL; - tmp = list; - - while (tmp) { - if (tmp->data == data) { - if (prev) { - prev->next = tmp->next; - } - if (list == tmp) { - list = list->next; - } - tmp->next = NULL; - delete_fluid_list(tmp); - - break; + while((n-- > 0) && list) + { + list = list->next; } - prev = tmp; - tmp = tmp->next; - } - - return list; + return list; } -fluid_list_t* +fluid_list_t * +fluid_list_remove(fluid_list_t *list, void *data) +{ + fluid_list_t *tmp; + fluid_list_t *prev; + + prev = NULL; + tmp = list; + + while(tmp) + { + if(tmp->data == data) + { + if(prev) + { + prev->next = tmp->next; + } + + if(list == tmp) + { + list = list->next; + } + + tmp->next = NULL; + delete_fluid_list(tmp); + + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +fluid_list_t * fluid_list_remove_link(fluid_list_t *list, fluid_list_t *link) { - fluid_list_t *tmp; - fluid_list_t *prev; + fluid_list_t *tmp; + fluid_list_t *prev; - prev = NULL; - tmp = list; + prev = NULL; + tmp = list; - while (tmp) { - if (tmp == link) { - if (prev) { - prev->next = tmp->next; - } - if (list == tmp) { - list = list->next; - } - tmp->next = NULL; - break; + while(tmp) + { + if(tmp == link) + { + if(prev) + { + prev->next = tmp->next; + } + + if(list == tmp) + { + list = list->next; + } + + tmp->next = NULL; + break; + } + + prev = tmp; + tmp = tmp->next; } - prev = tmp; - tmp = tmp->next; - } - - return list; + return list; } -static fluid_list_t* +static fluid_list_t * fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t compare_func) { - fluid_list_t list, *l; + fluid_list_t list, *l; - l = &list; + l = &list; - while (l1 && l2) { - if (compare_func(l1->data,l2->data) < 0) { - l = l->next = l1; - l1 = l1->next; - } else { - l = l->next = l2; - l2 = l2->next; + while(l1 && l2) + { + if(compare_func(l1->data, l2->data) < 0) + { + l = l->next = l1; + l1 = l1->next; + } + else + { + l = l->next = l2; + l2 = l2->next; + } } - } - l->next= l1 ? l1 : l2; - return list.next; + l->next = l1 ? l1 : l2; + + return list.next; } -fluid_list_t* +fluid_list_t * fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func) { - fluid_list_t *l1, *l2; + fluid_list_t *l1, *l2; - if (!list) { - return NULL; - } - if (!list->next) { - return list; - } + if(!list) + { + return NULL; + } - l1 = list; - l2 = list->next; + if(!list->next) + { + return list; + } - while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) - break; - l1=l1->next; - } - l2 = l1->next; - l1->next = NULL; + l1 = list; + l2 = list->next; - return fluid_list_sort_merge(fluid_list_sort(list, compare_func), - fluid_list_sort(l2, compare_func), - compare_func); + while((l2 = l2->next) != NULL) + { + if((l2 = l2->next) == NULL) + { + break; + } + + l1 = l1->next; + } + + l2 = l1->next; + l1->next = NULL; + + return fluid_list_sort_merge(fluid_list_sort(list, compare_func), + fluid_list_sort(l2, compare_func), + compare_func); } -fluid_list_t* +fluid_list_t * fluid_list_last(fluid_list_t *list) { - if (list) { - while (list->next) - list = list->next; - } + if(list) + { + while(list->next) + { + list = list->next; + } + } - return list; + return list; } int fluid_list_size(fluid_list_t *list) { - int n = 0; - while (list) { - n++; - list = list->next; - } - return n; + int n = 0; + + while(list) + { + n++; + list = list->next; + } + + return n; } -fluid_list_t* fluid_list_insert_at(fluid_list_t *list, int n, void* data) +fluid_list_t *fluid_list_insert_at(fluid_list_t *list, int n, void *data) { - fluid_list_t *new_list; - fluid_list_t *cur; - fluid_list_t *prev = NULL; + fluid_list_t *new_list; + fluid_list_t *cur; + fluid_list_t *prev = NULL; - new_list = new_fluid_list(); - new_list->data = data; + new_list = new_fluid_list(); + new_list->data = data; - cur = list; - while ((n-- > 0) && cur) { - prev = cur; - cur = cur->next; - } + cur = list; - new_list->next = cur; + while((n-- > 0) && cur) + { + prev = cur; + cur = cur->next; + } - if (prev) { - prev->next = new_list; - return list; - } else { - return new_list; - } + new_list->next = cur; + + if(prev) + { + prev->next = new_list; + return list; + } + else + { + return new_list; + } } /* Compare function to sort strings alphabetically, * for use with fluid_list_sort(). */ int -fluid_list_str_compare_func (void *a, void *b) +fluid_list_str_compare_func(void *a, void *b) { - if (a && b) return FLUID_STRCMP ((char *)a, (char *)b); - if (!a && !b) return 0; - if (a) return -1; - return 1; + if(a && b) + { + return FLUID_STRCMP((char *)a, (char *)b); + } + + if(!a && !b) + { + return 0; + } + + if(a) + { + return -1; + } + + return 1; } diff --git a/src/utils/fluid_list.h b/src/utils/fluid_list.h index 6159fe77..5be1cc39 100644 --- a/src/utils/fluid_list.h +++ b/src/utils/fluid_list.h @@ -33,30 +33,30 @@ typedef struct _fluid_list_t fluid_list_t; -typedef int (*fluid_compare_func_t)(void* a, void* b); +typedef int (*fluid_compare_func_t)(void *a, void *b); struct _fluid_list_t { - void* data; - fluid_list_t *next; + void *data; + fluid_list_t *next; }; -fluid_list_t* new_fluid_list(void); +fluid_list_t *new_fluid_list(void); void delete_fluid_list(fluid_list_t *list); void delete1_fluid_list(fluid_list_t *list); -fluid_list_t* fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func); -fluid_list_t* fluid_list_append(fluid_list_t *list, void* data); -fluid_list_t* fluid_list_prepend(fluid_list_t *list, void* data); -fluid_list_t* fluid_list_remove(fluid_list_t *list, void* data); -fluid_list_t* fluid_list_remove_link(fluid_list_t *list, fluid_list_t *llink); -fluid_list_t* fluid_list_nth(fluid_list_t *list, int n); -fluid_list_t* fluid_list_last(fluid_list_t *list); -fluid_list_t* fluid_list_insert_at(fluid_list_t *list, int n, void* data); +fluid_list_t *fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func); +fluid_list_t *fluid_list_append(fluid_list_t *list, void *data); +fluid_list_t *fluid_list_prepend(fluid_list_t *list, void *data); +fluid_list_t *fluid_list_remove(fluid_list_t *list, void *data); +fluid_list_t *fluid_list_remove_link(fluid_list_t *list, fluid_list_t *llink); +fluid_list_t *fluid_list_nth(fluid_list_t *list, int n); +fluid_list_t *fluid_list_last(fluid_list_t *list); +fluid_list_t *fluid_list_insert_at(fluid_list_t *list, int n, void *data); int fluid_list_size(fluid_list_t *list); #define fluid_list_next(slist) ((slist) ? (((fluid_list_t *)(slist))->next) : NULL) #define fluid_list_get(slist) ((slist) ? ((slist)->data) : NULL) -int fluid_list_str_compare_func (void *a, void *b); +int fluid_list_str_compare_func(void *a, void *b); #endif /* _FLUID_LIST_H */ diff --git a/src/utils/fluid_ringbuffer.c b/src/utils/fluid_ringbuffer.c index d94e9c84..71fd1e48 100644 --- a/src/utils/fluid_ringbuffer.c +++ b/src/utils/fluid_ringbuffer.c @@ -39,39 +39,39 @@ * only be one producer thread and one consumer thread. */ fluid_ringbuffer_t * -new_fluid_ringbuffer (int count, int elementsize) +new_fluid_ringbuffer(int count, int elementsize) { - fluid_ringbuffer_t *queue; + fluid_ringbuffer_t *queue; - fluid_return_val_if_fail (count > 0, NULL); + fluid_return_val_if_fail(count > 0, NULL); - queue = FLUID_NEW (fluid_ringbuffer_t); + queue = FLUID_NEW(fluid_ringbuffer_t); - if (!queue) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return NULL; - } + if(!queue) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - queue->array = FLUID_MALLOC (elementsize * count); + queue->array = FLUID_MALLOC(elementsize * count); - if (!queue->array) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - delete_fluid_ringbuffer(queue); - return NULL; - } + if(!queue->array) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + delete_fluid_ringbuffer(queue); + return NULL; + } - /* Clear array, in case dynamic pointer reclaiming is being done */ - FLUID_MEMSET (queue->array, 0, elementsize * count); + /* Clear array, in case dynamic pointer reclaiming is being done */ + FLUID_MEMSET(queue->array, 0, elementsize * count); - queue->totalcount = count; - queue->elementsize = elementsize; - fluid_atomic_int_set(&queue->count, 0); - queue->in = 0; - queue->out = 0; + queue->totalcount = count; + queue->elementsize = elementsize; + fluid_atomic_int_set(&queue->count, 0); + queue->in = 0; + queue->out = 0; - return (queue); + return (queue); } /** @@ -82,9 +82,9 @@ new_fluid_ringbuffer (int count, int elementsize) * producer threads will no longer access it. */ void -delete_fluid_ringbuffer (fluid_ringbuffer_t *queue) +delete_fluid_ringbuffer(fluid_ringbuffer_t *queue) { - fluid_return_if_fail(queue != NULL); - FLUID_FREE (queue->array); - FLUID_FREE (queue); + fluid_return_if_fail(queue != NULL); + FLUID_FREE(queue->array); + FLUID_FREE(queue); } diff --git a/src/utils/fluid_ringbuffer.h b/src/utils/fluid_ringbuffer.h index ce318647..e78d5229 100644 --- a/src/utils/fluid_ringbuffer.h +++ b/src/utils/fluid_ringbuffer.h @@ -28,20 +28,20 @@ */ struct _fluid_ringbuffer_t { - char *array; /**< Queue array of arbitrary size elements */ - int totalcount; /**< Total count of elements in array */ - fluid_atomic_int_t count; /**< Current count of elements */ - int in; /**< Index in queue to store next pushed element */ - int out; /**< Index in queue of next popped element */ - int elementsize; /**< Size of each element */ - void* userdata; + char *array; /**< Queue array of arbitrary size elements */ + int totalcount; /**< Total count of elements in array */ + fluid_atomic_int_t count; /**< Current count of elements */ + int in; /**< Index in queue to store next pushed element */ + int out; /**< Index in queue of next popped element */ + int elementsize; /**< Size of each element */ + void *userdata; }; typedef struct _fluid_ringbuffer_t fluid_ringbuffer_t; -fluid_ringbuffer_t *new_fluid_ringbuffer (int count, int elementsize); -void delete_fluid_ringbuffer (fluid_ringbuffer_t *queue); +fluid_ringbuffer_t *new_fluid_ringbuffer(int count, int elementsize); +void delete_fluid_ringbuffer(fluid_ringbuffer_t *queue); /** * Get pointer to next input array element in queue. @@ -55,11 +55,11 @@ void delete_fluid_ringbuffer (fluid_ringbuffer_t *queue); * if the queue has wrapped around. This can be used to reclaim pointers to * allocated memory, etc. */ -static FLUID_INLINE void* -fluid_ringbuffer_get_inptr (fluid_ringbuffer_t *queue, int offset) +static FLUID_INLINE void * +fluid_ringbuffer_get_inptr(fluid_ringbuffer_t *queue, int offset) { - return fluid_atomic_int_get (&queue->count) + offset >= queue->totalcount ? NULL - : queue->array + queue->elementsize * ((queue->in + offset) % queue->totalcount); + return fluid_atomic_int_get(&queue->count) + offset >= queue->totalcount ? NULL + : queue->array + queue->elementsize * ((queue->in + offset) % queue->totalcount); } /** @@ -71,13 +71,16 @@ fluid_ringbuffer_get_inptr (fluid_ringbuffer_t *queue, int offset) * operation and is split into 2 functions to avoid element copy. */ static FLUID_INLINE void -fluid_ringbuffer_next_inptr (fluid_ringbuffer_t *queue, int count) +fluid_ringbuffer_next_inptr(fluid_ringbuffer_t *queue, int count) { - fluid_atomic_int_add (&queue->count, count); + fluid_atomic_int_add(&queue->count, count); - queue->in += count; - if (queue->in >= queue->totalcount) - queue->in -= queue->totalcount; + queue->in += count; + + if(queue->in >= queue->totalcount) + { + queue->in -= queue->totalcount; + } } /** @@ -86,9 +89,9 @@ fluid_ringbuffer_next_inptr (fluid_ringbuffer_t *queue, int count) * @return amount of items currently in queue */ static FLUID_INLINE int -fluid_ringbuffer_get_count (fluid_ringbuffer_t *queue) +fluid_ringbuffer_get_count(fluid_ringbuffer_t *queue) { - return fluid_atomic_int_get (&queue->count); + return fluid_atomic_int_get(&queue->count); } @@ -101,11 +104,11 @@ fluid_ringbuffer_get_count (fluid_ringbuffer_t *queue) * This function along with fluid_ringbuffer_next_outptr() form a queue "pop" * operation and is split into 2 functions to avoid an element copy. */ -static FLUID_INLINE void* -fluid_ringbuffer_get_outptr (fluid_ringbuffer_t *queue) +static FLUID_INLINE void * +fluid_ringbuffer_get_outptr(fluid_ringbuffer_t *queue) { - return fluid_ringbuffer_get_count(queue) == 0 ? NULL - : queue->array + queue->elementsize * queue->out; + return fluid_ringbuffer_get_count(queue) == 0 ? NULL + : queue->array + queue->elementsize * queue->out; } @@ -117,12 +120,14 @@ fluid_ringbuffer_get_outptr (fluid_ringbuffer_t *queue) * operation and is split into 2 functions to avoid an element copy. */ static FLUID_INLINE void -fluid_ringbuffer_next_outptr (fluid_ringbuffer_t *queue) +fluid_ringbuffer_next_outptr(fluid_ringbuffer_t *queue) { - fluid_atomic_int_add (&queue->count, -1); + fluid_atomic_int_add(&queue->count, -1); - if (++queue->out == queue->totalcount) - queue->out = 0; + if(++queue->out == queue->totalcount) + { + queue->out = 0; + } } #endif /* _FLUID_ringbuffer_H */ diff --git a/src/utils/fluid_settings.c b/src/utils/fluid_settings.c index 0d0f17d2..71a29746 100644 --- a/src/utils/fluid_settings.c +++ b/src/utils/fluid_settings.c @@ -28,222 +28,230 @@ #include "fluid_midi.h" /* Defined in fluid_filerenderer.c */ -extern void fluid_file_renderer_settings (fluid_settings_t* settings); +extern void fluid_file_renderer_settings(fluid_settings_t *settings); /* maximum allowed components of a settings variable (separated by '.') */ #define MAX_SETTINGS_TOKENS 8 /* currently only a max of 3 are used */ #define MAX_SETTINGS_LABEL 256 /* max length of a settings variable label */ -static void fluid_settings_init(fluid_settings_t* settings); -static void fluid_settings_key_destroy_func(void* value); -static void fluid_settings_value_destroy_func(void* value); +static void fluid_settings_init(fluid_settings_t *settings); +static void fluid_settings_key_destroy_func(void *value); +static void fluid_settings_value_destroy_func(void *value); static int fluid_settings_tokenize(const char *s, char *buf, char **ptr); /* Common structure to all settings nodes */ -typedef struct { - char* value; - char* def; - int hints; - fluid_list_t* options; - fluid_str_update_t update; - void* data; +typedef struct +{ + char *value; + char *def; + int hints; + fluid_list_t *options; + fluid_str_update_t update; + void *data; } fluid_str_setting_t; -typedef struct { - double value; - double def; - double min; - double max; - int hints; - fluid_num_update_t update; - void* data; +typedef struct +{ + double value; + double def; + double min; + double max; + int hints; + fluid_num_update_t update; + void *data; } fluid_num_setting_t; -typedef struct { - int value; - int def; - int min; - int max; - int hints; - fluid_int_update_t update; - void* data; +typedef struct +{ + int value; + int def; + int min; + int max; + int hints; + fluid_int_update_t update; + void *data; } fluid_int_setting_t; -typedef struct { - fluid_hashtable_t *hashtable; +typedef struct +{ + fluid_hashtable_t *hashtable; } fluid_set_setting_t; -typedef struct { - int type; /**< fluid_types_enum */ - - union - { - fluid_str_setting_t str; - fluid_num_setting_t num; - fluid_int_setting_t i; - fluid_set_setting_t set; - }; +typedef struct +{ + int type; /**< fluid_types_enum */ + + union + { + fluid_str_setting_t str; + fluid_num_setting_t num; + fluid_int_setting_t i; + fluid_set_setting_t set; + }; } fluid_setting_node_t; -static fluid_setting_node_t* -new_fluid_str_setting(const char* value, const char* def, int hints) +static fluid_setting_node_t * +new_fluid_str_setting(const char *value, const char *def, int hints) { - fluid_setting_node_t* node; - fluid_str_setting_t* str; - - node = FLUID_NEW(fluid_setting_node_t); + fluid_setting_node_t *node; + fluid_str_setting_t *str; - if (!node) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + node = FLUID_NEW(fluid_setting_node_t); - node->type = FLUID_STR_TYPE; - - str = &node->str; - str->value = value? FLUID_STRDUP(value) : NULL; - str->def = def? FLUID_STRDUP(def) : NULL; - str->hints = hints; - str->options = NULL; - str->update = NULL; - str->data = NULL; - return node; -} - -static void -delete_fluid_str_setting(fluid_setting_node_t* node) -{ - fluid_return_if_fail(node != NULL); - - FLUID_ASSERT(node->type == FLUID_STR_TYPE); - - FLUID_FREE(node->str.value); - FLUID_FREE(node->str.def); - - if (node->str.options) { - fluid_list_t* list = node->str.options; - - while (list) { - FLUID_FREE (list->data); - list = fluid_list_next(list); + if(!node) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - delete_fluid_list(node->str.options); - } + node->type = FLUID_STR_TYPE; - FLUID_FREE(node); + str = &node->str; + str->value = value ? FLUID_STRDUP(value) : NULL; + str->def = def ? FLUID_STRDUP(def) : NULL; + str->hints = hints; + str->options = NULL; + str->update = NULL; + str->data = NULL; + return node; +} + +static void +delete_fluid_str_setting(fluid_setting_node_t *node) +{ + fluid_return_if_fail(node != NULL); + + FLUID_ASSERT(node->type == FLUID_STR_TYPE); + + FLUID_FREE(node->str.value); + FLUID_FREE(node->str.def); + + if(node->str.options) + { + fluid_list_t *list = node->str.options; + + while(list) + { + FLUID_FREE(list->data); + list = fluid_list_next(list); + } + + delete_fluid_list(node->str.options); + } + + FLUID_FREE(node); } -static fluid_setting_node_t* +static fluid_setting_node_t * new_fluid_num_setting(double min, double max, double def, int hints) { - fluid_setting_node_t* node; - fluid_num_setting_t* num; + fluid_setting_node_t *node; + fluid_num_setting_t *num; - node = FLUID_NEW(fluid_setting_node_t); + node = FLUID_NEW(fluid_setting_node_t); - if (!node) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + if(!node) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - node->type = FLUID_NUM_TYPE; + node->type = FLUID_NUM_TYPE; - num = &node->num; - num->value = def; - num->def = def; - num->min = min; - num->max = max; - num->hints = hints; - num->update = NULL; - num->data = NULL; - - return node; + num = &node->num; + num->value = def; + num->def = def; + num->min = min; + num->max = max; + num->hints = hints; + num->update = NULL; + num->data = NULL; + + return node; } static void -delete_fluid_num_setting(fluid_setting_node_t* node) +delete_fluid_num_setting(fluid_setting_node_t *node) { - fluid_return_if_fail(node != NULL); - - FLUID_ASSERT (node->type == FLUID_NUM_TYPE); - FLUID_FREE(node); + fluid_return_if_fail(node != NULL); + + FLUID_ASSERT(node->type == FLUID_NUM_TYPE); + FLUID_FREE(node); } -static fluid_setting_node_t* +static fluid_setting_node_t * new_fluid_int_setting(int min, int max, int def, int hints) { - fluid_setting_node_t* node; - fluid_int_setting_t* i; + fluid_setting_node_t *node; + fluid_int_setting_t *i; - node = FLUID_NEW(fluid_setting_node_t); + node = FLUID_NEW(fluid_setting_node_t); - if (!node) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + if(!node) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - node->type = FLUID_INT_TYPE; + node->type = FLUID_INT_TYPE; - i = &node->i; - i->value = def; - i->def = def; - i->min = min; - i->max = max; - i->hints = hints; - i->update = NULL; - i->data = NULL; - return node; + i = &node->i; + i->value = def; + i->def = def; + i->min = min; + i->max = max; + i->hints = hints; + i->update = NULL; + i->data = NULL; + return node; } static void -delete_fluid_int_setting(fluid_setting_node_t* node) +delete_fluid_int_setting(fluid_setting_node_t *node) { fluid_return_if_fail(node != NULL); - - FLUID_ASSERT (node->type == FLUID_INT_TYPE); - FLUID_FREE(node); + + FLUID_ASSERT(node->type == FLUID_INT_TYPE); + FLUID_FREE(node); } -static fluid_setting_node_t* +static fluid_setting_node_t * new_fluid_set_setting(void) { - fluid_setting_node_t* node; - fluid_set_setting_t* set; + fluid_setting_node_t *node; + fluid_set_setting_t *set; - node = FLUID_NEW(fluid_setting_node_t); + node = FLUID_NEW(fluid_setting_node_t); - if (!node) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } + if(!node) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } - node->type = FLUID_SET_TYPE; - set = &node->set; - - set->hashtable = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal, - fluid_settings_key_destroy_func, - fluid_settings_value_destroy_func); - if (!set->hashtable) - { - FLUID_FREE (node); - return NULL; - } + node->type = FLUID_SET_TYPE; + set = &node->set; - return node; + set->hashtable = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal, + fluid_settings_key_destroy_func, + fluid_settings_value_destroy_func); + + if(!set->hashtable) + { + FLUID_FREE(node); + return NULL; + } + + return node; } static void -delete_fluid_set_setting(fluid_setting_node_t* node) +delete_fluid_set_setting(fluid_setting_node_t *node) { fluid_return_if_fail(node != NULL); - - FLUID_ASSERT (node->type == FLUID_SET_TYPE); + + FLUID_ASSERT(node->type == FLUID_SET_TYPE); delete_fluid_hashtable(node->set.hashtable); FLUID_FREE(node); } @@ -255,16 +263,20 @@ delete_fluid_set_setting(fluid_setting_node_t* node) fluid_settings_t * new_fluid_settings(void) { - fluid_settings_t* settings; + fluid_settings_t *settings; - settings = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal, - fluid_settings_key_destroy_func, - fluid_settings_value_destroy_func); - if (settings == NULL) return NULL; + settings = new_fluid_hashtable_full(fluid_str_hash, fluid_str_equal, + fluid_settings_key_destroy_func, + fluid_settings_value_destroy_func); - fluid_rec_mutex_init (settings->mutex); - fluid_settings_init(settings); - return settings; + if(settings == NULL) + { + return NULL; + } + + fluid_rec_mutex_init(settings->mutex); + fluid_settings_init(settings); + return settings; } /** @@ -272,84 +284,91 @@ new_fluid_settings(void) * @param settings a settings object */ void -delete_fluid_settings(fluid_settings_t* settings) +delete_fluid_settings(fluid_settings_t *settings) { - fluid_return_if_fail (settings != NULL); + fluid_return_if_fail(settings != NULL); - fluid_rec_mutex_destroy (settings->mutex); - delete_fluid_hashtable(settings); + fluid_rec_mutex_destroy(settings->mutex); + delete_fluid_hashtable(settings); } /* Settings hash key destroy function */ static void -fluid_settings_key_destroy_func(void* value) +fluid_settings_key_destroy_func(void *value) { - FLUID_FREE (value); /* Free the string key value */ + FLUID_FREE(value); /* Free the string key value */ } /* Settings hash value destroy function */ static void -fluid_settings_value_destroy_func(void* value) +fluid_settings_value_destroy_func(void *value) { - fluid_setting_node_t *node = value; + fluid_setting_node_t *node = value; - switch (node->type) { - case FLUID_NUM_TYPE: - delete_fluid_num_setting(node); - break; - case FLUID_INT_TYPE: - delete_fluid_int_setting(node); - break; - case FLUID_STR_TYPE: - delete_fluid_str_setting(node); - break; - case FLUID_SET_TYPE: - delete_fluid_set_setting(node); - break; - } + switch(node->type) + { + case FLUID_NUM_TYPE: + delete_fluid_num_setting(node); + break; + + case FLUID_INT_TYPE: + delete_fluid_int_setting(node); + break; + + case FLUID_STR_TYPE: + delete_fluid_str_setting(node); + break; + + case FLUID_SET_TYPE: + delete_fluid_set_setting(node); + break; + } } void -fluid_settings_init(fluid_settings_t* settings) +fluid_settings_init(fluid_settings_t *settings) { - fluid_return_if_fail (settings != NULL); + fluid_return_if_fail(settings != NULL); - fluid_synth_settings(settings); - fluid_shell_settings(settings); - fluid_player_settings(settings); - fluid_file_renderer_settings(settings); - fluid_audio_driver_settings(settings); - fluid_midi_driver_settings(settings); + fluid_synth_settings(settings); + fluid_shell_settings(settings); + fluid_player_settings(settings); + fluid_file_renderer_settings(settings); + fluid_audio_driver_settings(settings); + fluid_midi_driver_settings(settings); } static int fluid_settings_tokenize(const char *s, char *buf, char **ptr) { - char *tokstr, *tok; - int n = 0; + char *tokstr, *tok; + int n = 0; - if (strlen (s) > MAX_SETTINGS_LABEL) - { - FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars", - MAX_SETTINGS_LABEL); - return 0; - } - - FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */ - tokstr = buf; - - while ((tok = fluid_strtok (&tokstr, "."))) - { - if (n >= MAX_SETTINGS_TOKENS) + if(strlen(s) > MAX_SETTINGS_LABEL) { - FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d", - MAX_SETTINGS_TOKENS); - return 0; - } else - ptr[n++] = tok; - } + FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars", + MAX_SETTINGS_LABEL); + return 0; + } - return n; + FLUID_STRCPY(buf, s); /* copy string to buffer, since it gets modified */ + tokstr = buf; + + while((tok = fluid_strtok(&tokstr, "."))) + { + if(n >= MAX_SETTINGS_TOKENS) + { + FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max token count of %d", + MAX_SETTINGS_TOKENS); + return 0; + } + else + { + ptr[n++] = tok; + } + } + + return n; } /** @@ -361,31 +380,42 @@ fluid_settings_tokenize(const char *s, char *buf, char **ptr) * @return #FLUID_OK if the node exists, #FLUID_FAILED otherwise */ static int -fluid_settings_get(fluid_settings_t* settings, const char *name, +fluid_settings_get(fluid_settings_t *settings, const char *name, fluid_setting_node_t **value) { - fluid_hashtable_t* table = settings; - fluid_setting_node_t *node = NULL; - char* tokens[MAX_SETTINGS_TOKENS]; - char buf[MAX_SETTINGS_LABEL+1]; - int ntokens; - int n; + fluid_hashtable_t *table = settings; + fluid_setting_node_t *node = NULL; + char *tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL + 1]; + int ntokens; + int n; - ntokens = fluid_settings_tokenize (name, buf, tokens); + ntokens = fluid_settings_tokenize(name, buf, tokens); - if (table == NULL || ntokens <= 0) return FLUID_FAILED; + if(table == NULL || ntokens <= 0) + { + return FLUID_FAILED; + } - for (n = 0; n < ntokens; n++) { + for(n = 0; n < ntokens; n++) + { - node = fluid_hashtable_lookup(table, tokens[n]); - if (!node) return FLUID_FAILED; + node = fluid_hashtable_lookup(table, tokens[n]); - table = (node->type == FLUID_SET_TYPE) ? node->set.hashtable : NULL; - } + if(!node) + { + return FLUID_FAILED; + } - if (value) *value = node; + table = (node->type == FLUID_SET_TYPE) ? node->set.hashtable : NULL; + } - return FLUID_OK; + if(value) + { + *value = node; + } + + return FLUID_OK; } /** @@ -397,73 +427,92 @@ fluid_settings_get(fluid_settings_t* settings, const char *name, * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise */ static int -fluid_settings_set(fluid_settings_t* settings, const char *name, fluid_setting_node_t* value) +fluid_settings_set(fluid_settings_t *settings, const char *name, fluid_setting_node_t *value) { - fluid_hashtable_t* table = settings; - fluid_setting_node_t *node; - char* tokens[MAX_SETTINGS_TOKENS]; - char buf[MAX_SETTINGS_LABEL+1]; - int n, num; - char *dupname; + fluid_hashtable_t *table = settings; + fluid_setting_node_t *node; + char *tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL + 1]; + int n, num; + char *dupname; - num = fluid_settings_tokenize (name, buf, tokens); - if (num == 0) - return FLUID_FAILED; - - num--; - - for (n = 0; n < num; n++) { - - node = fluid_hashtable_lookup(table, tokens[n]); - - if (node) { - - if (node->type == FLUID_SET_TYPE) { - table = node->set.hashtable; - } else { - /* path ends prematurely */ - FLUID_LOG(FLUID_WARN, "'%s' is not a node. Name of the setting was '%s'", tokens[n], name); - return FLUID_FAILED; - } - - } else { - /* create a new node */ - fluid_setting_node_t* setnode; - - dupname = FLUID_STRDUP (tokens[n]); - setnode = new_fluid_set_setting (); - - if (!dupname || !setnode) - { - if (dupname) FLUID_FREE (dupname); - else FLUID_LOG(FLUID_ERR, "Out of memory"); - - if (setnode) delete_fluid_set_setting (setnode); + num = fluid_settings_tokenize(name, buf, tokens); + if(num == 0) + { return FLUID_FAILED; - } - - fluid_hashtable_insert(table, dupname, setnode); - table = setnode->set.hashtable; } - } - dupname = FLUID_STRDUP (tokens[num]); + num--; - if (!dupname) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return FLUID_FAILED; - } + for(n = 0; n < num; n++) + { - fluid_hashtable_insert(table, dupname, value); + node = fluid_hashtable_lookup(table, tokens[n]); - return FLUID_OK; + if(node) + { + + if(node->type == FLUID_SET_TYPE) + { + table = node->set.hashtable; + } + else + { + /* path ends prematurely */ + FLUID_LOG(FLUID_WARN, "'%s' is not a node. Name of the setting was '%s'", tokens[n], name); + return FLUID_FAILED; + } + + } + else + { + /* create a new node */ + fluid_setting_node_t *setnode; + + dupname = FLUID_STRDUP(tokens[n]); + setnode = new_fluid_set_setting(); + + if(!dupname || !setnode) + { + if(dupname) + { + FLUID_FREE(dupname); + } + else + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + } + + if(setnode) + { + delete_fluid_set_setting(setnode); + } + + return FLUID_FAILED; + } + + fluid_hashtable_insert(table, dupname, setnode); + table = setnode->set.hashtable; + } + } + + dupname = FLUID_STRDUP(tokens[num]); + + if(!dupname) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; + } + + fluid_hashtable_insert(table, dupname, value); + + return FLUID_OK; } /** * Registers a new string value for the specified setting. - * + * * @param settings a settings object * @param name the setting's name * @param def the default value for the setting @@ -471,41 +520,51 @@ fluid_settings_set(fluid_settings_t* settings, const char *name, fluid_setting_n * @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise */ int -fluid_settings_register_str(fluid_settings_t* settings, const char* name, const char* def, int hints) +fluid_settings_register_str(fluid_settings_t *settings, const char *name, const char *def, int hints) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) != FLUID_OK) { - node = new_fluid_str_setting(def, def, hints); - retval = fluid_settings_set(settings, name, node); - if (retval != FLUID_OK) delete_fluid_str_setting (node); - } else { - /* if variable already exists, don't change its value. */ - if (node->type == FLUID_STR_TYPE) { - fluid_str_setting_t* setting = &node->str; - setting->def = def? FLUID_STRDUP(def) : NULL; - setting->hints = hints; - retval = FLUID_OK; - } else { - FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name); + if(fluid_settings_get(settings, name, &node) != FLUID_OK) + { + node = new_fluid_str_setting(def, def, hints); + retval = fluid_settings_set(settings, name, node); + + if(retval != FLUID_OK) + { + delete_fluid_str_setting(node); + } + } + else + { + /* if variable already exists, don't change its value. */ + if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; + setting->def = def ? FLUID_STRDUP(def) : NULL; + setting->hints = hints; + retval = FLUID_OK; + } + else + { + FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name); + } } - } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** * Registers a new float value for the specified setting. - * + * * @param settings a settings object * @param name the setting's name * @param def the default value for the setting @@ -515,49 +574,59 @@ fluid_settings_register_str(fluid_settings_t* settings, const char* name, const * @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise */ int -fluid_settings_register_num(fluid_settings_t* settings, const char* name, double def, - double min, double max, int hints) +fluid_settings_register_num(fluid_settings_t *settings, const char *name, double def, + double min, double max, int hints) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); - /* For now, all floating point settings are bounded below and above */ - hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE; + /* For now, all floating point settings are bounded below and above */ + hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE; - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) != FLUID_OK) { - /* insert a new setting */ - node = new_fluid_num_setting(min, max, def, hints); - retval = fluid_settings_set(settings, name, node); - if (retval != FLUID_OK) delete_fluid_num_setting (node); - } else { - if (node->type == FLUID_NUM_TYPE) { - /* update the existing setting but don't change its value */ - fluid_num_setting_t* setting = &node->num; - setting->min = min; - setting->max = max; - setting->def = def; - setting->hints = hints; - retval = FLUID_OK; - } else { - /* type mismatch */ - FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name); + if(fluid_settings_get(settings, name, &node) != FLUID_OK) + { + /* insert a new setting */ + node = new_fluid_num_setting(min, max, def, hints); + retval = fluid_settings_set(settings, name, node); + + if(retval != FLUID_OK) + { + delete_fluid_num_setting(node); + } + } + else + { + if(node->type == FLUID_NUM_TYPE) + { + /* update the existing setting but don't change its value */ + fluid_num_setting_t *setting = &node->num; + setting->min = min; + setting->max = max; + setting->def = def; + setting->hints = hints; + retval = FLUID_OK; + } + else + { + /* type mismatch */ + FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name); + } } - } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** * Registers a new integer value for the specified setting. - * + * * @param settings a settings object * @param name the setting's name * @param def the default value for the setting @@ -567,44 +636,54 @@ fluid_settings_register_num(fluid_settings_t* settings, const char* name, double * @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise */ int -fluid_settings_register_int(fluid_settings_t* settings, const char* name, int def, - int min, int max, int hints) +fluid_settings_register_int(fluid_settings_t *settings, const char *name, int def, + int min, int max, int hints) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); - /* For now, all integer settings are bounded below and above */ - hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE; + /* For now, all integer settings are bounded below and above */ + hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE; - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) != FLUID_OK) { - /* insert a new setting */ - node = new_fluid_int_setting(min, max, def, hints); - retval = fluid_settings_set(settings, name, node); - if (retval != FLUID_OK) delete_fluid_int_setting (node); - } else { - if (node->type == FLUID_INT_TYPE) { - /* update the existing setting but don't change its value */ - fluid_int_setting_t* setting = &node->i; - setting->min = min; - setting->max = max; - setting->def = def; - setting->hints = hints; - retval = FLUID_OK; - } else { - /* type mismatch */ - FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name); + if(fluid_settings_get(settings, name, &node) != FLUID_OK) + { + /* insert a new setting */ + node = new_fluid_int_setting(min, max, def, hints); + retval = fluid_settings_set(settings, name, node); + + if(retval != FLUID_OK) + { + delete_fluid_int_setting(node); + } + } + else + { + if(node->type == FLUID_INT_TYPE) + { + /* update the existing setting but don't change its value */ + fluid_int_setting_t *setting = &node->i; + setting->min = min; + setting->max = max; + setting->def = def; + setting->hints = hints; + retval = FLUID_OK; + } + else + { + /* type mismatch */ + FLUID_LOG(FLUID_WARN, "Type mismatch on setting '%s'", name); + } } - } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -616,20 +695,20 @@ fluid_settings_register_int(fluid_settings_t* settings, const char* name, int de * @param data user supplied data passed to the update function * @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise */ -int fluid_settings_callback_str(fluid_settings_t* settings, const char* name, - fluid_str_update_t callback, void* data) +int fluid_settings_callback_str(fluid_settings_t *settings, const char *name, + fluid_str_update_t callback, void *data) { fluid_setting_node_t *node; fluid_str_setting_t *setting; - fluid_return_val_if_fail (settings != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED); + fluid_return_val_if_fail(settings != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if ((fluid_settings_get(settings, name, &node) != FLUID_OK) - || node->type != FLUID_STR_TYPE) + if((fluid_settings_get(settings, name, &node) != FLUID_OK) + || node->type != FLUID_STR_TYPE) { fluid_rec_mutex_unlock(settings->mutex); return FLUID_FAILED; @@ -652,20 +731,20 @@ int fluid_settings_callback_str(fluid_settings_t* settings, const char* name, * @param data user supplied data passed to the update function * @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise */ -int fluid_settings_callback_num(fluid_settings_t* settings, const char* name, - fluid_num_update_t callback, void* data) +int fluid_settings_callback_num(fluid_settings_t *settings, const char *name, + fluid_num_update_t callback, void *data) { fluid_setting_node_t *node; fluid_num_setting_t *setting; - fluid_return_val_if_fail (settings != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED); + fluid_return_val_if_fail(settings != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if ((fluid_settings_get(settings, name, &node) != FLUID_OK) - || node->type != FLUID_NUM_TYPE) + if((fluid_settings_get(settings, name, &node) != FLUID_OK) + || node->type != FLUID_NUM_TYPE) { fluid_rec_mutex_unlock(settings->mutex); return FLUID_FAILED; @@ -688,20 +767,20 @@ int fluid_settings_callback_num(fluid_settings_t* settings, const char* name, * @param data user supplied data passed to the update function * @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise */ -int fluid_settings_callback_int(fluid_settings_t* settings, const char* name, - fluid_int_update_t callback, void* data) +int fluid_settings_callback_int(fluid_settings_t *settings, const char *name, + fluid_int_update_t callback, void *data) { fluid_setting_node_t *node; fluid_int_setting_t *setting; - fluid_return_val_if_fail (settings != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED); + fluid_return_val_if_fail(settings != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if ((fluid_settings_get(settings, name, &node) != FLUID_OK) - || node->type != FLUID_INT_TYPE) + if((fluid_settings_get(settings, name, &node) != FLUID_OK) + || node->type != FLUID_INT_TYPE) { fluid_rec_mutex_unlock(settings->mutex); return FLUID_FAILED; @@ -723,22 +802,25 @@ int fluid_settings_callback_int(fluid_settings_t* settings, const char* name, * @return the type for the named setting (see #fluid_types_enum), or #FLUID_NO_TYPE when it does not exist */ int -fluid_settings_get_type(fluid_settings_t* settings, const char *name) +fluid_settings_get_type(fluid_settings_t *settings, const char *name) { - fluid_setting_node_t *node; - int type = FLUID_NO_TYPE; + fluid_setting_node_t *node; + int type = FLUID_NO_TYPE; - fluid_return_val_if_fail (settings != NULL, type); - fluid_return_val_if_fail (name != NULL, type); - fluid_return_val_if_fail (name[0] != '\0', type); + fluid_return_val_if_fail(settings != NULL, type); + fluid_return_val_if_fail(name != NULL, type); + fluid_return_val_if_fail(name[0] != '\0', type); - fluid_rec_mutex_lock (settings->mutex); - if(fluid_settings_get (settings, name, &node) == FLUID_OK) - type = node->type; - - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - return type; + if(fluid_settings_get(settings, name, &node) == FLUID_OK) + { + type = node->type; + } + + fluid_rec_mutex_unlock(settings->mutex); + + return type; } /** @@ -750,36 +832,42 @@ fluid_settings_get_type(fluid_settings_t* settings, const char *name) * @return #FLUID_OK if hints associated to the named setting exist, #FLUID_FAILED otherwise */ int -fluid_settings_get_hints(fluid_settings_t* settings, const char *name, int* hints) +fluid_settings_get_hints(fluid_settings_t *settings, const char *name, int *hints) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK) { - if (node->type == FLUID_NUM_TYPE) { - fluid_num_setting_t* setting = &node->num; - *hints = setting->hints; - retval = FLUID_OK; - } else if (node->type == FLUID_STR_TYPE) { - fluid_str_setting_t* setting = &node->str; - *hints = setting->hints; - retval = FLUID_OK; - } else if (node->type == FLUID_INT_TYPE) { - fluid_int_setting_t* setting = &node->i; - *hints = setting->hints; - retval = FLUID_OK; + if(fluid_settings_get(settings, name, &node) == FLUID_OK) + { + if(node->type == FLUID_NUM_TYPE) + { + fluid_num_setting_t *setting = &node->num; + *hints = setting->hints; + retval = FLUID_OK; + } + else if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; + *hints = setting->hints; + retval = FLUID_OK; + } + else if(node->type == FLUID_INT_TYPE) + { + fluid_int_setting_t *setting = &node->i; + *hints = setting->hints; + retval = FLUID_OK; + } } - } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -790,33 +878,39 @@ fluid_settings_get_hints(fluid_settings_t* settings, const char *name, int* hint * @return TRUE if the setting is changeable in real-time, FALSE otherwise */ int -fluid_settings_is_realtime(fluid_settings_t* settings, const char *name) +fluid_settings_is_realtime(fluid_settings_t *settings, const char *name) { - fluid_setting_node_t *node; - int isrealtime = FALSE; + fluid_setting_node_t *node; + int isrealtime = FALSE; - fluid_return_val_if_fail (settings != NULL, 0); - fluid_return_val_if_fail (name != NULL, 0); - fluid_return_val_if_fail (name[0] != '\0', 0); + fluid_return_val_if_fail(settings != NULL, 0); + fluid_return_val_if_fail(name != NULL, 0); + fluid_return_val_if_fail(name[0] != '\0', 0); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK) { - if (node->type == FLUID_NUM_TYPE) { - fluid_num_setting_t* setting = &node->num; - isrealtime = setting->update != NULL; - } else if (node->type == FLUID_STR_TYPE) { - fluid_str_setting_t* setting = &node->str; - isrealtime = setting->update != NULL; - } else if (node->type == FLUID_INT_TYPE) { - fluid_int_setting_t* setting = &node->i; - isrealtime = setting->update != NULL; + if(fluid_settings_get(settings, name, &node) == FLUID_OK) + { + if(node->type == FLUID_NUM_TYPE) + { + fluid_num_setting_t *setting = &node->num; + isrealtime = setting->update != NULL; + } + else if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; + isrealtime = setting->update != NULL; + } + else if(node->type == FLUID_INT_TYPE) + { + fluid_int_setting_t *setting = &node->i; + isrealtime = setting->update != NULL; + } } - } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return isrealtime; + return isrealtime; } /** @@ -828,57 +922,63 @@ fluid_settings_is_realtime(fluid_settings_t* settings, const char *name) * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise */ int -fluid_settings_setstr(fluid_settings_t* settings, const char *name, const char *str) +fluid_settings_setstr(fluid_settings_t *settings, const char *name, const char *str) { - fluid_setting_node_t *node; - fluid_str_setting_t *setting; - char *new_value = NULL; - fluid_str_update_t callback = NULL; - void *data = NULL; + fluid_setting_node_t *node; + fluid_str_setting_t *setting; + char *new_value = NULL; + fluid_str_update_t callback = NULL; + void *data = NULL; - fluid_return_val_if_fail (settings != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED); + fluid_return_val_if_fail(settings != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if ((fluid_settings_get (settings, name, &node) != FLUID_OK) - || (node->type != FLUID_STR_TYPE)) { + if((fluid_settings_get(settings, name, &node) != FLUID_OK) + || (node->type != FLUID_STR_TYPE)) + { goto error_recovery; - } - - setting = &node->str; - - if (setting->value) { - FLUID_FREE (setting->value); - } - - if (str) { - new_value = FLUID_STRDUP (str); - if (new_value == NULL) { - FLUID_LOG (FLUID_ERR, "Out of memory"); - goto error_recovery; } - } - setting->value = new_value; + setting = &node->str; - callback = setting->update; - data = setting->data; + if(setting->value) + { + FLUID_FREE(setting->value); + } - /* Release the mutex before calling the update callback, to avoid - * possible deadlocks with FluidSynths API lock */ - fluid_rec_mutex_unlock (settings->mutex); + if(str) + { + new_value = FLUID_STRDUP(str); - if (callback) { - (*callback)(data, name, new_value); - } + if(new_value == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + goto error_recovery; + } + } - return FLUID_OK; + setting->value = new_value; + + callback = setting->update; + data = setting->data; + + /* Release the mutex before calling the update callback, to avoid + * possible deadlocks with FluidSynths API lock */ + fluid_rec_mutex_unlock(settings->mutex); + + if(callback) + { + (*callback)(data, name, new_value); + } + + return FLUID_OK; error_recovery: - fluid_rec_mutex_unlock (settings->mutex); - return FLUID_FAILED; + fluid_rec_mutex_unlock(settings->mutex); + return FLUID_FAILED; } /** @@ -894,51 +994,51 @@ error_recovery: * @note A size of 256 should be more than sufficient for the string buffer. */ int -fluid_settings_copystr(fluid_settings_t* settings, const char *name, +fluid_settings_copystr(fluid_settings_t *settings, const char *name, char *str, int len) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (str != NULL, retval); - fluid_return_val_if_fail (len > 0, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(str != NULL, retval); + fluid_return_val_if_fail(len > 0, retval); - str[0] = 0; + str[0] = 0; - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get (settings, name, &node) == FLUID_OK) - { - if (node->type == FLUID_STR_TYPE) + if(fluid_settings_get(settings, name, &node) == FLUID_OK) { - fluid_str_setting_t *setting = &node->str; + if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; - if (setting->value) - { - FLUID_STRNCPY (str, setting->value, len); - } + if(setting->value) + { + FLUID_STRNCPY(str, setting->value, len); + } - retval = FLUID_OK; + retval = FLUID_OK; + } + else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ + { + fluid_int_setting_t *setting = &node->i; + + if(setting->hints & FLUID_HINT_TOGGLED) + { + FLUID_STRNCPY(str, setting->value ? "yes" : "no", len); + + retval = FLUID_OK; + } + } } - else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ - { - fluid_int_setting_t *setting = &node->i; - if (setting->hints & FLUID_HINT_TOGGLED) - { - FLUID_STRNCPY (str, setting->value ? "yes" : "no", len); + fluid_rec_mutex_unlock(settings->mutex); - retval = FLUID_OK; - } - } - } - - fluid_rec_mutex_unlock (settings->mutex); - - return retval; + return retval; } /** @@ -953,49 +1053,63 @@ fluid_settings_copystr(fluid_settings_t* settings, const char *name, * owns the string and should free it with free() when done using it. */ int -fluid_settings_dupstr(fluid_settings_t* settings, const char *name, char** str) +fluid_settings_dupstr(fluid_settings_t *settings, const char *name, char **str) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (str != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(str != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK) - { - if (node->type == FLUID_STR_TYPE) + if(fluid_settings_get(settings, name, &node) == FLUID_OK) { - fluid_str_setting_t *setting = &node->str; + if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; - if (setting->value) - { - *str = FLUID_STRDUP (setting->value); - if (!*str) FLUID_LOG (FLUID_ERR, "Out of memory"); - } + if(setting->value) + { + *str = FLUID_STRDUP(setting->value); - if (!setting->value || *str) retval = FLUID_OK; /* Don't set to FLUID_OK if out of memory */ + if(!*str) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + } + } + + if(!setting->value || *str) + { + retval = FLUID_OK; /* Don't set to FLUID_OK if out of memory */ + } + } + else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ + { + fluid_int_setting_t *setting = &node->i; + + if(setting->hints & FLUID_HINT_TOGGLED) + { + *str = FLUID_STRDUP(setting->value ? "yes" : "no"); + + if(!*str) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + } + + if(!setting->value || *str) + { + retval = FLUID_OK; /* Don't set to FLUID_OK if out of memory */ + } + } + } } - else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ - { - fluid_int_setting_t *setting = &node->i; - if (setting->hints & FLUID_HINT_TOGGLED) - { - *str = FLUID_STRDUP (setting->value ? "yes" : "no"); - if (!*str) FLUID_LOG (FLUID_ERR, "Out of memory"); + fluid_rec_mutex_unlock(settings->mutex); - if (!setting->value || *str) retval = FLUID_OK; /* Don't set to FLUID_OK if out of memory */ - } - } - } - - fluid_rec_mutex_unlock (settings->mutex); - - return retval; + return retval; } @@ -1008,38 +1122,43 @@ fluid_settings_dupstr(fluid_settings_t* settings, const char *name, char** str) * @return TRUE if the value exists and is equal to 's', FALSE otherwise */ int -fluid_settings_str_equal (fluid_settings_t* settings, const char *name, const char *s) +fluid_settings_str_equal(fluid_settings_t *settings, const char *name, const char *s) { - fluid_setting_node_t *node; - int retval = FALSE; + fluid_setting_node_t *node; + int retval = FALSE; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (s != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(s != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get (settings, name, &node) == FLUID_OK) - { - if (node->type == FLUID_STR_TYPE) + if(fluid_settings_get(settings, name, &node) == FLUID_OK) { - fluid_str_setting_t *setting = &node->str; - if (setting->value) - retval = FLUID_STRCMP (setting->value, s) == 0; + if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; + + if(setting->value) + { + retval = FLUID_STRCMP(setting->value, s) == 0; + } + } + else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ + { + fluid_int_setting_t *setting = &node->i; + + if(setting->hints & FLUID_HINT_TOGGLED) + { + retval = FLUID_STRCMP(setting->value ? "yes" : "no", s) == 0; + } + } } - else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ - { - fluid_int_setting_t *setting = &node->i; - if (setting->hints & FLUID_HINT_TOGGLED) - retval = FLUID_STRCMP (setting->value ? "yes" : "no", s) == 0; - } - } + fluid_rec_mutex_unlock(settings->mutex); - fluid_rec_mutex_unlock (settings->mutex); - - return retval; + return retval; } /** @@ -1052,37 +1171,39 @@ fluid_settings_str_equal (fluid_settings_t* settings, const char *name, const ch * @return FLUID_OK on success, FLUID_FAILED otherwise */ int -fluid_settings_getstr_default(fluid_settings_t* settings, const char *name, char** def) +fluid_settings_getstr_default(fluid_settings_t *settings, const char *name, char **def) { - fluid_setting_node_t *node; - char *retval = NULL; + fluid_setting_node_t *node; + char *retval = NULL; - fluid_return_val_if_fail (settings != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED); + fluid_return_val_if_fail(settings != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get (settings, name, &node) == FLUID_OK) - { - if (node->type == FLUID_STR_TYPE) + if(fluid_settings_get(settings, name, &node) == FLUID_OK) { - fluid_str_setting_t* setting = &node->str; - retval = setting->def; + if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; + retval = setting->def; + } + else if(node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ + { + fluid_int_setting_t *setting = &node->i; + + if(setting->hints & FLUID_HINT_TOGGLED) + { + retval = setting->def ? "yes" : "no"; + } + } } - else if (node->type == FLUID_INT_TYPE) /* Handle boolean integers for backwards compatibility */ - { - fluid_int_setting_t *setting = &node->i; - if (setting->hints & FLUID_HINT_TOGGLED) - retval = setting->def ? "yes" : "no"; - } - } + *def = retval; + fluid_rec_mutex_unlock(settings->mutex); - *def = retval; - fluid_rec_mutex_unlock (settings->mutex); - - return retval != NULL ? FLUID_OK : FLUID_FAILED; + return retval != NULL ? FLUID_OK : FLUID_FAILED; } /** @@ -1095,30 +1216,31 @@ fluid_settings_getstr_default(fluid_settings_t* settings, const char *name, char * Causes the setting's #FLUID_HINT_OPTIONLIST hint to be set. */ int -fluid_settings_add_option(fluid_settings_t* settings, const char *name, const char *s) +fluid_settings_add_option(fluid_settings_t *settings, const char *name, const char *s) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (s != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(s != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_STR_TYPE)) { - fluid_str_setting_t* setting = &node->str; - char* copy = FLUID_STRDUP(s); - setting->options = fluid_list_append(setting->options, copy); - setting->hints |= FLUID_HINT_OPTIONLIST; - retval = FLUID_OK; - } + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_STR_TYPE)) + { + fluid_str_setting_t *setting = &node->str; + char *copy = FLUID_STRDUP(s); + setting->options = fluid_list_append(setting->options, copy); + setting->hints |= FLUID_HINT_OPTIONLIST; + retval = FLUID_OK; + } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -1129,39 +1251,44 @@ fluid_settings_add_option(fluid_settings_t* settings, const char *name, const ch * @return #FLUID_OK if the setting exists and option was removed, #FLUID_FAILED otherwise */ int -fluid_settings_remove_option(fluid_settings_t* settings, const char *name, const char* s) +fluid_settings_remove_option(fluid_settings_t *settings, const char *name, const char *s) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (s != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(s != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_STR_TYPE)) { + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_STR_TYPE)) + { - fluid_str_setting_t* setting = &node->str; - fluid_list_t* list = setting->options; + fluid_str_setting_t *setting = &node->str; + fluid_list_t *list = setting->options; - while (list) { - char* option = (char*) fluid_list_get(list); - if (FLUID_STRCMP(s, option) == 0) { - FLUID_FREE (option); - setting->options = fluid_list_remove_link(setting->options, list); - retval = FLUID_OK; - break; - } - list = fluid_list_next(list); + while(list) + { + char *option = (char *) fluid_list_get(list); + + if(FLUID_STRCMP(s, option) == 0) + { + FLUID_FREE(option); + setting->options = fluid_list_remove_link(setting->options, list); + retval = FLUID_OK; + break; + } + + list = fluid_list_next(list); + } } - } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -1173,48 +1300,52 @@ fluid_settings_remove_option(fluid_settings_t* settings, const char *name, const * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise */ int -fluid_settings_setnum(fluid_settings_t* settings, const char *name, double val) +fluid_settings_setnum(fluid_settings_t *settings, const char *name, double val) { - fluid_setting_node_t *node; - fluid_num_setting_t *setting; - fluid_num_update_t callback = NULL; - void *data = NULL; + fluid_setting_node_t *node; + fluid_num_setting_t *setting; + fluid_num_update_t callback = NULL; + void *data = NULL; - fluid_return_val_if_fail (settings != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED); + fluid_return_val_if_fail(settings != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if ((fluid_settings_get (settings, name, &node) != FLUID_OK) - || (node->type != FLUID_NUM_TYPE)) { + if((fluid_settings_get(settings, name, &node) != FLUID_OK) + || (node->type != FLUID_NUM_TYPE)) + { goto error_recovery; - } + } - setting = &node->num; - if (val < setting->min || val > setting->max) { - FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name); - goto error_recovery; - } + setting = &node->num; - setting->value = val; + if(val < setting->min || val > setting->max) + { + FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name); + goto error_recovery; + } - callback = setting->update; - data = setting->data; + setting->value = val; - /* Release the mutex before calling the update callback, to avoid - * possible deadlocks with FluidSynths API lock */ - fluid_rec_mutex_unlock (settings->mutex); + callback = setting->update; + data = setting->data; - if (callback) { - (*callback)(data, name, val); - } + /* Release the mutex before calling the update callback, to avoid + * possible deadlocks with FluidSynths API lock */ + fluid_rec_mutex_unlock(settings->mutex); - return FLUID_OK; + if(callback) + { + (*callback)(data, name, val); + } + + return FLUID_OK; error_recovery: - fluid_rec_mutex_unlock (settings->mutex); - return FLUID_FAILED; + fluid_rec_mutex_unlock(settings->mutex); + return FLUID_FAILED; } /** @@ -1226,28 +1357,29 @@ error_recovery: * @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise */ int -fluid_settings_getnum(fluid_settings_t* settings, const char *name, double* val) +fluid_settings_getnum(fluid_settings_t *settings, const char *name, double *val) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (val != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(val != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_NUM_TYPE)) { - fluid_num_setting_t* setting = &node->num; - *val = setting->value; - retval = FLUID_OK; - } + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_NUM_TYPE)) + { + fluid_num_setting_t *setting = &node->num; + *val = setting->value; + retval = FLUID_OK; + } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -1262,7 +1394,7 @@ int fluid_settings_getnum_float(fluid_settings_t *settings, const char *name, fl { double tmp; - if (fluid_settings_getnum(settings, name, &tmp) == FLUID_OK) + if(fluid_settings_getnum(settings, name, &tmp) == FLUID_OK) { *val = tmp; return FLUID_OK; @@ -1281,31 +1413,32 @@ int fluid_settings_getnum_float(fluid_settings_t *settings, const char *name, fl * @return #FLUID_OK if the setting's range exists, #FLUID_FAILED otherwise */ int -fluid_settings_getnum_range(fluid_settings_t* settings, const char *name, - double* min, double* max) +fluid_settings_getnum_range(fluid_settings_t *settings, const char *name, + double *min, double *max) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (min != NULL, retval); - fluid_return_val_if_fail (max != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(min != NULL, retval); + fluid_return_val_if_fail(max != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_NUM_TYPE)) { - fluid_num_setting_t* setting = &node->num; - *min = setting->min; - *max = setting->max; - retval = FLUID_OK; - } + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_NUM_TYPE)) + { + fluid_num_setting_t *setting = &node->num; + *min = setting->min; + *max = setting->max; + retval = FLUID_OK; + } - fluid_rec_mutex_unlock (settings->mutex); - - return retval; + fluid_rec_mutex_unlock(settings->mutex); + + return retval; } /** @@ -1317,28 +1450,29 @@ fluid_settings_getnum_range(fluid_settings_t* settings, const char *name, * @return #FLUID_OK if the default value of the named setting exists, #FLUID_FAILED otherwise */ int -fluid_settings_getnum_default(fluid_settings_t* settings, const char *name, double* val) +fluid_settings_getnum_default(fluid_settings_t *settings, const char *name, double *val) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (val != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(val != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_NUM_TYPE)) { - fluid_num_setting_t* setting = &node->num; - *val = setting->def; - retval = FLUID_OK; - } + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_NUM_TYPE)) + { + fluid_num_setting_t *setting = &node->num; + *val = setting->def; + retval = FLUID_OK; + } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -1350,48 +1484,52 @@ fluid_settings_getnum_default(fluid_settings_t* settings, const char *name, doub * @return #FLUID_OK if the value has been set, #FLUID_FAILED otherwise */ int -fluid_settings_setint(fluid_settings_t* settings, const char *name, int val) +fluid_settings_setint(fluid_settings_t *settings, const char *name, int val) { - fluid_setting_node_t *node; - fluid_int_setting_t *setting; - fluid_int_update_t callback = NULL; - void *data = NULL; + fluid_setting_node_t *node; + fluid_int_setting_t *setting; + fluid_int_update_t callback = NULL; + void *data = NULL; - fluid_return_val_if_fail (settings != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name != NULL, FLUID_FAILED); - fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED); + fluid_return_val_if_fail(settings != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name != NULL, FLUID_FAILED); + fluid_return_val_if_fail(name[0] != '\0', FLUID_FAILED); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if ((fluid_settings_get (settings, name, &node) != FLUID_OK) - || (node->type != FLUID_INT_TYPE)) { + if((fluid_settings_get(settings, name, &node) != FLUID_OK) + || (node->type != FLUID_INT_TYPE)) + { goto error_recovery; - } + } - setting = &node->i; - if (val < setting->min || val > setting->max) { - FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name); - goto error_recovery; - } + setting = &node->i; - setting->value = val; + if(val < setting->min || val > setting->max) + { + FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name); + goto error_recovery; + } - callback = setting->update; - data = setting->data; + setting->value = val; - /* Release the mutex before calling the update callback, to avoid - * possible deadlocks with FluidSynths API lock */ - fluid_rec_mutex_unlock (settings->mutex); + callback = setting->update; + data = setting->data; - if (callback) { - (*callback)(data, name, val); - } + /* Release the mutex before calling the update callback, to avoid + * possible deadlocks with FluidSynths API lock */ + fluid_rec_mutex_unlock(settings->mutex); - return FLUID_OK; + if(callback) + { + (*callback)(data, name, val); + } + + return FLUID_OK; error_recovery: - fluid_rec_mutex_unlock (settings->mutex); - return FLUID_FAILED; + fluid_rec_mutex_unlock(settings->mutex); + return FLUID_FAILED; } /** @@ -1403,28 +1541,29 @@ error_recovery: * @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise */ int -fluid_settings_getint(fluid_settings_t* settings, const char *name, int* val) +fluid_settings_getint(fluid_settings_t *settings, const char *name, int *val) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (val != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(val != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_INT_TYPE)) { - fluid_int_setting_t* setting = &node->i; - *val = setting->value; - retval = FLUID_OK; - } + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_INT_TYPE)) + { + fluid_int_setting_t *setting = &node->i; + *val = setting->value; + retval = FLUID_OK; + } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -1436,31 +1575,32 @@ fluid_settings_getint(fluid_settings_t* settings, const char *name, int* val) * @return #FLUID_OK if the setting's range exists, #FLUID_FAILED otherwise */ int -fluid_settings_getint_range(fluid_settings_t* settings, const char *name, - int* min, int* max) +fluid_settings_getint_range(fluid_settings_t *settings, const char *name, + int *min, int *max) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (min != NULL, retval); - fluid_return_val_if_fail (max != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(min != NULL, retval); + fluid_return_val_if_fail(max != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_INT_TYPE)) { - fluid_int_setting_t* setting = &node->i; - *min = setting->min; - *max = setting->max; - retval = FLUID_OK; - } + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_INT_TYPE)) + { + fluid_int_setting_t *setting = &node->i; + *min = setting->min; + *max = setting->max; + retval = FLUID_OK; + } - fluid_rec_mutex_unlock (settings->mutex); - - return retval; + fluid_rec_mutex_unlock(settings->mutex); + + return retval; } /** @@ -1471,28 +1611,29 @@ fluid_settings_getint_range(fluid_settings_t* settings, const char *name, * @param val set to the setting's default integer value if it exists * @return #FLUID_OK if the setting's default integer value exists, #FLUID_FAILED otherwise */ -int fluid_settings_getint_default(fluid_settings_t* settings, const char *name, int* val) +int fluid_settings_getint_default(fluid_settings_t *settings, const char *name, int *val) { - fluid_setting_node_t *node; - int retval = FLUID_FAILED; + fluid_setting_node_t *node; + int retval = FLUID_FAILED; - fluid_return_val_if_fail (settings != NULL, retval); - fluid_return_val_if_fail (name != NULL, retval); - fluid_return_val_if_fail (name[0] != '\0', retval); - fluid_return_val_if_fail (val != NULL, retval); + fluid_return_val_if_fail(settings != NULL, retval); + fluid_return_val_if_fail(name != NULL, retval); + fluid_return_val_if_fail(name[0] != '\0', retval); + fluid_return_val_if_fail(val != NULL, retval); - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && (node->type == FLUID_INT_TYPE)) { - fluid_int_setting_t* setting = &node->i; - *val = setting->def; - retval = FLUID_OK; - } + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && (node->type == FLUID_INT_TYPE)) + { + fluid_int_setting_t *setting = &node->i; + *val = setting->def; + retval = FLUID_OK; + } - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_unlock(settings->mutex); - return retval; + return retval; } /** @@ -1508,42 +1649,46 @@ int fluid_settings_getint_default(fluid_settings_t* settings, const char *name, * option in alphabetical order. Sort order was undefined in previous versions. */ void -fluid_settings_foreach_option (fluid_settings_t* settings, const char *name, - void* data, fluid_settings_foreach_option_t func) +fluid_settings_foreach_option(fluid_settings_t *settings, const char *name, + void *data, fluid_settings_foreach_option_t func) { - fluid_setting_node_t *node; - fluid_str_setting_t *setting; - fluid_list_t *p, *newlist = NULL; + fluid_setting_node_t *node; + fluid_str_setting_t *setting; + fluid_list_t *p, *newlist = NULL; - fluid_return_if_fail (settings != NULL); - fluid_return_if_fail (name != NULL); - fluid_return_if_fail (name[0] != '\0'); - fluid_return_if_fail (func != NULL); + fluid_return_if_fail(settings != NULL); + fluid_return_if_fail(name != NULL); + fluid_return_if_fail(name[0] != '\0'); + fluid_return_if_fail(func != NULL); - fluid_rec_mutex_lock (settings->mutex); /* ++ lock */ + fluid_rec_mutex_lock(settings->mutex); /* ++ lock */ - if (fluid_settings_get (settings, name, &node) != FLUID_OK - || node->type != FLUID_STR_TYPE) - { - fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */ - return; - } + if(fluid_settings_get(settings, name, &node) != FLUID_OK + || node->type != FLUID_STR_TYPE) + { + fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */ + return; + } - setting = &node->str; + setting = &node->str; - /* Duplicate option list */ - for (p = setting->options; p; p = p->next) - newlist = fluid_list_append (newlist, fluid_list_get (p)); + /* Duplicate option list */ + for(p = setting->options; p; p = p->next) + { + newlist = fluid_list_append(newlist, fluid_list_get(p)); + } - /* Sort by name */ - newlist = fluid_list_sort (newlist, fluid_list_str_compare_func); + /* Sort by name */ + newlist = fluid_list_sort(newlist, fluid_list_str_compare_func); - for (p = newlist; p; p = p->next) - (*func)(data, name, (const char *)fluid_list_get (p)); + for(p = newlist; p; p = p->next) + { + (*func)(data, name, (const char *)fluid_list_get(p)); + } - fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */ + fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */ - delete_fluid_list (newlist); + delete_fluid_list(newlist); } /** @@ -1555,22 +1700,26 @@ fluid_settings_foreach_option (fluid_settings_t* settings, const char *name, * @since 1.1.0 */ int -fluid_settings_option_count (fluid_settings_t *settings, const char *name) +fluid_settings_option_count(fluid_settings_t *settings, const char *name) { - fluid_setting_node_t *node; - int count = -1; + fluid_setting_node_t *node; + int count = -1; - fluid_return_val_if_fail (settings != NULL, -1); - fluid_return_val_if_fail (name != NULL, -1); - fluid_return_val_if_fail (name[0] != '\0', -1); + fluid_return_val_if_fail(settings != NULL, -1); + fluid_return_val_if_fail(name != NULL, -1); + fluid_return_val_if_fail(name[0] != '\0', -1); - fluid_rec_mutex_lock (settings->mutex); - if (fluid_settings_get(settings, name, &node) == FLUID_OK - && node->type == FLUID_STR_TYPE) - count = fluid_list_size (node->str.options); - fluid_rec_mutex_unlock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - return (count); + if(fluid_settings_get(settings, name, &node) == FLUID_OK + && node->type == FLUID_STR_TYPE) + { + count = fluid_list_size(node->str.options); + } + + fluid_rec_mutex_unlock(settings->mutex); + + return (count); } /** @@ -1583,114 +1732,136 @@ fluid_settings_option_count (fluid_settings_t *settings, const char *name) * @since 1.1.0 */ char * -fluid_settings_option_concat (fluid_settings_t *settings, const char *name, - const char *separator) +fluid_settings_option_concat(fluid_settings_t *settings, const char *name, + const char *separator) { - fluid_setting_node_t *node; - fluid_str_setting_t *setting; - fluid_list_t *p, *newlist = NULL; - int count, len; - char *str, *option; + fluid_setting_node_t *node; + fluid_str_setting_t *setting; + fluid_list_t *p, *newlist = NULL; + int count, len; + char *str, *option; - fluid_return_val_if_fail (settings != NULL, NULL); - fluid_return_val_if_fail (name != NULL, NULL); - fluid_return_val_if_fail (name[0] != '\0', NULL); + fluid_return_val_if_fail(settings != NULL, NULL); + fluid_return_val_if_fail(name != NULL, NULL); + fluid_return_val_if_fail(name[0] != '\0', NULL); - if (!separator) separator = ", "; - - fluid_rec_mutex_lock (settings->mutex); /* ++ lock */ - - if (fluid_settings_get (settings, name, &node) != FLUID_OK - || node->type != FLUID_STR_TYPE) - { - fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */ - return (NULL); - } - - setting = &node->str; - - /* Duplicate option list, count options and get total string length */ - for (p = setting->options, count = 0, len = 0; p; p = p->next, count++) - { - option = fluid_list_get (p); - - if (option) + if(!separator) { - newlist = fluid_list_append (newlist, option); - len += strlen (option); + separator = ", "; } - } - if (count > 1) len += (count - 1) * strlen (separator); - len++; /* For terminator */ + fluid_rec_mutex_lock(settings->mutex); /* ++ lock */ - /* Sort by name */ - newlist = fluid_list_sort (newlist, fluid_list_str_compare_func); - - str = FLUID_MALLOC (len); - - if (str) - { - str[0] = 0; - for (p = newlist; p; p = p->next) + if(fluid_settings_get(settings, name, &node) != FLUID_OK + || node->type != FLUID_STR_TYPE) { - option = fluid_list_get (p); - strcat (str, option); - if (p->next) strcat (str, separator); + fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */ + return (NULL); } - } - fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */ + setting = &node->str; - delete_fluid_list (newlist); + /* Duplicate option list, count options and get total string length */ + for(p = setting->options, count = 0, len = 0; p; p = p->next, count++) + { + option = fluid_list_get(p); - if (!str) FLUID_LOG (FLUID_ERR, "Out of memory"); + if(option) + { + newlist = fluid_list_append(newlist, option); + len += strlen(option); + } + } - return (str); + if(count > 1) + { + len += (count - 1) * strlen(separator); + } + + len++; /* For terminator */ + + /* Sort by name */ + newlist = fluid_list_sort(newlist, fluid_list_str_compare_func); + + str = FLUID_MALLOC(len); + + if(str) + { + str[0] = 0; + + for(p = newlist; p; p = p->next) + { + option = fluid_list_get(p); + strcat(str, option); + + if(p->next) + { + strcat(str, separator); + } + } + } + + fluid_rec_mutex_unlock(settings->mutex); /* -- unlock */ + + delete_fluid_list(newlist); + + if(!str) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + } + + return (str); } /* Structure passed to fluid_settings_foreach_iter recursive function */ typedef struct { - char path[MAX_SETTINGS_LABEL+1]; /* Maximum settings label length */ - fluid_list_t *names; /* For fluid_settings_foreach() */ + char path[MAX_SETTINGS_LABEL + 1]; /* Maximum settings label length */ + fluid_list_t *names; /* For fluid_settings_foreach() */ } fluid_settings_foreach_bag_t; static int -fluid_settings_foreach_iter (void* key, void* value, void* data) +fluid_settings_foreach_iter(void *key, void *value, void *data) { - fluid_settings_foreach_bag_t *bag = data; - char *keystr = key; - fluid_setting_node_t *node = value; - int pathlen; - char *s; + fluid_settings_foreach_bag_t *bag = data; + char *keystr = key; + fluid_setting_node_t *node = value; + int pathlen; + char *s; - pathlen = strlen (bag->path); + pathlen = strlen(bag->path); - if (pathlen > 0) - { - bag->path[pathlen] = '.'; - bag->path[pathlen + 1] = 0; - } + if(pathlen > 0) + { + bag->path[pathlen] = '.'; + bag->path[pathlen + 1] = 0; + } - strcat (bag->path, keystr); + strcat(bag->path, keystr); - switch (node->type) { - case FLUID_NUM_TYPE: - case FLUID_INT_TYPE: - case FLUID_STR_TYPE: - s = FLUID_STRDUP (bag->path); - if (s) bag->names = fluid_list_append (bag->names, s); - break; - case FLUID_SET_TYPE: - fluid_hashtable_foreach(node->set.hashtable, - fluid_settings_foreach_iter, bag); - break; - } + switch(node->type) + { + case FLUID_NUM_TYPE: + case FLUID_INT_TYPE: + case FLUID_STR_TYPE: + s = FLUID_STRDUP(bag->path); - bag->path[pathlen] = 0; + if(s) + { + bag->names = fluid_list_append(bag->names, s); + } - return 0; + break; + + case FLUID_SET_TYPE: + fluid_hashtable_foreach(node->set.hashtable, + fluid_settings_foreach_iter, bag); + break; + } + + bag->path[pathlen] = 0; + + return 0; } /** @@ -1705,39 +1876,42 @@ fluid_settings_foreach_iter (void* key, void* value, void* data) * setting in alphabetical order. Sort order was undefined in previous versions. */ void -fluid_settings_foreach (fluid_settings_t* settings, void* data, - fluid_settings_foreach_t func) +fluid_settings_foreach(fluid_settings_t *settings, void *data, + fluid_settings_foreach_t func) { - fluid_settings_foreach_bag_t bag; - fluid_setting_node_t *node; - fluid_list_t *p; + fluid_settings_foreach_bag_t bag; + fluid_setting_node_t *node; + fluid_list_t *p; - fluid_return_if_fail (settings != NULL); - fluid_return_if_fail (func != NULL); + fluid_return_if_fail(settings != NULL); + fluid_return_if_fail(func != NULL); - bag.path[0] = 0; - bag.names = NULL; + bag.path[0] = 0; + bag.names = NULL; - fluid_rec_mutex_lock (settings->mutex); + fluid_rec_mutex_lock(settings->mutex); - /* Add all node names to the bag.names list */ - fluid_hashtable_foreach (settings, fluid_settings_foreach_iter, &bag); + /* Add all node names to the bag.names list */ + fluid_hashtable_foreach(settings, fluid_settings_foreach_iter, &bag); - /* Sort names */ - bag.names = fluid_list_sort (bag.names, fluid_list_str_compare_func); + /* Sort names */ + bag.names = fluid_list_sort(bag.names, fluid_list_str_compare_func); - /* Loop over names and call the callback */ - for (p = bag.names; p; p = p->next) - { - if (fluid_settings_get (settings, (const char *)(p->data), &node) == FLUID_OK - && node) - (*func) (data, (const char *)(p->data), node->type); - FLUID_FREE (p->data); /* -- Free name */ - } + /* Loop over names and call the callback */ + for(p = bag.names; p; p = p->next) + { + if(fluid_settings_get(settings, (const char *)(p->data), &node) == FLUID_OK + && node) + { + (*func)(data, (const char *)(p->data), node->type); + } - fluid_rec_mutex_unlock (settings->mutex); + FLUID_FREE(p->data); /* -- Free name */ + } - delete_fluid_list (bag.names); /* -- Free names list */ + fluid_rec_mutex_unlock(settings->mutex); + + delete_fluid_list(bag.names); /* -- Free names list */ } /** @@ -1751,24 +1925,25 @@ fluid_settings_foreach (fluid_settings_t* settings, void* data, */ int fluid_settings_split_csv(const char *str, int *buf, int buf_len) { - char *s; - char *tok; - char *tokstr; - int n = 0; + char *s; + char *tok; + char *tokstr; + int n = 0; - s = tokstr = FLUID_STRDUP(str); - if (s == NULL) - { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return -1; - } + s = tokstr = FLUID_STRDUP(str); - while ((tok = fluid_strtok(&tokstr, ",")) && n < buf_len) - { - buf[n++] = atoi(tok); - } + if(s == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return -1; + } - FLUID_FREE(s); + while((tok = fluid_strtok(&tokstr, ",")) && n < buf_len) + { + buf[n++] = atoi(tok); + } - return n; + FLUID_FREE(s); + + return n; } diff --git a/src/utils/fluid_settings.h b/src/utils/fluid_settings.h index 45582ec8..4a952f1b 100644 --- a/src/utils/fluid_settings.h +++ b/src/utils/fluid_settings.h @@ -22,33 +22,33 @@ #ifndef _FLUID_SETTINGS_H #define _FLUID_SETTINGS_H -int fluid_settings_add_option(fluid_settings_t* settings, const char* name, const char* s); -int fluid_settings_remove_option(fluid_settings_t* settings, const char* name, const char* s); +int fluid_settings_add_option(fluid_settings_t *settings, const char *name, const char *s); +int fluid_settings_remove_option(fluid_settings_t *settings, const char *name, const char *s); -typedef void (*fluid_str_update_t)(void* data, const char* name, const char* value); +typedef void (*fluid_str_update_t)(void *data, const char *name, const char *value); -int fluid_settings_register_str(fluid_settings_t* settings, const char* name, const char* def, int hints); -int fluid_settings_callback_str(fluid_settings_t* settings, const char* name, - fluid_str_update_t fun, void* data); +int fluid_settings_register_str(fluid_settings_t *settings, const char *name, const char *def, int hints); +int fluid_settings_callback_str(fluid_settings_t *settings, const char *name, + fluid_str_update_t fun, void *data); -typedef void (*fluid_num_update_t)(void* data, const char* name, double value); +typedef void (*fluid_num_update_t)(void *data, const char *name, double value); -int fluid_settings_register_num(fluid_settings_t* settings, const char* name, double def, +int fluid_settings_register_num(fluid_settings_t *settings, const char *name, double def, double min, double max, int hints); -int fluid_settings_callback_num(fluid_settings_t* settings, const char* name, - fluid_num_update_t fun, void* data); +int fluid_settings_callback_num(fluid_settings_t *settings, const char *name, + fluid_num_update_t fun, void *data); /* Type specific wrapper for fluid_settings_getnum */ int fluid_settings_getnum_float(fluid_settings_t *settings, const char *name, float *val); -typedef void (*fluid_int_update_t)(void* data, const char* name, int value); -int fluid_settings_register_int(fluid_settings_t* settings, const char* name, int def, +typedef void (*fluid_int_update_t)(void *data, const char *name, int value); +int fluid_settings_register_int(fluid_settings_t *settings, const char *name, int def, int min, int max, int hints); -int fluid_settings_callback_int(fluid_settings_t* settings, const char* name, - fluid_int_update_t fun, void* data); +int fluid_settings_callback_int(fluid_settings_t *settings, const char *name, + fluid_int_update_t fun, void *data); int fluid_settings_split_csv(const char *str, int *buf, int buf_len); diff --git a/src/utils/fluid_sys.c b/src/utils/fluid_sys.c index 663d684e..30ffe3f4 100644 --- a/src/utils/fluid_sys.c +++ b/src/utils/fluid_sys.c @@ -33,11 +33,11 @@ /* WIN32 HACK - Flag used to differentiate between a file descriptor and a socket. * Should work, so long as no SOCKET or file descriptor ends up with this bit set. - JG */ #ifdef _WIN32 - #define FLUID_SOCKET_FLAG 0x40000000 +#define FLUID_SOCKET_FLAG 0x40000000 #else - #define FLUID_SOCKET_FLAG 0x00000000 - #define SOCKET_ERROR -1 - #define INVALID_SOCKET -1 +#define FLUID_SOCKET_FLAG 0x00000000 +#define SOCKET_ERROR -1 +#define INVALID_SOCKET -1 #endif /* SCHED_FIFO priority for high priority timer threads */ @@ -46,38 +46,38 @@ typedef struct { - fluid_thread_func_t func; - void *data; - int prio_level; + fluid_thread_func_t func; + void *data; + int prio_level; } fluid_thread_info_t; struct _fluid_timer_t { - long msec; - fluid_timer_callback_t callback; - void *data; - fluid_thread_t *thread; - int cont; - int auto_destroy; + long msec; + fluid_timer_callback_t callback; + void *data; + fluid_thread_t *thread; + int cont; + int auto_destroy; }; struct _fluid_server_socket_t { - fluid_socket_t socket; - fluid_thread_t *thread; - int cont; - fluid_server_func_t func; - void *data; + fluid_socket_t socket; + fluid_thread_t *thread; + int cont; + fluid_server_func_t func; + void *data; }; -static int fluid_istream_gets(fluid_istream_t in, char* buf, int len); +static int fluid_istream_gets(fluid_istream_t in, char *buf, int len); static char fluid_errbuf[512]; /* buffer for error message */ static fluid_log_function_t fluid_log_function[LAST_LOG_LEVEL]; -static void* fluid_log_user_data[LAST_LOG_LEVEL]; +static void *fluid_log_user_data[LAST_LOG_LEVEL]; static int fluid_log_initialized = 0; static const char fluid_libname[] = "fluidsynth"; @@ -85,7 +85,7 @@ static const char fluid_libname[] = "fluidsynth"; void fluid_sys_config() { - fluid_log_config(); + fluid_log_config(); } @@ -97,16 +97,18 @@ void fluid_sys_config() * @return The previously installed function. */ fluid_log_function_t -fluid_set_log_function(int level, fluid_log_function_t fun, void* data) +fluid_set_log_function(int level, fluid_log_function_t fun, void *data) { - fluid_log_function_t old = NULL; + fluid_log_function_t old = NULL; - if ((level >= 0) && (level < LAST_LOG_LEVEL)) { - old = fluid_log_function[level]; - fluid_log_function[level] = fun; - fluid_log_user_data[level] = data; - } - return old; + if((level >= 0) && (level < LAST_LOG_LEVEL)) + { + old = fluid_log_function[level]; + fluid_log_function[level] = fun; + fluid_log_user_data[level] = data; + } + + return old; } /** @@ -116,43 +118,51 @@ fluid_set_log_function(int level, fluid_log_function_t fun, void* data) * @param data User supplied data (not used) */ void -fluid_default_log_function(int level, char* message, void* data) +fluid_default_log_function(int level, char *message, void *data) { - FILE* out; + FILE *out; #if defined(WIN32) - out = stdout; + out = stdout; #else - out = stderr; + out = stderr; #endif - if (fluid_log_initialized == 0) { - fluid_log_config(); - } + if(fluid_log_initialized == 0) + { + fluid_log_config(); + } - switch (level) { - case FLUID_PANIC: - FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message); - break; - case FLUID_ERR: - FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message); - break; - case FLUID_WARN: - FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message); - break; - case FLUID_INFO: - FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message); - break; - case FLUID_DBG: + switch(level) + { + case FLUID_PANIC: + FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message); + break; + + case FLUID_ERR: + FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message); + break; + + case FLUID_WARN: + FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message); + break; + + case FLUID_INFO: + FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message); + break; + + case FLUID_DBG: #if DEBUG - FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message); + FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message); #endif - break; - default: - FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message); - break; - } - fflush(out); + break; + + default: + FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message); + break; + } + + fflush(out); } /* @@ -161,30 +171,36 @@ fluid_default_log_function(int level, char* message, void* data) void fluid_log_config(void) { - if (fluid_log_initialized == 0) { + if(fluid_log_initialized == 0) + { - fluid_log_initialized = 1; + fluid_log_initialized = 1; - if (fluid_log_function[FLUID_PANIC] == NULL) { - fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL); + if(fluid_log_function[FLUID_PANIC] == NULL) + { + fluid_set_log_function(FLUID_PANIC, fluid_default_log_function, NULL); + } + + if(fluid_log_function[FLUID_ERR] == NULL) + { + fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL); + } + + if(fluid_log_function[FLUID_WARN] == NULL) + { + fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL); + } + + if(fluid_log_function[FLUID_INFO] == NULL) + { + fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL); + } + + if(fluid_log_function[FLUID_DBG] == NULL) + { + fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL); + } } - - if (fluid_log_function[FLUID_ERR] == NULL) { - fluid_set_log_function(FLUID_ERR, fluid_default_log_function, NULL); - } - - if (fluid_log_function[FLUID_WARN] == NULL) { - fluid_set_log_function(FLUID_WARN, fluid_default_log_function, NULL); - } - - if (fluid_log_function[FLUID_INFO] == NULL) { - fluid_set_log_function(FLUID_INFO, fluid_default_log_function, NULL); - } - - if (fluid_log_function[FLUID_DBG] == NULL) { - fluid_set_log_function(FLUID_DBG, fluid_default_log_function, NULL); - } - } } /** @@ -195,22 +211,26 @@ fluid_log_config(void) * @return Always returns #FLUID_FAILED */ int -fluid_log(int level, const char* fmt, ...) +fluid_log(int level, const char *fmt, ...) { - fluid_log_function_t fun = NULL; + fluid_log_function_t fun = NULL; - va_list args; - va_start (args, fmt); - FLUID_VSNPRINTF (fluid_errbuf, sizeof (fluid_errbuf), fmt, args); - va_end (args); + va_list args; + va_start(args, fmt); + FLUID_VSNPRINTF(fluid_errbuf, sizeof(fluid_errbuf), fmt, args); + va_end(args); - if ((level >= 0) && (level < LAST_LOG_LEVEL)) { - fun = fluid_log_function[level]; - if (fun != NULL) { - (*fun)(level, fluid_errbuf, fluid_log_user_data[level]); + if((level >= 0) && (level < LAST_LOG_LEVEL)) + { + fun = fluid_log_function[level]; + + if(fun != NULL) + { + (*fun)(level, fluid_errbuf, fluid_log_user_data[level]); + } } - } - return FLUID_FAILED; + + return FLUID_FAILED; } /** @@ -226,70 +246,76 @@ fluid_log(int level, const char* fmt, ...) * @param delim String of delimiter chars. * @return Pointer to the next token or NULL if no more tokens. */ -char *fluid_strtok (char **str, char *delim) +char *fluid_strtok(char **str, char *delim) { - char *s, *d, *token; - char c; + char *s, *d, *token; + char c; - if (str == NULL || delim == NULL || !*delim) - { - FLUID_LOG(FLUID_ERR, "Null pointer"); - return NULL; - } - - s = *str; - if (!s) return NULL; /* str points to a NULL pointer? (tokenize already ended) */ - - /* skip delimiter chars at beginning of token */ - do - { - c = *s; - if (!c) /* end of source string? */ + if(str == NULL || delim == NULL || !*delim) { - *str = NULL; - return NULL; + FLUID_LOG(FLUID_ERR, "Null pointer"); + return NULL; } - for (d = delim; *d; d++) /* is source char a token char? */ + s = *str; + + if(!s) { - if (c == *d) /* token char match? */ - { - s++; /* advance to next source char */ - break; - } + return NULL; /* str points to a NULL pointer? (tokenize already ended) */ } - } while (*d); /* while token char match */ - token = s; /* start of token found */ - - /* search for next token char or end of source string */ - for (s = s+1; *s; s++) - { - c = *s; - - for (d = delim; *d; d++) /* is source char a token char? */ + /* skip delimiter chars at beginning of token */ + do { - if (c == *d) /* token char match? */ - { - *s = '\0'; /* overwrite token char with zero byte to terminate token */ - *str = s+1; /* update str to point to beginning of next token */ - return token; - } - } - } + c = *s; - /* we get here only if source string ended */ - *str = NULL; - return token; + if(!c) /* end of source string? */ + { + *str = NULL; + return NULL; + } + + for(d = delim; *d; d++) /* is source char a token char? */ + { + if(c == *d) /* token char match? */ + { + s++; /* advance to next source char */ + break; + } + } + } + while(*d); /* while token char match */ + + token = s; /* start of token found */ + + /* search for next token char or end of source string */ + for(s = s + 1; *s; s++) + { + c = *s; + + for(d = delim; *d; d++) /* is source char a token char? */ + { + if(c == *d) /* token char match? */ + { + *s = '\0'; /* overwrite token char with zero byte to terminate token */ + *str = s + 1; /* update str to point to beginning of next token */ + return token; + } + } + } + + /* we get here only if source string ended */ + *str = NULL; + return token; } /* * fluid_error */ -char* +char * fluid_error() { - return fluid_errbuf; + return fluid_errbuf; } /** @@ -303,19 +329,23 @@ fluid_error() int fluid_is_midifile(const char *filename) { - FILE* fp = fopen(filename, "rb"); - char id[4]; + FILE *fp = fopen(filename, "rb"); + char id[4]; + + if(fp == NULL) + { + return 0; + } + + if(fread((void *) id, 1, 4, fp) != 4) + { + fclose(fp); + return 0; + } - if (fp == NULL) { - return 0; - } - if (fread((void*) id, 1, 4, fp) != 4) { fclose(fp); - return 0; - } - fclose(fp); - return FLUID_STRNCMP(id, "MThd", 4) == 0; + return FLUID_STRNCMP(id, "MThd", 4) == 0; } /** @@ -329,23 +359,25 @@ fluid_is_midifile(const char *filename) int fluid_is_soundfont(const char *filename) { - FILE* fp = fopen(filename, "rb"); - char riff_id[4], sfbk_id[4]; + FILE *fp = fopen(filename, "rb"); + char riff_id[4], sfbk_id[4]; + + if(fp == NULL) + { + return 0; + } + + if((fread((void *) riff_id, 1, sizeof(riff_id), fp) != sizeof(riff_id)) || + (fseek(fp, 4, SEEK_CUR) != 0) || + (fread((void *) sfbk_id, 1, sizeof(sfbk_id), fp) != sizeof(sfbk_id))) + { + goto error_rec; + } + + fclose(fp); + return (FLUID_STRNCMP(riff_id, "RIFF", sizeof(riff_id)) == 0) && + (FLUID_STRNCMP(sfbk_id, "sfbk", sizeof(sfbk_id)) == 0); - if (fp == NULL) { - return 0; - } - if((fread((void*) riff_id, 1, sizeof(riff_id), fp) != sizeof(riff_id)) || - (fseek(fp, 4, SEEK_CUR) != 0) || - (fread((void*) sfbk_id, 1, sizeof(sfbk_id), fp) != sizeof(sfbk_id))) - { - goto error_rec; - } - - fclose(fp); - return (FLUID_STRNCMP(riff_id, "RIFF", sizeof(riff_id)) == 0) && - (FLUID_STRNCMP(sfbk_id, "sfbk", sizeof(sfbk_id)) == 0); - error_rec: fclose(fp); return 0; @@ -357,7 +389,7 @@ error_rec: */ void fluid_msleep(unsigned int msecs) { - g_usleep(msecs * 1000); + g_usleep(msecs * 1000); } /** @@ -366,17 +398,18 @@ void fluid_msleep(unsigned int msecs) */ unsigned int fluid_curtime(void) { - static glong initial_seconds = 0; - GTimeVal timeval; + static glong initial_seconds = 0; + GTimeVal timeval; - if (initial_seconds == 0) { - g_get_current_time (&timeval); - initial_seconds = timeval.tv_sec; - } + if(initial_seconds == 0) + { + g_get_current_time(&timeval); + initial_seconds = timeval.tv_sec; + } - g_get_current_time (&timeval); + g_get_current_time(&timeval); - return (unsigned int)((timeval.tv_sec - initial_seconds) * 1000.0 + timeval.tv_usec / 1000.0); + return (unsigned int)((timeval.tv_sec - initial_seconds) * 1000.0 + timeval.tv_usec / 1000.0); } /** @@ -388,40 +421,42 @@ unsigned int fluid_curtime(void) * uses high precision performance counter instead of g_getmonotic_time(). */ double -fluid_utime (void) +fluid_utime(void) { double utime; - + #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 28 - /* use high precision monotonic clock if available (g_monotonic_time(). - * For Winfdows, if this clock is actually implemented as low prec. clock - * (i.e. in case glib is too old), high precision performance counter are - * used instead. - * see: https://bugzilla.gnome.org/show_bug.cgi?id=783340 - */ + /* use high precision monotonic clock if available (g_monotonic_time(). + * For Winfdows, if this clock is actually implemented as low prec. clock + * (i.e. in case glib is too old), high precision performance counter are + * used instead. + * see: https://bugzilla.gnome.org/show_bug.cgi?id=783340 + */ #if defined(WITH_PROFILING) && defined(WIN32) &&\ /* glib < 2.53.3 */\ (GLIB_MINOR_VERSION <= 53 && (GLIB_MINOR_VERSION < 53 || GLIB_MICRO_VERSION < 3)) - /* use high precision performance counter. */ - static LARGE_INTEGER freq_cache = {0,0}; /* Performance Frequency */ - LARGE_INTEGER perf_cpt; - if (! freq_cache.QuadPart) - { - QueryPerformanceFrequency(&freq_cache); /* Frequency value */ - } - QueryPerformanceCounter(&perf_cpt); /* Counter value */ - utime = perf_cpt.QuadPart * 1000000.0/freq_cache.QuadPart; /* time in micros */ + /* use high precision performance counter. */ + static LARGE_INTEGER freq_cache = {0, 0}; /* Performance Frequency */ + LARGE_INTEGER perf_cpt; + + if(! freq_cache.QuadPart) + { + QueryPerformanceFrequency(&freq_cache); /* Frequency value */ + } + + QueryPerformanceCounter(&perf_cpt); /* Counter value */ + utime = perf_cpt.QuadPart * 1000000.0 / freq_cache.QuadPart; /* time in micros */ #else - utime = g_get_monotonic_time(); + utime = g_get_monotonic_time(); #endif #else - /* fallback to less precise clock */ - GTimeVal timeval; - g_get_current_time (&timeval); - utime = (timeval.tv_sec * 1000000.0 + timeval.tv_usec); + /* fallback to less precise clock */ + GTimeVal timeval; + g_get_current_time(&timeval); + utime = (timeval.tv_sec * 1000000.0 + timeval.tv_usec); #endif - - return utime; + + return utime; } @@ -429,47 +464,55 @@ fluid_utime (void) #if defined(WIN32) /* Windoze specific stuff */ void -fluid_thread_self_set_prio (int prio_level) +fluid_thread_self_set_prio(int prio_level) { - if (prio_level > 0) - SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + if(prio_level > 0) + { + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + } } #elif defined(__OS2__) /* OS/2 specific stuff */ void -fluid_thread_self_set_prio (int prio_level) +fluid_thread_self_set_prio(int prio_level) { - if (prio_level > 0) - DosSetPriority (PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0); + if(prio_level > 0) + { + DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0); + } } #else /* POSIX stuff.. Nice POSIX.. Good POSIX. */ void -fluid_thread_self_set_prio (int prio_level) +fluid_thread_self_set_prio(int prio_level) { - struct sched_param priority; + struct sched_param priority; - if (prio_level > 0) - { + if(prio_level > 0) + { - memset(&priority, 0, sizeof(priority)); - priority.sched_priority = prio_level; + memset(&priority, 0, sizeof(priority)); + priority.sched_priority = prio_level; + + if(pthread_setschedparam(pthread_self(), SCHED_FIFO, &priority) == 0) + { + return; + } - if (pthread_setschedparam (pthread_self (), SCHED_FIFO, &priority) == 0) { - return; - } #ifdef DBUS_SUPPORT -/* Try to gain high priority via rtkit */ - - if (fluid_rtkit_make_realtime(0, prio_level) == 0) { - return; - } + /* Try to gain high priority via rtkit */ + + if(fluid_rtkit_make_realtime(0, prio_level) == 0) + { + return; + } + #endif - FLUID_LOG(FLUID_WARN, "Failed to set thread to high priority"); - } + FLUID_LOG(FLUID_WARN, "Failed to set thread to high priority"); + } } #ifdef FPE_CHECK @@ -509,34 +552,34 @@ fluid_thread_self_set_prio (int prio_level) * Checks, if the floating point unit has produced an exception, print a message * if so and clear the exception. */ -unsigned int fluid_check_fpe_i386(char* explanation) +unsigned int fluid_check_fpe_i386(char *explanation) { - unsigned int s; + unsigned int s; - _FPU_GET_SW(s); - _FPU_CLR_SW(); + _FPU_GET_SW(s); + _FPU_CLR_SW(); - s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE; + s &= _FPU_STATUS_IE | _FPU_STATUS_DE | _FPU_STATUS_ZE | _FPU_STATUS_OE | _FPU_STATUS_UE; - if (s) - { - FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation, - (s & _FPU_STATUS_IE) ? "Invalid operation " : "", - (s & _FPU_STATUS_DE) ? "Denormal number " : "", - (s & _FPU_STATUS_ZE) ? "Zero divide " : "", - (s & _FPU_STATUS_OE) ? "Overflow " : "", - (s & _FPU_STATUS_UE) ? "Underflow " : ""); - } + if(s) + { + FLUID_LOG(FLUID_WARN, "FPE exception (before or in %s): %s%s%s%s%s", explanation, + (s & _FPU_STATUS_IE) ? "Invalid operation " : "", + (s & _FPU_STATUS_DE) ? "Denormal number " : "", + (s & _FPU_STATUS_ZE) ? "Zero divide " : "", + (s & _FPU_STATUS_OE) ? "Overflow " : "", + (s & _FPU_STATUS_UE) ? "Underflow " : ""); + } - return s; + return s; } /* Purpose: * Clear floating point exception. */ -void fluid_clear_fpe_i386 (void) +void fluid_clear_fpe_i386(void) { - _FPU_CLR_SW(); + _FPU_CLR_SW(); } #endif // ifdef FPE_CHECK @@ -573,7 +616,7 @@ unsigned char fluid_profile_bank = FLUID_PROFILE_DEFAULT_BANK; unsigned char fluid_profile_prog = FLUID_PROFILE_DEFAULT_PROG; /* print mode */ -unsigned char fluid_profile_print= FLUID_PROFILE_DEFAULT_PRINT; +unsigned char fluid_profile_print = FLUID_PROFILE_DEFAULT_PRINT; /* number of measures */ unsigned short fluid_profile_n_prof = FLUID_PROFILE_DEFAULT_N_PROF; /* measure duration in ms */ @@ -589,15 +632,15 @@ unsigned char fluid_profile_status = PROFILE_STOP; /* command and status */ unsigned int fluid_profile_end_ticks = 0; /* ending position (in ticks) */ fluid_profile_data_t fluid_profile_data[] = /* Data duration */ { - {"synth_write_* ------------>", 1e10, 0.0, 0.0, 0, 0, 0}, - {"synth_one_block ---------->", 1e10, 0.0, 0.0, 0, 0, 0}, - {"synth_one_block:clear ---->", 1e10, 0.0, 0.0, 0, 0, 0}, - {"synth_one_block:one voice->", 1e10, 0.0, 0.0, 0, 0, 0}, - {"synth_one_block:all voices>", 1e10, 0.0, 0.0, 0, 0, 0}, - {"synth_one_block:reverb --->", 1e10, 0.0, 0.0, 0, 0, 0}, - {"synth_one_block:chorus --->", 1e10, 0.0, 0.0, 0, 0, 0}, - {"voice:note --------------->", 1e10, 0.0, 0.0, 0, 0, 0}, - {"voice:release ------------>", 1e10, 0.0, 0.0, 0, 0, 0} + {"synth_write_* ------------>", 1e10, 0.0, 0.0, 0, 0, 0}, + {"synth_one_block ---------->", 1e10, 0.0, 0.0, 0, 0, 0}, + {"synth_one_block:clear ---->", 1e10, 0.0, 0.0, 0, 0, 0}, + {"synth_one_block:one voice->", 1e10, 0.0, 0.0, 0, 0, 0}, + {"synth_one_block:all voices>", 1e10, 0.0, 0.0, 0, 0, 0}, + {"synth_one_block:reverb --->", 1e10, 0.0, 0.0, 0, 0, 0}, + {"synth_one_block:chorus --->", 1e10, 0.0, 0.0, 0, 0, 0}, + {"voice:note --------------->", 1e10, 0.0, 0.0, 0, 0, 0}, + {"voice:release ------------>", 1e10, 0.0, 0.0, 0, 0, 0} }; @@ -607,28 +650,28 @@ fluid_profile_data_t fluid_profile_data[] = /* Data duration */ /* logging profiling data (used on synthesizer instance deletion) */ void fluid_profiling_print(void) { - int i; + int i; - printf("fluid_profiling_print\n"); + printf("fluid_profiling_print\n"); - FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)"); + FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)"); - for (i = 0; i < FLUID_PROFILE_NBR; i++) - { - if (fluid_profile_data[i].count > 0) - { - FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f", - fluid_profile_data[i].description, - fluid_profile_data[i].min, - fluid_profile_data[i].total / fluid_profile_data[i].count, - fluid_profile_data[i].max); - } - else - { - FLUID_LOG(FLUID_DBG, "%s: no profiling available", - fluid_profile_data[i].description); - } - } + for(i = 0; i < FLUID_PROFILE_NBR; i++) + { + if(fluid_profile_data[i].count > 0) + { + FLUID_LOG(FLUID_INFO, "%s: %.3f/%.3f/%.3f", + fluid_profile_data[i].description, + fluid_profile_data[i].min, + fluid_profile_data[i].total / fluid_profile_data[i].count, + fluid_profile_data[i].max); + } + else + { + FLUID_LOG(FLUID_DBG, "%s: no profiling available", + fluid_profile_data[i].description); + } + } } /* Macro that returns cpu load in percent (%) @@ -654,73 +697,73 @@ void fluid_profiling_print(void) */ static void fluid_profiling_print_load(double sample_rate, fluid_ostream_t out) { - unsigned int n_voices; /* voices number */ - static const char max_voices_not_available[]=" not available"; - const char * pmax_voices; - char max_voices_available[20]; + unsigned int n_voices; /* voices number */ + static const char max_voices_not_available[] = " not available"; + const char *pmax_voices; + char max_voices_available[20]; - /* First computes data to be printed */ - double total, voices, reverb, chorus, all_voices, voice; - /* voices number */ - n_voices = fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count ? - fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].n_voices/ - fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count: 0; + /* First computes data to be printed */ + double total, voices, reverb, chorus, all_voices, voice; + /* voices number */ + n_voices = fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count ? + fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].n_voices / + fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count : 0; - /* total load (%) */ - total = fluid_profile_data[FLUID_PROF_WRITE].count ? - fluid_profile_load(fluid_profile_data[FLUID_PROF_WRITE].total,sample_rate, - fluid_profile_data[FLUID_PROF_WRITE].n_samples) : 0; + /* total load (%) */ + total = fluid_profile_data[FLUID_PROF_WRITE].count ? + fluid_profile_load(fluid_profile_data[FLUID_PROF_WRITE].total, sample_rate, + fluid_profile_data[FLUID_PROF_WRITE].n_samples) : 0; - /* reverb load (%) */ - reverb = fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].count ? - fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].total, - sample_rate, - fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].n_samples) : 0; + /* reverb load (%) */ + reverb = fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].count ? + fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].total, + sample_rate, + fluid_profile_data[FLUID_PROF_ONE_BLOCK_REVERB].n_samples) : 0; - /* chorus load (%) */ - chorus = fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].count ? - fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].total, - sample_rate, - fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].n_samples) : 0; + /* chorus load (%) */ + chorus = fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].count ? + fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].total, + sample_rate, + fluid_profile_data[FLUID_PROF_ONE_BLOCK_CHORUS].n_samples) : 0; - /* total voices load: total - reverb - chorus (%) */ - voices = total - reverb - chorus; + /* total voices load: total - reverb - chorus (%) */ + voices = total - reverb - chorus; - /* One voice load (%): all_voices / n_voices. */ - all_voices = fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count ? - fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].total, - sample_rate, - fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].n_samples) : 0; + /* One voice load (%): all_voices / n_voices. */ + all_voices = fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].count ? + fluid_profile_load(fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].total, + sample_rate, + fluid_profile_data[FLUID_PROF_ONE_BLOCK_VOICES].n_samples) : 0; - voice = n_voices ? all_voices / n_voices : 0; + voice = n_voices ? all_voices / n_voices : 0; - /* estimated maximum voices number */ - if(voice > 0) - { - FLUID_SNPRINTF(max_voices_available,sizeof(max_voices_available), - "%17d",(unsigned int) ((100.0 - reverb - chorus)/voice)); - pmax_voices = max_voices_available; - } - else - { - pmax_voices = max_voices_not_available; - } + /* estimated maximum voices number */ + if(voice > 0) + { + FLUID_SNPRINTF(max_voices_available, sizeof(max_voices_available), + "%17d", (unsigned int)((100.0 - reverb - chorus) / voice)); + pmax_voices = max_voices_available; + } + else + { + pmax_voices = max_voices_not_available; + } - /* Now prints data */ - fluid_ostream_printf(out, - " ------------------------------------------------------------------------------\n"); - fluid_ostream_printf(out, - " Cpu loads(%%) (sr:%6.0f Hz, sp:%6.2f microsecond) and maximum voices\n", - sample_rate, 1000000.0/sample_rate); - fluid_ostream_printf(out, - " ------------------------------------------------------------------------------\n"); - fluid_ostream_printf(out, - " nVoices| total(%%)|voices(%%)| reverb(%%)|chorus(%%)| voice(%%)|estimated maxVoices\n"); - fluid_ostream_printf(out, - " -------|---------|---------|----------|---------|---------|-------------------\n"); - fluid_ostream_printf(out, - "%8d|%9.3f|%9.3f|%10.3f|%9.3f|%9.3f|%s\n", n_voices, total, voices, - reverb, chorus, voice, pmax_voices); + /* Now prints data */ + fluid_ostream_printf(out, + " ------------------------------------------------------------------------------\n"); + fluid_ostream_printf(out, + " Cpu loads(%%) (sr:%6.0f Hz, sp:%6.2f microsecond) and maximum voices\n", + sample_rate, 1000000.0 / sample_rate); + fluid_ostream_printf(out, + " ------------------------------------------------------------------------------\n"); + fluid_ostream_printf(out, + " nVoices| total(%%)|voices(%%)| reverb(%%)|chorus(%%)| voice(%%)|estimated maxVoices\n"); + fluid_ostream_printf(out, + " -------|---------|---------|----------|---------|---------|-------------------\n"); + fluid_ostream_printf(out, + "%8d|%9.3f|%9.3f|%10.3f|%9.3f|%9.3f|%s\n", n_voices, total, voices, + reverb, chorus, voice, pmax_voices); } /* @@ -758,61 +801,67 @@ static void fluid_profiling_print_load(double sample_rate, fluid_ostream_t out) */ void fluid_profiling_print_data(double sample_rate, fluid_ostream_t out) { - int i; - if (fluid_profile_print) - { - /* print all details: Duration(microsecond) and cpu loads(%) */ - fluid_ostream_printf(out, - " ------------------------------------------------------------------------------\n"); - fluid_ostream_printf(out, - " Duration(microsecond) and cpu loads(%%) (sr:%6.0f Hz, sp:%6.2f microsecond)\n", - sample_rate, 1000000.0/sample_rate); - fluid_ostream_printf(out, - " ------------------------------------------------------------------------------\n"); - fluid_ostream_printf(out, - " Code under profiling |Voices| Duration (microsecond) | Load(%%)\n"); - fluid_ostream_printf(out, - " | nbr| min| avg| max|\n"); - fluid_ostream_printf(out, - " ---------------------------|------|--------------------------------|----------\n"); + int i; - for (i = 0; i < FLUID_PROFILE_NBR; i++) - { - unsigned int count = fluid_profile_data[i].count; - if (count > 0) - { /* data are available */ + if(fluid_profile_print) + { + /* print all details: Duration(microsecond) and cpu loads(%) */ + fluid_ostream_printf(out, + " ------------------------------------------------------------------------------\n"); + fluid_ostream_printf(out, + " Duration(microsecond) and cpu loads(%%) (sr:%6.0f Hz, sp:%6.2f microsecond)\n", + sample_rate, 1000000.0 / sample_rate); + fluid_ostream_printf(out, + " ------------------------------------------------------------------------------\n"); + fluid_ostream_printf(out, + " Code under profiling |Voices| Duration (microsecond) | Load(%%)\n"); + fluid_ostream_printf(out, + " | nbr| min| avg| max|\n"); + fluid_ostream_printf(out, + " ---------------------------|------|--------------------------------|----------\n"); - if(FLUID_PROF_WRITE <= i && i <= FLUID_PROF_ONE_BLOCK_CHORUS ) - { - double load = fluid_profile_load(fluid_profile_data[i].total,sample_rate, - fluid_profile_data[i].n_samples); - fluid_ostream_printf(out," %s|%6d|%10.2f|%10.2f|%10.2f|%8.3f\n", - fluid_profile_data[i].description, /* code under profiling */ - fluid_profile_data[i].n_voices / count, /* voices number */ - fluid_profile_data[i].min, /* minimum duration */ - fluid_profile_data[i].total / count, /* average duration */ - fluid_profile_data[i].max, /* maximum duration */ - load ); /* cpu load */ - } - else - { /* note and release duration */ - fluid_ostream_printf(out," %s|%6d|%10.0f|%10.0f|%10.0f|\n", - fluid_profile_data[i].description, /* code under profiling */ - fluid_profile_data[i].n_voices / count, - fluid_profile_data[i].min, /* minimum duration */ - fluid_profile_data[i].total / count, /* average duration */ - fluid_profile_data[i].max); /* maximum duration */ - } - } - else - { /* data aren't available */ - fluid_ostream_printf(out, - " %s| no profiling available\n", fluid_profile_data[i].description); - } - } - } - /* prints cpu loads only */ - fluid_profiling_print_load(sample_rate, out);/* prints cpu loads */ + for(i = 0; i < FLUID_PROFILE_NBR; i++) + { + unsigned int count = fluid_profile_data[i].count; + + if(count > 0) + { + /* data are available */ + + if(FLUID_PROF_WRITE <= i && i <= FLUID_PROF_ONE_BLOCK_CHORUS) + { + double load = fluid_profile_load(fluid_profile_data[i].total, sample_rate, + fluid_profile_data[i].n_samples); + fluid_ostream_printf(out, " %s|%6d|%10.2f|%10.2f|%10.2f|%8.3f\n", + fluid_profile_data[i].description, /* code under profiling */ + fluid_profile_data[i].n_voices / count, /* voices number */ + fluid_profile_data[i].min, /* minimum duration */ + fluid_profile_data[i].total / count, /* average duration */ + fluid_profile_data[i].max, /* maximum duration */ + load); /* cpu load */ + } + else + { + /* note and release duration */ + fluid_ostream_printf(out, " %s|%6d|%10.0f|%10.0f|%10.0f|\n", + fluid_profile_data[i].description, /* code under profiling */ + fluid_profile_data[i].n_voices / count, + fluid_profile_data[i].min, /* minimum duration */ + fluid_profile_data[i].total / count, /* average duration */ + fluid_profile_data[i].max); /* maximum duration */ + } + } + else + { + /* data aren't available */ + fluid_ostream_printf(out, + " %s| no profiling available\n", fluid_profile_data[i].description); + } + } + } + + /* prints cpu loads only */ + fluid_profiling_print_load(sample_rate, out);/* prints cpu loads */ } /* @@ -828,37 +877,37 @@ int fluid_profile_is_cancel_req(void) #ifdef FLUID_PROFILE_CANCEL #if defined(WIN32) /* Windows specific stuff */ - /* Profile cancellation is supported for Windows */ - /* returns TRUE if key is depressed */ - return(GetAsyncKeyState(VK_RETURN) & 0x1); + /* Profile cancellation is supported for Windows */ + /* returns TRUE if key is depressed */ + return(GetAsyncKeyState(VK_RETURN) & 0x1); #elif defined(__OS2__) /* OS/2 specific stuff */ - /* Profile cancellation isn't yet supported for OS2 */ - /* For OS2, replaces the following line with the function that returns - true when the keyboard key is depressed */ - return FALSE; /* default value */ + /* Profile cancellation isn't yet supported for OS2 */ + /* For OS2, replaces the following line with the function that returns + true when the keyboard key is depressed */ + return FALSE; /* default value */ #else /* POSIX stuff */ - /* Profile cancellation is supported for Linux */ - /* returns true is is depressed */ - { - /* Here select() is used to poll the standard input to see if an input - is ready. As the standard input is usually buffered, the user - needs to depress to set the input to a "ready" state. - */ - struct timeval tv; - fd_set fds; /* just one fds need to be polled */ - tv.tv_sec = 0; /* Setting both values to 0, means a 0 timeout */ - tv.tv_usec = 0; - FD_ZERO(&fds); /* reset fds */ - FD_SET(STDIN_FILENO, &fds); /* sets fds to poll standard input only */ - select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv); /* polling */ - return (FD_ISSET(0, &fds)); /* returns true if standard input is ready */ - } + /* Profile cancellation is supported for Linux */ + /* returns true is is depressed */ + { + /* Here select() is used to poll the standard input to see if an input + is ready. As the standard input is usually buffered, the user + needs to depress to set the input to a "ready" state. + */ + struct timeval tv; + fd_set fds; /* just one fds need to be polled */ + tv.tv_sec = 0; /* Setting both values to 0, means a 0 timeout */ + tv.tv_usec = 0; + FD_ZERO(&fds); /* reset fds */ + FD_SET(STDIN_FILENO, &fds); /* sets fds to poll standard input only */ + select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv); /* polling */ + return (FD_ISSET(0, &fds)); /* returns true if standard input is ready */ + } #endif /* OS stuff */ #else /* FLUID_PROFILE_CANCEL not defined */ - return FALSE; /* default value */ + return FALSE; /* default value */ #endif /* FLUID_PROFILE_CANCEL */ } @@ -878,24 +927,25 @@ int fluid_profile_is_cancel_req(void) */ int fluid_profile_get_status(void) { - /* Checks if user has requested to cancel the current measurement */ - /* Cancellation must have precedence over other status */ - if(fluid_profile_is_cancel_req()) - { - fluid_profile_start_stop(0,0); /* stops the measurement */ - return PROFILE_CANCELED; - } - switch(fluid_profile_status) - { - case PROFILE_READY: - return PROFILE_READY; /* profiling data are ready */ + /* Checks if user has requested to cancel the current measurement */ + /* Cancellation must have precedence over other status */ + if(fluid_profile_is_cancel_req()) + { + fluid_profile_start_stop(0, 0); /* stops the measurement */ + return PROFILE_CANCELED; + } - case PROFILE_START: - return PROFILE_RUNNING;/* profiling data are under acquisition */ + switch(fluid_profile_status) + { + case PROFILE_READY: + return PROFILE_READY; /* profiling data are ready */ - default: - return PROFILE_STOP; - } + case PROFILE_START: + return PROFILE_RUNNING;/* profiling data are under acquisition */ + + default: + return PROFILE_STOP; + } } /** @@ -915,32 +965,36 @@ int fluid_profile_get_status(void) */ void fluid_profile_start_stop(unsigned int end_ticks, short clear_data) { - if ( end_ticks ) /* This is a "start" request */ - { - /* Checks if a measure is already running */ - if (fluid_profile_status != PROFILE_START ) - { - short i; - fluid_profile_end_ticks = end_ticks; - /* Clears profile data */ - if (clear_data == 0) for (i = 0; i < FLUID_PROFILE_NBR; i++) - { - fluid_profile_data[i].min = 1e10;/* min sets to max value */ - fluid_profile_data[i].max = 0; /* maximum sets to min value */ - fluid_profile_data[i].total = 0; /* total duration microsecond */ - fluid_profile_data[i].count = 0; /* data count */ - fluid_profile_data[i].n_voices = 0; /* voices number */ - fluid_profile_data[i].n_samples = 0;/* audio samples number */ - } - fluid_profile_status = PROFILE_START; /* starts profiling */ - } - /* else do nothing when profiling is already started */ - } - else /* This is a "stop" request */ - { - /* forces the current running profile (if any) to stop */ - fluid_profile_status = PROFILE_STOP; /* stops profiling */ - } + if(end_ticks) /* This is a "start" request */ + { + /* Checks if a measure is already running */ + if(fluid_profile_status != PROFILE_START) + { + short i; + fluid_profile_end_ticks = end_ticks; + + /* Clears profile data */ + if(clear_data == 0) + for(i = 0; i < FLUID_PROFILE_NBR; i++) + { + fluid_profile_data[i].min = 1e10;/* min sets to max value */ + fluid_profile_data[i].max = 0; /* maximum sets to min value */ + fluid_profile_data[i].total = 0; /* total duration microsecond */ + fluid_profile_data[i].count = 0; /* data count */ + fluid_profile_data[i].n_voices = 0; /* voices number */ + fluid_profile_data[i].n_samples = 0;/* audio samples number */ + } + + fluid_profile_status = PROFILE_START; /* starts profiling */ + } + + /* else do nothing when profiling is already started */ + } + else /* This is a "stop" request */ + { + /* forces the current running profile (if any) to stop */ + fluid_profile_status = PROFILE_STOP; /* stops profiling */ + } } #endif /* WITH_PROFILING */ @@ -956,25 +1010,29 @@ void fluid_profile_start_stop(unsigned int end_ticks, short clear_data) /* Rather than inline this one, we just declare it as a function, to prevent * GCC warning about inline failure. */ fluid_cond_t * -new_fluid_cond (void) +new_fluid_cond(void) { - if (!g_thread_supported ()) g_thread_init (NULL); - return g_cond_new (); + if(!g_thread_supported()) + { + g_thread_init(NULL); + } + + return g_cond_new(); } #endif static gpointer -fluid_thread_high_prio (gpointer data) +fluid_thread_high_prio(gpointer data) { - fluid_thread_info_t *info = data; + fluid_thread_info_t *info = data; - fluid_thread_self_set_prio (info->prio_level); + fluid_thread_self_set_prio(info->prio_level); - info->func (info->data); - FLUID_FREE (info); + info->func(info->data); + FLUID_FREE(info); - return NULL; + return NULL; } /** @@ -987,59 +1045,78 @@ fluid_thread_high_prio (gpointer data) * @return New thread pointer or NULL on error */ fluid_thread_t * -new_fluid_thread (const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach) +new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach) { - GThread *thread; - fluid_thread_info_t *info; - GError *err = NULL; + GThread *thread; + fluid_thread_info_t *info; + GError *err = NULL; - g_return_val_if_fail (func != NULL, NULL); + g_return_val_if_fail(func != NULL, NULL); #if OLD_GLIB_THREAD_API - /* Make sure g_thread_init has been called. - * FIXME - Probably not a good idea in a shared library, - * but what can we do *and* remain backwards compatible? */ - if (!g_thread_supported ()) g_thread_init (NULL); -#endif - if (prio_level > 0) - { - info = FLUID_NEW (fluid_thread_info_t); - - if (!info) + /* Make sure g_thread_init has been called. + * FIXME - Probably not a good idea in a shared library, + * but what can we do *and* remain backwards compatible? */ + if(!g_thread_supported()) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; + g_thread_init(NULL); } - info->func = func; - info->data = data; - info->prio_level = prio_level; +#endif + + if(prio_level > 0) + { + info = FLUID_NEW(fluid_thread_info_t); + + if(!info) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; + } + + info->func = func; + info->data = data; + info->prio_level = prio_level; #if NEW_GLIB_THREAD_API - thread = g_thread_try_new (name, fluid_thread_high_prio, info, &err); + thread = g_thread_try_new(name, fluid_thread_high_prio, info, &err); #else - thread = g_thread_create (fluid_thread_high_prio, info, detach == FALSE, &err); + thread = g_thread_create(fluid_thread_high_prio, info, detach == FALSE, &err); #endif - } + } + #if NEW_GLIB_THREAD_API - else thread = g_thread_try_new (name, (GThreadFunc)func, data, &err); + else + { + thread = g_thread_try_new(name, (GThreadFunc)func, data, &err); + } + #else - else thread = g_thread_create ((GThreadFunc)func, data, detach == FALSE, &err); + else + { + thread = g_thread_create((GThreadFunc)func, data, detach == FALSE, &err); + } + #endif - if (!thread) - { - FLUID_LOG(FLUID_ERR, "Failed to create the thread: %s", - fluid_gerror_message (err)); - g_clear_error (&err); - return NULL; - } + if(!thread) + { + FLUID_LOG(FLUID_ERR, "Failed to create the thread: %s", + fluid_gerror_message(err)); + g_clear_error(&err); + return NULL; + } #if NEW_GLIB_THREAD_API - if (detach) g_thread_unref (thread); // Release thread reference, if caller wants to detach + + if(detach) + { + g_thread_unref(thread); // Release thread reference, if caller wants to detach + } + #endif - return thread; + return thread; } /** @@ -1047,9 +1124,9 @@ new_fluid_thread (const char *name, fluid_thread_func_t func, void *data, int pr * @param thread Thread to free */ void -delete_fluid_thread(fluid_thread_t* thread) +delete_fluid_thread(fluid_thread_t *thread) { - /* Threads free themselves when they quit, nothing to do */ + /* Threads free themselves when they quit, nothing to do */ } /** @@ -1058,124 +1135,142 @@ delete_fluid_thread(fluid_thread_t* thread) * @return FLUID_OK */ int -fluid_thread_join(fluid_thread_t* thread) +fluid_thread_join(fluid_thread_t *thread) { - g_thread_join (thread); + g_thread_join(thread); - return FLUID_OK; + return FLUID_OK; } static fluid_thread_return_t -fluid_timer_run (void *data) +fluid_timer_run(void *data) { - fluid_timer_t *timer; - int count = 0; - int cont; - long start; - long delay; + fluid_timer_t *timer; + int count = 0; + int cont; + long start; + long delay; - timer = (fluid_timer_t *)data; + timer = (fluid_timer_t *)data; - /* keep track of the start time for absolute positioning */ - start = fluid_curtime (); + /* keep track of the start time for absolute positioning */ + start = fluid_curtime(); - while (timer->cont) - { - cont = (*timer->callback)(timer->data, fluid_curtime() - start); + while(timer->cont) + { + cont = (*timer->callback)(timer->data, fluid_curtime() - start); - count++; - if (!cont) break; + count++; - /* to avoid incremental time errors, calculate the delay between - two callbacks bringing in the "absolute" time (count * - timer->msec) */ - delay = (count * timer->msec) - (fluid_curtime() - start); - if (delay > 0) fluid_msleep(delay); - } + if(!cont) + { + break; + } - FLUID_LOG (FLUID_DBG, "Timer thread finished"); + /* to avoid incremental time errors, calculate the delay between + two callbacks bringing in the "absolute" time (count * + timer->msec) */ + delay = (count * timer->msec) - (fluid_curtime() - start); - if (timer->auto_destroy) - FLUID_FREE (timer); + if(delay > 0) + { + fluid_msleep(delay); + } + } - return FLUID_THREAD_RETURN_VALUE; + FLUID_LOG(FLUID_DBG, "Timer thread finished"); + + if(timer->auto_destroy) + { + FLUID_FREE(timer); + } + + return FLUID_THREAD_RETURN_VALUE; } -fluid_timer_t* -new_fluid_timer (int msec, fluid_timer_callback_t callback, void* data, - int new_thread, int auto_destroy, int high_priority) +fluid_timer_t * +new_fluid_timer(int msec, fluid_timer_callback_t callback, void *data, + int new_thread, int auto_destroy, int high_priority) { - fluid_timer_t *timer; + fluid_timer_t *timer; - timer = FLUID_NEW (fluid_timer_t); + timer = FLUID_NEW(fluid_timer_t); - if (timer == NULL) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - return NULL; - } - - timer->msec = msec; - timer->callback = callback; - timer->data = data; - timer->cont = TRUE ; - timer->thread = NULL; - timer->auto_destroy = auto_destroy; - - if (new_thread) - { - timer->thread = new_fluid_thread ("timer", fluid_timer_run, timer, high_priority - ? FLUID_SYS_TIMER_HIGH_PRIO_LEVEL : 0, FALSE); - if (!timer->thread) + if(timer == NULL) { - FLUID_FREE (timer); - return NULL; + FLUID_LOG(FLUID_ERR, "Out of memory"); + return NULL; } - } - else - { - fluid_timer_run (timer); /* Run directly, instead of as a separate thread */ - if(auto_destroy) - { - /* do NOT return freed memory */ - return NULL; - } - } - return timer; + timer->msec = msec; + timer->callback = callback; + timer->data = data; + timer->cont = TRUE ; + timer->thread = NULL; + timer->auto_destroy = auto_destroy; + + if(new_thread) + { + timer->thread = new_fluid_thread("timer", fluid_timer_run, timer, high_priority + ? FLUID_SYS_TIMER_HIGH_PRIO_LEVEL : 0, FALSE); + + if(!timer->thread) + { + FLUID_FREE(timer); + return NULL; + } + } + else + { + fluid_timer_run(timer); /* Run directly, instead of as a separate thread */ + + if(auto_destroy) + { + /* do NOT return freed memory */ + return NULL; + } + } + + return timer; } void -delete_fluid_timer (fluid_timer_t *timer) +delete_fluid_timer(fluid_timer_t *timer) { - int auto_destroy; - fluid_return_if_fail(timer != NULL); - - auto_destroy = timer->auto_destroy; + int auto_destroy; + fluid_return_if_fail(timer != NULL); - timer->cont = 0; - fluid_timer_join (timer); + auto_destroy = timer->auto_destroy; - /* Shouldn't access timer now if auto_destroy enabled, since it has been destroyed */ + timer->cont = 0; + fluid_timer_join(timer); - if (!auto_destroy) FLUID_FREE (timer); + /* Shouldn't access timer now if auto_destroy enabled, since it has been destroyed */ + + if(!auto_destroy) + { + FLUID_FREE(timer); + } } int -fluid_timer_join (fluid_timer_t *timer) +fluid_timer_join(fluid_timer_t *timer) { - int auto_destroy; + int auto_destroy; - if (timer->thread) - { - auto_destroy = timer->auto_destroy; - fluid_thread_join (timer->thread); + if(timer->thread) + { + auto_destroy = timer->auto_destroy; + fluid_thread_join(timer->thread); - if (!auto_destroy) timer->thread = NULL; - } + if(!auto_destroy) + { + timer->thread = NULL; + } + } - return FLUID_OK; + return FLUID_OK; } @@ -1190,9 +1285,9 @@ fluid_timer_join (fluid_timer_t *timer) * @return Standard in stream. */ fluid_istream_t -fluid_get_stdin (void) +fluid_get_stdin(void) { - return STDIN_FILENO; + return STDIN_FILENO; } /** @@ -1200,9 +1295,9 @@ fluid_get_stdin (void) * @return Standard out stream. */ fluid_ostream_t -fluid_get_stdout (void) +fluid_get_stdout(void) { - return STDOUT_FILENO; + return STDOUT_FILENO; } /** @@ -1210,31 +1305,34 @@ fluid_get_stdout (void) * @return 0 if end-of-stream, -1 if error, non zero otherwise */ int -fluid_istream_readline (fluid_istream_t in, fluid_ostream_t out, char* prompt, - char* buf, int len) +fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt, + char *buf, int len) { #if WITH_READLINE - if (in == fluid_get_stdin ()) - { - char *line; - line = readline (prompt); + if(in == fluid_get_stdin()) + { + char *line; - if (line == NULL) - return -1; + line = readline(prompt); - FLUID_SNPRINTF (buf, len, "%s", line); - buf[len - 1] = 0; + if(line == NULL) + { + return -1; + } - free(line); - return 1; - } - else + FLUID_SNPRINTF(buf, len, "%s", line); + buf[len - 1] = 0; + + free(line); + return 1; + } + else #endif - { - fluid_ostream_printf (out, "%s", prompt); - return fluid_istream_gets (in, buf, len); - } + { + fluid_ostream_printf(out, "%s", prompt); + return fluid_istream_gets(in, buf, len); + } } /** @@ -1245,49 +1343,67 @@ fluid_istream_readline (fluid_istream_t in, fluid_ostream_t out, char* prompt, * @return 1 if a line was read, 0 on end of stream, -1 on error */ static int -fluid_istream_gets (fluid_istream_t in, char* buf, int len) +fluid_istream_gets(fluid_istream_t in, char *buf, int len) { - char c; - int n; + char c; + int n; - buf[len - 1] = 0; + buf[len - 1] = 0; - while (--len > 0) - { + while(--len > 0) + { #ifndef WIN32 - n = read(in, &c, 1); - if (n == -1) return -1; + n = read(in, &c, 1); + + if(n == -1) + { + return -1; + } + #else - /* Handle read differently depending on if its a socket or file descriptor */ - if (!(in & FLUID_SOCKET_FLAG)) - { - n = read(in, &c, 1); - if (n == -1) return -1; - } - else - { - n = recv(in & ~FLUID_SOCKET_FLAG, &c, 1, 0); - if (n == SOCKET_ERROR) return -1; - } + + /* Handle read differently depending on if its a socket or file descriptor */ + if(!(in & FLUID_SOCKET_FLAG)) + { + n = read(in, &c, 1); + + if(n == -1) + { + return -1; + } + } + else + { + n = recv(in & ~FLUID_SOCKET_FLAG, &c, 1, 0); + + if(n == SOCKET_ERROR) + { + return -1; + } + } + #endif - if (n == 0) - { - *buf = 0; - return 0; + if(n == 0) + { + *buf = 0; + return 0; + } + + if(c == '\n') + { + *buf = 0; + return 1; + } + + /* Store all characters excluding CR */ + if(c != '\r') + { + *buf++ = c; + } } - if (c == '\n') - { - *buf = 0; - return 1; - } - - /* Store all characters excluding CR */ - if (c != '\r') *buf++ = c; - } - - return -1; + return -1; } /** @@ -1298,44 +1414,46 @@ fluid_istream_gets (fluid_istream_t in, char* buf, int len) * @return Number of bytes written or -1 on error */ int -fluid_ostream_printf (fluid_ostream_t out, const char* format, ...) +fluid_ostream_printf(fluid_ostream_t out, const char *format, ...) { - char buf[4096]; - va_list args; - int len; + char buf[4096]; + va_list args; + int len; - va_start (args, format); - len = FLUID_VSNPRINTF (buf, 4095, format, args); - va_end (args); + va_start(args, format); + len = FLUID_VSNPRINTF(buf, 4095, format, args); + va_end(args); - if (len == 0) - { - return 0; - } + if(len == 0) + { + return 0; + } - if (len < 0) - { - printf("fluid_ostream_printf: buffer overflow"); - return -1; - } + if(len < 0) + { + printf("fluid_ostream_printf: buffer overflow"); + return -1; + } - buf[4095] = 0; + buf[4095] = 0; #ifndef WIN32 - return write (out, buf, strlen (buf)); + return write(out, buf, strlen(buf)); #else - { - int retval; + { + int retval; - /* Handle write differently depending on if its a socket or file descriptor */ - if (!(out & FLUID_SOCKET_FLAG)) - return write(out, buf, strlen (buf)); + /* Handle write differently depending on if its a socket or file descriptor */ + if(!(out & FLUID_SOCKET_FLAG)) + { + return write(out, buf, strlen(buf)); + } - /* Socket */ - retval = send (out & ~FLUID_SOCKET_FLAG, buf, strlen (buf), 0); + /* Socket */ + retval = send(out & ~FLUID_SOCKET_FLAG, buf, strlen(buf), 0); - return retval != SOCKET_ERROR ? retval : -1; - } + return retval != SOCKET_ERROR ? retval : -1; + } #endif } @@ -1343,234 +1461,250 @@ fluid_ostream_printf (fluid_ostream_t out, const char* format, ...) int fluid_server_socket_join(fluid_server_socket_t *server_socket) { - return fluid_thread_join (server_socket->thread); + return fluid_thread_join(server_socket->thread); } static int fluid_socket_init(void) { #ifdef _WIN32 - WSADATA wsaData; - int res = WSAStartup(MAKEWORD(2,2), &wsaData); + WSADATA wsaData; + int res = WSAStartup(MAKEWORD(2, 2), &wsaData); + + if(res != 0) + { + FLUID_LOG(FLUID_ERR, "Server socket creation error: WSAStartup failed: %d", res); + return FLUID_FAILED; + } - if (res != 0) { - FLUID_LOG(FLUID_ERR, "Server socket creation error: WSAStartup failed: %d", res); - return FLUID_FAILED; - } #endif - return FLUID_OK; + return FLUID_OK; } static void fluid_socket_cleanup(void) { #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif } static int fluid_socket_get_error(void) { #ifdef _WIN32 - return (int)WSAGetLastError(); + return (int)WSAGetLastError(); #else - return errno; + return errno; #endif } -fluid_istream_t fluid_socket_get_istream (fluid_socket_t sock) +fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock) { - return sock | FLUID_SOCKET_FLAG; + return sock | FLUID_SOCKET_FLAG; } -fluid_ostream_t fluid_socket_get_ostream (fluid_socket_t sock) +fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock) { - return sock | FLUID_SOCKET_FLAG; + return sock | FLUID_SOCKET_FLAG; } -void fluid_socket_close (fluid_socket_t sock) +void fluid_socket_close(fluid_socket_t sock) { - if (sock != INVALID_SOCKET) + if(sock != INVALID_SOCKET) + { #ifdef _WIN32 - closesocket(sock); + closesocket(sock); + #else - close(sock); + close(sock); #endif + } } -static fluid_thread_return_t fluid_server_socket_run (void *data) +static fluid_thread_return_t fluid_server_socket_run(void *data) { - fluid_server_socket_t *server_socket = (fluid_server_socket_t *)data; - fluid_socket_t client_socket; + fluid_server_socket_t *server_socket = (fluid_server_socket_t *)data; + fluid_socket_t client_socket; #ifdef IPV6_SUPPORT - struct sockaddr_in6 addr; + struct sockaddr_in6 addr; #else - struct sockaddr_in addr; + struct sockaddr_in addr; #endif #ifdef HAVE_INETNTOP #ifdef IPV6_SUPPORT - char straddr[INET6_ADDRSTRLEN]; + char straddr[INET6_ADDRSTRLEN]; #else - char straddr[INET_ADDRSTRLEN]; + char straddr[INET_ADDRSTRLEN]; #endif /* IPV6_SUPPORT */ #endif /* HAVE_INETNTOP */ - socklen_t addrlen = sizeof (addr); - int r; - FLUID_MEMSET((char *)&addr, 0, sizeof(addr)); + socklen_t addrlen = sizeof(addr); + int r; + FLUID_MEMSET((char *)&addr, 0, sizeof(addr)); - FLUID_LOG(FLUID_DBG, "Server listening for connections"); + FLUID_LOG(FLUID_DBG, "Server listening for connections"); - while (server_socket->cont) - { - client_socket = accept (server_socket->socket, (struct sockaddr *)&addr, &addrlen); - - FLUID_LOG (FLUID_DBG, "New client connection"); - - if (client_socket == INVALID_SOCKET) + while(server_socket->cont) { - if (server_socket->cont) - FLUID_LOG (FLUID_ERR, "Failed to accept connection: %ld", fluid_socket_get_error()); + client_socket = accept(server_socket->socket, (struct sockaddr *)&addr, &addrlen); - server_socket->cont = 0; - return FLUID_THREAD_RETURN_VALUE; - } - else - { + FLUID_LOG(FLUID_DBG, "New client connection"); + + if(client_socket == INVALID_SOCKET) + { + if(server_socket->cont) + { + FLUID_LOG(FLUID_ERR, "Failed to accept connection: %ld", fluid_socket_get_error()); + } + + server_socket->cont = 0; + return FLUID_THREAD_RETURN_VALUE; + } + else + { #ifdef HAVE_INETNTOP #ifdef IPV6_SUPPORT - inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr)); + inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr)); #else - inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr)); + inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr)); #endif - r = server_socket->func (server_socket->data, client_socket, - straddr); + r = server_socket->func(server_socket->data, client_socket, + straddr); #else - r = server_socket->func (server_socket->data, client_socket, - inet_ntoa (addr.sin_addr)); + r = server_socket->func(server_socket->data, client_socket, + inet_ntoa(addr.sin_addr)); #endif - if (r != 0) - fluid_socket_close (client_socket); + + if(r != 0) + { + fluid_socket_close(client_socket); + } + } } - } - FLUID_LOG (FLUID_DBG, "Server closing"); - - return FLUID_THREAD_RETURN_VALUE; + FLUID_LOG(FLUID_DBG, "Server closing"); + + return FLUID_THREAD_RETURN_VALUE; } -fluid_server_socket_t* -new_fluid_server_socket(int port, fluid_server_func_t func, void* data) +fluid_server_socket_t * +new_fluid_server_socket(int port, fluid_server_func_t func, void *data) { - fluid_server_socket_t* server_socket; + fluid_server_socket_t *server_socket; #ifdef IPV6_SUPPORT - struct sockaddr_in6 addr; + struct sockaddr_in6 addr; #else - struct sockaddr_in addr; + struct sockaddr_in addr; #endif - fluid_socket_t sock; + fluid_socket_t sock; - fluid_return_val_if_fail (func != NULL, NULL); + fluid_return_val_if_fail(func != NULL, NULL); + + if(fluid_socket_init() != FLUID_OK) + { + return NULL; + } - if (fluid_socket_init() != FLUID_OK) - { - return NULL; - } #ifdef IPV6_SUPPORT - sock = socket (AF_INET6, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) - { - FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error()); - fluid_socket_cleanup(); - return NULL; - } + sock = socket(AF_INET6, SOCK_STREAM, 0); - FLUID_MEMSET(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_port = htons ((uint16_t)port); - addr.sin6_addr = in6addr_any; + if(sock == INVALID_SOCKET) + { + FLUID_LOG(FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error()); + fluid_socket_cleanup(); + return NULL; + } + + FLUID_MEMSET(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons((uint16_t)port); + addr.sin6_addr = in6addr_any; #else - sock = socket (AF_INET, SOCK_STREAM, 0); + sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) - { - FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error()); - fluid_socket_cleanup(); - return NULL; - } + if(sock == INVALID_SOCKET) + { + FLUID_LOG(FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error()); + fluid_socket_cleanup(); + return NULL; + } - FLUID_MEMSET(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons ((uint16_t)port); - addr.sin_addr.s_addr = htonl (INADDR_ANY); + FLUID_MEMSET(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons((uint16_t)port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); #endif - if (bind(sock, (const struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) - { - FLUID_LOG (FLUID_ERR, "Failed to bind server socket: %ld", fluid_socket_get_error()); - fluid_socket_close (sock); - fluid_socket_cleanup(); - return NULL; - } + if(bind(sock, (const struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) + { + FLUID_LOG(FLUID_ERR, "Failed to bind server socket: %ld", fluid_socket_get_error()); + fluid_socket_close(sock); + fluid_socket_cleanup(); + return NULL; + } - if (listen (sock, SOMAXCONN) == SOCKET_ERROR) - { - FLUID_LOG (FLUID_ERR, "Failed to listen on server socket: %ld", fluid_socket_get_error()); - fluid_socket_close (sock); - fluid_socket_cleanup(); - return NULL; - } + if(listen(sock, SOMAXCONN) == SOCKET_ERROR) + { + FLUID_LOG(FLUID_ERR, "Failed to listen on server socket: %ld", fluid_socket_get_error()); + fluid_socket_close(sock); + fluid_socket_cleanup(); + return NULL; + } - server_socket = FLUID_NEW (fluid_server_socket_t); + server_socket = FLUID_NEW(fluid_server_socket_t); - if (server_socket == NULL) - { - FLUID_LOG (FLUID_ERR, "Out of memory"); - fluid_socket_close (sock); - fluid_socket_cleanup(); - return NULL; - } + if(server_socket == NULL) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + fluid_socket_close(sock); + fluid_socket_cleanup(); + return NULL; + } - server_socket->socket = sock; - server_socket->func = func; - server_socket->data = data; - server_socket->cont = 1; + server_socket->socket = sock; + server_socket->func = func; + server_socket->data = data; + server_socket->cont = 1; - server_socket->thread = new_fluid_thread("server", fluid_server_socket_run, server_socket, - 0, FALSE); - if (server_socket->thread == NULL) - { - FLUID_FREE (server_socket); - fluid_socket_close (sock); - fluid_socket_cleanup(); - return NULL; - } + server_socket->thread = new_fluid_thread("server", fluid_server_socket_run, server_socket, + 0, FALSE); - return server_socket; + if(server_socket->thread == NULL) + { + FLUID_FREE(server_socket); + fluid_socket_close(sock); + fluid_socket_cleanup(); + return NULL; + } + + return server_socket; } void delete_fluid_server_socket(fluid_server_socket_t *server_socket) { - fluid_return_if_fail(server_socket != NULL); - - server_socket->cont = 0; + fluid_return_if_fail(server_socket != NULL); - if (server_socket->socket != INVALID_SOCKET) - fluid_socket_close (server_socket->socket); + server_socket->cont = 0; - if (server_socket->thread) { - fluid_thread_join(server_socket->thread); - delete_fluid_thread (server_socket->thread); - } + if(server_socket->socket != INVALID_SOCKET) + { + fluid_socket_close(server_socket->socket); + } - FLUID_FREE (server_socket); + if(server_socket->thread) + { + fluid_thread_join(server_socket->thread); + delete_fluid_thread(server_socket->thread); + } - // Should be called the same number of times as fluid_socket_init() - fluid_socket_cleanup(); + FLUID_FREE(server_socket); + + // Should be called the same number of times as fluid_socket_init() + fluid_socket_cleanup(); } #endif // NETWORK_SUPPORT diff --git a/src/utils/fluid_sys.h b/src/utils/fluid_sys.h index 59c31743..55927097 100644 --- a/src/utils/fluid_sys.h +++ b/src/utils/fluid_sys.h @@ -97,7 +97,7 @@ else \ /* * Utility functions */ -char *fluid_strtok (char **str, char *delim); +char *fluid_strtok(char **str, char *delim); #if defined(__OS2__) @@ -118,17 +118,17 @@ double fluid_utime(void); /* if the callback function returns 1 the timer will continue; if it returns 0 it will stop */ -typedef int (*fluid_timer_callback_t)(void* data, unsigned int msec); +typedef int (*fluid_timer_callback_t)(void *data, unsigned int msec); typedef struct _fluid_timer_t fluid_timer_t; -fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback, - void* data, int new_thread, int auto_destroy, +fluid_timer_t *new_fluid_timer(int msec, fluid_timer_callback_t callback, + void *data, int new_thread, int auto_destroy, int high_priority); -void delete_fluid_timer(fluid_timer_t* timer); -int fluid_timer_join(fluid_timer_t* timer); -int fluid_timer_stop(fluid_timer_t* timer); +void delete_fluid_timer(fluid_timer_t *timer); +int fluid_timer_join(fluid_timer_t *timer); +int fluid_timer_stop(fluid_timer_t *timer); // Macros to use for pre-processor if statements to test which Glib thread API we have (pre or post 2.32) #define NEW_GLIB_THREAD_API (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 32)) @@ -161,20 +161,20 @@ typedef GMutex fluid_cond_mutex_t; #define fluid_cond_mutex_unlock(m) g_mutex_unlock(m) static FLUID_INLINE fluid_cond_mutex_t * -new_fluid_cond_mutex (void) +new_fluid_cond_mutex(void) { - GMutex *mutex; - mutex = g_new (GMutex, 1); - g_mutex_init (mutex); - return (mutex); + GMutex *mutex; + mutex = g_new(GMutex, 1); + g_mutex_init(mutex); + return (mutex); } static FLUID_INLINE void -delete_fluid_cond_mutex (fluid_cond_mutex_t *m) +delete_fluid_cond_mutex(fluid_cond_mutex_t *m) { - fluid_return_if_fail(m != NULL); - g_mutex_clear (m); - g_free (m); + fluid_return_if_fail(m != NULL); + g_mutex_clear(m); + g_free(m); } /* Thread condition signaling */ @@ -184,20 +184,20 @@ typedef GCond fluid_cond_t; #define fluid_cond_wait(cond, mutex) g_cond_wait(cond, mutex) static FLUID_INLINE fluid_cond_t * -new_fluid_cond (void) +new_fluid_cond(void) { - GCond *cond; - cond = g_new (GCond, 1); - g_cond_init (cond); - return (cond); + GCond *cond; + cond = g_new(GCond, 1); + g_cond_init(cond); + return (cond); } static FLUID_INLINE void -delete_fluid_cond (fluid_cond_t *cond) +delete_fluid_cond(fluid_cond_t *cond) { - fluid_return_if_fail(cond != NULL); - g_cond_clear (cond); - g_free (cond); + fluid_return_if_fail(cond != NULL); + g_cond_clear(cond); + g_free(cond); } /* Thread private data */ @@ -242,15 +242,19 @@ typedef GMutex fluid_cond_mutex_t; #define fluid_cond_mutex_unlock(m) g_mutex_unlock(m) static FLUID_INLINE fluid_cond_mutex_t * -new_fluid_cond_mutex (void) +new_fluid_cond_mutex(void) { - if (!g_thread_supported ()) g_thread_init (NULL); - return g_mutex_new (); + if(!g_thread_supported()) + { + g_thread_init(NULL); + } + + return g_mutex_new(); } /* Thread condition signaling */ typedef GCond fluid_cond_t; -fluid_cond_t *new_fluid_cond (void); +fluid_cond_t *new_fluid_cond(void); #define delete_fluid_cond(cond) g_cond_free(cond) #define fluid_cond_signal(cond) g_cond_signal(cond) #define fluid_cond_broadcast(cond) g_cond_broadcast(cond) @@ -299,41 +303,41 @@ typedef GStaticPrivate fluid_private_t; static FLUID_INLINE void fluid_atomic_float_set(volatile float *fptr, float val) { - int32_t ival; - memcpy (&ival, &val, 4); - fluid_atomic_int_set ((volatile int *)fptr, ival); + int32_t ival; + memcpy(&ival, &val, 4); + fluid_atomic_int_set((volatile int *)fptr, ival); } static FLUID_INLINE float fluid_atomic_float_get(volatile float *fptr) { - int32_t ival; - float fval; - ival = fluid_atomic_int_get ((volatile int *)fptr); - memcpy (&fval, &ival, 4); - return fval; + int32_t ival; + float fval; + ival = fluid_atomic_int_get((volatile int *)fptr); + memcpy(&fval, &ival, 4); + return fval; } /* Threads */ /* other thread implementations might change this for their needs */ -typedef void* fluid_thread_return_t; +typedef void *fluid_thread_return_t; /* static return value for thread functions which requires a return value */ #define FLUID_THREAD_RETURN_VALUE (NULL) typedef GThread fluid_thread_t; -typedef fluid_thread_return_t (*fluid_thread_func_t)(void* data); +typedef fluid_thread_return_t (*fluid_thread_func_t)(void *data); #define FLUID_THREAD_ID_NULL NULL /* A NULL "ID" value */ #define fluid_thread_id_t GThread * /* Data type for a thread ID */ #define fluid_thread_get_id() g_thread_self() /* Get unique "ID" for current thread */ -fluid_thread_t* new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, +fluid_thread_t *new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, int prio_level, int detach); -void delete_fluid_thread(fluid_thread_t* thread); -void fluid_thread_self_set_prio (int prio_level); -int fluid_thread_join(fluid_thread_t* thread); +void delete_fluid_thread(fluid_thread_t *thread); +void fluid_thread_self_set_prio(int prio_level); +int fluid_thread_join(fluid_thread_t *thread); /* Dynamic Module Loading, currently only used by LADSPA subsystem */ #ifdef LADSPA @@ -350,19 +354,19 @@ typedef GModule fluid_module_t; /* Sockets and I/O */ -fluid_istream_t fluid_get_stdin (void); -fluid_ostream_t fluid_get_stdout (void); -int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char* prompt, char* buf, int len); -int fluid_ostream_printf (fluid_ostream_t out, const char* format, ...); +fluid_istream_t fluid_get_stdin(void); +fluid_ostream_t fluid_get_stdout(void); +int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char *prompt, char *buf, int len); +int fluid_ostream_printf(fluid_ostream_t out, const char *format, ...); /* The function should return 0 if no error occured, non-zero otherwise. If the function return non-zero, the socket will be closed by the server. */ -typedef int (*fluid_server_func_t)(void* data, fluid_socket_t client_socket, char* addr); +typedef int (*fluid_server_func_t)(void *data, fluid_socket_t client_socket, char *addr); -fluid_server_socket_t* new_fluid_server_socket(int port, fluid_server_func_t func, void* data); -void delete_fluid_server_socket(fluid_server_socket_t* sock); -int fluid_server_socket_join(fluid_server_socket_t* sock); +fluid_server_socket_t *new_fluid_server_socket(int port, fluid_server_func_t func, void *data); +void delete_fluid_server_socket(fluid_server_socket_t *sock); +int fluid_server_socket_join(fluid_server_socket_t *sock); void fluid_socket_close(fluid_socket_t sock); fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock); fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock); @@ -457,24 +461,24 @@ void fluid_profiling_print(void); piece of code. */ typedef struct _fluid_profile_data_t { - const char* description; /* name of the piece of code under profiling */ - double min, max, total; /* duration (microsecond) */ - unsigned int count; /* total count */ - unsigned int n_voices; /* voices number */ - unsigned int n_samples; /* audio samples number */ + const char *description; /* name of the piece of code under profiling */ + double min, max, total; /* duration (microsecond) */ + unsigned int count; /* total count */ + unsigned int n_voices; /* voices number */ + unsigned int n_samples; /* audio samples number */ } fluid_profile_data_t; enum { - /* commands/status (profiling interface) */ - PROFILE_STOP, /* command to stop a profiling measure */ - PROFILE_START, /* command to start a profile measure */ - PROFILE_READY, /* status to signal that a profiling measure has finished + /* commands/status (profiling interface) */ + PROFILE_STOP, /* command to stop a profiling measure */ + PROFILE_START, /* command to start a profile measure */ + PROFILE_READY, /* status to signal that a profiling measure has finished and ready to be printed */ - /*- State returned by fluid_profile_get_status() -*/ - /* between profiling commands and internal profiling API */ - PROFILE_RUNNING, /* a profiling measure is running */ - PROFILE_CANCELED,/* a profiling measure has been canceled */ + /*- State returned by fluid_profile_get_status() -*/ + /* between profiling commands and internal profiling API */ + PROFILE_RUNNING, /* a profiling measure is running */ + PROFILE_CANCELED,/* a profiling measure has been canceled */ }; /* Data interface */ @@ -499,16 +503,16 @@ extern fluid_profile_data_t fluid_profile_data[]; /* Profiling data */ */ enum { - FLUID_PROF_WRITE, - FLUID_PROF_ONE_BLOCK, - FLUID_PROF_ONE_BLOCK_CLEAR, - FLUID_PROF_ONE_BLOCK_VOICE, - FLUID_PROF_ONE_BLOCK_VOICES, - FLUID_PROF_ONE_BLOCK_REVERB, - FLUID_PROF_ONE_BLOCK_CHORUS, - FLUID_PROF_VOICE_NOTE, - FLUID_PROF_VOICE_RELEASE, - FLUID_PROFILE_NBR /* number of profile probes */ + FLUID_PROF_WRITE, + FLUID_PROF_ONE_BLOCK, + FLUID_PROF_ONE_BLOCK_CLEAR, + FLUID_PROF_ONE_BLOCK_VOICE, + FLUID_PROF_ONE_BLOCK_VOICES, + FLUID_PROF_ONE_BLOCK_REVERB, + FLUID_PROF_ONE_BLOCK_CHORUS, + FLUID_PROF_VOICE_NOTE, + FLUID_PROF_VOICE_RELEASE, + FLUID_PROFILE_NBR /* number of profile probes */ }; /** Those macros are used to calculate the min/avg/max. Needs a profile number, a time reference, the voices and samples number. */ @@ -600,7 +604,7 @@ enum #define fluid_clear_fpe() #endif -unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe); +unsigned int fluid_check_fpe_i386(char *explanation_in_case_of_fpe); void fluid_clear_fpe_i386(void); /* System control */ @@ -609,21 +613,21 @@ void fluid_msleep(unsigned int msecs); /** * Advances the given \c ptr to the next \c alignment byte boundary. * Make sure you've allocated an extra of \c alignment bytes to avoid a buffer overflow. - * + * * @note \c alignment must be a power of two * @return Returned pointer is guarenteed to be aligned to \c alignment boundary and in range \f[ ptr <= returned_ptr < ptr + alignment \f]. */ -static FLUID_INLINE void* fluid_align_ptr(const void* ptr, unsigned int alignment) +static FLUID_INLINE void *fluid_align_ptr(const void *ptr, unsigned int alignment) { uintptr_t ptr_int = (uintptr_t)ptr; - unsigned int offset = ptr_int & (alignment-1); - unsigned int add = (alignment - offset) & (alignment-1); // advance the pointer to the next alignment boundary + unsigned int offset = ptr_int & (alignment - 1); + unsigned int add = (alignment - offset) & (alignment - 1); // advance the pointer to the next alignment boundary ptr_int += add; - + /* assert alignment is power of two */ FLUID_ASSERT(!(alignment == 0) && !(alignment & (alignment - 1))); - - return (void*)ptr_int; + + return (void *)ptr_int; } #define FLUID_DEFAULT_ALIGNMENT (64U) diff --git a/src/utils/fluidsynth_priv.h b/src/utils/fluidsynth_priv.h index 3d65cb92..5d216b10 100644 --- a/src/utils/fluidsynth_priv.h +++ b/src/utils/fluidsynth_priv.h @@ -214,12 +214,12 @@ typedef struct _fluid_rvoice_eventhandler_t fluid_rvoice_eventhandler_t; * in fluid_lfo.c and fluid_adsr.c as well */ typedef union _fluid_rvoice_param_t { - void* ptr; + void *ptr; int i; fluid_real_t real; } fluid_rvoice_param_t; enum { MAX_EVENT_PARAMS = 6 }; /**< Maximum number of #fluid_rvoice_param_t to be passed to an #fluid_rvoice_function_t */ -typedef void (*fluid_rvoice_function_t)(void* obj, const fluid_rvoice_param_t param[MAX_EVENT_PARAMS]); +typedef void (*fluid_rvoice_function_t)(void *obj, const fluid_rvoice_param_t param[MAX_EVENT_PARAMS]); /* Macro for declaring an rvoice event function (#fluid_rvoice_function_t). The functions may only access * those params that were previously set in fluid_voice.c @@ -245,7 +245,7 @@ typedef void (*fluid_rvoice_function_t)(void* obj, const fluid_rvoice_param_t pa * * SYSTEM INTERFACE */ -typedef FILE* fluid_file; +typedef FILE *fluid_file; #define FLUID_MALLOC(_n) malloc(_n) #define FLUID_REALLOC(_p,_n) realloc(_p,_n) @@ -274,40 +274,40 @@ do { strncpy(_dst,_src,_n); \ #define FLUID_STRRCHR(_s,_c) strrchr(_s,_c) #ifdef strdup - #define FLUID_STRDUP(s) strdup(s) +#define FLUID_STRDUP(s) strdup(s) #else - #define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s) +#define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s) #endif #define FLUID_SPRINTF sprintf #define FLUID_FPRINTF fprintf #if (defined(WIN32) && _MSC_VER < 1900) || defined(MINGW32) - /* need to make sure we use a C99 compliant implementation of (v)snprintf(), - * i.e. not microsofts non compliant extension _snprintf() as it doesnt - * reliably null-terminates the buffer - */ - #define FLUID_SNPRINTF g_snprintf +/* need to make sure we use a C99 compliant implementation of (v)snprintf(), + * i.e. not microsofts non compliant extension _snprintf() as it doesnt + * reliably null-terminates the buffer + */ +#define FLUID_SNPRINTF g_snprintf #else - #define FLUID_SNPRINTF snprintf +#define FLUID_SNPRINTF snprintf #endif #if (defined(WIN32) && _MSC_VER < 1500) || defined(MINGW32) - #define FLUID_VSNPRINTF g_vsnprintf +#define FLUID_VSNPRINTF g_vsnprintf #else - #define FLUID_VSNPRINTF vsnprintf +#define FLUID_VSNPRINTF vsnprintf #endif #if defined(WIN32) && !defined(MINGW32) - #define FLUID_STRCASECMP _stricmp +#define FLUID_STRCASECMP _stricmp #else - #define FLUID_STRCASECMP strcasecmp +#define FLUID_STRCASECMP strcasecmp #endif #if defined(WIN32) && !defined(MINGW32) - #define FLUID_STRNCASECMP _strnicmp +#define FLUID_STRNCASECMP _strnicmp #else - #define FLUID_STRNCASECMP strncasecmp +#define FLUID_STRNCASECMP strncasecmp #endif @@ -339,12 +339,12 @@ do { strncpy(_dst,_src,_n); \ #ifdef DEBUG #define FLUID_ASSERT(a) g_assert(a) #else -#define FLUID_ASSERT(a) +#define FLUID_ASSERT(a) #endif #define FLUID_LIKELY G_LIKELY #define FLUID_UNLIKELY G_UNLIKELY -char* fluid_error(void); +char *fluid_error(void); #endif /* _FLUIDSYNTH_PRIV_H */ diff --git a/test/test_pointer_alignment.c b/test/test_pointer_alignment.c index a7447912..0b1508a1 100644 --- a/test/test_pointer_alignment.c +++ b/test/test_pointer_alignment.c @@ -8,24 +8,24 @@ int main(void) { unsigned int align; uintptr_t ptr, aligned_ptr; - - for(align = 32; align <= 4*1024u; align <<= 1) + + for(align = 32; align <= 4 * 1024u; align <<= 1) { - for(ptr = 0; ptr <= (align<<10); ptr++) + for(ptr = 0; ptr <= (align << 10); ptr++) { - char* tmp = fluid_align_ptr((char*)ptr, align); + char *tmp = fluid_align_ptr((char *)ptr, align); aligned_ptr = (uintptr_t)tmp; - + // pointer must be aligned properly TEST_ASSERT(aligned_ptr % align == 0); - + // aligned pointer must not be smaller than ptr TEST_ASSERT(aligned_ptr >= ptr); - + // aligned pointer must not be bigger than alignment TEST_ASSERT(aligned_ptr < ptr + align); } } - + return EXIT_SUCCESS; } diff --git a/test/test_preset_sample_loading.c b/test/test_preset_sample_loading.c index dae90402..fcccc639 100644 --- a/test/test_preset_sample_loading.c +++ b/test/test_preset_sample_loading.c @@ -9,11 +9,11 @@ int main(void) { int id[2], sfcount, dyn_sample, i; - + /* setup */ fluid_settings_t *settings = new_fluid_settings(); - - for(dyn_sample=0; dyn_sample <= 1; dyn_sample++) + + for(dyn_sample = 0; dyn_sample <= 1; dyn_sample++) { fluid_synth_t *synth; fluid_settings_setint(settings, "synth.dynamic-sample-loading", dyn_sample); @@ -21,9 +21,9 @@ int main(void) id[0] = fluid_synth_sfload(synth, TEST_SOUNDFONT, 0); id[1] = fluid_synth_sfload(synth, TEST_SOUNDFONT_SF3, 0); sfcount = fluid_synth_sfcount(synth); - + TEST_ASSERT(id[0] != FLUID_FAILED); - + #if LIBSNDFILE_SUPPORT TEST_ASSERT(id[1] != FLUID_FAILED); TEST_ASSERT(sfcount == 2); @@ -31,8 +31,8 @@ int main(void) TEST_ASSERT(id[1] == FLUID_FAILED); TEST_ASSERT(sfcount == 1); #endif - - for(i=0; inotify != NULL) { preset->notify(preset, FLUID_PRESET_SELECTED, 0); } - + /* make sure we actually got a different preset */ TEST_ASSERT(preset != prev_preset); prev_preset = preset; } + /* VintageDreams has 136 presets */ TEST_ASSERT(count == 136); /* Make sure we have the right number of samples */ count = 0; - for (list = defsfont->sample; list; list = fluid_list_next(list)) + + for(list = defsfont->sample; list; list = fluid_list_next(list)) { fluid_sample_t *sample = fluid_list_get(list); - if (sample->data != NULL) + + if(sample->data != NULL) { count++; } - + TEST_ASSERT(sample->amplitude_that_reaches_noise_floor_is_valid); /* Make sure we actually got a different sample */ TEST_ASSERT(sample != prev_sample); prev_sample = sample; } + /* VintageDreams has 123 valid samples (one is a ROM sample and ignored) */ TEST_ASSERT(count == 123); } + /* teardown */ delete_fluid_synth(synth); } + delete_fluid_settings(settings); return EXIT_SUCCESS; diff --git a/test/test_sample_cache.c b/test/test_sample_cache.c index e9e8b081..16771649 100644 --- a/test/test_sample_cache.c +++ b/test/test_sample_cache.c @@ -10,33 +10,33 @@ int main(void) { enum { FRAMES = 1024 }; float buf[FRAMES * 2]; - + fluid_settings_t *settings = new_fluid_settings(); fluid_synth_t *synth1 = new_fluid_synth(settings), - *synth2 = new_fluid_synth(settings); - + *synth2 = new_fluid_synth(settings); + TEST_ASSERT(settings != NULL); TEST_ASSERT(synth1 != NULL); TEST_ASSERT(synth2 != NULL); - + // load a sfont to synth1 TEST_SUCCESS(fluid_synth_sfload(synth1, TEST_SOUNDFONT, 1)); - + // load the same font to synth2 and start a note TEST_SUCCESS(fluid_synth_sfload(synth2, TEST_SOUNDFONT, 1)); TEST_SUCCESS(fluid_synth_noteon(synth2, 0, 60, 127)); - + // render some audio TEST_SUCCESS(fluid_synth_write_float(synth2, FRAMES, buf, 0, 2, buf, 1, 2)); - + // delete the synth that owns the soundfont delete_fluid_synth(synth1); - + // render again with the unloaded sfont and hope no segfault happens TEST_SUCCESS(fluid_synth_write_float(synth2, FRAMES, buf, 0, 2, buf, 1, 2)); - + delete_fluid_synth(synth2); delete_fluid_settings(settings); - + return EXIT_SUCCESS; } diff --git a/test/test_sample_rate_change.c b/test/test_sample_rate_change.c index e4ef5492..48e66df8 100644 --- a/test/test_sample_rate_change.c +++ b/test/test_sample_rate_change.c @@ -6,19 +6,19 @@ #include "rvoice/fluid_rvoice.h" #include "utils/fluidsynth_priv.h" -static void verify_sample_rate(fluid_synth_t* synth, int expected_srate) +static void verify_sample_rate(fluid_synth_t *synth, int expected_srate) { int i; - + TEST_ASSERT(synth->sample_rate == expected_srate); - - for (i=0; i < synth->polyphony; i++) + + for(i = 0; i < synth->polyphony; i++) { TEST_ASSERT(synth->voice[i]->output_rate == expected_srate); TEST_ASSERT(synth->voice[i]->rvoice->dsp.output_rate == expected_srate); TEST_ASSERT(synth->voice[i]->overflow_rvoice->dsp.output_rate == expected_srate); } - + // TODO check fx, rvoice_mixer et. al.? } @@ -27,40 +27,40 @@ int main(void) { int polyphony; double sample_rate; - + fluid_settings_t *settings = new_fluid_settings(); fluid_synth_t *synth = new_fluid_synth(settings); - + TEST_ASSERT(settings != NULL); TEST_ASSERT(synth != NULL); - + TEST_SUCCESS(fluid_settings_getint(settings, "synth.polyphony", &polyphony)); TEST_ASSERT(polyphony == synth->polyphony); - + TEST_SUCCESS(fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate)); - + verify_sample_rate(synth, sample_rate); - - - TEST_SUCCESS(fluid_synth_sfload(synth, TEST_SOUNDFONT, 1)); + + + TEST_SUCCESS(fluid_synth_sfload(synth, TEST_SOUNDFONT, 1)); // play some notes to start some voices TEST_SUCCESS(fluid_synth_noteon(synth, 0, 60, 127)); TEST_SUCCESS(fluid_synth_noteon(synth, 2, 71, 127)); TEST_SUCCESS(fluid_synth_noteon(synth, 3, 82, 127)); - + verify_sample_rate(synth, sample_rate); - + // set srate to minimum allowed sample_rate = 8000; fluid_synth_set_sample_rate(synth, sample_rate); - + // manually dispatch rvoice events to get samples rates updated (this simulates the render thread) fluid_synth_process_event_queue(synth); - + verify_sample_rate(synth, sample_rate); - + delete_fluid_synth(synth); delete_fluid_settings(settings); - + return EXIT_SUCCESS; } diff --git a/test/test_seqbind_unregister.c b/test/test_seqbind_unregister.c index 2548f784..4e36bc66 100644 --- a/test/test_seqbind_unregister.c +++ b/test/test_seqbind_unregister.c @@ -5,25 +5,25 @@ // simple test to ensure that manually unregistering and deleting the internal fluid_seqbind_t works without crashing int main(void) { - fluid_settings_t* settings = new_fluid_settings(); - fluid_synth_t* synth = new_fluid_synth(settings); - fluid_sequencer_t* seq = new_fluid_sequencer2(0 /*i.e. use sample timer*/); + fluid_settings_t *settings = new_fluid_settings(); + fluid_synth_t *synth = new_fluid_synth(settings); + fluid_sequencer_t *seq = new_fluid_sequencer2(0 /*i.e. use sample timer*/); // silently creates a fluid_seqbind_t int seqid = fluid_sequencer_register_fluidsynth(seq, synth); - fluid_event_t* evt = new_fluid_event(); + fluid_event_t *evt = new_fluid_event(); fluid_event_set_source(evt, -1); fluid_event_set_dest(evt, seqid); - + // manually free the fluid_seqbind_t fluid_event_unregistering(evt); fluid_sequencer_send_now(seq, evt); - + // client should be removed, deleting the seq should not free the struct again delete_fluid_sequencer(seq); delete_fluid_synth(synth); delete_fluid_settings(settings); - + return EXIT_SUCCESS; } diff --git a/test/test_sfont_loading.c b/test/test_sfont_loading.c index a853e7b6..9f63b0c6 100644 --- a/test/test_sfont_loading.c +++ b/test/test_sfont_loading.c @@ -11,55 +11,55 @@ int main(void) { int id; fluid_sfont_t *sfont; - + fluid_settings_t *settings = new_fluid_settings(); fluid_synth_t *synth = new_fluid_synth(settings); - + TEST_ASSERT(settings != NULL); TEST_ASSERT(synth != NULL); - + // no sfont loaded TEST_ASSERT(fluid_synth_sfcount(synth) == 0); - + // load a sfont to synth TEST_SUCCESS(id = fluid_synth_sfload(synth, TEST_SOUNDFONT, 1)); // one sfont loaded TEST_ASSERT(fluid_synth_sfcount(synth) == 1); TEST_ASSERT((sfont = fluid_synth_get_sfont_by_id(synth, id)) != NULL); - + // this is still the same filename as we've put in TEST_ASSERT(FLUID_STRCMP(TEST_SOUNDFONT, fluid_sfont_get_name(sfont)) == 0); TEST_ASSERT(fluid_sfont_get_id(sfont) == id); - + // still the same id? TEST_ASSERT(fluid_synth_sfreload(synth, id) == id); // one sfont loaded TEST_ASSERT(fluid_synth_sfcount(synth) == 1); TEST_ASSERT((sfont = fluid_synth_get_sfont_by_id(synth, id)) != NULL); - + // still the same filename? TEST_ASSERT(FLUID_STRCMP(TEST_SOUNDFONT, fluid_sfont_get_name(sfont)) == 0); // correct id stored? TEST_ASSERT(fluid_sfont_get_id(sfont) == id); - + // remove the sfont without deleting TEST_SUCCESS(fluid_synth_remove_sfont(synth, sfont)); // no sfont loaded TEST_ASSERT(fluid_synth_sfcount(synth) == 0); - + // re-add the sfont without deleting TEST_SUCCESS(id = fluid_synth_add_sfont(synth, sfont)); // one sfont loaded TEST_ASSERT(fluid_synth_sfcount(synth) == 1); - - + + // destroy the sfont TEST_SUCCESS(fluid_synth_sfunload(synth, id, 0)); // no sfont loaded TEST_ASSERT(fluid_synth_sfcount(synth) == 0); - + delete_fluid_synth(synth); delete_fluid_settings(settings); - + return EXIT_SUCCESS; } diff --git a/test/test_snprintf.c b/test/test_snprintf.c index ae0da198..d0fee749 100644 --- a/test/test_snprintf.c +++ b/test/test_snprintf.c @@ -6,7 +6,7 @@ int main(void) { - char buf[2+1]; + char buf[2 + 1]; int ret = FLUID_SNPRINTF(buf, sizeof(buf), "99"); TEST_ASSERT(ret == 2); diff --git a/test/test_synth_chorus_reverb.c b/test/test_synth_chorus_reverb.c index ac2c0baa..7c372d9b 100644 --- a/test/test_synth_chorus_reverb.c +++ b/test/test_synth_chorus_reverb.c @@ -8,55 +8,55 @@ int main(void) fluid_synth_t *synth; fluid_settings_t *settings = new_fluid_settings(); TEST_ASSERT(settings != NULL); - + TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.room-size", 0.1)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.damp", 0.2)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.width", 0.3)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.level", 0.4)); - + TEST_SUCCESS(fluid_settings_setint(settings, "synth.chorus.nr", 99)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.level", 0.5)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.speed", 0.6)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.depth", 0.7)); - + synth = new_fluid_synth(settings); - TEST_ASSERT(synth != NULL); - + TEST_ASSERT(synth != NULL); + // check that the synth is initialized with the correct values TEST_ASSERT(fluid_synth_get_reverb_roomsize(synth) == 0.1); TEST_ASSERT(fluid_synth_get_reverb_damp(synth) == 0.2); TEST_ASSERT(fluid_synth_get_reverb_width(synth) == 0.3); TEST_ASSERT(fluid_synth_get_reverb_level(synth) == 0.4); - + TEST_ASSERT(fluid_synth_get_chorus_nr(synth) == 99); TEST_ASSERT(fluid_synth_get_chorus_level(synth) == 0.5); TEST_ASSERT(fluid_synth_get_chorus_speed(synth) == 0.6); TEST_ASSERT(fluid_synth_get_chorus_depth(synth) == 0.7); - + // update the realtime settings afterward TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.room-size", 0.11)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.damp", 0.22)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.width", 0.33)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.reverb.level", 0.44)); - + TEST_SUCCESS(fluid_settings_setint(settings, "synth.chorus.nr", 11)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.level", 0.55)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.speed", 0.66)); TEST_SUCCESS(fluid_settings_setnum(settings, "synth.chorus.depth", 0.77)); - + // check that the realtime settings correctly update the values in the synth TEST_ASSERT(fluid_synth_get_reverb_roomsize(synth) == 0.11); TEST_ASSERT(fluid_synth_get_reverb_damp(synth) == 0.22); TEST_ASSERT(fluid_synth_get_reverb_width(synth) == 0.33); TEST_ASSERT(fluid_synth_get_reverb_level(synth) == 0.44); - + TEST_ASSERT(fluid_synth_get_chorus_nr(synth) == 11); TEST_ASSERT(fluid_synth_get_chorus_level(synth) == 0.55); TEST_ASSERT(fluid_synth_get_chorus_speed(synth) == 0.66); TEST_ASSERT(fluid_synth_get_chorus_depth(synth) == 0.77); - + delete_fluid_synth(synth); delete_fluid_settings(settings); - + return EXIT_SUCCESS; }