From 5c102180bd905cad6e9d6c842b4ac091c91c6cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 18 Mar 2008 22:17:50 +0000 Subject: [PATCH] updated fluidsynth to 1.0.8 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24454 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/libs/fluidsynth/fluidsynth.h | 65 +- headers/libs/fluidsynth/fluidsynth/audio.h | 30 +- headers/libs/fluidsynth/fluidsynth/event.h | 49 +- headers/libs/fluidsynth/fluidsynth/gen.h | 156 +-- headers/libs/fluidsynth/fluidsynth/log.h | 70 +- headers/libs/fluidsynth/fluidsynth/midi.h | 58 +- headers/libs/fluidsynth/fluidsynth/sfont.h | 4 +- headers/libs/fluidsynth/fluidsynth/version.h | 4 +- src/libs/fluidsynth/AUTHORS | 19 +- src/libs/fluidsynth/src/Jamfile | 2 +- src/libs/fluidsynth/src/fluid_adriver.c | 117 +- src/libs/fluidsynth/src/fluid_adriver.h | 4 +- src/libs/fluidsynth/src/fluid_aufile.c | 53 +- src/libs/fluidsynth/src/fluid_chan.c | 80 +- src/libs/fluidsynth/src/fluid_chan.h | 4 +- src/libs/fluidsynth/src/fluid_chorus.c | 121 +- src/libs/fluidsynth/src/fluid_chorus.h | 6 +- src/libs/fluidsynth/src/fluid_cmd.c | 342 +++--- src/libs/fluidsynth/src/fluid_cmd.h | 12 +- src/libs/fluidsynth/src/fluid_conv.c | 46 +- src/libs/fluidsynth/src/fluid_conv.h | 2 +- src/libs/fluidsynth/src/fluid_defsfont.c | 411 +++---- src/libs/fluidsynth/src/fluid_defsfont.h | 10 +- src/libs/fluidsynth/src/fluid_dsp_core.c | 26 - src/libs/fluidsynth/src/fluid_dsp_float.c | 860 ++++++++++---- src/libs/fluidsynth/src/fluid_dsp_simple.c | 40 +- src/libs/fluidsynth/src/fluid_dsp_sse.c | 387 ------- src/libs/fluidsynth/src/fluid_event.c | 292 ++++- src/libs/fluidsynth/src/fluid_event_priv.h | 4 +- src/libs/fluidsynth/src/fluid_gen.c | 19 +- src/libs/fluidsynth/src/fluid_gen.h | 2 +- src/libs/fluidsynth/src/fluid_hash.c | 92 +- src/libs/fluidsynth/src/fluid_hash.h | 2 +- src/libs/fluidsynth/src/fluid_io.c | 22 +- src/libs/fluidsynth/src/fluid_io.h | 12 +- src/libs/fluidsynth/src/fluid_ladspa.c | 220 ++-- src/libs/fluidsynth/src/fluid_ladspa.h | 36 +- src/libs/fluidsynth/src/fluid_lash.c | 40 +- src/libs/fluidsynth/src/fluid_lash.h | 4 +- src/libs/fluidsynth/src/fluid_list.c | 26 +- src/libs/fluidsynth/src/fluid_mdriver.c | 65 +- src/libs/fluidsynth/src/fluid_mdriver.h | 4 +- src/libs/fluidsynth/src/fluid_midi.c | 271 +++-- src/libs/fluidsynth/src/fluid_midi.h | 12 +- src/libs/fluidsynth/src/fluid_midi_router.c | 188 +-- src/libs/fluidsynth/src/fluid_midi_router.h | 4 +- src/libs/fluidsynth/src/fluid_mod.c | 104 +- src/libs/fluidsynth/src/fluid_mod.h | 4 +- src/libs/fluidsynth/src/fluid_phase.h | 116 +- src/libs/fluidsynth/src/fluid_ramsfont.c | 222 ++-- src/libs/fluidsynth/src/fluid_ramsfont.h | 2 +- src/libs/fluidsynth/src/fluid_rev.c | 91 +- src/libs/fluidsynth/src/fluid_rev.h | 6 +- src/libs/fluidsynth/src/fluid_seq.c | 206 ++-- src/libs/fluidsynth/src/fluid_seqbind.c | 38 +- src/libs/fluidsynth/src/fluid_settings.c | 243 ++-- src/libs/fluidsynth/src/fluid_settings.h | 6 +- src/libs/fluidsynth/src/fluid_sfont.h | 4 +- src/libs/fluidsynth/src/fluid_sse.h | 263 ----- src/libs/fluidsynth/src/fluid_strtok.c | 123 -- src/libs/fluidsynth/src/fluid_strtok.h | 44 - src/libs/fluidsynth/src/fluid_synth.c | 827 +++++++------- src/libs/fluidsynth/src/fluid_synth.h | 34 +- src/libs/fluidsynth/src/fluid_sys.c | 313 +++-- src/libs/fluidsynth/src/fluid_sys.h | 54 +- src/libs/fluidsynth/src/fluid_tuning.c | 6 +- src/libs/fluidsynth/src/fluid_tuning.h | 2 +- src/libs/fluidsynth/src/fluid_voice.c | 1073 ++++++++---------- src/libs/fluidsynth/src/fluid_voice.h | 71 +- src/libs/fluidsynth/src/fluidsynth.c | 61 +- src/libs/fluidsynth/src/fluidsynth_priv.h | 33 +- 71 files changed, 4114 insertions(+), 4125 deletions(-) delete mode 100644 src/libs/fluidsynth/src/fluid_dsp_core.c delete mode 100644 src/libs/fluidsynth/src/fluid_dsp_sse.c delete mode 100644 src/libs/fluidsynth/src/fluid_sse.h delete mode 100644 src/libs/fluidsynth/src/fluid_strtok.c delete mode 100644 src/libs/fluidsynth/src/fluid_strtok.h diff --git a/headers/libs/fluidsynth/fluidsynth.h b/headers/libs/fluidsynth/fluidsynth.h index 9e59a1c056..ef40f824fe 100644 --- a/headers/libs/fluidsynth/fluidsynth.h +++ b/headers/libs/fluidsynth/fluidsynth.h @@ -44,40 +44,37 @@ extern "C" { #endif - /** - - \file fluidsynth.h - - \brief fluidsynth is a real-time SoundFont(R) synthesizer. This is - the header of the fluidsynth library and contains the - synthesizer's public API. - - Depending on how you want to use or extend the synthesizer you - will need different API functions. You probably do not need all - of them. Here is what you might want to do: - - o Embedded synthesizer: create a new synthesizer and send MIDI - events to it. The sound goes directly to the audio output of - your system. - - o Plugin synthesizer: create a synthesizer and send MIDI events - but pull the audio back into your application. - - o SoundFont plugin: create a new type of "SoundFont" and allow - the synthesizer to load your type of SoundFonts. - - o MIDI input: Create a MIDI handler to read the MIDI input on your - machine and send the MIDI events directly to the synthesizer. - - o MIDI files: Open MIDI files and send the MIDI events to the - synthesizer. - - o Command lines: You can send textual commands to the synthesizer. - - - SoundFont(R) is a registered trademark of E-mu Systems, Inc. - - */ +/** + * @file fluidsynth.h + * @brief FluidSynth is a real-time synthesizer designed for SoundFont(R) files. + * + * This is the header of the fluidsynth library and contains the + * synthesizer's public API. + * + * Depending on how you want to use or extend the synthesizer you + * will need different API functions. You probably do not need all + * of them. Here is what you might want to do: + * + * o Embedded synthesizer: create a new synthesizer and send MIDI + * events to it. The sound goes directly to the audio output of + * your system. + * + * o Plugin synthesizer: create a synthesizer and send MIDI events + * but pull the audio back into your application. + * + * o SoundFont plugin: create a new type of "SoundFont" and allow + * the synthesizer to load your type of SoundFonts. + * + * o MIDI input: Create a MIDI handler to read the MIDI input on your + * machine and send the MIDI events directly to the synthesizer. + * + * o MIDI files: Open MIDI files and send the MIDI events to the + * synthesizer. + * + * o Command lines: You can send textual commands to the synthesizer. + * + * SoundFont(R) is a registered trademark of E-mu Systems, Inc. + */ #include "fluidsynth/types.h" #include "fluidsynth/settings.h" diff --git a/headers/libs/fluidsynth/fluidsynth/audio.h b/headers/libs/fluidsynth/fluidsynth/audio.h index 45d6935657..e2c9bd1d13 100644 --- a/headers/libs/fluidsynth/fluidsynth/audio.h +++ b/headers/libs/fluidsynth/fluidsynth/audio.h @@ -25,15 +25,29 @@ extern "C" { #endif +/** + * @file audio.h + * @brief Functions for audio driver output. + * + * Defines functions for creating audio driver output. Use + * new_fluid_audio_driver() to create a new audio driver for a given synth + * and configuration settings. The function new_fluid_audio_driver2() can be + * used if custom audio processing is desired before the audio is sent to the + * audio driver (although it is not as efficient). + */ - - /** Audio driver - * - * - */ - - - /** The function should return non-zero if an error occured. */ +/** + * Callback function type used with new_fluid_audio_driver2() to allow for + * custom user audio processing before the audio is sent to the driver. This + * function is responsible for rendering the audio to the buffers. + * @param data The user data parameter as passed to new_fluid_audio_driver2(). + * @param len Length of the audio in frames. + * @param nin Count of buffers in 'in' + * @param in FIXME - Not used currently? + * @param nout Count of arrays in 'out' (i.e., channel count) + * @param out Output buffers, one for each channel + * @return Should return 0 on success, non-zero if an error occured. + */ typedef int (*fluid_audio_func_t)(void* data, int len, int nin, float** in, int nout, float** out); diff --git a/headers/libs/fluidsynth/fluidsynth/event.h b/headers/libs/fluidsynth/fluidsynth/event.h index c724cbb3db..086a87809f 100644 --- a/headers/libs/fluidsynth/fluidsynth/event.h +++ b/headers/libs/fluidsynth/fluidsynth/event.h @@ -25,28 +25,37 @@ extern "C" { #endif +/** + * @file event.h + * @brief Sequencer event functions and defines. + * + * Functions and constants for creating/processing sequencer events. + */ +/** + * Sequencer event type enumeration. + */ enum fluid_seq_event_type { - FLUID_SEQ_NOTE = 0, - FLUID_SEQ_NOTEON, - FLUID_SEQ_NOTEOFF, - FLUID_SEQ_ALLSOUNDSOFF, - FLUID_SEQ_ALLNOTESOFF, - FLUID_SEQ_BANKSELECT, - FLUID_SEQ_PROGRAMCHANGE, - FLUID_SEQ_PROGRAMSELECT, - FLUID_SEQ_PITCHBEND, - FLUID_SEQ_PITCHWHHELSENS, - FLUID_SEQ_MODULATION, - FLUID_SEQ_SUSTAIN, - FLUID_SEQ_CONTROLCHANGE, - FLUID_SEQ_PAN, - FLUID_SEQ_VOLUME, - FLUID_SEQ_REVERBSEND, - FLUID_SEQ_CHORUSSEND, - FLUID_SEQ_TIMER, - FLUID_SEQ_ANYCONTROLCHANGE, // used for remove_events only - FLUID_SEQ_LASTEVENT + FLUID_SEQ_NOTE = 0, /**< Note event (DOCME) */ + 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 (DOCME) */ + FLUID_SEQ_PITCHBEND, /**< Pitch bend message */ + FLUID_SEQ_PITCHWHHELSENS, /**< Pitch wheel sensitivity set message */ + 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 (DOCME) */ + FLUID_SEQ_ANYCONTROLCHANGE, /**< DOCME (used for remove_events only) */ + FLUID_SEQ_LASTEVENT /**< Defines the count of event enums */ }; /* Event alloc/free */ diff --git a/headers/libs/fluidsynth/fluidsynth/gen.h b/headers/libs/fluidsynth/fluidsynth/gen.h index bdd4857a38..055ea753f2 100644 --- a/headers/libs/fluidsynth/fluidsynth/gen.h +++ b/headers/libs/fluidsynth/fluidsynth/gen.h @@ -25,99 +25,105 @@ extern "C" { #endif +/** + * @file gen.h + * @brief Functions and defines for SoundFont generator effects. + */ - /** List of generator numbers - Soundfont 2.01 specifications section 8.1.3 */ +/** + * Generator (effect) numbers (Soundfont 2.01 specifications section 8.1.3) + */ enum fluid_gen_type { - GEN_STARTADDROFS, - GEN_ENDADDROFS, - GEN_STARTLOOPADDROFS, - GEN_ENDLOOPADDROFS, - GEN_STARTADDRCOARSEOFS, - GEN_MODLFOTOPITCH, - GEN_VIBLFOTOPITCH, - GEN_MODENVTOPITCH, - GEN_FILTERFC, - GEN_FILTERQ, - GEN_MODLFOTOFILTERFC, - GEN_MODENVTOFILTERFC, - GEN_ENDADDRCOARSEOFS, - GEN_MODLFOTOVOL, - GEN_UNUSED1, - GEN_CHORUSSEND, - GEN_REVERBSEND, - GEN_PAN, - GEN_UNUSED2, - GEN_UNUSED3, - GEN_UNUSED4, - GEN_MODLFODELAY, - GEN_MODLFOFREQ, - GEN_VIBLFODELAY, - GEN_VIBLFOFREQ, - GEN_MODENVDELAY, - GEN_MODENVATTACK, - GEN_MODENVHOLD, - GEN_MODENVDECAY, - GEN_MODENVSUSTAIN, - GEN_MODENVRELEASE, - GEN_KEYTOMODENVHOLD, - GEN_KEYTOMODENVDECAY, - GEN_VOLENVDELAY, - GEN_VOLENVATTACK, - GEN_VOLENVHOLD, - GEN_VOLENVDECAY, - GEN_VOLENVSUSTAIN, - GEN_VOLENVRELEASE, - GEN_KEYTOVOLENVHOLD, - GEN_KEYTOVOLENVDECAY, - GEN_INSTRUMENT, - GEN_RESERVED1, - GEN_KEYRANGE, - GEN_VELRANGE, - GEN_STARTLOOPADDRCOARSEOFS, - GEN_KEYNUM, - GEN_VELOCITY, - GEN_ATTENUATION, - GEN_RESERVED2, - GEN_ENDLOOPADDRCOARSEOFS, - GEN_COARSETUNE, - GEN_FINETUNE, - GEN_SAMPLEID, - GEN_SAMPLEMODE, - GEN_RESERVED3, - GEN_SCALETUNE, - GEN_EXCLUSIVECLASS, - GEN_OVERRIDEROOTKEY, + 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, - GEN_LAST + GEN_PITCH, /**< Pitch (NOTE: Not a real SoundFont generator) */ + GEN_LAST /**< Value defines the count of generators (#fluid_gen_type) */ }; - /* - * fluid_gen_t - * Sound font generator - */ +/** + * SoundFont generator structure. + */ typedef struct _fluid_gen_t { - unsigned char flags; /* is it used or not */ - 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; +/** + * Enum value for 'flags' field of #_fluid_gen_t (not really flags). + */ enum fluid_gen_flags { - GEN_UNUSED, - GEN_SET, - GEN_ABS_NRPN + GEN_UNUSED, /**< Generator value is not set */ + GEN_SET, /**< Generator value is set */ + GEN_ABS_NRPN /**< DOCME */ }; - /** Reset an array of generators to the SF2.01 default values */ FLUIDSYNTH_API int fluid_gen_set_default_values(fluid_gen_t* gen); diff --git a/headers/libs/fluidsynth/fluidsynth/log.h b/headers/libs/fluidsynth/fluidsynth/log.h index f731e48d3a..51fdebecec 100644 --- a/headers/libs/fluidsynth/fluidsynth/log.h +++ b/headers/libs/fluidsynth/fluidsynth/log.h @@ -27,57 +27,55 @@ extern "C" { #endif - /** - * - * Logging interface - * - * The default logging function of the fluidsynth prints its messages - * to the stderr. The synthesizer uses four level of messages: FLUID_PANIC, - * ERR, WARN, and FLUID_DBG. They are commented in the definition below. - * - * A client application can install a new log function to handle the - * messages differently. In the following example, the application - * sets a callback function to display "FLUID_PANIC" messages in a dialog, - * and ignores all other messages by setting the log function to - * NULL: - * - * ... - * fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window); - * fluid_set_log_function(ERR, NULL, NULL); - * fluid_set_log_function(WARN, NULL, NULL); - * fluid_set_log_function(FLUID_DBG, NULL, NULL); - * ... - * - */ +/** + * @file log.h + * @brief Logging interface + * + * The default logging function of the fluidsynth prints its messages + * to the stderr. The synthesizer uses five level of messages: #FLUID_PANIC, + * #FLUID_ERR, #FLUID_WARN, #FLUID_INFO, and #FLUID_DBG. + * + * A client application can install a new log function to handle the + * messages differently. In the following example, the application + * sets a callback function to display #FLUID_PANIC messages in a dialog, + * and ignores all other messages by setting the log function to + * NULL: + * + * DOCME (formatting) + * fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window); + * fluid_set_log_function(FLUID_ERR, NULL, NULL); + * fluid_set_log_function(FLUID_WARN, NULL, NULL); + * fluid_set_log_function(FLUID_DBG, NULL, NULL); + */ +/** + * FluidSynth log levels. + */ enum fluid_log_level { - FLUID_PANIC, /* the synth can't function correctly any more */ - FLUID_ERR, /* the synth can function, but with serious limitation */ - FLUID_WARN, /* the synth might not function as expected */ - FLUID_INFO, /* verbose messages */ - FLUID_DBG, /* debugging messages */ + 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 */ LAST_LOG_LEVEL }; +/** + * Log function handler callback type used by fluid_set_log_function(). + * @param level Log level (#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); - /** fluid_set_log_function installs a new log function for the - * specified level. It returns the previously installed function. - */ FLUIDSYNTH_API fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data); - - /** fluid_default_log_function is the fluid's default log function. It - * prints to the stderr. */ FLUIDSYNTH_API void fluid_default_log_function(int level, char* message, void* data); - /** print a message to the log */ FLUIDSYNTH_API int fluid_log(int level, char * fmt, ...); - - #ifdef __cplusplus } #endif diff --git a/headers/libs/fluidsynth/fluidsynth/midi.h b/headers/libs/fluidsynth/fluidsynth/midi.h index f55bc39cdd..822c56c1e1 100644 --- a/headers/libs/fluidsynth/fluidsynth/midi.h +++ b/headers/libs/fluidsynth/fluidsynth/midi.h @@ -25,7 +25,10 @@ extern "C" { #endif - +/** + * @file midi.h + * @brief Functions for MIDI events, drivers and MIDI file playback. + */ FLUIDSYNTH_API fluid_midi_event_t* new_fluid_midi_event(void); FLUIDSYNTH_API int delete_fluid_midi_event(fluid_midi_event_t* event); @@ -48,58 +51,41 @@ 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); - /* Generic callback function for MIDI events. - * Will be used between - * - MIDI driver and MIDI router - * - MIDI router and synth - * to communicate events. - * In the not-so-far future... - */ +/** + * Generic callback function for MIDI events. + * @param data User defined data pointer + * @param event The MIDI event + * @return DOCME + * + * Will be used between + * - MIDI driver and MIDI router + * - MIDI router and synth + * to communicate events. + * In the not-so-far future... + */ typedef int (*handle_midi_event_func_t)(void* data, fluid_midi_event_t* event); - /* - * - * MIDI router - * - * The MIDI handler forwards incoming MIDI events to the synthesizer - * - */ +/* + * MIDI router + * + * The MIDI handler forwards incoming MIDI events to the synthesizer + */ - /** Create a new midi router. A midi handler connects to a midi input - * device and forwards incoming midi events to the synthesizer. - */ FLUIDSYNTH_API fluid_midi_router_t* new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data); - /** Delete the midi router. - * - * \param handler a pointer to the midi handler - * \return 0 if no error occured, -1 otherwise - */ FLUIDSYNTH_API int delete_fluid_midi_router(fluid_midi_router_t* handler); - - /** The standard handler function. Every MIDI event goes through - this. */ FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event); - - /** An optional link in the MIDI chain to dump MIDI data between MIDI - driver and router */ FLUIDSYNTH_API int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event); - - /** An optional link in the MIDI chain to dump MIDI data between MIDI - router and the synthesizer */ FLUIDSYNTH_API int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event); /* - * * MIDI driver * * The MIDI handler forwards incoming MIDI events to the synthesizer - * */ - FLUIDSYNTH_API fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, @@ -110,11 +96,9 @@ FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t* driver); /* - * * MIDI file player * * The MIDI player allows you to play MIDI files with the FLUID Synth - * */ FLUIDSYNTH_API fluid_player_t* new_fluid_player(fluid_synth_t* synth); diff --git a/headers/libs/fluidsynth/fluidsynth/sfont.h b/headers/libs/fluidsynth/fluidsynth/sfont.h index edf0671936..84020ba305 100644 --- a/headers/libs/fluidsynth/fluidsynth/sfont.h +++ b/headers/libs/fluidsynth/fluidsynth/sfont.h @@ -144,9 +144,9 @@ struct _fluid_sample_t { char name[21]; unsigned int start; - unsigned int end; + unsigned int end; /* Note: Index of last valid sample point (contrary to SF spec) */ unsigned int loopstart; - unsigned int loopend; + unsigned int loopend; /* Note: first point following the loop (superimposed on loopstart) */ unsigned int samplerate; int origpitch; int pitchadj; diff --git a/headers/libs/fluidsynth/fluidsynth/version.h b/headers/libs/fluidsynth/fluidsynth/version.h index e3a92ad492..68a0c146c5 100644 --- a/headers/libs/fluidsynth/fluidsynth/version.h +++ b/headers/libs/fluidsynth/fluidsynth/version.h @@ -26,10 +26,10 @@ extern "C" { #endif -#define FLUIDSYNTH_VERSION "1.0.7" +#define FLUIDSYNTH_VERSION "1.0.8" #define FLUIDSYNTH_VERSION_MAJOR 1 #define FLUIDSYNTH_VERSION_MINOR 0 -#define FLUIDSYNTH_VERSION_MICRO 7 +#define FLUIDSYNTH_VERSION_MICRO 8 FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro); diff --git a/src/libs/fluidsynth/AUTHORS b/src/libs/fluidsynth/AUTHORS index 96ddb9aad8..1580adf427 100644 --- a/src/libs/fluidsynth/AUTHORS +++ b/src/libs/fluidsynth/AUTHORS @@ -6,10 +6,10 @@ [:Development:] -Many people contributed to FluidSynth, send suggestions or bug +Many people contributed to FluidSynth, sent suggestions or bug fixes. The project was started by Peter Hanappe who is the main author. Josh Green is the current maintainer. Below you'll find a -summery of contributions. +summary of contributions. * Peter Hanappe. Initiated the project. files: sticked his nose in all @@ -24,10 +24,6 @@ summery of contributions. (the blue waves with FluidSynth letters partially submerged). files: iiwu_defsfont.{c,h}, iiwu_alsa{c,h} and others. -* Stephane Letz from Grame wrote most of the MidiShare driver, all of - the PortAudio driver, ported iiwusynth to MacOS X, and sent in many - fixes. files: iiwu_midishare.c, iiwu_portaudio.c - * Markus Nentwig (re-)designed the resonant filter, the chorus, the LADSPA subsystem, the MIDI router, optimized for SSE, made many changes and bug fixes and got the synthesizer to actually work. Most @@ -36,6 +32,10 @@ summery of contributions. iiwu_sse.h, iiwu_dsp_core.h, iiwu_rev.{c,h}, and basically all the other files. +* Stephane Letz from Grame wrote most of the MidiShare driver, all of + the PortAudio driver, ported iiwusynth to MacOS X, and sent in many + fixes. files: iiwu_midishare.c, iiwu_portaudio.c + * Antoine Schmitt added the sequencer support, support for sample loading (RAM Sfont), developed the MacroMedia Director Xtra, and send in many many bug reports. Thanks @@ -67,8 +67,7 @@ summery of contributions. portability. * The midi device uses code from jMax's alsarawmidi.c file and from - Smurf's midi_alsaraw.c by Josh Green. Josh also added support for - the alsa sequencer interface. file: iiwu_alsa.c + Smurf's midi_alsaraw.c by Josh Green. file: iiwu_alsa.c * The reverb algorithm was written by Jezar (http://www.dreampoint.co.uk). His code is public domain. The code @@ -115,3 +114,7 @@ Gerald Pye Rui Nuno Capela Frieder Bürzele Henri Manson +Mihail Zenkov +Paul Millar +Nick Daly +David Hilvert diff --git a/src/libs/fluidsynth/src/Jamfile b/src/libs/fluidsynth/src/Jamfile index 58d725fb2a..a31c4fbabe 100644 --- a/src/libs/fluidsynth/src/Jamfile +++ b/src/libs/fluidsynth/src/Jamfile @@ -14,6 +14,7 @@ SharedLibrary libfluidsynth.so : fluid_cmd.c fluid_conv.c fluid_defsfont.c + fluid_dsp_float.c fluid_event.c fluid_gen.c fluid_hash.c @@ -28,7 +29,6 @@ SharedLibrary libfluidsynth.so : fluid_seq.c fluid_seqbind.c fluid_settings.c - fluid_strtok.c fluid_synth.c fluid_sys.c fluid_tuning.c diff --git a/src/libs/fluidsynth/src/fluid_adriver.c b/src/libs/fluidsynth/src/fluid_adriver.c index d5185a3db5..4b49da728c 100644 --- a/src/libs/fluidsynth/src/fluid_adriver.c +++ b/src/libs/fluidsynth/src/fluid_adriver.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -25,12 +25,12 @@ * fluid_adriver_definition_t */ -typedef struct _fluid_audriver_definition_t +typedef struct _fluid_audriver_definition_t { 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, + fluid_audio_driver_t* (*new2)(fluid_settings_t* settings, + fluid_audio_func_t func, void* data); int (*free)(fluid_audio_driver_t* driver); void (*settings)(fluid_settings_t* settings); @@ -48,57 +48,57 @@ 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_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_driver_t* new_fluid_oss_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data); int 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_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, +fluid_audio_driver_t* new_fluid_core_audio_driver2(fluid_settings_t* settings, + fluid_audio_func_t func, void* data); int 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_audio_driver_t* new_fluid_dsound_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth); int delete_fluid_dsound_audio_driver(fluid_audio_driver_t* p); void fluid_dsound_audio_driver_settings(fluid_settings_t* settings); #endif #if PORTAUDIO_SUPPORT -fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings, +fluid_audio_driver_t* new_fluid_portaudio_driver(fluid_settings_t* settings, fluid_synth_t* synth); int 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_driver_t* new_fluid_jack_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data); int 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_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, +fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings, + fluid_audio_func_t func, void* data); int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p); #endif #define AUFILE_SUPPORT 1 #if AUFILE_SUPPORT -fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings, +fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth); int delete_fluid_file_audio_driver(fluid_audio_driver_t* p); void fluid_file_audio_driver_settings(fluid_settings_t* settings); @@ -106,10 +106,10 @@ void fluid_file_audio_driver_settings(fluid_settings_t* settings); fluid_audriver_definition_t fluid_audio_drivers[] = { #if OSS_SUPPORT - { "oss", - new_fluid_oss_audio_driver, + { "oss", + new_fluid_oss_audio_driver, new_fluid_oss_audio_driver2, - delete_fluid_oss_audio_driver, + delete_fluid_oss_audio_driver, fluid_oss_audio_driver_settings }, #endif #if ALSA_SUPPORT @@ -120,45 +120,45 @@ fluid_audriver_definition_t fluid_audio_drivers[] = { fluid_alsa_audio_driver_settings }, #endif #if COREAUDIO_SUPPORT - { "coreaudio", - new_fluid_core_audio_driver, + { "coreaudio", + new_fluid_core_audio_driver, new_fluid_core_audio_driver2, - delete_fluid_core_audio_driver, + delete_fluid_core_audio_driver, fluid_core_audio_driver_settings }, #endif #if DSOUND_SUPPORT - { "dsound", - new_fluid_dsound_audio_driver, + { "dsound", + new_fluid_dsound_audio_driver, NULL, - delete_fluid_dsound_audio_driver, + delete_fluid_dsound_audio_driver, fluid_dsound_audio_driver_settings }, #endif #if PORTAUDIO_SUPPORT - { "portaudio", - new_fluid_portaudio_driver, + { "portaudio", + new_fluid_portaudio_driver, NULL, - delete_fluid_portaudio_driver, - NULL }, + delete_fluid_portaudio_driver, + NULL }, #endif #if SNDMAN_SUPPORT - { "sndman", - new_fluid_sndmgr_audio_driver, + { "sndman", + new_fluid_sndmgr_audio_driver, new_fluid_sndmgr_audio_driver2, - delete_fluid_sndmgr_audio_driver, + delete_fluid_sndmgr_audio_driver, NULL }, #endif #if JACK_SUPPORT - { "jack", - new_fluid_jack_audio_driver, + { "jack", + new_fluid_jack_audio_driver, new_fluid_jack_audio_driver2, - delete_fluid_jack_audio_driver, + delete_fluid_jack_audio_driver, fluid_jack_audio_driver_settings }, #endif #if AUFILE_SUPPORT - { "file", - new_fluid_file_audio_driver, + { "file", + new_fluid_file_audio_driver, NULL, - delete_fluid_file_audio_driver, + delete_fluid_file_audio_driver, fluid_file_audio_driver_settings }, #endif { NULL, NULL, NULL, NULL, NULL } @@ -241,11 +241,21 @@ void fluid_audio_driver_settings(fluid_settings_t* settings) if (fluid_audio_drivers[i].settings != NULL) { fluid_audio_drivers[i].settings(settings); } - } + } } -fluid_audio_driver_t* +/** + * Create a new audio driver. + * @param settings Configuration settings used to select and create the audio + * driver. + * @param synth Synthesizer instance for which the audio driver is created for. + * @return The new audio driver instance. + * + * 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) { int i; @@ -260,7 +270,7 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) driver = (*fluid_audio_drivers[i].new)(settings, synth); if (driver) { driver->name = fluid_audio_drivers[i].name; - } + } return driver; } } @@ -269,7 +279,20 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) return NULL; } -fluid_audio_driver_t* +/** + * Create a new audio driver. + * @param settings Configuration settings used to select and create the audio + * driver. + * @param func Function called to fill audio buffers for audio playback + * @param data User defined data pointer to pass to 'func' + * @return The new audio driver instance. + * + * Like new_fluid_audio_driver() but allows for custom audio processing before + * audio is sent to audio driver. It is the responsibility of the callback + * 'func' to render the audio into the buffers. + * 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) { int i; @@ -285,7 +308,7 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi driver = (*fluid_audio_drivers[i].new2)(settings, func, data); if (driver) { driver->name = fluid_audio_drivers[i].name; - } + } return driver; } } @@ -294,7 +317,13 @@ new_fluid_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, voi return NULL; } -void +/** + * Deletes an audio driver instance. + * @param driver Audio driver instance to delete + * + * Shuts down an audio driver and deletes its instance. + */ +void delete_fluid_audio_driver(fluid_audio_driver_t* driver) { int i; diff --git a/src/libs/fluidsynth/src/fluid_adriver.h b/src/libs/fluidsynth/src/fluid_adriver.h index 0b925d69d7..c03937b2dc 100644 --- a/src/libs/fluidsynth/src/fluid_adriver.h +++ b/src/libs/fluidsynth/src/fluid_adriver.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -30,7 +30,7 @@ void fluid_audio_driver_settings(fluid_settings_t* settings); * fluid_audio_driver_t */ -struct _fluid_audio_driver_t +struct _fluid_audio_driver_t { char* name; }; diff --git a/src/libs/fluidsynth/src/fluid_aufile.c b/src/libs/fluidsynth/src/fluid_aufile.c index 905c829f2d..579844e831 100644 --- a/src/libs/fluidsynth/src/fluid_aufile.c +++ b/src/libs/fluidsynth/src/fluid_aufile.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -20,7 +20,7 @@ /* fluid_aufile.c * - * Audio driver, outputs the audio to a file (non real-time) + * Audio driver, outputs the audio to a file (non real-time) * */ @@ -31,9 +31,9 @@ /** fluid_file_audio_driver_t - * + * * This structure should not be accessed directly. Use audio port - * functions instead. + * functions instead. */ typedef struct { fluid_audio_driver_t driver; @@ -70,7 +70,7 @@ void fluid_file_audio_driver_settings(fluid_settings_t* settings) } -fluid_audio_driver_t* +fluid_audio_driver_t* new_fluid_file_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth) { @@ -82,7 +82,7 @@ new_fluid_file_audio_driver(fluid_settings_t* settings, dev = FLUID_NEW(fluid_file_audio_driver_t); if (dev == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; + return NULL; } FLUID_MEMSET(dev, 0, sizeof(fluid_file_audio_driver_t)); @@ -125,7 +125,7 @@ new_fluid_file_audio_driver(fluid_settings_t* settings, int delete_fluid_file_audio_driver(fluid_audio_driver_t* p) { fluid_file_audio_driver_t* dev = (fluid_file_audio_driver_t*) p; - + if (dev == NULL) { return FLUID_OK; } @@ -157,48 +157,27 @@ int delete_fluid_file_audio_driver(fluid_audio_driver_t* p) 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; - float* handle[2]; - int i, k, n, offset; - float s; + int n, offset; unsigned int sample_time; - handle[0] = dev->left; - handle[1] = dev->right; - - sample_time = (unsigned int) (dev->samples / dev->sample_rate * 1000.0); if (sample_time > clock_time) { return 1; } - (*dev->callback)(dev->data, dev->period_size, 0, NULL, 2, handle); - - for (i = 0, k = 0; i < dev->period_size; i++, k += 2) { - s = 32768.0f * dev->left[i]; - fluid_clip(s, -32768.0f, 32767.0f); - dev->buf[k] = (short) s; - } - - for (i = 0, k = 1; i < dev->period_size; i++, k += 2) { - s = 32768.0f * dev->right[i]; - fluid_clip(s, -32768.0f, 32767.0f); - dev->buf[k] = (short) s; - } - + fluid_synth_write_s16(dev->data, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2); + for (offset = 0; offset < dev->buf_size; offset += n) { - + n = fwrite((char*) dev->buf + offset, 1, dev->buf_size - offset, dev->file); if (n < 0) { - FLUID_LOG(FLUID_ERR, "Audio file error"); - return 0; - } + FLUID_LOG(FLUID_ERR, "Audio output file write error: %s", + strerror (errno)); + return 0; + } } - + dev->samples += dev->period_size; return 1; - - error_recovery: - - return 0; } diff --git a/src/libs/fluidsynth/src/fluid_chan.c b/src/libs/fluidsynth/src/fluid_chan.c index 81eaf5038d..f0e7346ade 100644 --- a/src/libs/fluidsynth/src/fluid_chan.c +++ b/src/libs/fluidsynth/src/fluid_chan.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -28,7 +28,7 @@ /* * new_fluid_channel */ -fluid_channel_t* +fluid_channel_t* new_fluid_channel(fluid_synth_t* synth, int num) { fluid_channel_t* chan; @@ -41,6 +41,7 @@ new_fluid_channel(fluid_synth_t* synth, int num) chan->synth = synth; chan->channum = num; + chan->preset = NULL; fluid_channel_init(chan); fluid_channel_init_ctrl(chan); @@ -48,19 +49,22 @@ new_fluid_channel(fluid_synth_t* synth, int num) return chan; } -void +void fluid_channel_init(fluid_channel_t* chan) { chan->prognum = (chan->channum == 9)? 0 : chan->channum; chan->banknum = (chan->channum == 9)? 128 : 0; chan->sfontnum = 0; + + if (chan->preset) delete_fluid_preset (chan->preset); chan->preset = fluid_synth_find_preset(chan->synth, chan->banknum, chan->prognum); + chan->interp_method = FLUID_INTERP_DEFAULT; chan->tuning = NULL; chan->nrpn_select = 0; } -void +void fluid_channel_init_ctrl(fluid_channel_t* chan) { int i; @@ -79,21 +83,21 @@ fluid_channel_init_ctrl(fluid_channel_t* chan) for (i = 0; i < 128; i++) { SETCC(chan, i, 0); } - + /* Volume / initial attenuation (MSB & LSB) */ - SETCC(chan, 7, 127); - SETCC(chan, 39, 0); + SETCC(chan, 7, 127); + SETCC(chan, 39, 0); /* Pan (MSB & LSB) */ - SETCC(chan, 10, 64); - SETCC(chan, 10, 64); + SETCC(chan, 10, 64); + SETCC(chan, 10, 64); /* Expression (MSB & LSB) */ - SETCC(chan, 11, 127); - SETCC(chan, 43, 127); + SETCC(chan, 11, 127); + SETCC(chan, 43, 127); } -void +void fluid_channel_reset(fluid_channel_t* chan) { fluid_channel_init(chan); @@ -103,9 +107,10 @@ fluid_channel_reset(fluid_channel_t* chan) /* * delete_fluid_channel */ -int +int delete_fluid_channel(fluid_channel_t* chan) { + if (chan->preset) delete_fluid_preset (chan->preset); FLUID_FREE(chan); return FLUID_OK; } @@ -113,12 +118,13 @@ delete_fluid_channel(fluid_channel_t* chan) /* * fluid_channel_set_preset */ -int +int fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset) { fluid_preset_notify(chan->preset, FLUID_PRESET_UNSELECTED, chan->channum); fluid_preset_notify(preset, FLUID_PRESET_SELECTED, chan->channum); + if (chan->preset) delete_fluid_preset (chan->preset); chan->preset = preset; return FLUID_OK; } @@ -126,7 +132,7 @@ fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset) /* * fluid_channel_get_preset */ -fluid_preset_t* +fluid_preset_t* fluid_channel_get_preset(fluid_channel_t* chan) { return chan->preset; @@ -135,7 +141,7 @@ fluid_channel_get_preset(fluid_channel_t* chan) /* * fluid_channel_get_banknum */ -unsigned int +unsigned int fluid_channel_get_banknum(fluid_channel_t* chan) { return chan->banknum; @@ -144,7 +150,7 @@ fluid_channel_get_banknum(fluid_channel_t* chan) /* * fluid_channel_set_prognum */ -int +int fluid_channel_set_prognum(fluid_channel_t* chan, int prognum) { chan->prognum = prognum; @@ -154,7 +160,7 @@ fluid_channel_set_prognum(fluid_channel_t* chan, int prognum) /* * fluid_channel_get_prognum */ -int +int fluid_channel_get_prognum(fluid_channel_t* chan) { return chan->prognum; @@ -163,7 +169,7 @@ fluid_channel_get_prognum(fluid_channel_t* chan) /* * fluid_channel_set_banknum */ -int +int fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum) { chan->banknum = banknum; @@ -173,14 +179,14 @@ fluid_channel_set_banknum(fluid_channel_t* chan, unsigned int banknum) /* * fluid_channel_cc */ -int +int fluid_channel_cc(fluid_channel_t* chan, int num, int value) { chan->cc[num] = value; - + switch (num) { - - case SUSTAIN_SWITCH: + + case SUSTAIN_SWITCH: { if (value < 64) { /* printf("** sustain off\n"); */ @@ -190,7 +196,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value) } } break; - + case BANK_SELECT_MSB: { chan->bank_msb = (unsigned char) (value & 0x7f); @@ -207,17 +213,17 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value) fluid_channel_set_banknum(chan, (unsigned int)(value & 0x7f)); /* KLE */ } break; - + case BANK_SELECT_LSB: { /* FIXME: according to the Downloadable Sounds II specification, bit 31 should be set when we receive the message on channel 10 (drum channel) */ - fluid_channel_set_banknum(chan, (((unsigned int) value & 0x7f) + fluid_channel_set_banknum(chan, (((unsigned int) value & 0x7f) + ((unsigned int) chan->bank_msb << 7))); } break; - + case ALL_NOTES_OFF: fluid_synth_all_notes_off(chan->synth, chan->channum); break; @@ -231,7 +237,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value) fluid_synth_modulate_voices_all(chan->synth, chan->channum); break; - case DATA_ENTRY_MSB: + case DATA_ENTRY_MSB: { int data = (value << 7) + chan->cc[DATA_ENTRY_LSB]; @@ -239,7 +245,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value) if ((chan->cc[NRPN_MSB] == 120) && (chan->cc[NRPN_LSB] < 100)) { float val = fluid_gen_scale_nrpn(chan->nrpn_select, data); FLUID_LOG(FLUID_WARN, "%s: %d: Data = %d, value = %f", __FILE__, __LINE__, data, val); - fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val); + fluid_synth_set_gen(chan->synth, chan->channum, chan->nrpn_select, val); } break; } @@ -262,7 +268,7 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value) chan->nrpn_select += value; FLUID_LOG(FLUID_WARN, "%s: %d: NRPN Select = %d", __FILE__, __LINE__, chan->nrpn_select); } - } + } break; case RPN_MSB: @@ -278,14 +284,14 @@ fluid_channel_cc(fluid_channel_t* chan, int num, int value) default: fluid_synth_modulate_voices(chan->synth, chan->channum, 1, num); } - + return FLUID_OK; } /* * fluid_channel_get_cc */ -int +int fluid_channel_get_cc(fluid_channel_t* chan, int num) { return ((num >= 0) && (num < 128))? chan->cc[num] : 0; @@ -294,7 +300,7 @@ fluid_channel_get_cc(fluid_channel_t* chan, int num) /* * fluid_channel_pitch_bend */ -int +int fluid_channel_pitch_bend(fluid_channel_t* chan, int val) { chan->pitch_bend = val; @@ -305,7 +311,7 @@ fluid_channel_pitch_bend(fluid_channel_t* chan, int val) /* * fluid_channel_pitch_wheel_sens */ -int +int fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val) { chan->pitch_wheel_sensitivity = val; @@ -316,7 +322,7 @@ fluid_channel_pitch_wheel_sens(fluid_channel_t* chan, int val) /* * fluid_channel_get_num */ -int +int fluid_channel_get_num(fluid_channel_t* chan) { return chan->channum; @@ -324,7 +330,7 @@ fluid_channel_get_num(fluid_channel_t* chan) /* Purpose: * Sets the index of the interpolation method used on this channel, - * as in fluid_interp in fluidsynth.h + * as in fluid_interp in fluidsynth.h */ void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method) { @@ -333,7 +339,7 @@ void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method) /* Purpose: * Returns the index of the interpolation method used on this channel, - * as in fluid_interp in fluidsynth.h + * as in fluid_interp in fluidsynth.h */ int fluid_channel_get_interp_method(fluid_channel_t* chan) { diff --git a/src/libs/fluidsynth/src/fluid_chan.h b/src/libs/fluidsynth/src/fluid_chan.h index 788efb6bb0..72e201849f 100644 --- a/src/libs/fluidsynth/src/fluid_chan.h +++ b/src/libs/fluidsynth/src/fluid_chan.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -64,7 +64,7 @@ struct _fluid_channel_t * 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 sound font * and the values of modulators. The gen_abs field, is a boolean diff --git a/src/libs/fluidsynth/src/fluid_chorus.c b/src/libs/fluidsynth/src/fluid_chorus.c index 74cf5d8867..0f19995128 100644 --- a/src/libs/fluidsynth/src/fluid_chorus.c +++ b/src/libs/fluidsynth/src/fluid_chorus.c @@ -2,8 +2,8 @@ * August 24, 1998 * Copyright (C) 1998 Juergen Mueller And Sundry Contributors * This source code is freely redistributable and may be used for - * any purpose. This copyright notice must be maintained. - * Juergen Mueller And Sundry Contributors are not responsible for + * any purpose. This copyright notice must be maintained. + * Juergen Mueller And Sundry Contributors are not responsible for * the consequences of using this software. */ @@ -12,7 +12,7 @@ CHANGES - Adapted for fluidsynth, Peter Hanappe, March 2002 - + - Variable delay line implementation using bandlimited interpolation, code reorganization: Markus Nentwig May 2002 @@ -21,7 +21,7 @@ /* * Chorus effect. - * + * * Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ): * * * gain-in ___ @@ -40,7 +40,7 @@ * +---->| delay n |----------------------------->| | * |_________| | | * /|\ |___| - * | | + * | | * +-----------------+ +--------------+ | * gain-out * | Delay control n |<--| mod. speed n | | * +-----------------+ +--------------+ +----->obuff @@ -74,10 +74,10 @@ #define MIN_SPEED_HZ 0.29 #define MAX_SPEED_HZ 5 -/* Length of one delay line in samples: - * Set through MAX_SAMPLES_LN2. - * For example: - * MAX_SAMPLES_LN2=12 +/* Length of one delay line in samples: + * Set through MAX_SAMPLES_LN2. + * For example: + * MAX_SAMPLES_LN2=12 * => MAX_SAMPLES=pow(2,12)=4096 * => MAX_SAMPLES_ANDMASK=4095 */ @@ -89,7 +89,7 @@ /* Interpolate how many steps between samples? Must be power of two For example: 8 => use a resolution of 256 steps between any two - samples + samples */ #define INTERPOLATION_SUBSAMPLES_LN2 8 #define INTERPOLATION_SUBSAMPLES (1 << (INTERPOLATION_SUBSAMPLES_LN2-1)) @@ -98,13 +98,13 @@ /* Use how many samples for interpolation? Must be odd. '7' sounds relatively clean, when listening to the modulated delay signal alone. For a demo on aliasing try '1' With '3', the aliasing is - still quite pronounced for some input frequencies + still quite pronounced for some input frequencies */ #define INTERPOLATION_SAMPLES 5 /* Private data for SKEL file */ struct _fluid_chorus_t { - /* Store the values between fluid_chorus_set_xxx and fluid_chorus_update + /* Store the values between fluid_chorus_set_xxx and fluid_chorus_update * Logic behind this: * - both 'parameter' and 'new_parameter' hold the same value. * - To change the chorus settings, 'new_parameter' is modified and @@ -124,7 +124,7 @@ struct _fluid_chorus_t { int new_number_blocks; /* next value, if parameter check is OK */ fluid_real_t *chorusbuf; - int counter; + int counter; long phase[MAX_CHORUS]; long modulation_period_samples; int *lookup_tab; @@ -137,12 +137,12 @@ struct _fluid_chorus_t { void fluid_chorus_triangle(int *buf, int len, int depth); 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; - + chorus = FLUID_NEW(fluid_chorus_t); if (chorus == NULL) { fluid_log(FLUID_PANIC, "chorus: Out of memory"); @@ -157,7 +157,7 @@ new_fluid_chorus(fluid_real_t sample_rate) /* i: Offset in terms of whole samples */ for (i = 0; i < INTERPOLATION_SAMPLES; i++){ - + /* ii: Offset in terms of fractional samples ('subsamples') */ for (ii = 0; ii < INTERPOLATION_SUBSAMPLES; ii++){ /* Move the origin into the center of the table */ @@ -182,7 +182,7 @@ new_fluid_chorus(fluid_real_t sample_rate) fluid_log(FLUID_PANIC, "chorus: Out of memory"); goto error_recovery; } - + /* allocate sample buffer */ chorus->chorusbuf = FLUID_ARRAY(fluid_real_t, MAX_SAMPLES); @@ -194,7 +194,7 @@ new_fluid_chorus(fluid_real_t sample_rate) if (fluid_chorus_init(chorus) != FLUID_OK){ goto error_recovery; }; - + return chorus; error_recovery: @@ -203,7 +203,7 @@ new_fluid_chorus(fluid_real_t sample_rate) } -int +int fluid_chorus_init(fluid_chorus_t* chorus) { int i; @@ -306,7 +306,7 @@ int fluid_chorus_get_type(fluid_chorus_t* chorus) return chorus->type; }; -void +void delete_fluid_chorus(fluid_chorus_t* chorus) { if (chorus == NULL) { @@ -320,7 +320,7 @@ delete_fluid_chorus(fluid_chorus_t* chorus) if (chorus->lookup_tab != NULL) { FLUID_FREE(chorus->lookup_tab); } - + FLUID_FREE(chorus); } @@ -328,12 +328,12 @@ delete_fluid_chorus(fluid_chorus_t* chorus) /* Purpose: * Calculates the internal chorus parameters using the settings from * fluid_chorus_set_xxx. */ -int +int fluid_chorus_update(fluid_chorus_t* chorus) { int i; int modulation_depth_samples; - + if (chorus->new_number_blocks < 0) { fluid_log(FLUID_WARN, "chorus: number blocks must be >=0! Setting value to 0."); chorus->new_number_blocks = 0; @@ -342,13 +342,13 @@ fluid_chorus_update(fluid_chorus_t* chorus) MAX_CHORUS); chorus->new_number_blocks = MAX_CHORUS; }; - + if (chorus->new_speed_Hz < MIN_SPEED_HZ) { - fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.", + fluid_log(FLUID_WARN, "chorus: speed is too low (min %f)! Setting value to min.", (double) MIN_SPEED_HZ); chorus->new_speed_Hz = MIN_SPEED_HZ; } else if (chorus->new_speed_Hz > MAX_SPEED_HZ) { - fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.", + fluid_log(FLUID_WARN, "chorus: speed must be below %f Hz! Setting value to max.", (double) MAX_SPEED_HZ); chorus->new_speed_Hz = MAX_SPEED_HZ; } @@ -357,7 +357,7 @@ fluid_chorus_update(fluid_chorus_t* chorus) chorus->new_depth_ms = 0.0; } /* Depth: Check for too high value through modulation_depth_samples. */ - + if (chorus->new_level < 0.0) { fluid_log(FLUID_WARN, "chorus: level must be positive! Setting value to 0."); chorus->new_level = 0.0; @@ -366,40 +366,40 @@ fluid_chorus_update(fluid_chorus_t* chorus) "Setting it to 0.1."); chorus->new_level = 0.1; } - + /* The modulating LFO goes through a full period every x samples: */ chorus->modulation_period_samples = chorus->sample_rate / chorus->new_speed_Hz; - + /* The variation in delay time is x: */ - modulation_depth_samples = (int) + modulation_depth_samples = (int) (chorus->new_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, + 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, + 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, + 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 + chorus->phase[i] = (int) ((double) chorus->modulation_period_samples * (double) i / (double) chorus->number_blocks); } - + /* Start of the circular buffer */ chorus->counter = 0; @@ -409,7 +409,7 @@ fluid_chorus_update(fluid_chorus_t* chorus) chorus->speed_Hz = chorus->new_speed_Hz; chorus->number_blocks = chorus->new_number_blocks; return FLUID_OK; - + /* failure: */ /* Note: This lives on the assumption, that the last chorus values were correct. * If not, this will loop forever and a day. */ @@ -423,7 +423,7 @@ fluid_chorus_update(fluid_chorus_t* chorus) } -void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, +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; @@ -447,19 +447,19 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, 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 + int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter - chorus->lookup_tab[chorus->phase[i]]); - + int pos_samples = pos_subsamples/INTERPOLATION_SUBSAMPLES; /* 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 @@ -467,8 +467,8 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, /* 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]); + d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] + * chorus->sinc_table[ii][pos_subsamples]; pos_samples--; }; @@ -478,11 +478,11 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, } /* foreach chorus block */ d_out *= chorus->level; - + /* 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; @@ -490,8 +490,8 @@ void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, } /* foreach sample */ } -/* Duplication of code ... */ -void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, +/* 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) { int sample_index; @@ -515,19 +515,19 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, 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 + int pos_subsamples = (INTERPOLATION_SUBSAMPLES * chorus->counter - chorus->lookup_tab[chorus->phase[i]]); - + int pos_samples = pos_subsamples / INTERPOLATION_SUBSAMPLES; /* 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 @@ -535,7 +535,8 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, /* 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]; + d_out += chorus->chorusbuf[pos_samples & MAX_SAMPLES_ANDMASK] + * chorus->sinc_table[ii][pos_subsamples]; pos_samples--; }; @@ -545,11 +546,11 @@ void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, } /* foreach chorus block */ d_out *= chorus->level; - - /* Add the chorus sum d_out to output */ + + /* 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; @@ -598,7 +599,7 @@ void fluid_chorus_triangle(int *buf, int len, int depth) } } -void +void fluid_chorus_reset(fluid_chorus_t* chorus) { fluid_chorus_init(chorus); diff --git a/src/libs/fluidsynth/src/fluid_chorus.h b/src/libs/fluidsynth/src/fluid_chorus.h index 1a26710b25..e82b2ff8c4 100644 --- a/src/libs/fluidsynth/src/fluid_chorus.h +++ b/src/libs/fluidsynth/src/fluid_chorus.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -32,9 +32,9 @@ typedef struct _fluid_chorus_t fluid_chorus_t; */ fluid_chorus_t* new_fluid_chorus(fluid_real_t sample_rate); void delete_fluid_chorus(fluid_chorus_t* chorus); -void fluid_chorus_processmix(fluid_chorus_t* chorus, fluid_real_t *in, +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, +void fluid_chorus_processreplace(fluid_chorus_t* chorus, fluid_real_t *in, fluid_real_t *left_out, fluid_real_t *right_out); int fluid_chorus_init(fluid_chorus_t* chorus); diff --git a/src/libs/fluidsynth/src/fluid_cmd.c b/src/libs/fluidsynth/src/fluid_cmd.c index dd880c6fa8..086a225fed 100644 --- a/src/libs/fluidsynth/src/fluid_cmd.c +++ b/src/libs/fluidsynth/src/fluid_cmd.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -21,7 +21,6 @@ #include "fluidsynth_priv.h" #include "fluid_cmd.h" #include "fluid_synth.h" -#include "fluid_strtok.h" #include "fluid_settings.h" #include "fluid_io.h" #include "fluid_hash.h" @@ -36,6 +35,7 @@ #endif #define MAX_TOKENS 100 /* LADSPA plugins need lots of parameters */ +#define MAX_COMMAND_LEN 1024 /* max command length accepted by fluid_command() */ #define FLUID_WORKLINELENGTH 1024 /* LADSPA plugins use long command lines */ void fluid_shell_settings(fluid_settings_t* settings) @@ -157,44 +157,43 @@ fluid_cmd_t fluid_commands[] = { { NULL, NULL, NULL, NULL, NULL } }; -int fluid_command2(fluid_strtok_t* strtok, fluid_cmd_handler_t* handler, - char* cmd, fluid_ostream_t out); - -int +/** + * Process a string command. + * NOTE: FluidSynth 1.0.8+ no longer modifies the 'cmd' string. + * @param handle FluidSynth command handler + * @param cmd Command string (NOTE: Gets modified by FluidSynth prior to 1.0.8) + * @param out Output stream to display command response to + * @return Integer value corresponding to: -1 on command error, 0 on success, + * 1 if 'cmd' is a comment or is empty and -2 if quit was issued + */ +int fluid_command(fluid_cmd_handler_t* handler, char* cmd, fluid_ostream_t out) -{ - int ret; - - fluid_strtok_t* st = new_fluid_strtok(cmd, " \t\n\r"); - if (st == NULL) { - return -1; - } - - ret = fluid_command2(st, handler, cmd, out); - delete_fluid_strtok(st); - return ret; -} - -int -fluid_command2(fluid_strtok_t* st, fluid_cmd_handler_t* handler, char* cmd, fluid_ostream_t out) { char* token[MAX_TOKENS]; + char buf[MAX_COMMAND_LEN+1]; + char *strtok, *tok; int num_tokens = 0; if (cmd[0] == '#') { return 1; } - /* tokenize the input line */ - fluid_strtok_set(st, cmd, " \t\n\r"); - while (fluid_strtok_has_more(st)) { - token[num_tokens++] = fluid_strtok_next_token(st); - } - - if (num_tokens == 0) { - return 1; + if (strlen (cmd) > MAX_COMMAND_LEN) + { + fluid_ostream_printf(out, "Command exceeded max length of %d chars\n", + MAX_COMMAND_LEN); + return -1; } + FLUID_STRCPY(buf, cmd); /* copy - since fluid_strtok thrashes it */ + strtok = buf; + + /* tokenize the input line */ + while ((tok = fluid_strtok (&strtok, " \t\n\r"))) + token[num_tokens++] = tok; + + if (num_tokens == 0) return 1; + /* handle the command */ return fluid_cmd_handler_handle(handler, num_tokens, &token[0], out); } @@ -203,13 +202,12 @@ struct _fluid_shell_t { fluid_settings_t* settings; fluid_cmd_handler_t* handler; fluid_thread_t* thread; - fluid_strtok_t* st; fluid_istream_t in; fluid_ostream_t out; }; int fluid_shell_run(fluid_shell_t* shell); -void fluid_shell_init(fluid_shell_t* shell, +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); @@ -241,13 +239,12 @@ fluid_shell_t* new_fluid_shell(fluid_settings_t* settings, fluid_cmd_handler_t* } -void fluid_shell_init(fluid_shell_t* shell, +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) { shell->settings = settings; shell->handler = handler; - shell->st = new_fluid_strtok(NULL, NULL); shell->in = in; shell->out = out; } @@ -257,6 +254,7 @@ void delete_fluid_shell(fluid_shell_t* shell) if (shell->thread != NULL) { delete_fluid_thread(shell->thread); } + FLUID_FREE(shell); } @@ -275,7 +273,7 @@ int fluid_shell_run(fluid_shell_t* shell) /* handle user input */ while (cont) { - + n = fluid_istream_readline(shell->in, prompt, workline, FLUID_WORKLINELENGTH); if (n < 0) { @@ -287,13 +285,13 @@ int fluid_shell_run(fluid_shell_t* shell) add_history(workline); } #endif - + /* handle the command */ - switch (fluid_command2(shell->st, shell->handler, workline, shell->out)) { - + switch (fluid_command(shell->handler, workline, shell->out)) { + case 1: /* empty line or comment */ break; - + case -1: /* erronous command */ errors++; case 0: /* valid command */ @@ -313,7 +311,7 @@ int fluid_shell_run(fluid_shell_t* shell) } -void +void fluid_usershell(fluid_settings_t* settings, fluid_cmd_handler_t* handler) { fluid_shell_t shell; @@ -321,13 +319,13 @@ fluid_usershell(fluid_settings_t* settings, fluid_cmd_handler_t* handler) fluid_shell_run(&shell); } -int +int fluid_source(fluid_cmd_handler_t* handler, char* filename) { int file; fluid_shell_t shell; -#ifdef WIN32 +#ifdef WIN32 file = _open(filename, _O_RDONLY); #else file = open(filename, O_RDONLY); @@ -340,8 +338,8 @@ fluid_source(fluid_cmd_handler_t* handler, char* filename) } -char* -fluid_get_userconf(char* buf, int len) +char* +fluid_get_userconf(char* buf, int len) { #if defined(WIN32) || defined(MACOS9) return NULL; @@ -356,8 +354,8 @@ fluid_get_userconf(char* buf, int len) #endif } -char* -fluid_get_sysconf(char* buf, int len) +char* +fluid_get_sysconf(char* buf, int len) { #if defined(WIN32) || defined(MACOS9) return NULL; @@ -368,10 +366,10 @@ fluid_get_sysconf(char* buf, int len) } -/* - * handlers +/* + * handlers */ -int +int fluid_handle_noteon(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 3) { @@ -382,10 +380,10 @@ fluid_handle_noteon(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out fluid_ostream_printf(out, "noteon: invalid argument\n"); return -1; } - return fluid_synth_noteon(synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); + return fluid_synth_noteon(synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); } -int +int fluid_handle_noteoff(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 2) { @@ -396,10 +394,10 @@ fluid_handle_noteoff(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t ou fluid_ostream_printf(out, "noteon: invalid argument\n"); return -1; } - return fluid_synth_noteoff(synth, atoi(av[0]), atoi(av[1])); + return fluid_synth_noteoff(synth, atoi(av[0]), atoi(av[1])); } -int +int fluid_handle_cc(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 3) { @@ -410,10 +408,10 @@ fluid_handle_cc(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) fluid_ostream_printf(out, "cc: invalid argument\n"); return -1; } - return fluid_synth_cc(synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); + return fluid_synth_cc(synth, atoi(av[0]), atoi(av[1]), atoi(av[2])); } -int +int fluid_handle_prog(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 2) { @@ -424,10 +422,10 @@ fluid_handle_prog(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) fluid_ostream_printf(out, "prog: invalid argument\n"); return -1; } - return fluid_synth_program_change(synth, atoi(av[0]), atoi(av[1])); + return fluid_synth_program_change(synth, atoi(av[0]), atoi(av[1])); } -int +int fluid_handle_select(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int sfont_id; @@ -439,12 +437,12 @@ fluid_handle_select(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out fluid_ostream_printf(out, "preset: too few arguments\n"); return -1; } - if (!fluid_is_number(av[0]) || !fluid_is_number(av[1]) + 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 -1; } - + chan = atoi(av[0]); sfont_id = atoi(av[1]); bank = atoi(av[2]); @@ -452,7 +450,7 @@ fluid_handle_select(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out if (sfont_id != 0) { return fluid_synth_program_select(synth, chan, sfont_id, bank, prog); - } else { + } else { if (fluid_synth_bank_select(synth, chan, bank) == FLUID_OK) { return fluid_synth_program_change(synth, chan, prog); } @@ -460,7 +458,7 @@ fluid_handle_select(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out } } -int +int fluid_handle_inst(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int font; @@ -482,18 +480,18 @@ fluid_handle_inst(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) sfont = fluid_synth_get_sfont_by_id(synth, font); offset = fluid_synth_get_bank_offset(synth, font); - + if (sfont == NULL) { - fluid_ostream_printf(out, "inst: invalid font number\n"); + fluid_ostream_printf(out, "inst: invalid font number\n"); return -1; } fluid_sfont_iteration_start(sfont); while (fluid_sfont_iteration_next(sfont, &preset)) { - fluid_ostream_printf(out, "%03d-%03d %s\n", - fluid_preset_get_banknum(&preset) + offset, - fluid_preset_get_num(&preset), + fluid_ostream_printf(out, "%03d-%03d %s\n", + fluid_preset_get_banknum(&preset) + offset, + fluid_preset_get_num(&preset), fluid_preset_get_name(&preset)); } @@ -501,15 +499,15 @@ fluid_handle_inst(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) } -int +int fluid_handle_channels(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int i; fluid_preset_t* preset; int verbose = 0; - + if (ac > 0 && strcmp( av[0], "-verbose") == 0) verbose = 1; - + for (i = 0; i < fluid_synth_count_midi_channels(synth); i++) { preset = fluid_synth_get_channel_preset(synth, i); if (preset == NULL) fluid_ostream_printf(out, "chan %d, no preset\n", i); @@ -523,7 +521,7 @@ fluid_handle_channels(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t o return 0; } -int +int fluid_handle_load(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { char buf[1024]; @@ -565,7 +563,7 @@ fluid_handle_load(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) return 0; } -int +int fluid_handle_unload(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int reset = 1; @@ -587,7 +585,7 @@ fluid_handle_unload(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out return 0; } -int +int fluid_handle_reload(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 1) { @@ -606,7 +604,7 @@ fluid_handle_reload(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out } -int +int fluid_handle_fonts(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int i; @@ -624,15 +622,15 @@ fluid_handle_fonts(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) for (i = 0; i < num; i++) { sfont = fluid_synth_get_sfont(synth, i); - fluid_ostream_printf(out, "%2d %s\n", - fluid_sfont_get_id(sfont), + fluid_ostream_printf(out, "%2d %s\n", + fluid_sfont_get_id(sfont), fluid_sfont_get_name(sfont)); } return 0; } -int +int fluid_handle_mstat(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { /* fluid_ostream_printf(out, "Dvr=%s, Dev=%s\n", */ @@ -802,7 +800,7 @@ fluid_handle_choruslevel(fluid_synth_t* synth, int ac, char** av, fluid_ostream_ return -1; } level = atof(av[0]); - fluid_chorus_set_level(synth->chorus, level); + fluid_chorus_set_level(synth->chorus, level); return fluid_chorus_update(synth->chorus); } @@ -817,7 +815,7 @@ fluid_handle_chorusspeed(fluid_synth_t* synth, int ac, char** av, fluid_ostream_ fluid_ostream_printf(out, "cho_set_speed: too few arguments.\n"); return -1; } - speed = atof(av[0]); + speed = atof(av[0]); fluid_chorus_set_speed_Hz(synth->chorus, speed); return fluid_chorus_update(synth->chorus); } @@ -837,14 +835,14 @@ fluid_handle_chorusdepth(fluid_synth_t* synth, int ac, char** av, fluid_ostream_ return fluid_chorus_update(synth->chorus); } -int +int fluid_handle_chorus(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 1) { fluid_ostream_printf(out, "chorus: too few arguments\n"); return -1; } - + if ((strcmp(av[0], "0") == 0) || (strcmp(av[0], "off") == 0)) { fluid_synth_set_chorus_on(synth,0); } else if ((strcmp(av[0], "1") == 0) || (strcmp(av[0], "on") == 0)) { @@ -862,7 +860,7 @@ fluid_handle_chorus(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out * The command itself is useful, when the synth is used via TCP/IP. * It can signal for example, that a list of commands has been processed. */ -int +int fluid_handle_echo(fluid_cmd_handler_t* handler, int ac, char** av, fluid_ostream_t out) { if (ac < 1) { @@ -875,7 +873,7 @@ fluid_handle_echo(fluid_cmd_handler_t* handler, int ac, char** av, fluid_ostream return 0; } -int +int fluid_handle_source(fluid_cmd_handler_t* handler, int ac, char** av, fluid_ostream_t out) { if (ac < 1) { @@ -924,7 +922,7 @@ fluid_handle_interp(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out fluid_ostream_printf(out, "interp: too few arguments.\n"); return -1; } - + interp = atoi(av[0]); if ((interp < 0) || (interp > FLUID_INTERP_HIGHEST)) { @@ -949,25 +947,25 @@ fluid_handle_interpc(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t ou fluid_ostream_printf(out, "interpc: too few arguments.\n"); return -1; } - + chan = atoi(av[0]); interp = atoi(av[1]); if ((chan < 0) || (chan >= fluid_synth_count_midi_channels(synth))){ fluid_ostream_printf(out, "interp: Bad value for channel number.\n"); - return -1; + return -1; }; if ((interp < 0) || (interp > FLUID_INTERP_HIGHEST)) { fluid_ostream_printf(out, "interp: Bad value for interpolation method.\n"); return -1; }; - + fluid_synth_set_interp_method(synth, chan, interp); return 0; } -int +int fluid_handle_tuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { char *name; @@ -977,27 +975,27 @@ fluid_handle_tuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out fluid_ostream_printf(out, "tuning: too few arguments.\n"); return -1; } - + name = av[0]; if (!fluid_is_number(av[1])) { fluid_ostream_printf(out, "tuning: 2nd argument should be a number.\n"); - return -1; + return -1; } bank = atoi(av[1]); if ((bank < 0) || (bank >= 128)){ fluid_ostream_printf(out, "tuning: invalid bank number.\n"); - return -1; + return -1; }; if (!fluid_is_number(av[2])) { fluid_ostream_printf(out, "tuning: 3rd argument should be a number.\n"); - return -1; + return -1; } prog = atoi(av[2]); if ((prog < 0) || (prog >= 128)){ fluid_ostream_printf(out, "tuning: invalid program number.\n"); - return -1; + return -1; }; fluid_synth_create_key_tuning(synth, bank, prog, name, NULL); @@ -1005,7 +1003,7 @@ fluid_handle_tuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out return 0; } -int +int fluid_handle_tune(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int bank, prog, key; @@ -1015,41 +1013,41 @@ fluid_handle_tune(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) fluid_ostream_printf(out, "tune: too few arguments.\n"); return -1; } - + if (!fluid_is_number(av[0])) { fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); - return -1; + return -1; } bank = atoi(av[0]); if ((bank < 0) || (bank >= 128)){ fluid_ostream_printf(out, "tune: invalid bank number.\n"); - return -1; + return -1; }; if (!fluid_is_number(av[1])) { fluid_ostream_printf(out, "tune: 2nd argument should be a number.\n"); - return -1; + return -1; } prog = atoi(av[1]); if ((prog < 0) || (prog >= 128)){ fluid_ostream_printf(out, "tune: invalid program number.\n"); - return -1; + return -1; }; if (!fluid_is_number(av[2])) { fluid_ostream_printf(out, "tune: 3rd argument should be a number.\n"); - return -1; + return -1; } key = atoi(av[2]); if ((key < 0) || (key >= 128)){ fluid_ostream_printf(out, "tune: invalid key number.\n"); - return -1; + return -1; }; pitch = atof(av[3]); if (pitch < 0.0f) { fluid_ostream_printf(out, "tune: invalid pitch.\n"); - return -1; + return -1; }; fluid_synth_tune_notes(synth, bank, prog, 1, &key, &pitch, 0); @@ -1057,7 +1055,7 @@ fluid_handle_tune(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) return 0; } -int +int fluid_handle_settuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int chan, bank, prog; @@ -1066,35 +1064,35 @@ fluid_handle_settuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t fluid_ostream_printf(out, "settuning: too few arguments.\n"); return -1; } - + if (!fluid_is_number(av[0])) { fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); - return -1; + return -1; } chan = atoi(av[0]); if ((chan < 0) || (chan >= fluid_synth_count_midi_channels(synth))){ fluid_ostream_printf(out, "tune: invalid channel number.\n"); - return -1; + return -1; }; if (!fluid_is_number(av[1])) { fluid_ostream_printf(out, "tuning: 2nd argument should be a number.\n"); - return -1; + return -1; } bank = atoi(av[1]); if ((bank < 0) || (bank >= 128)){ fluid_ostream_printf(out, "tuning: invalid bank number.\n"); - return -1; + return -1; }; if (!fluid_is_number(av[2])) { fluid_ostream_printf(out, "tuning: 3rd argument should be a number.\n"); - return -1; + return -1; } prog = atoi(av[2]); if ((prog < 0) || (prog >= 128)){ fluid_ostream_printf(out, "tuning: invalid program number.\n"); - return -1; + return -1; }; fluid_synth_select_tuning(synth, chan, bank, prog); @@ -1102,7 +1100,7 @@ fluid_handle_settuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t return 0; } -int +int fluid_handle_resettuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int chan; @@ -1111,15 +1109,15 @@ fluid_handle_resettuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_ fluid_ostream_printf(out, "resettuning: too few arguments.\n"); return -1; } - + if (!fluid_is_number(av[0])) { fluid_ostream_printf(out, "tune: 1st argument should be a number.\n"); - return -1; + return -1; } chan = atoi(av[0]); if ((chan < 0) || (chan >= fluid_synth_count_midi_channels(synth))){ fluid_ostream_printf(out, "tune: invalid channel number.\n"); - return -1; + return -1; }; fluid_synth_reset_tuning(synth, chan); @@ -1127,7 +1125,7 @@ fluid_handle_resettuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_ return 0; } -int +int fluid_handle_tunings(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int bank, prog; @@ -1149,7 +1147,7 @@ fluid_handle_tunings(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t ou return 0; } -int +int fluid_handle_dumptuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { int bank, prog, i; @@ -1160,25 +1158,25 @@ fluid_handle_dumptuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t fluid_ostream_printf(out, "dumptuning: too few arguments.\n"); return -1; } - + if (!fluid_is_number(av[0])) { fluid_ostream_printf(out, "dumptuning: 1st argument should be a number.\n"); - return -1; + return -1; } bank = atoi(av[0]); if ((bank < 0) || (bank >= 128)){ fluid_ostream_printf(out, "dumptuning: invalid bank number.\n"); - return -1; + return -1; }; if (!fluid_is_number(av[1])) { fluid_ostream_printf(out, "dumptuning: 2nd argument should be a number.\n"); - return -1; + return -1; } prog = atoi(av[1]); if ((prog < 0) || (prog >= 128)){ fluid_ostream_printf(out, "dumptuning: invalid program number.\n"); - return -1; + return -1; }; fluid_synth_tuning_dump(synth, bank, prog, name, 256, pitch); @@ -1192,13 +1190,13 @@ fluid_handle_dumptuning(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t return 0; } -int +int fluid_handle_set(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 2) { fluid_ostream_printf(out, "set: too few arguments.\n"); return -1; - } + } if (fluid_is_number(av[1])) { if (FLUID_STRCHR(av[1], '.') != NULL) { @@ -1213,18 +1211,18 @@ fluid_handle_set(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) return 0; } -int +int fluid_handle_get(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { if (ac < 1) { fluid_ostream_printf(out, "get: too few arguments.\n"); return -1; - } + } switch (fluid_settings_get_type(fluid_synth_get_settings(synth), av[0])) { case FLUID_NO_TYPE: fluid_ostream_printf(out, "get: no such settings '%s'.", av[0]); - return -1; + return -1; case FLUID_NUM_TYPE: { double value; @@ -1258,7 +1256,7 @@ fluid_handle_get(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) struct _fluid_handle_settings_data_t { int len; fluid_synth_t* synth; - fluid_ostream_t out; + fluid_ostream_t out; }; static void fluid_handle_settings_iter1(void* data, char* name, int type) @@ -1289,14 +1287,14 @@ static void fluid_handle_settings_iter2(void* data, char* name, int type) fluid_ostream_printf(d->out, "%.3f\n", value); break; } - + case FLUID_INT_TYPE: { int value; fluid_synth_getint(d->synth, name, &value); fluid_ostream_printf(d->out, "%d\n", value); break; } - + case FLUID_STR_TYPE: { char* s; fluid_synth_getstr(d->synth, name, &s); @@ -1306,7 +1304,7 @@ static void fluid_handle_settings_iter2(void* data, char* name, int type) } } -int +int fluid_handle_settings(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { struct _fluid_handle_settings_data_t data; @@ -1323,7 +1321,7 @@ fluid_handle_settings(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t o struct _fluid_handle_option_data_t { int first; - fluid_ostream_t out; + fluid_ostream_t out; }; void fluid_handle_print_option(void* data, char* name, char* option) @@ -1338,7 +1336,7 @@ void fluid_handle_print_option(void* data, char* name, char* option) } } -int +int fluid_handle_info(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { fluid_settings_t* settings = fluid_synth_get_settings(synth); @@ -1347,12 +1345,12 @@ fluid_handle_info(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) if (ac < 1) { fluid_ostream_printf(out, "info: too few arguments.\n"); return -1; - } + } switch (fluid_settings_get_type(settings, av[0])) { case FLUID_NO_TYPE: fluid_ostream_printf(out, "info: no such settings '%s'.", av[0]); - return -1; + return -1; case FLUID_NUM_TYPE: { double value, min, max; @@ -1363,9 +1361,9 @@ fluid_handle_info(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) 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", + fluid_ostream_printf(out, "Default value: %.3f\n", fluid_settings_getnum_default(settings, av[0])); - fluid_ostream_printf(out, "Real-time: %s\n", + fluid_ostream_printf(out, "Real-time: %s\n", fluid_settings_is_realtime(settings, av[0])? "yes" : "no"); break; } @@ -1379,9 +1377,9 @@ fluid_handle_info(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) 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", + fluid_ostream_printf(out, "Default value: %d\n", fluid_settings_getint_default(settings, av[0])); - fluid_ostream_printf(out, "Real-time: %s\n", + fluid_ostream_printf(out, "Real-time: %s\n", fluid_settings_is_realtime(settings, av[0])? "yes" : "no"); break; } @@ -1392,7 +1390,7 @@ fluid_handle_info(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) fluid_ostream_printf(out, "%s:\n", av[0]); fluid_ostream_printf(out, "Type: string\n"); fluid_ostream_printf(out, "Value: %s\n", s); - fluid_ostream_printf(out, "Default value: %s\n", + fluid_ostream_printf(out, "Default value: %s\n", fluid_settings_getstr_default(settings, av[0])); data.out = out; @@ -1401,7 +1399,7 @@ fluid_handle_info(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) 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_ostream_printf(out, "Real-time: %s\n", fluid_settings_is_realtime(settings, av[0])? "yes" : "no"); break; } @@ -1414,21 +1412,21 @@ fluid_handle_info(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) return 0; } -int +int fluid_handle_reset(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { fluid_synth_system_reset(synth); return 0; } -int +int fluid_handle_quit(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { fluid_ostream_printf(out, "cheers!\n"); return -2; } -int +int fluid_handle_help(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) { /* Purpose: @@ -1451,7 +1449,7 @@ fluid_handle_help(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) } if (strcmp(topic,"help") == 0){ /* "help help": Print a list of all topics */ - fluid_ostream_printf(out, + fluid_ostream_printf(out, "*** Help topics:***\n" "help help (prints this list)\n" "help all (prints all topics)\n"); @@ -1485,7 +1483,7 @@ fluid_handle_help(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out) return 0; } -int +int fluid_is_number(char* a) { while (*a != 0) { @@ -1497,7 +1495,7 @@ fluid_is_number(char* a) return 1; } -int +int fluid_is_empty(char* a) { while (*a != 0) { @@ -1509,7 +1507,7 @@ fluid_is_empty(char* a) return 1; } -char* +char* fluid_expand_path(char* path, char* new_path, int len) { #if defined(WIN32) || defined(MACOS9) @@ -1534,7 +1532,7 @@ fluid_expand_path(char* path, char* new_path, int len) /* - * Command + * Command */ fluid_cmd_t* fluid_cmd_copy(fluid_cmd_t* cmd) @@ -1573,7 +1571,7 @@ void delete_fluid_cmd(fluid_cmd_t* cmd) void fluid_cmd_handler_delete(void* value, int type) { - delete_fluid_cmd((fluid_cmd_t*) value); + delete_fluid_cmd((fluid_cmd_t*) value); } fluid_cmd_handler_t* new_fluid_cmd_handler(fluid_synth_t* synth) @@ -1581,9 +1579,9 @@ fluid_cmd_handler_t* new_fluid_cmd_handler(fluid_synth_t* synth) int i; fluid_cmd_handler_t* handler; - fluid_cmd_t source = { + fluid_cmd_t source = { "source", "general", (fluid_cmd_func_t) fluid_handle_source, NULL, - "source filename Load a file and parse every line as a command" + "source filename Load a file and parse every line as a command" }; handler = new_fluid_hashtable(fluid_cmd_handler_delete); @@ -1651,13 +1649,13 @@ struct _fluid_server_t { fluid_mutex_t mutex; }; -static void fluid_server_handle_connection(fluid_server_t* server, - fluid_socket_t client_socket, +static void fluid_server_handle_connection(fluid_server_t* server, + fluid_socket_t client_socket, char* addr); static void fluid_server_close(fluid_server_t* server); -fluid_server_t* -new_fluid_server(fluid_settings_t* settings, +fluid_server_t* +new_fluid_server(fluid_settings_t* settings, fluid_server_newclient_func_t newclient, void* data) { @@ -1666,7 +1664,7 @@ new_fluid_server(fluid_settings_t* settings, server = FLUID_NEW(fluid_server_t); if (server == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } @@ -1679,8 +1677,8 @@ new_fluid_server(fluid_settings_t* settings, fluid_settings_getint(settings, "shell.port", &port); - server->socket = new_fluid_server_socket(port, - (fluid_server_func_t) fluid_server_handle_connection, + server->socket = new_fluid_server_socket(port, + (fluid_server_func_t) fluid_server_handle_connection, server); if (server->socket == NULL) { FLUID_FREE(server); @@ -1720,7 +1718,7 @@ static void fluid_server_close(fluid_server_t* server) while (list) { client = fluid_list_get(list); - fluid_client_quit(client); + fluid_client_quit(client); list = fluid_list_next(list); } @@ -1732,7 +1730,7 @@ static void fluid_server_close(fluid_server_t* server) } } -static void +static void fluid_server_handle_connection(fluid_server_t* server, fluid_socket_t client_socket, char* addr) { fluid_client_t* client; @@ -1753,7 +1751,7 @@ fluid_server_handle_connection(fluid_server_t* server, fluid_socket_t client_soc 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); + server->clients = fluid_list_append(server->clients, client); fluid_mutex_unlock(server->mutex); } @@ -1785,26 +1783,26 @@ struct _fluid_client_t { static void fluid_client_run(fluid_client_t* client) { fluid_shell_t shell; - fluid_shell_init(&shell, - client->settings, - client->handler, - fluid_socket_get_istream(client->socket), + 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); + delete_fluid_client(client); } -fluid_client_t* -new_fluid_client(fluid_server_t* server, fluid_settings_t* settings, +fluid_client_t* +new_fluid_client(fluid_server_t* server, fluid_settings_t* settings, fluid_cmd_handler_t* handler, fluid_socket_t sock) { fluid_client_t* client; client = FLUID_NEW(fluid_client_t); if (client == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } @@ -1817,10 +1815,10 @@ new_fluid_client(fluid_server_t* server, fluid_settings_t* settings, if (client->thread == NULL) { fluid_socket_close(sock); - FLUID_FREE(client); - return NULL; + FLUID_FREE(client); + return NULL; } - + return client; } @@ -1831,7 +1829,7 @@ void fluid_client_quit(fluid_client_t* client) client->socket = INVALID_SOCKET; } FLUID_LOG(FLUID_DBG, "fluid_client_quit: joining"); - fluid_thread_join(client->thread); + fluid_thread_join(client->thread); FLUID_LOG(FLUID_DBG, "fluid_client_quit: done"); } @@ -1845,7 +1843,7 @@ void delete_fluid_client(fluid_client_t* client) delete_fluid_thread(client->thread); client->thread = NULL; } - FLUID_FREE(client); + FLUID_FREE(client); } diff --git a/src/libs/fluidsynth/src/fluid_cmd.h b/src/libs/fluidsynth/src/fluid_cmd.h index 8734053458..9c05589edd 100644 --- a/src/libs/fluidsynth/src/fluid_cmd.h +++ b/src/libs/fluidsynth/src/fluid_cmd.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -80,8 +80,8 @@ int fluid_handle_settings(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_cmd_t* fluid_cmd_copy(fluid_cmd_t* cmd); void delete_fluid_cmd(fluid_cmd_t* cmd); -int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler, - int ac, char** av, +int fluid_cmd_handler_handle(fluid_cmd_handler_t* handler, + int ac, char** av, fluid_ostream_t out); @@ -90,9 +90,9 @@ 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_cmd_handler_t* handler, +fluid_client_t* new_fluid_client(fluid_server_t* server, + fluid_settings_t* settings, + fluid_cmd_handler_t* handler, fluid_socket_t sock); void delete_fluid_client(fluid_client_t* client); diff --git a/src/libs/fluidsynth/src/fluid_conv.c b/src/libs/fluidsynth/src/fluid_conv.c index 57dc47c566..cf83550d42 100644 --- a/src/libs/fluidsynth/src/fluid_conv.c +++ b/src/libs/fluidsynth/src/fluid_conv.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -35,7 +35,7 @@ fluid_real_t fluid_pan_tab[FLUID_PAN_SIZE]; * * Does all the initialization for this module. */ -void +void fluid_conversion_config(void) { int i; @@ -44,7 +44,7 @@ fluid_conversion_config(void) 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 @@ -75,7 +75,7 @@ fluid_conversion_config(void) fluid_convex_tab[0] = 0; fluid_convex_tab[127] = 1.0; x = log10(128.0 / 127.0); - + /* There seems to be an error in the specs. The equations are implemented according to the pictures on SF2.01 page 73. */ @@ -95,11 +95,11 @@ fluid_conversion_config(void) /* * fluid_ct2hz */ -fluid_real_t -fluid_ct2hz_real(fluid_real_t cents) +fluid_real_t +fluid_ct2hz_real(fluid_real_t cents) { if (cents < 0) - return (fluid_real_t) 1.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) { @@ -132,8 +132,8 @@ fluid_ct2hz_real(fluid_real_t cents) /* * fluid_ct2hz */ -fluid_real_t -fluid_ct2hz(fluid_real_t cents) +fluid_real_t +fluid_ct2hz(fluid_real_t cents) { /* Filter fc limit: SF2.01 page 48 # 8 */ if (cents >= 13500){ @@ -150,15 +150,15 @@ fluid_ct2hz(fluid_real_t cents) * in: a value between 0 and 960, 0 is no attenuation * out: a value between 1 and 0 */ -fluid_real_t +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. */ - + /* minimum attenuation: 0 dB */ if (cb < 0) { return 1.0; @@ -166,7 +166,7 @@ fluid_cb2amp(fluid_real_t cb) if (cb >= FLUID_CB_AMP_SIZE) { return 0.0; } - return fluid_cb2amp_tab[(int) cb]; + return fluid_cb2amp_tab[(int) cb]; } /* @@ -178,7 +178,7 @@ fluid_cb2amp(fluid_real_t cb) * Note: Volume attenuation is supposed to be centibels but EMU8k/10k don't * follow this. Thats the reason for separate fluid_cb2amp and fluid_atten2amp. */ -fluid_real_t +fluid_real_t fluid_atten2amp(fluid_real_t atten) { if (atten < 0) return 1.0; @@ -189,7 +189,7 @@ fluid_atten2amp(fluid_real_t atten) /* * fluid_tc2sec_delay */ -fluid_real_t +fluid_real_t fluid_tc2sec_delay(fluid_real_t tc) { /* SF2.01 section 8.1.2 items 21, 23, 25, 33 @@ -212,7 +212,7 @@ fluid_tc2sec_delay(fluid_real_t tc) /* * fluid_tc2sec_attack */ -fluid_real_t +fluid_real_t fluid_tc2sec_attack(fluid_real_t tc) { /* SF2.01 section 8.1.2 items 26, 34 @@ -228,7 +228,7 @@ fluid_tc2sec_attack(fluid_real_t tc) /* * fluid_tc2sec */ -fluid_real_t +fluid_real_t fluid_tc2sec(fluid_real_t tc) { /* No range checking here! */ @@ -238,7 +238,7 @@ fluid_tc2sec(fluid_real_t tc) /* * fluid_tc2sec_release */ -fluid_real_t +fluid_real_t fluid_tc2sec_release(fluid_real_t tc) { /* SF2.01 section 8.1.2 items 30, 38 @@ -256,7 +256,7 @@ fluid_tc2sec_release(fluid_real_t tc) * * Convert from absolute cents to Hertz */ -fluid_real_t +fluid_real_t fluid_act2hz(fluid_real_t c) { return (fluid_real_t) (8.176 * pow(2.0, (double) c / 1200.0)); @@ -267,7 +267,7 @@ fluid_act2hz(fluid_real_t c) * * Convert from Hertz to cents */ -fluid_real_t +fluid_real_t fluid_hz2ct(fluid_real_t f) { return (fluid_real_t) (6900 + 1200 * log(f / 440.0) / log(2.0)); @@ -276,7 +276,7 @@ fluid_hz2ct(fluid_real_t f) /* * fluid_pan */ -fluid_real_t +fluid_real_t fluid_pan(fluid_real_t c, int left) { if (left) { @@ -294,7 +294,7 @@ fluid_pan(fluid_real_t c, int left) /* * fluid_concave */ -fluid_real_t +fluid_real_t fluid_concave(fluid_real_t val) { if (val < 0) { @@ -308,7 +308,7 @@ fluid_concave(fluid_real_t val) /* * fluid_convex */ -fluid_real_t +fluid_real_t fluid_convex(fluid_real_t val) { if (val < 0) { diff --git a/src/libs/fluidsynth/src/fluid_conv.h b/src/libs/fluidsynth/src/fluid_conv.h index 7044046151..ec9b7bdaa7 100644 --- a/src/libs/fluidsynth/src/fluid_conv.h +++ b/src/libs/fluidsynth/src/fluid_conv.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA diff --git a/src/libs/fluidsynth/src/fluid_defsfont.c b/src/libs/fluidsynth/src/fluid_defsfont.c index 6a042a2405..ba0f7eb2d0 100644 --- a/src/libs/fluidsynth/src/fluid_defsfont.c +++ b/src/libs/fluidsynth/src/fluid_defsfont.c @@ -14,7 +14,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -44,7 +44,7 @@ fluid_sfloader_t* new_fluid_defsfloader() loader->data = NULL; loader->free = delete_fluid_defsfloader; loader->load = fluid_defsfloader_load; - + return loader; } @@ -89,7 +89,7 @@ fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* file } - + /*************************************************************** * * PUBLIC INTERFACE @@ -109,7 +109,7 @@ char* fluid_defsfont_sfont_get_name(fluid_sfont_t* sfont) return fluid_defsfont_get_name((fluid_defsfont_t*) sfont->data); } -fluid_preset_t* +fluid_preset_t* fluid_defsfont_sfont_get_preset(fluid_sfont_t* sfont, unsigned int bank, unsigned int prenum) { fluid_preset_t* preset; @@ -159,34 +159,36 @@ int fluid_defsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* pr int fluid_defpreset_preset_delete(fluid_preset_t* preset) { FLUID_FREE(preset); -/* printf("TODO: free modulators\n"); */ + + /* TODO: free modulators */ + return 0; } char* fluid_defpreset_preset_get_name(fluid_preset_t* preset) { - return fluid_defpreset_get_name((fluid_defpreset_t*) preset->data); + return fluid_defpreset_get_name((fluid_defpreset_t*) preset->data); } int fluid_defpreset_preset_get_banknum(fluid_preset_t* preset) { - return fluid_defpreset_get_banknum((fluid_defpreset_t*) preset->data); + return fluid_defpreset_get_banknum((fluid_defpreset_t*) preset->data); } int fluid_defpreset_preset_get_num(fluid_preset_t* preset) { - return fluid_defpreset_get_num((fluid_defpreset_t*) preset->data); + return fluid_defpreset_get_num((fluid_defpreset_t*) preset->data); } -int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, +int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel) { - return fluid_defpreset_noteon((fluid_defpreset_t*) preset->data, synth, chan, key, vel); + return fluid_defpreset_noteon((fluid_defpreset_t*) preset->data, synth, chan, key, vel); } - + /*************************************************************** * * SFONT @@ -255,7 +257,7 @@ int delete_fluid_defsfont(fluid_defsfont_t* sfont) delete_fluid_defpreset(preset); preset = sfont->preset; } - + FLUID_FREE(sfont); return FLUID_OK; } @@ -301,50 +303,52 @@ int fluid_defsfont_load(fluid_defsfont_t* sfont, const char* file) sfont->samplesize = sfdata->samplesize; /* load sample data in one block */ - if (fluid_defsfont_load_sampledata(sfont) != FLUID_OK) { - return FLUID_FAILED; - } + if (fluid_defsfont_load_sampledata(sfont) != FLUID_OK) + goto err_exit; /* Create all the sample headers */ p = sfdata->sample; while (p != NULL) { sfsample = (SFSample *) p->data; + sample = new_fluid_sample(); - if (sample == NULL) { - return FLUID_FAILED; - } - if (fluid_sample_import_sfont(sample, sfsample, sfont) != FLUID_OK) { - return FLUID_FAILED; - } + if (sample == NULL) goto err_exit; + + if (fluid_sample_import_sfont(sample, sfsample, sfont) != FLUID_OK) + goto err_exit; + fluid_defsfont_add_sample(sfont, sample); fluid_voice_optimize_sample(sample); p = fluid_list_next(p); } - /* Load all the presets */ + /* Load all the presets */ p = sfdata->preset; while (p != NULL) { sfpreset = (SFPreset *) p->data; preset = new_fluid_defpreset(sfont); - if (preset == NULL) { - return FLUID_FAILED; - } - if (fluid_defpreset_import_sfont(preset, sfpreset, sfont) != FLUID_OK) { - return FLUID_FAILED; - } + if (preset == NULL) goto err_exit; + + if (fluid_defpreset_import_sfont(preset, sfpreset, sfont) != FLUID_OK) + goto err_exit; + fluid_defsfont_add_preset(sfont, preset); p = fluid_list_next(p); } - sfont_free_data(sfdata); + sfont_close (sfdata); return FLUID_OK; + +err_exit: + sfont_close (sfdata); + return FLUID_FAILED; } /* fluid_defsfont_add_sample * * Add a sample to the SoundFont */ -int fluid_defsfont_add_sample(fluid_defsfont_t* sfont, fluid_sample_t* sample) +int fluid_defsfont_add_sample(fluid_defsfont_t* sfont, fluid_sample_t* sample) { sfont->sample = fluid_list_append(sfont->sample, sample); return FLUID_OK; @@ -354,7 +358,7 @@ int fluid_defsfont_add_sample(fluid_defsfont_t* sfont, fluid_sample_t* sample) * * Add a preset to the SoundFont */ -int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset) +int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset) { fluid_defpreset_t *cur, *prev; if (sfont->preset == NULL) { @@ -365,7 +369,7 @@ int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset cur = sfont->preset; prev = NULL; while (cur != NULL) { - if ((preset->bank < cur->bank) + if ((preset->bank < cur->bank) || ((preset->bank == cur->bank) && (preset->num < cur->num))) { if (prev == NULL) { preset->next = cur; @@ -388,36 +392,36 @@ int fluid_defsfont_add_preset(fluid_defsfont_t* sfont, fluid_defpreset_t* preset /* * fluid_defsfont_load_sampledata */ -int -fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont) +int +fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont) { fluid_file fd; unsigned short endian; fd = FLUID_FOPEN(sfont->filename, "rb"); if (fd == NULL) { - FLUID_LOG(FLUID_ERR, "Can't open soundfont file"); + FLUID_LOG(FLUID_ERR, "Can't open soundfont file"); return FLUID_FAILED; } if (FLUID_FSEEK(fd, sfont->samplepos, SEEK_SET) == -1) { perror("error"); - FLUID_LOG(FLUID_ERR, "Failed to seek position in data file"); + FLUID_LOG(FLUID_ERR, "Failed to seek position in data file"); return FLUID_FAILED; } sfont->sampledata = (short*) FLUID_MALLOC(sfont->samplesize); if (sfont->sampledata == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return FLUID_FAILED; } if (FLUID_FREAD(sfont->sampledata, 1, sfont->samplesize, fd) < sfont->samplesize) { - FLUID_LOG(FLUID_ERR, "Failed to read sample data"); + FLUID_LOG(FLUID_ERR, "Failed to read sample data"); return FLUID_FAILED; } FLUID_FCLOSE(fd); - + /* Lock the memory to disable paging. It's okay if this fails. It probably means that the user doesn't have to required permission. */ if (fluid_mlock(sfont->sampledata, sfont->samplesize) != 0) { - FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible."); + FLUID_LOG(FLUID_WARN, "Failed to pin the sample data to RAM; swapping is possible."); } @@ -444,7 +448,7 @@ fluid_defsfont_load_sampledata(fluid_defsfont_t* sfont) /* * fluid_defsfont_get_sample */ -fluid_sample_t* fluid_defsfont_get_sample(fluid_defsfont_t* sfont, char *s) +fluid_sample_t* fluid_defsfont_get_sample(fluid_defsfont_t* sfont, char *s) { fluid_list_t* list; fluid_sample_t* sample; @@ -464,7 +468,7 @@ fluid_sample_t* fluid_defsfont_get_sample(fluid_defsfont_t* sfont, char *s) /* * fluid_defsfont_get_preset */ -fluid_defpreset_t* fluid_defsfont_get_preset(fluid_defsfont_t* sfont, unsigned int bank, unsigned int num) +fluid_defpreset_t* fluid_defsfont_get_preset(fluid_defsfont_t* sfont, unsigned int bank, unsigned int num) { fluid_defpreset_t* preset = sfont->preset; while (preset != NULL) { @@ -506,12 +510,12 @@ int fluid_defsfont_iteration_next(fluid_defsfont_t* sfont, fluid_preset_t* prese /* * new_fluid_defpreset */ -fluid_defpreset_t* +fluid_defpreset_t* new_fluid_defpreset(fluid_defsfont_t* sfont) { fluid_defpreset_t* preset = FLUID_NEW(fluid_defpreset_t); if (preset == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } preset->next = NULL; @@ -527,7 +531,7 @@ new_fluid_defpreset(fluid_defsfont_t* sfont) /* * delete_fluid_defpreset */ -int +int delete_fluid_defpreset(fluid_defpreset_t* preset) { int err = FLUID_OK; @@ -550,19 +554,19 @@ delete_fluid_defpreset(fluid_defpreset_t* preset) return err; } -int +int fluid_defpreset_get_banknum(fluid_defpreset_t* preset) { return preset->bank; } -int +int fluid_defpreset_get_num(fluid_defpreset_t* preset) { return preset->num; } -char* +char* fluid_defpreset_get_name(fluid_defpreset_t* preset) { return preset->name; @@ -571,7 +575,7 @@ fluid_defpreset_get_name(fluid_defpreset_t* preset) /* * fluid_defpreset_next */ -fluid_defpreset_t* +fluid_defpreset_t* fluid_defpreset_next(fluid_defpreset_t* preset) { return preset->next; @@ -581,8 +585,8 @@ fluid_defpreset_next(fluid_defpreset_t* preset) /* * fluid_defpreset_noteon */ -int -fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel) +int +fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel) { fluid_preset_zone_t *preset_zone, *global_preset_zone; fluid_inst_t* inst; @@ -593,9 +597,9 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan 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(preset); - + /* run thru all the zones of this preset */ preset_zone = fluid_defpreset_get_zone(preset); while (preset_zone != NULL) { @@ -603,42 +607,42 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan /* check if the note falls into the key and velocity range of this preset */ if (fluid_preset_zone_inside_range(preset_zone, key, vel)) { - + inst = fluid_preset_zone_get_inst(preset_zone); global_inst_zone = fluid_inst_get_global_zone(inst); - + /* 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 (fluid_sample_in_rom(sample) || (sample == NULL)) { inst_zone = fluid_inst_zone_next(inst_zone); continue; } - + /* check if the note falls into the key and velocity range of this instrument */ if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) { - + /* this is a good zone. allocate a new synthesis process and initialize it */ voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel); if (voice == NULL) { - return FLUID_FAILED; + return FLUID_FAILED; } - - + + z = inst_zone; - + /* Instrument level, generators */ - + for (i = 0; i < GEN_LAST; i++) { - /* SF 2.01 section 9.4 'bullet' 4: + /* SF 2.01 section 9.4 'bullet' 4: * * A generator in a local instrument zone supersedes a * global instrument zone generator. Both cases supersede @@ -648,7 +652,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan 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); + fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val); } else { /* The generator has not been defined in this instrument. @@ -657,7 +661,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan } } /* for all generators */ - + /* global instrument zone, modulators: Put them all into a * list. */ @@ -670,7 +674,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan mod = mod->next; } } - + /* local instrument zone, modulators. * Replace modulators with the same definition in the list: * SF 2.01 page 69, 'bullet' 8 @@ -689,7 +693,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan mod_list[i] = NULL; } } - + /* Finally add the new modulator to to the list. */ mod_list[mod_list_count++] = mod; mod = mod->next; @@ -714,12 +718,12 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan /* 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) + 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) @@ -736,7 +740,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan 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); + 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. @@ -744,8 +748,8 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan } } /* if available at preset level */ } /* for all generators */ - - + + /* Global preset zone, modulators: put them all into a * list. */ mod_list_count = 0; @@ -768,12 +772,12 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan mod_list[i] = NULL; } } - + /* Finally add the new modulator to the list. */ mod_list[mod_list_count++] = mod; mod = mod->next; } - + /* Add preset modulators (global / local) to the voice. */ for (i = 0; i < mod_list_count; i++){ mod = mod_list[i]; @@ -784,7 +788,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan * page */ fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD); } - } + } /* add the synthesis process to the synthesis loop. */ fluid_synth_start_voice(synth, voice); @@ -809,7 +813,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan /* * fluid_defpreset_set_global_zone */ -int +int fluid_defpreset_set_global_zone(fluid_defpreset_t* preset, fluid_preset_zone_t* zone) { preset->global_zone = zone; @@ -819,9 +823,9 @@ fluid_defpreset_set_global_zone(fluid_defpreset_t* preset, fluid_preset_zone_t* /* * fluid_defpreset_import_sfont */ -int -fluid_defpreset_import_sfont(fluid_defpreset_t* preset, - SFPreset* sfpreset, +int +fluid_defpreset_import_sfont(fluid_defpreset_t* preset, + SFPreset* sfpreset, fluid_defsfont_t* sfont) { fluid_list_t *p; @@ -862,7 +866,7 @@ fluid_defpreset_import_sfont(fluid_defpreset_t* preset, /* * fluid_defpreset_add_zone */ -int +int fluid_defpreset_add_zone(fluid_defpreset_t* preset, fluid_preset_zone_t* zone) { if (preset->zone == NULL) { @@ -878,7 +882,7 @@ fluid_defpreset_add_zone(fluid_defpreset_t* preset, fluid_preset_zone_t* zone) /* * fluid_defpreset_get_zone */ -fluid_preset_zone_t* +fluid_preset_zone_t* fluid_defpreset_get_zone(fluid_defpreset_t* preset) { return preset->zone; @@ -887,16 +891,16 @@ fluid_defpreset_get_zone(fluid_defpreset_t* preset) /* * fluid_defpreset_get_global_zone */ -fluid_preset_zone_t* +fluid_preset_zone_t* fluid_defpreset_get_global_zone(fluid_defpreset_t* preset) { - return preset->global_zone; + return preset->global_zone; } /* * fluid_preset_zone_next */ -fluid_preset_zone_t* +fluid_preset_zone_t* fluid_preset_zone_next(fluid_preset_zone_t* preset) { return preset->next; @@ -905,21 +909,21 @@ fluid_preset_zone_next(fluid_preset_zone_t* preset) /* * new_fluid_preset_zone */ -fluid_preset_zone_t* +fluid_preset_zone_t* new_fluid_preset_zone(char *name) { int size; fluid_preset_zone_t* zone = NULL; zone = FLUID_NEW(fluid_preset_zone_t); if (zone == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } zone->next = NULL; size = 1 + FLUID_STRLEN(name); zone->name = FLUID_MALLOC(size); if (zone->name == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_FREE(zone); return NULL; } @@ -946,9 +950,21 @@ new_fluid_preset_zone(char *name) /* * delete_fluid_preset_zone */ -int +int delete_fluid_preset_zone(fluid_preset_zone_t* zone) { + fluid_mod_t *mod, *tmp; + + mod = zone->mod; + while (mod) /* delete the modulators */ + { + tmp = mod; + mod = mod->next; + fluid_mod_delete (tmp); + } + + if (zone->name) FLUID_FREE (zone->name); + if (zone->inst) delete_fluid_inst (zone->inst); FLUID_FREE(zone); return FLUID_OK; } @@ -956,7 +972,7 @@ delete_fluid_preset_zone(fluid_preset_zone_t* zone) /* * fluid_preset_zone_import_sfont */ -int +int fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* sfont) { fluid_list_t *r; @@ -965,11 +981,11 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ for (count = 0, r = sfzone->gen; r != NULL; count++) { sfgen = (SFGen *) r->data; switch (sfgen->id) { - case GEN_KEYRANGE: + case GEN_KEYRANGE: zone->keylo = (int) sfgen->amount.range.lo; zone->keyhi = (int) sfgen->amount.range.hi; break; - case GEN_VELRANGE: + case GEN_VELRANGE: zone->vello = (int) sfgen->amount.range.lo; zone->velhi = (int) sfgen->amount.range.hi; break; @@ -988,9 +1004,9 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ return FLUID_FAILED; } if (fluid_inst_import_sfont(zone->inst, (SFInst *) sfzone->instsamp->data, sfont) != FLUID_OK) { - return FLUID_FAILED; + return FLUID_FAILED; } - } + } /* Import the modulators (only SF2.1 and higher) */ for (count = 0, r = sfzone->mod; r != NULL; count++) { @@ -1006,11 +1022,11 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ /* *** 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->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; @@ -1024,14 +1040,14 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ } 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; } - + /* modulator source types: SF2.01 section 8.2.1 page 52 */ type=(mod_src->src) >> 10; type &= 63; /* type is a 6-bit value */ @@ -1044,16 +1060,16 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ } else if (type == 3){ mod_dest->flags1 |= FLUID_MOD_SWITCH; } else { - /* This shouldn't happen - unknown type! + /* This shouldn't happen - unknown type! * Deactivate the modulator by setting the amount to 0. */ mod_dest->amount=0; } - + /* *** Dest *** */ - mod_dest->dest = mod_src->dest; /* index of controlled generator */ - + 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, p.50 */ + 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 7: CC flag SF 2.01 section 8.2.1 page 50*/ @@ -1069,14 +1085,14 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ } 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 */ @@ -1089,19 +1105,19 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ } else if (type == 3){ mod_dest->flags2 |= FLUID_MOD_SWITCH; } else { - /* This shouldn't happen - unknown type! + /* 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). + /* 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 @@ -1118,7 +1134,7 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ last_mod->next = mod_dest; } - + r = fluid_list_next(r); } /* foreach modulator */ @@ -1128,7 +1144,7 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_ /* * fluid_preset_zone_get_inst */ -fluid_inst_t* +fluid_inst_t* fluid_preset_zone_get_inst(fluid_preset_zone_t* zone) { return zone->inst; @@ -1137,7 +1153,7 @@ fluid_preset_zone_get_inst(fluid_preset_zone_t* zone) /* * fluid_preset_zone_inside_range */ -int +int fluid_preset_zone_inside_range(fluid_preset_zone_t* zone, int key, int vel) { return ((zone->keylo <= key) && @@ -1154,12 +1170,12 @@ fluid_preset_zone_inside_range(fluid_preset_zone_t* zone, int key, int vel) /* * 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"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } inst->name[0] = 0; @@ -1171,7 +1187,7 @@ new_fluid_inst() /* * delete_fluid_inst */ -int +int delete_fluid_inst(fluid_inst_t* inst) { fluid_inst_zone_t* zone; @@ -1188,7 +1204,7 @@ delete_fluid_inst(fluid_inst_t* inst) if (delete_fluid_inst_zone(zone) != FLUID_OK) { err = FLUID_FAILED; } - zone = inst->zone; + zone = inst->zone; } FLUID_FREE(inst); return err; @@ -1197,7 +1213,7 @@ delete_fluid_inst(fluid_inst_t* inst) /* * fluid_inst_set_global_zone */ -int +int fluid_inst_set_global_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone) { inst->global_zone = zone; @@ -1207,7 +1223,7 @@ fluid_inst_set_global_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone) /* * fluid_inst_import_sfont */ -int +int fluid_inst_import_sfont(fluid_inst_t* inst, SFInst *sfinst, fluid_defsfont_t* sfont) { fluid_list_t *p; @@ -1218,7 +1234,7 @@ fluid_inst_import_sfont(fluid_inst_t* inst, SFInst *sfinst, fluid_defsfont_t* sf p = sfinst->zone; if ((sfinst->name != NULL) && (FLUID_STRLEN(sfinst->name) > 0)) { - FLUID_STRCPY(inst->name, sfinst->name); + FLUID_STRCPY(inst->name, sfinst->name); } else { FLUID_STRCPY(inst->name, ""); } @@ -1254,7 +1270,7 @@ fluid_inst_import_sfont(fluid_inst_t* inst, SFInst *sfinst, fluid_defsfont_t* sf /* * fluid_inst_add_zone */ -int +int fluid_inst_add_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone) { if (inst->zone == NULL) { @@ -1270,7 +1286,7 @@ fluid_inst_add_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone) /* * fluid_inst_get_zone */ -fluid_inst_zone_t* +fluid_inst_zone_t* fluid_inst_get_zone(fluid_inst_t* inst) { return inst->zone; @@ -1279,10 +1295,10 @@ fluid_inst_get_zone(fluid_inst_t* inst) /* * fluid_inst_get_global_zone */ -fluid_inst_zone_t* +fluid_inst_zone_t* fluid_inst_get_global_zone(fluid_inst_t* inst) { - return inst->global_zone; + return inst->global_zone; } /*************************************************************** @@ -1293,21 +1309,21 @@ fluid_inst_get_global_zone(fluid_inst_t* inst) /* * new_fluid_inst_zone */ -fluid_inst_zone_t* +fluid_inst_zone_t* new_fluid_inst_zone(char* name) { int size; fluid_inst_zone_t* zone = NULL; zone = FLUID_NEW(fluid_inst_zone_t); if (zone == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } zone->next = NULL; size = 1 + FLUID_STRLEN(name); zone->name = FLUID_MALLOC(size); if (zone->name == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); FLUID_FREE(zone); return NULL; } @@ -1318,7 +1334,7 @@ new_fluid_inst_zone(char* name) zone->vello = 0; zone->velhi = 128; - /* Flag the generators as unused. + /* 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 */ @@ -1328,9 +1344,20 @@ new_fluid_inst_zone(char* name) /* * delete_fluid_inst_zone */ -int +int delete_fluid_inst_zone(fluid_inst_zone_t* zone) { + fluid_mod_t *mod, *tmp; + + mod = zone->mod; + while (mod) /* delete the modulators */ + { + tmp = mod; + mod = mod->next; + fluid_mod_delete (tmp); + } + + if (zone->name) FLUID_FREE (zone->name); FLUID_FREE(zone); return FLUID_OK; } @@ -1338,7 +1365,7 @@ delete_fluid_inst_zone(fluid_inst_zone_t* zone) /* * fluid_inst_zone_next */ -fluid_inst_zone_t* +fluid_inst_zone_t* fluid_inst_zone_next(fluid_inst_zone_t* zone) { return zone->next; @@ -1347,7 +1374,7 @@ fluid_inst_zone_next(fluid_inst_zone_t* zone) /* * fluid_inst_zone_import_sfont */ -int +int fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* sfont) { fluid_list_t *r; @@ -1357,11 +1384,11 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs for (count = 0, r = sfzone->gen; r != NULL; count++) { sfgen = (SFGen *) r->data; switch (sfgen->id) { - case GEN_KEYRANGE: + case GEN_KEYRANGE: zone->keylo = (int) sfgen->amount.range.lo; zone->keyhi = (int) sfgen->amount.range.hi; break; - case GEN_VELRANGE: + case GEN_VELRANGE: zone->vello = (int) sfgen->amount.range.lo; zone->velhi = (int) sfgen->amount.range.hi; break; @@ -1400,14 +1427,14 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs } mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ - + /* *** 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->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; @@ -1421,14 +1448,14 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs } 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; } - + /* modulator source types: SF2.01 section 8.2.1 page 52 */ type = (mod_src->src) >> 10; type &= 63; /* type is a 6-bit value */ @@ -1441,18 +1468,18 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs } else if (type == 3){ mod_dest->flags1 |= FLUID_MOD_SWITCH; } else { - /* This shouldn't happen - unknown type! + /* This shouldn't happen - unknown type! * Deactivate the modulator by setting the amount to 0. */ mod_dest->amount = 0; } - + /* *** Dest *** */ - mod_dest->dest=mod_src->dest; /* index of controlled generator */ - + 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->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; @@ -1466,14 +1493,14 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs } 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 */ @@ -1486,21 +1513,21 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs } else if (type == 3){ mod_dest->flags2 |= FLUID_MOD_SWITCH; } else { - /* This shouldn't happen - unknown type! + /* 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). + /* 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: + + /* 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; @@ -1512,7 +1539,7 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs } last_mod->next=mod_dest; } - + r = fluid_list_next(r); } /* foreach modulator */ return FLUID_OK; @@ -1521,7 +1548,7 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs /* * fluid_inst_zone_get_sample */ -fluid_sample_t* +fluid_sample_t* fluid_inst_zone_get_sample(fluid_inst_zone_t* zone) { return zone->sample; @@ -1530,7 +1557,7 @@ fluid_inst_zone_get_sample(fluid_inst_zone_t* zone) /* * fluid_inst_zone_inside_range */ -int +int fluid_inst_zone_inside_range(fluid_inst_zone_t* zone, int key, int vel) { return ((zone->keylo <= key) && @@ -1547,14 +1574,14 @@ fluid_inst_zone_inside_range(fluid_inst_zone_t* zone, int key, int vel) /* * new_fluid_sample */ -fluid_sample_t* +fluid_sample_t* new_fluid_sample() { fluid_sample_t* sample = NULL; sample = FLUID_NEW(fluid_sample_t); if (sample == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } @@ -1567,7 +1594,7 @@ new_fluid_sample() /* * delete_fluid_sample */ -int +int delete_fluid_sample(fluid_sample_t* sample) { FLUID_FREE(sample); @@ -1577,7 +1604,7 @@ delete_fluid_sample(fluid_sample_t* sample) /* * fluid_sample_in_rom */ -int +int fluid_sample_in_rom(fluid_sample_t* sample) { return (sample->sampletype & FLUID_SAMPLETYPE_ROM); @@ -1586,7 +1613,7 @@ fluid_sample_in_rom(fluid_sample_t* sample) /* * fluid_sample_import_sfont */ -int +int fluid_sample_import_sfont(fluid_sample_t* sample, SFSample* sfsample, fluid_defsfont_t* sfont) { FLUID_STRCPY(sample->name, sfsample->name); @@ -1770,8 +1797,12 @@ sfload_file (const char * fname) return (NULL); } - if (!(sf = safe_malloc (sizeof (SFData)))) - err = TRUE; + if (!(sf = FLUID_NEW (SFData))) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + err = TRUE; + } + if (!err) { memset (sf, 0, sizeof (SFData)); /* zero sfdata */ @@ -1907,16 +1938,16 @@ process_info (int size, SFData * sf, FILE * fd) 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 (FAIL); } if (sf->version.major > 2) { - FLUID_LOG (FLUID_WARN, + FLUID_LOG (FLUID_WARN, _("Sound font version is %d.%d which is newer than" - " what this version of FLUID Synth was designed for (v2.0x)"), + " what this version of FLUID Synth was designed for (v2.0x)"), sf->version.major, sf->version.minor); return (FAIL); @@ -1942,8 +1973,11 @@ process_info (int size, SFData * sf, FILE * fd) " of %d bytes"), &chunk.id, chunk.size)); /* alloc for chunk id and da chunk */ - if (!(item = safe_malloc (chunk.size + 1))) - return (FAIL); + if (!(item = FLUID_MALLOC (chunk.size + 1))) + { + FLUID_LOG(FLUID_ERR, "Out of memory"); + return (FAIL); + } /* attach to INFO list, sfont_close will cleanup if FAIL occurs */ sf->info = fluid_list_append (sf->info, item); @@ -2979,21 +3013,15 @@ unsigned short badpgen[] = { Gen_StartAddrOfs, Gen_EndAddrOfs, Gen_StartLoopAddr Gen_OverrideRootKey, 0 }; +/* close SoundFont file and delete a SoundFont structure */ void sfont_close (SFData * sf) { + fluid_list_t *p, *p2; + if (sf->sffd) fclose (sf->sffd); - sfont_free_data (sf); -} - -/* delete a sound font structure */ -void -sfont_free_data (SFData * sf) -{ - fluid_list_t *p, *p2; - if (sf->fname) free (sf->fname); @@ -3035,8 +3063,19 @@ sfont_free_data (SFData * sf) FLUID_FREE (p->data); p = fluid_list_next (p); } + delete_fluid_list (sf->inst); + sf->inst = NULL; + + p = sf->sample; + while (p) + { + FLUID_FREE (p->data); + p = fluid_list_next (p); + } delete_fluid_list (sf->sample); sf->sample = NULL; + + FLUID_FREE (sf); } /* free all elements of a zone (Preset or Instrument) */ @@ -3173,13 +3212,3 @@ safe_fseek (FILE * fd, long ofs, int whence) } return (OK); } - -void * -safe_malloc (size_t size) -{ - void *ptr; - - if (!(ptr = malloc (size))) - FLUID_LOG (FLUID_ERR, _("Attempted to allocate %d bytes"), (int) size); - return (ptr); -} diff --git a/src/libs/fluidsynth/src/fluid_defsfont.h b/src/libs/fluidsynth/src/fluid_defsfont.h index 844347fc88..1fe463f23c 100644 --- a/src/libs/fluidsynth/src/fluid_defsfont.h +++ b/src/libs/fluidsynth/src/fluid_defsfont.h @@ -13,7 +13,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -218,7 +218,6 @@ extern unsigned short badpgen[]; /* list of bad preset generators */ void sfont_init_chunks (void); void sfont_close (SFData * sf); -void sfont_free_data (SFData * sf); void sfont_free_zone (SFZone * zone); int sfont_preset_compare_func (void* a, void* b); @@ -230,8 +229,8 @@ int gen_validp (int gen); /*-----------------------------------sffile.h----------------------------*/ -/* - File structures and routines (used to be in sffile.h) +/* + File structures and routines (used to be in sffile.h) */ #define CHNKIDSTR(id) &idlist[(id - 1) * 4] @@ -427,7 +426,6 @@ enum #define ErrnoEnd ErrWrite int gerr (int ev, char * fmt, ...); -void *safe_malloc (size_t size); int safe_fread (void *buf, int count, FILE * fd); int safe_fwrite (void *buf, int count, FILE * fd); int safe_fseek (FILE * fd, long ofs, int whence); @@ -443,7 +441,7 @@ int safe_fseek (FILE * fd, long ofs, int whence); /*************************************************************** * - * FORWARD DECLARATIONS + * FORWARD DECLARATIONS */ typedef struct _fluid_defsfont_t fluid_defsfont_t; typedef struct _fluid_defpreset_t fluid_defpreset_t; diff --git a/src/libs/fluidsynth/src/fluid_dsp_core.c b/src/libs/fluidsynth/src/fluid_dsp_core.c deleted file mode 100644 index 4e09047eda..0000000000 --- a/src/libs/fluidsynth/src/fluid_dsp_core.c +++ /dev/null @@ -1,26 +0,0 @@ -/* FluidSynth - A Software Synthesizer - * - * Copyright (C) 2003 Peter Hanappe and others. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - -#ifdef ENABLE_SSE -#include "fluid_dsp_sse.c" -#else -/* #include "fluid_dsp_simple.c" */ -#include "fluid_dsp_float.c" -#endif diff --git a/src/libs/fluidsynth/src/fluid_dsp_float.c b/src/libs/fluidsynth/src/fluid_dsp_float.c index e251603f7f..cf64e2bfff 100644 --- a/src/libs/fluidsynth/src/fluid_dsp_float.c +++ b/src/libs/fluidsynth/src/fluid_dsp_float.c @@ -11,271 +11,677 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ +#include "fluidsynth_priv.h" +#include "fluid_phase.h" -/* Purpose: - * Low-level voice processing: +/* Purpose: * - * - interpolates (obtains values between the samples of the original waveform data) - * - filters (applies a lowpass filter with variable cutoff frequency and quality factor) - * - mixes the processed sample to left and right output using the pan setting - * - sends the processed sample to chorus and reverb + * Interpolates audio data (obtains values between the samples of the original + * waveform data). * - * - * This file does -not- generate an object file. - * Instead, it is #included in several places in fluid_voice.c. - * The motivation for this is - * - Calling it as a subroutine may be time consuming, especially with optimization off - * - The previous implementation as a macro was clumsy to handle - * - * - * Fluid_voice.c sets a couple of variables before #including this: + * Variables loaded from the voice structure (assigned in fluid_voice_write()): * - dsp_data: Pointer to the original waveform data - * - dsp_left_buf: The generated signal goes here, left channel - * - dsp_right_buf: right channel - * - dsp_reverb_buf: Send to reverb unit - * - dsp_chorus_buf: Send to chorus unit - * - dsp_start: Start processing at this output buffer index - * - dsp_end: End processing just before this output buffer index - * - dsp_a1: Coefficient for the filter - * - dsp_a2: same - * - dsp_b0: same - * - dsp_b1: same - * - dsp_b2: same - * - dsp_filter_flag: Set, the filter is needed (many sound fonts don't use - * the filter at all. If it is left at its default setting - * of roughly 20 kHz, there is no need to apply filterling.) - * - dsp_interp_method: Which interpolation method to use. - * - voice holds the voice structure - * - * Some variables are set and modified: * - dsp_phase: The position in the original waveform data. * This has an integer and a fractional part (between samples). * - dsp_phase_incr: For each output sample, the position in the original * waveform advances by dsp_phase_incr. This also has an integer * part and a fractional part. - * If a sample is played at root pitch (no pitch change), + * If a sample is played at root pitch (no pitch change), * dsp_phase_incr is integer=1 and fractional=0. * - dsp_amp: The current amplitude envelope value. * - dsp_amp_incr: The changing rate of the amplitude envelope. * * A couple of variables are used internally, their results are discarded: * - dsp_i: Index through the output buffer - * - dsp_phase_fractional: The fractional part of dsp_phase - * - dsp_coeff: A table of four coefficients, depending on the fractional phase. - * Used to interpolate between samples. - * - dsp_process_buffer: Holds the processed signal between stages - * - dsp_centernode: delay line for the IIR filter - * - dsp_hist1: same - * - dsp_hist2: same - * + * - dsp_buf: Output buffer of floating point values (FLUID_BUFSIZE in length) */ -/* Purpose: - * zap_almost_zero will return a number, as long as its - * absolute value is over a certain threshold. Otherwise 0. See - * fluid_rev.c for documentation (denormal numbers) - */ +#include "fluidsynth_priv.h" +#include "fluid_synth.h" +#include "fluid_voice.h" -# if defined(WITH_FLOAT) -# define zap_almost_zero(_sample) \ - ((((*(unsigned int*)&(_sample))&0x7f800000) < 0x08000000)? 0.0f : (_sample)) -# else -/* 1e-20 was chosen as an arbitrary (small) threshold. */ -#define zap_almost_zero(_sample) ((abs(_sample) < 1e-20)? 0.0f : (_sample)) -#endif /* Interpolation (find a value between two samples of the original waveform) */ -if ((fluid_phase_fract(dsp_phase) == 0) - && (fluid_phase_fract(dsp_phase_incr) == 0) - && (fluid_phase_index(dsp_phase_incr) == 1)) { +/* Linear interpolation table (2 coefficients centered on 1st) */ +static fluid_real_t interp_coeff_linear[FLUID_INTERP_MAX][2]; - /* Check for a special case: The current phase falls directly on an - * original sample. Also, the stepsize per output sample is exactly - * one sample, no fractional part. In other words: The sample is - * played back at normal phase and root pitch. => No interpolation - * needed. - */ - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - /* Mix to the buffer and advance the phase by one sample */ - dsp_buf[dsp_i] = dsp_amp * dsp_data[fluid_phase_index_plusplus(dsp_phase)]; - dsp_amp += dsp_amp_incr; - } +/* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */ +static fluid_real_t interp_coeff[FLUID_INTERP_MAX][4]; -} else { - - /* wave table interpolation: Choose the interpolation method */ - - switch(dsp_interp_method){ - case FLUID_INTERP_NONE: - /* No interpolation. Just take the sample, which is closest to - * the playback pointer. Questionable quality, but very - * efficient. */ - - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_phase_index = fluid_phase_index(dsp_phase); - dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index]; - - /* increment phase and amplitude */ - fluid_phase_incr(dsp_phase, dsp_phase_incr); - dsp_amp += dsp_amp_incr; - }; - break; - - case FLUID_INTERP_LINEAR: - /* Straight line interpolation. */ - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_coeff = &interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)]; - dsp_phase_index = fluid_phase_index(dsp_phase); - dsp_buf[dsp_i] = (dsp_amp * - (dsp_coeff->a0 * dsp_data[dsp_phase_index] - + dsp_coeff->a1 * dsp_data[dsp_phase_index+1])); - - /* increment phase and amplitude */ - fluid_phase_incr(dsp_phase, dsp_phase_incr); - dsp_amp += dsp_amp_incr; - }; - break; - - case FLUID_INTERP_4THORDER: - default: - /* Default interpolation loop using floats */ - - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; - - dsp_phase_index = fluid_phase_index(dsp_phase); - dsp_buf[dsp_i] = (dsp_amp * - (dsp_coeff->a0 * dsp_data[dsp_phase_index] - + dsp_coeff->a1 * dsp_data[dsp_phase_index+1] - + dsp_coeff->a2 * dsp_data[dsp_phase_index+2] - + dsp_coeff->a3 * dsp_data[dsp_phase_index+3])); - - /* increment phase and amplitude */ - fluid_phase_incr(dsp_phase, dsp_phase_incr); - dsp_amp += dsp_amp_incr; - } - break; +/* 7th order interpolation (7 coefficients centered on 3rd) */ +static fluid_real_t sinc_table7[FLUID_INTERP_MAX][7]; - case FLUID_INTERP_7THORDER: - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - int fract = fluid_phase_fract_to_tablerow(dsp_phase); - dsp_phase_index = fluid_phase_index(dsp_phase); - dsp_buf[dsp_i] = (dsp_amp * - (sinc_table7[0][fract] * (fluid_real_t) dsp_data[dsp_phase_index] - + sinc_table7[1][fract] * (fluid_real_t) dsp_data[dsp_phase_index+1] - + sinc_table7[2][fract] * (fluid_real_t) dsp_data[dsp_phase_index+2] - + sinc_table7[3][fract] * (fluid_real_t) dsp_data[dsp_phase_index+3] - + sinc_table7[4][fract] * (fluid_real_t) dsp_data[dsp_phase_index+4] - + sinc_table7[5][fract] * (fluid_real_t) dsp_data[dsp_phase_index+5] - + sinc_table7[6][fract] * (fluid_real_t) dsp_data[dsp_phase_index+6])); - - /* increment phase and amplitude */ - fluid_phase_incr(dsp_phase, dsp_phase_incr); - dsp_amp += dsp_amp_incr; - } - break; - - } /* switch interpolation method */ -} /* If interpolation is needed */ - -/* filter (implement the voice filter according to Soundfont standard) */ -if (dsp_use_filter_flag) { - - /* Check for denormal number (too close to zero) once in a - * while. This is not a big concern here - why would someone play a - * sample with an empty tail? */ - dsp_hist1 = zap_almost_zero(dsp_hist1); - - /* 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) { - /* The increment is added to each filter coefficient - filter_coeff_incr_count times. */ - - for (dsp_i = dsp_start; dsp_i < dsp_end; 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){ - dsp_a1 += dsp_a1_incr; - dsp_a2 += dsp_a2_incr; - dsp_b02 += dsp_b02_incr; - dsp_b1 += dsp_b1_incr; - } - } /* for dsp_i */ - - } else { - - /* The filter parameters are constant. This is duplicated to save - * time. */ - - for (dsp_i = dsp_start; dsp_i < dsp_end; 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 filter is fixed */ -} /* if filter is enabled */ +#define SINC_INTERP_ORDER 7 /* 7th order constant */ +/* Initializes interpolation tables */ +void fluid_dsp_float_config (void) +{ + int i, i2; + double x, v; + double i_shifted; -/* pan (Copy the signal to the left and right output buffer) The voice - * panning generator has a range of -500 .. 500. If it is centered, - * it's close to 0. voice->amp_left and voice->amp_right are then the - * same, and we can save one multiplication per voice and sample. - */ -if ((-0.5 < voice->pan) && (voice->pan < 0.5)) { - - /* The voice is centered. Use voice->amp_left twice. */ - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - float v = voice->amp_left * dsp_buf[dsp_i]; - dsp_left_buf[dsp_i] += v; - dsp_right_buf[dsp_i] += v; - } + /* 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/). */ -} else { + for (i = 0; i < FLUID_INTERP_MAX; i++) + { + x = (double) i / (double) FLUID_INTERP_MAX; - /* The voice is not centered. For stereo samples, one of the - * amplitudes will be zero. */ - if (voice->amp_left != 0.0){ - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_left_buf[dsp_i] += voice->amp_left * dsp_buf[dsp_i]; - } - } - if (voice->amp_right != 0.0){ - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_right_buf[dsp_i] += voice->amp_right * dsp_buf[dsp_i]; - } - } + 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++) + { + /* 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]); + } +#endif + + fluid_check_fpe("interpolation table calculation"); } -/* reverb send. Buffer may be NULL. */ -if ((dsp_reverb_buf != NULL) && (voice->amp_reverb != 0.0)) { - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_reverb_buf[dsp_i] += voice->amp_reverb * dsp_buf[dsp_i]; - } + +/* No interpolation. Just take the sample, which is closest to + * the playback pointer. Questionable quality, but very + * efficient. */ +int +fluid_dsp_float_interpolate_none (fluid_voice_t *voice) +{ + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr, end_phase; + short int *dsp_data = voice->sample->data; + fluid_real_t *dsp_buf = voice->dsp_buf; + 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; + int looping; + + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); + + /* voice is currently looping? */ + looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE + || (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE + && voice->volenv_section < FLUID_VOICE_ENVRELEASE); + + end_index = looping ? voice->loopend - 1 : voice->end; + + while (1) + { + dsp_phase_index = fluid_phase_index_round (dsp_phase); /* round to nearest point */ + + /* interpolate sequence of sample points */ + for ( ; dsp_i < FLUID_BUFSIZE && dsp_phase_index <= end_index; dsp_i++) + { + dsp_buf[dsp_i] = dsp_amp * dsp_data[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; + } + + voice->phase = dsp_phase; + voice->amp = dsp_amp; + + return (dsp_i); } -/* chorus send. Buffer may be NULL. */ -if ((dsp_chorus_buf != NULL) && (voice->amp_chorus != 0)) { - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_chorus_buf[dsp_i] += voice->amp_chorus * dsp_buf[dsp_i]; - } +/* Straight line interpolation. + * Returns number of samples processed (usually FLUID_BUFSIZE but could be + * smaller if end of sample occurs). + */ +int +fluid_dsp_float_interpolate_linear (fluid_voice_t *voice) +{ + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr, end_phase; + short int *dsp_data = voice->sample->data; + fluid_real_t *dsp_buf = voice->dsp_buf; + 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; + short int point; + fluid_real_t *coeffs; + int looping; + + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); + + /* voice is currently looping? */ + looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE + || (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE + && voice->volenv_section < FLUID_VOICE_ENVRELEASE); + + /* 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 = dsp_data[voice->loopstart]; /* loop start */ + else point = dsp_data[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++) + { + coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow (dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index] + + coeffs[1] * dsp_data[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] * dsp_data[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 */ + } + + voice->phase = dsp_phase; + voice->amp = dsp_amp; + + return (dsp_i); +} + +/* 4th order (cubic) interpolation. + * Returns number of samples processed (usually FLUID_BUFSIZE but could be + * smaller if end of sample occurs). + */ +int +fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice) +{ + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr, end_phase; + short int *dsp_data = voice->sample->data; + fluid_real_t *dsp_buf = voice->dsp_buf; + 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; + short int start_point, end_point1, end_point2; + fluid_real_t *coeffs; + int looping; + + /* Convert playback "speed" floating point value to phase index/fract */ + fluid_phase_set_float (dsp_phase_incr, voice->phase_incr); + + /* voice is currently looping? */ + looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE + || (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE + && voice->volenv_section < FLUID_VOICE_ENVRELEASE); + + /* 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 = dsp_data[voice->loopend - 1]; /* last point in loop (wrap around) */ + } + else + { + start_index = voice->start; + start_point = dsp_data[voice->start]; /* just duplicate the point */ + } + + /* get points off the end (loop start if looping, duplicate point if end) */ + if (looping) + { + end_point1 = dsp_data[voice->loopstart]; + end_point2 = dsp_data[voice->loopstart + 1]; + } + else + { + end_point1 = dsp_data[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++) + { + coeffs = interp_coeff[fluid_phase_fract_to_tablerow (dsp_phase)]; + dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * start_point + + coeffs[1] * dsp_data[dsp_phase_index] + + coeffs[2] * dsp_data[dsp_phase_index+1] + + coeffs[3] * dsp_data[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] * dsp_data[dsp_phase_index-1] + + coeffs[1] * dsp_data[dsp_phase_index] + + coeffs[2] * dsp_data[dsp_phase_index+1] + + coeffs[3] * dsp_data[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] * dsp_data[dsp_phase_index-1] + + coeffs[1] * dsp_data[dsp_phase_index] + + coeffs[2] * dsp_data[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] * dsp_data[dsp_phase_index-1] + + coeffs[1] * dsp_data[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 = dsp_data[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); +} + +/* 7th order interpolation. + * Returns number of samples processed (usually FLUID_BUFSIZE but could be + * smaller if end of sample occurs). + */ +int +fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice) +{ + fluid_phase_t dsp_phase = voice->phase; + fluid_phase_t dsp_phase_incr, end_phase; + short int *dsp_data = voice->sample->data; + fluid_real_t *dsp_buf = voice->dsp_buf; + 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; + short int start_points[3]; + short int end_points[3]; + fluid_real_t *coeffs; + int looping; + + /* 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); + + /* voice is currently looping? */ + looping = _SAMPLEMODE (voice) == FLUID_LOOP_DURING_RELEASE + || (_SAMPLEMODE (voice) == FLUID_LOOP_UNTIL_RELEASE + && voice->volenv_section < FLUID_VOICE_ENVRELEASE); + + /* 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] = dsp_data[voice->loopend - 1]; + start_points[1] = dsp_data[voice->loopend - 2]; + start_points[2] = dsp_data[voice->loopend - 3]; + } + else + { + start_index = voice->start; + start_points[0] = dsp_data[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] = dsp_data[voice->loopstart]; + end_points[1] = dsp_data[voice->loopstart + 1]; + end_points[2] = dsp_data[voice->loopstart + 2]; + } + else + { + end_points[0] = dsp_data[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++) + { + coeffs = sinc_table7[fluid_phase_fract_to_tablerow (dsp_phase)]; + + dsp_buf[dsp_i] = dsp_amp + * (coeffs[0] * (fluid_real_t)start_points[2] + + coeffs[1] * (fluid_real_t)start_points[1] + + coeffs[2] * (fluid_real_t)start_points[0] + + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index] + + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1] + + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2] + + coeffs[6] * (fluid_real_t)dsp_data[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] * (fluid_real_t)start_points[1] + + coeffs[1] * (fluid_real_t)start_points[0] + + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1] + + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index] + + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1] + + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2] + + coeffs[6] * (fluid_real_t)dsp_data[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] * (fluid_real_t)start_points[0] + + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2] + + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1] + + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index] + + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1] + + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2] + + coeffs[6] * (fluid_real_t)dsp_data[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_real_t)dsp_data[dsp_phase_index-3] + + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2] + + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1] + + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index] + + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1] + + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2] + + coeffs[6] * (fluid_real_t)dsp_data[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_real_t)dsp_data[dsp_phase_index-3] + + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2] + + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1] + + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index] + + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1] + + coeffs[5] * (fluid_real_t)dsp_data[dsp_phase_index+2] + + coeffs[6] * (fluid_real_t)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_real_t)dsp_data[dsp_phase_index-3] + + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2] + + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1] + + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index] + + coeffs[4] * (fluid_real_t)dsp_data[dsp_phase_index+1] + + coeffs[5] * (fluid_real_t)end_points[0] + + coeffs[6] * (fluid_real_t)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_real_t)dsp_data[dsp_phase_index-3] + + coeffs[1] * (fluid_real_t)dsp_data[dsp_phase_index-2] + + coeffs[2] * (fluid_real_t)dsp_data[dsp_phase_index-1] + + coeffs[3] * (fluid_real_t)dsp_data[dsp_phase_index] + + coeffs[4] * (fluid_real_t)end_points[0] + + coeffs[5] * (fluid_real_t)end_points[1] + + coeffs[6] * (fluid_real_t)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] = dsp_data[voice->loopend - 1]; + start_points[1] = dsp_data[voice->loopend - 2]; + start_points[2] = dsp_data[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); } diff --git a/src/libs/fluidsynth/src/fluid_dsp_simple.c b/src/libs/fluidsynth/src/fluid_dsp_simple.c index 6aa3cdf432..663f5a67c0 100644 --- a/src/libs/fluidsynth/src/fluid_dsp_simple.c +++ b/src/libs/fluidsynth/src/fluid_dsp_simple.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -19,7 +19,7 @@ */ -/* Purpose: +/* Purpose: * Low-level voice processing: * * - interpolates (obtains values between the samples of the original waveform data) @@ -60,7 +60,7 @@ * - dsp_phase_incr: For each output sample, the position in the original * waveform advances by dsp_phase_incr. This also has an integer * part and a fractional part. - * If a sample is played at root pitch (no pitch change), + * If a sample is played at root pitch (no pitch change), * dsp_phase_incr is integer=1 and fractional=0. * - dsp_amp: The current amplitude envelope value. * - dsp_amp_incr: The changing rate of the amplitude envelope. @@ -74,37 +74,37 @@ * - dsp_centernode: delay line for the IIR filter * - dsp_hist1: same * - dsp_hist2: same - * + * */ /* Nonoptimized DSP loop */ #warning "This code is meant for experiments only."; -/* wave table interpolation */ -for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { +/* wave table interpolation */ +for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; - dsp_phase_index = fluid_phase_index(dsp_phase); - dsp_sample = (dsp_amp * - (dsp_coeff->a0 * dsp_data[dsp_phase_index] - + dsp_coeff->a1 * dsp_data[dsp_phase_index+1] - + dsp_coeff->a2 * dsp_data[dsp_phase_index+2] + dsp_coeff = &interp_coeff[fluid_phase_fract_to_tablerow(dsp_phase)]; + dsp_phase_index = fluid_phase_index(dsp_phase); + dsp_sample = (dsp_amp * + (dsp_coeff->a0 * dsp_data[dsp_phase_index] + + dsp_coeff->a1 * dsp_data[dsp_phase_index+1] + + dsp_coeff->a2 * dsp_data[dsp_phase_index+2] + dsp_coeff->a3 * dsp_data[dsp_phase_index+3])); - - /* increment phase and amplitude */ - fluid_phase_incr(dsp_phase, dsp_phase_incr); + + /* increment phase and amplitude */ + fluid_phase_incr(dsp_phase, dsp_phase_incr); dsp_amp += dsp_amp_incr; - /* filter */ - /* The filter is implemented in Direct-II form. */ + /* filter */ + /* The filter is implemented in Direct-II form. */ dsp_centernode = dsp_sample - dsp_a1 * dsp_hist1 - dsp_a2 * dsp_hist2; dsp_sample = dsp_b0 * dsp_centernode + dsp_b1 * dsp_hist1 + dsp_b2 * dsp_hist2; - dsp_hist2 = dsp_hist1; - dsp_hist1 = dsp_centernode; + dsp_hist2 = dsp_hist1; + dsp_hist1 = dsp_centernode; /* pan */ - dsp_left_buf[dsp_i] += voice->amp_left * dsp_sample; + dsp_left_buf[dsp_i] += voice->amp_left * dsp_sample; dsp_right_buf[dsp_i] += voice->amp_right * dsp_sample; /* reverb */ diff --git a/src/libs/fluidsynth/src/fluid_dsp_sse.c b/src/libs/fluidsynth/src/fluid_dsp_sse.c deleted file mode 100644 index f2b8fdeb77..0000000000 --- a/src/libs/fluidsynth/src/fluid_dsp_sse.c +++ /dev/null @@ -1,387 +0,0 @@ -/* FluidSynth - A Software Synthesizer - * - * Copyright (C) 2003 Peter Hanappe and others. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - - -/* Purpose: - * Low-level voice processing: - * - * - interpolates (obtains values between the samples of the original waveform data) - * - filters (applies a lowpass filter with variable cutoff frequency and quality factor) - * - mixes the processed sample to left and right output using the pan setting - * - sends the processed sample to chorus and reverb - * - * - * This file does -not- generate an object file. - * Instead, it is #included in several places in fluid_voice.c. - * The motivation for this is - * - Calling it as a subroutine may be time consuming, especially with optimization off - * - The previous implementation as a macro was clumsy to handle - * - * - * Fluid_voice.c sets a couple of variables before #including this: - * - dsp_data: Pointer to the original waveform data - * - dsp_left_buf: The generated signal goes here, left channel - * - dsp_right_buf: right channel - * - dsp_reverb_buf: Send to reverb unit - * - dsp_chorus_buf: Send to chorus unit - * - dsp_start: Start processing at this output buffer index - * - dsp_end: End processing just before this output buffer index - * - dsp_a1: Coefficient for the filter - * - dsp_a2: same - * - dsp_b0: same - * - dsp_b1: same - * - dsp_b2: same - * - dsp_filter_flag: Set, the filter is needed (many sound fonts don't use - * the filter at all. If it is left at its default setting - * of roughly 20 kHz, there is no need to apply filterling.) - * - dsp_interp_method: Which interpolation method to use. - * - voice holds the voice structure - * - * Some variables are set and modified: - * - dsp_phase: The position in the original waveform data. - * This has an integer and a fractional part (between samples). - * - dsp_phase_incr: For each output sample, the position in the original - * waveform advances by dsp_phase_incr. This also has an integer - * part and a fractional part. - * If a sample is played at root pitch (no pitch change), - * dsp_phase_incr is integer=1 and fractional=0. - * - dsp_amp: The current amplitude envelope value. - * - dsp_amp_incr: The changing rate of the amplitude envelope. - * - * A couple of variables are used internally, their results are discarded: - * - dsp_i: Index through the output buffer - * - dsp_phase_fractional: The fractional part of dsp_phase - * - dsp_coeff: A table of four coefficients, depending on the fractional phase. - * Used to interpolate between samples. - * - dsp_process_buffer: Holds the processed signal between stages - * - dsp_centernode: delay line for the IIR filter - * - dsp_hist1: same - * - dsp_hist2: same - * - */ - -/* Purpose: - * zap_almost_zero will return a number, as long as its - * absolute value is over a certain threshold. Otherwise 0. See - * fluid_rev.c for documentation (denormal numbers) - */ - -# if defined(WITH_FLOAT) -# define zap_almost_zero(_sample) \ - ((((*(unsigned int*)&(_sample))&0x7f800000) < 0x08000000)? 0.0f : (_sample)) -# else -/* 1e-20 was chosen as an arbitrary (small) threshold. */ -#define zap_almost_zero(_sample) ((abs(_sample) < 1e-20)? 0.0f : (_sample)) -#endif - -/* Interpolation (find a value between two samples of the original waveform) */ - -if ((fluid_phase_fract(dsp_phase) == 0) - && (fluid_phase_fract(dsp_phase_incr) == 0) - && (fluid_phase_index(dsp_phase_incr) == 1)) { - - /* Check for a special case: The current phase falls directly on an - * original sample. Also, the stepsize per output sample is exactly - * one sample, no fractional part. In other words: The sample is - * played back at normal phase and root pitch. => No interpolation - * needed. - */ - for (dsp_i = dsp_start; dsp_i < dsp_end; dsp_i++) { - /* Mix to the buffer and advance the phase by one sample */ - dsp_buf[dsp_i] = dsp_amp * dsp_data[fluid_phase_index_plusplus(dsp_phase)]; - dsp_amp += dsp_amp_incr; - } - -} else { - - /* wave table interpolation: Choose the interpolation method */ - /* !!! SSE interpolation is less efficient that normal interpolation. */ - - - /* Initialize amplitude increase */ - sse_b->sf[0] = sse_b->sf[1] = sse_b->sf[2] = sse_b->sf[3] = 4.*dsp_amp_incr; - - /* Initialize amplitude => xmm7 - * The amplitude is kept in xmm7 throughout the whole process - */ - - sse_a->sf[0]=sse_a->sf[1]=sse_a->sf[2]=sse_a->sf[3]=dsp_amp; - sse_a->sf[1] += dsp_amp_incr; - sse_a->sf[2] += 2.* dsp_amp_incr; - sse_a->sf[3] += 3.* dsp_amp_incr; - movaps_m2r(*sse_a,xmm7); - - /* Where to store the result */ - sse_dest=(sse_t*)&dsp_buf[0]; - for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i += 4) { - /* Note / fixme: The coefficients are first copied to - * sse_c, then to the xmm register. Can't get it through - * the compiler differently... */ - - /* Load the four source samples for the 1st output sample */ - dsp_phase_index = fluid_phase_index(dsp_phase); - sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index]; - sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1]; - sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2]; - sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3]; - movaps_m2r(*sse_a,xmm0); - *sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)]; - mulps_m2r(*sse_c,xmm0); - - fluid_phase_incr(dsp_phase, dsp_phase_incr); - - /* Load the four source samples for the 2nd output sample */ - dsp_phase_index = fluid_phase_index(dsp_phase); - sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index]; - sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1]; - sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2]; - sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3]; - movaps_m2r(*sse_a,xmm1); - *sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)]; - mulps_m2r(*sse_c,xmm1); - - fluid_phase_incr(dsp_phase, dsp_phase_incr); - - /* Load the four source samples for the 3rd output sample */ - dsp_phase_index = fluid_phase_index(dsp_phase); - sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index]; - sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1]; - sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2]; - sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3]; - movaps_m2r(*sse_a,xmm2); - *sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)]; - mulps_m2r(*sse_c,xmm2); - - fluid_phase_incr(dsp_phase, dsp_phase_incr); - - /* Load the four source samples for the 4th output sample */ - dsp_phase_index = fluid_phase_index(dsp_phase); - sse_a->sf[0]=(fluid_real_t)dsp_data[dsp_phase_index]; - sse_a->sf[1]=(fluid_real_t)dsp_data[dsp_phase_index+1]; - sse_a->sf[2]=(fluid_real_t)dsp_data[dsp_phase_index+2]; - sse_a->sf[3]=(fluid_real_t)dsp_data[dsp_phase_index+3]; - movaps_m2r(*sse_a,xmm3); - *sse_c=interp_coeff_sse[fluid_phase_fract_to_tablerow(dsp_phase)]; - mulps_m2r(*sse_c,xmm3); - - fluid_phase_incr(dsp_phase, dsp_phase_incr); - -#if 0 - /*Testcase for horizontal add */ - sse_a->sf[0]=0.1;sse_a->sf[1]=0.01;sse_a->sf[2]=0.001;sse_a->sf[3]=0.0001; - movaps_m2r(*sse_a,xmm0); - sse_a->sf[0]=0.2;sse_a->sf[1]=0.02;sse_a->sf[2]=0.002;sse_a->sf[3]=0.0002; - movaps_m2r(*sse_a,xmm1); - sse_a->sf[0]=0.3;sse_a->sf[1]=0.03;sse_a->sf[2]=0.003;sse_a->sf[3]=0.0003; - movaps_m2r(*sse_a,xmm2); - sse_a->sf[0]=0.4;sse_a->sf[1]=0.04;sse_a->sf[2]=0.004;sse_a->sf[3]=0.0004; - movaps_m2r(*sse_a,xmm3); -#endif /* #if 0 */ - -#if 1 - /* Horizontal add - * xmm4[0]:=xmm0[0]+xmm1[0]+xmm2[0]+xmm3[0] - * xmm4[1]:=xmm0[1]+xmm1[1]+xmm2[1]+xmm3[1] - * etc. - * The only register, which is unused, is xmm7. - */ - movaps_r2r(xmm0,xmm5); - movaps_r2r(xmm2,xmm6); - movlhps_r2r(xmm1,xmm5); - movlhps_r2r(xmm3,xmm6); - movhlps_r2r(xmm0,xmm1); - movhlps_r2r(xmm2,xmm3); - addps_r2r(xmm1,xmm5); - addps_r2r(xmm3,xmm6); - movaps_r2r(xmm5,xmm4); - shufps_r2r(xmm6,xmm5,0xDD); - shufps_r2r(xmm6,xmm4,0x88); - addps_r2r(xmm5,xmm4); - -/* movaps_r2m(xmm4,*sse_a); */ -/* printf("xmm4 (Result): %f %f %f %f\n", */ -/* sse_a->sf[0], sse_a->sf[1], */ -/* sse_a->sf[2], sse_a->sf[3]); */ -#else - /* Add using normal FPU */ - movaps_r2m(xmm0,*sse_a); - sse_c->sf[0]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3]; - movaps_r2m(xmm1,*sse_a); - sse_c->sf[1]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3]; - movaps_r2m(xmm2,*sse_a); - sse_c->sf[2]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3]; - movaps_r2m(xmm3,*sse_a); - sse_c->sf[3]=sse_a->sf[0]+sse_a->sf[1]+sse_a->sf[2]+sse_a->sf[3]; - movaps_m2r(*sse_c,xmm4); -#endif /* #if 1 */ - /* end horizontal add. Result in xmm6. */ - - - /* Multiply xmm4 with amplitude */ - mulps_r2r(xmm7,xmm4); - - /* Store the result */ - movaps_r2m(xmm4,*sse_dest); // ++ - - /* Advance the position in the output buffer */ - sse_dest++; - - /* Change the amplitude */ - addps_m2r(*sse_b,xmm7); - - } /* for dsp_i in steps of four */ - - movaps_r2m(xmm7,*sse_a); - - /* Retrieve the last amplitude value. */ - dsp_amp=sse_a->sf[3]; - - -} /* If interpolation is needed */ - -/* filter (implement the voice filter according to Soundfont standard) */ -if (dsp_use_filter_flag) { - - /* Check for denormal number (too close to zero) once in a - * while. This is not a big concern here - why would someone play a - * sample with an empty tail? */ - dsp_hist1 = zap_almost_zero(dsp_hist1); - - /* 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) { - /* The increment is added to each filter coefficient - filter_coeff_incr_count times. */ - - for (dsp_i = dsp_start; dsp_i < dsp_end; 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){ - dsp_a1 += dsp_a1_incr; - dsp_a2 += dsp_a2_incr; - dsp_b02 += dsp_b02_incr; - dsp_b1 += dsp_b1_incr; - } - } /* for dsp_i */ - - } else { - - /* The filter parameters are constant. This is duplicated to save - * time. */ - - for (dsp_i = dsp_start; dsp_i < dsp_end; 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 filter is fixed */ -} /* if filter is enabled */ - - -/* The following optimization will process a whole buffer using the - * SSE extension of the Pentium processor. - */ - -if (voice->amp_left != 0.0) { - sse_a->sf[0]=voice->amp_left; - sse_a->sf[1]=voice->amp_left; - sse_a->sf[2]=voice->amp_left; - sse_a->sf[3]=voice->amp_left; - movaps_m2r(*sse_a,xmm0); - - sse_src=(sse_t*)dsp_buf; - sse_dest=(sse_t*)&dsp_left_buf[0]; - for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) { - movaps_m2r(*sse_src,xmm4); /* Load original sample */ - mulps_r2r(xmm0,xmm4); /* Gain */ - sse_src++; - addps_m2r(*sse_dest,xmm4); /* Mix with buf */ - movaps_r2m(xmm4,*sse_dest); /* Store in buf */ - sse_dest++; - } -} - -if (voice->amp_right != 0.0){ - sse_a->sf[0]=voice->amp_right; - sse_a->sf[1]=voice->amp_right; - sse_a->sf[2]=voice->amp_right; - sse_a->sf[3]=voice->amp_right; - movaps_m2r(*sse_a,xmm0); - - sse_src=(sse_t*)dsp_buf; - sse_dest=(sse_t*)&dsp_right_buf[0]; - for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) { - movaps_m2r(*sse_src,xmm4); /* Load original sample */ - sse_src++; - mulps_r2r(xmm0,xmm4); /* Gain */ - addps_m2r(*sse_dest,xmm4); /* Mix with buf */ - movaps_r2m(xmm4,*sse_dest); /* Store in buf */ - sse_dest++; - } -} - -/* reverb send. Buffer may be NULL. */ -if (dsp_reverb_buf && voice->amp_reverb != 0.0){ - sse_a->sf[0]=voice->amp_reverb; - sse_a->sf[1]=voice->amp_reverb; - sse_a->sf[2]=voice->amp_reverb; - sse_a->sf[3]=voice->amp_reverb; - movaps_m2r(*sse_a,xmm0); - - sse_src=(sse_t*)dsp_buf; - sse_dest=(sse_t*)&dsp_reverb_buf[0]; - for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) { - movaps_m2r(*sse_src,xmm4); /* Load original sample */ - sse_src++; - mulps_r2r(xmm0,xmm4); /* Gain */ - addps_m2r(*sse_dest,xmm4); /* Mix with buf */ - movaps_r2m(xmm4,*sse_dest); /* Store in buf */ - sse_dest++; - } -} - -/* chorus send. Buffer may be NULL. */ -if (dsp_chorus_buf && voice->amp_chorus != 0){ - sse_a->sf[0]=voice->amp_chorus; - sse_a->sf[1]=voice->amp_chorus; - sse_a->sf[2]=voice->amp_chorus; - sse_a->sf[3]=voice->amp_chorus; - movaps_m2r(*sse_a,xmm0); - - sse_src=(sse_t*)dsp_buf; - sse_dest=(sse_t*)&dsp_chorus_buf[0]; - for (dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i+=4) { - movaps_m2r(*sse_src,xmm4); /* Load original sample */ - sse_src++; - mulps_r2r(xmm0,xmm4); /* Gain */ - addps_m2r(*sse_dest,xmm4); /* Mix with buf */ - movaps_r2m(xmm4,*sse_dest); /* Store in buf */ - sse_dest++; - } -} diff --git a/src/libs/fluidsynth/src/fluid_event.c b/src/libs/fluidsynth/src/fluid_event.c index c8d8e84e38..aaa7465e1a 100644 --- a/src/libs/fluidsynth/src/fluid_event.c +++ b/src/libs/fluidsynth/src/fluid_event.c @@ -11,14 +11,14 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ - + /* 2002 : API design by Peter Hanappe and Antoine Schmitt August 2002 : Implementation by Antoine Schmitt as@gratin.org @@ -27,7 +27,7 @@ Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free. */ - + #include "fluid_event_priv.h" #include "fluidsynth_priv.h" @@ -38,11 +38,15 @@ /* Event alloc/free */ -fluid_event_t* +/** + * Create a new sequencer event structure. + * @return New sequencer event structure or NULL if out of memory + */ +fluid_event_t* new_fluid_event() { fluid_event_t* evt; - + evt = FLUID_NEW(fluid_event_t); if (evt == NULL) { fluid_log(FLUID_PANIC, "event: Out of memory\n"); @@ -50,46 +54,69 @@ new_fluid_event() } FLUID_MEMSET(evt, 0, sizeof(fluid_event_t)); - + // by default, no type - evt->dest = -1; - evt->src = -1; - evt->type = -1; - - return(evt); + evt->dest = -1; + evt->src = -1; + evt->type = -1; + + return(evt); } -void +/** + * Delete a sequencer event structure. + * @param evt Sequencer event structure created by new_fluid_event(). + */ +void delete_fluid_event(fluid_event_t* evt) { if (evt == NULL) { return; } - + FLUID_FREE(evt); } -/* Initializing events */ +/** + * Set the time field of a sequencer event. + * @internal + * @param evt Sequencer event structure + * @param time Time value to assign + */ void fluid_event_set_time(fluid_event_t* evt, unsigned int time) { evt->time = time; } +/** + * Set source of a sequencer event (DOCME). + * @param evt Sequencer event structure + * @param src DOCME + */ void fluid_event_set_source(fluid_event_t* evt, short src) { evt->src = src; } +/** + * Set destination of a sequencer event (DOCME). + * @param evt Sequencer event structure + * @param dest DOCME + */ void fluid_event_set_dest(fluid_event_t* evt, short dest) { evt->dest = dest; } -/* Timer events */ +/** + * Set a sequencer event to be a timer event. + * @param evt Sequencer event structure + * @param data DOCME + */ void fluid_event_timer(fluid_event_t* evt, void* data) { @@ -97,8 +124,13 @@ fluid_event_timer(fluid_event_t* evt, void* data) evt->data = data; } - -/* Note events */ +/** + * Set a sequencer event to be a note on event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param key MIDI note number (0-127) + * @param vel MIDI velocity value (0-127) + */ void fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel) { @@ -108,6 +140,12 @@ fluid_event_noteon(fluid_event_t* evt, int channel, short key, short vel) evt->vel = vel; } +/** + * Set a sequencer event to be a note off event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param key MIDI note number (0-127) + */ void fluid_event_noteoff(fluid_event_t* evt, int channel, short key) { @@ -116,6 +154,14 @@ fluid_event_noteoff(fluid_event_t* evt, int channel, short key) evt->key = key; } +/** + * Set a sequencer event to be a note duration event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param key MIDI note number (0-127) + * @param vel MIDI velocity value (0-127) + * @param duration Duration of note (DOCME units?) + */ void fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned int duration) { @@ -126,6 +172,11 @@ fluid_event_note(fluid_event_t* evt, int channel, short key, short vel, unsigned evt->duration = duration; } +/** + * Set a sequencer event to be an all sounds off event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + */ void fluid_event_all_sounds_off(fluid_event_t* evt, int channel) { @@ -133,6 +184,11 @@ fluid_event_all_sounds_off(fluid_event_t* evt, int channel) evt->channel = channel; } +/** + * Set a sequencer event to be a all notes off event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + */ void fluid_event_all_notes_off(fluid_event_t* evt, int channel) { @@ -140,6 +196,12 @@ fluid_event_all_notes_off(fluid_event_t* evt, int channel) evt->channel = channel; } +/** + * Set a sequencer event to be a bank select event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param bank_num MIDI bank number (0-16383) + */ void fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num) { @@ -148,6 +210,12 @@ fluid_event_bank_select(fluid_event_t* evt, int channel, short bank_num) evt->control = bank_num; } +/** + * Set a sequencer event to be a program change event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param val MIDI program number (0-127) + */ void fluid_event_program_change(fluid_event_t* evt, int channel, short val) { @@ -156,6 +224,14 @@ fluid_event_program_change(fluid_event_t* evt, int channel, short val) evt->value = val; } +/** + * Set a sequencer event to be a program select event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param sfont_id SoundFont ID number + * @param bank_num MIDI bank number (0-16383) + * @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) @@ -167,6 +243,12 @@ fluid_event_program_select(fluid_event_t* evt, int channel, evt->control = bank_num; } +/** + * Set a sequencer event to be an any control change event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * DOCME + */ void fluid_event_any_control_change(fluid_event_t* evt, int channel) { @@ -174,6 +256,12 @@ fluid_event_any_control_change(fluid_event_t* evt, int channel) evt->channel = channel; } +/** + * Set a sequencer event to be a pitch bend event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param pitch MIDI pitch bend value (0-16383, 8192 = no bend) + */ void fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch) { @@ -184,6 +272,12 @@ fluid_event_pitch_bend(fluid_event_t* evt, int channel, int pitch) evt->pitch = pitch; } +/** + * Set a sequencer event to be a pitch wheel sensitivity event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param value MIDI pitch wheel sensitivity value (DOCME units?) + */ void fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value) { @@ -192,6 +286,12 @@ fluid_event_pitch_wheelsens(fluid_event_t* evt, int channel, short value) evt->value = value; } +/** + * Set a sequencer event to be a modulation event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param val MIDI modulation value (0-127) + */ void fluid_event_modulation(fluid_event_t* evt, int channel, short val) { @@ -202,6 +302,12 @@ fluid_event_modulation(fluid_event_t* evt, int channel, short val) evt->value = val; } +/** + * Set a sequencer event to be a MIDI sustain event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param val MIDI sustain value (0-127) + */ void fluid_event_sustain(fluid_event_t* evt, int channel, short val) { @@ -212,6 +318,13 @@ fluid_event_sustain(fluid_event_t* evt, int channel, short val) evt->value = val; } +/** + * Set a sequencer event to be a MIDI control change event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param control MIDI control number (0-127) + * @param val MIDI control value (0-16383 DOCME is that true?) + */ void fluid_event_control_change(fluid_event_t* evt, int channel, short control, short val) { @@ -221,6 +334,12 @@ fluid_event_control_change(fluid_event_t* evt, int channel, short control, short evt->value = val; } +/** + * Set a sequencer event to be a stereo pan event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @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) { @@ -231,6 +350,12 @@ fluid_event_pan(fluid_event_t* evt, int channel, short val) evt->value = val; } +/** + * Set a sequencer event to be a volume event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param val Volume value (0-127) + */ void fluid_event_volume(fluid_event_t* evt, int channel, short val) { @@ -241,6 +366,12 @@ fluid_event_volume(fluid_event_t* evt, int channel, short val) evt->value = val; } +/** + * Set a sequencer event to be a reverb send event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param val Reverb amount (0-127) + */ void fluid_event_reverb_send(fluid_event_t* evt, int channel, short val) { @@ -251,6 +382,12 @@ fluid_event_reverb_send(fluid_event_t* evt, int channel, short val) evt->value = val; } +/** + * Set a sequencer event to be a chorus send event. + * @param evt Sequencer event structure + * @param channel MIDI channel number + * @param val Chorus amount (0-127) + */ void fluid_event_chorus_send(fluid_event_t* evt, int channel, short val) { @@ -261,76 +398,179 @@ fluid_event_chorus_send(fluid_event_t* evt, int channel, short val) evt->value = val; } -/* Accessing event data */ + +/* + * Accessing event data + */ + +/** + * Get the event type (#fluid_seq_event_type) field from a sequencer event structure. + * @param evt Sequencer event structure + * @return Event type (#fluid_seq_event_type). + */ int fluid_event_get_type(fluid_event_t* evt) { return evt->type; } +/** + * Get the time field from a sequencer event structure. + * @param evt Sequencer event structure + * @return Time value (DOCME units?) + */ unsigned int fluid_event_get_time(fluid_event_t* evt) { return evt->time; } +/** + * Get the source field from a sequencer event structure. + * @param evt Sequencer event structure + * @return DOCME + */ short fluid_event_get_source(fluid_event_t* evt) { return evt->src; } +/** + * Get the dest field from a sequencer event structure. + * @param evt Sequencer event structure + * @return DOCME + */ short fluid_event_get_dest(fluid_event_t* evt) { return evt->dest; } +/** + * Get the MIDI channel field from a sequencer event structure. + * @param evt Sequencer event structure + * @return MIDI channel number (DOCME 0-15 or more?) + */ int fluid_event_get_channel(fluid_event_t* evt) { return evt->channel; } +/** + * Get the MIDI note field from a sequencer event structure. + * @param evt Sequencer event structure + * @return MIDI note number (0-127) + */ short fluid_event_get_key(fluid_event_t* evt) { return evt->key; } +/** + * Get the MIDI velocity field from a sequencer event structure. + * @param evt Sequencer event structure + * @return MIDI velocity value (0-127) + */ short fluid_event_get_velocity(fluid_event_t* evt) { return evt->vel; } +/** + * Get the MIDI control number field from a sequencer event structure. + * @param evt Sequencer event structure + * @return MIDI control number (0-127) + */ short fluid_event_get_control(fluid_event_t* evt) { return evt->control; } +/** + * Get the value field from a sequencer event structure. + * @param evt Sequencer event structure + * @return Value field of event. + * + * The Value field is used by the following event types: + * #FLUID_SEQ_PROGRAMCHANGE, #FLUID_SEQ_PROGRAMSELECT (preset_num), + * #FLUID_SEQ_PITCHWHHELSENS, #FLUID_SEQ_MODULATION, #FLUID_SEQ_SUSTAIN, + * #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME, + * #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND. + */ short fluid_event_get_value(fluid_event_t* evt) { return evt->value; } +/** + * Get the data field from a sequencer event structure. + * @param evt Sequencer event structure + * @return Data field of event. + * + * Used by the #FLUID_SEQ_TIMER event type. + */ void* fluid_event_get_data(fluid_event_t* evt) { return evt->data; } +/** + * Get the duration field from a sequencer event structure. + * @param evt Sequencer event structure + * @return Note duration value (DOCME units?) + * + * Used by the #FLUID_SEQ_NOTE event type. + */ unsigned int fluid_event_get_duration(fluid_event_t* evt) { return evt->duration; } + +/** + * Get the MIDI bank field from a sequencer event structure. + * @param evt Sequencer event structure + * @return MIDI bank number (0-16383) + * + * Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT + * event types. + */ short fluid_event_get_bank(fluid_event_t* evt) { return evt->control; } + +/** + * Get the pitch field from a sequencer event structure. + * @param evt Sequencer event structure + * @return MIDI pitch bend pitch value (0-16383, 8192 = no bend) + * + * Used by the #FLUID_SEQ_PITCHBEND event type. + */ int fluid_event_get_pitch(fluid_event_t* evt) { return evt->pitch; } -short + +/** + * Get the MIDI program field from a sequencer event structure. + * @param evt Sequencer event structure + * @return MIDI program number (0-127) + * + * Used by the #FLUID_SEQ_PROGRAMCHANGE and #FLUID_SEQ_PROGRAMSELECT + * event types. + */ +short fluid_event_get_program(fluid_event_t* evt) { return evt->value; } -unsigned int + +/** + * Get the SoundFont ID field from a sequencer event structure. + * @param evt Sequencer event structure + * @return SoundFont identifier value. + * + * Used by the #FLUID_SEQ_PROGRAMSELECT event type. + */ +unsigned int fluid_event_get_sfont_id(fluid_event_t* evt) { return evt->duration; @@ -378,21 +618,21 @@ _fluid_evt_heap_init(int 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); - + /* 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); @@ -422,7 +662,7 @@ _fluid_evt_heap_free(fluid_evt_heap_t* heap) fluid_mutex_destroy(heap->mutex); FLUID_FREE(heap); - + #else FLUID_FREE(heap); #endif @@ -461,12 +701,12 @@ _fluid_seq_heap_get_free(fluid_evt_heap_t* heap) #else fluid_evt_entry* evt; if (heap->head == NULL) return NULL; - + /* take from head of the heap */ /* critical - should threadlock ? */ evt = heap->head; heap->head = heap->head->next; - + return evt; #endif } diff --git a/src/libs/fluidsynth/src/fluid_event_priv.h b/src/libs/fluidsynth/src/fluid_event_priv.h index 3fc1a61a7c..619381c4e1 100644 --- a/src/libs/fluidsynth/src/fluid_event_priv.h +++ b/src/libs/fluidsynth/src/fluid_event_priv.h @@ -11,14 +11,14 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ - + #ifndef _FLUID_EVENT_PRIV_H #define _FLUID_EVENT_PRIV_H diff --git a/src/libs/fluidsynth/src/fluid_gen.c b/src/libs/fluidsynth/src/fluid_gen.c index 24c4cc3232..4f9bb02346 100644 --- a/src/libs/fluidsynth/src/fluid_gen.c +++ b/src/libs/fluidsynth/src/fluid_gen.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -89,11 +89,12 @@ fluid_gen_info_t fluid_gen_info[] = { }; -/* fluid_gen_set_default_values - * - * Set an array of generators to their initial value +/** + * Set an array of generators to their default values. + * @param gen Array of generators (should be #GEN_LAST in size). + * @return Always returns 0 */ -int +int fluid_gen_set_default_values(fluid_gen_t* gen) { int i; @@ -111,9 +112,9 @@ fluid_gen_set_default_values(fluid_gen_t* gen) /* fluid_gen_init * - * Set an array of generators to their initial value + * Set an array of generators to their initial value */ -int +int fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel) { int i; @@ -135,8 +136,8 @@ fluid_gen_init(fluid_gen_t* gen, fluid_channel_t* channel) } fluid_real_t fluid_gen_scale(int gen, float value) -{ - return (fluid_gen_info[gen].min +{ + return (fluid_gen_info[gen].min + value * (fluid_gen_info[gen].max - fluid_gen_info[gen].min)); } diff --git a/src/libs/fluidsynth/src/fluid_gen.h b/src/libs/fluidsynth/src/fluid_gen.h index de446c857c..c35193a52c 100644 --- a/src/libs/fluidsynth/src/fluid_gen.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA diff --git a/src/libs/fluidsynth/src/fluid_hash.c b/src/libs/fluidsynth/src/fluid_hash.c index 3062b7b67f..9094908afe 100644 --- a/src/libs/fluidsynth/src/fluid_hash.c +++ b/src/libs/fluidsynth/src/fluid_hash.c @@ -21,10 +21,10 @@ * Modified by the GLib Team and others 1997-2000. See the AUTHORS * file for a list of people on the GLib Team. See the ChangeLog * files for a list of changes. These files are distributed with - * GLib at ftp://ftp.gtk.org/pub/gtk/. + * GLib at ftp://ftp.gtk.org/pub/gtk/. */ -/* +/* * MT safe */ @@ -60,7 +60,7 @@ struct _fluid_hashtable_t { if ((3 * hash_table->size <= hash_table->nnodes) \ && (hash_table->size < HASH_TABLE_MAX_SIZE)) { \ fluid_hashtable_resize(hash_table); \ - } + } static void fluid_hashtable_resize(fluid_hashtable_t *hash_table); static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_table, char* key); @@ -69,7 +69,7 @@ static fluid_hashnode_t** fluid_hashtable_lookup_node(fluid_hashtable_t *hash_ta * new_fluid_hashtable: * * Creates a new #fluid_hashtable_t. - * + * * Return value: a new #fluid_hashtable_t. **/ fluid_hashtable_t* @@ -94,22 +94,22 @@ new_fluid_hashtable(fluid_hash_delete_t del) /** * delete_fluid_hashtable: * @hash_table: a #fluid_hashtable_t. - * - * Destroys the #fluid_hashtable_t. If keys and/or values are dynamically + * + * Destroys the #fluid_hashtable_t. If keys and/or values are dynamically * allocated, you should either free them first or create the #fluid_hashtable_t - * using fluid_hashtable_new_full(). In the latter case the destroy functions - * you supplied will be called on all keys and values before destroying + * using fluid_hashtable_new_full(). In the latter case the destroy functions + * you supplied will be called on all keys and values before destroying * the #fluid_hashtable_t. **/ void delete_fluid_hashtable(fluid_hashtable_t *hash_table) { unsigned int i; - + if (hash_table == NULL) { return; } - + for (i = 0; i < hash_table->size; i++) { delete_fluid_hashnodes(hash_table->nodes[i], hash_table->del); } @@ -123,13 +123,13 @@ static /*inline*/ fluid_hashnode_t** fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key) { fluid_hashnode_t **node; - + node = &hash_table->nodes[fluid_str_hash(key) % hash_table->size]; - + while (*node && (FLUID_STRCMP((*node)->key, key) != 0)) { node = &(*node)->next; } - + return node; } @@ -137,16 +137,16 @@ fluid_hashtable_lookup_node (fluid_hashtable_t* hash_table, char* key) * fluid_hashtable_lookup: * @hash_table: a #fluid_hashtable_t. * @key: the key to look up. - * + * * Looks up a key in a #fluid_hashtable_t. - * + * * Return value: the associated value, or %NULL if the key is not found. **/ int fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, int* type) { fluid_hashnode_t *node; - + node = *fluid_hashtable_lookup_node(hash_table, key); if (node) { @@ -167,22 +167,22 @@ fluid_hashtable_lookup(fluid_hashtable_t *hash_table, char* key, void** value, i * @hash_table: a #fluid_hashtable_t. * @key: a key to insert. * @value: the value to associate with the key. - * + * * Inserts a new key and value into a #fluid_hashtable_t. - * + * * If the key already exists in the #fluid_hashtable_t its current value is replaced - * with the new value. If you supplied a @value_destroy_func when creating the + * with the new value. If you supplied a @value_destroy_func when creating the * #fluid_hashtable_t, the old value is freed using that function. If you supplied - * a @key_destroy_func when creating the #fluid_hashtable_t, the passed key is freed + * a @key_destroy_func when creating the #fluid_hashtable_t, the passed key is freed * using that function. **/ void fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, int type) { fluid_hashnode_t **node; - + node = fluid_hashtable_lookup_node(hash_table, key); - + if (*node) { (*node)->value = value; (*node)->type = type; @@ -199,21 +199,21 @@ fluid_hashtable_insert(fluid_hashtable_t *hash_table, char* key, void* value, in * @hash_table: a #GHashTable. * @key: a key to insert. * @value: the value to associate with the key. - * - * Inserts a new key and value into a #GHashTable similar to - * fluid_hashtable_insert(). The difference is that if the key already exists - * in the #GHashTable, it gets replaced by the new key. If you supplied a - * @value_destroy_func when creating the #GHashTable, the old value is freed - * using that function. If you supplied a @key_destroy_func when creating the - * #GHashTable, the old key is freed using that function. + * + * Inserts a new key and value into a #GHashTable similar to + * fluid_hashtable_insert(). The difference is that if the key already exists + * in the #GHashTable, it gets replaced by the new key. If you supplied a + * @value_destroy_func when creating the #GHashTable, the old value is freed + * using that function. If you supplied a @key_destroy_func when creating the + * #GHashTable, the old key is freed using that function. **/ void fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, int type) { fluid_hashnode_t **node; - + node = fluid_hashtable_lookup_node(hash_table, key); - + if (*node) { if (hash_table->del) { hash_table->del((*node)->value, (*node)->type); @@ -231,30 +231,30 @@ fluid_hashtable_replace(fluid_hashtable_t *hash_table, char* key, void* value, i * fluid_hashtable_remove: * @hash_table: a #fluid_hashtable_t. * @key: the key to remove. - * + * * Removes a key and its associated value from a #fluid_hashtable_t. * * 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. - * + * * Return value: %TRUE if the key was found and removed from the #fluid_hashtable_t. **/ int fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key) { fluid_hashnode_t **node, *dest; - + node = fluid_hashtable_lookup_node(hash_table, key); if (*node) { dest = *node; (*node) = dest->next; delete_fluid_hashnode(dest, hash_table->del); hash_table->nnodes--; - + FLUID_HASHTABLE_RESIZE (hash_table); - + return 1; } @@ -266,7 +266,7 @@ fluid_hashtable_remove (fluid_hashtable_t *hash_table, char* key) * @hash_table: a #fluid_hashtable_t. * @func: the function to call for each key/value pair. * @user_data: user data to pass to the function. - * + * * Calls the given function for each of the key/value pairs in the * #fluid_hashtable_t. The function is passed the key and value of each * pair, and the given @user_data parameter. The hash table may not @@ -290,9 +290,9 @@ fluid_hashtable_foreach(fluid_hashtable_t *hash_table, fluid_hash_iter_t func, v /** * fluid_hashtable_size: * @hash_table: a #fluid_hashtable_t. - * + * * Returns the number of elements contained in the #fluid_hashtable_t. - * + * * Return value: the number of key/value pairs in the #fluid_hashtable_t. **/ unsigned int @@ -315,14 +315,14 @@ fluid_hashtable_resize(fluid_hashtable_t *hash_table) new_size = (new_size > HASH_TABLE_MAX_SIZE)? HASH_TABLE_MAX_SIZE : new_size; /* printf("%s: %d: resizing, new size = %d\n", __FILE__, __LINE__, new_size); */ - + new_nodes = FLUID_ARRAY(fluid_hashnode_t*, new_size); FLUID_MEMSET(new_nodes, 0, new_size * sizeof(fluid_hashnode_t*)); for (i = 0; i < hash_table->size; i++) { for (node = hash_table->nodes[i]; node; node = next) { next = node->next; - hash_val = fluid_str_hash(node->key) % new_size; + hash_val = fluid_str_hash(node->key) % new_size; node->next = new_nodes[hash_val]; new_nodes[hash_val] = node; } @@ -337,14 +337,14 @@ static fluid_hashnode_t* new_fluid_hashnode(char* key, void* value, int type) { fluid_hashnode_t *hash_node; - + hash_node = FLUID_NEW(fluid_hashnode_t); - + hash_node->key = FLUID_STRDUP(key); hash_node->value = value; hash_node->type = type; hash_node->next = NULL; - + return hash_node; } @@ -367,7 +367,7 @@ delete_fluid_hashnodes(fluid_hashnode_t *hash_node, fluid_hash_delete_t del) fluid_hashnode_t *next = hash_node->next; delete_fluid_hashnode(hash_node, del); hash_node = next; - } + } } diff --git a/src/libs/fluidsynth/src/fluid_hash.h b/src/libs/fluidsynth/src/fluid_hash.h index 9cb21b52bf..d2e8577eb5 100644 --- a/src/libs/fluidsynth/src/fluid_hash.h +++ b/src/libs/fluidsynth/src/fluid_hash.h @@ -21,7 +21,7 @@ * Modified by the GLib Team and others 1997-2000. See the AUTHORS * file for a list of people on the GLib Team. See the ChangeLog * files for a list of changes. These files are distributed with - * GLib at ftp://ftp.gtk.org/pub/gtk/. + * GLib at ftp://ftp.gtk.org/pub/gtk/. */ /* diff --git a/src/libs/fluidsynth/src/fluid_io.c b/src/libs/fluidsynth/src/fluid_io.c index e00251b2d4..1c46d9d378 100644 --- a/src/libs/fluidsynth/src/fluid_io.c +++ b/src/libs/fluidsynth/src/fluid_io.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -52,15 +52,15 @@ int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len) #if WITH_READLINE if (in == fluid_get_stdin()) { char* line; - + line = readline(prompt); if (line == NULL) { return -1; } - + snprintf(buf, len, "%s", line); buf[len - 1] = 0; - + free(line); return 1; } else { @@ -78,19 +78,19 @@ int fluid_istream_gets(fluid_istream_t in, char* buf, int len) int n; buf[len - 1] = 0; - + while (--len > 0) { n = read(in, &c, 1); if (n == 0) { *buf++ = 0; return 0; - } + } if (n < 0) { return n; } if ((c == '\n') || (c == '\r')) { *buf++ = 0; - return 1; + return 1; } *buf++ = c; } @@ -102,12 +102,12 @@ int fluid_istream_gets(fluid_istream_t in, char* buf, int len) int fluid_ostream_printf(fluid_ostream_t out, char* format, ...) { char buf[4096]; - va_list args; + va_list args; int len; - va_start(args, format); - len = vsnprintf(buf, 4095, format, args); - va_end(args); + va_start(args, format); + len = vsnprintf(buf, 4095, format, args); + va_end(args); if (len <= 0) { printf("fluid_ostream_printf: buffer overflow"); diff --git a/src/libs/fluidsynth/src/fluid_io.h b/src/libs/fluidsynth/src/fluid_io.h index 733ac0c05e..95e1aaff64 100644 --- a/src/libs/fluidsynth/src/fluid_io.h +++ b/src/libs/fluidsynth/src/fluid_io.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -23,15 +23,15 @@ #define _FLUID_IO_H -/** Read a line from the input stream. - - \returns 0 if end-of-stream, -1 if error, non zero otherwise +/** Read a line from the input stream. + + \returns 0 if end-of-stream, -1 if error, non zero otherwise */ int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len); -/** Read a line from the input stream. - +/** Read a line from the input stream. + \returns The number of bytes written. If an error occured, -1 is returned. */ diff --git a/src/libs/fluidsynth/src/fluid_ladspa.c b/src/libs/fluidsynth/src/fluid_ladspa.c index 153dfb9225..57efa9be7a 100644 --- a/src/libs/fluidsynth/src/fluid_ladspa.c +++ b/src/libs/fluidsynth/src/fluid_ladspa.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -57,17 +57,17 @@ fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth){ return FxUnit; }; -/* Purpose: +/* Purpose: * Creates the system nodes to get data into and out of the Fx unit. */ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){ - char str[99]; + char str[99]; int nr_input_nodes; int nr_fx_input_nodes; int nr_output_nodes; int temp; int i; - + /* Retrieve the number of synth / audio out / Fx send nodes */ assert(fluid_settings_getint(FxUnit->synth->settings, "synth.audio-groups", &temp)); nr_input_nodes=(int) temp; @@ -78,7 +78,7 @@ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){ assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp)); nr_fx_input_nodes=temp; - + /* Create regular input nodes (associated with audio groups) */ for (i=0; i < nr_input_nodes; i++){ sprintf(str, "in%i_L",(i+1)); @@ -104,13 +104,13 @@ void fluid_LADSPA_CreateSystemNodes(fluid_LADSPA_FxUnit_t* FxUnit){ }; }; -/* Purpose: +/* Purpose: * Creates predeclared nodes for control of the Fx unit during operation. */ -void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){ +void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){ int i; fluid_LADSPA_Node_t* CurrentNode; - + for (i=0; iNumberUserControlNodes; i++){ CurrentNode=fluid_LADSPA_CreateNode(FxUnit,FxUnit->UserControlNodeNames[i],fluid_LADSPA_node_is_control); assert(CurrentNode); @@ -120,10 +120,10 @@ void fluid_LADSPA_CreateUserControlNodes(fluid_LADSPA_FxUnit_t* FxUnit){ }; }; -/* Purpose: +/* Purpose: * Returns the pointer to the shared library loaded using 'LibraryFilename' (if it has been loaded). * Return NULL otherwise. - * If not: Clear Fx and abort. + * If not: Clear Fx and abort. */ void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){ void * CurrentLib=NULL; @@ -137,15 +137,15 @@ void * fluid_LADSPA_RetrieveSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * return CurrentLib; }; -/* Purpose: +/* Purpose: * Loads a shared LADSPA library. - * Return NULL, if failed. + * Return NULL, if failed. * TODO: use LADSPA_PATH */ void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * LibraryFilename){ void * LoadedLib; assert(LibraryFilename); - LoadedLib=dlopen(LibraryFilename,RTLD_NOW); + LoadedLib=dlopen(LibraryFilename,RTLD_NOW); if (!LoadedLib){ return NULL; }; @@ -155,7 +155,7 @@ void * fluid_LADSPA_LoadSharedLibrary(fluid_LADSPA_FxUnit_t* FxUnit, char * Libr return LoadedLib; }; -/* Purpose: +/* Purpose: * Retrieves a descriptor to the plugin labeled 'PluginLabel' from the shared library. */ const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * CurrentLib, char * PluginLabel){ @@ -164,16 +164,16 @@ const LADSPA_Descriptor * fluid_LADSPA_Retrieve_Plugin_Descriptor(void * Current const LADSPA_Descriptor * psDescriptor; pfDescriptorFunction = (LADSPA_Descriptor_Function)dlsym(CurrentLib,"ladspa_descriptor"); while (pfDescriptorFunction(lPluginIndex)){ - psDescriptor = pfDescriptorFunction(lPluginIndex); + psDescriptor = pfDescriptorFunction(lPluginIndex); if (FLUID_STRCMP(psDescriptor->Label, PluginLabel) == 0){ - return psDescriptor; + return psDescriptor; }; lPluginIndex++; }; return NULL; -}; +}; -/* Purpose: +/* Purpose: * Finds out, if 'PortName' starts with 'PluginPort'. * Spaces and underscore mean the same. * The comparison is not case sensitive. @@ -203,7 +203,7 @@ fluid_LADSPA_Stringmatch_t fluid_LADSPA_Check_SubString_Match(const char * Plugi }; /* Purpose: - * Load the plugins added with 'ladspa_add' and then start the Fx unit. + * Load the plugins added with 'ladspa_add' and then start the Fx unit. */ int @@ -214,7 +214,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream char * PluginLabel; char ** TokenSequence; void * CurrentLib; - int NodeCount; //x + int NodeCount; //x int IngoingSignalCount; // Count signals going into LADSPA Fx section int OutgoingSignalCount; // Count signals going out of LADSPA Fx section int ReturnVal=FLUID_OK; /* If warnings occur, this is set to -1. */ @@ -223,7 +223,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream L(fluid_ostream_printf(out,"ladspa_start: starting...")); assert(synth); FxUnit=synth->LADSPA_FxUnit; assert(FxUnit); - + /* When calling fluid_ladspastart, the Fx unit must be 'cleared' (no plugins, no libs, no nodes). Verify this here. */ if (FxUnit->NumberPlugins || FxUnit->NumberLibs){ fluid_ostream_printf(out, "***Error006***\n" @@ -238,12 +238,12 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream "Use ladspa_add first!\n"); fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); - }; - + }; + /* Create predefined nodes */ L(fluid_ostream_printf(out,"ladspa_start: creating predefined nodes...")); fluid_LADSPA_CreateSystemNodes(FxUnit); - + /* Create predeclared nodes, that will allow to control the Fx unit during operation */ L(fluid_ostream_printf(out,"ladspa_start: creating user control nodes...")); fluid_LADSPA_CreateUserControlNodes(FxUnit); @@ -251,14 +251,14 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream L(fluid_ostream_printf(out,"ladspa_start: Processing command lines...")); for (CommandLineCount=0; CommandLineCountNumberCommands; CommandLineCount++){ int CurrentPlugin_PortConnected[FLUID_LADSPA_MaxTokens/3]; /* For example: 100 tokens corresponds to roughly 30 ports. */ - char LibFullPath[FLUID_LADSPA_MaxPathLength]; + char LibFullPath[FLUID_LADSPA_MaxPathLength]; const LADSPA_Descriptor * CurrentPluginDescriptor; - LADSPA_Handle CurrentPlugin; + LADSPA_Handle CurrentPlugin; unsigned long PortCount; int TokenCount=0; char * Search; - int HasASlash=0; - + int HasASlash=0; + if (FxUnit->NumberPlugins>=FLUID_LADSPA_MaxPlugins){ fluid_ostream_printf(out, "***Error003***\n" "Too many plugins at the same time (%i).\n" @@ -269,13 +269,13 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream }; L(fluid_ostream_printf(out,"Processing plugin nr. %i",FxUnit->NumberPlugins)); - + TokenSequence=FxUnit->LADSPA_Command_Sequence[CommandLineCount]; assert(TokenSequence); - /* Check, if the library is already loaded. If not, load. */ + /* Check, if the library is already loaded. If not, load. */ LibraryFilename=TokenSequence[TokenCount++]; assert(LibraryFilename); - + L(fluid_ostream_printf(out,"Library name from ladspa_add: %s",LibraryFilename)); /* A slash-free filename refers to the LADSPA_PATH directory. Add that path, if needed. */ @@ -286,7 +286,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream * If that fails, signal error. * Otherwise leave the filename as it is. */; - + /* Determine, if the library name is just the filename, or a path (including a slash) */ Search=LibraryFilename; while (*Search != '\0') { @@ -295,9 +295,9 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream }; Search++; }; - + if (!HasASlash){ - if (!LADSPA_Path){ + if (!LADSPA_Path){ fluid_ostream_printf(out, "***Error018***\n" "The library file name %s does not include a path.\n" "The environment variable LADSPA_PATH is not set.\n" @@ -319,7 +319,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream CurrentLib=fluid_LADSPA_RetrieveSharedLibrary(FxUnit, LibFullPath); if (!CurrentLib){ - LADSPA_Descriptor_Function pfDescriptorFunction; + LADSPA_Descriptor_Function pfDescriptorFunction; L(fluid_ostream_printf(out,"Library %s not yet loaded. Loading.",LibFullPath)); @@ -330,7 +330,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + /* Load a LADSPA plugin library and store it for future use.*/ CurrentLib=fluid_LADSPA_LoadSharedLibrary(FxUnit, LibFullPath); @@ -350,23 +350,23 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream if (!pcError) {pcError="Huh?! No error from lib!";}; fluid_ostream_printf(out, "***Error015***\n" "Unable to find ladspa_descriptor() function in plugin library file \"%s\": %s.\n" - "Are you sure this is a LADSPA plugin file?\n", + "Are you sure this is a LADSPA plugin file?\n", LibraryFilename, pcError); fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + L(fluid_ostream_printf(out,"Library loaded.")); }; - + PluginLabel=TokenSequence[TokenCount++]; assert(PluginLabel); L(fluid_ostream_printf(out,"Plugin Label from ladspa_add: %s",PluginLabel)); /* Retrieve a 'plugin descriptor' from the library. */ L(fluid_ostream_printf(out,"Looking for the plugin labeled %s",PluginLabel)); - + CurrentPluginDescriptor=fluid_LADSPA_Retrieve_Plugin_Descriptor(CurrentLib, PluginLabel); - + /* Check, that the plugin was actually found.*/ if (CurrentPluginDescriptor==NULL){ @@ -379,30 +379,30 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + /* Create an instance of the plugin type from the descriptor */ L(fluid_ostream_printf(out,"instantiating plugin %s",PluginLabel)); CurrentPlugin=CurrentPluginDescriptor ->instantiate(CurrentPluginDescriptor,44100); /* Sample rate hardcoded */ assert(CurrentPlugin); - + /* The descriptor ("type of plugin") and the instance are stored for each plugin instantiation. If one plugin type is instantiated several times, they will have the same descriptor, only different instances.*/ FxUnit->PluginDescriptorTable[FxUnit->NumberPlugins]=CurrentPluginDescriptor; FxUnit->PluginInstanceTable[FxUnit->NumberPlugins]=CurrentPlugin; - + /* - * - * Wire up the inputs and outputs - * + * + * Wire up the inputs and outputs + * */ /* List for checking, that each plugin port is exactly connected once */ for (PortCount=0; PortCountPortCount; PortCount++){ CurrentPlugin_PortConnected[PortCount]=0; }; - + /* Note: There are three NULL tokens at the end. The last condition may be evaluated even if the first one already detects the end. */ while (TokenSequence[TokenCount] && TokenSequence[TokenCount+1] && TokenSequence[TokenCount+2]){ int CurrentPort_StringMatchCount; @@ -418,11 +418,11 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream CurrentPort_StringMatchCount=0; L(fluid_ostream_printf(out,"Wiring %s %s %s",Plugin_Port, Direction, FLUID_Node)); - + /* Find the port number on the plugin, that belongs to "Plugin_Port". * Match the identifier specified by the user against the first characters * of the port name. - * + * * If the given identifier matches several port names only partly, then the input is ambiguous, an error * message results. * @@ -430,19 +430,19 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream * - Output Envelope Attack (s) * - Output Envelope Decay (s) * - Output - * + * * The user input 'Output' matches the first two labels partly, the third fully. This will be accepted. * The user input 'Out' matches all three only partly, this results in an error message. */ - + for (PortCount=0; PortCountPortCount; PortCount++){ PortName=CurrentPluginDescriptor->PortNames[PortCount]; - + StringMatchType=fluid_LADSPA_Check_SubString_Match(Plugin_Port, PortName); /* If a full-string match has been found earlier, reject all partial matches. */ if (StringMatchType==fluid_LADSPA_FullMatch || (StringMatchType==fluid_LADSPA_PartialMatch && CurrentPort_StringMatchType != fluid_LADSPA_FullMatch)){ - + if(StringMatchType==fluid_LADSPA_FullMatch && CurrentPort_StringMatchType==fluid_LADSPA_FullMatch){ fluid_ostream_printf(out, "***Error027***\n" "While processing plugin %s: The port label %s appears more than once!\n" @@ -450,14 +450,14 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + CurrentPort_Index=PortCount; CurrentPort_StringMatchType=StringMatchType; CurrentPort_StringMatchCount++; - + }; /* if suitable match */ }; /* For port count */ - + /* Several partial matches? Then the identifier is not unique. */ if (CurrentPort_StringMatchCount > 1 && CurrentPort_StringMatchType == fluid_LADSPA_PartialMatch){ fluid_ostream_printf(out, "***Error019***\n" @@ -467,7 +467,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + if (CurrentPort_Index<0){ fluid_ostream_printf(out, "***Error017***\n" "Unable to find port '%s' on plugin %s\n" @@ -479,13 +479,13 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index]; + CurrentPort_Descriptor=CurrentPluginDescriptor->PortDescriptors[CurrentPort_Index]; assert(CurrentPort_Descriptor); - + /* Retrieve the node with the right name. */ Current_Node=fluid_LADSPA_RetrieveNode(FxUnit,FLUID_Node); #define PortIsAudio LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor)) -#define PortIsControl LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor)) +#define PortIsControl LADSPA_IS_PORT_CONTROL(CurrentPort_Descriptor) && !(LADSPA_IS_PORT_AUDIO(CurrentPort_Descriptor)) if (!Current_Node){ /* Doesn't exist? Then create it. */ if (FxUnit->NumberNodes>=FLUID_LADSPA_MaxNodes){ @@ -504,21 +504,21 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream "Plugin port number %i is neither input nor output!\n" "This is an error in the plugin.\n" "Please check plugin sourcecode.\n", - CurrentPort_Index); + CurrentPort_Index); fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; }; assert(Current_Node); - - /* + + /* * * Check flowgraph for some possible errors. * */ if (FLUID_STRCMP(Direction,"->")==0){ - /* Data from plugin to FLUID, into node + /* Data from plugin to FLUID, into node * * *** Rule: **** * A node may not have more than one data source.*/ @@ -530,11 +530,11 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream }; Current_Node->InCount++; } else if (FLUID_STRCMP(Direction,"<-")==0){ - /* Data from FLUID to plugin, out of node + /* Data from FLUID to plugin, out of node * * This check verifies the integrity of the flow graph: * *** Rule *** - * The execution order of the plugins is the order, in which they are programmed. + * The execution order of the plugins is the order, in which they are programmed. * The plugins must be ordered so, that the input of a plugin is already computed at the time of its execution. * If the user tries to read data out of a node that has not yet an input, then something is wrong.*/ assert(Current_Node->InCount<=1); @@ -542,7 +542,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_ostream_printf(out, "***Error010***\n" "Plugin %s tries to read data through input %s from node %s.\n" "But at this point there is no valid data at that node.\n" - "Please check the flowgraph and especially the execution order!\n",PluginLabel,Plugin_Port,FLUID_Node); + "Please check the flowgraph and especially the execution order!\n",PluginLabel,Plugin_Port,FLUID_Node); fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; @@ -550,7 +550,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream } else { fluid_ostream_printf(out, "***Error024***\n" "Syntax error: Illegal `arrow' `%s', expecting -> or <-\n", - Direction); + Direction); fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; @@ -558,7 +558,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream /* In any case, there must be a valid data source for the port at this time. */ assert(Current_Node->InCount==1); - /* Keep track on the number of connections to each port. + /* Keep track on the number of connections to each port. * This error occurs only, if an attempt is made to connect one port twice (i.e. ladspa_add libname pluginname port <- nodex port <- nodey) */ if (CurrentPlugin_PortConnected[CurrentPort_Index]){ fluid_ostream_printf(out, "***Error011***\n" @@ -570,9 +570,9 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream /* * * Connect the port - * + * */ - + L(fluid_ostream_printf(out,"Connecting %i",CurrentPort_Index)); CurrentPluginDescriptor->connect_port (CurrentPlugin, @@ -580,7 +580,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream Current_Node->buf ); CurrentPlugin_PortConnected[CurrentPort_Index]++; - + }; /* While Tokensequence (more connections) */ /* @@ -588,7 +588,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream * Check for left-over tokens * */ - + if (TokenSequence[TokenCount]){ char * T1="";char * T2="";char * T3=""; if (TokenSequence[TokenCount]){T1=TokenSequence[TokenCount];}; @@ -599,7 +599,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + /* * * Check, that all plugin ports are connected @@ -615,7 +615,7 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream return(PrintErrorMessage); }; }; - + /* * *Run activate function on plugin, where possible @@ -625,21 +625,21 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream if (CurrentPluginDescriptor->activate !=NULL){ CurrentPluginDescriptor->activate(CurrentPlugin); }; - + FxUnit->NumberPlugins++; }; /* For CommandLineCount: once for each new command (i.e. plugin instantiation request from user */ - + /* * * Further flow graph checks * */ - + L(fluid_ostream_printf(out,"Checking flow graph")); IngoingSignalCount=0; OutgoingSignalCount=0; - + for (NodeCount=0; NodeCountNumberNodes; NodeCount++){ fluid_LADSPA_Node_t* Current_Node; Current_Node=FxUnit->Nodelist[NodeCount]; @@ -649,8 +649,8 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream } else if (Current_Node->flags & fluid_LADSPA_node_is_sink){ OutgoingSignalCount+=Current_Node->InCount; } else { - - /* A node without any input doesn't make sense. + + /* A node without any input doesn't make sense. * The flow graph check aborts with an error. This case cannot happen. */ if (Current_Node->InCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ /* There can only be one warning at a time. */ @@ -658,12 +658,12 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream "No input into node %s.\n" "Use '_' as first char in nodename to suppress this warning.\n" "Hint: Check for typos in the node name.\n",Current_Node->Name); - /* A warning can also be printed as an error message (check fluid_cmd.c). The only difference between + /* A warning can also be printed as an error message (check fluid_cmd.c). The only difference between the return values -1 and 0 is, that -1 prints the result. */ }; ReturnVal=PrintErrorMessage; }; - + /* A node without any output doesn't make sense. */ if (Current_Node->OutCount==0 && !Current_Node->flags & fluid_LADSPA_node_is_dummy){ fluid_ostream_printf(out, "***Warning021***\n" @@ -675,27 +675,27 @@ fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ostream /* A free-flying node simply cannot happen. */ assert(Current_Node->OutCount+Current_Node->InCount); }; /* Foreach node */ - + /* Issue a warning, if no signal goes into the Fx section. */ - if (IngoingSignalCount==0){ + if (IngoingSignalCount==0){ fluid_ostream_printf(out, "***Warning022***\n" "You have not connected anything to the synthesizer section (in1_L, in1_R).\n"); ReturnVal=PrintErrorMessage; }; - + /* Issue a warning, if no signal leaves the Fx section. */ - if (OutgoingSignalCount==0){ + if (OutgoingSignalCount==0){ fluid_ostream_printf(out, "***Warning023***\n" "You have not connected anything to the output (out1_L, out1_R).\n"); }; - + /* Finally turn on the Fx unit. */ FxUnit->Bypass=fluid_LADSPA_Active; L(fluid_ostream_printf(out,"LADSPA Init OK")); return(ReturnVal); }; -void +void fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]){ int i; int ii; @@ -719,10 +719,10 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_ assert(fluid_settings_getint(FxUnit->synth->settings, "synth.effects-channels", &temp)); nr_fx_sends=temp; - /* Fixme: Retrieving nodes via names is inefficient - * (but not that bad, because the interesting nodes are always at the start of the list). + /* Fixme: Retrieving nodes via names is inefficient + * (but not that bad, because the interesting nodes are always at the start of the list). */ - + /* Input and output are processed via the same buffers. Therefore the effect is bypassed by just skipping everything else. */ if (FxUnit->Bypass==fluid_LADSPA_Bypassed){ return; @@ -736,7 +736,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_ L(printf("LADSPA_Run: Command line asked for bypass of Fx unit. Acknowledged.")); return; }; - + assert(FxUnit); /* Clear the output buffers, if they are not connected anywhere */ @@ -756,16 +756,16 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_ FLUID_MEMSET(n->buf, 0, byte_size); }; }; - + /* Prepare the incoming data: * Convert fluid_real_t data type to LADSPA_Data type */ for (ii=0; ii < nr_groups; ii++){ fluid_real_t* src_buf=left_buf[ii]; sprintf(str, "in%i_L",(ii+1)); n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); - + assert(FLUID_BUFSIZE % 2 == 0); - + /* Add a very small high frequency signal. This avoids denormal number problems. */ for (i=0; ibuf[i]=(LADSPA_Data)(src_buf[i]+1.e-15); @@ -816,7 +816,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_ for (i=0; ibuf[i]; }; - + dest_buf=right_buf[ii]; sprintf(str, "out%i_R",(ii+1)); n=fluid_LADSPA_RetrieveNode(FxUnit, str); assert(n); @@ -826,7 +826,7 @@ fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* FxUnit, fluid_real_t* left_buf[], fluid_ }; }; -fluid_LADSPA_Node_t* +fluid_LADSPA_Node_t* fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){ int i=0; assert(FxUnit);assert(Name); @@ -840,12 +840,12 @@ fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name){ }; -/* Purpose: +/* Purpose: * Creates a new node from the node name given by the user. */ -fluid_LADSPA_Node_t* +fluid_LADSPA_Node_t* fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){ - int Dummy=0; + int Dummy=0; fluid_LADSPA_Node_t* NewNode; assert(FxUnit); assert(Name); @@ -858,7 +858,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){ fluid_LADSPA_clear(FxUnit); return NULL; }; - + /* Don't allow node names, which start with -, 0..9 */ if (Name[0] == '-' || (Name[0]>='0' && Name[0]<='9')){ printf( "***Error026***\n" @@ -870,7 +870,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){ fluid_LADSPA_clear(FxUnit); return NULL; }; - + /* A nodename starting with "_" is a possible dummy node, which may (but need not) act as a data sink or source (dummy node). */ if (Name[0] == ' '){ /* ??? Should be '_' ??? */ Dummy=1; @@ -880,7 +880,7 @@ fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags){ /* Audio node contains buffer. */ NewNode->buf=FLUID_ARRAY(LADSPA_Data, (FLUID_BUFSIZE));assert(NewNode->buf); /* It is permitted to use a dummy node without input. Therefore clear all node buffers at startup. */ - FLUID_MEMSET(NewNode->buf, 0, (FLUID_BUFSIZE*sizeof(LADSPA_Data))); + FLUID_MEMSET(NewNode->buf, 0, (FLUID_BUFSIZE*sizeof(LADSPA_Data))); } else if (flags & fluid_LADSPA_node_is_control){ /* Control node contains single value. */ NewNode->buf=FLUID_ARRAY(LADSPA_Data, 1);assert(NewNode->buf); @@ -939,7 +939,7 @@ void fluid_LADSPA_clear(fluid_LADSPA_FxUnit_t* FxUnit){ FLUID_FREE(FxUnit->UserControlNodeNames[i]); }; FxUnit->NumberUserControlNodes=0; - + L(printf("Clear all plugin instances")); for (i=0; iNumberPlugins; i++){ assert(FxUnit->PluginDescriptorTable[i]); @@ -952,14 +952,14 @@ void fluid_LADSPA_clear(fluid_LADSPA_FxUnit_t* FxUnit){ FxUnit->PluginDescriptorTable[i]->cleanup(FxUnit->PluginInstanceTable[i]); }; FxUnit->NumberPlugins=0; - + L(printf("Clear all nodes")); /* Only after removing plugins! */ for (i=0; iNumberNodes; i++){ FLUID_FREE(FxUnit->Nodelist[i]->buf); FLUID_FREE(FxUnit->Nodelist[i]); }; FxUnit->NumberNodes=0; - + L(printf("Clear all plugin libraries")); for (i=0; iNumberLibs; i++){ @@ -1012,7 +1012,7 @@ int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostre fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + /* CommandLine (token sequence) is terminated with NULL. * Add two more NULLs, so that a chunk of three tokens can be checked later without risk.*/ @@ -1052,7 +1052,7 @@ int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_ fluid_LADSPA_clear(FxUnit); return(PrintErrorMessage); }; - + NodeName=FLUID_STRDUP(av[0]); assert(NodeName); NodeValue=atof(av[1]); FxUnit->UserControlNodeNames[FxUnit->NumberUserControlNodes]=NodeName; diff --git a/src/libs/fluidsynth/src/fluid_ladspa.h b/src/libs/fluidsynth/src/fluid_ladspa.h index 5f9ba86985..45706a228a 100644 --- a/src/libs/fluidsynth/src/fluid_ladspa.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -79,7 +79,7 @@ typedef enum { fluid_LADSPA_node_is_user_ctrl=32 } fluid_LADSPA_nodeflags; -/* fluid_LADSPA_Node_t +/* fluid_LADSPA_Node_t * An internal node of the Fx unit. * A 'node' is the 'glue' that connects several LADSPA plugins. * Basically it's a real-valued variable (control node) or a real-valued buffer (audio node). @@ -107,11 +107,11 @@ typedef struct { int NumberLibs; void * ppvPluginLibs[FLUID_LADSPA_MaxLibs]; char * ppvPluginLibNames[FLUID_LADSPA_MaxLibs]; - + /*List of plugins (descriptor and instance) * A LADSPA plugin descriptor points to the code, which is executed, when a plugin is run. * The plugin instance is given as a parameter, when calling. - */ + */ int NumberPlugins; const LADSPA_Descriptor * PluginDescriptorTable[FLUID_LADSPA_MaxPlugins]; LADSPA_Handle * PluginInstanceTable[FLUID_LADSPA_MaxPlugins]; @@ -119,12 +119,12 @@ typedef struct { /* List of nodes */ int NumberNodes; fluid_LADSPA_Node_t * Nodelist[FLUID_LADSPA_MaxNodes]; - + /* List of Command lines * During the setup phase, each ladspa_add command creates one command sequence. For example: - * ./aw.so alienwah_stereo Input <- Master_L_Synth Output -> Master_R_Synth Parameter <- #42.0 - * Those lists are stored in LADSPA_Command_Sequence. - * One command line results in one plugin => size MaxPlugins. + * ./aw.so alienwah_stereo Input <- Master_L_Synth Output -> Master_R_Synth Parameter <- #42.0 + * Those lists are stored in LADSPA_Command_Sequence. + * One command line results in one plugin => size MaxPlugins. */ int NumberCommands; char ** LADSPA_Command_Sequence[FLUID_LADSPA_MaxPlugins]; @@ -138,11 +138,11 @@ typedef struct { /* Bypass switch * If set, the LADSPA Fx unit does not touch the signal.*/ - fluid_LADSPA_BypassState Bypass; + fluid_LADSPA_BypassState Bypass; /* Communication between the 'command line' process and the synthesis process. * A possible conflict situation arises, when fluid_clear is called, and starts to destroy - * the plugins. But the synthesis thread still processes plugins at the same time. The consequences are ugly. + * the plugins. But the synthesis thread still processes plugins at the same time. The consequences are ugly. * Therefore ladspa_clear waits for acknowledgement from the synthesis thread, that the Fx unit is bypassed. * 'cond' is used for the communication, the mutex is required for changing the condition. */ @@ -168,13 +168,13 @@ fluid_LADSPA_FxUnit_t* new_fluid_LADSPA_FxUnit(fluid_synth_t* synth); */ void fluid_LADSPA_run(fluid_LADSPA_FxUnit_t* Fx_unit, fluid_real_t* left_buf[], fluid_real_t* right_buf[], fluid_real_t* fx_left_buf[], fluid_real_t* fx_right_buf[]); -/* Purpose: - * Returns the node belonging to Name or NULL, if not found +/* Purpose: + * Returns the node belonging to Name or NULL, if not found */ fluid_LADSPA_Node_t* fluid_LADSPA_RetrieveNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name); -/* Purpose: - * Creates a new node with the given characteristics. +/* Purpose: + * Creates a new node with the given characteristics. */ fluid_LADSPA_Node_t* fluid_LADSPA_CreateNode(fluid_LADSPA_FxUnit_t* FxUnit, char * Name, int flags); @@ -196,8 +196,8 @@ void fluid_LADSPA_shutdown(fluid_LADSPA_FxUnit_t* FxUnit); /* - * fluid_handle_LADSPA_XXX - * Those functions are called from fluid_cmd, when a command is entered on the command line. + * fluid_handle_LADSPA_XXX + * Those functions are called from fluid_cmd, when a command is entered on the command line. */ /* Purpose: @@ -226,12 +226,12 @@ int fluid_LADSPA_handle_start(fluid_synth_t* synth, int ac, char** av, fluid_ost int fluid_LADSPA_handle_add(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out); /* Purpose: - * Declares a user control node and a value; for further processing in ladspa_start. + * Declares a user control node and a value; for further processing in ladspa_start. */ int fluid_LADSPA_handle_declnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out); /* Purpose: - * Assigns a value to the a user control node + * Assigns a value to the a user control node */ int fluid_LADSPA_handle_setnode(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out); diff --git a/src/libs/fluidsynth/src/fluid_lash.c b/src/libs/fluidsynth/src/fluid_lash.c index 744f89708a..0f3c55f284 100644 --- a/src/libs/fluidsynth/src/fluid_lash.c +++ b/src/libs/fluidsynth/src/fluid_lash.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -73,7 +73,7 @@ fluid_lash_save (fluid_synth_t * synth) fluid_sfont_t * sfont; lash_config_t * config; char num[32]; - + sfcount = fluid_synth_sfcount (synth); config = lash_config_new (); @@ -85,12 +85,12 @@ fluid_lash_save (fluid_synth_t * synth) { sfont = fluid_synth_get_sfont (synth, i); config = lash_config_new (); - + sprintf (num, "%d", i); - + lash_config_set_key (config, num); lash_config_set_value_string (config, sfont->get_name (sfont)); - + lash_send_config (fluid_lash_client, config); } } @@ -110,11 +110,11 @@ fluid_lash_run (void * data) int done = 0; int err; int pending_restores = 0; - + synth = (fluid_synth_t *) data; - + while (!done) - { + { while ( (event = lash_get_event (fluid_lash_client)) ) { switch (lash_event_get_type (event)) @@ -144,7 +144,7 @@ fluid_lash_run (void * data) break; } } - + while ( (config = lash_get_config (fluid_lash_client)) ) { if (strcmp (lash_config_get_key (config), "soundfont count") == 0) @@ -162,10 +162,10 @@ fluid_lash_run (void * data) lash_send_event (fluid_lash_client, event); } } - + usleep (10000); } - + return NULL; } @@ -200,7 +200,7 @@ fluid_lash_save (fluid_synth_t * synth) fluid_sfont_t * sfont; cca_config_t * config; char num[32]; - + sfcount = fluid_synth_sfcount (synth); config = cca_config_new (); @@ -212,12 +212,12 @@ fluid_lash_save (fluid_synth_t * synth) { sfont = fluid_synth_get_sfont (synth, i); config = cca_config_new (); - + sprintf (num, "%d", i); - + cca_config_set_key (config, num); cca_config_set_value_string (config, sfont->get_name (sfont)); - + cca_send_config (fluid_lash_client, config); } } @@ -238,9 +238,9 @@ fluid_lash_run (void * data) int done = 0; int err; int pending_restores = 0; - + synth = (fluid_synth_t *) data; - + while (!done) { while ( (event = cca_get_event (fluid_lash_client)) ) @@ -272,7 +272,7 @@ fluid_lash_run (void * data) break; } } - + while ( (config = cca_get_config (fluid_lash_client)) ) { if (strcmp (cca_config_get_key (config), "soundfont count") == 0) @@ -290,10 +290,10 @@ fluid_lash_run (void * data) cca_send_event (fluid_lash_client, event); } } - + usleep (10000); } - + return NULL; } diff --git a/src/libs/fluidsynth/src/fluid_lash.h b/src/libs/fluidsynth/src/fluid_lash.h index 00ad405ee0..125283c051 100644 --- a/src/libs/fluidsynth/src/fluid_lash.h +++ b/src/libs/fluidsynth/src/fluid_lash.h @@ -11,13 +11,15 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #if defined(HAVE_LASH) || defined(HAVE_LADCCA) diff --git a/src/libs/fluidsynth/src/fluid_list.c b/src/libs/fluidsynth/src/fluid_list.c index 31cf49ac9e..4d1e64fd5f 100644 --- a/src/libs/fluidsynth/src/fluid_list.c +++ b/src/libs/fluidsynth/src/fluid_list.c @@ -21,7 +21,7 @@ * Modified by the GLib Team and others 1997-1999. See the AUTHORS * file for a list of people on the GLib Team. See the ChangeLog * files for a list of changes. These files are distributed with - * GLib at ftp://ftp.gtk.org/pub/gtk/. + * GLib at ftp://ftp.gtk.org/pub/gtk/. */ @@ -120,10 +120,10 @@ fluid_list_remove(fluid_list_t *list, void* data) } tmp->next = NULL; delete_fluid_list(tmp); - + break; } - + prev = tmp; tmp = tmp->next; } @@ -151,15 +151,15 @@ fluid_list_remove_link(fluid_list_t *list, fluid_list_t *link) tmp->next = NULL; break; } - + prev = tmp; tmp = tmp->next; } - + 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; @@ -176,11 +176,11 @@ fluid_list_sort_merge(fluid_list_t *l1, fluid_list_t *l2, fluid_compare_func_t c } } 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; @@ -192,15 +192,15 @@ fluid_list_sort(fluid_list_t *list, fluid_compare_func_t compare_func) return list; } - l1 = list; + l1 = list; l2 = list->next; while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) + if ((l2 = l2->next) == NULL) break; l1=l1->next; } - l2 = l1->next; + l2 = l1->next; l1->next = NULL; return fluid_list_sort_merge(fluid_list_sort(list, compare_func), @@ -220,7 +220,7 @@ fluid_list_last(fluid_list_t *list) return list; } -int +int fluid_list_size(fluid_list_t *list) { int n = 0; @@ -249,7 +249,7 @@ fluid_list_t* fluid_list_insert_at(fluid_list_t *list, int n, void* data) new_list->next = cur; if (prev) { - prev->next = new_list; + prev->next = new_list; return list; } else { return new_list; diff --git a/src/libs/fluidsynth/src/fluid_mdriver.c b/src/libs/fluidsynth/src/fluid_mdriver.c index 0c20bb86dc..c9d3886aee 100644 --- a/src/libs/fluidsynth/src/fluid_mdriver.c +++ b/src/libs/fluidsynth/src/fluid_mdriver.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -25,13 +25,13 @@ /* ALSA */ #if ALSA_SUPPORT fluid_midi_driver_t* new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, + handle_midi_event_func_t handler, void* event_handler_data); int 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, + handle_midi_event_func_t handler, void* event_handler_data); int delete_fluid_alsa_seq_driver(fluid_midi_driver_t* p); void fluid_alsa_seq_driver_settings(fluid_settings_t* settings); @@ -40,7 +40,7 @@ void fluid_alsa_seq_driver_settings(fluid_settings_t* settings); /* OSS */ #if OSS_SUPPORT fluid_midi_driver_t* new_fluid_oss_midi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, + handle_midi_event_func_t handler, void* event_handler_data); int delete_fluid_oss_midi_driver(fluid_midi_driver_t* p); void fluid_oss_midi_driver_settings(fluid_settings_t* settings); @@ -49,7 +49,7 @@ void fluid_oss_midi_driver_settings(fluid_settings_t* settings); /* Windows MIDI service */ #if WINMIDI_SUPPORT fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings, - handle_midi_event_func_t handler, + handle_midi_event_func_t handler, void* event_handler_data); int delete_fluid_winmidi_driver(fluid_midi_driver_t* p); #endif @@ -57,7 +57,7 @@ int delete_fluid_winmidi_driver(fluid_midi_driver_t* p); /* definitions for the MidiShare driver */ #if MIDISHARE_SUPPORT fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings, - void* event_handler_data, + void* event_handler_data, handle_midi_event_func_t handler); int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p); #endif @@ -69,8 +69,8 @@ int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p); */ struct fluid_mdriver_definition_t { char* name; - fluid_midi_driver_t* (*new)(fluid_settings_t* settings, - handle_midi_event_func_t event_handler, + fluid_midi_driver_t* (*new)(fluid_settings_t* settings, + handle_midi_event_func_t event_handler, void* event_handler_data); int (*free)(fluid_midi_driver_t* p); void (*settings)(fluid_settings_t* settings); @@ -79,31 +79,31 @@ struct fluid_mdriver_definition_t { struct fluid_mdriver_definition_t fluid_midi_drivers[] = { #if OSS_SUPPORT - { "oss", - new_fluid_oss_midi_driver, - delete_fluid_oss_midi_driver, + { "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, + { "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, + { "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, + { "winmidi", + new_fluid_winmidi_driver, + delete_fluid_winmidi_driver, NULL }, #endif #if MIDISHARE_SUPPORT - { "midishare", - new_fluid_midishare_midi_driver, - delete_fluid_midishare_midi_driver, + { "midishare", + new_fluid_midishare_midi_driver, + delete_fluid_midishare_midi_driver, NULL }, #endif { NULL, NULL, NULL, NULL } @@ -112,7 +112,7 @@ struct fluid_mdriver_definition_t fluid_midi_drivers[] = { void fluid_midi_driver_settings(fluid_settings_t* settings) -{ +{ int i; /* Set the default driver */ @@ -147,11 +147,18 @@ void fluid_midi_driver_settings(fluid_settings_t* settings) if (fluid_midi_drivers[i].settings != NULL) { fluid_midi_drivers[i].settings(settings); } - } + } } - +/** + * Create a new MIDI driver instance. + * @param settings Settings used to configure new MIDI driver. + * @param handler MIDI handler callback (for example: fluid_midi_router_handle_midi_event() + * for MIDI router) + * @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) { int i; @@ -171,6 +178,10 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_mi return NULL; } +/** + * Delete a MIDI driver instance. + * @param driver MIDI driver to delete + */ void delete_fluid_midi_driver(fluid_midi_driver_t* driver) { int i; @@ -180,5 +191,5 @@ void delete_fluid_midi_driver(fluid_midi_driver_t* driver) fluid_midi_drivers[i].free(driver); return; } - } + } } diff --git a/src/libs/fluidsynth/src/fluid_mdriver.h b/src/libs/fluidsynth/src/fluid_mdriver.h index 8d0dd2b013..f366efc453 100644 --- a/src/libs/fluidsynth/src/fluid_mdriver.h +++ b/src/libs/fluidsynth/src/fluid_mdriver.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -30,7 +30,7 @@ void fluid_midi_driver_settings(fluid_settings_t* settings); * fluid_midi_driver_t */ -struct _fluid_midi_driver_t +struct _fluid_midi_driver_t { char* name; handle_midi_event_func_t handler; diff --git a/src/libs/fluidsynth/src/fluid_midi.c b/src/libs/fluidsynth/src/fluid_midi.c index 04a6529a2d..5579b99f1d 100644 --- a/src/libs/fluidsynth/src/fluid_midi.c +++ b/src/libs/fluidsynth/src/fluid_midi.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -55,8 +55,12 @@ static int remains_80e0[] = { * * MIDIFILE */ -/* - * new_fluid_midi_file + +/** + * Open a MIDI file and return a new MIDI file handle. + * @internal + * @param filename Path of file to open. + * @return New MIDI file handle or NULL on error. */ fluid_midi_file* new_fluid_midi_file(char* filename) { @@ -76,7 +80,7 @@ fluid_midi_file* new_fluid_midi_file(char* filename) if (mf->fp == NULL) { FLUID_LOG(FLUID_ERR, "Couldn't open the MIDI file"); FLUID_FREE(mf); - return NULL; + return NULL; } if (fluid_midi_file_read_mthd(mf) != FLUID_OK) { @@ -86,8 +90,10 @@ fluid_midi_file* new_fluid_midi_file(char* filename) return mf; } -/* - * delete_fluid_midi_file +/** + * Delete a MIDI file handle. + * @internal + * @param mf MIDI file handle to close and free. */ void delete_fluid_midi_file(fluid_midi_file* mf) { @@ -102,7 +108,7 @@ void delete_fluid_midi_file(fluid_midi_file* mf) } /* - * fluid_midi_file_getc + * Get the next byte in a MIDI file. */ int fluid_midi_file_getc(fluid_midi_file* mf) { @@ -150,7 +156,7 @@ int fluid_midi_file_skip(fluid_midi_file* mf, int skip) int err = FLUID_FSEEK(mf->fp, skip, SEEK_CUR); if (err) { FLUID_LOG(FLUID_ERR, "Failed to seek position in file"); - return FLUID_FAILED; + return FLUID_FAILED; } return FLUID_OK; } @@ -289,7 +295,7 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int while (!fluid_midi_file_eot(mf)) { if (fluid_midi_file_read_event(mf, track) != FLUID_OK) { - return FLUID_FAILED; + return FLUID_FAILED; } } @@ -318,7 +324,7 @@ int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int * fluid_midi_file_read_varlen */ int fluid_midi_file_read_varlen(fluid_midi_file* mf) -{ +{ int i; int c; mf->varlen = 0; @@ -338,7 +344,7 @@ int fluid_midi_file_read_varlen(fluid_midi_file* mf) } else { mf->varlen += c; break; - } + } } return FLUID_OK; } @@ -382,7 +388,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) } fluid_midi_file_push(mf, status); status = mf->running_status; - } + } /* check what message we have */ if (status & 0x80) { @@ -426,7 +432,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) } return FLUID_OK; - + } else if (status == MIDI_META_EVENT) { /* meta events */ int result = FLUID_OK; @@ -498,7 +504,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) break; } mf->eot = 1; - break; + break; case MIDI_SET_TEMPO: if (mf->varlen != 3) { @@ -519,7 +525,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) evt->param1 = tempo; evt->param2 = 0; fluid_track_add_event(track, evt); - break; + break; case MIDI_SMPTE_OFFSET: if (mf->varlen != 5) { @@ -527,7 +533,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) result = FLUID_FAILED; break; } - break; /* we don't use smtp */ + break; /* we don't use smtp */ case MIDI_TIME_SIGNATURE: if (mf->varlen != 4) { @@ -540,7 +546,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) clocks = metadata[2]; notes = metadata[3]; - FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d", + FLUID_LOG(FLUID_DBG, "signature=%d/%d, metronome=%d, 32nd-notes=%d", nominator, denominator, clocks, notes); break; @@ -568,7 +574,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) } return result; - + } else { /* channel messages */ type = status & 0xf0; @@ -589,7 +595,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) } break; - case NOTE_OFF: + case NOTE_OFF: if ((param2 = fluid_midi_file_getc(mf)) < 0) { FLUID_LOG(FLUID_ERR, "Unexpected end of file"); return FLUID_FAILED; @@ -629,7 +635,7 @@ int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track) default: /* Can't possibly happen !? */ FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event"); - return FLUID_FAILED; + return FLUID_FAILED; } evt = new_fluid_midi_event(); if (evt == NULL) { @@ -660,8 +666,9 @@ int fluid_midi_file_get_division(fluid_midi_file* midifile) * fluid_track_t */ -/* - * new_fluid_midi_event +/** + * Create a MIDI event structure. + * @return New MIDI event structure or NULL when out of memory. */ fluid_midi_event_t* new_fluid_midi_event() { @@ -680,8 +687,10 @@ fluid_midi_event_t* new_fluid_midi_event() return evt; } -/* - * delete_fluid_midi_event +/** + * Delete MIDI event structure. + * @param evt MIDI event structure + * @return Always returns 0 */ int delete_fluid_midi_event(fluid_midi_event_t* evt) { @@ -696,16 +705,23 @@ int delete_fluid_midi_event(fluid_midi_event_t* evt) return FLUID_OK; } -/* - * fluid_midi_event_get_type +/** + * Get the event type field of a MIDI event structure. + * DOCME - Event type enum appears to be internal (fluid_midi.h) + * @param evt MIDI event structure + * @return Event type field */ int fluid_midi_event_get_type(fluid_midi_event_t* evt) { return evt->type; } -/* - * fluid_midi_event_set_type +/** + * Set the event type field of a MIDI event structure. + * DOCME - Event type enum appears to be internal (fluid_midi.h) + * @param evt MIDI event structure + * @param type Event type field + * @return Always returns 0 */ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type) { @@ -713,16 +729,21 @@ int fluid_midi_event_set_type(fluid_midi_event_t* evt, int type) return FLUID_OK; } -/* - * fluid_midi_event_get_channel +/** + * Get the channel field of a MIDI event structure. + * @param evt MIDI event structure + * @return Channel field */ int fluid_midi_event_get_channel(fluid_midi_event_t* evt) { return evt->channel; } -/* - * fluid_midi_event_set_channel +/** + * Set the channel field of a MIDI event structure. + * @param evt MIDI event structure + * @param chan MIDI channel field + * @return Always returns 0 */ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan) { @@ -730,16 +751,21 @@ int fluid_midi_event_set_channel(fluid_midi_event_t* evt, int chan) return FLUID_OK; } -/* - * fluid_midi_event_get_key +/** + * Get the key field of a MIDI event structure. + * @param evt MIDI event structure + * @return MIDI note number (0-127) */ int fluid_midi_event_get_key(fluid_midi_event_t* evt) { return evt->param1; } -/* - * fluid_midi_event_set_key +/** + * Set the key field of a MIDI event structure. + * @param evt MIDI event structure + * @param v MIDI note number (0-127) + * @return Always returns 0 */ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v) { @@ -747,16 +773,21 @@ int fluid_midi_event_set_key(fluid_midi_event_t* evt, int v) return FLUID_OK; } -/* - * fluid_midi_event_get_velocity +/** + * Get the velocity field of a MIDI event structure. + * @param evt MIDI event structure + * @return MIDI velocity number (0-127) */ int fluid_midi_event_get_velocity(fluid_midi_event_t* evt) { return evt->param2; } -/* - * fluid_midi_event_set_velocity +/** + * Set the velocity field of a MIDI event structure. + * @param evt MIDI event structure + * @param v MIDI velocity value + * @return Always returns 0 */ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v) { @@ -764,16 +795,21 @@ int fluid_midi_event_set_velocity(fluid_midi_event_t* evt, int v) return FLUID_OK; } -/* - * fluid_midi_event_get_control +/** + * Get the control number of a MIDI event structure. + * @param evt MIDI event structure + * @return MIDI control number */ int fluid_midi_event_get_control(fluid_midi_event_t* evt) { return evt->param1; } -/* - * fluid_midi_event_set_control +/** + * Set the control field of a MIDI event structure. + * @param evt MIDI event structure + * @param v MIDI control number + * @return Always returns 0 */ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v) { @@ -781,16 +817,21 @@ int fluid_midi_event_set_control(fluid_midi_event_t* evt, int v) return FLUID_OK; } -/* - * fluid_midi_event_get_value +/** + * Get the value field from a MIDI event structure. + * @param evt MIDI event structure + * @return Value field */ int fluid_midi_event_get_value(fluid_midi_event_t* evt) { return evt->param2; } -/* - * fluid_midi_event_set_value +/** + * Set the value field of a MIDI event structure. + * @param evt MIDI event structure + * @param v Value to assign + * @return Always returns 0 */ int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v) { @@ -798,22 +839,44 @@ int fluid_midi_event_set_value(fluid_midi_event_t* evt, int v) return FLUID_OK; } +/** + * Get the program field of a MIDI event structure. + * @param evt MIDI event structure + * @return MIDI program number (0-127) + */ int fluid_midi_event_get_program(fluid_midi_event_t* evt) { return evt->param1; } +/** + * Set the program field of a MIDI event structure. + * @param evt MIDI event structure + * @param val MIDI program number (0-127) + * @return Always returns 0 + */ int fluid_midi_event_set_program(fluid_midi_event_t* evt, int val) { evt->param1 = val; return FLUID_OK; } +/** + * Get the pitch field of a MIDI event structure. + * @param evt MIDI event structure + * @return Pitch value (DOCME units?) + */ int fluid_midi_event_get_pitch(fluid_midi_event_t* evt) { return evt->param1; } +/** + * Set the pitch field of a MIDI event structure. + * @param evt MIDI event structure + * @param val Pitch value (DOCME units?) + * @return Always returns 0 + */ int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int val) { evt->param1 = val; @@ -904,7 +967,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name) } if (name == NULL) { track->name = NULL; - return FLUID_OK; + return FLUID_OK; } len = FLUID_STRLEN(name); track->name = FLUID_MALLOC(len + 1); @@ -913,7 +976,7 @@ int fluid_track_set_name(fluid_track_t* track, char* name) return FLUID_FAILED; } FLUID_STRCPY(track->name, name); - return FLUID_OK; + return FLUID_OK; } /* @@ -995,7 +1058,7 @@ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track) /* * fluid_track_reset */ -int +int fluid_track_reset(fluid_track_t* track) { track->ticks = 0; @@ -1006,8 +1069,8 @@ fluid_track_reset(fluid_track_t* track) /* * fluid_track_send_events */ -int -fluid_track_send_events(fluid_track_t* track, +int +fluid_track_send_events(fluid_track_t* track, fluid_synth_t* synth, fluid_player_t* player, unsigned int ticks) @@ -1046,8 +1109,11 @@ fluid_track_send_events(fluid_track_t* track, * * fluid_player */ -/* - * new_fluid_player + +/** + * Create a new MIDI player. + * @param synth Fluid synthesizer instance to create player for + * @return New MIDI player instance or NULL on error (out of memory) */ fluid_player_t* new_fluid_player(fluid_synth_t* synth) { @@ -1075,8 +1141,10 @@ fluid_player_t* new_fluid_player(fluid_synth_t* synth) return player; } -/* - * delete_fluid_player +/** + * Delete a MIDI player instance. + * @param player MIDI player instance + * @return Always returns 0 */ int delete_fluid_player(fluid_player_t* player) { @@ -1157,7 +1225,7 @@ int fluid_player_load(fluid_player_t* player, char *filename) { fluid_midi_file* midifile; - midifile = new_fluid_midi_file(filename); + midifile = new_fluid_midi_file(filename); if (midifile == NULL) { return FLUID_FAILED; } @@ -1169,7 +1237,7 @@ int fluid_player_load(fluid_player_t* player, char *filename) return FLUID_FAILED; } delete_fluid_midi_file(midifile); - return FLUID_OK; + return FLUID_OK; } /* @@ -1217,9 +1285,9 @@ int fluid_player_callback(void* data, unsigned int msec) } player->cur_msec = msec; - player->cur_ticks = (player->start_ticks + + player->cur_ticks = (player->start_ticks + (int) ((double) (player->cur_msec - player->start_msec) / player->deltatime)); - + for (i = 0; i < player->ntracks; i++) { if (!fluid_track_eot(player->track[i])) { status = FLUID_PLAYER_PLAYING; @@ -1232,30 +1300,32 @@ int fluid_player_callback(void* data, unsigned int msec) player->status = status; if (player->status == FLUID_PLAYER_DONE) { - FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", + FLUID_LOG(FLUID_DBG, "%s: %d: Duration=%.3f sec", __FILE__, __LINE__, (msec - player->begin_msec) / 1000.0); - player->current_file = NULL; + player->current_file = NULL; } return 1; } -/* - * fluid_player_play +/** + * Activates play mode for a MIDI player if not already playing. + * @param player MIDI player instance + * @return 0 on success, -1 on failure */ int fluid_player_play(fluid_player_t* player) { if (player->status == FLUID_PLAYER_PLAYING) { return FLUID_OK; } - + if (player->playlist == NULL) { return FLUID_OK; } player->status = FLUID_PLAYER_PLAYING; - player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback, + player->timer = new_fluid_timer((int) player->deltatime, fluid_player_callback, (void*) player, 1, 0); if (player->timer == NULL) { return FLUID_FAILED; @@ -1263,8 +1333,10 @@ int fluid_player_play(fluid_player_t* player) return FLUID_OK; } -/* - * fluid_player_stop +/** + * Stops a MIDI player. + * @param player MIDI player instance + * @return Always returns 0 */ int fluid_player_stop(fluid_player_t* player) { @@ -1276,8 +1348,13 @@ int fluid_player_stop(fluid_player_t* player) return FLUID_OK; } -/* - * fluid_player_set_loop +/* FIXME - Looping seems to not actually be implemented? */ + +/** + * Enable looping of a MIDI player (DOCME - Does this actually work?) + * @param player MIDI player instance + * @param loop Value for looping (DOCME - What would this value be, boolean/time index?) + * @return Always returns 0 */ int fluid_player_set_loop(fluid_player_t* player, int loop) { @@ -1285,8 +1362,12 @@ int fluid_player_set_loop(fluid_player_t* player, int loop) return FLUID_OK; } -/* - * fluid_player_set_midi_tempo +/** + * Set the tempo of a MIDI player. + * @param player MIDI player instance + * @param tempo Tempo to set playback speed to (DOCME - Units?) + * @return Always returns 0 + * */ int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo) { @@ -1294,23 +1375,29 @@ int fluid_player_set_midi_tempo(fluid_player_t* player, int tempo) player->deltatime = (double) tempo / player->division / 1000.0; /* in milliseconds */ player->start_msec = player->cur_msec; player->start_ticks = player->cur_ticks; - - FLUID_LOG(FLUID_DBG,"tempo=%d, tick time=%f msec, cur time=%d msec, cur tick=%d", + + 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); return FLUID_OK; } -/* - * fluid_player_set_bpm +/** + * Set the tempo of a MIDI player in beats per minute. + * @param player MIDI player instance + * @param bpm Tempo in beats per minute + * @return Always returns 0 */ int fluid_player_set_bpm(fluid_player_t* player, int bpm) { return fluid_player_set_midi_tempo(player, (int)((double) 60 * 1e6 / bpm)); } -/* - * fluid_player_join +/** + * Wait for a MIDI player to terminate (when done playing). + * @param player MIDI player instance + * @return 0 on success, -1 otherwise + * */ int fluid_player_join(fluid_player_t* player) { @@ -1360,10 +1447,10 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne /* 'Process' system real-time messages */ /*********************************************************************/ /* There are not too many real-time messages that are of interest here. - * They can occur anywhere, even in the middle of a noteon message! + * They can occur anywhere, even in the middle of a noteon message! * Real-time range: 0xF8 .. 0xFF * Note: Real-time does not affect (running) status. - */ + */ if (c >= 0xF8){ if (c == MIDI_SYSTEM_RESET){ parser->event.type = c; @@ -1372,23 +1459,23 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne }; return NULL; }; - + /*********************************************************************/ /* 'Process' system common messages (again, just skip them) */ /*********************************************************************/ /* There are no system common messages that are of interest here. - * System common range: 0xF0 .. 0xF7 + * System common range: 0xF0 .. 0xF7 */ if (c > 0xF0){ - /* MIDI specs say: To ignore a non-real-time message, just discard all data up to - * the next status byte. + /* MIDI specs say: To ignore a non-real-time message, just discard all data up to + * the next status byte. * And our parser will ignore data that is received without a valid status. * Note: system common cancels running status. */ parser->status = 0; return NULL; }; - + /*********************************************************************/ /* Process voice category messages: */ /*********************************************************************/ @@ -1399,7 +1486,7 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne * as soon as a byte >= 0x80 comes in, we are dealing with a status byte * and start a new event. */ - + if (c & 0x80){ parser->channel = c & 0x0F; parser->status = c & 0xF0; @@ -1431,12 +1518,12 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne if (parser->nr_bytes < parser->nr_bytes_total){ return NULL; }; - + /*********************************************************************/ /* Send the event */ /*********************************************************************/ /* The event is ready-to-go. - * About 'running status': + * About 'running status': * The MIDI protocol has a built-in compression mechanism. If several similar events are sent * in-a-row, for example note-ons, then the event type is only sent once. For this case, * the last event type (status) is remembered. @@ -1459,14 +1546,14 @@ fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigne /* Pitch-bend is transmitted with 14-bit precision. */ parser->event.param1 = ((parser->p[1] << 7) | parser->p[0]); /* Note: '|' does here the same as '+' (no common bits), but might be faster */ break; - default: + default: /* Unlikely */ return NULL; }; return &parser->event; }; -/* Purpose: +/* Purpose: * Returns the length of the MIDI message starting with c. * Taken from Nagano Daisuke's USB-MIDI driver */ int fluid_midi_event_length(unsigned char event){ @@ -1525,5 +1612,3 @@ int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, fluid_mi } return FLUID_OK; } - - diff --git a/src/libs/fluidsynth/src/fluid_midi.h b/src/libs/fluidsynth/src/fluid_midi.h index 15ac14dd84..1fe556286a 100644 --- a/src/libs/fluidsynth/src/fluid_midi.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -161,14 +161,14 @@ enum midi_meta_event { MIDI_SEQUENCER_EVENT = 0x7f }; -enum fluid_player_status +enum fluid_player_status { FLUID_PLAYER_READY, FLUID_PLAYER_PLAYING, FLUID_PLAYER_DONE }; -enum fluid_driver_status +enum fluid_driver_status { FLUID_MIDI_READY, FLUID_MIDI_LISTENING, @@ -181,7 +181,7 @@ enum fluid_driver_status */ /* From ctype.h */ -#define fluid_isascii(c) (((c) & ~0x7f) == 0) +#define fluid_isascii(c) (((c) & ~0x7f) == 0) @@ -222,7 +222,7 @@ fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track); int fluid_track_get_duration(fluid_track_t* track); int fluid_track_reset(fluid_track_t* track); -int fluid_track_send_events(fluid_track_t* track, +int fluid_track_send_events(fluid_track_t* track, fluid_synth_t* synth, fluid_player_t* player, unsigned int ticks); @@ -273,7 +273,7 @@ typedef struct { int uses_smpte; unsigned int smpte_fps; unsigned int smpte_res; - unsigned int division; /* If uses_SMPTE == 0 then division is + unsigned int division; /* If uses_SMPTE == 0 then division is ticks per beat (quarter-note) */ double tempo; /* Beats per second (SI rules =) */ int tracklen; diff --git a/src/libs/fluidsynth/src/fluid_midi_router.c b/src/libs/fluidsynth/src/fluid_midi_router.c index 30a7e89dd7..f907f7f7de 100644 --- a/src/libs/fluidsynth/src/fluid_midi_router.c +++ b/src/libs/fluidsynth/src/fluid_midi_router.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -26,21 +26,29 @@ #include "fluid_synth.h" #include "fluid_io.h" -/* - * new_fluid_midi_router +/** + * Create a new midi router. + * @param settings Settings used to configure MIDI router + * @param handler MIDI event callback + * @param event_handler_data Caller defined data pointer which gets passed to 'handler' + * @return New MIDI router instance or NULL on error + * + * A midi handler connects to a midi input + * device and forwards incoming midi events to the synthesizer. */ -fluid_midi_router_t* +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; - fluid_midi_router_rule_t* rule=NULL;; + fluid_midi_router_rule_t* rule=NULL; + /* create the router */ router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){ FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; }; - - /* Clear the router, so that error_recovery can safely free all the rules. + + /* Clear the router, so that error_recovery can safely free all the rules. * Dump functions are also NULLed. */ FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t)); @@ -53,12 +61,12 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl router->event_handler=handler; router->event_handler_data=event_handler_data; - /* Create the default routing rules + /* Create the default routing rules * They accept events on any channel for any range of parameters, * and route them unchanged ("result=par*1.0+0") */ if (fluid_midi_router_create_default_rules(router) != FLUID_OK) goto error_recovery; - + return router; error_recovery: @@ -68,10 +76,12 @@ new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handl return NULL; } -/* - * delete_fluid_midi_router +/** + * Delete a MIDI router instance. + * @param router MIDI router to delete + * @return Always returns 0 */ -int +int delete_fluid_midi_router(fluid_midi_router_t* router) { if (router == NULL) { @@ -84,7 +94,7 @@ delete_fluid_midi_router(fluid_midi_router_t* router) /* * fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router) - * Purpose: + * Purpose: * Frees the used memory. This is used only for shutdown! */ void fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router){ @@ -127,7 +137,7 @@ fluid_midi_router_rule_t* new_fluid_midi_router_rule(void) /* * delete_fluid_midi_router_rule */ -int +int delete_fluid_midi_router_rule(fluid_midi_router_rule_t* rule) { FLUID_FREE(rule); @@ -139,7 +149,7 @@ int fluid_midi_router_create_default_rules(fluid_midi_router_t* router) { fluid_midi_router_rule_t** rules[6]; int i; - + rules[0]=&router->note_rules; rules[1]=&router->cc_rules; rules[2]=&router->progchange_rules; @@ -238,18 +248,22 @@ int fluid_midi_router_end(fluid_midi_router_t* router){ delete_fluid_midi_router_rule(rule); return FLUID_FAILED; }; - -/* - * fluid_midi_router_send_event + +/** + * Handle a MIDI event through a MIDI router instance. + * @param data MIDI router instance #fluid_midi_router_t (DOCME why is it a void *?) + * @param event MIDI event to handle + * @return 0 on success, -1 otherwise + * * Purpose: The midi router is called for each event, that is received * via the 'physical' midi input. Each event can trigger an arbitrary number * of generated events. - * + * * In default mode, a noteon event is just forwarded to the synth's 'noteon' function, * a 'CC' event to the synth's 'CC' function and so on. - * + * * The router can be used to - * - filter messages (for example: Pass sustain pedal CCs only to selected channels), + * - filter messages (for example: Pass sustain pedal CCs only to selected channels), * - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2), * - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...) * - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users @@ -258,7 +272,7 @@ int fluid_midi_router_end(fluid_midi_router_t* router){ * - get rid of aftertouch * - ... */ -int +int fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) { fluid_midi_router_t* router=(fluid_midi_router_t*)data; @@ -276,12 +290,12 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) if (event->type == NOTE_ON && event->param2 == 0) { /* Channel: Remains the same * Param 1: Note number, remains the same - * Param 2: release velocity), set to max + * Param 2: release velocity), set to max */ event->type = NOTE_OFF; event->param2=127; }; - + /* Lock the rules table, so that for example the shell thread doesn't * clear the rules we are just working with */ fluid_mutex_lock(router->ruletables_mutex); @@ -324,26 +338,26 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) default: break; } - + /* At this point 'rule' contains the first rule in a linked list. * Check for all rules, whether channel and parameter ranges match. */ - + while (rule){ int chan; /* Channel of the generated event */ int par1; /* par1 of the generated event */ - int par2=0; + int par2=0; int event_par1=(int)event->param1; int event_par2=(int)event->param2; fluid_midi_event_t new_event; - + /* Store the pointer to the next rule right now. If the rule is later flagged for destruction, * it may not be accessed anymore. */ next_rule=rule->next; - /* Check, whether the rule is still active. Expired rules cannot be removed immediately, - * because freeing memory in a realtime thread is no good idea. And the MIDI thread, + /* Check, whether the rule is still active. Expired rules cannot be removed immediately, + * because freeing memory in a realtime thread is no good idea. And the MIDI thread, * which calls us here, has raised priority.*/ if (rule->state == MIDIRULE_DONE){ goto do_next_rule; @@ -374,11 +388,11 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) goto do_next_rule; } }; - + /* 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) */ @@ -392,9 +406,9 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) }; }; }; - + /* Channel scaling / offset - * Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all + * 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); @@ -406,7 +420,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) 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); }; - + /* Channel range limiting */ if (chan < 0){ chan=0; @@ -437,7 +451,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) */ if ( - event->type == NOTE_ON + event->type == NOTE_ON || (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 >= 64) ){ /* Noteon or sustain pedal down event generated */ @@ -446,7 +460,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) rule->pending_events++; }; } else if ( - event->type == NOTE_OFF + event->type == NOTE_OFF || (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 < 64) ){ /* Noteoff or sustain pedal up event generated */ @@ -463,7 +477,7 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) /* There are no more pending events in the rule - all keys are up. * Change its state to 'unused', it will be cleared up at the next * opportunity to run 'free' safely. - * Note: After this, the rule may disappear at any time + * Note: After this, the rule may disappear at any time */ rule->state=MIDIRULE_DONE; }; @@ -477,9 +491,9 @@ fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event) goto do_next_rule; }; }; - + /* At this point it is decided, what is sent to the synth. - * Create a new event and make the appropriate call + * Create a new event and make the appropriate call */ fluid_midi_event_set_type(&new_event, event->type); @@ -516,8 +530,8 @@ int fluid_midi_router_handle_clear(fluid_synth_t* synth, int ac, char** av, flui if (ac != 0) { fluid_ostream_printf(out, "router_clear needs no arguments.\n"); goto error_recovery; - } - + } + /* Disable rules and mark for destruction */ fluid_midi_router_disable_all_rules(router); @@ -536,8 +550,8 @@ int fluid_midi_router_handle_default(fluid_synth_t* synth, int ac, char** av, fl if (ac != 0) { fluid_ostream_printf(out, "router_default needs no arguments.\n"); return -1; - } - + } + /* Disable rules and mark for destruction */ fluid_midi_router_disable_all_rules(router); @@ -564,7 +578,7 @@ int fluid_midi_router_handle_begin(fluid_synth_t* synth, int ac, char** av, flui fluid_ostream_printf(out, "router_begin needs no arguments.\n"); goto error_recovery; } - + if (FLUID_STRCMP(av[0],"note") == 0){ dest=& router->note_rules; } else if (FLUID_STRCMP(av[0],"cc") == 0){ @@ -578,12 +592,12 @@ int fluid_midi_router_handle_begin(fluid_synth_t* synth, int ac, char** av, flui } else if (FLUID_STRCMP(av[0],"kpress") == 0){ dest=& router->key_pressure_rules; }; - + if (dest == NULL){ fluid_ostream_printf(out, "router_begin args: note, cc, prog, pbend, cpress, kpress\n"); goto error_recovery; }; - + if (fluid_midi_router_begin(router, dest) != FLUID_OK){ goto error_recovery; }; @@ -609,8 +623,8 @@ int fluid_midi_router_handle_end(fluid_synth_t* synth, int ac, char** av, fluid_ if (fluid_midi_router_end(router) != FLUID_OK){ FLUID_LOG(FLUID_ERR, "midi_router_end failed"); goto error_recovery; - }; - + }; + /* Free unused rules (give it a try) */ fluid_midi_router_free_unused_rules(router); @@ -658,7 +672,7 @@ int fluid_midi_router_handle_par1(fluid_synth_t* synth, int ac, char** av, fluid router->new_rule_par1_add=atoi(av[3]); /* Free unused rules (give it a try) */ - fluid_midi_router_free_unused_rules(router); + fluid_midi_router_free_unused_rules(router); return 0; @@ -760,23 +774,23 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router) default: break; }; - + while (*p){ fluid_midi_router_rule_t* current_rule=*p; fluid_midi_router_rule_t* next_rule=current_rule->next; - + if (current_rule->state == MIDIRULE_DONE){ /* p points to current_rule. * current_rule->next points to next_rule. * Unlink current_rule from the chain by setting the content * of p to next_rule. */ - + *p=next_rule; - + /* Now the rule is not in the chain anymore. Destroy it. */ delete_fluid_midi_router_rule(current_rule); - + } else { /* We have to keep the rule, there is still unfinished business. */ p = ¤t_rule->next; @@ -785,48 +799,44 @@ void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router) fluid_mutex_unlock(router->ruletables_mutex); }; }; - -/* Purpose: - * This function demonstrates, how to access incoming MIDI messages. - * It prints a message to stdout (which can be used to hook up an external user interface), - * and hands the event on to the MIDI router. - * It is not a part of the MIDI router, but an added link in the MIDI chain. + +/** + * MIDI event callback function to display event information to stdout + * @param data MIDI router instance + * @param event MIDI event data + * @return 0 on success, -1 otherwise + * + * An implementation of the #handle_midi_event_func_t function type, used for + * 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) -{ +{ switch (event->type) { case NOTE_ON: - fprintf(stdout, "event_pre_noteon %i %i %i\n", + fprintf(stdout, "event_pre_noteon %i %i %i\n", event->channel, event->param1, event->param2); - fflush(stdout); break; case NOTE_OFF: - fprintf(stdout, "event_pre_noteoff %i %i %i\n", + fprintf(stdout, "event_pre_noteoff %i %i %i\n", event->channel, event->param1, event->param2); - fflush(stdout); - break; break; case CONTROL_CHANGE: - fprintf(stdout, "event_pre_cc %i %i %i\n", + fprintf(stdout, "event_pre_cc %i %i %i\n", event->channel, event->param1, event->param2); - fflush(stdout); break; case PROGRAM_CHANGE: - fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1); - fflush(stdout); + 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); - fflush(stdout); + 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); - fflush(stdout); break; case KEY_PRESSURE: - fprintf(stdout, "event_pre_kpress %i %i %i\n", + fprintf(stdout, "event_pre_kpress %i %i %i\n", event->channel, event->param1, event->param2); - fflush(stdout); break; default: break; @@ -834,30 +844,30 @@ int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event) return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event); }; -/* Purpose: - * This function demonstrates, how to access MIDI messages going from the MIDI - * router to the synth. - * Again, it prints a message to stdout and hands the event on to the synth. - * It is not a part of the MIDI router, but an added link in the MIDI chain. +/** + * MIDI event callback function to display event information to stdout + * @param data MIDI router instance + * @param event MIDI event data + * @return 0 on success, -1 otherwise + * + * An implementation of the #handle_midi_event_func_t function type, used for + * 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) { switch (event->type) { case NOTE_ON: - fprintf(stdout, "event_post_noteon %i %i %i\n", + fprintf(stdout, "event_post_noteon %i %i %i\n", event->channel, event->param1, event->param2); - fflush(stdout); break; case NOTE_OFF: - fprintf(stdout, "event_post_noteoff %i %i %i\n", + fprintf(stdout, "event_post_noteoff %i %i %i\n", event->channel, event->param1, event->param2); - fflush(stdout); - break; break; case CONTROL_CHANGE: - fprintf(stdout, "event_post_cc %i %i %i\n", + fprintf(stdout, "event_post_cc %i %i %i\n", event->channel, event->param1, event->param2); - fflush(stdout); break; case PROGRAM_CHANGE: fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1); @@ -869,7 +879,7 @@ int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event) 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", + fprintf(stdout, "event_post_kpress %i %i %i\n", event->channel, event->param1, event->param2); break; default: diff --git a/src/libs/fluidsynth/src/fluid_midi_router.h b/src/libs/fluidsynth/src/fluid_midi_router.h index 48ce003b45..4a1fce4a8a 100644 --- a/src/libs/fluidsynth/src/fluid_midi_router.h +++ b/src/libs/fluidsynth/src/fluid_midi_router.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -79,7 +79,7 @@ struct _fluid_midi_router_t { void* event_handler_data; /* One arg for the callback */ int nr_midi_channels; /* For clipping the midi channel */ - fluid_mutex_t ruletables_mutex; + fluid_mutex_t ruletables_mutex; }; struct _fluid_midi_router_rule_t { diff --git a/src/libs/fluidsynth/src/fluid_mod.c b/src/libs/fluidsynth/src/fluid_mod.c index dc91e429a8..c8839ab4e7 100644 --- a/src/libs/fluidsynth/src/fluid_mod.c +++ b/src/libs/fluidsynth/src/fluid_mod.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -25,56 +25,56 @@ /* * fluid_mod_clone */ -void +void fluid_mod_clone(fluid_mod_t* mod, 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->src1 = src->src1; + mod->flags1 = src->flags1; + mod->src2 = src->src2; + mod->flags2 = src->flags2; + mod->amount = src->amount; } /* * fluid_mod_set_source1 */ -void +void fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags) { - mod->src1 = src; - mod->flags1 = flags; + mod->src1 = src; + mod->flags1 = flags; } /* * fluid_mod_set_source2 */ -void +void fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags) { - mod->src2 = src; - mod->flags2 = flags; + mod->src2 = src; + mod->flags2 = flags; } /* * fluid_mod_set_dest */ -void +void fluid_mod_set_dest(fluid_mod_t* mod, int dest) { - mod->dest = dest; + mod->dest = dest; } /* * fluid_mod_set_amount */ -void +void fluid_mod_set_amount(fluid_mod_t* mod, double amount) { mod->amount = (double) amount; } -int fluid_mod_get_source1(fluid_mod_t* mod) +int fluid_mod_get_source1(fluid_mod_t* mod) { return mod->src1; } @@ -108,7 +108,7 @@ double fluid_mod_get_amount(fluid_mod_t* mod) /* * fluid_mod_get_value */ -fluid_real_t +fluid_real_t fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voice) { fluid_real_t v1 = 0.0, v2 = 1.0; @@ -117,9 +117,9 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic if (chan == NULL) { return 0.0f; } - + /* 'special treatment' for default controller - * + * * Reference: SF2.01 section 8.4.2 * * The GM default controller 'vel-to-filter cut off' is not clearly @@ -140,10 +140,10 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic * several SF2.1 sound fonts (where it is used only to turn it off). * */ if ((mod->src2 == FLUID_MOD_VELOCITY) && - (mod->src1 == FLUID_MOD_VELOCITY) && - (mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR + (mod->src1 == FLUID_MOD_VELOCITY) && + (mod->flags1 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE | FLUID_MOD_LINEAR)) && - (mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR + (mod->flags2 == (FLUID_MOD_GC | FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE | FLUID_MOD_SWITCH)) && (mod->dest == GEN_FILTERFC)) { if (voice->vel < 64){ @@ -152,37 +152,37 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic return (fluid_real_t) mod->amount * (127 - voice->vel) / 127; } } - + /* get the initial value of the first source */ if (mod->src1 > 0) { if (mod->flags1 & FLUID_MOD_CC) { v1 = fluid_channel_get_cc(chan, mod->src1); } else { /* source 1 is one of the direct controllers */ switch (mod->src1) { - case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */ + case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */ v1 = range1; break; - case FLUID_MOD_VELOCITY: + case FLUID_MOD_VELOCITY: v1 = voice->vel; break; - case FLUID_MOD_KEY: + case FLUID_MOD_KEY: v1 = voice->key; break; - case FLUID_MOD_KEYPRESSURE: + case FLUID_MOD_KEYPRESSURE: v1 = chan->key_pressure; break; - case FLUID_MOD_CHANNELPRESSURE: - v1 = chan->channel_pressure; + case FLUID_MOD_CHANNELPRESSURE: + v1 = chan->channel_pressure; break; - case FLUID_MOD_PITCHWHEEL: + case FLUID_MOD_PITCHWHEEL: v1 = chan->pitch_bend; range1 = 0x4000; break; - case FLUID_MOD_PITCHWHEELSENS: + case FLUID_MOD_PITCHWHEELSENS: v1 = chan->pitch_wheel_sensitivity; break; - default: - v1 = 0.0; + default: + v1 = 0.0; } } @@ -192,7 +192,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic v1 /= range1; break; case 1: /* linear, unipolar, negative */ - v1 = 1.0f - v1 / range1; + v1 = 1.0f - v1 / range1; break; case 2: /* linear, bipolar, positive */ v1 = -1.0f + 2.0f * v1 / range1; @@ -252,29 +252,29 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic v2 = fluid_channel_get_cc(chan, mod->src2); } else { switch (mod->src2) { - case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */ + case FLUID_MOD_NONE: /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */ v2 = range2; break; - case FLUID_MOD_VELOCITY: + case FLUID_MOD_VELOCITY: v2 = voice->vel; break; - case FLUID_MOD_KEY: + case FLUID_MOD_KEY: v2 = voice->key; break; - case FLUID_MOD_KEYPRESSURE: + case FLUID_MOD_KEYPRESSURE: v2 = chan->key_pressure; break; - case FLUID_MOD_CHANNELPRESSURE: - v2 = chan->channel_pressure; + case FLUID_MOD_CHANNELPRESSURE: + v2 = chan->channel_pressure; break; - case FLUID_MOD_PITCHWHEEL: + case FLUID_MOD_PITCHWHEEL: v2 = chan->pitch_bend; break; - case FLUID_MOD_PITCHWHEELSENS: + case FLUID_MOD_PITCHWHEELSENS: v2 = chan->pitch_wheel_sensitivity; break; - default: - v1 = 0.0f; + default: + v1 = 0.0f; } } @@ -284,7 +284,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic v2 /= range2; break; case 1: /* linear, unipolar, negative */ - v2 = 1.0f - v2 / range2; + v2 = 1.0f - v2 / range2; break; case 2: /* linear, bipolar, positive */ v2 = -1.0f + 2.0f * v2 / range2; @@ -340,12 +340,12 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic /* * fluid_mod_new */ -fluid_mod_t* +fluid_mod_t* fluid_mod_new() { fluid_mod_t* mod = FLUID_NEW(fluid_mod_t); if (mod == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } return mod; @@ -362,7 +362,7 @@ fluid_mod_delete(fluid_mod_t * mod) /* * fluid_mod_test_identity - */ + */ /* Purpose: * Checks, if two modulators are identical. * SF2.01 section 9.5.1 page 69, 'bullet' 3 defines 'identical'. @@ -384,7 +384,7 @@ void fluid_dump_modulator(fluid_mod_t * mod){ 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); @@ -408,8 +408,8 @@ void fluid_dump_modulator(fluid_mod_t * mod){ 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 ");}; + 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; diff --git a/src/libs/fluidsynth/src/fluid_mod.h b/src/libs/fluidsynth/src/fluid_mod.h index b24c62a2f0..31fb124618 100644 --- a/src/libs/fluidsynth/src/fluid_mod.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -25,7 +25,7 @@ #include "fluid_conv.h" void fluid_mod_clone(fluid_mod_t* mod, fluid_mod_t* src); -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); void fluid_dump_modulator(fluid_mod_t * mod); #define fluid_mod_has_source(mod,cc,ctrl) \ diff --git a/src/libs/fluidsynth/src/fluid_phase.h b/src/libs/fluidsynth/src/fluid_phase.h index 411fbfc0d2..59baa668ac 100644 --- a/src/libs/fluidsynth/src/fluid_phase.h +++ b/src/libs/fluidsynth/src/fluid_phase.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -37,141 +37,81 @@ #define FLUID_FRACT_MAX ((double)4294967296.0) -/* fluid_phase_t +/* fluid_phase_t * Purpose: * Playing pointer for voice playback -* +* * When a sample is played back at a different pitch, the playing pointer in the * source sample will not advance exactly one sample per output sample. * This playing pointer is implemented using fluid_phase_t. -* It is a 64 bit number. The higher 32 bits contain the 'index' (number of +* It is a 64 bit number. The higher 32 bits contain the 'index' (number of * the current sample), the lower 32 bits the fractional part. -* Access is possible in two ways: -* -through the 64 bit part 'b64', if the architecture supports 64 bit integers -* -through 'index' and 'fract' -* Note: b64 and index / fract share the same memory location! */ -typedef union { - struct{ - /* Note, that the two 32-bit ints form a 64-bit int! */ -#ifdef WORDS_BIGENDIAN - sint32 index; - uint32 fract; -#else - uint32 fract; - sint32 index; -#endif - } b32; -#ifdef USE_LONGLONG - long long b64; -#endif -} fluid_phase_t; +typedef unsigned long long fluid_phase_t; /* Purpose: * Set a to b. * a: fluid_phase_t * b: fluid_phase_t */ -#ifdef USE_LONGLONG #define fluid_phase_set(a,b) a=b; -#else -#define fluid_phase_set(a, b) { \ - (a).b32.fract = (b).b32.fract; \ - (a).b32.index = (b).b32.index; \ -} -#endif -#define fluid_phase_set_int(a, b) { \ - (a).b32.index = (sint32) (b); \ - (a).b32.fract = 0; \ -} +#define fluid_phase_set_int(a, b) ((a) = ((unsigned long long)(b)) << 32) /* Purpose: * Sets the phase a to a phase increment given in b. * For example, assume b is 0.9. After setting a to it, adding a to * the playing pointer will advance it by 0.9 samples. */ -#define fluid_phase_set_float(a, b) { \ - (a).b32.index = (sint32) (b); \ - (a).b32.fract = (uint32) (((double)(b) - (double)((a).b32.index)) * (double)FLUID_FRACT_MAX); \ -} +#define fluid_phase_set_float(a, b) \ + (a) = (((unsigned long long)(b)) << 32) \ + | (uint32) (((double)(b) - (int)(b)) * (double)FLUID_FRACT_MAX) + +/* create a fluid_phase_t from an index and a fraction value */ +#define fluid_phase_from_index_fract(index, fract) \ + ((((unsigned long long)(index)) << 32) + (fract)) /* Purpose: * Return the index and the fractional part, respectively. */ #define fluid_phase_index(_x) \ - ((int)(_x).b32.index) + ((unsigned int)((_x) >> 32)) #define fluid_phase_fract(_x) \ - ((_x).b32.fract) + ((uint32)((_x) & 0xFFFFFFFF)) + +/* Get the phase index with fractional rounding */ +#define fluid_phase_index_round(_x) \ + ((unsigned int)(((_x) + 0x80000000) >> 32)) + /* Purpose: * Takes the fractional part of the argument phase and * calculates the corresponding position in the interpolation table. * The fractional position of the playing pointer is calculated with a quite high - * resolution (32 bits). It would be unpractical to keep a set of interpolation + * resolution (32 bits). It would be unpractical to keep a set of interpolation * coefficients for each possible fractional part... */ #define fluid_phase_fract_to_tablerow(_x) \ - ((int)(((_x).b32.fract & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT)) + ((unsigned int)(fluid_phase_fract(_x) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT) #define fluid_phase_double(_x) \ - ((double)((_x).b32.index) + ((double)((_x).b32.fract) / FLUID_FRACT_MAX)) + ((double)(fluid_phase_index(_x)) + ((double)fluid_phase_fract(_x) / FLUID_FRACT_MAX)) /* Purpose: * Advance a by a step of b (both are fluid_phase_t). */ -#ifdef USE_LONGLONG -#define fluid_phase_incr(a, b) (a).b64 += (b).b64; -#else -/* The idea to use (a).index += (b).index + ((a).fract < (b).fract) to - handle wrap-arounds comes from Mozilla's macros to handle 64-bit - integer on 32-bit platforms. Header prlong.h in the NSPR - library. www.mozilla.org. */ -#define fluid_phase_incr(a, b) { \ - (a).b32.fract += (b).b32.fract; \ - (a).b32.index += (b).b32.index + ((a).b32.fract < (b).b32.fract); \ -} -#endif +#define fluid_phase_incr(a, b) a += b /* Purpose: * Subtract b from a (both are fluid_phase_t). */ -#ifdef USE_LONGLONG -#define fluid_phase_decr(a, b) a-=b; -#else -#define fluid_phase_decr(a, b) { \ - (a).b32.index -= b.b32.index - ((a).b32.fract < (b).b32.fract); \ - (a).b32.fract -= b.b32.fract; \ -} -#endif +#define fluid_phase_decr(a, b) a -= b /* Purpose: * Subtract b samples from a. */ -#define fluid_phase_sub_int(a, b) { (a).b32.index -= b; } - -#if 0 -#define fluid_phase_fract(_x) \ - ((fluid_real_t)((double)((_x).fract) / FLUID_FRACT_MAX)) - -#define fluid_phase_lt(a, b) \ - (((a).index < (b).index) || (((a).index == (b).index) && ((a).fract < (b).fract))) - -#define fluid_phase_gt(a, b) \ - (((a).index > (b).index) || (((a).index == (b).index) && ((a).fract > (b).fract))) - -#define fluid_phase_eq(a, b) \ - (((a).index == (b).index) && ((a).fract == (b).fract)) -#endif +#define fluid_phase_sub_int(a, b) ((a) -= (unsigned long long)(b) << 32) /* Purpose: - * The playing pointer is _phase. How many output samples are produced, until the point _p1 in the sample is reached, - * if _phase advances in steps of _incr? - */ -#define fluid_phase_steps(_phase,_index,_incr) \ - (int)(((double)(_index) - fluid_phase_double(_phase)) / (double)_incr) - -/* Purpose: - * Creates the expression a.index++. - * It is slightly different, when USE_LONGLONG is turned on. */ -#define fluid_phase_index_plusplus(a) (((a).b32.index)++) + * Creates the expression a.index++. */ +#define fluid_phase_index_plusplus(a) (((a) += 0x100000000LL) #endif /* _FLUID_PHASE_H */ diff --git a/src/libs/fluidsynth/src/fluid_ramsfont.c b/src/libs/fluidsynth/src/fluid_ramsfont.c index d705fb58e4..5df20eb59e 100644 --- a/src/libs/fluidsynth/src/fluid_ramsfont.c +++ b/src/libs/fluidsynth/src/fluid_ramsfont.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -21,7 +21,7 @@ #include "fluid_ramsfont.h" #include "fluid_sys.h" #include "fluid_synth.h" - + /* thenumber of samples before the start and after the end */ #define SAMPLE_LOOP_MARGIN 8 @@ -40,12 +40,12 @@ fluid_ramsfont_create_sfont() { fluid_sfont_t* sfont; fluid_ramsfont_t* ramsfont; - + ramsfont = new_fluid_ramsfont(); if (ramsfont == NULL) { return NULL; } - + sfont = FLUID_NEW(fluid_sfont_t); if (sfont == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); @@ -130,33 +130,35 @@ int fluid_ramsfont_sfont_iteration_next(fluid_sfont_t* sfont, fluid_preset_t* pr int fluid_rampreset_preset_delete(fluid_preset_t* preset) { FLUID_FREE(preset); - printf("TODO: free modulators\n"); + +/* TODO: free modulators */ + return 0; } char* 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); } int 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); } int 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); } int 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); } - + /*************************************************************** * * SFONT @@ -214,7 +216,7 @@ int delete_fluid_ramsfont(fluid_ramsfont_t* sfont) delete_fluid_rampreset(preset); preset = sfont->preset; } - + FLUID_FREE(sfont); return FLUID_OK; } @@ -242,7 +244,7 @@ fluid_ramsfont_set_name(fluid_ramsfont_t* sfont, char * name) * * Add a preset to the SoundFont */ -int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset) +int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset) { fluid_rampreset_t *cur, *prev; if (sfont->preset == NULL) { @@ -253,7 +255,7 @@ int fluid_ramsfont_add_preset(fluid_ramsfont_t* sfont, fluid_rampreset_t* preset cur = sfont->preset; prev = NULL; while (cur != NULL) { - if ((preset->bank < cur->bank) + if ((preset->bank < cur->bank) || ((preset->bank == cur->bank) && (preset->num < cur->num))) { if (prev == NULL) { preset->next = cur; @@ -285,7 +287,7 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont, - add the sample to the list of samples */ int err; - + fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); if (preset == NULL) { // Create it @@ -293,27 +295,27 @@ int fluid_ramsfont_add_izone(fluid_ramsfont_t* sfont, if (preset == NULL) { return FLUID_FAILED; } - + preset->bank = bank; preset->num = num; - + err = fluid_rampreset_add_sample(preset, sample, lokey, hikey); if (err != FLUID_OK) { return FLUID_FAILED; } - + // sort the preset fluid_ramsfont_add_preset(sfont, preset); - + } else { - + // just add it err = fluid_rampreset_add_sample(preset, sample, lokey, hikey); if (err != FLUID_OK) { return FLUID_FAILED; - } + } } - + sfont->sample = fluid_list_append(sfont->sample, sample); return FLUID_OK; } @@ -343,12 +345,12 @@ int fluid_ramsfont_remove_izone(fluid_ramsfont_t* sfont, int fluid_ramsfont_izone_set_gen(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num, fluid_sample_t* sample, int gen_type, float value) { - + fluid_rampreset_t* preset = fluid_ramsfont_get_preset(sfont, bank, num); if (preset == NULL) { return FLUID_FAILED; } - + return fluid_rampreset_izone_set_gen(preset, sample, gen_type, value); } @@ -360,14 +362,14 @@ int fluid_ramsfont_izone_set_loop(fluid_ramsfont_t* sfont, if (preset == NULL) { return FLUID_FAILED; } - + return fluid_rampreset_izone_set_loop(preset, sample, on, loopstart, loopend); } /* * fluid_ramsfont_get_preset */ -fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num) +fluid_rampreset_t* fluid_ramsfont_get_preset(fluid_ramsfont_t* sfont, unsigned int bank, unsigned int num) { fluid_rampreset_t* preset = sfont->preset; while (preset != NULL) { @@ -415,12 +417,12 @@ struct _fluid_rampreset_voice_t { /* * new_fluid_rampreset */ -fluid_rampreset_t* +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"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } preset->next = NULL; @@ -437,13 +439,13 @@ new_fluid_rampreset(fluid_ramsfont_t* sfont) /* * delete_fluid_rampreset */ -int +int delete_fluid_rampreset(fluid_rampreset_t* preset) { int err = FLUID_OK; fluid_preset_zone_t* zone; fluid_rampreset_voice_t *data; - + if (preset->global_zone != NULL) { if (delete_fluid_preset_zone(preset->global_zone) != FLUID_OK) { err = FLUID_FAILED; @@ -458,37 +460,37 @@ delete_fluid_rampreset(fluid_rampreset_t* preset) } 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); - + next = tmp->next; FLUID_FREE(tmp); tmp = next; } } preset->presetvoices = NULL; - + FLUID_FREE(preset); return err; } -int +int fluid_rampreset_get_banknum(fluid_rampreset_t* preset) { return preset->bank; } -int +int fluid_rampreset_get_num(fluid_rampreset_t* preset) { return preset->num; } -char* +char* fluid_rampreset_get_name(fluid_rampreset_t* preset) { return preset->name; @@ -497,7 +499,7 @@ fluid_rampreset_get_name(fluid_rampreset_t* preset) /* * fluid_rampreset_next */ -fluid_rampreset_t* +fluid_rampreset_t* fluid_rampreset_next(fluid_rampreset_t* preset) { return preset->next; @@ -507,7 +509,7 @@ fluid_rampreset_next(fluid_rampreset_t* preset) /* * fluid_rampreset_add_zone */ -int +int fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone) { if (preset->zone == NULL) { @@ -527,7 +529,7 @@ fluid_rampreset_add_zone(fluid_rampreset_t* preset, fluid_preset_zone_t* zone) int 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 */ - + /* one preset zone */ if (preset->zone == NULL) { fluid_preset_zone_t* zone; @@ -535,17 +537,17 @@ int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample 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); } - + /* add an instrument zone for each sample */ { fluid_inst_t* inst = fluid_preset_zone_get_inst(preset->zone); @@ -553,20 +555,20 @@ int fluid_rampreset_add_sample(fluid_rampreset_t* preset, fluid_sample_t* sample if (izone == NULL) { return FLUID_FAILED; } - + if (fluid_inst_add_zone(inst, izone) != FLUID_OK) { delete_fluid_inst_zone(izone); return FLUID_FAILED; } - + izone->sample = sample; izone->keylo = lokey; izone->keyhi = hikey; - + // give the preset the name of the sample FLUID_MEMCPY(preset->name, sample->name, 20); } - + return FLUID_OK; } @@ -574,9 +576,9 @@ fluid_inst_zone_t* fluid_rampreset_izoneforsample(fluid_rampreset_t* preset, flu { fluid_inst_t* inst; fluid_inst_zone_t* izone; - + if (preset->zone == NULL) return NULL; - + inst = fluid_preset_zone_get_inst(preset->zone); izone = inst->zone; while (izone) { @@ -591,17 +593,17 @@ int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sa int on, float loopstart, float loopend) { fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample); short coarse, fine; - + 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; } - + /* NOTE : We should check that (sample->startloop + loopStart <= sample->endloop - loopend - 32) */ /* loopstart */ @@ -645,12 +647,12 @@ int fluid_rampreset_izone_set_loop(fluid_rampreset_t* preset, fluid_sample_t* sa 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; } @@ -659,12 +661,12 @@ int fluid_rampreset_izone_set_gen(fluid_rampreset_t* preset, fluid_sample_t* sam fluid_inst_zone_t* izone = fluid_rampreset_izoneforsample(preset, sample); if (izone == NULL) return FLUID_FAILED; - + izone->gen[gen_type].flags = GEN_SET; izone->gen[gen_type].val = value; - + fluid_rampreset_updatevoices(preset, gen_type, value); - + return FLUID_OK; } @@ -672,7 +674,7 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp 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; @@ -694,7 +696,7 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp } if (!found) return FLUID_FAILED; - + // stop all the voices that use this sample, so that // the sample can be cleared up { @@ -719,23 +721,23 @@ int fluid_rampreset_remove_izone(fluid_rampreset_t* preset, fluid_sample_t* samp /* * fluid_rampreset_remembervoice */ -int +int fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) { /* stores the voice and the its ID in the preset for later update on gen_set */ fluid_rampreset_voice_t *presetvoice = FLUID_NEW(fluid_rampreset_voice_t); if (presetvoice == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return FLUID_FAILED; } - + 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; + FLUID_LOG(FLUID_ERR, "Out of memory"); + return FLUID_FAILED; } return FLUID_OK; } @@ -743,10 +745,10 @@ fluid_rampreset_remembervoice(fluid_rampreset_t* preset, fluid_voice_t* voice) { /* * fluid_rampreset_updatevoice */ -void +void fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) { 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 */ @@ -756,7 +758,7 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) if (!fluid_voice_is_playing(voice) || (fluid_voice_get_id(voice) != presetvoice->voiceID)) { /* forget it */ FLUID_FREE(presetvoice); - + /* unlink it */ next = tmp->next; FLUID_FREE(tmp); @@ -764,15 +766,15 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) prev->next = next; } else { preset->presetvoices = next; - } + } tmp = next; - + } else { - + /* update */ fluid_voice_gen_set(voice, gen_type, val); - fluid_voice_update_param(voice, gen_type); - + fluid_voice_update_param(voice, gen_type); + /* next */ prev = tmp; tmp = tmp->next; @@ -784,8 +786,8 @@ fluid_rampreset_updatevoices(fluid_rampreset_t* preset, int gen_type, float val) /* * fluid_rampreset_noteon */ -int -fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan, int key, int vel) +int +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; @@ -796,7 +798,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan 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) { @@ -804,45 +806,45 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan /* check if the note falls into the key and velocity range of this preset */ if (fluid_preset_zone_inside_range(preset_zone, key, vel)) { - + inst = fluid_preset_zone_get_inst(preset_zone); global_inst_zone = fluid_inst_get_global_zone(inst); - + /* 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 (fluid_sample_in_rom(sample) || (sample == NULL)) { inst_zone = fluid_inst_zone_next(inst_zone); continue; } - + /* check if the note falls into the key and velocity range of this instrument */ if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) { - + /* this is a good zone. allocate a new synthesis process and initialize it */ voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel); if (voice == NULL) { - return FLUID_FAILED; + return FLUID_FAILED; } - + if (fluid_rampreset_remembervoice(preset, voice) != FLUID_OK) { - return FLUID_FAILED; + return FLUID_FAILED; } - + z = inst_zone; - + /* Instrument level, generators */ - + for (i = 0; i < GEN_LAST; i++) { - /* SF 2.01 section 9.4 'bullet' 4: + /* SF 2.01 section 9.4 'bullet' 4: * * A generator in a local instrument zone supersedes a * global instrument zone generator. Both cases supersede @@ -852,7 +854,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan 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); + fluid_voice_gen_set(voice, i, global_inst_zone->gen[i].val); } else { /* The generator has not been defined in this instrument. @@ -861,7 +863,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan }; }; /* for all generators */ - + /* global instrument zone, modulators: Put them all into a * list. */ @@ -874,7 +876,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan mod = mod->next; }; }; - + /* local instrument zone, modulators. * Replace modulators with the same definition in the list: * SF 2.01 page 69, 'bullet' 8 @@ -893,7 +895,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan mod_list[i] = NULL; }; }; - + /* Finally add the new modulator to to the list. */ mod_list[mod_list_count++] = mod; mod = mod->next; @@ -918,12 +920,12 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan /* 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) + 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) @@ -946,8 +948,8 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan }; }; /* if available at preset level */ }; /* for all generators */ - - + + /* Global preset zone, modulators: put them all into a * list. */ mod_list_count = 0; @@ -963,12 +965,12 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan mod_list[i] = NULL; }; }; - + /* Finally add the new modulator to the list. */ mod_list[mod_list_count++] = mod; mod = mod->next; }; - + /* Add preset modulators (global / local) to the voice. */ for (i = 0; i < mod_list_count; i++){ mod = mod_list[i]; @@ -979,7 +981,7 @@ fluid_rampreset_noteon(fluid_rampreset_t* preset, fluid_synth_t* synth, int chan * page */ fluid_voice_add_mod(voice, mod, FLUID_VOICE_ADD); }; - }; + }; /* add the synthesis process to the synthesis loop. */ fluid_synth_start_voice(synth, voice); @@ -1029,18 +1031,18 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb /* 16 bit mono 44.1KHz data in */ /* in all cases, the sample has ownership of the data : it will release it in the end */ unsigned int storedNbFrames; - + /* in case we already have some data */ if (sample->data != NULL) { FLUID_FREE(sample->data); } - + if (copy_data) { - + /* nbframes should be >= 48 (SoundFont specs) */ storedNbFrames = nbframes; if (storedNbFrames < 48) storedNbFrames = 48; - + sample->data = FLUID_MALLOC(storedNbFrames*2 + 4*SAMPLE_LOOP_MARGIN); if (sample->data == NULL) { FLUID_LOG(FLUID_ERR, "Out of memory"); @@ -1054,7 +1056,7 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb FLUID_MEMCPY((char*)(sample->data) + 2*SAMPLE_LOOP_MARGIN + storedNbFrames*2, (char*)data, 2*SAMPLE_LOOP_MARGIN); FLUID_MEMCPY((char*)(sample->data), (char*)data + nbframes*2 - 2*SAMPLE_LOOP_MARGIN, 2*SAMPLE_LOOP_MARGIN); #endif - + /* pointers */ /* all from the start of data */ sample->start = SAMPLE_LOOP_MARGIN; @@ -1065,11 +1067,11 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb sample->start = 0; sample->end = nbframes; } - + /* only used as markers for the LOOP generators : set them on the first real frame */ sample->loopstart = sample->start; sample->loopend = sample->end; - + sample->samplerate = 44100; sample->origpitch = rootkey; sample->pitchadj = 0; @@ -1082,7 +1084,7 @@ fluid_sample_set_sound_data(fluid_sample_t* sample, short *data, unsigned int nb /* * new_fluid_ramsample */ -fluid_sample_t* +fluid_sample_t* new_fluid_ramsample() { /* same as new_fluid_sample. Only here so that it is exported */ @@ -1090,7 +1092,7 @@ new_fluid_ramsample() sample = FLUID_NEW(fluid_sample_t); if (sample == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } diff --git a/src/libs/fluidsynth/src/fluid_ramsfont.h b/src/libs/fluidsynth/src/fluid_ramsfont.h index 5ffb4ae403..0e28dbf434 100644 --- a/src/libs/fluidsynth/src/fluid_ramsfont.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA diff --git a/src/libs/fluidsynth/src/fluid_rev.c b/src/libs/fluidsynth/src/fluid_rev.c index a1a1c539bc..3f09b6d638 100644 --- a/src/libs/fluidsynth/src/fluid_rev.c +++ b/src/libs/fluidsynth/src/fluid_rev.c @@ -16,7 +16,7 @@ * REVERB */ -/* Denormalising: +/* Denormalising: * * According to music-dsp thread 'Denormalise', Pentium processors * have a hardware 'feature', that is of interest here, related to @@ -76,15 +76,15 @@ 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 +void fluid_allpass_setbuffer(fluid_allpass* allpass, fluid_real_t *buf, int size) { allpass->bufidx = 0; - allpass->buffer = buf; + allpass->buffer = buf; allpass->bufsize = size; } -void +void fluid_allpass_init(fluid_allpass* allpass) { int i; @@ -95,13 +95,13 @@ fluid_allpass_init(fluid_allpass* allpass) } } -void +void fluid_allpass_setfeedback(fluid_allpass* allpass, fluid_real_t val) { allpass->feedback = val; } -fluid_real_t +fluid_real_t fluid_allpass_getfeedback(fluid_allpass* allpass) { return allpass->feedback; @@ -151,16 +151,16 @@ 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, fluid_real_t *buf, int size) +void +fluid_comb_setbuffer(fluid_comb* comb, fluid_real_t *buf, int size) { comb->filterstore = 0; comb->bufidx = 0; - comb->buffer = buf; + comb->buffer = buf; comb->bufsize = size; } -void +void fluid_comb_init(fluid_comb* comb) { int i; @@ -171,27 +171,27 @@ fluid_comb_init(fluid_comb* comb) } } -void -fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val) +void +fluid_comb_setdamp(fluid_comb* comb, fluid_real_t val) { - comb->damp1 = val; + comb->damp1 = val; comb->damp2 = 1 - val; } -fluid_real_t -fluid_comb_getdamp(fluid_comb* comb) +fluid_real_t +fluid_comb_getdamp(fluid_comb* comb) { return comb->damp1; } -void -fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val) +void +fluid_comb_setfeedback(fluid_comb* comb, fluid_real_t val) { comb->feedback = val; } -fluid_real_t -fluid_comb_getfeedback(fluid_comb* comb) +fluid_real_t +fluid_comb_getfeedback(fluid_comb* comb) { return comb->feedback; } @@ -227,11 +227,11 @@ fluid_comb_getfeedback(fluid_comb* comb) #define numallpasses 4 #define fixedgain 0.015f #define scalewet 3.0f -#define scaledamp 0.4f +#define scaledamp 1.0f #define scaleroom 0.28f #define offsetroom 0.7f #define initialroom 0.5f -#define initialdamp 0.5f +#define initialdamp 0.2f #define initialwet 1 #define initialdry 0 #define initialwidth 1 @@ -275,7 +275,7 @@ struct _fluid_revmodel_t { fluid_real_t width; fluid_real_t gain; /* - The following are all declared inline + The following are all declared inline to remove the need for dynamic allocation with its subsequent error-checking messiness */ @@ -316,7 +316,7 @@ struct _fluid_revmodel_t { void fluid_revmodel_update(fluid_revmodel_t* rev); void fluid_revmodel_init(fluid_revmodel_t* rev); -fluid_revmodel_t* +fluid_revmodel_t* new_fluid_revmodel() { fluid_revmodel_t* rev; @@ -376,13 +376,13 @@ new_fluid_revmodel() return rev; } -void +void delete_fluid_revmodel(fluid_revmodel_t* rev) { FLUID_FREE(rev); } -void +void fluid_revmodel_init(fluid_revmodel_t* rev) { int i; @@ -396,14 +396,14 @@ fluid_revmodel_init(fluid_revmodel_t* rev) } } -void +void fluid_revmodel_reset(fluid_revmodel_t* rev) { fluid_revmodel_init(rev); } -void -fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, +void +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; @@ -412,7 +412,7 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, for (k = 0; k < FLUID_BUFSIZE; k++) { 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 @@ -438,10 +438,10 @@ fluid_revmodel_processreplace(fluid_revmodel_t* rev, fluid_real_t *in, 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, +void +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; @@ -450,7 +450,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, for (k = 0; k < FLUID_BUFSIZE; k++) { 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 @@ -478,7 +478,7 @@ fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, } } -void +void fluid_revmodel_update(fluid_revmodel_t* rev) { /* Recalculate internal values after parameter change */ @@ -491,6 +491,7 @@ fluid_revmodel_update(fluid_revmodel_t* rev) 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); @@ -503,7 +504,7 @@ fluid_revmodel_update(fluid_revmodel_t* rev) because as you develop the reverb model, you may wish to take dynamic action when they are called. */ -void +void fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value) { /* fluid_clip(value, 0.0f, 1.0f); */ @@ -511,13 +512,13 @@ fluid_revmodel_setroomsize(fluid_revmodel_t* rev, fluid_real_t value) fluid_revmodel_update(rev); } -fluid_real_t +fluid_real_t fluid_revmodel_getroomsize(fluid_revmodel_t* rev) { return (rev->roomsize - offsetroom) / scaleroom; } -void +void fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value) { /* fluid_clip(value, 0.0f, 1.0f); */ @@ -525,27 +526,27 @@ fluid_revmodel_setdamp(fluid_revmodel_t* rev, fluid_real_t value) fluid_revmodel_update(rev); } -fluid_real_t +fluid_real_t fluid_revmodel_getdamp(fluid_revmodel_t* rev) { return rev->damp / scaledamp; } -void +void fluid_revmodel_setlevel(fluid_revmodel_t* rev, fluid_real_t value) { -/* fluid_clip(value, 0.0f, 1.0f); */ -/* rev->wet = value * scalewet; */ -/* fluid_revmodel_update(rev); */ + fluid_clip(value, 0.0f, 1.0f); + rev->wet = value * scalewet; + fluid_revmodel_update(rev); } -fluid_real_t +fluid_real_t fluid_revmodel_getlevel(fluid_revmodel_t* rev) { return rev->wet / scalewet; } -void +void fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value) { /* fluid_clip(value, 0.0f, 1.0f); */ @@ -553,7 +554,7 @@ fluid_revmodel_setwidth(fluid_revmodel_t* rev, fluid_real_t value) fluid_revmodel_update(rev); } -fluid_real_t +fluid_real_t fluid_revmodel_getwidth(fluid_revmodel_t* rev) { return rev->width; diff --git a/src/libs/fluidsynth/src/fluid_rev.h b/src/libs/fluidsynth/src/fluid_rev.h index ddfbf728a2..1d0fd2ed40 100644 --- a/src/libs/fluidsynth/src/fluid_rev.h +++ b/src/libs/fluidsynth/src/fluid_rev.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -33,10 +33,10 @@ typedef struct _fluid_revmodel_t fluid_revmodel_t; fluid_revmodel_t* new_fluid_revmodel(void); void delete_fluid_revmodel(fluid_revmodel_t* rev); -void fluid_revmodel_processmix(fluid_revmodel_t* rev, fluid_real_t *in, +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, +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); diff --git a/src/libs/fluidsynth/src/fluid_seq.c b/src/libs/fluidsynth/src/fluid_seq.c index 7922b29d79..7a8dd85897 100644 --- a/src/libs/fluidsynth/src/fluid_seq.c +++ b/src/libs/fluidsynth/src/fluid_seq.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -19,14 +19,14 @@ */ - + /* 2002 : API design by Peter Hanappe and Antoine Schmitt August 2002 : Implementation by Antoine Schmitt as@gratin.org as part of the infiniteCD author project http://www.infiniteCD.org/ */ - + #include "fluid_event_priv.h" #include "fluidsynth_priv.h" // FLUID_NEW, etc #include "fluid_sys.h" // timer, threads, etc... @@ -82,11 +82,11 @@ int _fluid_seq_queue_process(void* data, unsigned int msec); // callback from ti /* API implementation */ -fluid_sequencer_t* +fluid_sequencer_t* new_fluid_sequencer() { fluid_sequencer_t* seq; - + seq = FLUID_NEW(fluid_sequencer_t); if (seq == NULL) { fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); @@ -99,7 +99,7 @@ new_fluid_sequencer() seq->startMs = fluid_curtime(); 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"); @@ -113,7 +113,7 @@ new_fluid_sequencer() _fluid_seq_queue_end(seq); FLUID_FREE(seq); fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); - return NULL; + return NULL; } seq->traceptr = seq->tracebuf; #endif @@ -121,16 +121,16 @@ new_fluid_sequencer() return(seq); } -void +void delete_fluid_sequencer(fluid_sequencer_t* seq) { - + if (seq == NULL) { return; } - + _fluid_seq_queue_end(seq); - + /* cleanup clients */ if (seq->clients) { fluid_list_t *tmp = seq->clients; @@ -142,9 +142,9 @@ delete_fluid_sequencer(fluid_sequencer_t* seq) delete_fluid_list(seq->clients); seq->clients = NULL; } - + #if FLUID_SEQ_WITH_TRACE - if (seq->tracebuf != NULL) + if (seq->tracebuf != NULL) FLUID_FREE(seq->tracebuf); seq->tracebuf = NULL; #endif @@ -161,7 +161,7 @@ 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_start (args, fmt); len = vsnprintf(seq->traceptr, remain, fmt, args); va_end (args); @@ -175,7 +175,7 @@ fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) seq->traceptr = seq->tracebuf + seq->tracelen; } } - + return; } @@ -198,12 +198,12 @@ void fluid_seq_dotrace(fluid_sequencer_t* seq, char *fmt, ...) {} /* clients */ -short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name, +short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name, fluid_event_callback_t callback, void* data) { 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"); @@ -215,16 +215,16 @@ short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name, fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); return -1; } - + seq->clientsID++; 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); } @@ -232,15 +232,15 @@ short fluid_sequencer_register_client(fluid_sequencer_t* seq, char* name, void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id) { fluid_list_t *tmp; - + if (seq->clients == NULL) return; - + tmp = seq->clients; while (tmp) { fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; - + if (client->id == id) { - if (client->name) + if (client->name) FLUID_FREE(client->name); seq->clients = fluid_list_remove_link(seq->clients, tmp); delete1_fluid_list(tmp); @@ -253,7 +253,7 @@ void fluid_sequencer_unregister_client(fluid_sequencer_t* seq, short id) int fluid_sequencer_count_clients(fluid_sequencer_t* seq) { - if (seq->clients == NULL) + if (seq->clients == NULL) return 0; return fluid_list_size(seq->clients); } @@ -274,17 +274,17 @@ short fluid_sequencer_get_client_id(fluid_sequencer_t* seq, int index) char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id) { fluid_list_t *tmp; - - if (seq->clients == NULL) + + if (seq->clients == NULL) return NULL; - + tmp = seq->clients; while (tmp) { fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; - + if (client->id == id) return client->name; - + tmp = tmp->next; } return NULL; @@ -293,16 +293,16 @@ char* fluid_sequencer_get_client_name(fluid_sequencer_t* seq, int id) int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id) { fluid_list_t *tmp; - + if (seq->clients == NULL) return 0; - + tmp = seq->clients; while (tmp) { fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; - + if (client->id == id) return (client->callback != NULL); - + tmp = tmp->next; } return 0; @@ -312,15 +312,15 @@ int fluid_sequencer_client_is_dest(fluid_sequencer_t* seq, int id) void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt) { short 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; - + if (dest->id == destID) { if (dest->callback) - (dest->callback)(fluid_sequencer_get_tick(seq), + (dest->callback)(fluid_sequencer_get_tick(seq), evt, seq, dest->data); return; } @@ -336,24 +336,24 @@ fluid_sequencer_send_at(fluid_sequencer_t* seq, fluid_event_t* evt, unsigned int /* set absolute */ if (!absolute) time = now + time; - + /* time stamp event */ fluid_event_set_time(evt, time); - + /* process late */ if (time < now) { fluid_sequencer_send_now(seq, evt); return 0; } - + /* process now */ if (time == now) { fluid_sequencer_send_now(seq, evt); return 0; } - + /* queue for processing later */ - return _fluid_seq_queue_pre_insert(seq, evt); + return _fluid_seq_queue_pre_insert(seq, evt); } void @@ -382,14 +382,14 @@ void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale) 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 (seq->scale != scale) { double oldScale = seq->scale; - + // stop timer if (seq->timer) { delete_fluid_timer(seq->timer); @@ -405,10 +405,10 @@ void fluid_sequencer_set_time_scale(fluid_sequencer_t* seq, double scale) { fluid_evt_entry* tmp; tmp = seq->preQueue; - while (tmp) { + while (tmp) { if (tmp->entryType == FLUID_EVT_ENTRY_INSERT) tmp->evt.time = tmp->evt.time*seq->scale/oldScale; - + tmp = tmp->next; } } @@ -434,7 +434,7 @@ double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq) /* The queue stores all future events to be processed. - + Data structures There is a heap, allocated at init time, for managing a pool @@ -455,33 +455,33 @@ double fluid_sequencer_get_time_scale(fluid_sequencer_t* seq) events is fast (below 65535 ticks, that is about 1 minute if 1 tick=1ms). Inserting later events is more slow, but this is a realtime engine, isn't it ? - + The queue0 starts at queue0StartTime. When 256 ticks have elapsed, the queue0 array is emptied, and the first cell of the queue1 array is expanded in the queue0 array, according to the time of each event. The queue1 array is shifted to the left, and the first events of the queueLater list are inserte in the last cell of the queue1 array. - + We remember the previously managed cell in queue0 in the prevCellNb variable. When processing the current cell, we process the events in between (late events). Functions - + The main thread functions first get an event entry from the heap, and copy the given event into it, then merely enqueue it in a preQueue. This is in order to protect the data structure: everything is managed in the callback (thread or interrupt, depending on the architecture). - + All queue data structure management is done in a timer callback: '_fluid_seq_queue_process'. The _fluid_seq_queue_process function first process the preQueue, inserting or removing event entrys from the queue, then processes the queue, by sending events ready to be sent at the current time. - + Critical sections between the main thread (or app) and the sequencer thread (or interrupt) are: @@ -530,11 +530,11 @@ _fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents) seq->queueLater = NULL; seq->queue0StartTime = fluid_sequencer_get_tick(seq); seq->prevCellNb = -1; - + fluid_mutex_init(seq->mutex); /* start timer */ - seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, + seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, (void *)seq, 1, 0); return (0); } @@ -546,7 +546,7 @@ _fluid_seq_queue_end(fluid_sequencer_t* seq) delete_fluid_timer(seq->timer); seq->timer = NULL; } - + if (seq->heap) { _fluid_evt_heap_free(seq->heap); seq->heap = NULL; @@ -572,11 +572,11 @@ _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt) fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); return -1; } - + evtentry->next = NULL; evtentry->entryType = FLUID_EVT_ENTRY_INSERT; FLUID_MEMCPY(&(evtentry->evt), evt, sizeof(fluid_event_t)); - + fluid_mutex_lock(seq->mutex); /* append to preQueue */ @@ -588,7 +588,7 @@ _fluid_seq_queue_pre_insert(fluid_sequencer_t* seq, fluid_event_t * evt) seq->preQueueLast = evtentry; fluid_mutex_unlock(seq->mutex); - + return (0); } @@ -604,7 +604,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t fluid_log(FLUID_PANIC, "sequencer: no more free events\n"); return; } - + evtentry->next = NULL; evtentry->entryType = FLUID_EVT_ENTRY_REMOVE; { @@ -614,7 +614,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t fluid_event_set_dest(evt, dest); evt->type = type; } - + fluid_mutex_lock(seq->mutex); /* append to preQueue */ @@ -624,7 +624,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t seq->preQueue = evtentry; } seq->preQueueLast = evtentry; - + fluid_mutex_unlock(seq->mutex); return; } @@ -632,7 +632,7 @@ _fluid_seq_queue_pre_remove(fluid_sequencer_t* seq, short src, short dest, int t /*********************** * callback from timer * (may be in a different thread, or in an interrupt) - * + * ***********************/ int _fluid_seq_queue_process(void* data, unsigned int msec) @@ -651,23 +651,23 @@ _fluid_seq_queue_process(void* data, unsigned int msec) seq->preQueueLast = NULL; fluid_mutex_unlock(seq->mutex); - + /* 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); } - + tmp = next; } - + /* send queued events */ _fluid_seq_queue_send_queued_events(seq); - + /* continue timer */ return 1; } @@ -680,7 +680,7 @@ _fluid_seq_queue_print_later(fluid_sequencer_t* seq) fluid_evt_entry* tmp = seq->queueLater; printf("queueLater:\n"); - + while (tmp) { unsigned int delay = tmp->evt.time - seq->queue0StartTime; printf("queueLater: Delay = %i\n", delay); @@ -720,19 +720,19 @@ _fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evt { fluid_evt_entry* prev; fluid_evt_entry* tmp; - unsigned int time = evtentry->evt.time; + unsigned int time = evtentry->evt.time; /* insert in 'queueLater', after the ones that have the same * time */ - + /* first? */ - if ((seq->queueLater == NULL) + 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 */ @@ -752,7 +752,7 @@ _fluid_seq_queue_insert_queue_later(fluid_sequencer_t* seq, fluid_evt_entry* evt /* last */ evtentry->next = NULL; - prev->next = evtentry; + prev->next = evtentry; } void @@ -760,43 +760,43 @@ _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 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 + 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; } } - + 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 + /* 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; } } - + delay = time - seq->queue0StartTime; - + 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 { _fluid_seq_queue_insert_queue0(seq, evtentry, delay); } @@ -806,21 +806,21 @@ int _fluid_seq_queue_matchevent(fluid_event_t* evt, int templType, short templSrc, short templDest) { int eventType; - + if (templSrc != -1 && templSrc != fluid_event_get_source(evt)) return 0; - + if (templDest != -1 && templDest != fluid_event_get_dest(evt)) return 0; - + if (templType == -1) return 1; - + eventType = fluid_event_get_type(evt); - + if (templType == eventType) return 1; - + if (templType == FLUID_SEQ_ANYCONTROLCHANGE) if (eventType == FLUID_SEQ_PITCHBEND || eventType == FLUID_SEQ_MODULATION || @@ -841,14 +841,14 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry /* we walk everything : this is slow, but that is life */ int i, type; short src, dest; - + 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); - + /* queue0 */ for (i = 0 ; i < 256 ; i++) { fluid_evt_entry* tmp = seq->queue0[i][0]; @@ -876,10 +876,10 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry } else { prev = tmp; tmp = prev->next; - } + } } } - + /* queue1 */ for (i = 0 ; i < 255 ; i++) { fluid_evt_entry* tmp = seq->queue1[i][0]; @@ -906,7 +906,7 @@ _fluid_seq_queue_remove_entries_matching(fluid_sequencer_t* seq, fluid_evt_entry } else { prev = tmp; tmp = prev->next; - } + } } } @@ -950,9 +950,9 @@ _fluid_seq_queue_send_cell_events(fluid_sequencer_t* seq, int cellNb) _fluid_seq_heap_set_free(seq->heap, tmp); tmp = next; - } + } seq->queue0[cellNb][0] = NULL; - seq->queue0[cellNb][1] = NULL; + seq->queue0[cellNb][1] = NULL; } void @@ -989,7 +989,7 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq) } seq->queue1[254][0] = NULL; seq->queue1[254][1] = NULL; - + /* append queueLater to queue1[254] */ count = 0; @@ -1003,9 +1003,9 @@ _fluid_seq_queue_slide(fluid_sequencer_t* seq) next = tmp->next; - /* append it */ + /* append it */ _fluid_seq_queue_insert_queue1(seq, tmp, 254); - tmp = next; + tmp = next; count++; } @@ -1024,14 +1024,14 @@ _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq) cellNb = 0; _fluid_seq_queue_slide(seq); } /* slide */ - - + + /* process queue0[cellNb] */ _fluid_seq_queue_send_cell_events(seq, cellNb); /* next cell */ cellNb++; } - + seq->prevCellNb = cellNb - 1; } diff --git a/src/libs/fluidsynth/src/fluid_seqbind.c b/src/libs/fluidsynth/src/fluid_seqbind.c index 542cdc63ce..3702d3f3d2 100644 --- a/src/libs/fluidsynth/src/fluid_seqbind.c +++ b/src/libs/fluidsynth/src/fluid_seqbind.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -28,7 +28,7 @@ */ #include "fluidsynth_priv.h" - + /*************************************************************** * * SEQUENCER BINDING @@ -47,17 +47,17 @@ short fluid_sequencer_register_fluidsynth(fluid_sequencer_t* seq, fluid_synth_t* void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data) { fluid_synth_t* synth = (fluid_synth_t *)data; - + 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_NOTEOFF: fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt)); break; - + case FLUID_SEQ_NOTE: { unsigned int dur; @@ -75,28 +75,28 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_ case FLUID_SEQ_ALLNOTESOFF: fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0); 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_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_PITCHBEND: fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt)); break; - + case FLUID_SEQ_PITCHWHHELSENS: fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); break; @@ -104,53 +104,53 @@ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_ 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: { short ctrl = 0x01; // MODULATION_MSB fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; - + case FLUID_SEQ_SUSTAIN: { short ctrl = 0x40; // SUSTAIN_SWITCH fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; - + case FLUID_SEQ_PAN: { short ctrl = 0x0A; // PAN_MSB fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; - + case FLUID_SEQ_VOLUME: { short ctrl = 0x07; // VOLUME_MSB fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; - + case FLUID_SEQ_REVERBSEND: { short ctrl = 0x5B; // EFFECTS_DEPTH1 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; - + case FLUID_SEQ_CHORUSSEND: { short ctrl = 0x5D; // EFFECTS_DEPTH3 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; - + case FLUID_SEQ_TIMER: /* nothing in fluidsynth */ break; - + default: break; } diff --git a/src/libs/fluidsynth/src/fluid_settings.c b/src/libs/fluidsynth/src/fluid_settings.c index 923c538dff..46dda0951a 100644 --- a/src/libs/fluidsynth/src/fluid_settings.c +++ b/src/libs/fluidsynth/src/fluid_settings.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -19,18 +19,21 @@ */ #include "fluidsynth_priv.h" -#include "fluid_settings.h" +#include "fluid_sys.h" #include "fluid_hash.h" -#include "fluid_strtok.h" #include "fluid_synth.h" #include "fluid_cmd.h" #include "fluid_adriver.h" #include "fluid_mdriver.h" +#include "fluid_settings.h" +/* 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_hash_delete(void* value, int type); -static int fluid_settings_tokenize(char* s, char* buf, char** ptr); +static int fluid_settings_tokenize(char* s, char *buf, char** ptr); typedef struct { @@ -42,7 +45,7 @@ typedef struct { void* data; } fluid_str_setting_t; -static fluid_str_setting_t* +static fluid_str_setting_t* new_fluid_str_setting(char* value, char* def, int hints, fluid_str_update_t fun, void* data) { fluid_str_setting_t* str; @@ -60,13 +63,20 @@ static void delete_fluid_str_setting(fluid_str_setting_t* str) { if (str) { if (str->value) { - FLUID_FREE(str->value); + FLUID_FREE(str->value); } if (str->def) { - FLUID_FREE(str->def); + FLUID_FREE(str->def); } if (str->options) { - delete_fluid_list(str->options); + fluid_list_t* list = str->options; + + while (list) { + FLUID_FREE (list->data); + list = fluid_list_next(list); + } + + delete_fluid_list(str->options); } FLUID_FREE(str); } @@ -86,7 +96,7 @@ typedef struct { } fluid_num_setting_t; -static fluid_num_setting_t* +static fluid_num_setting_t* new_fluid_num_setting(double min, double max, double def, int hints, fluid_num_update_t fun, void* data) { @@ -123,7 +133,7 @@ typedef struct { } fluid_int_setting_t; -static fluid_int_setting_t* +static fluid_int_setting_t* new_fluid_int_setting(int min, int max, int def, int hints, fluid_int_update_t fun, void* data) { @@ -189,37 +199,46 @@ void fluid_settings_init(fluid_settings_t* settings) fluid_midi_driver_settings(settings); } -static fluid_strtok_t* fluid_settings_strtok = NULL; - -int fluid_settings_tokenize(char* s, char* buf, char** ptr) +static int fluid_settings_tokenize(char* s, char *buf, char** ptr) { + char *tokstr, *tok; int n = 0; - FLUID_STRCPY(buf, s); - - if (fluid_settings_strtok == NULL) { - fluid_settings_strtok = new_fluid_strtok(buf, "."); - } else { - fluid_strtok_set(fluid_settings_strtok, buf, "."); + if (strlen (s) > MAX_SETTINGS_LABEL) + { + FLUID_LOG(FLUID_ERR, "Setting variable name exceeded max length of %d chars", + MAX_SETTINGS_LABEL); + return 0; } - while (fluid_strtok_has_more(fluid_settings_strtok)) { - ptr[n++] = fluid_strtok_next_token(fluid_settings_strtok); + 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; + } + + ptr[n++] = tok; } return n; } /** returns 1 if the value exists, 0 otherwise */ -static int fluid_settings_get(fluid_settings_t* settings, - char** name, int len, +static int fluid_settings_get(fluid_settings_t* settings, + char** name, int len, void** value, int* type) { fluid_hashtable_t* table = settings; int t; void* v; int n; - + for (n = 0; n < len; n++) { if (table == NULL) { @@ -244,10 +263,9 @@ static int fluid_settings_get(fluid_settings_t* settings, return 1; } - /** returns 1 if the value has been set, zero otherwise */ -static int fluid_settings_set(fluid_settings_t* settings, - char** name, int len, +static int fluid_settings_set(fluid_settings_t* settings, + char** name, int len, void* value, int type) { fluid_hashtable_t* table = settings; @@ -276,29 +294,29 @@ static int fluid_settings_set(fluid_settings_t* settings, } } - fluid_hashtable_replace(table, name[num], value, type); + fluid_hashtable_replace(table, name[num], value, type); return 1; } -/** returns 1 if the value has been resgister correctly, 0 +/** returns 1 if the value has been registered correctly, 0 otherwise */ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, int hints, fluid_str_update_t fun, void* data) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; fluid_str_setting_t* setting; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) { + if (!fluid_settings_get(settings, tokens, ntokens, &value, &type)) { setting = new_fluid_str_setting(def, def, hints, fun, data); return fluid_settings_set(settings, tokens, ntokens, setting, FLUID_STR_TYPE); - + } else { /* if variable already exists, don't change its value. */ if (type == FLUID_STR_TYPE) { @@ -317,14 +335,14 @@ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* de /** returns 1 if the value has been register correctly, zero otherwise */ -int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def, - double min, double max, int hints, +int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def, + double min, double max, int hints, fluid_num_update_t fun, void* data) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); @@ -357,14 +375,14 @@ int fluid_settings_register_num(fluid_settings_t* settings, char* name, double d /** returns 1 if the value has been register correctly, zero otherwise */ -int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def, - int min, int max, int hints, +int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def, + int min, int max, int hints, fluid_int_update_t fun, void* data) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); @@ -395,13 +413,12 @@ int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def, } } - int fluid_settings_get_type(fluid_settings_t* settings, char* name) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); @@ -409,13 +426,12 @@ int fluid_settings_get_type(fluid_settings_t* settings, char* name) return (fluid_settings_get(settings, tokens, ntokens, &value, &type))? type : FLUID_NO_TYPE; } - int fluid_settings_get_hints(fluid_settings_t* settings, char* name) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); @@ -439,8 +455,8 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); @@ -461,11 +477,10 @@ int fluid_settings_is_realtime(fluid_settings_t* settings, char* name) } } - int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str) { - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; int type; void* value; @@ -474,7 +489,7 @@ int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str) ntokens = fluid_settings_tokenize(name, buf, tokens); if (fluid_settings_get(settings, tokens, ntokens, &value, &type)) { - + if (type != FLUID_STR_TYPE) { return 0; } @@ -485,14 +500,14 @@ int fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str) FLUID_FREE(setting->value); } setting->value = str? FLUID_STRDUP(str) : NULL; - + if (setting->update) { (*setting->update)(setting->data, name, setting->value); } - + return 1; - } else { + } else { /* insert a new setting */ fluid_str_setting_t* setting; setting = new_fluid_str_setting(str, NULL, 0, NULL, NULL); @@ -504,13 +519,13 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_STR_TYPE)) { fluid_str_setting_t* setting = (fluid_str_setting_t*) value; *str = setting->value; @@ -520,18 +535,17 @@ int fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str) return 0; } - int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_STR_TYPE)) { fluid_str_setting_t* setting = (fluid_str_setting_t*) value; return FLUID_STRCMP(setting->value, s) == 0; @@ -539,19 +553,18 @@ int fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s) return 0; } - -char* +char* fluid_settings_getstr_default(fluid_settings_t* settings, char* name) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_STR_TYPE)) { fluid_str_setting_t* setting = (fluid_str_setting_t*) value; return setting->def; @@ -564,13 +577,13 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_STR_TYPE)) { fluid_str_setting_t* setting = (fluid_str_setting_t*) value; char* copy = FLUID_STRDUP(s); @@ -578,20 +591,20 @@ int fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s) return 1; } else { return 0; - } + } } int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_STR_TYPE)) { fluid_str_setting_t* setting = (fluid_str_setting_t*) value; @@ -600,6 +613,7 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s 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); return 1; } @@ -609,17 +623,16 @@ int fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s return 0; } else { return 0; - } + } } - int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val) { int type; void* value; fluid_num_setting_t* setting; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); @@ -631,22 +644,22 @@ int fluid_settings_setnum(fluid_settings_t* settings, char* name, double val) } setting = (fluid_num_setting_t*) value; - + if (val < setting->min) { val = setting->min; } else if (val > setting->max) { val = setting->max; } - + setting->value = val; - + if (setting->update) { (*setting->update)(setting->data, name, val); } - + return 1; - } else { + } else { /* insert a new setting */ fluid_num_setting_t* setting; setting = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL); @@ -659,13 +672,13 @@ int fluid_settings_getnum(fluid_settings_t* settings, char* name, double* val) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_NUM_TYPE)) { fluid_num_setting_t* setting = (fluid_num_setting_t*) value; *val = setting->value; @@ -679,13 +692,13 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double* { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_NUM_TYPE)) { fluid_num_setting_t* setting = (fluid_num_setting_t*) value; *min = setting->min; @@ -693,18 +706,18 @@ void fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double* } } -double +double fluid_settings_getnum_default(fluid_settings_t* settings, char* name) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_NUM_TYPE)) { fluid_num_setting_t* setting = (fluid_num_setting_t*) value; return setting->def; @@ -719,8 +732,8 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val) int type; void* value; fluid_int_setting_t* setting; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); @@ -732,22 +745,22 @@ int fluid_settings_setint(fluid_settings_t* settings, char* name, int val) } setting = (fluid_int_setting_t*) value; - + if (val < setting->min) { val = setting->min; } else if (val > setting->max) { val = setting->max; } - + setting->value = val; - + if (setting->update) { (*setting->update)(setting->data, name, val); } - + return 1; - } else { + } else { /* insert a new setting */ fluid_int_setting_t* setting; setting = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL); @@ -760,13 +773,13 @@ int fluid_settings_getint(fluid_settings_t* settings, char* name, int* val) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_INT_TYPE)) { fluid_int_setting_t* setting = (fluid_int_setting_t*) value; *val = setting->value; @@ -780,13 +793,13 @@ void fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* mi { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_INT_TYPE)) { fluid_int_setting_t* setting = (fluid_int_setting_t*) value; *min = setting->min; @@ -799,13 +812,13 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_INT_TYPE)) { fluid_int_setting_t* setting = (fluid_int_setting_t*) value; return setting->def; @@ -817,13 +830,13 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name) -void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* data, +void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* data, fluid_settings_foreach_option_t func) { int type; void* value; - char buf[1024]; - char* tokens[16]; + char* tokens[MAX_SETTINGS_TOKENS]; + char buf[MAX_SETTINGS_LABEL+1]; int ntokens; if (!func) { @@ -832,7 +845,7 @@ void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* ntokens = fluid_settings_tokenize(name, buf, tokens); - if (fluid_settings_get(settings, tokens, ntokens, &value, &type) + if (fluid_settings_get(settings, tokens, ntokens, &value, &type) && (type == FLUID_STR_TYPE)) { fluid_str_setting_t* setting = (fluid_str_setting_t*) value; @@ -843,7 +856,7 @@ void fluid_settings_foreach_option(fluid_settings_t* settings, char* name, void* (*func)(data, name, option); list = fluid_list_next(list); } - } + } } diff --git a/src/libs/fluidsynth/src/fluid_settings.h b/src/libs/fluidsynth/src/fluid_settings.h index d6d7dae5a7..198640d857 100644 --- a/src/libs/fluidsynth/src/fluid_settings.h +++ b/src/libs/fluidsynth/src/fluid_settings.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -42,13 +42,13 @@ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* de /** returns 0 if the value has been resgister correctly, non-zero otherwise */ -int fluid_settings_register_num(fluid_settings_t* settings, char* name, double min, double max, +int fluid_settings_register_num(fluid_settings_t* settings, char* name, double min, double max, double def, int hints, fluid_num_update_t fun, void* data); /** returns 0 if the value has been resgister correctly, non-zero otherwise */ -int fluid_settings_register_int(fluid_settings_t* settings, char* name, int min, int max, +int fluid_settings_register_int(fluid_settings_t* settings, char* name, int min, int max, int def, int hints, fluid_int_update_t fun, void* data); diff --git a/src/libs/fluidsynth/src/fluid_sfont.h b/src/libs/fluidsynth/src/fluid_sfont.h index e22910b993..57bddd9958 100644 --- a/src/libs/fluidsynth/src/fluid_sfont.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -61,7 +61,7 @@ #define fluid_sample_decr_ref(_sample) \ (_sample)->refcount--; \ if (((_sample)->refcount == 0) && ((_sample)->notify)) \ - (*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE); + (*(_sample)->notify)(_sample, FLUID_SAMPLE_DONE); diff --git a/src/libs/fluidsynth/src/fluid_sse.h b/src/libs/fluidsynth/src/fluid_sse.h deleted file mode 100644 index 84b958a852..0000000000 --- a/src/libs/fluidsynth/src/fluid_sse.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * sse.h - * Copyright (C) 1999 R. Fisher - * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. - * - * mpeg2dec is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpeg2dec 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 02111-1307 USA - */ - -/* Purpose: -* This file defines assembler macros for the SSE instructions of Pentium III and higher. -* They are used to execute several floating point multiplications in parallel. -*/ - - -#ifndef FLUID_SSE_H -#define FLUID_SSE_H -typedef union { - float sf[4]; /* Single-precision (32-bit) value */ -} __attribute__ ((aligned(16))) sse_t; /* On a 16 byte (128-bit) boundary */ - - -#define sse_i2r(op, imm, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (imm) ) - -#define sse_m2r(op, mem, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem)) - -#define sse_r2m(op, reg, mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=X" (mem) \ - : /* nothing */ ) - -#define sse_r2r(op, regs, regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) - -#define sse_r2ri(op, regs, regd, imm) \ - __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ - : /* nothing */ \ - : "X" (imm) ) - -#define sse_m2ri(op, mem, reg, subop) \ - __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ - : /* nothing */ \ - : "X" (mem)) - - -#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) -#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) -#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) - -#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) - -#define movups_m2r(var, reg) sse_m2r(movups, var, reg) -#define movups_r2m(reg, var) sse_r2m(movups, reg, var) -#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) - -#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) - -#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) - -#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) -#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) - -#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) -#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) - -#define movss_m2r(var, reg) sse_m2r(movss, var, reg) -#define movss_r2m(reg, var) sse_r2m(movss, reg, var) -#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) - -#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) -#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) - -#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) -#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) - -#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) -#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) - -#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) -#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) - -#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) -#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) - -#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - -#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - -#define movmskps(xmmreg, reg) \ - __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) - -#define addps_m2r(var, reg) sse_m2r(addps, var, reg) -#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) - -#define addss_m2r(var, reg) sse_m2r(addss, var, reg) -#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) - -#define subps_m2r(var, reg) sse_m2r(subps, var, reg) -#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) - -#define subss_m2r(var, reg) sse_m2r(subss, var, reg) -#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) - -#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) -#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) - -#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) -#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) - -#define divps_m2r(var, reg) sse_m2r(divps, var, reg) -#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) - -#define divss_m2r(var, reg) sse_m2r(divss, var, reg) -#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) - -#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) -#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) - -#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) -#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) - -#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) -#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) - -#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) -#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) - -#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) -#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) - -#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) -#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) - -#define andps_m2r(var, reg) sse_m2r(andps, var, reg) -#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) - -#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) -#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) - -#define orps_m2r(var, reg) sse_m2r(orps, var, reg) -#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) - -#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) -#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) - -#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) -#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) - -#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) -#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) - -#define minps_m2r(var, reg) sse_m2r(minps, var, reg) -#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) - -#define minss_m2r(var, reg) sse_m2r(minss, var, reg) -#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) - -#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) -#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) - -#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) -#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) - -#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) -#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) - -#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) -#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) - -#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) -#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) - -#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) -#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) - -#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) -#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) - -#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) -#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) - -#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) -#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) - -#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) -#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) - -#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) -#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) - -#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) -#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) - -#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) -#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) - -#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) -#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) - -#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) -#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) - -#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) -#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) - -#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) -#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) - -#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) -#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) - -#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) -#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) - -#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) -#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) - -#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) -#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) - -#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) -#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) - -#define fxrstor(mem) \ - __asm__ __volatile__ ("fxrstor %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define fxsave(mem) \ - __asm__ __volatile__ ("fxsave %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define stmxcsr(mem) \ - __asm__ __volatile__ ("stmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define ldmxcsr(mem) \ - __asm__ __volatile__ ("ldmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) -#endif diff --git a/src/libs/fluidsynth/src/fluid_strtok.c b/src/libs/fluidsynth/src/fluid_strtok.c deleted file mode 100644 index 6f115ca6fb..0000000000 --- a/src/libs/fluidsynth/src/fluid_strtok.c +++ /dev/null @@ -1,123 +0,0 @@ -/* FluidSynth - A Software Synthesizer - * - * Copyright (C) 2003 Peter Hanappe and others. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - - -#include "fluid_strtok.h" -#include "fluidsynth_priv.h" - -/* - * new_fluid_strtok - */ -fluid_strtok_t* new_fluid_strtok(char* s, char* d) -{ - fluid_strtok_t* st; - st = FLUID_NEW(fluid_strtok_t); - if (st == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); - return NULL; - } - /* Careful! the strings are not copied for speed */ - st->string = s; - st->delimiters = d; - st->offset = 0; - st->len = (s == NULL)? 0 : strlen(s); - return st; -} - -int delete_fluid_strtok(fluid_strtok_t* st) -{ - if (st == NULL) { - FLUID_LOG(FLUID_ERR, "Null pointer"); - return 0; - } - free(st); - return 0; -} - -int fluid_strtok_set(fluid_strtok_t* st, char* s, char* d) -{ - /* Careful! the strings are not copied for speed */ - st->string = s; - st->delimiters = d; - st->offset = 0; - st->len = (s == NULL)? 0 : strlen(s); - return 0; -} - -char* fluid_strtok_next_token(fluid_strtok_t* st) -{ - int start = st->offset; - int end; - if ((st == NULL) || (st->string == NULL) || (st->delimiters == NULL)) { - FLUID_LOG(FLUID_ERR, "Null pointer"); - return NULL; - } - if (start >= st->len) { - return NULL; - } - while (fluid_strtok_char_index(st->string[start], st->delimiters) >= 0) { - if (start == st->len) { - return NULL; - } - start++; - } - end = start + 1; - while (fluid_strtok_char_index(st->string[end], st->delimiters) < 0) { - if (end == st->len) { - break; - } - end++; - } - st->string[end] = 0; - st->offset = end + 1; - return &st->string[start]; -} - -int fluid_strtok_has_more(fluid_strtok_t* st) -{ - int cur = st->offset; - if ((st == NULL) || (st->string == NULL) || (st->delimiters == NULL)) { - FLUID_LOG(FLUID_ERR, "Null pointer"); - return -1; - } - while (cur < st->len) { - if (fluid_strtok_char_index(st->string[cur], st->delimiters) < 0) { - return -1; - } - cur++; - } - return 0; -} - -int fluid_strtok_char_index(char c, char* s) -{ - int i; - if (s == NULL) { - FLUID_LOG(FLUID_ERR, "Null pointer"); - return -1; - } - for (i = 0; s[i] != 0; i++) { - if (s[i] == c) { - return i; - } - } - return -1; -} - diff --git a/src/libs/fluidsynth/src/fluid_strtok.h b/src/libs/fluidsynth/src/fluid_strtok.h deleted file mode 100644 index 0764905848..0000000000 --- a/src/libs/fluidsynth/src/fluid_strtok.h +++ /dev/null @@ -1,44 +0,0 @@ -/* FluidSynth - A Software Synthesizer - * - * Copyright (C) 2003 Peter Hanappe and others. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307, USA - */ - - -#ifndef _FLUID_STRTOK_H -#define _FLUID_STRTOK_H - -#include "fluidsynth_priv.h" - - -/** string tokenizer */ -typedef struct { - char* string; - char* delimiters; - int offset; - int len; -} fluid_strtok_t; - -fluid_strtok_t* new_fluid_strtok(char* s, char* d); -int delete_fluid_strtok(fluid_strtok_t* st); -int fluid_strtok_set(fluid_strtok_t* st, char* s, char* d); -char* fluid_strtok_next_token(fluid_strtok_t* st); -int fluid_strtok_has_more(fluid_strtok_t* st); -int fluid_strtok_char_index(char c, char* s); - - -#endif /* _FLUID_STRTOK_H */ diff --git a/src/libs/fluidsynth/src/fluid_synth.c b/src/libs/fluidsynth/src/fluid_synth.c index 2baf4e5a1e..d8307d7bf5 100644 --- a/src/libs/fluidsynth/src/fluid_synth.c +++ b/src/libs/fluidsynth/src/fluid_synth.c @@ -11,13 +11,14 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ +#include #include "fluid_synth.h" #include "fluid_sys.h" @@ -26,6 +27,14 @@ #include "fluid_settings.h" #include "fluid_sfont.h" +#ifdef TRAP_ON_FPE +#define _GNU_SOURCE +#include + +/* seems to not be declared in fenv.h */ +extern int feenableexcept (int excepts); +#endif + fluid_sfloader_t* new_fluid_defsfloader(void); @@ -37,35 +46,36 @@ fluid_sfloader_t* new_fluid_defsfloader(void); * ************************************************************************/ -int fluid_synth_program_select2(fluid_synth_t* synth, - int chan, - char* sfont_name, - unsigned int bank_num, +int fluid_synth_program_select2(fluid_synth_t* synth, + int chan, + char* sfont_name, + unsigned int bank_num, unsigned int preset_num); fluid_sfont_t* fluid_synth_get_sfont_by_name(fluid_synth_t* synth, char *name); -int fluid_synth_set_gen2(fluid_synth_t* synth, int chan, - int param, float value, +int fluid_synth_set_gen2(fluid_synth_t* synth, int chan, + int param, float value, int absolute, int normalized); - + /*************************************************************** * * GLOBAL */ /* has the synth module been initialized? */ -static int fluid_synth_initialized = 0; +static int fluid_synth_initialized = 0; static void fluid_synth_init(void); +static void init_dither(void); /* default modulators * SF2.01 page 52 ff: * * There is a set of predefined default modulators. They have to be - * explicitly overridden by the sound font in order to turn them off. + * explicitly overridden by the sound font in order to turn them off. */ - + fluid_mod_t default_vel2att_mod; /* SF2.01 section 8.4.1 */ fluid_mod_t default_vel2filter_mod; /* SF2.01 section 8.4.2 */ fluid_mod_t default_at2viblfo_mod; /* SF2.01 section 8.4.3 */ @@ -80,11 +90,11 @@ fluid_mod_t default_pitch_bend_mod; /* SF2.01 section 8.4.10 */ /* reverb presets */ static 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 }, + { "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 }, { NULL, 0.0f, 0.0f, 0.0f, 0.0f } }; @@ -103,21 +113,21 @@ void fluid_synth_settings(fluid_settings_t* settings) fluid_settings_register_str(settings, "synth.chorus.active", "yes", 0, NULL, NULL); fluid_settings_register_str(settings, "synth.ladspa.active", "no", 0, NULL, NULL); - fluid_settings_register_int(settings, "synth.polyphony", + fluid_settings_register_int(settings, "synth.polyphony", 256, 16, 4096, 0, NULL, NULL); - fluid_settings_register_int(settings, "synth.midi-channels", + fluid_settings_register_int(settings, "synth.midi-channels", 16, 16, 256, 0, NULL, NULL); - fluid_settings_register_num(settings, "synth.gain", - 0.2f, 0.0f, 10.0f, + fluid_settings_register_num(settings, "synth.gain", + 0.2f, 0.0f, 10.0f, 0, NULL, NULL); - fluid_settings_register_int(settings, "synth.audio-channels", + fluid_settings_register_int(settings, "synth.audio-channels", 1, 1, 256, 0, NULL, NULL); - fluid_settings_register_int(settings, "synth.audio-groups", + fluid_settings_register_int(settings, "synth.audio-groups", 1, 1, 256, 0, NULL, NULL); - fluid_settings_register_int(settings, "synth.effects-channels", + fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0, NULL, NULL); - fluid_settings_register_num(settings, "synth.sample-rate", - 44100.0f, 22050.0f, 96000.0f, + fluid_settings_register_num(settings, "synth.sample-rate", + 44100.0f, 22050.0f, 96000.0f, 0, NULL, NULL); } @@ -145,23 +155,30 @@ char* fluid_version_str(void) * * Does all the initialization for this module. */ -static void +static void fluid_synth_init() { fluid_synth_initialized++; +#ifdef TRAP_ON_FPE + /* Turn on floating point exception traps */ + feenableexcept (FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID); +#endif + fluid_conversion_config(); - fluid_voice_config(); + fluid_dsp_float_config(); fluid_sys_config(); + init_dither(); + /* 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_CONCAVE /* Curve shape. Corresponds to 'type=1' */ | FLUID_MOD_UNIPOLAR /* Polarity. Corresponds to 'P=0' */ | FLUID_MOD_NEGATIVE /* Direction. Corresponds to 'D=1' */ ); @@ -171,10 +188,10 @@ fluid_synth_init() - /* SF2.01 page 53 section 8.4.2: MIDI Note-On Velocity to Filter Cutoff + /* 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 + * 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... */ @@ -184,10 +201,10 @@ fluid_synth_init() | FLUID_MOD_UNIPOLAR /* P=0 */ | FLUID_MOD_NEGATIVE /* D=1 */ ); - fluid_mod_set_source2(&default_vel2filter_mod, FLUID_MOD_VELOCITY, /* Index=2 */ + 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 */ + | FLUID_MOD_UNIPOLAR /* P=0 */ // do not remove | FLUID_MOD_NEGATIVE /* D=1 */ | FLUID_MOD_POSITIVE /* D=0 */ ); @@ -223,9 +240,9 @@ fluid_synth_init() /* SF2.01 page 55 section 8.4.5: MIDI continuous controller 7 to initial attenuation*/ - fluid_mod_set_source1(&default_att_mod, 7, /* index=7 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_CONCAVE /* type=1 */ + fluid_mod_set_source1(&default_att_mod, 7, /* index=7 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_CONCAVE /* type=1 */ | FLUID_MOD_UNIPOLAR /* P=0 */ | FLUID_MOD_NEGATIVE /* D=1 */ ); @@ -238,8 +255,8 @@ fluid_synth_init() /* SF2.01 page 55 section 8.4.6 MIDI continuous controller 10 to Pan Position */ fluid_mod_set_source1(&default_pan_mod, 10, /* index=10 */ FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_LINEAR /* type=0 */ - | FLUID_MOD_BIPOLAR /* P=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 */ @@ -247,13 +264,13 @@ fluid_synth_init() /* 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); + 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, 11, /* index=11 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_CONCAVE /* type=1 */ + fluid_mod_set_source1(&default_expr_mod, 11, /* index=11 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_CONCAVE /* type=1 */ | FLUID_MOD_UNIPOLAR /* P=0 */ | FLUID_MOD_NEGATIVE /* D=1 */ ); @@ -264,9 +281,9 @@ fluid_synth_init() /* SF2.01 page 55 section 8.4.8: MIDI continuous controller 91 to Reverb send */ - fluid_mod_set_source1(&default_reverb_mod, 91, /* index=91 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_LINEAR /* type=0 */ + fluid_mod_set_source1(&default_reverb_mod, 91, /* index=91 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_LINEAR /* type=0 */ | FLUID_MOD_UNIPOLAR /* P=0 */ | FLUID_MOD_POSITIVE /* D=0 */ ); @@ -277,9 +294,9 @@ fluid_synth_init() /* SF2.01 page 55 section 8.4.9: MIDI continuous controller 93 to Reverb send */ - fluid_mod_set_source1(&default_chorus_mod, 93, /* index=93 */ - FLUID_MOD_CC /* CC=1 */ - | FLUID_MOD_LINEAR /* type=0 */ + fluid_mod_set_source1(&default_chorus_mod, 93, /* index=93 */ + FLUID_MOD_CC /* CC=1 */ + | FLUID_MOD_LINEAR /* type=0 */ | FLUID_MOD_UNIPOLAR /* P=0 */ | FLUID_MOD_POSITIVE /* D=0 */ ); @@ -290,10 +307,10 @@ fluid_synth_init() /* 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_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_BIPOLAR /* P=1 */ | FLUID_MOD_POSITIVE /* D=0 */ ); fluid_mod_set_source2(&default_pitch_bend_mod, FLUID_MOD_PITCHWHEELSENS, /* Index = 16 */ @@ -301,7 +318,7 @@ fluid_synth_init() | 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 */ } @@ -320,7 +337,7 @@ int fluid_synth_verify_settings(fluid_settings_t *settings) /* * new_fluid_synth */ -fluid_synth_t* +fluid_synth_t* new_fluid_synth(fluid_settings_t *settings) { int i; @@ -337,11 +354,11 @@ new_fluid_synth(fluid_settings_t *settings) /* allocate a new synthesizer object */ synth = FLUID_NEW(fluid_synth_t); if (synth == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t)); - + fluid_mutex_init(synth->busy); synth->settings = settings; @@ -360,10 +377,10 @@ new_fluid_synth(fluid_settings_t *settings) fluid_settings_getnum(settings, "synth.gain", &synth->gain); /* register the callbacks */ - fluid_settings_register_num(settings, "synth.gain", - 0.2f, 0.0f, 10.0f, 0, + fluid_settings_register_num(settings, "synth.gain", + 0.2f, 0.0f, 10.0f, 0, (fluid_num_update_t) fluid_synth_update_gain, synth); - fluid_settings_register_int(settings, "synth.polyphony", + fluid_settings_register_int(settings, "synth.polyphony", synth->polyphony, 16, 4096, 0, (fluid_int_update_t) fluid_synth_update_polyphony, synth); @@ -374,27 +391,27 @@ new_fluid_synth(fluid_settings_t *settings) 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_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 (synth->audio_channels < 1) { - FLUID_LOG(FLUID_WARN, "Requested number of audio channels is smaller than 1. " - "Changing this setting to 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); + 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; } if (synth->audio_groups < 1) { - FLUID_LOG(FLUID_WARN, "Requested number of audio groups is smaller than 1. " - "Changing this setting to 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); + 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; } @@ -417,7 +434,7 @@ new_fluid_synth(fluid_settings_t *settings) /* Create and initialize the Fx unit.*/ synth->LADSPA_FxUnit = new_fluid_LADSPA_FxUnit(synth); #endif - + /* as soon as the synth is created it starts playing. */ synth->state = FLUID_SYNTH_PLAYING; synth->sfont = NULL; @@ -429,7 +446,7 @@ new_fluid_synth(fluid_settings_t *settings) loader = new_fluid_defsfloader(); if (loader == NULL) { - FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader"); + FLUID_LOG(FLUID_WARN, "Failed to create the default SoundFont loader"); } else { fluid_synth_add_sfloader(synth, loader); } @@ -437,7 +454,7 @@ new_fluid_synth(fluid_settings_t *settings) /* 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"); + FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_recovery; } for (i = 0; i < synth->midi_channels; i++) { @@ -460,109 +477,80 @@ new_fluid_synth(fluid_settings_t *settings) } } - /* Allocate the sample buffers - * - * GCC seems to have a bug with alignment (address must be multiple - * of 16 bytes. So we have to align for ourselves... As soon as - * GCC aligns reliably, this mess can be cleaned up. - */ - + /* Allocate the sample buffers */ synth->left_buf = NULL; synth->right_buf = NULL; - synth->left_ubuf = NULL; - synth->right_ubuf = NULL; synth->fx_left_buf = NULL; synth->fx_right_buf = NULL; - synth->fx_left_ubuf = NULL; - synth->fx_right_ubuf = NULL; /* Left and right audio buffers */ synth->left_buf = FLUID_ARRAY(fluid_real_t*, synth->nbuf); synth->right_buf = FLUID_ARRAY(fluid_real_t*, synth->nbuf); - synth->left_ubuf = FLUID_ARRAY(fluid_real_t*, synth->nbuf); - synth->right_ubuf = FLUID_ARRAY(fluid_real_t*, synth->nbuf); - if ((synth->left_buf == NULL) || (synth->right_buf == NULL) || - (synth->left_ubuf == NULL) || (synth->right_ubuf == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + if ((synth->left_buf == NULL) || (synth->right_buf == NULL)) { + FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_recovery; - } + } FLUID_MEMSET(synth->left_buf, 0, synth->nbuf * sizeof(fluid_real_t*)); FLUID_MEMSET(synth->right_buf, 0, synth->nbuf * sizeof(fluid_real_t*)); - FLUID_MEMSET(synth->left_ubuf, 0, synth->nbuf * sizeof(fluid_real_t*)); - FLUID_MEMSET(synth->right_ubuf, 0, synth->nbuf * sizeof(fluid_real_t*)); for (i = 0; i < synth->nbuf; i++) { - /* +4: add four floats for 16 added bytes */ + synth->left_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE); + synth->right_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE); - synth->left_ubuf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE + 4); - synth->right_ubuf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE + 4); - - if ((synth->left_ubuf[i] == NULL) || (synth->right_ubuf[i] == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + if ((synth->left_buf[i] == NULL) || (synth->right_buf[i] == NULL)) { + FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_recovery; - } - - synth->left_buf[i] = (fluid_real_t*) FLUID_ALIGN16BYTE(synth->left_ubuf[i]); - synth->right_buf[i] = (fluid_real_t*) FLUID_ALIGN16BYTE(synth->right_ubuf[i]); + } } /* Effects audio buffers */ synth->fx_left_buf = FLUID_ARRAY(fluid_real_t*, synth->effects_channels); synth->fx_right_buf = FLUID_ARRAY(fluid_real_t*, synth->effects_channels); - synth->fx_left_ubuf = FLUID_ARRAY(fluid_real_t*, synth->effects_channels); - synth->fx_right_ubuf = FLUID_ARRAY(fluid_real_t*, synth->effects_channels); - if ((synth->fx_left_buf == NULL) || (synth->fx_left_ubuf == NULL) || - (synth->fx_right_buf == NULL) || (synth->fx_right_ubuf == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + if ((synth->fx_left_buf == NULL) || (synth->fx_right_buf == NULL)) { + FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_recovery; - } + } - FLUID_MEMSET(synth->fx_left_ubuf, 0, 2 * sizeof(fluid_real_t*)); FLUID_MEMSET(synth->fx_left_buf, 0, 2 * sizeof(fluid_real_t*)); - FLUID_MEMSET(synth->fx_right_ubuf, 0, 2 * sizeof(fluid_real_t*)); FLUID_MEMSET(synth->fx_right_buf, 0, 2 * sizeof(fluid_real_t*)); for (i = 0; i < synth->effects_channels; i++) { + synth->fx_left_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE); + synth->fx_right_buf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE); - /* +4: add four floats for 16 added bytes */ - synth->fx_left_ubuf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE + 4); - synth->fx_right_ubuf[i] = FLUID_ARRAY(fluid_real_t, FLUID_BUFSIZE + 4); - - if ((synth->fx_left_ubuf[i] == NULL) || (synth->fx_right_ubuf[i] == NULL)) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + if ((synth->fx_left_buf[i] == NULL) || (synth->fx_right_buf[i] == NULL)) { + FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_recovery; - } - - synth->fx_left_buf[i] = (fluid_real_t*) FLUID_ALIGN16BYTE(synth->fx_left_ubuf[i]); - synth->fx_right_buf[i] = (fluid_real_t*) FLUID_ALIGN16BYTE(synth->fx_right_ubuf[i]); + } } synth->cur = FLUID_BUFSIZE; + synth->dither_index = 0; /* allocate the reverb module */ synth->reverb = new_fluid_revmodel(); if (synth->reverb == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_recovery; } - fluid_synth_set_reverb(synth, - FLUID_REVERB_DEFAULT_ROOMSIZE, - FLUID_REVERB_DEFAULT_DAMP, - FLUID_REVERB_DEFAULT_WIDTH, + fluid_synth_set_reverb(synth, + FLUID_REVERB_DEFAULT_ROOMSIZE, + FLUID_REVERB_DEFAULT_DAMP, + FLUID_REVERB_DEFAULT_WIDTH, FLUID_REVERB_DEFAULT_LEVEL); /* allocate the chorus module */ synth->chorus = new_fluid_chorus(synth->sample_rate); if (synth->chorus == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); goto error_recovery; } @@ -579,8 +567,8 @@ new_fluid_synth(fluid_settings_t *settings) /* * delete_fluid_synth */ -int -delete_fluid_synth(fluid_synth_t* synth) +int +delete_fluid_synth(fluid_synth_t* synth) { int i, k; fluid_list_t *list; @@ -596,6 +584,14 @@ delete_fluid_synth(fluid_synth_t* synth) synth->state = FLUID_SYNTH_STOPPED; + /* turn off all voices, needed to unload SoundFont data */ + if (synth->voice != NULL) { + for (i = 0; i < synth->nvoice; i++) { + if (synth->voice[i] && fluid_voice_is_playing (synth->voice[i])) + fluid_voice_off (synth->voice[i]); + } + } + /* delete all the SoundFonts */ for (list = synth->sfont; list; list = fluid_list_next(list)) { sfont = (fluid_sfont_t*) fluid_list_get(list); @@ -603,7 +599,7 @@ delete_fluid_synth(fluid_synth_t* synth) } delete_fluid_list(synth->sfont); - + /* and the SoundFont offsets */ for (list = synth->bank_offsets; list; list = fluid_list_next(list)) { bank_offset = (fluid_bank_offset_t*) fluid_list_get(list); @@ -611,10 +607,10 @@ delete_fluid_synth(fluid_synth_t* synth) } delete_fluid_list(synth->bank_offsets); - - + + /* 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); @@ -642,31 +638,40 @@ delete_fluid_synth(fluid_synth_t* synth) } /* free all the sample buffers */ - if (synth->left_ubuf != NULL) { + if (synth->left_buf != NULL) { for (i = 0; i < synth->nbuf; i++) { - if (synth->left_ubuf[i] != NULL) { - FLUID_FREE(synth->left_ubuf[i]); + if (synth->left_buf[i] != NULL) { + FLUID_FREE(synth->left_buf[i]); } } - FLUID_FREE(synth->left_ubuf); + FLUID_FREE(synth->left_buf); } - if (synth->right_ubuf != NULL) { + if (synth->right_buf != NULL) { for (i = 0; i < synth->nbuf; i++) { - if (synth->right_ubuf[i] != NULL) { - FLUID_FREE(synth->right_ubuf[i]); + if (synth->right_buf[i] != NULL) { + FLUID_FREE(synth->right_buf[i]); } } - FLUID_FREE(synth->right_ubuf); + FLUID_FREE(synth->right_buf); } - if (synth->fx_left_ubuf != NULL) { + if (synth->fx_left_buf != NULL) { for (i = 0; i < 2; i++) { - if (synth->fx_left_ubuf[i] != NULL) { - FLUID_FREE(synth->fx_left_ubuf[i]); + if (synth->fx_left_buf[i] != NULL) { + FLUID_FREE(synth->fx_left_buf[i]); } } - FLUID_FREE(synth->fx_left_ubuf); + FLUID_FREE(synth->fx_left_buf); + } + + if (synth->fx_right_buf != NULL) { + for (i = 0; i < 2; i++) { + if (synth->fx_right_buf[i] != NULL) { + FLUID_FREE(synth->fx_right_buf[i]); + } + } + FLUID_FREE(synth->fx_right_buf); } /* release the reverb module */ @@ -699,7 +704,7 @@ delete_fluid_synth(fluid_synth_t* synth) fluid_LADSPA_shutdown(synth->LADSPA_FxUnit); FLUID_FREE(synth->LADSPA_FxUnit); #endif - + fluid_mutex_destroy(synth->busy); FLUID_FREE(synth); @@ -713,7 +718,7 @@ delete_fluid_synth(fluid_synth_t* synth) * The error messages are not thread-save, yet. They are still stored * in a global message buffer (see fluid_sys.c). * */ -char* +char* fluid_synth_error(fluid_synth_t* synth) { return fluid_error(); @@ -722,8 +727,8 @@ fluid_synth_error(fluid_synth_t* synth) /* * fluid_synth_noteon */ -int -fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel) +int +fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel) { fluid_channel_t* channel; int r = FLUID_FAILED; @@ -744,14 +749,14 @@ fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel) /* make 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, - (float) synth->ticks / 44100.0f, + 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, + (float) synth->ticks / 44100.0f, (fluid_curtime() - synth->start) / 1000.0f, 0.0f, 0, "channel has no preset"); } return FLUID_FAILED; - } + } /* If there is another voice process on the same channel and key, advance it to the release phase. */ @@ -763,7 +768,7 @@ fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel) /* * fluid_synth_noteoff */ -int +int fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key) { int i; @@ -771,7 +776,7 @@ fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key) int status = FLUID_FAILED; /* fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread *\/ */ /* fluid_mutex_unlock(synth->busy); */ - + for (i = 0; i < synth->polyphony; i++) { voice = synth->voice[i]; if (_ON(voice) && (voice->chan == chan) && (voice->key == key)) { @@ -783,8 +788,8 @@ fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key) used_voices++; } } - FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d", - voice->chan, voice->key, 0, voice->id, + FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%.3f\t%.3f\t%d", + voice->chan, voice->key, 0, voice->id, (float) (voice->start_time + voice->ticks) / 44100.0f, (fluid_curtime() - synth->start) / 1000.0f, (float) voice->ticks / 44100.0f, @@ -800,7 +805,7 @@ fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key) /* * fluid_synth_damp_voices */ -int +int fluid_synth_damp_voices(fluid_synth_t* synth, int chan) { int i; @@ -823,7 +828,7 @@ fluid_synth_damp_voices(fluid_synth_t* synth, int chan) /* * fluid_synth_cc */ -int +int fluid_synth_cc(fluid_synth_t* synth, int chan, int num, int val) { /* fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread *\/ */ @@ -832,15 +837,15 @@ fluid_synth_cc(fluid_synth_t* synth, int chan, int num, int val) /* check the ranges of the arguments */ if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if ((num < 0) || (num >= 128)) { FLUID_LOG(FLUID_WARN, "Ctrl out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if ((val < 0) || (val >= 128)) { FLUID_LOG(FLUID_WARN, "Value out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if (synth->verbose) { @@ -862,13 +867,13 @@ fluid_synth_get_cc(fluid_synth_t* synth, int chan, int num, int* pval) /* check the ranges of the arguments */ if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if ((num < 0) || (num >= 128)) { FLUID_LOG(FLUID_WARN, "Ctrl out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } - + *pval = synth->channel[chan]->cc[num]; return FLUID_OK; } @@ -916,7 +921,7 @@ fluid_synth_all_sounds_off(fluid_synth_t* synth, int chan) /* * fluid_synth_system_reset * - * Purpose: + * Purpose: * Respond to the MIDI command 'system reset' (0xFF, big red 'panic' button) */ int @@ -948,7 +953,7 @@ fluid_synth_system_reset(fluid_synth_t* synth) * tell all synthesis processes on this channel to update their * synthesis parameters after a control change. */ -int +int fluid_synth_modulate_voices(fluid_synth_t* synth, int chan, int is_cc, int ctrl) { int i; @@ -973,7 +978,7 @@ fluid_synth_modulate_voices(fluid_synth_t* synth, int chan, int is_cc, int ctrl) * synthesis parameters after an all control off message (i.e. all * controller have been reset to their default value). */ -int +int fluid_synth_modulate_voices_all(fluid_synth_t* synth, int chan) { int i; @@ -994,7 +999,7 @@ fluid_synth_modulate_voices_all(fluid_synth_t* synth, int chan) /* * fluid_synth_pitch_bend */ -int +int fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val) { @@ -1004,7 +1009,7 @@ fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val) /* check the ranges of the arguments */ if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if (synth->verbose) { @@ -1026,9 +1031,9 @@ fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend) /* check the ranges of the arguments */ if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } - + *ppitch_bend = synth->channel[chan]->pitch_bend; return FLUID_OK; } @@ -1036,14 +1041,14 @@ fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend) /* * Fluid_synth_pitch_wheel_sens */ -int +int fluid_synth_pitch_wheel_sens(fluid_synth_t* synth, int chan, int val) { /* check the ranges of the arguments */ if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if (synth->verbose) { @@ -1064,14 +1069,14 @@ fluid_synth_pitch_wheel_sens(fluid_synth_t* synth, int chan, int val) * version of fluidsynth. Maybe v2.0 ? -- Antoine Schmitt May 2003 */ -int +int fluid_synth_get_pitch_wheel_sens(fluid_synth_t* synth, int chan, int* pval) { // check the ranges of the arguments if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } // get the pitch-bend value in the channel @@ -1084,7 +1089,7 @@ fluid_synth_get_pitch_wheel_sens(fluid_synth_t* synth, int chan, int* pval) * fluid_synth_get_preset */ fluid_preset_t* -fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum, +fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum, unsigned int banknum, unsigned int prognum) { fluid_preset_t* preset = NULL; @@ -1093,7 +1098,7 @@ fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum, int offset; sfont = fluid_synth_get_sfont_by_id(synth, sfontnum); - + if (sfont != NULL) { offset = fluid_synth_get_bank_offset(synth, sfontnum); preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum); @@ -1108,7 +1113,7 @@ fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum, * fluid_synth_get_preset2 */ fluid_preset_t* -fluid_synth_get_preset2(fluid_synth_t* synth, char* sfont_name, +fluid_synth_get_preset2(fluid_synth_t* synth, char* sfont_name, unsigned int banknum, unsigned int prognum) { fluid_preset_t* preset = NULL; @@ -1116,7 +1121,7 @@ fluid_synth_get_preset2(fluid_synth_t* synth, char* sfont_name, int offset; sfont = fluid_synth_get_sfont_by_name(synth, sfont_name); - + if (sfont != NULL) { offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont)); preset = fluid_sfont_get_preset(sfont, banknum - offset, prognum); @@ -1127,8 +1132,8 @@ fluid_synth_get_preset2(fluid_synth_t* synth, char* sfont_name, return NULL; } -fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, - unsigned int banknum, +fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, + unsigned int banknum, unsigned int prognum) { fluid_preset_t* preset = NULL; @@ -1146,7 +1151,7 @@ fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, preset->sfont = sfont; /* FIXME */ return preset; } - + list = fluid_list_next(list); } @@ -1157,7 +1162,7 @@ fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, /* * fluid_synth_program_change */ -int +int fluid_synth_program_change(fluid_synth_t* synth, int chan, int prognum) { fluid_preset_t* preset = NULL; @@ -1236,8 +1241,8 @@ int fluid_synth_sfont_select(fluid_synth_t* synth, int chan, unsigned int sfont_ /* * fluid_synth_get_program */ -int -fluid_synth_get_program(fluid_synth_t* synth, int chan, +int +fluid_synth_get_program(fluid_synth_t* synth, int chan, unsigned int* sfont_id, unsigned int* bank_num, unsigned int* preset_num) { fluid_channel_t* channel; @@ -1254,10 +1259,10 @@ fluid_synth_get_program(fluid_synth_t* synth, int chan, /* * fluid_synth_program_select */ -int fluid_synth_program_select(fluid_synth_t* synth, - int chan, - unsigned int sfont_id, - unsigned int bank_num, +int fluid_synth_program_select(fluid_synth_t* synth, + int chan, + unsigned int sfont_id, + unsigned int bank_num, unsigned int preset_num) { fluid_preset_t* preset = NULL; @@ -1271,12 +1276,12 @@ int fluid_synth_program_select(fluid_synth_t* synth, 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", + 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); return FLUID_FAILED; } - + /* inform the channel of the new bank and program number */ fluid_channel_set_sfontnum(channel, sfont_id); fluid_channel_set_banknum(channel, bank_num); @@ -1290,10 +1295,10 @@ int fluid_synth_program_select(fluid_synth_t* synth, /* * fluid_synth_program_select2 */ -int fluid_synth_program_select2(fluid_synth_t* synth, - int chan, - char* sfont_name, - unsigned int bank_num, +int fluid_synth_program_select2(fluid_synth_t* synth, + int chan, + char* sfont_name, + unsigned int bank_num, unsigned int preset_num) { fluid_preset_t* preset = NULL; @@ -1316,8 +1321,8 @@ int fluid_synth_program_select2(fluid_synth_t* synth, offset = fluid_synth_get_bank_offset(synth, fluid_sfont_get_id(sfont)); preset = fluid_sfont_get_preset(sfont, bank_num - offset, preset_num); if (preset == NULL) { - FLUID_LOG(FLUID_ERR, - "There is no preset with bank number %d and preset number %d in SoundFont %s", + 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); return FLUID_FAILED; } @@ -1342,10 +1347,10 @@ void fluid_synth_update_presets(fluid_synth_t* synth) for (chan = 0; chan < synth->midi_channels; chan++) { channel = synth->channel[chan]; - fluid_channel_set_preset(channel, - fluid_synth_get_preset(synth, - fluid_channel_get_sfontnum(channel), - fluid_channel_get_banknum(channel), + fluid_channel_set_preset(channel, + fluid_synth_get_preset(synth, + fluid_channel_get_sfontnum(channel), + fluid_channel_get_banknum(channel), fluid_channel_get_prognum(channel))); } } @@ -1354,7 +1359,7 @@ void fluid_synth_update_presets(fluid_synth_t* synth) /* * fluid_synth_update_gain */ -int fluid_synth_update_gain(fluid_synth_t* synth, char* name, double value) +int fluid_synth_update_gain(fluid_synth_t* synth, char* name, double value) { fluid_synth_set_gain(synth, (float) value); return 0; @@ -1371,7 +1376,7 @@ void fluid_synth_set_gain(fluid_synth_t* synth, float gain) synth->gain = gain; for (i = 0; i < synth->polyphony; i++) { - fluid_voice_t* voice = synth->voice[i]; + fluid_voice_t* voice = synth->voice[i]; if (_PLAYING(voice)) { fluid_voice_set_gain(voice, gain); } @@ -1408,7 +1413,7 @@ int fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony) /* turn off any voices above the new limit */ for (i = polyphony; i < synth->nvoice; i++) { - fluid_voice_t* voice = synth->voice[i]; + fluid_voice_t* voice = synth->voice[i]; if (_PLAYING(voice)) { fluid_voice_off(voice); } @@ -1441,9 +1446,9 @@ int fluid_synth_get_internal_bufsize(fluid_synth_t* synth) * Resend a bank select and a program change for every channel. This * function is called mainly after a SoundFont has been loaded, * unloaded or reloaded. */ -int +int fluid_synth_program_reset(fluid_synth_t* synth) -{ +{ int i; /* try to set the correct presets */ for (i = 0; i < synth->midi_channels; i++){ @@ -1474,7 +1479,7 @@ int fluid_synth_set_reverb_preset(fluid_synth_t* synth, int num) /* * fluid_synth_set_reverb */ -void fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize, double damping, +void fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize, double damping, double width, double level) { /* fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread *\/ */ @@ -1489,7 +1494,7 @@ void fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize, double dampin /* * fluid_synth_set_chorus */ -void fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level, +void fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level, double speed, double depth_ms, int type) { /* fluid_mutex_lock(synth->busy); /\* Don't interfere with the audio thread *\/ */ @@ -1552,12 +1557,12 @@ void fluid_synth_set_chorus(fluid_synth_t* synth, int nr, double level, ***************************************************/ -/* +/* * fluid_synth_nwrite_float */ -int -fluid_synth_nwrite_float(fluid_synth_t* synth, int len, - float** left, float** right, +int +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 = synth->left_buf; @@ -1599,7 +1604,7 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len, num = (FLUID_BUFSIZE > len - count)? len - count : FLUID_BUFSIZE; bytes = num * sizeof(float); - + for (i = 0; i < synth->audio_channels; i++) { FLUID_MEMCPY(left[i] + count, left_in[i], bytes); FLUID_MEMCPY(right[i] + count, right_in[i], bytes); @@ -1608,7 +1613,7 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len, FLUID_MEMCPY(fx_left[i] + count, fx_left_in[i], bytes); FLUID_MEMCPY(fx_right[i] + count, fx_right_in[i], bytes); } - + count += num; } @@ -1624,19 +1629,19 @@ fluid_synth_nwrite_float(fluid_synth_t* synth, int len, } int fluid_synth_process(fluid_synth_t* synth, int len, - int nin, float** in, + int nin, float** in, int nout, float** out) { - return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1); + return fluid_synth_write_float(synth, len, out[0], 0, 1, out[1], 0, 1); } -/* +/* * fluid_synth_write_float */ -int -fluid_synth_write_float(fluid_synth_t* synth, int len, - void* lout, int loff, int lincr, +int +fluid_synth_write_float(fluid_synth_t* synth, int len, + void* lout, int loff, int lincr, void* rout, int roff, int rincr) { int i, j, k, l; @@ -1659,11 +1664,11 @@ fluid_synth_write_float(fluid_synth_t* synth, int len, fluid_synth_one_block(synth, 0); l = 0; } - + left_out[j] = (float) left_in[l]; right_out[k] = (float) right_in[l]; } - + synth->cur = l; time = fluid_utime() - time; @@ -1675,12 +1680,43 @@ fluid_synth_write_float(fluid_synth_t* synth, int len, return 0; } -/* +#define DITHER_SIZE 48000 +#define DITHER_CHANNELS 2 + +static float rand_table[DITHER_CHANNELS][DITHER_SIZE]; + +static void init_dither(void) +{ + 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; + } + rand_table[c][DITHER_SIZE-1] = 0 - dp; + } +} + +/* A portable replacement for roundf(), seems it may actually be faster too! */ +static inline int +roundi (float x) +{ + if (x >= 0.0f) + return (int)(x+0.5f); + else + return (int)(x-0.5f); +} + +/* * fluid_synth_write_s16 */ -int -fluid_synth_write_s16(fluid_synth_t* synth, int len, - void* lout, int loff, int lincr, +int +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; @@ -1692,6 +1728,8 @@ fluid_synth_write_s16(fluid_synth_t* synth, int len, fluid_real_t left_sample; fluid_real_t right_sample; double time = fluid_utime(); + int di = synth->dither_index; + double prof_ref_on_block; /* make sure we're playing */ if (synth->state != FLUID_SYNTH_PLAYING) { @@ -1704,36 +1742,32 @@ fluid_synth_write_s16(fluid_synth_t* synth, int len, /* fill up the buffers as needed */ if (cur == FLUID_BUFSIZE) { - - double prof_ref_on_block = fluid_profile_ref(); + prof_ref_on_block = fluid_profile_ref(); fluid_synth_one_block(synth, 0); cur = 0; - + fluid_profile(FLUID_PROF_ONE_BLOCK, prof_ref_on_block); } - left_sample=left_in[cur]* 32767.0f; - right_sample=right_in[cur] * 32767.0f; - + left_sample = roundi (left_in[cur] * 32766.0f + rand_table[0][di]); + right_sample = roundi (right_in[cur] * 32766.0f + rand_table[1][di]); + + di++; + if (di >= DITHER_SIZE) di = 0; + /* digital clipping */ - if (left_sample > 32767.0f) { - left_sample = 32767; - } - if (left_sample < -32768.0f) { - left_sample = -32768; - } - if (right_sample > 32767.0f) { - right_sample = 32767; - } - if (right_sample < -32768.0f) { - right_sample = -32768; - } + 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 */ fluid_profile(FLUID_PROF_WRITE_S16, prof_ref); @@ -1747,11 +1781,54 @@ fluid_synth_write_s16(fluid_synth_t* synth, int len, return 0; } +/* + * fluid_synth_dither_s16 + * Converts stereo floating point sample data to signed 16 bit data with + * dithering. 'dither_index' parameter is a caller supplied pointer to an + * integer which should be initialized to 0 before the first call and passed + * unmodified to additional calls which are part of the same synthesis output. + * Only used internally currently. + */ +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 i, j, k; + signed short* left_out = (signed short*) lout; + signed short* right_out = (signed short*) rout; + double prof_ref = fluid_profile_ref(); + fluid_real_t left_sample; + fluid_real_t right_sample; + int di = *dither_index; -/* + 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]); + + 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; + } + + *dither_index = di; /* keep dither buffer continous */ + + fluid_profile(FLUID_PROF_WRITE_S16, prof_ref); +} + +/* * fluid_synth_one_block */ -int +int fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out) { int i, auchan; @@ -1764,14 +1841,15 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out) double prof_ref = fluid_profile_ref(); /* fluid_mutex_lock(synth->busy); /\* Here comes the audio thread. Lock the synth. *\/ */ - - fluid_check_fpe("??? Just starting up ???"); + + fluid_check_fpe("??? Just starting up ???"); /* clean the audio buffers */ for (i = 0; i < synth->nbuf; i++) { FLUID_MEMSET(synth->left_buf[i], 0, byte_size); FLUID_MEMSET(synth->right_buf[i], 0, byte_size); } + for (i = 0; i < synth->effects_channels; i++) { FLUID_MEMSET(synth->fx_left_buf[i], 0, byte_size); FLUID_MEMSET(synth->fx_right_buf[i], 0, byte_size); @@ -1781,25 +1859,15 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out) * enabled on synth level. Nonexisting buffers are detected in the * DSP loop. Not sending the reverb / chorus signal saves some time * in that case. */ - if (synth->with_reverb) { - reverb_buf = synth->fx_left_buf[0]; - } else { - reverb_buf = NULL; - } - - if (synth->with_chorus) { - chorus_buf = synth->fx_left_buf[1]; - } else { - chorus_buf = NULL; - } - + reverb_buf = synth->with_reverb ? synth->fx_left_buf[0] : NULL; + chorus_buf = synth->with_chorus ? synth->fx_left_buf[1] : NULL; fluid_profile(FLUID_PROF_ONE_BLOCK_CLEAR, prof_ref); /* call all playing synthesis processes */ for (i = 0; i < synth->polyphony; i++) { voice = synth->voice[i]; - + if (_PLAYING(voice)) { double prof_ref_voice = fluid_profile_ref(); @@ -1825,6 +1893,7 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out) fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref_voice); } } + fluid_check_fpe("Synthesis processes"); fluid_profile(FLUID_PROF_ONE_BLOCK_VOICES, prof_ref); @@ -1837,16 +1906,16 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out) /* send to reverb */ if (reverb_buf) { - fluid_revmodel_processreplace(synth->reverb, reverb_buf, + fluid_revmodel_processreplace(synth->reverb, reverb_buf, synth->fx_left_buf[0], synth->fx_right_buf[0]); fluid_check_fpe("Reverb"); } fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref); - + /* send to chorus */ if (chorus_buf) { - fluid_chorus_processreplace(synth->chorus, chorus_buf, + fluid_chorus_processreplace(synth->chorus, chorus_buf, synth->fx_left_buf[1], synth->fx_right_buf[1]); fluid_check_fpe("Chorus"); } @@ -1855,16 +1924,16 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out) /* send to reverb */ if (reverb_buf) { - fluid_revmodel_processmix(synth->reverb, reverb_buf, + fluid_revmodel_processmix(synth->reverb, reverb_buf, synth->left_buf[0], synth->right_buf[0]); fluid_check_fpe("Reverb"); } fluid_profile(FLUID_PROF_ONE_BLOCK_REVERB, prof_ref); - + /* send to chorus */ if (chorus_buf) { - fluid_chorus_processmix(synth->chorus, chorus_buf, + fluid_chorus_processmix(synth->chorus, chorus_buf, synth->left_buf[0], synth->right_buf[0]); fluid_check_fpe("Chorus"); } @@ -1888,7 +1957,7 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out) /* fluid_mutex_unlock(synth->busy); /\* Allow other threads to touch the synth *\/ */ - return 0; + return 0; } @@ -1911,9 +1980,9 @@ fluid_synth_free_voice_by_kill(fluid_synth_t* synth) /* fluid_mutex_unlock(synth->busy); */ for (i = 0; i < synth->polyphony; i++) { - + voice = synth->voice[i]; - + /* safeguard against an available voice. */ if (_AVAILABLE(voice)) { return voice; @@ -1921,9 +1990,9 @@ fluid_synth_free_voice_by_kill(fluid_synth_t* synth) /* Determine, how 'important' a voice is. * Start with an arbitrary number */ - this_voice_prio = 10000.; - - /* Is this voice on the drum channel? + this_voice_prio = 10000.; + + /* Is this voice on the drum channel? * Then it is very important. * Also, forget about the released-note condition: * Typically, drum notes are triggered only very briefly, they run most @@ -1948,15 +2017,15 @@ fluid_synth_free_voice_by_kill(fluid_synth_t* synth) */ this_voice_prio -= 1000; } - + /* 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. + * chord. * So subtract the age of the voice from the priority - an older voice is just a little - * bit less important than a younger voice. + * bit less important than a younger voice. * This is a number between roughly 0 and 100.*/ this_voice_prio -= (synth->noteid - fluid_voice_get_id(voice)); - + /* take a rough estimate of loudness into account. Louder voices are more important. */ if (voice->volenv_section != FLUID_VOICE_ENVATTACK){ this_voice_prio += voice->volenv_val * 1000.; @@ -1981,7 +2050,7 @@ fluid_synth_free_voice_by_kill(fluid_synth_t* synth) /* * fluid_synth_alloc_voice */ -fluid_voice_t* +fluid_voice_t* fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, int key, int vel) { int i, k; @@ -2007,7 +2076,7 @@ fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, if (voice == NULL) { FLUID_LOG(FLUID_WARN, "Failed to allocate a synthesis process. (chan=%d,key=%d)", chan, key); return NULL; - } + } if (synth->verbose) { k = 0; @@ -2017,9 +2086,9 @@ fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, } } - 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) synth->ticks / 44100.0f, + 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) synth->ticks / 44100.0f, (fluid_curtime() - synth->start) / 1000.0f, 0.0f, k); @@ -2029,12 +2098,12 @@ fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, channel = synth->channel[chan]; } - if (fluid_voice_init(voice, sample, channel, key, vel, + if (fluid_voice_init(voice, sample, channel, key, vel, synth->storeid, synth->ticks, synth->gain) != FLUID_OK) { FLUID_LOG(FLUID_WARN, "Failed to initialize voice"); return NULL; } - + /* add the default modulators to the synthesis process. */ fluid_voice_add_mod(voice, &default_vel2att_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.1 */ fluid_voice_add_mod(voice, &default_vel2filter_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.2 */ @@ -2046,7 +2115,7 @@ fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample, int chan, fluid_voice_add_mod(voice, &default_reverb_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.8 */ fluid_voice_add_mod(voice, &default_chorus_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.9 */ fluid_voice_add_mod(voice, &default_pitch_bend_mod, FLUID_VOICE_DEFAULT); /* SF2.01 $8.4.10 */ - + return voice; } @@ -2064,50 +2133,50 @@ void fluid_synth_kill_by_exclusive_class(fluid_synth_t* synth, fluid_voice_t* ne terminate all voices on a channel belonging into the exclusive class excl_class. */ - + int i; int excl_class = _GEN(new_voice,GEN_EXCLUSIVECLASS); /* Check if the voice belongs to an exclusive class. In that case, previous notes from the same class are released. */ - + /* Excl. class 0: No exclusive class */ - if (excl_class == 0) { - return; + if (excl_class == 0) { + return; } - + // FLUID_LOG(FLUID_INFO, "Voice belongs to exclusive class (class=%d, ignore_id=%d)", excl_class, ignore_ID); - + /* 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]; - + /* Existing voice does not play? Leave it alone. */ if (!_PLAYING(existing_voice)) { continue; } - + /* An exclusive class is valid for a whole channel (or preset). * Is the voice on a different channel? Leave it alone. */ if (existing_voice->chan != new_voice->chan) { continue; } - + /* Existing voice has a different (or no) exclusive class? Leave it alone. */ if ((int)_GEN(existing_voice, GEN_EXCLUSIVECLASS) != excl_class) { continue; } - + /* Existing voice is a voice process belonging to this noteon * event (for example: stereo sample)? Leave it alone. */ if (fluid_voice_get_id(existing_voice) == fluid_voice_get_id(new_voice)) { continue; } - - // FLUID_LOG(FLUID_INFO, "Releasing previous voice of exclusive class (class=%d, id=%d)", + + // FLUID_LOG(FLUID_INFO, "Releasing previous voice of exclusive class (class=%d, id=%d)", // (int)_GEN(existing_voice, GEN_EXCLUSIVECLASS), (int)fluid_voice_get_id(existing_voice)); - + fluid_voice_kill_excl(existing_voice); }; }; @@ -2123,7 +2192,7 @@ void fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* 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(synth, voice); + fluid_synth_kill_by_exclusive_class(synth, voice); /* Start the new voice */ @@ -2142,7 +2211,7 @@ void fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader) /* * fluid_synth_sfload */ -int +int fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets) { fluid_sfont_t* sfont; @@ -2154,13 +2223,13 @@ fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets #endif if (filename == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid filename"); + FLUID_LOG(FLUID_ERR, "Invalid filename"); return FLUID_FAILED; } 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) { @@ -2179,7 +2248,7 @@ fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets } } - FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); + FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); return -1; } @@ -2214,7 +2283,7 @@ void fluid_synth_sfunload_macos9(fluid_synth_t* synth) } list = next; } -#endif +#endif } /* @@ -2230,7 +2299,7 @@ fluid_synth_sfunload(fluid_synth_t* synth, unsigned int id, int reset_presets) #endif if (!sfont) { - FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); + FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); return FLUID_FAILED; } @@ -2250,9 +2319,9 @@ fluid_synth_sfunload(fluid_synth_t* synth, unsigned int id, int reset_presets) #else /* spin off a timer thread to unload the sfont later */ new_fluid_timer(100, fluid_synth_sfunload_callback, sfont, 1, 1); -#endif +#endif } - + return FLUID_OK; } @@ -2270,7 +2339,7 @@ int fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id) sfont = fluid_synth_get_sfont_by_id(synth, id); if (!sfont) { - FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); + FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id); return FLUID_FAILED; } @@ -2293,7 +2362,7 @@ int fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id) 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) { @@ -2310,7 +2379,7 @@ int fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id) } } - FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); + FLUID_LOG(FLUID_ERR, "Failed to load SoundFont \"%s\"", filename); return -1; } @@ -2324,10 +2393,10 @@ int fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) /* insert the sfont as the first one on the list */ synth->sfont = fluid_list_prepend(synth->sfont, sfont); - + /* reset the presets for all channels */ fluid_synth_program_reset(synth); - + return sfont->id; } @@ -2343,7 +2412,7 @@ void fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) /* remove a possible bank offset */ fluid_synth_remove_bank_offset(synth, sfont_id); - + /* reset the presets for all channels */ fluid_synth_program_reset(synth); } @@ -2351,9 +2420,9 @@ void fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont) /* fluid_synth_sfcount * - * Returns the number of loaded SoundFonts + * Returns the number of loaded SoundFonts */ -int +int fluid_synth_sfcount(fluid_synth_t* synth) { return fluid_list_size(synth->sfont); @@ -2361,9 +2430,9 @@ fluid_synth_sfcount(fluid_synth_t* synth) /* fluid_synth_get_sfont * - * Returns SoundFont num + * Returns SoundFont num */ -fluid_sfont_t* +fluid_sfont_t* fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num) { return (fluid_sfont_t*) fluid_list_get(fluid_list_nth(synth->sfont, num)); @@ -2384,7 +2453,7 @@ fluid_sfont_t* fluid_synth_get_sfont_by_id(fluid_synth_t* synth, unsigned int id } list = fluid_list_next(list); } - return NULL; + return NULL; } /* fluid_synth_get_sfont_by_name @@ -2402,7 +2471,7 @@ fluid_sfont_t* fluid_synth_get_sfont_by_name(fluid_synth_t* synth, char *name) } list = fluid_list_next(list); } - return NULL; + return NULL; } /* @@ -2414,7 +2483,7 @@ fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan) if ((chan >= 0) && (chan < synth->midi_channels)) { return fluid_channel_get_preset(synth->channel[chan]); } - + return NULL; } @@ -2431,7 +2500,7 @@ fluid_synth_get_voicelist(fluid_synth_t* synth, fluid_voice_t* buf[], int bufsiz if (count >= bufsize) { return; } - + if (_PLAYING(voice) && ((int)voice->id == ID || ID < 0)) { buf[count++] = voice; } @@ -2442,21 +2511,21 @@ fluid_synth_get_voicelist(fluid_synth_t* synth, fluid_voice_t* buf[], int bufsiz buf[count++] = NULL; } -/* Purpose: +/* Purpose: * Turns on / off the reverb unit in the synth */ void fluid_synth_set_reverb_on(fluid_synth_t* synth, int on) { synth->with_reverb = on; } -/* Purpose: +/* Purpose: * Turns on / off the chorus unit in the synth */ void fluid_synth_set_chorus_on(fluid_synth_t* synth, int on) { synth->with_chorus = on; } -/* Purpose: +/* Purpose: * Reports the current setting of the chorus unit. */ int fluid_synth_get_chorus_nr(fluid_synth_t* synth) { @@ -2505,7 +2574,7 @@ double fluid_synth_get_reverb_width(fluid_synth_t* synth) return (double) fluid_revmodel_getwidth(synth->reverb); } -/* Purpose: +/* Purpose: * * If the same note is hit twice on the same channel, then the older * voice process is advanced to the release stage. Using a mechanical @@ -2524,9 +2593,9 @@ void fluid_synth_release_voice_on_same_note(fluid_synth_t* synth, int chan, int for (i = 0; i < synth->polyphony; i++) { voice = synth->voice[i]; - if (_PLAYING(voice) - && (voice->chan == chan) - && (voice->key == key) + if (_PLAYING(voice) + && (voice->chan == chan) + && (voice->key == key) && (fluid_voice_get_id(voice) != synth->noteid)) { fluid_voice_noteoff(voice); } @@ -2541,7 +2610,7 @@ int fluid_synth_set_interp_method(fluid_synth_t* synth, int chan, int interp_met int i; for (i = 0; i < synth->midi_channels; i++) { if (synth->channel[i] == NULL){ - FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!"); + FLUID_LOG(FLUID_ERR, "Channels don't exist (yet)!"); return FLUID_FAILED; }; if (chan < 0 || fluid_channel_get_num(synth->channel[i]) == chan){ @@ -2554,7 +2623,7 @@ int fluid_synth_set_interp_method(fluid_synth_t* synth, int chan, int interp_met /* Purpose: * Returns the number of allocated midi channels */ -int +int fluid_synth_count_midi_channels(fluid_synth_t* synth) { return synth->midi_channels; @@ -2563,7 +2632,7 @@ fluid_synth_count_midi_channels(fluid_synth_t* synth) /* Purpose: * Returns the number of allocated audio channels */ -int +int fluid_synth_count_audio_channels(fluid_synth_t* synth) { return synth->audio_channels; @@ -2572,7 +2641,7 @@ fluid_synth_count_audio_channels(fluid_synth_t* synth) /* Purpose: * Returns the number of allocated audio channels */ -int +int fluid_synth_count_audio_groups(fluid_synth_t* synth) { return synth->audio_groups; @@ -2592,36 +2661,36 @@ double fluid_synth_get_cpu_load(fluid_synth_t* synth) return synth->cpu_load; } -static fluid_tuning_t* +static fluid_tuning_t* fluid_synth_get_tuning(fluid_synth_t* synth, int bank, int prog) { if ((bank < 0) || (bank >= 128)) { FLUID_LOG(FLUID_WARN, "Bank number out of range"); - return NULL; + return NULL; } if ((prog < 0) || (prog >= 128)) { FLUID_LOG(FLUID_WARN, "Program number out of range"); - return NULL; + return NULL; } if ((synth->tuning == NULL) || (synth->tuning[bank] == NULL) || (synth->tuning[bank][prog] == NULL)) { FLUID_LOG(FLUID_WARN, "No tuning at bank %d, prog %d", bank, prog); - return NULL; + return NULL; } return synth->tuning[bank][prog]; } -static fluid_tuning_t* +static fluid_tuning_t* fluid_synth_create_tuning(fluid_synth_t* synth, int bank, int prog, char* name) { if ((bank < 0) || (bank >= 128)) { FLUID_LOG(FLUID_WARN, "Bank number out of range"); - return NULL; + return NULL; } if ((prog < 0) || (prog >= 128)) { FLUID_LOG(FLUID_WARN, "Program number out of range"); - return NULL; + return NULL; } if (synth->tuning == NULL) { synth->tuning = FLUID_ARRAY(fluid_tuning_t**, 128); @@ -2648,7 +2717,7 @@ fluid_synth_create_tuning(fluid_synth_t* synth, int bank, int prog, char* name) } } - if ((fluid_tuning_get_name(synth->tuning[bank][prog]) == NULL) + if ((fluid_tuning_get_name(synth->tuning[bank][prog]) == NULL) || (FLUID_STRCMP(fluid_tuning_get_name(synth->tuning[bank][prog]), name) != 0)) { fluid_tuning_set_name(synth->tuning[bank][prog], name); } @@ -2656,7 +2725,7 @@ fluid_synth_create_tuning(fluid_synth_t* synth, int bank, int prog, char* name) return synth->tuning[bank][prog]; } -int fluid_synth_create_key_tuning(fluid_synth_t* synth, +int fluid_synth_create_key_tuning(fluid_synth_t* synth, int bank, int prog, char* name, double* pitch) { @@ -2671,7 +2740,7 @@ int fluid_synth_create_key_tuning(fluid_synth_t* synth, } -int fluid_synth_create_octave_tuning(fluid_synth_t* synth, +int fluid_synth_create_octave_tuning(fluid_synth_t* synth, int bank, int prog, char* name, double* pitch) { @@ -2689,8 +2758,8 @@ int fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog, fluid_tuning_t* tuning = fluid_synth_get_tuning(synth, bank, prog); int i; - if (tuning == NULL) { - return FLUID_FAILED; + if (tuning == NULL) { + return FLUID_FAILED; } for (i = 0; i < len; i++) { @@ -2700,17 +2769,17 @@ int fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog, return FLUID_OK; } -int fluid_synth_select_tuning(fluid_synth_t* synth, int chan, +int fluid_synth_select_tuning(fluid_synth_t* synth, int chan, int bank, int prog) { fluid_tuning_t* tuning = fluid_synth_get_tuning(synth, bank, prog); - if (tuning == NULL) { - return FLUID_FAILED; + if (tuning == NULL) { + return FLUID_FAILED; } if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } fluid_channel_set_tuning(synth->channel[chan], synth->tuning[bank][prog]); @@ -2722,11 +2791,11 @@ int fluid_synth_reset_tuning(fluid_synth_t* synth, int chan) { if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } fluid_channel_set_tuning(synth->channel[chan], NULL); - + return FLUID_OK; } @@ -2738,7 +2807,7 @@ void fluid_synth_tuning_iteration_start(fluid_synth_t* synth) int fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog) { int b = 0, p = 0; - + if (synth->tuning == NULL) { return 0; } @@ -2772,13 +2841,13 @@ int fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog return 0; } -int fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog, +int fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog, char* name, int len, double* pitch) { fluid_tuning_t* tuning = fluid_synth_get_tuning(synth, bank, prog); - if (tuning == NULL) { - return FLUID_FAILED; + if (tuning == NULL) { + return FLUID_FAILED; } if (name) { @@ -2827,7 +2896,7 @@ int fluid_synth_getint(fluid_synth_t* synth, char* name, int* val) return fluid_settings_getint(synth->settings, name, val); } -int +int fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value) { int i; @@ -2835,12 +2904,12 @@ fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value) if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if ((param < 0) || (param >= GEN_LAST)) { FLUID_LOG(FLUID_WARN, "Parameter number out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } fluid_channel_set_gen(synth->channel[chan], param, value, 0); @@ -2852,7 +2921,7 @@ fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value) } } - return FLUID_OK; + return FLUID_OK; } /** Change the value of a generator. This function allows to control @@ -2863,7 +2932,7 @@ fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value) parameter numbers and ranges are described in the SoundFont 2.01 specification, paragraph 8.1.3, page 48. See also 'fluid_gen_type'. - + Using the fluid_synth_set_gen2() function, it is possible to set the absolute value of a generator. This is an extension to the SoundFont standard. If 'absolute' is non-zero, the value of the @@ -2871,15 +2940,15 @@ fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value) generator is fixed to the value passed as argument. To undo this behavior, you must call fluid_synth_set_gen2 again, with 'absolute' set to 0 (and possibly 'value' set to zero). - + If 'normalized' is non-zero, the value is supposed to be normalized between 0 and 1. Before applying the value, it will be scaled and shifted to the range defined in the SoundFont specifications. */ -int -fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param, +int +fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param, float value, int absolute, int normalized) { int i; @@ -2888,12 +2957,12 @@ fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param, if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } if ((param < 0) || (param >= GEN_LAST)) { FLUID_LOG(FLUID_WARN, "Parameter number out of range"); - return FLUID_FAILED; + return FLUID_FAILED; } v = (normalized)? fluid_gen_scale(param, value) : value; @@ -2907,25 +2976,25 @@ fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param, } } - return FLUID_OK; + return FLUID_OK; } float fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param) { if ((chan < 0) || (chan >= synth->midi_channels)) { FLUID_LOG(FLUID_WARN, "Channel out of range"); - return 0.0; + return 0.0; } if ((param < 0) || (param >= GEN_LAST)) { FLUID_LOG(FLUID_WARN, "Parameter number out of range"); - return 0.0; + return 0.0; } return fluid_channel_get_gen(synth->channel[chan], param); } -/* The synth needs to know the router for the command line handlers (they only +/* The synth needs to know the router for the command line handlers (they only * supply the synth as argument) */ void fluid_synth_set_midi_router(fluid_synth_t* synth, fluid_midi_router_t* router){ @@ -2944,16 +3013,16 @@ int fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event) switch(type) { case NOTE_ON: - return fluid_synth_noteon(synth, chan, - fluid_midi_event_get_key(event), + 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 CONTROL_CHANGE: - return fluid_synth_cc(synth, chan, - fluid_midi_event_get_control(event), + return fluid_synth_cc(synth, chan, + fluid_midi_event_get_control(event), fluid_midi_event_get_value(event)); case PROGRAM_CHANGE: @@ -2969,7 +3038,7 @@ int fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event) } -int fluid_synth_start(fluid_synth_t* synth, unsigned int id, fluid_preset_t* preset, +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) { int r; @@ -3006,7 +3075,7 @@ int fluid_synth_stop(fluid_synth_t* synth, unsigned int id) fluid_voice_t* voice; int status = FLUID_FAILED; int count = 0; - + for (i = 0; i < synth->polyphony; i++) { voice = synth->voice[i]; @@ -3021,12 +3090,12 @@ int fluid_synth_stop(fluid_synth_t* synth, unsigned int id) return status; } -fluid_bank_offset_t* +fluid_bank_offset_t* fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id) { fluid_list_t* list = synth->bank_offsets; fluid_bank_offset_t* offset; - + while (list) { offset = (fluid_bank_offset_t*) fluid_list_get(list); @@ -3036,11 +3105,11 @@ fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id) list = fluid_list_next(list); } - + return NULL; } -int +int fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset) { fluid_bank_offset_t* bank_offset; @@ -3062,7 +3131,7 @@ fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset) return 0; } -int +int fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id) { fluid_bank_offset_t* bank_offset; @@ -3071,7 +3140,7 @@ fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id) return (bank_offset == NULL)? 0 : bank_offset->offset; } -void +void fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id) { fluid_bank_offset_t* bank_offset; diff --git a/src/libs/fluidsynth/src/fluid_synth.h b/src/libs/fluidsynth/src/fluid_synth.h index 615e1b7bf6..de80f6cb31 100644 --- a/src/libs/fluidsynth/src/fluid_synth.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -98,7 +98,7 @@ struct _fluid_synth_t double sample_rate; /** The sample rate */ int midi_channels; /** the number of MIDI channels (>= 16) */ int audio_channels; /** the number of audio channels (1 channel=left+right) */ - int audio_groups; /** the number of (stereo) 'sub'groups from the synth. + 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) */ unsigned int state; /** the synthesizer state */ @@ -120,7 +120,7 @@ struct _fluid_synth_t int nvoice; /** the length of the synthesis process array */ fluid_voice_t** voice; /** the synthesis processes */ unsigned int noteid; /** the id is incremented for every new note. it's used for noteoff's */ - unsigned int storeid; + unsigned int storeid; int nbuf; /** How many audio buffers are used? (depends on nr of audio channels / groups)*/ fluid_real_t** left_buf; @@ -128,23 +128,19 @@ struct _fluid_synth_t fluid_real_t** fx_left_buf; fluid_real_t** fx_right_buf; - fluid_real_t** left_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */ - fluid_real_t** right_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */ - fluid_real_t** fx_left_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */ - fluid_real_t** fx_right_ubuf; /* Stores the unaligned buffers (see new_fluid_synth) */ - fluid_revmodel_t* reverb; fluid_chorus_t* chorus; int cur; /** the current sample in the audio buffers to be output */ + int dither_index; /* current index in random dither value buffer: fluid_synth_(write_s16|dither_s16) */ char outbuf[256]; /** buffer for message output */ double cpu_load; - fluid_tuning_t*** tuning; /** 128 banks of 128 programs for the tunings */ - fluid_tuning_t* cur_tuning; /** current tuning in the iteration */ + fluid_tuning_t*** tuning; /** 128 banks of 128 programs for the tunings */ + fluid_tuning_t* cur_tuning; /** current tuning in the iteration */ fluid_midi_router_t* midi_router; /* The midi router. Could be done nicer. */ - fluid_mutex_t busy; /* Indicates, whether the audio thread is currently running. + fluid_mutex_t busy; /* Indicates, whether the audio thread is currently running. * Note: This simple scheme does -not- provide 100 % protection against * thread problems, for example from MIDI thread and shell thread */ @@ -153,7 +149,6 @@ struct _fluid_synth_t #endif }; - /** returns 1 if the value has been set, 0 otherwise */ int fluid_synth_setstr(fluid_synth_t* synth, char* name, char* str); @@ -177,13 +172,13 @@ int fluid_synth_set_reverb_preset(fluid_synth_t* synth, int num); int fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out); -fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth, - unsigned int sfontnum, - unsigned int banknum, +fluid_preset_t* fluid_synth_get_preset(fluid_synth_t* synth, + unsigned int sfontnum, + unsigned int banknum, unsigned int prognum); -fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, - unsigned int banknum, +fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth, + unsigned int banknum, unsigned int prognum); int fluid_synth_all_notes_off(fluid_synth_t* synth, int chan); @@ -210,8 +205,9 @@ int fluid_synth_update_polyphony(fluid_synth_t* synth, char* name, int value); fluid_bank_offset_t* fluid_synth_get_bank_offset0(fluid_synth_t* synth, int sfont_id); void fluid_synth_remove_bank_offset(fluid_synth_t* synth, int sfont_id); - - +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); /* * misc */ diff --git a/src/libs/fluidsynth/src/fluid_sys.c b/src/libs/fluidsynth/src/fluid_sys.c index 802839b193..a565cc8c83 100644 --- a/src/libs/fluidsynth/src/fluid_sys.c +++ b/src/libs/fluidsynth/src/fluid_sys.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -20,7 +20,6 @@ #include "fluid_sys.h" -//#include static char fluid_errbuf[512]; /* buffer for error message */ @@ -34,7 +33,7 @@ static char* fluid_libname = "fluidsynth"; void fluid_sys_config() { fluid_log_config(); - fluid_time_config(); + fluid_time_config(); } @@ -48,25 +47,29 @@ int fluid_debug(int level, char * fmt, ...) { if (fluid_debug_flags & level) { fluid_log_function_t fun; - va_list args; + va_list args; - va_start (args, fmt); + va_start (args, fmt); vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args); - va_end (args); + va_end (args); fun = fluid_log_function[FLUID_DBG]; if (fun != NULL) { (*fun)(level, fluid_errbuf, fluid_log_user_data[FLUID_DBG]); } - } + } return 0; } #endif -/* - * fluid_set_log_function +/** + * Installs a new log function for a specified log level. + * @param level Log level to install handler for. + * @param fun Callback function handler to call for logged messages + * @param data User supplied data pointer to pass to log function + * @return The previously installed function. */ -fluid_log_function_t +fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void* data) { fluid_log_function_t old = NULL; @@ -79,10 +82,13 @@ fluid_set_log_function(int level, fluid_log_function_t fun, void* data) return old; } -/* - * fluid_default_log_function +/** + * Default log function which prints to the stderr. + * @param level Log level + * @param message Log message + * @param data User supplied data (not used) */ -void +void fluid_default_log_function(int level, char* message, void* data) { FILE* out; @@ -92,25 +98,25 @@ fluid_default_log_function(int level, char* message, void* data) #else out = stderr; #endif - + if (fluid_log_initialized == 0) { fluid_log_config(); } switch (level) { - case FLUID_PANIC: + case FLUID_PANIC: FLUID_FPRINTF(out, "%s: panic: %s\n", fluid_libname, message); break; - case FLUID_ERR: + case FLUID_ERR: FLUID_FPRINTF(out, "%s: error: %s\n", fluid_libname, message); break; - case FLUID_WARN: + case FLUID_WARN: FLUID_FPRINTF(out, "%s: warning: %s\n", fluid_libname, message); break; - case FLUID_INFO: + case FLUID_INFO: FLUID_FPRINTF(out, "%s: %s\n", fluid_libname, message); break; - case FLUID_DBG: + case FLUID_DBG: #if DEBUG FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message); #endif @@ -125,7 +131,7 @@ fluid_default_log_function(int level, char* message, void* data) /* * fluid_init_log */ -void +void fluid_log_config(void) { if (fluid_log_initialized == 0) { @@ -135,37 +141,41 @@ fluid_log_config(void) 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); } } } -/* - * fluid_log +/** + * Print a message to the log. + * @param level Log level (#fluid_log_level). + * @param fmt Printf style format string for log message + * @param ... Arguments for printf 'fmt' message string + * @return Always returns -1 */ -int +int fluid_log(int level, char* fmt, ...) { fluid_log_function_t fun = NULL; - va_list args; - va_start (args, fmt); + va_list args; + va_start (args, fmt); vsnprintf(fluid_errbuf, sizeof (fluid_errbuf), fmt, args); - va_end (args); + va_end (args); if ((level >= 0) && (level < LAST_LOG_LEVEL)) { fun = fluid_log_function[level]; @@ -173,14 +183,83 @@ fluid_log(int level, char* fmt, ...) (*fun)(level, fluid_errbuf, fluid_log_user_data[level]); } } - return FLUID_FAILED; + return FLUID_FAILED; } +/** + * An improved strtok, still trashes the input string, but is portable and + * thread safe. Also skips token chars at beginning of token string and never + * returns an empty token (will return NULL if source ends in token chars though). + * NOTE: NOT part of public API + * @internal + * @param str Pointer to a string pointer of source to tokenize. Pointer gets + * updated on each invocation to point to beginning of next token. Note that + * token char get's overwritten with a 0 byte. String pointer is set to NULL + * when final token is returned. + * @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 *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? */ + { + *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; @@ -188,9 +267,9 @@ fluid_error() /* - * + * * fluid_is_midifile - */ + */ int fluid_is_midifile(char* filename) { @@ -205,14 +284,14 @@ fluid_is_midifile(char* filename) return 0; } fclose(fp); - + return strncmp(id, "MThd", 4) == 0; } /* - * fluid_is_soundfont - * - */ + * fluid_is_soundfont + * + */ int fluid_is_soundfont(char* filename) { @@ -227,7 +306,7 @@ fluid_is_soundfont(char* filename) return 0; } fclose(fp); - + return strncmp(id, "RIFF", 4) == 0; } @@ -245,7 +324,7 @@ fluid_is_soundfont(char* filename) * */ -struct _fluid_timer_t +struct _fluid_timer_t { long msec; fluid_timer_callback_t callback; @@ -259,13 +338,13 @@ struct _fluid_timer_t static int fluid_timer_count = 0; DWORD WINAPI fluid_timer_run(LPVOID data); -fluid_timer_t* -new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, +fluid_timer_t* +new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, int new_thread, int auto_destroy) { fluid_timer_t* timer = FLUID_NEW(fluid_timer_t); if (timer == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } @@ -279,18 +358,18 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, if (new_thread) { timer->thread = CreateThread(NULL, 0, fluid_timer_run, (LPVOID) timer, 0, &timer->thread_id); if (timer->thread == NULL) { - FLUID_LOG(FLUID_ERR, "Couldn't create timer thread"); + FLUID_LOG(FLUID_ERR, "Couldn't create timer thread"); FLUID_FREE(timer); return NULL; } SetThreadPriority(timer->thread, THREAD_PRIORITY_TIME_CRITICAL); } else { - fluid_timer_run((LPVOID) timer); + fluid_timer_run((LPVOID) timer); } return timer; } -DWORD WINAPI +DWORD WINAPI fluid_timer_run(LPVOID data) { int count = 0; @@ -337,16 +416,16 @@ fluid_timer_run(LPVOID data) return 0; } -int +int delete_fluid_timer(fluid_timer_t* timer) { timer->cont = 0; - fluid_timer_join(timer); + fluid_timer_join(timer); FLUID_FREE(timer); return FLUID_OK; } -int +int fluid_timer_join(fluid_timer_t* timer) { DWORD wait_result; @@ -371,7 +450,7 @@ static double fluid_cpu_frequency = -1.0; void fluid_time_config(void) { if (fluid_cpu_frequency < 0.0) { - fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0; + fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0; } } @@ -422,7 +501,7 @@ double fluid_estimate_cpu_frequency(void) QueryPerformanceCounter(&start); Sleep(1000); - + after = fluid_curtime(); QueryPerformanceCounter(&stop); @@ -445,7 +524,7 @@ double fluid_estimate_cpu_frequency(void) * Timer */ -struct _fluid_timer_t +struct _fluid_timer_t { TMTask myTmTask; long msec; @@ -472,13 +551,13 @@ _timerCallback(fluid_timer_t *timer) timer->count++; } -fluid_timer_t* -new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, +fluid_timer_t* +new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, int new_thread, int auto_destroy) { fluid_timer_t* timer = FLUID_NEW(fluid_timer_t); if (timer == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } @@ -501,14 +580,14 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, timer->isInstalled = 1; timer->count = 0; timer->auto_destroy = auto_destroy; - + InsXTime((QElemPtr)timer); PrimeTime((QElemPtr)timer, msec); return timer; } -int +int delete_fluid_timer(fluid_timer_t* timer) { if (timer->isInstalled) { @@ -518,7 +597,7 @@ delete_fluid_timer(fluid_timer_t* timer) return FLUID_OK; } -int +int fluid_timer_join(fluid_timer_t* timer) { if (timer->isInstalled) { @@ -545,16 +624,17 @@ unsigned int fluid_curtime() UnsignedWide uS; double mSf; unsigned int ms; - + Microseconds(&uS); - + mSf = ((((double) uS.hi) * kTwoPower32) + uS.lo)/1000.0f; - + ms = mSf; - + return (ms); } + #elif __BEOS__ struct _fluid_timer_t @@ -660,8 +740,8 @@ double fluid_utime(void) * * Timer */ - -struct _fluid_timer_t + +struct _fluid_timer_t { long msec; fluid_timer_callback_t callback; @@ -671,7 +751,7 @@ struct _fluid_timer_t int auto_destroy; }; -void* +void* fluid_timer_start(void *data) { int count = 0; @@ -714,8 +794,8 @@ fluid_timer_start(void *data) return NULL; } -fluid_timer_t* -new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, +fluid_timer_t* +new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, int new_thread, int auto_destroy) { pthread_attr_t *attr = NULL; @@ -726,7 +806,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, fluid_timer_t* timer = FLUID_NEW(fluid_timer_t); if (timer == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } timer->msec = msec; @@ -736,7 +816,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, timer->thread = 0; timer->auto_destroy = auto_destroy; - err = pthread_attr_init(&rt_attr); + err = pthread_attr_init(&rt_attr); if (err == 0) { err = pthread_attr_setschedpolicy(&rt_attr, SCHED_FIFO); if (err == 0) { @@ -744,14 +824,14 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, err = pthread_attr_setschedparam(&rt_attr, &priority); if (err == 0) { attr = &rt_attr; - } + } } } if (new_thread) { err = pthread_create(&timer->thread, attr, fluid_timer_start, (void*) timer); if (err == 0) { - FLUID_LOG(FLUID_DBG, "The timer thread was created with real-time priority"); + FLUID_LOG(FLUID_DBG, "The timer thread was created with real-time priority"); } else { /* Create the thread with default attributes */ err = pthread_create(&timer->thread, NULL, fluid_timer_start, (void*) timer); @@ -769,7 +849,7 @@ new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, return timer; } -int +int delete_fluid_timer(fluid_timer_t* timer) { timer->cont = 0; @@ -779,7 +859,7 @@ delete_fluid_timer(fluid_timer_t* timer) return FLUID_OK; } -int +int fluid_timer_join(fluid_timer_t* timer) { int err = 0; @@ -805,7 +885,8 @@ double fluid_estimate_cpu_frequency(void); void fluid_time_config(void) { if (fluid_cpu_frequency < 0.0) { - fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0; + fluid_cpu_frequency = fluid_estimate_cpu_frequency() / 1000000.0; + if (fluid_cpu_frequency == 0.0) fluid_cpu_frequency = 1.0; } } @@ -849,11 +930,11 @@ double fluid_estimate_cpu_frequency(void) unsigned int a0, b0, a1, b1; unsigned int before, after; - before = fluid_curtime(); + before = fluid_curtime(); __asm__ ("rdtsc" : "=a" (a0), "=d" (b0)); sleep(1); - + after = fluid_curtime(); __asm__ ("rdtsc" : "=a" (a1), "=d" (b1)); @@ -866,7 +947,7 @@ double fluid_estimate_cpu_frequency(void) #endif -#if 0 +#ifdef FPE_CHECK /*************************************************************** * @@ -875,7 +956,7 @@ double fluid_estimate_cpu_frequency(void) * The floating point exception functions were taken from Ircam's * jMax source code. http://www.ircam.fr/jmax * - * FIXME: check in config for i386 machine + * FIXME: check in config for i386 machine * * Currently not used. I leave the code here in case we want to pick * this up again some time later. @@ -900,7 +981,8 @@ double fluid_estimate_cpu_frequency(void) #define _FPU_CLR_SW() __asm__ ("fnclex" : : ) /* Purpose: - * Checks, if the floating point unit has produced an exception in the meantime. + * 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) { @@ -909,11 +991,10 @@ unsigned int fluid_check_fpe_i386(char* explanation) _FPU_GET_SW(s); _FPU_CLR_SW(); - if ((s & _FPU_STATUS_IE) - || (s & _FPU_STATUS_DE) - || (s & _FPU_STATUS_ZE) - || (s & _FPU_STATUS_OE) - || (s & _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 " : "", @@ -921,14 +1002,22 @@ unsigned int fluid_check_fpe_i386(char* explanation) (s & _FPU_STATUS_OE) ? "Overflow " : "", (s & _FPU_STATUS_UE) ? "Underflow " : ""); } - + return s; } -#endif +/* Purpose: + * Clear floating point exception. + */ +void fluid_clear_fpe_i386 (void) +{ + _FPU_CLR_SW(); +} + +#endif // ifdef FPE_CHECK -#endif +#endif // #else (its POSIX) /*************************************************************** @@ -939,7 +1028,7 @@ unsigned int fluid_check_fpe_i386(char* explanation) #if WITH_PROFILING -fluid_profile_data_t fluid_profile_data[] = +fluid_profile_data_t fluid_profile_data[] = { { FLUID_PROF_WRITE_S16, "fluid_synth_write_s16 ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_ONE_BLOCK, "fluid_synth_one_block ", 1e10, 0.0, 0.0, 0}, @@ -950,7 +1039,7 @@ fluid_profile_data_t fluid_profile_data[] = { FLUID_PROF_ONE_BLOCK_CHORUS, "fluid_synth_one_block:chorus ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_VOICE_NOTE, "fluid_voice:note ", 1e10, 0.0, 0.0, 0}, { FLUID_PROF_VOICE_RELEASE, "fluid_voice:release ", 1e10, 0.0, 0.0, 0}, - { FLUID_PROF_LAST, "last", 1e100, 0.0, 0.0, 0} + { FLUID_PROF_LAST, "last", 1e100, 0.0, 0.0, 0} }; @@ -959,16 +1048,16 @@ void fluid_profiling_print(void) int i; printf("fluid_profiling_print\n"); - - FLUID_LOG(FLUID_INFO, "Estimated CPU frequency: %.0f MHz", fluid_cpu_frequency); - FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)"); + + FLUID_LOG(FLUID_INFO, "Estimated CPU frequency: %.0f MHz", fluid_cpu_frequency); + FLUID_LOG(FLUID_INFO, "Estimated times: min/avg/max (micro seconds)"); for (i = 0; i < FLUID_PROF_LAST; 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_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); @@ -1010,7 +1099,7 @@ static DWORD WINAPI fluid_thread_start(LPVOID data) thread->func(thread->data); if (thread->detached) { - FLUID_FREE(thread); + FLUID_FREE(thread); } return 0; @@ -1022,13 +1111,13 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac fluid_thread_t* thread; if (func == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid thread function"); + FLUID_LOG(FLUID_ERR, "Invalid thread function"); return NULL; } thread = FLUID_NEW(fluid_thread_t); if (thread == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } @@ -1036,21 +1125,21 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac thread->func = func; thread->detached = detach; - thread->thread = CreateThread(NULL, 0, fluid_thread_start, (LPVOID) thread, + thread->thread = CreateThread(NULL, 0, fluid_thread_start, (LPVOID) thread, 0, &thread->thread_id); if (thread->thread == NULL) { - FLUID_LOG(FLUID_ERR, "Couldn't create the thread"); + FLUID_LOG(FLUID_ERR, "Couldn't create the thread"); FLUID_FREE(thread); return NULL; } - + return thread; } int delete_fluid_thread(fluid_thread_t* thread) { FLUID_FREE(thread); - return FLUID_OK; + return FLUID_OK; } @@ -1087,7 +1176,7 @@ static void* fluid_thread_start(void *data) thread->func(thread->data); if (thread->detached) { - FLUID_FREE(thread); + FLUID_FREE(thread); } return NULL; @@ -1099,13 +1188,13 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac pthread_attr_t attr; if (func == NULL) { - FLUID_LOG(FLUID_ERR, "Invalid thread function"); + FLUID_LOG(FLUID_ERR, "Invalid thread function"); return NULL; } thread = FLUID_NEW(fluid_thread_t); if (thread == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); return NULL; } @@ -1124,14 +1213,14 @@ fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detac FLUID_FREE(thread); return NULL; } - + return thread; } int delete_fluid_thread(fluid_thread_t* thread) { FLUID_FREE(thread); - return FLUID_OK; + return FLUID_OK; } int fluid_thread_join(fluid_thread_t* thread) @@ -1235,7 +1324,7 @@ static void fluid_server_socket_run(void* data) 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) { @@ -1250,13 +1339,13 @@ static void fluid_server_socket_run(void* data) if (r != 0) { fluid_socket_close(client_socket); } - } + } } FLUID_LOG(FLUID_DBG, "Server closing"); } -fluid_server_socket_t* +fluid_server_socket_t* new_fluid_server_socket(int port, fluid_server_func_t func, void* data) { fluid_server_socket_t* server_socket; @@ -1293,7 +1382,7 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data) server_socket = FLUID_NEW(fluid_server_socket_t); if (server_socket == NULL) { - FLUID_LOG(FLUID_ERR, "Out of memory"); + FLUID_LOG(FLUID_ERR, "Out of memory"); fluid_socket_close(sock); return NULL; } diff --git a/src/libs/fluidsynth/src/fluid_sys.h b/src/libs/fluidsynth/src/fluid_sys.h index 203dfc5e1f..b60169d8fa 100644 --- a/src/libs/fluidsynth/src/fluid_sys.h +++ b/src/libs/fluidsynth/src/fluid_sys.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -43,8 +43,15 @@ void fluid_sys_config(void); void fluid_log_config(void); void fluid_time_config(void); + +/* + * Utility functions + */ +char *fluid_strtok (char **str, char *delim); + + /** - + Additional debugging system, separate from the log system. This allows to print selected debug messages of a specific subsystem. @@ -61,7 +68,7 @@ enum fluid_debug_level { int fluid_debug(int level, char * fmt, ...); #else -#define fluid_debug +#define fluid_debug #endif @@ -98,7 +105,7 @@ double fluid_utime(void); -/** +/** Timers */ @@ -109,25 +116,25 @@ 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, +fluid_timer_t* new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, int new_thread, int auto_destroy); int delete_fluid_timer(fluid_timer_t* timer); int fluid_timer_join(fluid_timer_t* timer); int fluid_timer_stop(fluid_timer_t* timer); -/** +/** - Muteces + Muteces */ #if defined(MACOS9) typedef int fluid_mutex_t; #define fluid_mutex_init(_m) { (_m) = 0; } -#define fluid_mutex_destroy(_m) -#define fluid_mutex_lock(_m) -#define fluid_mutex_unlock(_m) +#define fluid_mutex_destroy(_m) +#define fluid_mutex_lock(_m) +#define fluid_mutex_unlock(_m) #elif defined(WIN32) typedef HANDLE fluid_mutex_t; @@ -140,7 +147,7 @@ typedef HANDLE fluid_mutex_t; #ifndef HAIKU_TARGET_PLATFORM_HAIKU typedef sem_id fluid_mutex_t; #define fluid_mutex_init(_m) { (_m) = create_sem(1, "fs_sem"); } -#define fluid_mutex_destroy(_m) delete_sem(_m); +#define fluid_mutex_destroy(_m) delete_sem(_m); #define fluid_mutex_lock(_m) acquire_sem(_m); #define fluid_mutex_unlock(_m) release_sem(_m); @@ -153,6 +160,7 @@ typedef pthread_mutex_t fluid_mutex_t; #endif #endif + /** Threads @@ -199,13 +207,13 @@ fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock); -/** +/** - Profiling + Profiling */ -/** +/** Profile numbers. List all the pieces of code you want to profile here. Be sure to add an entry in the fluid_profile_data table in fluid_sys.c @@ -267,9 +275,9 @@ extern fluid_profile_data_t fluid_profile_data[]; -/** +/** - Memory locking + Memory locking Memory locking is used to avoid swapping of the large block of sample data. @@ -280,26 +288,26 @@ extern fluid_profile_data_t fluid_profile_data[]; #define fluid_munlock(_p,_n) munlock(_p,_n) #else #define fluid_mlock(_p,_n) 0 -#define fluid_munlock(_p,_n) +#define fluid_munlock(_p,_n) #endif -/** +/** - Floating point exceptions + Floating point exceptions fluid_check_fpe() checks for "unnormalized numbers" and other exceptions of the floating point processsor. */ -#if 0 -/* Enable FPE exception check */ +#ifdef FPE_CHECK #define fluid_check_fpe(expl) fluid_check_fpe_i386(expl) +#define fluid_clear_fpe() fluid_clear_fpe_i386() #else -/* Disable FPE exception check */ #define fluid_check_fpe(expl) +#define fluid_clear_fpe() #endif unsigned int fluid_check_fpe_i386(char * explanation_in_case_of_fpe); +void fluid_clear_fpe_i386(void); #endif /* _FLUID_SYS_H */ - diff --git a/src/libs/fluidsynth/src/fluid_tuning.c b/src/libs/fluidsynth/src/fluid_tuning.c index 9404e64947..7a12e22832 100644 --- a/src/libs/fluidsynth/src/fluid_tuning.c +++ b/src/libs/fluidsynth/src/fluid_tuning.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -38,7 +38,7 @@ fluid_tuning_t* new_fluid_tuning(char* name, int bank, int prog) if (name != NULL) { tuning->name = FLUID_STRDUP(name); - } + } tuning->bank = bank; tuning->prog = prog; @@ -69,7 +69,7 @@ void fluid_tuning_set_name(fluid_tuning_t* tuning, char* name) } if (name != NULL) { tuning->name = FLUID_STRDUP(name); - } + } } char* fluid_tuning_get_name(fluid_tuning_t* tuning) diff --git a/src/libs/fluidsynth/src/fluid_tuning.h b/src/libs/fluidsynth/src/fluid_tuning.h index 661a537921..4693f4ec34 100644 --- a/src/libs/fluidsynth/src/fluid_tuning.h +++ b/src/libs/fluidsynth/src/fluid_tuning.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA diff --git a/src/libs/fluidsynth/src/fluid_voice.c b/src/libs/fluidsynth/src/fluid_voice.c index a2dda2ef56..d8cc676b50 100644 --- a/src/libs/fluidsynth/src/fluid_voice.c +++ b/src/libs/fluidsynth/src/fluid_voice.c @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -27,23 +27,11 @@ #include "fluid_sys.h" #include "fluid_sfont.h" -#ifndef WITH_FLOAT -#ifdef ENABLE_SSE -#error "Can't use SSE extensions with other than float type!" -#endif -#endif - -#ifdef ENABLE_SSE -#include "fluid_sse.h" -float interp_coeff_sse_mem[FLUID_INTERP_MAX*4+4]; -sse_t* interp_coeff_sse; -#endif - /* used for filter turn off optimization - if filter cutoff is above the specified value and filter q is below the other value, turn filter off */ #define FLUID_MAX_AUDIBLE_FILTER_FC 19000.0f #define FLUID_MIN_AUDIBLE_FILTER_Q 1.2f - + /* Smallest amplitude that can be perceived (full scale is +/- 0.5) * 16 bits => 96+4=100 dB dynamic range => 0.00001 * 0.00001 * 2 is approximately 0.00003 :) @@ -52,87 +40,21 @@ sse_t* interp_coeff_sse; /* these should be the absolute minimum that FluidSynth can deal with */ #define FLUID_MIN_LOOP_SIZE 2 -#define FLUID_MIN_LOOP_PAD 1 +#define FLUID_MIN_LOOP_PAD 0 /* min vol envelope release (to stop clicks) in SoundFont timecents */ #define FLUID_MIN_VOLENVRELEASE -7200.0f /* ~16ms */ -fluid_interp_coeff_t interp_coeff[FLUID_INTERP_MAX]; -fluid_interp_coeff_t interp_coeff_linear[FLUID_INTERP_MAX]; -fluid_real_t sinc_table7[7][FLUID_INTERP_MAX]; - -/* - * fluid_voice_config - */ -void fluid_voice_config() -{ - int i; - double x; - -#ifdef ENABLE_SSE - sse_t* sse_a; - interp_coeff_sse = (sse_t*)FLUID_ALIGN16BYTE(&interp_coeff_sse_mem); -#endif - - /* 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].a0 = (fluid_real_t) (x * (-0.5 + x * (1 - 0.5 * x))); - interp_coeff[i].a1 = (fluid_real_t) (1.0 + x * x * (1.5 * x - 2.5)); - interp_coeff[i].a2 = (fluid_real_t) (x * (0.5 + x * (2.0 - 1.5 * x))); - interp_coeff[i].a3 = (fluid_real_t) (0.5 * x * x * (x - 1.0)); - - interp_coeff_linear[i].a0 = (fluid_real_t) (1. -x); - interp_coeff_linear[i].a1 = (fluid_real_t) x; - -#if 0 - interp_coeff[i].c0 = (signed int) (65536.0 * x * (-0.5 + x * (1 - 0.5 * x))); - interp_coeff[i].c1 = (signed int) (65536.0 * (1.0 + x * x * (1.5 * x - 2.5))); - interp_coeff[i].c2 = (signed int) (65536.0 * x * (0.5 + x * (2.0 - 1.5 * x))); - interp_coeff[i].c3 = (signed int) (65536.0 * 0.5 * x * x * (x - 1.0)); -#endif -#ifdef ENABLE_SSE - sse_a=&interp_coeff_sse[i]; - sse_a->sf[0]=interp_coeff[i].a0; - sse_a->sf[1]=interp_coeff[i].a1; - sse_a->sf[2]=interp_coeff[i].a2; - sse_a->sf[3]=interp_coeff[i].a3; -#endif -} - -#define sinc_interp_order 7 - /* i: Offset in terms of whole samples */ - for (i = 0; i < sinc_interp_order; i++){ - int ii; - /* ii: Offset in terms of fractional samples ('subsamples') */ - for (ii = 0; ii < FLUID_INTERP_MAX; ii++){ - /* Move the origin into the center of the table */ - double i_shifted=(double)i-((double)sinc_interp_order)/2. - + (double)ii/(double)FLUID_INTERP_MAX; - double v=1.; - - /* 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)); - } - sinc_table7[i][FLUID_INTERP_MAX-ii-1]=v; - } - } - fluid_check_fpe("interpolation table calculation"); -} +static inline void fluid_voice_effects (fluid_voice_t *voice, int count, + fluid_real_t* dsp_left_buf, + fluid_real_t* dsp_right_buf, + fluid_real_t* dsp_reverb_buf, + fluid_real_t* dsp_chorus_buf); /* * new_fluid_voice - */ -fluid_voice_t* + */ +fluid_voice_t* new_fluid_voice(fluid_real_t output_rate) { fluid_voice_t* voice; @@ -150,7 +72,7 @@ new_fluid_voice(fluid_real_t output_rate) voice->output_rate = output_rate; /* The 'sustain' and 'finished' segments of the volume / modulation - * envelope are constant. They are never affected by any modulator + * 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. */ @@ -184,7 +106,7 @@ new_fluid_voice(fluid_real_t output_rate) /* * delete_fluid_voice */ -int +int delete_fluid_voice(fluid_voice_t* voice) { if (voice == NULL) { @@ -198,16 +120,16 @@ delete_fluid_voice(fluid_voice_t* voice) * * Initialize the synthesis process */ -int -fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, - fluid_channel_t* channel, int key, int vel, unsigned int id, +int +fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, + 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. */ - + voice->id = id; voice->chan = fluid_channel_get_num(channel); @@ -230,8 +152,8 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, voice->volenv_val = 0.0f; voice->amp = 0.0f; /* The last value of the volume envelope, used to calculate the volume increment during - processing */ - + processing */ + /* mod env initialization*/ voice->modenv_count = 0; voice->modenv_section = 0; @@ -244,7 +166,7 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, /* vib lfo */ voice->viblfo_val = 0.0f; /* Fixme: See mod lfo */ - + /* Clear sample history in filter */ voice->hist1 = 0; voice->hist2 = 0; @@ -256,7 +178,7 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, * into voice parameters in * fluid_voice_calculate_runtime_synthesis_parameters. */ fluid_gen_init(&voice->gen[0], channel); - + voice->synth_gain = gain; /* avoid division by zero later*/ if (voice->synth_gain < 0.0000001){ @@ -264,17 +186,17 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, } /* For a looped sample, this value will be overwritten as soon as the - * loop parameters are initialized (they may depend on modulators). + * loop parameters are initialized (they may depend on modulators). * This value can be kept, it is a worst-case estimate. */ - voice->amplitude_that_reaches_noise_floor_nonloop = FLUID_NOISE_FLOOR / voice->synth_gain; - voice->amplitude_that_reaches_noise_floor_loop = FLUID_NOISE_FLOOR / voice->synth_gain; + voice->amplitude_that_reaches_noise_floor_nonloop = FLUID_NOISE_FLOOR / voice->synth_gain; + voice->amplitude_that_reaches_noise_floor_loop = FLUID_NOISE_FLOOR / voice->synth_gain; /* Increment the reference count of the sample to prevent the unloading of the soundfont while this voice is playing. */ fluid_sample_incr_ref(voice->sample); - + return FLUID_OK; } @@ -319,99 +241,63 @@ fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num) * the dsp parameters (all the control data boil down to only a few * dsp parameters). The dsp routine is #included in several places (fluid_dsp_core.c). */ -int +int fluid_voice_write(fluid_voice_t* voice, - fluid_real_t* dsp_left_buf, fluid_real_t* dsp_right_buf, + fluid_real_t* dsp_left_buf, fluid_real_t* dsp_right_buf, fluid_real_t* dsp_reverb_buf, fluid_real_t* dsp_chorus_buf) { - unsigned int i, start, end_in_buffer; + unsigned int i; fluid_real_t incr; - fluid_real_t fres; + fluid_real_t fres; + fluid_real_t target_amp; /* target amplitude */ + int count; - /* All variables starting with dsp_ are used by the DSP - loop. Documented in fluid_dsp_core.c */ - - int dsp_phase_index; - unsigned int dsp_i; - fluid_phase_t dsp_phase, dsp_phase_incr; - fluid_real_t dsp_incr; - fluid_real_t dsp_amp, dsp_amp_incr, dsp_centernode, dsp_hist1, dsp_hist2; - fluid_real_t dsp_b02, dsp_b1, dsp_a1, dsp_a2; - fluid_real_t dsp_a1_incr; - fluid_real_t dsp_a2_incr; - fluid_real_t dsp_b02_incr; - fluid_real_t dsp_b1_incr; - fluid_interp_coeff_t* dsp_coeff; - unsigned int dsp_start, dsp_end; - int dsp_filter_coeff_incr_count; - int dsp_use_filter_flag = 1; - short* dsp_data; int dsp_interp_method = voice->interp_method; - -#ifdef ENABLE_SSE - float mem_for_sse_interface[5*4+4]; /* Reserve memory */ - /* +4: add four floats for 16 added bytes */ - - /* Align the first element */ - sse_t* sse_n = (sse_t*) FLUID_ALIGN16BYTE(&mem_for_sse_interface); - sse_t* sse_a = sse_n++; /* The ++ operator increases - * by the size of the structure! */ - sse_t* sse_b = sse_n++; - sse_t* sse_c = sse_n++; - sse_t* sse_d = sse_n++; - sse_t* sse_e = sse_n++; - sse_t* sse_coeff; - - sse_t* sse_src; - sse_t* sse_dest_left; - sse_t* sse_dest_right; - sse_t* sse_dest; -#endif - - /* +4: add four floats for 16 added bytes */ - fluid_real_t dsp_buf_unaligned[FLUID_BUFSIZE+4]; - fluid_real_t* dsp_buf = (fluid_real_t*) FLUID_ALIGN16BYTE(&dsp_buf_unaligned); + fluid_real_t dsp_buf[FLUID_BUFSIZE]; fluid_env_data_t* env_data; fluid_real_t x; /* make sure we're playing and that we have sample data */ - if (!_PLAYING(voice)) { - return FLUID_OK; - } + if (!_PLAYING(voice)) return FLUID_OK; /******************* sample **********************/ - if (voice->sample == NULL) { + if (voice->sample == NULL) + { fluid_voice_off(voice); return FLUID_OK; } - - fluid_check_fpe("voice_write startup"); - /* Range checking for sample- and loop-related parameters + fluid_check_fpe ("voice_write startup"); + + /* Range checking for sample- and loop-related parameters * Initial phase is calculated here*/ - fluid_voice_check_sample_sanity(voice); + fluid_voice_check_sample_sanity (voice); /******************* vol env **********************/ env_data = &voice->volenv_data[voice->volenv_section]; /* skip to the next section of the envelope if necessary */ - while (voice->volenv_count >= env_data->count) { + while (voice->volenv_count >= env_data->count) + { env_data = &voice->volenv_data[++voice->volenv_section]; voice->volenv_count = 0; } /* calculate the envelope value and check for valid range */ x = env_data->coeff * voice->volenv_val + env_data->incr; - if (x < env_data->min) { - x = env_data->min; + if (x < env_data->min) + { + x = env_data->min; voice->volenv_section++; voice->volenv_count = 0; - } else if (x > env_data->max) { - x = env_data->max; + } + else if (x > env_data->max) + { + x = env_data->max; voice->volenv_section++; voice->volenv_count = 0; } @@ -419,19 +305,22 @@ fluid_voice_write(fluid_voice_t* voice, voice->volenv_val = x; voice->volenv_count++; - if (voice->volenv_section == FLUID_VOICE_ENVFINISHED) { - fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref); - fluid_voice_off(voice); + if (voice->volenv_section == FLUID_VOICE_ENVFINISHED) + { + fluid_profile (FLUID_PROF_VOICE_RELEASE, voice->ref); + fluid_voice_off (voice); return FLUID_OK; } - fluid_check_fpe("voice_write vol env"); + + fluid_check_fpe ("voice_write vol env"); /******************* mod env **********************/ env_data = &voice->modenv_data[voice->modenv_section]; /* skip to the next section of the envelope if necessary */ - while (voice->modenv_count >= env_data->count) { + while (voice->modenv_count >= env_data->count) + { env_data = &voice->modenv_data[++voice->modenv_section]; voice->modenv_count = 0; } @@ -439,85 +328,93 @@ fluid_voice_write(fluid_voice_t* voice, /* calculate the envelope value and check for valid range */ x = env_data->coeff * voice->modenv_val + env_data->incr; - if (x < env_data->min) { - x = env_data->min; + if (x < env_data->min) + { + x = env_data->min; voice->modenv_section++; voice->modenv_count = 0; - } else if (x > env_data->max) { - x = env_data->max; + } + else if (x > env_data->max) + { + x = env_data->max; voice->modenv_section++; voice->modenv_count = 0; } voice->modenv_val = x; voice->modenv_count++; - fluid_check_fpe("voice_write mod env"); + fluid_check_fpe ("voice_write mod env"); /******************* mod lfo **********************/ - if (voice->ticks >= voice->modlfo_delay) { + if (voice->ticks >= voice->modlfo_delay) + { voice->modlfo_val += voice->modlfo_incr; - if (voice->modlfo_val > 1.0) { + + if (voice->modlfo_val > 1.0) + { voice->modlfo_incr = -voice->modlfo_incr; voice->modlfo_val = (fluid_real_t) 2.0 - voice->modlfo_val; - } else if (voice->modlfo_val < -1.0) { + } + else if (voice->modlfo_val < -1.0) + { voice->modlfo_incr = -voice->modlfo_incr; voice->modlfo_val = (fluid_real_t) -2.0 - voice->modlfo_val; } } - fluid_check_fpe("voice_write mod LFO"); + + fluid_check_fpe ("voice_write mod LFO"); /******************* vib lfo **********************/ - if (voice->ticks >= voice->viblfo_delay) { + if (voice->ticks >= voice->viblfo_delay) + { voice->viblfo_val += voice->viblfo_incr; - if (voice->viblfo_val > (fluid_real_t) 1.0) { + + if (voice->viblfo_val > (fluid_real_t) 1.0) + { voice->viblfo_incr = -voice->viblfo_incr; voice->viblfo_val = (fluid_real_t) 2.0 - voice->viblfo_val; - } else if (voice->viblfo_val < -1.0) { + } + else if (voice->viblfo_val < -1.0) + { voice->viblfo_incr = -voice->viblfo_incr; voice->viblfo_val = (fluid_real_t) -2.0 - voice->viblfo_val; } } - fluid_check_fpe("voice_write Vib LFO"); - + + fluid_check_fpe ("voice_write Vib LFO"); + /******************* amplitude **********************/ - /* calculate final amplitude + /* calculate final amplitude * - initial gain * - amplitude envelope */ - if (voice->volenv_section == FLUID_VOICE_ENVDELAY) { - /* The volume amplitude is in hold phase. No sound is produced. */ - goto post_process; - } else if (voice->volenv_section == FLUID_VOICE_ENVATTACK) { + if (voice->volenv_section == FLUID_VOICE_ENVDELAY) + goto post_process; /* The volume amplitude is in hold phase. No sound is produced. */ + + if (voice->volenv_section == 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). */ - dsp_amp = fluid_atten2amp(voice->attenuation) + target_amp = fluid_atten2amp (voice->attenuation) * fluid_cb2amp (voice->modlfo_val * -voice->modlfo_to_vol) * voice->volenv_val; - } else { + } + else + { fluid_real_t amplitude_that_reaches_noise_floor; fluid_real_t amp_max; - dsp_amp = fluid_atten2amp(voice->attenuation) + target_amp = fluid_atten2amp (voice->attenuation) * fluid_cb2amp (960.0f * (1.0f - voice->volenv_val) + voice->modlfo_val * -voice->modlfo_to_vol); - /* Here we are trying to turn off a voice, if the volume has dropped - * low enough. - * Motivation: - * If voices are not turned off as soon as possible, the - * DSP loop burns a lot of CPU time producing sounds that no one - * can hear - * Problem: - * It would be tempting to just look at the attenuation, but then - * a voice terminates as soon as it is brought to 0 with a volume - * pedal (MIDI CC 7 or 11). - */ - + /* 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. @@ -526,340 +423,361 @@ fluid_voice_write(fluid_voice_t* voice, /* If the loop amplitude is known, we can use it if the voice loop is within * the sample loop */ -#if 0 - printf("%i %i %i %i %i %i\n", voice->has_looped, voice->sample->amplitude_that_reaches_noise_floor_is_valid, voice->loopstart, voice->loopend, voice->sample->loopstart, voice->sample->loopend ); -#endif - + /* Is the playing pointer already in the loop? */ - if (voice->has_looped){ - amplitude_that_reaches_noise_floor = voice->amplitude_that_reaches_noise_floor_loop; - } else { + if (voice->has_looped) + amplitude_that_reaches_noise_floor = voice->amplitude_that_reaches_noise_floor_loop; + else amplitude_that_reaches_noise_floor = voice->amplitude_that_reaches_noise_floor_nonloop; - }; -#if 0 - printf("Retrieving %f\n", amplitude_that_reaches_noise_floor); -#endif - + /* 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_atten2amp(voice->min_attenuation_cB) * voice->volenv_val; - - /* printf("Att min: %f Amp max: %f Limit: %f\n",voice->min_attenuation_cB,amp_max, amplitude_that_reaches_noise_floor); */ - -// printf("Amp max: %f\n",amp_max); + amp_max = fluid_atten2amp (voice->min_attenuation_cB) * voice->volenv_val; /* 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){ - fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref); -#if 0 - printf("Voice turned off! Amp is %f\n", amp_max); -#endif - fluid_voice_off(voice); - goto post_process; + if (amp_max < amplitude_that_reaches_noise_floor) + { + fluid_profile (FLUID_PROF_VOICE_RELEASE, voice->ref); + fluid_voice_off (voice); + goto post_process; } } - - /* At this point, dsp_amp is the desired amplitude for the voice. - * This value will be reached at the end of the next buffer. So we - * raise the amplitude smoothly from the current voice amplitude - * (voice->amp) to the wanted amplitude dsp_amp. - * - * By how much do we have to increase voice->amp, so that it reaches - * dsp_amp, when the increment is added FLUID_BUFSIZE times? */ - dsp_amp_incr = (dsp_amp - voice->amp) / FLUID_BUFSIZE; - /* dsp_amp will now be fed into the DSP loop. Use the amplitude, - * that came out of the last DSP loop run. */ - dsp_amp = voice->amp; - - fluid_check_fpe("voice_write amplitude calculation"); - if ((dsp_amp == 0.0f) && (dsp_amp_incr == 0.0f)) { - goto post_process; - } + /* Volume increment to go from voice->amp to target_amp in FLUID_BUFSIZE steps */ + voice->amp_incr = (target_amp - voice->amp) / FLUID_BUFSIZE; + + fluid_check_fpe ("voice_write amplitude calculation"); + + /* no volume and not changing? - No need to process */ + if ((voice->amp == 0.0f) && (voice->amp_incr == 0.0f)) + goto post_process; /* 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.*/ - incr = fluid_ct2hz_real(voice->pitch - + voice->modlfo_val * voice->modlfo_to_pitch - + voice->viblfo_val * voice->viblfo_to_pitch - + voice->modenv_val * voice->modenv_to_pitch) / voice->root_pitch; + voice->phase_incr = fluid_ct2hz_real + (voice->pitch + voice->modlfo_val * voice->modlfo_to_pitch + + voice->viblfo_val * voice->viblfo_to_pitch + + voice->modenv_val * voice->modenv_to_pitch) / voice->root_pitch; - /* Transfer the phase from the voice into the dsp loop parameter - dsp_phase */ - fluid_phase_set(dsp_phase, voice->phase); + fluid_check_fpe ("voice_write phase calculation"); - /* Convert the 'speed' through the original waveform to a - * representation 'integer part' and 'fractional part' */ - fluid_phase_set_float(dsp_phase_incr, incr); - /* incr *= 1.00000000000001; FIXME: gcc optimization problem. Quick fix. [Commented out. Don't understand the problem, PH] */ - fluid_check_fpe("voice_write phase calculation"); - - /* Check, if we are really making progress through the original - * sample. If the step size is rounded to 0, the DSP loop would get - * stuck. */ - /* [PH] I commented this out. The first time a voice is called, dsp_phase - * will be zero. Settings the fractionnal part of the phase to - * non-zero, causes the sample to be interpolated even if it is - * played a the root key (cfr. fluid_dsp_float.c:96: - * if ((fluid_phase_fract(dsp_phase) == 0))) - * - * I replaced it with a check on the phase increment. - */ -/* if ((fluid_phase_index(dsp_phase) == 0) && (fluid_phase_fract(dsp_phase) == 0)) { */ -/* fluid_phase_fract(dsp_phase) = 1; */ -/* } */ - if ((fluid_phase_index(dsp_phase_incr) == 0) && (fluid_phase_fract(dsp_phase_incr) == 0)) { - fluid_phase_fract(dsp_phase_incr) = 1; - } + /* if phase_incr is not advancing, set it to the minimum fraction value (prevent stuckage) */ + if (voice->phase_incr == 0) voice->phase_incr = 1; /*************** resonant filter ******************/ /* calculate the frequency of the resonant filter in Hz */ - fres = fluid_ct2hz(voice->fres - + voice->modlfo_val * voice->modlfo_to_fc + fres = fluid_ct2hz(voice->fres + + voice->modlfo_val * voice->modlfo_to_fc + voice->modenv_val * voice->modenv_to_fc); - /* Testcase for filter resonance: Use the following line, and press - * A3. There should be a _very_ pronounced resonant peak, which - * drops down, when moving the pitch bend wheel only slightly. */ - //fres=440;voice->q_lin=100; - - /* FIXME - Still potential for a click during turn on, can we interpolate between 20khz cutoff and 0 Q? */ - /* if filter has not yet started and filter cutoff and Q don't - exceed "audible" thresholds, then don't turn on the filter. - Once the filter is turned on, it remains on. */ -/* if (voice->filter_startup */ -/* && (fres > FLUID_MAX_AUDIBLE_FILTER_FC) */ -/* && (voice->q_lin < FLUID_MIN_AUDIBLE_FILTER_Q)) { */ -/* dsp_use_filter_flag = 0; */ -/* } else if (fres < 5) { */ -/* fres = 5; */ -/* } */ - /* I removed the optimization of turning the filter off when the * resonance frequence is above the maximum frequency. Instead, the - * filter frequence is set to a maximum of 0.45 times the sampling + * 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 reasing is that were problems with anti-aliasing when the + * 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 * voice->output_rate) { - fres = 0.45f * voice->output_rate; - } else if (fres < 5) { + if (fres > 0.45f * voice->output_rate) + fres = 0.45f * voice->output_rate; + else if (fres < 5) fres = 5; - } - /* if filter enabled and there is a significant frequency change.. */ - if (/*dsp_use_filter_flag &&*/ (abs(fres - voice->last_fres) > 0.01)) { + if ((abs (fres - voice->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. + * + * 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'. */ - /* 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. - * - * 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 * (fres / 44100.0f)); - 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 * voice->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: - * voice->b0=(1.-cos_coeff)*a0_inv*0.5*voice->filter_gain; - * voice->b1=(1.-cos_coeff)*a0_inv*voice->filter_gain; - * voice->b2=(1.-cos_coeff)*a0_inv*0.5*voice->filter_gain; */ - - 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 b1_temp = (1.0f - cos_coeff) * a0_inv * voice->filter_gain; - /* both b0 -and- b2 */ - fluid_real_t b02_temp = b1_temp * 0.5f; + fluid_real_t omega = (fluid_real_t) (2.0 * M_PI * (fres / 44100.0f)); + 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 * voice->q_lin); + fluid_real_t a0_inv = 1.0f / (1.0f + alpha_coeff); - if (voice->filter_startup) { - /* The filter is calculated, because the voice was started up. - * In this case set the filter coefficients without delay. - */ - voice->a1 = a1_temp; - voice->a2 = a2_temp; - voice->b02 = b02_temp; - voice->b1 = b1_temp; - voice->filter_coeff_incr_count = 0; - voice->filter_startup = 0; + /* 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: + * voice->b0=(1.-cos_coeff)*a0_inv*0.5*voice->filter_gain; + * voice->b1=(1.-cos_coeff)*a0_inv*voice->filter_gain; + * voice->b2=(1.-cos_coeff)*a0_inv*0.5*voice->filter_gain; */ + + 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 b1_temp = (1.0f - cos_coeff) * a0_inv * voice->filter_gain; + /* both b0 -and- b2 */ + fluid_real_t b02_temp = b1_temp * 0.5f; + + if (voice->filter_startup) + { + /* The filter is calculated, because the voice was started up. + * In this case set the filter coefficients without delay. + */ + voice->a1 = a1_temp; + voice->a2 = a2_temp; + voice->b02 = b02_temp; + voice->b1 = b1_temp; + voice->filter_coeff_incr_count = 0; + voice->filter_startup = 0; // printf("Setting initial filter coefficients.\n"); - } else { + } + 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. - */ + /* 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. + */ #define FILTER_TRANSITION_SAMPLES (FLUID_BUFSIZE) - voice->a1_incr = (a1_temp - voice->a1) / FILTER_TRANSITION_SAMPLES; - voice->a2_incr = (a2_temp - voice->a2) / FILTER_TRANSITION_SAMPLES; - voice->b02_incr = (b02_temp - voice->b02) / FILTER_TRANSITION_SAMPLES; - voice->b1_incr = (b1_temp - voice->b1) / FILTER_TRANSITION_SAMPLES; - /* Have to add the increments filter_coeff_incr_count times. */ - voice->filter_coeff_incr_count = FILTER_TRANSITION_SAMPLES; - } - voice->last_fres = fres; - fluid_check_fpe("voice_write filter calculation"); - } + voice->a1_incr = (a1_temp - voice->a1) / FILTER_TRANSITION_SAMPLES; + voice->a2_incr = (a2_temp - voice->a2) / FILTER_TRANSITION_SAMPLES; + voice->b02_incr = (b02_temp - voice->b02) / FILTER_TRANSITION_SAMPLES; + voice->b1_incr = (b1_temp - voice->b1) / FILTER_TRANSITION_SAMPLES; + /* Have to add the increments filter_coeff_incr_count times. */ + voice->filter_coeff_incr_count = FILTER_TRANSITION_SAMPLES; + } + voice->last_fres = fres; + fluid_check_fpe ("voice_write filter calculation"); + } - /* Now we set up the variables, that go into the DSP routine. For documentation, - * see fluid_dsp_core.c - */ - /* Sample waveform data */ - dsp_data = voice->sample->data; - - /* IIR filter sample history */ - dsp_hist1 = voice->hist1; - dsp_hist2 = voice->hist2; - /* IIR filter coefficients */ - dsp_a1 = voice->a1; - dsp_a2 = voice->a2; - dsp_b02 = voice->b02; - dsp_b1 = voice->b1; - dsp_a1_incr = voice->a1_incr; - dsp_a2_incr = voice->a2_incr; - dsp_b02_incr = voice->b02_incr; - dsp_b1_incr = voice->b1_incr; - dsp_filter_coeff_incr_count = voice->filter_coeff_incr_count; - - fluid_check_fpe("voice_write DSP coefficients"); + fluid_check_fpe ("voice_write DSP coefficients"); /*********************** run the dsp chain ************************ - * The sample is mixed with the output buffer. + * 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 + * Depending on the position in the loop and the loop size, this * may require several runs. */ - fluid_check_fpe("voice_write DSP processing"); - if (((_SAMPLEMODE(voice) == FLUID_LOOP_UNTIL_RELEASE) && (voice->volenv_section < FLUID_VOICE_ENVRELEASE)) - || (_SAMPLEMODE(voice) == FLUID_LOOP_DURING_RELEASE)) { + voice->dsp_buf = dsp_buf; - /* At which index does the loop point occur in the output buffer? - * This calculates the first index in the buffer, which uses - * sample data taken after the looparound. */ - end_in_buffer = fluid_phase_steps(dsp_phase, voice->loopend, incr); - - if (end_in_buffer >= FLUID_BUFSIZE) { - /* The loop occurs after the end of the buffer. - * Process the whole buffer in one run. */ - dsp_start = 0; - dsp_end = FLUID_BUFSIZE; -#include "fluid_dsp_core.c" + switch (voice->interp_method) + { + case FLUID_INTERP_NONE: + count = fluid_dsp_float_interpolate_none (voice); + break; + case FLUID_INTERP_LINEAR: + count = fluid_dsp_float_interpolate_linear (voice); + break; + case FLUID_INTERP_4THORDER: + default: + count = fluid_dsp_float_interpolate_4th_order (voice); + break; + case FLUID_INTERP_7THORDER: + count = fluid_dsp_float_interpolate_7th_order (voice); + break; + } - } else { - /* The loop occurs during the current buffer length. Note, that - * this method is unable to cope with a 'skipped' loop point. * - * If, by means of witchcraft, evil magic or modulators, we end - * up beyond * the loop point, a SEGV is unavoidable. * We - * can't even detect this here, because the calculations are - * done using * unsigned ints (only positive), and end_in_buffer - * would be negative * for a skipped loop point...*/ - start = 0; + fluid_check_fpe ("voice_write interpolation"); - while (end_in_buffer < FLUID_BUFSIZE) { + if (count > 0) + fluid_voice_effects (voice, count, dsp_left_buf, dsp_right_buf, + dsp_reverb_buf, dsp_chorus_buf); - dsp_start = start; - dsp_end = end_in_buffer; -#include "fluid_dsp_core.c" - - /* loop */ - fluid_phase_sub_int(dsp_phase, voice->loopend - voice->loopstart); - start = end_in_buffer; - end_in_buffer += fluid_phase_steps(dsp_phase, voice->loopend, incr); - } - voice->has_looped=1; - dsp_start = start; - dsp_end = FLUID_BUFSIZE; -#include "fluid_dsp_core.c" - } - - } else { - /* Not looping right now. */ - - dsp_start = 0; - end_in_buffer = fluid_phase_steps(dsp_phase, voice->end, incr); - - if (end_in_buffer >= FLUID_BUFSIZE) { - /* Run the whole buffer at once */ - dsp_end = FLUID_BUFSIZE; -#include "fluid_dsp_core.c" - } else { - /* The sample ends in the middle of the buffer length. - * Process that far, and turn the voice off. - */ - dsp_end = end_in_buffer; -#include "fluid_dsp_core.c" + /* turn off voice if short count (sample ended and not looping) */ + if (count < FLUID_BUFSIZE) + { fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref); fluid_voice_off(voice); - goto post_process; + } + + post_process: + voice->ticks += FLUID_BUFSIZE; + fluid_check_fpe ("voice_write postprocess"); + return FLUID_OK; +} + + +/* Purpose: + * + * - filters (applies a lowpass filter with variable cutoff frequency and quality factor) + * - mixes the processed sample to left and right output using the pan setting + * - sends the processed sample to chorus and reverb + * + * Variable description: + * - dsp_data: Pointer to the original waveform data + * - dsp_left_buf: The generated signal goes here, left channel + * - dsp_right_buf: right channel + * - dsp_reverb_buf: Send to reverb unit + * - dsp_chorus_buf: Send to chorus unit + * - dsp_a1: Coefficient for the filter + * - dsp_a2: same + * - dsp_b0: same + * - dsp_b1: same + * - dsp_b2: same + * - voice holds the voice structure + * + * A couple of variables are used internally, their results are discarded: + * - dsp_i: Index through the output buffer + * - dsp_phase_fractional: The fractional part of dsp_phase + * - dsp_coeff: A table of four coefficients, depending on the fractional phase. + * Used to interpolate between samples. + * - dsp_process_buffer: Holds the processed signal between stages + * - dsp_centernode: delay line for the IIR filter + * - dsp_hist1: same + * - dsp_hist2: same + * + */ +static inline void +fluid_voice_effects (fluid_voice_t *voice, int count, + fluid_real_t* dsp_left_buf, fluid_real_t* dsp_right_buf, + fluid_real_t* dsp_reverb_buf, fluid_real_t* dsp_chorus_buf) +{ + /* IIR filter sample history */ + fluid_real_t dsp_hist1 = voice->hist1; + fluid_real_t dsp_hist2 = voice->hist2; + + /* IIR filter coefficients */ + fluid_real_t dsp_a1 = voice->a1; + fluid_real_t dsp_a2 = voice->a2; + fluid_real_t dsp_b02 = voice->b02; + fluid_real_t dsp_b1 = voice->b1; + fluid_real_t dsp_a1_incr = voice->a1_incr; + fluid_real_t dsp_a2_incr = voice->a2_incr; + fluid_real_t dsp_b02_incr = voice->b02_incr; + fluid_real_t dsp_b1_incr = voice->b1_incr; + int dsp_filter_coeff_incr_count = voice->filter_coeff_incr_count; + + fluid_real_t *dsp_buf = voice->dsp_buf; + + fluid_real_t dsp_centernode; + int dsp_i; + float v; + + /* 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) + { + /* 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) + { + dsp_a1 += dsp_a1_incr; + dsp_a2 += dsp_a2_incr; + dsp_b02 += dsp_b02_incr; + dsp_b1 += dsp_b1_incr; + } + } /* 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; } } - /*************** finishing ******************/ - /* copy back the state for the next cycle */ + /* pan (Copy the signal to the left and right output buffer) The voice + * panning generator has a range of -500 .. 500. If it is centered, + * it's close to 0. voice->amp_left and voice->amp_right are then the + * same, and we can save one multiplication per voice and sample. + */ + if ((-0.5 < voice->pan) && (voice->pan < 0.5)) + { + /* The voice is centered. Use voice->amp_left twice. */ + for (dsp_i = 0; dsp_i < count; dsp_i++) + { + v = voice->amp_left * dsp_buf[dsp_i]; + dsp_left_buf[dsp_i] += v; + dsp_right_buf[dsp_i] += v; + } + } + else /* The voice is not centered. Stereo samples have one side zero. */ + { + if (voice->amp_left != 0.0) + { + for (dsp_i = 0; dsp_i < count; dsp_i++) + dsp_left_buf[dsp_i] += voice->amp_left * dsp_buf[dsp_i]; + } + + if (voice->amp_right != 0.0) + { + for (dsp_i = 0; dsp_i < count; dsp_i++) + dsp_right_buf[dsp_i] += voice->amp_right * dsp_buf[dsp_i]; + } + } + + /* reverb send. Buffer may be NULL. */ + if ((dsp_reverb_buf != NULL) && (voice->amp_reverb != 0.0)) + { + for (dsp_i = 0; dsp_i < count; dsp_i++) + dsp_reverb_buf[dsp_i] += voice->amp_reverb * dsp_buf[dsp_i]; + } + + /* chorus send. Buffer may be NULL. */ + if ((dsp_chorus_buf != NULL) && (voice->amp_chorus != 0)) + { + for (dsp_i = 0; dsp_i < count; dsp_i++) + dsp_chorus_buf[dsp_i] += voice->amp_chorus * dsp_buf[dsp_i]; + } voice->hist1 = dsp_hist1; voice->hist2 = dsp_hist2; - voice->phase = dsp_phase; - voice->amp = dsp_amp; voice->a1 = dsp_a1; voice->a2 = dsp_a2; voice->b02 = dsp_b02; voice->b1 = dsp_b1; voice->filter_coeff_incr_count = dsp_filter_coeff_incr_count; -/* if (dsp_filter_coeff_incr_count) { */ -/* printf("ticks = %d, dsp_filter_coeff_incr_count = %d\n", */ -/* voice->ticks, dsp_filter_coeff_incr_count); */ -/* } */ - - post_process: - voice->ticks += FLUID_BUFSIZE; - fluid_check_fpe("voice_write postprocess"); - return FLUID_OK; + fluid_check_fpe ("voice_effects"); } /* * fluid_voice_get_channel */ -fluid_channel_t* +fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice) { return voice->channel; @@ -870,12 +788,12 @@ fluid_voice_get_channel(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); - + /* Force setting of the phase at the first DSP loop run * This cannot be done earlier, because it depends on modulators.*/ voice->check_sample_sanity_flag=FLUID_SAMPLESANITY_STARTUP; @@ -895,7 +813,7 @@ void fluid_voice_start(fluid_voice_t* voice) * conversion will be done in the DSP function. This is the case, for * example, for the pitch since it is modulated by the controllers in * cents. */ -int +int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice) { fluid_real_t x; @@ -948,13 +866,13 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice) GEN_KEYNUM, /* #46 */ GEN_VELOCITY, /* #47 */ GEN_ATTENUATION, /* #48 */ - /* GEN_ENDLOOPADDRCOARSEOFS [1] #50 */ + /* GEN_ENDLOOPADDRCOARSEOFS [1] #50 */ /* GEN_COARSETUNE [1] #51 */ /* GEN_FINETUNE [1] #52 */ GEN_OVERRIDEROOTKEY, /* #58 */ GEN_PITCH, /* --- */ -1}; /* end-of-list marker */ - + /* When the voice is made ready for the synthesis process, a lot of * voice-internal parameters have to be calculated. * @@ -981,7 +899,7 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice) fluid_gen_t* dest_gen = &voice->gen[dest_gen_index]; dest_gen->mod += modval; /* fluid_dump_modulator(mod); */ - } + } /* The GEN_PITCH is a hack to fit the pitch bend controller into the * modulator paradigm. Now the nominal pitch of the key is set. @@ -994,10 +912,10 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice) /* pitch(60) + scale * (pitch(key) - pitch(60)) */ #define __pitch(_k) fluid_tuning_get_pitch(tuning, _k) fluid_tuning_t* tuning = fluid_channel_get_tuning(voice->channel); - voice->gen[GEN_PITCH].val = (__pitch(60) + (voice->gen[GEN_SCALETUNE].val / 100.0f * + voice->gen[GEN_PITCH].val = (__pitch(60) + (voice->gen[GEN_SCALETUNE].val / 100.0f * (__pitch(voice->key) - __pitch(60)))); } else { - voice->gen[GEN_PITCH].val = (voice->gen[GEN_SCALETUNE].val * (voice->key - 60.0f) + voice->gen[GEN_PITCH].val = (voice->gen[GEN_SCALETUNE].val * (voice->key - 60.0f) + 100.0f * 60.0f); } @@ -1013,7 +931,7 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* 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 (i = 0; list_of_generators_to_initialize[i] != -1; i++) { fluid_voice_update_param(voice, list_of_generators_to_initialize[i]); @@ -1021,14 +939,14 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice) /* Make an estimate on how loud this voice can get at any time (attenuation). */ voice->min_attenuation_cB = fluid_voice_get_lower_boundary_for_attenuation(voice); - + return FLUID_OK; } -/* +/* * calculate_hold_decay_buffers */ -int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, +int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, int gen_key2base, int is_decay) { /* Purpose: @@ -1039,7 +957,7 @@ int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, * GEN_MODENVDECAY gen_key2base=GEN_KEYTOVOLENVHOLD, * GEN_KEYTOVOLENVDECAY, GEN_KEYTOMODENVHOLD, GEN_KEYTOMODENVDECAY */ - + fluid_real_t timecents; fluid_real_t seconds; int buffers; @@ -1052,7 +970,7 @@ int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, * The time is cut in half. */ timecents = (_GEN(voice, gen_base) + _GEN(voice, gen_key2base) * (60.0 - voice->key)); - + /* Range checking */ if (is_decay){ /* SF 2.01 section 8.1.3 # 28, 36 */ @@ -1061,11 +979,11 @@ int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, } } else { /* SF 2.01 section 8.1.3 # 27, 35 */ - if (timecents > 5000) { + if (timecents > 5000) { timecents = 5000.0; } /* SF 2.01 section 8.1.2 # 27, 35: - * The most negative number indicates no hold time + * The most negative number indicates no hold time */ if (timecents <= -32768.) { return 0; @@ -1075,12 +993,12 @@ int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, if (timecents < -12000.0) { timecents = -12000.0; } - + 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) + buffers = (int)(((fluid_real_t)voice->output_rate * seconds) / (fluid_real_t)FLUID_BUFSIZE +0.5); @@ -1090,7 +1008,7 @@ int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, /* * fluid_voice_update_param * - * Purpose: + * Purpose: * * The value of a generator (gen) has changed. (The different * generators are listed in fluidsynth.h, or in SF2.01 page 48-49) @@ -1106,7 +1024,7 @@ int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, * NRPN system. _GEN(voice, generator_enumerator) returns the sum * of all three. */ -void +void fluid_voice_update_param(fluid_voice_t* voice, int gen) { double q_dB; @@ -1115,33 +1033,33 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) unsigned int count; switch (gen) { - + case GEN_PAN: /* range checking is done in the fluid_pan function */ voice->pan = _GEN(voice, GEN_PAN); voice->amp_left = fluid_pan(voice->pan, 1) * voice->synth_gain / 32768.0f; voice->amp_right = fluid_pan(voice->pan, 0) * voice->synth_gain / 32768.0f; break; - + case GEN_ATTENUATION: voice->attenuation = _GEN(voice, GEN_ATTENUATION); - /* Range: SF2.01 section 8.1.3 # 48 - * Motivation for range checking: + /* 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); break; - - /* The pitch is calculated from three different generators. - * Read comment in fluidsynth.h about GEN_PITCH. + + /* 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 = (_GEN(voice, GEN_PITCH) - + 100.0f * _GEN(voice, GEN_COARSETUNE) - + _GEN(voice, GEN_FINETUNE)); + voice->pitch = (_GEN(voice, GEN_PITCH) + + 100.0f * _GEN(voice, GEN_COARSETUNE) + + _GEN(voice, GEN_FINETUNE)); break; case GEN_REVERBSEND: @@ -1155,7 +1073,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) /* The generator unit is 'tenths of a percent'. */ voice->chorus_send = _GEN(voice, GEN_CHORUSSEND) / 1000.0f; fluid_clip(voice->chorus_send, 0.0, 1.0); - voice->amp_chorus = voice->chorus_send * voice->synth_gain / 32768.0f; + voice->amp_chorus = voice->chorus_send * voice->synth_gain / 32768.0f; break; case GEN_OVERRIDEROOTKEY: @@ -1194,10 +1112,10 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) /* The generator contains 'centibels' (1/10 dB) => divide by 10 to * obtain dB */ q_dB = _GEN(voice, GEN_FILTERQ) / 10.0f; - + /* Range: SF2.01 section 8.1.3 # 8 (convert from cB to dB => /10) */ fluid_clip(q_dB, 0.0f, 96.0f); - + /* Short version: Modify the Q definition in a way, that a Q of 0 * dB leads to no resonance hump in the freq. response. * @@ -1214,7 +1132,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) * 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. */ voice->q_lin = (fluid_real_t) (pow(10.0f, q_dB / 20.0f)); @@ -1231,16 +1149,16 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) * only on Q, so this is the right place to calculate it. */ voice->filter_gain = (fluid_real_t) (1.0 / sqrt(voice->q_lin)); - + /* The synthesis loop will have to recalculate the filter coefficients. */ voice->last_fres = -1.; break; - + case GEN_MODLFOTOPITCH: voice->modlfo_to_pitch = _GEN(voice, GEN_MODLFOTOPITCH); fluid_clip(voice->modlfo_to_pitch, -12000.0, 12000.0); break; - + case GEN_MODLFOTOVOL: voice->modlfo_to_vol = _GEN(voice, GEN_MODLFOTOVOL); fluid_clip(voice->modlfo_to_vol, -960.0, 960.0); @@ -1250,7 +1168,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->modlfo_to_fc = _GEN(voice, GEN_MODLFOTOFILTERFC); fluid_clip(voice->modlfo_to_fc, -12000, 12000); break; - + case GEN_MODLFODELAY: x = _GEN(voice, GEN_MODLFODELAY); fluid_clip(x, -12000.0f, 5000.0f); @@ -1267,7 +1185,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) break; case GEN_VIBLFOFREQ: - /* vib lfo + /* vib lfo * * - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples * - the delay into a sample delay @@ -1276,18 +1194,18 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) fluid_clip(x, -16000.0f, 4500.0f); voice->viblfo_incr = (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate); break; - + case GEN_VIBLFODELAY: x = _GEN(voice,GEN_VIBLFODELAY); fluid_clip(x, -12000.0f, 5000.0f); voice->viblfo_delay = (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x)); break; - + case GEN_VIBLFOTOPITCH: voice->viblfo_to_pitch = _GEN(voice, GEN_VIBLFOTOPITCH); fluid_clip(voice->viblfo_to_pitch, -12000.0, 12000.0); break; - + case GEN_KEYNUM: /* GEN_KEYNUM: SF2.01 page 46, item 46 * @@ -1302,7 +1220,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->key = x; } break; - + case GEN_VELOCITY: /* GEN_VELOCITY: SF2.01 page 46, item 47 * @@ -1316,33 +1234,33 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->vel = x; } break; - + case GEN_MODENVTOPITCH: voice->modenv_to_pitch = _GEN(voice, GEN_MODENVTOPITCH); fluid_clip(voice->modenv_to_pitch, -12000.0, 12000.0); break; - + case GEN_MODENVTOFILTERFC: voice->modenv_to_fc = _GEN(voice,GEN_MODENVTOFILTERFC); - /* Range: SF2.01 section 8.1.3 # 1 - * Motivation for range checking: + /* Range: SF2.01 section 8.1.3 # 1 + * Motivation for range checking: * Filter is reported to make funny noises now and then */ fluid_clip(voice->modenv_to_fc, -12000.0, 12000.0); break; - - - /* sample start and ends points - * - * Range checking is initiated via the + + + /* sample start and ends points + * + * Range checking is initiated via the * voice->check_sample_sanity flag, * because it is impossible to check here: * During the voice setup, all modulators are processed, while * the voice is inactive. Therefore, illegal settings may * occur during the setup (for example: First move the loop * end point ahead of the loop start point => invalid, then - * move the loop start point forward => valid again. + * 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 */ @@ -1355,7 +1273,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) 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) { + if (voice->sample != NULL) { voice->end = (voice->sample->end + (int) _GEN(voice, GEN_ENDADDROFS) + 32768 * (int) _GEN(voice, GEN_ENDADDRCOARSEOFS)); @@ -1371,7 +1289,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->check_sample_sanity_flag = FLUID_SAMPLESANITY_CHECK; } 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) { @@ -1403,7 +1321,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->volenv_data[FLUID_VOICE_ENVDELAY].min = -1.0f; voice->volenv_data[FLUID_VOICE_ENVDELAY].max = 1.0f; break; - + case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */ x = _GEN(voice, GEN_VOLENVATTACK); fluid_clip(x, -12000.0f, 8000.0f); @@ -1448,7 +1366,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->volenv_data[FLUID_VOICE_ENVRELEASE].min = 0.0f; voice->volenv_data[FLUID_VOICE_ENVRELEASE].max = 1.0f; break; - + /* Modulation envelope */ case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */ x = _GEN(voice, GEN_MODENVDELAY); @@ -1459,7 +1377,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->modenv_data[FLUID_VOICE_ENVDELAY].min = -1.0f; voice->modenv_data[FLUID_VOICE_ENVDELAY].max = 1.0f; break; - + case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */ x = _GEN(voice, GEN_MODENVATTACK); fluid_clip(x, -12000.0f, 8000.0f); @@ -1470,7 +1388,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->modenv_data[FLUID_VOICE_ENVATTACK].min = -1.0f; voice->modenv_data[FLUID_VOICE_ENVATTACK].max = 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 */ @@ -1493,7 +1411,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) voice->modenv_data[FLUID_VOICE_ENVDECAY].min = y; voice->modenv_data[FLUID_VOICE_ENVDECAY].max = 2.0f; break; - + case GEN_MODENVRELEASE: /* SF 2.01 section 8.1.3 # 30 */ x = _GEN(voice, GEN_MODENVRELEASE); fluid_clip(x, -12000.0f, 8000.0f); @@ -1528,7 +1446,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen) * modulators. * * - For every changed generator, convert its value to the correct - * unit of the corresponding DSP parameter + * unit of the corresponding DSP parameter * * @fn int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl, int val) * @param voice the synthesis voice @@ -1541,9 +1459,9 @@ int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl) 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); */ - + for (i = 0; i < voice->mod_count; i++) { mod = &voice->mod[i]; @@ -1571,7 +1489,7 @@ int fluid_voice_modulate(fluid_voice_t* voice, int cc, int ctrl) fluid_voice_update_param(voice, gen); } } - return FLUID_OK; + return FLUID_OK; } /** @@ -1587,7 +1505,7 @@ int fluid_voice_modulate_all(fluid_voice_t* voice) 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' @@ -1617,13 +1535,13 @@ int fluid_voice_modulate_all(fluid_voice_t* voice) fluid_voice_update_param(voice, gen); } - return FLUID_OK; + return FLUID_OK; } /* * fluid_voice_noteoff */ -int +int fluid_voice_noteoff(fluid_voice_t* voice) { fluid_profile(FLUID_PROF_VOICE_NOTE, voice->ref); @@ -1655,7 +1573,7 @@ fluid_voice_noteoff(fluid_voice_t* voice) return FLUID_OK; } -/* +/* * fluid_voice_kill_excl * * Percussion sounds can be mutually exclusive: for example, a 'closed @@ -1666,15 +1584,15 @@ fluid_voice_noteoff(fluid_voice_t* voice) * or channel. fluid_voice_kill_excl gets called, when 'voice' is to * be killed for that reason. */ -int +int fluid_voice_kill_excl(fluid_voice_t* voice){ if (!_PLAYING(voice)) { return FLUID_OK; } - + /* Turn off the exclusive class information for this voice, - so that it doesn't get killed twice + so that it doesn't get killed twice */ fluid_voice_gen_set(voice, GEN_EXCLUSIVECLASS, 0); @@ -1685,27 +1603,27 @@ fluid_voice_kill_excl(fluid_voice_t* voice){ voice->modenv_section = FLUID_VOICE_ENVRELEASE; voice->modenv_count = 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); - - return FLUID_OK; + + return FLUID_OK; } /* * fluid_voice_off - * + * * Purpose: * Turns off a voice, meaning that it is not processed * anymore by the DSP loop. */ -int +int fluid_voice_off(fluid_voice_t* voice) { fluid_profile(FLUID_PROF_VOICE_RELEASE, voice->ref); @@ -1718,9 +1636,10 @@ fluid_voice_off(fluid_voice_t* voice) voice->status = FLUID_VOICE_OFF; /* Decrement the reference count of the sample. */ - fluid_sample_decr_ref(voice->sample); - - voice->sample = NULL; + if (voice->sample) { + fluid_sample_decr_ref(voice->sample); + voice->sample = NULL; + } return FLUID_OK; } @@ -1736,20 +1655,20 @@ fluid_voice_off(fluid_voice_t* voice) * mode == FLUID_VOICE_DEFAULT: This is a default modulator, there can be no identical modulator. * Don't check. */ -void +void fluid_voice_add_mod(fluid_voice_t* voice, fluid_mod_t* mod, int mode) { 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. + * sound card. Discard them, maybe print a warning. */ - if (((mod->flags1 & FLUID_MOD_CC) == 0) - && ((mod->src1 != 0) /* SF2.01 section 8.2.1: Constant value */ - && (mod->src1 != 2) /* Note-on velocity */ + if (((mod->flags1 & FLUID_MOD_CC) == 0) + && ((mod->src1 != 0) /* SF2.01 section 8.2.1: Constant value */ + && (mod->src1 != 2) /* Note-on velocity */ && (mod->src1 != 3) /* Note-on key number */ && (mod->src1 != 10) /* Poly pressure */ && (mod->src1 != 13) /* Channel pressure */ @@ -1771,7 +1690,7 @@ fluid_voice_add_mod(fluid_voice_t* voice, fluid_mod_t* mod, int mode) } } else if (mode == FLUID_VOICE_OVERWRITE) { - + /* 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)) { @@ -1779,7 +1698,7 @@ fluid_voice_add_mod(fluid_voice_t* voice, fluid_mod_t* mod, int mode) voice->mod[i].amount = mod->amount; return; } - } + } } /* Add a new modulator (No existing modulator to add / overwrite). @@ -1823,15 +1742,15 @@ fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice 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))) { - + 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) - || (mod->flags1 & FLUID_MOD_BIPOLAR) - || (mod->flags2 & FLUID_MOD_BIPOLAR) + if ((mod->src1 == FLUID_MOD_PITCHWHEEL) + || (mod->flags1 & FLUID_MOD_BIPOLAR) + || (mod->flags2 & FLUID_MOD_BIPOLAR) || (mod->amount < 0)) { /* Can this modulator produce a negative contribution? */ v *= -1.0; @@ -1840,19 +1759,19 @@ fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice v = 0; } - /* For example: + /* For example: * - current_val=100 * - min_val=-4000 * - possible_att_reduction_cB += 4100 */ if (current_val > v){ - possible_att_reduction_cB += (current_val - v); + possible_att_reduction_cB += (current_val - v); } } } - + lower_bound = voice->attenuation-possible_att_reduction_cB; - + /* SF2.01 specs do not allow negative attenuation */ if (lower_bound < 0) { lower_bound = 0; @@ -1873,7 +1792,7 @@ void fluid_voice_check_sample_sanity(fluid_voice_t* voice) /* make sure we have enough samples surrounding the loop */ int min_index_loop=(int) voice->sample->start + FLUID_MIN_LOOP_PAD; - int max_index_loop=(int) voice->sample->end - FLUID_MIN_LOOP_PAD; + int max_index_loop=(int) voice->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 (!voice->check_sample_sanity_flag){ @@ -1900,7 +1819,7 @@ void fluid_voice_check_sample_sanity(fluid_voice_t* voice) } else if (voice->end > max_index_nonloop){ voice->end = max_index_nonloop; } - + /* Keep start and end point in the right order */ if (voice->start > voice->end){ int temp = voice->start; @@ -1908,14 +1827,14 @@ void fluid_voice_check_sample_sanity(fluid_voice_t* voice) voice->end = temp; /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of start / end points!"); */ } - + /* Zero length? */ if (voice->start == voice->end){ fluid_voice_off(voice); return; } - if ((_SAMPLEMODE(voice) == FLUID_LOOP_UNTIL_RELEASE) + if ((_SAMPLEMODE(voice) == FLUID_LOOP_UNTIL_RELEASE) || (_SAMPLEMODE(voice) == FLUID_LOOP_DURING_RELEASE)) { /* Keep the loop start point within the sample data */ if (voice->loopstart < min_index_loop){ @@ -1923,14 +1842,14 @@ void fluid_voice_check_sample_sanity(fluid_voice_t* voice) } else if (voice->loopstart > max_index_loop){ voice->loopstart = max_index_loop; } - + /* Keep the loop end point within the sample data */ if (voice->loopend < min_index_loop){ voice->loopend = min_index_loop; } else if (voice->loopend > max_index_loop){ voice->loopend = max_index_loop; } - + /* Keep loop start and end point in the right order */ if (voice->loopstart > voice->loopend){ int temp = voice->loopstart; @@ -1938,27 +1857,27 @@ void fluid_voice_check_sample_sanity(fluid_voice_t* voice) voice->loopend = temp; /*FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Changing order of loop points!"); */ } - + /* Loop too short? Then don't loop. */ if (voice->loopend < voice->loopstart + FLUID_MIN_LOOP_SIZE){ - voice->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED; - } + voice->gen[GEN_SAMPLEMODE].val = 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->loopstart >= (int)voice->sample->loopstart + if ((int)voice->loopstart >= (int)voice->sample->loopstart && (int)voice->loopend <= (int)voice->sample->loopend){ /* Is there a valid peak amplitude available for the loop? */ if (voice->sample->amplitude_that_reaches_noise_floor_is_valid){ voice->amplitude_that_reaches_noise_floor_loop=voice->sample->amplitude_that_reaches_noise_floor / voice->synth_gain; } else { /* Worst case */ - voice->amplitude_that_reaches_noise_floor_loop=voice->amplitude_that_reaches_noise_floor_nonloop; + voice->amplitude_that_reaches_noise_floor_loop=voice->amplitude_that_reaches_noise_floor_nonloop; }; }; } /* if sample mode is looped */ - + /* Run startup specific code (only once, when the voice is started) */ if (voice->check_sample_sanity_flag & FLUID_SAMPLESANITY_STARTUP){ if (max_index_loop - min_index_loop < FLUID_MIN_LOOP_SIZE){ @@ -1967,15 +1886,15 @@ void fluid_voice_check_sample_sanity(fluid_voice_t* voice) voice->gen[GEN_SAMPLEMODE].val = FLUID_UNLOOPED; } } - + /* Set the initial phase of the voice (using the result from the start offset modulators). */ fluid_phase_set_int(voice->phase, voice->start); } /* if startup */ - + /* Is this voice run in loop mode, or does it run straight to the end of the waveform data? */ - if (((_SAMPLEMODE(voice) == FLUID_LOOP_UNTIL_RELEASE) && (voice->volenv_section < FLUID_VOICE_ENVRELEASE)) + if (((_SAMPLEMODE(voice) == FLUID_LOOP_UNTIL_RELEASE) && (voice->volenv_section < FLUID_VOICE_ENVRELEASE)) || (_SAMPLEMODE(voice) == 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) @@ -1995,7 +1914,7 @@ void fluid_voice_check_sample_sanity(fluid_voice_t* voice) } } /* FLUID_LOG(FLUID_DBG, "Loop / sample sanity check: Sample from %i to %i, loop from %i to %i", voice->start, voice->end, voice->loopstart, voice->loopend); */ - + /* Sample sanity has been assured. Don't check again, until some sample parameter is changed by modulation. */ voice->check_sample_sanity_flag=0; @@ -2025,13 +1944,13 @@ int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain) voice->amp_left = fluid_pan(voice->pan, 1) * gain / 32768.0f; voice->amp_right = fluid_pan(voice->pan, 0) * gain / 32768.0f; voice->amp_reverb = voice->reverb_send * gain / 32768.0f; - voice->amp_chorus = voice->chorus_send * gain / 32768.0f; + voice->amp_chorus = voice->chorus_send * gain / 32768.0f; return FLUID_OK; } /* - Scan the loop - * - determine the peak level + * - determine the peak level * - Calculate, what factor will make the loop inaudible * - Store in sample */ @@ -2057,7 +1976,7 @@ int fluid_voice_optimize_sample(fluid_sample_t* s) peak_min = val; } } - + /* Determine the peak level */ if (peak_max >- peak_min){ peak = peak_max; @@ -2075,11 +1994,11 @@ int fluid_voice_optimize_sample(fluid_sample_t* s) * 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)/32768.; 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; diff --git a/src/libs/fluidsynth/src/fluid_voice.h b/src/libs/fluidsynth/src/fluid_voice.h index 6a4a60b5a2..fa8d56623d 100644 --- a/src/libs/fluidsynth/src/fluid_voice.h +++ b/src/libs/fluidsynth/src/fluid_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 * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -43,9 +43,9 @@ enum fluid_voice_status struct _fluid_env_data_t { unsigned int count; fluid_real_t coeff; - fluid_real_t incr; - fluid_real_t min; - fluid_real_t max; + fluid_real_t incr; + fluid_real_t min; + fluid_real_t max; }; /* Indices for envelope tables */ @@ -60,20 +60,12 @@ enum fluid_voice_envelope_index_t{ FLUID_VOICE_ENVLAST }; -/* - * interpolation data - */ -typedef struct { - fluid_real_t a0, a1, a2, a3; -/* signed int c0, c1, c2, c3; */ -} fluid_interp_coeff_t; - /* * fluid_voice_t */ 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 */ @@ -85,7 +77,7 @@ struct _fluid_voice_t int mod_count; int has_looped; /* Flag that is set as soon as the first loop is completed. */ fluid_sample_t* sample; - int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters + int check_sample_sanity_flag; /* Flag that initiates, that sample-related parameters have to be checked. */ #if 0 /* Instead of keeping a pointer to a fluid_sample_t structure, @@ -116,12 +108,16 @@ struct _fluid_voice_t unsigned int start_time; unsigned int ticks; - fluid_real_t amp; /* the linear amplitude */ + fluid_real_t amp; /* current linear amplitude */ fluid_phase_t phase; /* the phase of the sample wave */ -#if 0 - fluid_real_t incr; /* the phase increment for the next 64 samples [NEW, PH] */ -#endif + /* Temporary variables used in fluid_voice_write() */ + + fluid_real_t phase_incr; /* the phase increment for the next 64 samples */ + fluid_real_t amp_incr; /* amplitude increment value */ + fluid_real_t *dsp_buf; /* buffer to store interpolated sample data to */ + + /* End temporary variables */ /* basic parameters */ fluid_real_t pitch; /* the pitch in midicents */ @@ -134,7 +130,7 @@ struct _fluid_voice_t int start; int end; int loopstart; - int loopend; + int loopend; /* Note: first point following the loop (superimposed on loopstart) */ /* master gain */ fluid_real_t synth_gain; @@ -152,22 +148,22 @@ struct _fluid_voice_t unsigned int modenv_count; int modenv_section; fluid_real_t modenv_val; /* the value of the modulation envelope */ - fluid_real_t modenv_to_fc; - fluid_real_t modenv_to_pitch; + fluid_real_t modenv_to_fc; + fluid_real_t modenv_to_pitch; /* mod lfo */ fluid_real_t modlfo_val; /* the value of the modulation LFO */ unsigned int modlfo_delay; /* the delay of the lfo in samples */ - fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */ - fluid_real_t modlfo_to_fc; - fluid_real_t modlfo_to_pitch; - fluid_real_t modlfo_to_vol; + fluid_real_t modlfo_incr; /* the lfo frequency is converted to a per-buffer increment */ + fluid_real_t modlfo_to_fc; + fluid_real_t modlfo_to_pitch; + fluid_real_t modlfo_to_vol; /* vib lfo */ fluid_real_t viblfo_val; /* the value of the vibrato LFO */ unsigned int viblfo_delay; /* the delay of the lfo in samples */ - fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */ - fluid_real_t viblfo_to_pitch; + fluid_real_t viblfo_incr; /* the lfo frequency is converted to a per-buffer increment */ + fluid_real_t viblfo_to_pitch; /* resonant filter */ fluid_real_t fres; /* the resonance frequency, in cents (not absolute cents) */ @@ -177,7 +173,7 @@ struct _fluid_voice_t 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 hist1, hist2; /* Sample history for the IIR filter */ - int filter_startup; /* Flag: If set, the filter will be set directly. + int filter_startup; /* Flag: If set, the filter will be set directly. Else it changes smoothly. */ /* filter coefficients */ @@ -219,14 +215,14 @@ struct _fluid_voice_t fluid_voice_t* new_fluid_voice(fluid_real_t output_rate); int delete_fluid_voice(fluid_voice_t* voice); -void fluid_voice_start(fluid_voice_t* voice); +void fluid_voice_start(fluid_voice_t* voice); int fluid_voice_write(fluid_voice_t* voice, - fluid_real_t* left, fluid_real_t* right, + fluid_real_t* left, fluid_real_t* right, fluid_real_t* reverb_buf, fluid_real_t* chorus_buf); -int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, - fluid_channel_t* channel, int key, int vel, +int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample, + 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); @@ -250,7 +246,7 @@ int fluid_voice_noteoff(fluid_voice_t* voice); int fluid_voice_off(fluid_voice_t* voice); int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice); fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice); -int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, +int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base, int gen_key2base, int is_decay); int fluid_voice_kill_excl(fluid_voice_t* voice); fluid_real_t fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice); @@ -282,7 +278,14 @@ fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num); #define FLUID_SAMPLESANITY_CHECK (1 << 0) #define FLUID_SAMPLESANITY_STARTUP (1 << 1) -void fluid_voice_config(void); +/* defined in fluid_dsp_float.c */ + +void fluid_dsp_float_config (void); +int fluid_dsp_float_interpolate_none (fluid_voice_t *voice); +int fluid_dsp_float_interpolate_linear (fluid_voice_t *voice); +int fluid_dsp_float_interpolate_4th_order (fluid_voice_t *voice); +int fluid_dsp_float_interpolate_7th_order (fluid_voice_t *voice); + #endif /* _FLUID_VOICE_H */ diff --git a/src/libs/fluidsynth/src/fluidsynth.c b/src/libs/fluidsynth/src/fluidsynth.c index 1f2297c008..84222bdf3d 100644 --- a/src/libs/fluidsynth/src/fluidsynth.c +++ b/src/libs/fluidsynth/src/fluidsynth.c @@ -11,14 +11,16 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307, USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include @@ -37,10 +39,6 @@ #include "fluidsynth.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #if defined(WIN32) && !defined(MINGW32) #include "config_win32.h" #endif @@ -88,7 +86,7 @@ extern int optind, opterr, optopt; /* process_o_cmd_line_option * * Purpose: - * Process a command line option -o setting=value, + * 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){ @@ -127,7 +125,7 @@ void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg){ default: fprintf (stderr, "Settings argument on command line: Failed to set \"%s\" to \"%s\".\n" "Most likely the parameter \"%s\" does not exist.\n", optarg, val, optarg); - } + } } static void @@ -180,7 +178,7 @@ settings_foreach_func (void *data, char *name, int type) #ifdef HAVE_SIGNAL_H -/* +/* * handle_signal */ void handle_signal(int sig_num) @@ -192,7 +190,7 @@ void handle_signal(int sig_num) /* * main */ -int main(int argc, char** argv) +int main(int argc, char** argv) { fluid_settings_t* settings; int arg1 = 1; @@ -200,7 +198,7 @@ int main(int argc, char** argv) int c, i, fragcount = DEFAULT_FRAG_COUNT; int interactive = 1; int midi_in = 1; - fluid_player_t* player = NULL; + fluid_player_t* player = NULL; fluid_midi_router_t* router = NULL; fluid_midi_driver_t* mdriver = NULL; fluid_audio_driver_t* adriver = NULL; @@ -354,7 +352,7 @@ int main(int argc, char** argv) case 'n': midi_in = 0; break; - case 'o': + case 'o': process_o_cmd_line_option(settings, optarg); break; case 'R': @@ -433,16 +431,16 @@ int main(int argc, char** argv) */ if ((audio_groups == 0) && (audio_channels != 0)) { audio_groups = audio_channels; - } + } fluid_settings_setint(settings, "synth.audio-groups", audio_groups); - + /* create the synthesizer */ synth = new_fluid_synth(settings); if (synth == NULL) { fprintf(stderr, "Failed to create the synthesizer\n"); exit(-1); } - + cmd_handler = new_fluid_cmd_handler(synth); if (cmd_handler == NULL) { fprintf(stderr, "Failed to create the command handler\n"); @@ -458,13 +456,16 @@ int main(int argc, char** argv) fluid_source(cmd_handler, buf); } - /* load the soundfonts */ + /* load the soundfonts (check that all non options are SoundFont or MIDI files) */ for (i = arg1; i < argc; i++) { - if ((argv[i][0] != '-') && fluid_is_soundfont(argv[i])) { - if (fluid_synth_sfload(synth, argv[i], 1) == -1) { + 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]); } #ifdef HAVE_SIGNAL_H @@ -487,10 +488,10 @@ int main(int argc, char** argv) */ router = new_fluid_midi_router( - settings, - dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event, + 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" @@ -498,7 +499,7 @@ int main(int argc, char** argv) } else { fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */ mdriver = new_fluid_midi_driver( - settings, + settings, dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event, (void*) router); if (mdriver == NULL) { @@ -561,7 +562,7 @@ int main(int argc, char** argv) * 0. */ fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> "); - fluid_usershell(settings, cmd_handler); + fluid_usershell(settings, cmd_handler); } cleanup: @@ -584,7 +585,7 @@ int main(int argc, char** argv) /* if the user typed 'quit' in the shell, stop the player */ if (interactive) { fluid_player_stop(player); - } + } fluid_player_join(player); delete_fluid_player(player); } @@ -623,8 +624,8 @@ static fluid_cmd_handler_t* newclient(void* data, char* addr) /* * print_usage */ -void -print_usage() +void +print_usage() { print_welcome (); fprintf(stderr, "Usage: fluidsynth [options] [soundfonts]\n"); @@ -635,8 +636,8 @@ print_usage() /* * print_welcome */ -void -print_welcome() +void +print_welcome() { printf("FluidSynth version %s\n" "Copyright (C) 2000-2006 Peter Hanappe and others.\n" @@ -648,8 +649,8 @@ print_welcome() /* * print_help */ -void -print_help() +void +print_help() { print_welcome (); printf("Usage: \n"); diff --git a/src/libs/fluidsynth/src/fluidsynth_priv.h b/src/libs/fluidsynth/src/fluidsynth_priv.h index f417713f44..0b2b6cd374 100644 --- a/src/libs/fluidsynth/src/fluidsynth_priv.h +++ b/src/libs/fluidsynth/src/fluidsynth_priv.h @@ -11,7 +11,7 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA @@ -26,9 +26,9 @@ #include "config.h" #endif -//#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__)) -//#include "config_maxmsp43.h" -//#endif +#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__)) +#include "config_maxmsp43.h" +#endif #if defined(WIN32) && !defined(MINGW32) #include "config_win32.h" @@ -229,7 +229,7 @@ typedef u_int64_t uint64; /*************************************************************** * - * FORWARD DECLARATIONS + * FORWARD DECLARATIONS */ typedef struct _fluid_env_data_t fluid_env_data_t; typedef struct _fluid_adriver_definition_t fluid_adriver_definition_t; @@ -241,7 +241,7 @@ typedef struct _fluid_server_socket_t fluid_server_socket_t; /*************************************************************** * - * CONSTANTS + * CONSTANTS */ #define FLUID_BUFSIZE 64 @@ -267,7 +267,7 @@ typedef FILE* fluid_file; #define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set) #define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n) #define FLUID_MEMSET(_s,_c,_n) memset(_s,_c,_n) -#define FLUID_STRLEN(_s) strlen(_s) +#define FLUID_STRLEN(_s) strlen(_s) #define FLUID_STRCMP(_s,_t) strcmp(_s,_t) #define FLUID_STRNCMP(_s,_t,_n) strncmp(_s,_t,_n) #define FLUID_STRCPY(_dst,_src) strcpy(_dst,_src) @@ -276,31 +276,16 @@ typedef FILE* fluid_file; #define FLUID_STRDUP(s) strdup(s) #else #define FLUID_STRDUP(s) FLUID_STRCPY(FLUID_MALLOC(FLUID_STRLEN(s) + 1), s) -#endif +#endif #define FLUID_SPRINTF sprintf #define FLUID_FPRINTF fprintf #define fluid_clip(_val, _min, _max) \ { (_val) = ((_val) < (_min))? (_min) : (((_val) > (_max))? (_max) : (_val)); } -/* Purpose: - * Some commands (SSE extensions on Pentium) need aligned data( - * The address must be ...xxx0. - * Take a pointer, and round it up to the next suitable address. - * Obviously, one has to allocate 15 bytes of additional memory. - * As soon as proper alignment is supported by the compiler, this - * can be removed. - */ -#ifdef ENABLE_SSE -/* FIXME - This is broken on AMD 64 - only used if SSE enabled */ -#define FLUID_ALIGN16BYTE(ptr)(((int)(ptr)+15) & (~0xFL)) -#else -#define FLUID_ALIGN16BYTE(ptr) ptr -#endif - #if WITH_FTS #define FLUID_PRINTF post -#define FLUID_FLUSH() +#define FLUID_FLUSH() #else #define FLUID_PRINTF printf #define FLUID_FLUSH() fflush(stdout)