Merge branch 'master' into sm24

This commit is contained in:
derselbst 2017-12-07 18:58:12 +01:00
commit 7de0e02a82
51 changed files with 976 additions and 844 deletions

View file

@ -28,9 +28,9 @@ set ( CMAKE_EXPORT_COMPILE_COMMANDS 1 )
set ( PACKAGE "fluidsynth" )
# FluidSynth package version
set ( FLUIDSYNTH_VERSION_MAJOR 1 )
set ( FLUIDSYNTH_VERSION_MINOR 1 )
set ( FLUIDSYNTH_VERSION_MICRO 8 )
set ( FLUIDSYNTH_VERSION_MAJOR 2 )
set ( FLUIDSYNTH_VERSION_MINOR 0 )
set ( FLUIDSYNTH_VERSION_MICRO 0 )
set ( VERSION "${FLUIDSYNTH_VERSION_MAJOR}.${FLUIDSYNTH_VERSION_MINOR}.${FLUIDSYNTH_VERSION_MICRO}" )
set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" )
@ -43,9 +43,9 @@ set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" )
# if any interfaces have been added: AGE++
# if any interfaces have been removed/changed (compatibility broken): AGE=0
# This is not exactly the same algorithm as the libtool one, but the results are the same.
set ( LIB_VERSION_CURRENT 1 )
set ( LIB_VERSION_AGE 6 )
set ( LIB_VERSION_REVISION 1 )
set ( LIB_VERSION_CURRENT 2 )
set ( LIB_VERSION_AGE 0 )
set ( LIB_VERSION_REVISION 0 )
set ( LIB_VERSION_INFO
"${LIB_VERSION_CURRENT}.${LIB_VERSION_AGE}.${LIB_VERSION_REVISION}" )
@ -158,9 +158,9 @@ if ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang" )
endif ( OS2 )
set ( GNUCC_WARNING_FLAGS "-Wall -W -Wpointer-arith -Wbad-function-cast -Wno-cast-qual -Wcast-align -Wstrict-prototypes -Wno-unused-parameter -Wdeclaration-after-statement" )
set ( CMAKE_C_FLAGS_DEBUG "-std=gnu89 -g ${GNUCC_VISIBILITY_FLAG} -DDEBUG ${GNUCC_WARNING_FLAGS} -fsanitize=undefined" )
set ( CMAKE_C_FLAGS_RELEASE "-std=gnu89 -O2 -fomit-frame-pointer -finline-functions ${GNUCC_VISIBILITY_FLAG} -DNDEBUG ${GNUCC_WARNING_FLAGS}" )
set ( CMAKE_C_FLAGS_RELWITHDEBINFO "-std=gnu89 -O2 -g -fomit-frame-pointer -finline-functions ${GNUCC_VISIBILITY_FLAG} -DNDEBUG ${GNUCC_WARNING_FLAGS}" )
set ( CMAKE_C_FLAGS_DEBUG "-std=gnu89 -g ${GNUCC_VISIBILITY_FLAG} -DDEBUG ${GNUCC_WARNING_FLAGS} -fsanitize=undefined ${CMAKE_C_FLAGS_DEBUG}" )
set ( CMAKE_C_FLAGS_RELEASE "-std=gnu89 -O2 -fomit-frame-pointer -finline-functions ${GNUCC_VISIBILITY_FLAG} -DNDEBUG ${GNUCC_WARNING_FLAGS} ${CMAKE_C_FLAGS_RELEASE}" )
set ( CMAKE_C_FLAGS_RELWITHDEBINFO "-std=gnu89 -O2 -g -fomit-frame-pointer -finline-functions ${GNUCC_VISIBILITY_FLAG} -DNDEBUG ${GNUCC_WARNING_FLAGS} ${CMAKE_C_FLAGS_RELWITHDEBINFO}" )
endif ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang" )
# Windows

View file

@ -88,7 +88,7 @@ FILE_PATTERNS = *.c *.h
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_PATTERNS = fluid_*.h
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = ../doc
EXAMPLE_PATTERNS = *.c
@ -200,7 +200,7 @@ EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
PREDEFINED = __DOXYGEN__
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------

View file

@ -88,7 +88,7 @@ FILE_PATTERNS = *.c *.h
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_PATTERNS = fluid_*.h
EXCLUDE_SYMBOLS =
EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/doc
EXAMPLE_PATTERNS = *.c
@ -200,7 +200,7 @@ EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
PREDEFINED = __DOXYGEN__
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------

View file

@ -114,6 +114,96 @@ https://stackoverflow.com/a/6251757
<desc>
Sets the minimum note duration in milliseconds. This ensures that really short duration note events, such as percussion notes, have a better chance of sounding as intended. Set to 0 to disable this feature.</desc>
</setting>
<setting>
<name>overflow.age</name>
<type>num</type>
<def>1000</def>
<min>-10000</min>
<max>10000</max>
<desc>
This score is divided by the number of seconds this voice has been
active and is added to the overflow priority. It is usually a positive
value and gives voices which have just been started a higher priority,
making them less likely to be killed in an overflow situation.
</desc>
</setting>
<setting>
<name>overflow.important</name>
<type>num</type>
<def>5000</def>
<min>-50000</min>
<max>50000</max>
<desc>
This score is added to voices on channels marked with the
synth.overflow.important-channels setting.
</desc>
</setting>
<setting>
<name>overflow.important-channels</name>
<type>str</type>
<def>""</def>
<desc>
This setting is a comma-separated list of MIDI channel numbers that should
be treated as "important" by the overflow calculation, adding the score
set by synth.overflow.important to each voice on those channels. It can
be used to make voices on particular MIDI channels
less likely (synth.overflow.important &gt; 0) or more likely
(synth.overflow.important &lt; 0) to be killed in an overflow situation. Channel
numbers are 1-based, so the first MIDI channel is number 1.
</desc>
</setting>
<setting>
<name>overflow.percussion</name>
<type>num</type>
<def>4000</def>
<min>-10000</min>
<max>10000</max>
<desc>
Sets the overflow priority score added to voices on a percussion
channel. This is usually a positive score, to give percussion voices
a higher priority and less chance of being killed in an overflow
situation.
</desc>
</setting>
<setting>
<name>overflow.released</name>
<type>num</type>
<def>-2000</def>
<min>-10000</min>
<max>10000</max>
<desc>
Sets the overflow priority score added to voices that have already
received a note-off event. This is usually a negative score, to give released
voices a lower priority so that they are killed first in an overflow
situation.
</desc>
</setting>
<setting>
<name>overflow.sustained</name>
<type>num</type>
<def>-1000</def>
<min>-10000</min>
<max>10000</max>
<desc>
Sets the overflow priority score added to voices that are currently
sustained. With the default value, sustained voices are considered less
important and are more likely to be killed in an overflow situation.
</desc>
</setting>
<setting>
<name>overflow.volume</name>
<type>num</type>
<def>500</def>
<min>-10000</min>
<max>10000</max>
<desc>
Sets the overflow priority score added to voices based on their current
volume. The voice volume is normalized to a value between 0 and 1 and
multiplied with this setting. So voices with maximum volume get added
the full score, voices with only half that volume get added half of this
score.
</desc>
</setting>
<setting>
<name>parallel-render</name>
<type>bool</type>

View file

@ -74,33 +74,45 @@ FluidSynths SOVERSION was bumped. The API was reworked, deprecated functions wer
Changes in FluidSynth 2.0.0 concerning developers:
- remove deprecated fluid_synth_get_program() and fluid_synth_get_channel_preset(), use fluid_synth_get_channel_info() instead
- remove deprecated fluid_synth_get_channel_info() in favour of fluid_synth_get_program() and fluid_synth_get_channel_preset()
- remove deprecated fluid_settings_getstr()
- remove deprecated fluid_synth_set_midi_router()
- remove deprecated fluid_get_hinstance() and fluid_set_hinstance() (dsound driver now uses the desktop window)
- remove deprecated fluid_synth_create_key_tuning(), use fluid_synth_activate_key_tuning(synth, bank, prog, name, pitch, FALSE) instead
- remove deprecated fluid_synth_create_octave_tuning(), use fluid_synth_activate_octave_tuning(synth, bank, prog, name, pitch, FALSE) instead
- remove deprecated fluid_synth_select_tuning(), use fluid_synth_activate_tuning(synth, chan, bank, prog, FALSE) instead
- remove deprecated fluid_synth_reset_tuning(), use fluid_synth_deactivate_tuning(synth, chan, FALSE) instead
- remove deprecated FLUID_HINT_INTEGER
- remove misspelled FLUID_SEQ_PITCHWHHELSENS macro
- remove obsolete "audio.[out|in]put-channels" settings
- remove unimplemented "synth.dump" setting
- remove fluid_synth_set_gen2(), fluid_synth_set_gen() now behaves as fluid_synth_set_gen2()
- remove struct fluid_mod_t from public API, use the getters and setters of mod.h instead
- remove struct _fluid_mod_t from public API, use the getters and setters of mod.h instead
- remove struct _fluid_gen_t, fluid_gen_set_default_values() and enum fluid_gen_flags from public API
- remove macros fluid_sfont_get_id() and fluid_sample_refcount() from public API
- remove FLUID_NUM_MOD macro from public API
- remove the following deprecated enum values:
- GEN_LAST
- LAST_LOG_LEVEL
- FLUID_SEQ_LASTEVENT
- FLUID_MIDI_ROUTER_RULE_COUNT
<br /><br />
- all public \c fluid_settings_* functions that return an integer which is not meant to be interpreted as bool consistently return either FLUID_OK or FLUID_FAILED
- all public delete_* functions return void and are safe when called with NULL
- the shell command handler was decoupled internally, as a consequence the param list of new_fluid_server() and new_fluid_cmd_handler() was adapted
- reverb: roomsize is now limited to an upper threshold of 1.0
- use unique device names for the "audio.portaudio.device" setting
- rename fluid_mod_new() and fluid_mod_delete() to match naming conventions: new_fluid_mod() and delete_fluid_mod()
<br /><br />
- add "synth.volenv" a setting for volume envelope processing
- add "midi.autoconnect" a setting for automatically connecting fluidsynth to available MIDI input ports
- add support for polyonic key pressure events, see fluid_event_key_pressure()
- add support for polyphonic key pressure events, see fluid_event_key_pressure() and fluid_synth_key_pressure()
- add fluid_synth_add_default_mod() and fluid_synth_remove_default_mod() for manipulating default modulators
- add individual reverb setters: fluid_synth_set_reverb_roomsize(), fluid_synth_set_reverb_damp(), fluid_synth_set_reverb_width(), fluid_synth_set_reverb_level()
- add individual chorus setters: fluid_synth_set_chorus_nr(), fluid_synth_set_chorus_level(), fluid_synth_set_chorus_speed(), fluid_synth_set_chorus_depth(), fluid_synth_set_chorus_type()
- introduce a separate data type for sequencer client IDs: #fluid_seq_id_t
- add file callback struct to _fluid_sfloader_t and expose new_fluid_defsfloader() to enable soundfont loading from memory ( see fluid_sfload_mem.c )
- add seek support to midi-player, see fluid_player_seek()
- expose functions to manipulate the ladspa effects unit (see ladspa.h)
\section NewIn1_1_9 Whats new in 1.1.9?

View file

@ -59,7 +59,9 @@ enum fluid_seq_event_type {
FLUID_SEQ_KEYPRESSURE, /**< Polyphonic aftertouch event @since 2.0.0 */
FLUID_SEQ_SYSTEMRESET, /**< System reset event @since 1.1.0 */
FLUID_SEQ_UNREGISTERING, /**< Called when a sequencer client is being unregistered. @since 1.1.0 */
FLUID_SEQ_LASTEVENT /**< Defines the count of event enums @deprecated As of 1.1.7 this enum value is deprecated and will be removed in a future release, because it prevents adding new enum values without breaking ABI compatibility. */
#ifndef __DOXYGEN__
FLUID_SEQ_LASTEVENT /**< @internal Defines the count of events enums @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
#endif
};
/* Event alloc/free */

View file

@ -99,7 +99,9 @@ enum fluid_gen_type {
* is used, however, as the destination for the default pitch wheel
* modulator. */
GEN_PITCH, /**< Pitch @note Not a real SoundFont generator */
GEN_LAST /**< Value defines the count of generators (#fluid_gen_type) @deprecated As of 1.1.7 this enum value is deprecated and will be removed in a future release, because it prevents adding new enum values without breaking ABI compatibility. */
#ifndef __DOXYGEN__
GEN_LAST /**< @internal Value defines the count of generators (#fluid_gen_type) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
#endif
};

View file

@ -25,6 +25,17 @@
extern "C" {
#endif
/**
* @file ladspa.h
* @brief Functions for manipulating the ladspa effects unit
*
* This header defines useful functions for programatically manipulating the ladspa
* effects unit of the synth that can be retrieved via fluid_synth_get_ladspa_fx().
*
* Using any of those functions requires fluidsynth to be compiled with ladspa support.
* Else all of those functions are useless dummies.
*/
FLUIDSYNTH_API int fluid_ladspa_is_active(fluid_ladspa_fx_t *fx);
FLUIDSYNTH_API int fluid_ladspa_activate(fluid_ladspa_fx_t *fx);
FLUIDSYNTH_API int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx);

View file

@ -58,7 +58,9 @@ enum fluid_log_level {
FLUID_WARN, /**< Warning */
FLUID_INFO, /**< Verbose informational messages */
FLUID_DBG, /**< Debugging messages */
LAST_LOG_LEVEL /**< @deprecated As of 1.1.7 this enum value is deprecated and will be removed in a future release, because it prevents adding new enum values without breaking ABI compatibility. */
#ifndef __DOXYGEN__
LAST_LOG_LEVEL /**< @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
#endif
};
/**

View file

@ -64,7 +64,9 @@ typedef enum
FLUID_MIDI_ROUTER_RULE_PITCH_BEND, /**< MIDI pitch bend rule */
FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE, /**< MIDI channel pressure rule */
FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE, /**< MIDI key pressure rule */
FLUID_MIDI_ROUTER_RULE_COUNT /**< Total count of rule types */
#ifndef __DOXYGEN__
FLUID_MIDI_ROUTER_RULE_COUNT /**< @internal Total count of rule types @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time!*/
#endif
} fluid_midi_router_rule_type;
/**

View file

@ -30,7 +30,6 @@ extern "C" {
* @brief SoundFont modulator functions and constants.
*/
#define FLUID_NUM_MOD 64 /**< Maximum number of modulators in a voice */
/**
* Flags defining the polarity, mapping function and type of a modulator source.
@ -68,8 +67,8 @@ enum fluid_mod_src
FLUID_MOD_PITCHWHEELSENS = 16 /**< Pitch wheel sensitivity */
};
FLUIDSYNTH_API fluid_mod_t* fluid_mod_new(void);
FLUIDSYNTH_API void fluid_mod_delete(fluid_mod_t * mod);
FLUIDSYNTH_API fluid_mod_t* new_fluid_mod(void);
FLUIDSYNTH_API void delete_fluid_mod(fluid_mod_t * mod);
FLUIDSYNTH_API void fluid_mod_set_source1(fluid_mod_t* mod, int src, int flags);
FLUIDSYNTH_API void fluid_mod_set_source2(fluid_mod_t* mod, int src, int flags);

View file

@ -70,6 +70,18 @@ enum {
FLUID_SAMPLE_DONE /**< Sample no longer needed notify */
};
/**
* Indicates the type of a sample used by the _fluid_sample_t::sampletype field.
*/
enum fluid_sample_type
{
FLUID_SAMPLETYPE_MONO = 0x1, /**< Used for mono samples */
FLUID_SAMPLETYPE_RIGHT = 0x2, /**< Used for right samples of a stereo pair */
FLUID_SAMPLETYPE_LEFT = 0x4, /**< Used for left samples of a stereo pair */
FLUID_SAMPLETYPE_LINKED = 0x8, /**< Currently not used */
FLUID_SAMPLETYPE_OGG_VORBIS = 0x10, /**< Used for Ogg Vorbis compressed samples @since 1.1.7 */
FLUID_SAMPLETYPE_ROM = 0x8000 /**< Indicates ROM samples, causes sample to be ignored */
};
/**
* SoundFont loader structure.
@ -191,7 +203,6 @@ struct _fluid_sfont_t {
int (*iteration_next)(fluid_sfont_t* sfont, fluid_preset_t* preset);
};
#define fluid_sfont_get_id(_sf) ((_sf)->id)
/**
* Virtual SoundFont preset.
@ -284,7 +295,7 @@ struct _fluid_sample_t
unsigned int samplerate; /**< Sample rate */
int origpitch; /**< Original pitch (MIDI note number, 0-127) */
int pitchadj; /**< Fine pitch adjustment (+/- 99 cents) */
int sampletype; /**< Values: #FLUID_SAMPLETYPE_MONO, FLUID_SAMPLETYPE_RIGHT, FLUID_SAMPLETYPE_LEFT, FLUID_SAMPLETYPE_ROM */
int sampletype; /**< Specifies the type of this sample as indicated by the #fluid_sample_type enum */
int valid; /**< Should be TRUE if sample data is valid, FALSE otherwise (in which case it will not be synthesized) */
short* data; /**< Pointer to the sample's 16 bit PCM data */
char* data24; /**< If not NULL, pointer to the sample's contains the least significant byte counterparts to each sample data point */
@ -292,7 +303,7 @@ struct _fluid_sample_t
int amplitude_that_reaches_noise_floor_is_valid; /**< Indicates if \a amplitude_that_reaches_noise_floor is valid (TRUE), set to FALSE initially to calculate. */
double amplitude_that_reaches_noise_floor; /**< The amplitude at which the sample's loop will be below the noise floor. For voice off optimization, calculated automatically. */
unsigned int refcount; /**< Count of voices using this sample (use #fluid_sample_refcount to access this field) */
unsigned int refcount; /**< Count of voices using this sample */
/**
* Implement this function to receive notification when sample is no longer used.
@ -306,18 +317,6 @@ struct _fluid_sample_t
};
#define fluid_sample_refcount(_sample) ((_sample)->refcount) /**< Get the reference count of a sample. Should only be called from within synthesis context (noteon method for example) */
#define FLUID_SAMPLETYPE_MONO 1 /**< Flag for #fluid_sample_t \a sampletype field for mono samples */
#define FLUID_SAMPLETYPE_RIGHT 2 /**< Flag for #fluid_sample_t \a sampletype field for right samples of a stereo pair */
#define FLUID_SAMPLETYPE_LEFT 4 /**< Flag for #fluid_sample_t \a sampletype field for left samples of a stereo pair */
#define FLUID_SAMPLETYPE_LINKED 8 /**< Flag for #fluid_sample_t \a sampletype field, not used currently */
#define FLUID_SAMPLETYPE_OGG_VORBIS 0x10 /**< Flag for #fluid_sample_t \a sampletype field for Ogg Vorbis compressed samples @since 1.1.7 */
#define FLUID_SAMPLETYPE_ROM 0x8000 /**< Flag for #fluid_sample_t \a sampletype field, ROM sample, causes sample to be ignored */
#ifdef __cplusplus
}
#endif

View file

@ -45,22 +45,6 @@ extern "C" {
* fluid_synth_noteon(), fluid_synth_noteoff(), ...
*/
#define FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE 32 /**< Length of channel info name field (including zero terminator) */
/**
* Channel information structure for fluid_synth_get_channel_info().
* @since 2.0.0
*/
struct _fluid_synth_channel_info_t
{
int assigned : 1; /**< TRUE if a preset is assigned, FALSE otherwise */
/* Reserved flag bits (at the least 31) */
int sfont_id; /**< ID of parent SoundFont */
int bank; /**< MIDI bank number (0-16383) */
int program; /**< MIDI program number (0-127) */
char name[FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE]; /**< Channel preset name */
char reserved[32]; /**< Reserved data for future expansion */
};
FLUIDSYNTH_API fluid_synth_t* new_fluid_synth(fluid_settings_t* settings);
FLUIDSYNTH_API void delete_fluid_synth(fluid_synth_t* synth);
@ -95,9 +79,6 @@ FLUIDSYNTH_API
int fluid_synth_get_program(fluid_synth_t* synth, int chan, unsigned int* sfont_id,
unsigned int* bank_num, unsigned int* preset_num);
FLUIDSYNTH_API int fluid_synth_unset_program (fluid_synth_t *synth, int chan);
FLUIDSYNTH_API
FLUID_DEPRECATED
int fluid_synth_get_channel_info (fluid_synth_t *synth, int chan, fluid_synth_channel_info_t *info);
FLUIDSYNTH_API int fluid_synth_program_reset(fluid_synth_t* synth);
FLUIDSYNTH_API int fluid_synth_system_reset(fluid_synth_t* synth);
@ -237,6 +218,8 @@ enum fluid_interp {
/* Generator interface */
FLUIDSYNTH_API int fluid_synth_set_gen (fluid_synth_t* synth, int chan,
int param, float value);
FLUIDSYNTH_API int fluid_synth_set_gen2 (fluid_synth_t* synth, int chan,
int param, float value,
int absolute, int normalized);
FLUIDSYNTH_API float fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param);
@ -244,33 +227,19 @@ FLUIDSYNTH_API float fluid_synth_get_gen(fluid_synth_t* synth, int chan, int par
/* Tuning */
FLUIDSYNTH_API
FLUID_DEPRECATED
int fluid_synth_create_key_tuning(fluid_synth_t* synth, int bank, int prog,
const char* name, const double* pitch);
FLUIDSYNTH_API
int fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog,
const char* name, const double* pitch, int apply);
FLUIDSYNTH_API
FLUID_DEPRECATED
int fluid_synth_create_octave_tuning(fluid_synth_t* synth, int bank, int prog,
const char* name, const double* pitch);
FLUIDSYNTH_API
int fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog,
const char* name, const double* pitch, int apply);
FLUIDSYNTH_API
int fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog,
int len, const int *keys, const double* pitch, int apply);
FLUIDSYNTH_API
FLUID_DEPRECATED
int fluid_synth_select_tuning(fluid_synth_t* synth, int chan, int bank, int prog);
FLUIDSYNTH_API
int fluid_synth_activate_tuning(fluid_synth_t* synth, int chan, int bank, int prog,
int apply);
FLUIDSYNTH_API
FLUID_DEPRECATED
int fluid_synth_reset_tuning(fluid_synth_t* synth, int chan);
FLUIDSYNTH_API
int fluid_synth_deactivate_tuning(fluid_synth_t* synth, int chan, int apply);
FLUIDSYNTH_API void fluid_synth_tuning_iteration_start(fluid_synth_t* synth);
FLUIDSYNTH_API
@ -343,9 +312,6 @@ FLUIDSYNTH_API void fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t*
FLUIDSYNTH_API void fluid_synth_get_voicelist(fluid_synth_t* synth,
fluid_voice_t* buf[], int bufsize, int ID);
FLUIDSYNTH_API int fluid_synth_handle_midi_event(void* data, fluid_midi_event_t* event);
FLUIDSYNTH_API
FLUID_DEPRECATED
void fluid_synth_set_midi_router(fluid_synth_t* synth, fluid_midi_router_t* router);
/* LADSPA */

View file

@ -35,7 +35,6 @@ extern "C" {
typedef struct _fluid_hashtable_t fluid_settings_t; /**< Configuration settings instance */
typedef struct _fluid_synth_t fluid_synth_t; /**< Synthesizer instance */
typedef struct _fluid_synth_channel_info_t fluid_synth_channel_info_t; /**< SoundFont channel info */
typedef struct _fluid_voice_t fluid_voice_t; /**< Synthesis voice instance */
typedef struct _fluid_sfloader_t fluid_sfloader_t; /**< SoundFont loader plugin */
typedef struct _fluid_sfont_t fluid_sfont_t; /**< SoundFont */

View file

@ -36,8 +36,6 @@ extern "C" {
*/
FLUIDSYNTH_API void fluid_voice_update_param(fluid_voice_t* voice, int gen);
/**
* Enum used with fluid_voice_add_mod() to specify how to handle duplicate modulators.
*/
@ -48,21 +46,22 @@ enum fluid_voice_add_mod {
};
FLUIDSYNTH_API void fluid_voice_add_mod(fluid_voice_t* voice, fluid_mod_t* mod, int mode);
FLUIDSYNTH_API void fluid_voice_gen_set(fluid_voice_t* voice, int gen, float val);
FLUIDSYNTH_API float fluid_voice_gen_get(fluid_voice_t* voice, int gen);
FLUIDSYNTH_API void fluid_voice_gen_set(fluid_voice_t* voice, int gen, float val);
FLUIDSYNTH_API void fluid_voice_gen_incr(fluid_voice_t* voice, int gen, float val);
FLUIDSYNTH_API unsigned int fluid_voice_get_id(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_channel(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_key(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_actual_key(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_velocity(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_actual_velocity(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_is_playing(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_is_on(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_is_sustained(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_is_sostenuto(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_channel(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_actual_key(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_key(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_actual_velocity(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_get_velocity(const fluid_voice_t* voice);
FLUIDSYNTH_API int fluid_voice_optimize_sample(fluid_sample_t* s);
FLUIDSYNTH_API int fluid_voice_optimize_sample(fluid_sample_t* s);
FLUIDSYNTH_API void fluid_voice_update_param(fluid_voice_t* voice, int gen);
#ifdef __cplusplus

View file

@ -80,8 +80,8 @@ static int fluid_handle_voice_count (void* data, int ac, char **av,
void fluid_shell_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "shell.prompt", "", 0, NULL, NULL);
fluid_settings_register_int(settings, "shell.port", 9800, 1, 65535, 0, NULL, NULL);
fluid_settings_register_str(settings, "shell.prompt", "", 0);
fluid_settings_register_int(settings, "shell.port", 9800, 1, 65535, 0);
}
@ -1363,9 +1363,9 @@ fluid_handle_set(void* data, int ac, char** av, fluid_ostream_t out)
if (fluid_settings_get_hints (handler->synth->settings, av[0], &hints) == FLUID_OK
&& hints & FLUID_HINT_TOGGLED)
{
if (FLUID_STRCMP (av[1], "yes") == 0 || FLUID_STRCMP (av[1], "True") == 0
|| FLUID_STRCMP (av[1], "TRUE") == 0 || FLUID_STRCMP (av[1], "true") == 0
|| FLUID_STRCMP (av[1], "T") == 0)
if (FLUID_STRCASECMP (av[1], "yes") == 0
|| FLUID_STRCASECMP (av[1], "true") == 0
|| FLUID_STRCASECMP (av[1], "t") == 0)
ival = 1;
else ival = atoi (av[1]);
}

View file

@ -22,10 +22,8 @@
* Low-level routines for file output.
*/
#include <stdio.h>
#include "fluidsynth_priv.h"
#include "fluid_synth.h"
#include "fluid_sys.h"
#include "fluid_synth.h"
#include "fluid_settings.h"
#if LIBSNDFILE_SUPPORT
@ -113,10 +111,10 @@ fluid_file_renderer_settings (fluid_settings_t* settings)
unsigned int n;
fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.wav",
FLUID_HINT_FILENAME, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.type", "auto", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.format", "s16", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.endian", "auto", 0, NULL, NULL);
FLUID_HINT_FILENAME);
fluid_settings_register_str(settings, "audio.file.type", "auto", 0);
fluid_settings_register_str(settings, "audio.file.format", "s16", 0);
fluid_settings_register_str(settings, "audio.file.endian", "auto", 0);
fluid_settings_add_option (settings, "audio.file.type", "auto");
@ -149,12 +147,12 @@ fluid_file_renderer_settings (fluid_settings_t* settings)
#else
fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.raw", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.type", "raw", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.raw", 0);
fluid_settings_register_str(settings, "audio.file.type", "raw", 0);
fluid_settings_add_option (settings, "audio.file.type", "raw");
fluid_settings_register_str(settings, "audio.file.format", "s16", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.format", "s16", 0);
fluid_settings_add_option (settings, "audio.file.format", "s16");
fluid_settings_register_str(settings, "audio.file.endian", "cpu", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.file.endian", "cpu", 0);
fluid_settings_add_option (settings, "audio.file.endian", "cpu");
#endif
}
@ -290,10 +288,10 @@ new_fluid_file_renderer(fluid_synth_t* synth)
* @since 1.1.7
*/
int
fluid_file_set_encoding_quality(fluid_file_renderer_t* r, double q)
fluid_file_set_encoding_quality(fluid_file_renderer_t* dev, double q)
{
#if LIBSNDFILE_SUPPORT
if (sf_command (r->sndfile, SFC_SET_VBR_ENCODING_QUALITY, &q, sizeof (double)) == SF_TRUE)
if (sf_command (dev->sndfile, SFC_SET_VBR_ENCODING_QUALITY, &q, sizeof (double)) == SF_TRUE)
return FLUID_OK;
else
#endif
@ -455,7 +453,6 @@ fluid_file_renderer_parse_options (char *filetype, char *format, char *endian,
/**
* Searches for a supported libsndfile file type by extension.
* @param extension The extension string
* @param ext_len Length of the extension string
* @param type Location to store the type (unmodified if not found)
* @return TRUE if found, FALSE otherwise
*/

View file

@ -27,7 +27,7 @@
#include "fluid_ladspa.h"
#ifdef LADSPA
#if defined(LADSPA) || defined(__DOXYGEN__)
#include <math.h>
#include <ladspa.h>

View file

@ -268,47 +268,47 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
{
unsigned int i;
fluid_settings_register_str(settings, "audio.sample-format", "16bits", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.sample-format", "16bits", 0);
fluid_settings_add_option(settings, "audio.sample-format", "16bits");
fluid_settings_add_option(settings, "audio.sample-format", "float");
#if defined(WIN32)
fluid_settings_register_int(settings, "audio.period-size", 512, 64, 8192, 0, NULL, NULL);
fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0, NULL, NULL);
fluid_settings_register_int(settings, "audio.period-size", 512, 64, 8192, 0);
fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0);
#elif defined(MACOS9)
fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0, NULL, NULL);
fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0, NULL, NULL);
fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0);
fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0);
#else
fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0, NULL, NULL);
fluid_settings_register_int(settings, "audio.periods", 16, 2, 64, 0, NULL, NULL);
fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0);
fluid_settings_register_int(settings, "audio.periods", 16, 2, 64, 0);
#endif
fluid_settings_register_int (settings, "audio.realtime-prio",
FLUID_DEFAULT_AUDIO_RT_PRIO, 0, 99, 0, NULL, NULL);
FLUID_DEFAULT_AUDIO_RT_PRIO, 0, 99, 0);
/* Set the default driver */
#if JACK_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "jack", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "jack", 0);
#elif ALSA_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "alsa", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "alsa", 0);
#elif PULSE_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "pulseaudio", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "pulseaudio", 0);
#elif OSS_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "oss", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "oss", 0);
#elif COREAUDIO_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "coreaudio", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "coreaudio", 0);
#elif DSOUND_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "dsound", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "dsound", 0);
#elif SNDMAN_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "sndman", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "sndman", 0);
#elif PORTAUDIO_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "portaudio", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "portaudio", 0);
#elif DART_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "dart", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "dart", 0);
#elif AUFILE_SUPPORT
fluid_settings_register_str(settings, "audio.driver", "file", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "file", 0);
#else
fluid_settings_register_str(settings, "audio.driver", "", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.driver", "", 0);
#endif
/* Add all drivers to the list of options */

View file

@ -34,13 +34,7 @@
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/poll.h>
#include <glib.h>
#include "config.h"
#include "fluid_lash.h"
@ -151,7 +145,7 @@ static fluid_thread_return_t fluid_alsa_seq_run(void* d);
void fluid_alsa_audio_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "audio.alsa.device", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.alsa.device", "default", 0);
}
@ -548,7 +542,7 @@ static fluid_thread_return_t fluid_alsa_audio_run_s16 (void *d)
void fluid_alsa_rawmidi_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "midi.alsa.device", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.alsa.device", "default", 0);
}
/*
@ -715,8 +709,8 @@ fluid_alsa_midi_run(void* d)
void fluid_alsa_seq_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "midi.alsa_seq.device", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.alsa_seq.id", "pid", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.alsa_seq.device", "default", 0);
fluid_settings_register_str(settings, "midi.alsa_seq.id", "pid", 0);
}

View file

@ -24,11 +24,9 @@
*
*/
#include "fluid_sys.h"
#include "fluid_adriver.h"
#include "fluid_settings.h"
#include "fluid_sys.h"
#include "config.h"
#include <stdio.h>
/** fluid_file_audio_driver_t

View file

@ -30,8 +30,6 @@
#include "fluid_mdriver.h"
#include "fluid_settings.h"
#include "config.h"
#if COREAUDIO_SUPPORT
#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudioTypes.h>
@ -111,7 +109,7 @@ fluid_core_audio_driver_settings(fluid_settings_t* settings)
pa.mScope = kAudioObjectPropertyScopeWildcard;
pa.mElement = kAudioObjectPropertyElementMaster;
fluid_settings_register_str (settings, "audio.coreaudio.device", "default", 0, NULL, NULL);
fluid_settings_register_str (settings, "audio.coreaudio.device", "default", 0);
fluid_settings_add_option (settings, "audio.coreaudio.device", "default");
if (OK (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size))) {
int num = size / (int) sizeof (AudioDeviceID);

View file

@ -66,7 +66,7 @@ void fluid_coremidi_callback(const MIDIPacketList *list, void *p, void *src);
void fluid_coremidi_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "midi.coremidi.id", "pid", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.coremidi.id", "pid", 0);
}
/*

View file

@ -75,7 +75,7 @@ static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuff
void fluid_dart_audio_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "audio.dart.device", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.dart.device", "default", 0);
}

View file

@ -84,7 +84,7 @@ fluid_dsound_enum_callback2(LPGUID guid, LPCTSTR description, LPCTSTR module, LP
void fluid_dsound_audio_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "audio.dsound.device", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.dsound.device", "default", 0);
fluid_settings_add_option(settings, "audio.dsound.device", "default");
DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback, settings);
}

View file

@ -28,7 +28,6 @@
*
*/
#include "fluidsynth_priv.h"
#include "fluid_sys.h"
#include "fluid_synth.h"
#include "fluid_adriver.h"
@ -38,7 +37,6 @@
#include <jack/jack.h>
#include <jack/midiport.h>
#include "config.h"
#include "fluid_lash.h"
@ -106,10 +104,10 @@ static fluid_jack_client_t *last_client = NULL; /* Last unpaired client. F
void
fluid_jack_audio_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "audio.jack.id", "fluidsynth", 0, NULL, NULL);
fluid_settings_register_int(settings, "audio.jack.multi", 0, 0, 1, FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "audio.jack.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_str(settings, "audio.jack.server", "", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.jack.id", "fluidsynth", 0);
fluid_settings_register_int(settings, "audio.jack.multi", 0, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_int(settings, "audio.jack.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_str(settings, "audio.jack.server", "", 0);
}
/*
@ -614,8 +612,8 @@ fluid_jack_driver_shutdown(void *arg)
void fluid_jack_midi_driver_settings (fluid_settings_t *settings)
{
fluid_settings_register_str (settings, "midi.jack.id", "fluidsynth-midi", 0, NULL, NULL);
fluid_settings_register_str (settings, "midi.jack.server", "", 0, NULL, NULL);
fluid_settings_register_str (settings, "midi.jack.id", "fluidsynth-midi", 0);
fluid_settings_register_str (settings, "midi.jack.server", "", 0);
}
/*

View file

@ -144,26 +144,26 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
{
unsigned int i;
fluid_settings_register_int (settings, "midi.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int (settings, "midi.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_int (settings, "midi.realtime-prio",
FLUID_DEFAULT_MIDI_RT_PRIO, 0, 99, 0, NULL, NULL);
FLUID_DEFAULT_MIDI_RT_PRIO, 0, 99, 0);
/* Set the default driver */
#if ALSA_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "alsa_seq", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.driver", "alsa_seq", 0);
#elif JACK_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "jack", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.driver", "jack", 0);
#elif OSS_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "oss", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.driver", "oss", 0);
#elif WINMIDI_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "winmidi", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.driver", "winmidi", 0);
#elif MIDISHARE_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "midishare", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.driver", "midishare", 0);
#elif COREMIDI_SUPPORT
fluid_settings_register_str(settings, "midi.driver", "coremidi", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.driver", "coremidi", 0);
#else
fluid_settings_register_str(settings, "midi.driver", "", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.driver", "", 0);
#endif
/* Add all drivers to the list of options */

View file

@ -101,7 +101,7 @@ static fluid_thread_return_t fluid_oss_midi_run(void* d);
void
fluid_oss_audio_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "audio.oss.device", "/dev/dsp", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.oss.device", "/dev/dsp", 0);
}
/*
@ -502,7 +502,7 @@ fluid_oss_audio_run2(void* d)
void fluid_oss_midi_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "midi.oss.device", "/dev/midi", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.oss.device", "/dev/midi", 0);
}
/*

View file

@ -122,7 +122,7 @@ fluid_portaudio_driver_settings (fluid_settings_t *settings)
PaError err;
int i;
fluid_settings_register_str (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE, 0, NULL, NULL);
fluid_settings_register_str (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE, 0);
fluid_settings_add_option (settings, "audio.portaudio.device", PORTAUDIO_DEFAULT_DEVICE);
err = Pa_Initialize();

View file

@ -28,8 +28,6 @@
#include "fluid_adriver.h"
#include "fluid_settings.h"
#include "config.h"
#if PULSE_SUPPORT
#include <pulse/simple.h>
@ -63,11 +61,11 @@ static fluid_thread_return_t fluid_pulse_audio_run2(void* d);
void fluid_pulse_audio_driver_settings(fluid_settings_t* settings)
{
fluid_settings_register_str(settings, "audio.pulseaudio.server", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.pulseaudio.device", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.pulseaudio.media-role", "music", 0, NULL, NULL);
fluid_settings_register_str(settings, "audio.pulseaudio.server", "default", 0);
fluid_settings_register_str(settings, "audio.pulseaudio.device", "default", 0);
fluid_settings_register_str(settings, "audio.pulseaudio.media-role", "music", 0);
fluid_settings_register_int(settings, "audio.pulseaudio.adjust-latency", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
FLUID_HINT_TOGGLED);
}

View file

@ -26,8 +26,7 @@
* NOTE: Unfortunately midiInAddBuffer(), for SYSEX data, should not be called
* from within the MIDI input callback, despite many examples contrary to that
* on the Internet. Some MIDI devices will deadlock. Therefore we add MIDIHDR
* pointers to a queue and re-add them in a separate thread, using a mutex and
* conditional to wake up the thread. Lame-o API! :(
* pointers to a queue and re-add them in a separate thread. Lame-o API! :(
*/
#include "fluidsynth_priv.h"
@ -44,22 +43,17 @@
typedef struct {
fluid_midi_driver_t driver;
HMIDIIN hmidiin;
fluid_atomic_int_t closing; /* Set to TRUE when closing driver, to prevent endless SYSEX lockup loop */
fluid_thread_t *sysExAddThread; /* Thread for SYSEX re-add thread */
fluid_cond_mutex_t *mutex; /* Lock for condition */
fluid_cond_t *cond; /* Condition to signal MIDI event thread of available events */
/* MIDI HDR for SYSEX buffer */
MIDIHDR sysExHdrs[MIDI_SYSEX_BUF_COUNT];
/* TRUE for each MIDIHDR buffer which should be re-added to MIDI device */
fluid_atomic_int_t sysExHdrAdd[MIDI_SYSEX_BUF_COUNT];
/* Thread for SYSEX re-add thread */
HANDLE hThread;
DWORD dwThread;
/* Sysex data buffer */
unsigned char sysExBuf[MIDI_SYSEX_BUF_COUNT * MIDI_SYSEX_MAX_SIZE];
int sysExOffset; /* Current offset in sysex buffer (for message continuation) */
} fluid_winmidi_driver_t;
static char fluid_winmidi_error_buffer[256];
@ -76,9 +70,7 @@ void delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
void CALLBACK fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
DWORD_PTR msg, DWORD_PTR extra);
static fluid_thread_return_t fluid_winmidi_add_sysex_thread (void *data);
static char* fluid_winmidi_input_error(int no);
int fluid_winmidi_driver_status(fluid_midi_driver_t* p);
static char* fluid_winmidi_input_error(MMRESULT no);
void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings)
@ -86,7 +78,7 @@ void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings)
MMRESULT res;
MIDIINCAPS in_caps;
UINT i, num;
fluid_settings_register_str(settings, "midi.winmidi.device", "default", 0, NULL, NULL);
fluid_settings_register_str(settings, "midi.winmidi.device", "default", 0);
num = midiInGetNumDevs();
if (num > 0) {
fluid_settings_add_option(settings, "midi.winmidi.device", "default");
@ -99,6 +91,34 @@ void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings)
}
}
/* Thread for re-adding SYSEX buffers */
static DWORD WINAPI fluid_winmidi_add_sysex_thread(void *data)
{
fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *)data;
MSG msg;
int code;
for (;;) {
code = GetMessage(&msg, NULL, 0, 0);
if (code < 0) {
FLUID_LOG(FLUID_ERR, "fluid_winmidi_add_sysex_thread: GetMessage() failed.");
break;
}
if (msg.message == WM_CLOSE)
break;
switch (msg.message) {
case MM_MIM_LONGDATA:
midiInAddBuffer(dev->hmidiin, (LPMIDIHDR)msg.lParam, sizeof(MIDIHDR));
break;
}
}
return 0;
}
/*
* new_fluid_winmidi_driver
*/
@ -109,7 +129,7 @@ new_fluid_winmidi_driver(fluid_settings_t* settings,
fluid_winmidi_driver_t* dev;
MIDIHDR *hdr;
MMRESULT res;
UINT i, err, num, midi_num = 0;
UINT i, num, midi_num = 0;
MIDIINCAPS in_caps;
char* devname = NULL;
@ -124,12 +144,11 @@ new_fluid_winmidi_driver(fluid_settings_t* settings,
return NULL;
}
memset (dev, 0, sizeof (fluid_winmidi_driver_t));
FLUID_MEMSET (dev, 0, sizeof (fluid_winmidi_driver_t));
dev->hmidiin = NULL;
dev->driver.handler = handler;
dev->driver.data = data;
fluid_atomic_int_set (&dev->closing, FALSE);
/* get the device name. if none is specified, use the default device. */
if(fluid_settings_dupstr(settings, "midi.winmidi.device", &devname) != FLUID_OK || !devname) {
@ -169,40 +188,55 @@ new_fluid_winmidi_driver(fluid_settings_t* settings,
}
/* try opening the device */
err = midiInOpen(&dev->hmidiin, midi_num,
res = midiInOpen(&dev->hmidiin, midi_num,
(DWORD_PTR) fluid_winmidi_callback,
(DWORD_PTR) dev, CALLBACK_FUNCTION);
if (err != MMSYSERR_NOERROR) {
if (res != MMSYSERR_NOERROR) {
FLUID_LOG(FLUID_ERR, "Couldn't open MIDI input: %s (error %d)",
fluid_winmidi_input_error(err), err);
fluid_winmidi_input_error(res), res);
goto error_recovery;
}
/* Prepare and add SYSEX buffers */
for (i = 0; i < MIDI_SYSEX_BUF_COUNT; i++)
{
fluid_atomic_int_set (&dev->sysExHdrAdd[i], FALSE);
hdr = &dev->sysExHdrs[i];
hdr->lpData = &dev->sysExBuf[i * MIDI_SYSEX_MAX_SIZE];
hdr->lpData = (LPSTR)&dev->sysExBuf[i * MIDI_SYSEX_MAX_SIZE];
hdr->dwBufferLength = MIDI_SYSEX_MAX_SIZE;
/* Prepare a buffer for SYSEX data and add it */
err = midiInPrepareHeader (dev->hmidiin, hdr, sizeof (MIDIHDR));
res = midiInPrepareHeader (dev->hmidiin, hdr, sizeof (MIDIHDR));
if (err == MMSYSERR_NOERROR)
if (res == MMSYSERR_NOERROR)
{
err = midiInAddBuffer (dev->hmidiin, hdr, sizeof (MIDIHDR));
res = midiInAddBuffer (dev->hmidiin, hdr, sizeof (MIDIHDR));
if (err != MMSYSERR_NOERROR)
if (res != MMSYSERR_NOERROR)
{
FLUID_LOG (FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)",
fluid_winmidi_input_error (err), err);
fluid_winmidi_input_error (res), res);
midiInUnprepareHeader (dev->hmidiin, hdr, sizeof (MIDIHDR));
}
}
else FLUID_LOG (FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)",
fluid_winmidi_input_error (err), err);
fluid_winmidi_input_error (res), res);
}
/* Create thread which processes re-adding SYSEX buffers */
dev->hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)
fluid_winmidi_add_sysex_thread,
dev,
0,
&dev->dwThread);
if (dev->hThread == NULL)
{
FLUID_LOG(FLUID_ERR, "Failed to create SYSEX buffer processing thread");
goto error_recovery;
}
/* Start the MIDI input interface */
@ -211,25 +245,6 @@ new_fluid_winmidi_driver(fluid_settings_t* settings,
goto error_recovery;
}
/* Create mutex and condition */
dev->mutex = new_fluid_cond_mutex ();
dev->cond = new_fluid_cond ();
if (!dev->mutex || !dev->cond)
{
FLUID_LOG(FLUID_ERR, "Out of memory");
goto error_recovery;
}
/* Create thread which processes re-adding SYSEX buffers */
dev->sysExAddThread = new_fluid_thread ("winmidi-sysex", fluid_winmidi_add_sysex_thread,
dev, 0, FALSE);
if (!dev->sysExAddThread)
{
FLUID_LOG(FLUID_ERR, "Failed to create SYSEX buffer processing thread");
goto error_recovery;
}
if (devname) FLUID_FREE (devname); /* -- free device name */
return (fluid_midi_driver_t*) dev;
@ -248,27 +263,22 @@ delete_fluid_winmidi_driver(fluid_midi_driver_t* p)
{
fluid_winmidi_driver_t* dev = (fluid_winmidi_driver_t*) p;
fluid_return_if_fail (dev != NULL);
if (dev->hmidiin != NULL) {
fluid_atomic_int_set (&dev->closing, TRUE);
if (dev->sysExAddThread)
{
fluid_cond_mutex_lock (dev->mutex); /* ++ lock */
fluid_cond_signal (dev->cond);
fluid_cond_mutex_unlock (dev->mutex); /* -- unlock */
if (dev->hThread != NULL)
{
PostThreadMessage(dev->dwThread, WM_CLOSE, 0, 0);
WaitForSingleObject(dev->hThread, INFINITE);
fluid_thread_join (dev->sysExAddThread);
}
dev->hThread = NULL;
}
if (dev->hmidiin != NULL)
{
midiInStop(dev->hmidiin);
midiInReset(dev->hmidiin);
midiInClose(dev->hmidiin);
}
if (dev->mutex) delete_fluid_cond_mutex (dev->mutex);
if (dev->cond) delete_fluid_cond (dev->cond);
FLUID_FREE(dev);
}
@ -280,7 +290,6 @@ fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
fluid_midi_event_t event;
LPMIDIHDR pMidiHdr;
unsigned char *data;
int index;
unsigned int msg_param = (unsigned int) dwParam1;
switch (wMsg) {
@ -306,7 +315,8 @@ fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
break;
case MIM_LONGDATA: /* SYSEX data */
if (fluid_atomic_int_get (&dev->closing)) break; /* Prevent MIM_LONGDATA endless loop, don't re-add buffer if closing */
if (dev->hThread == NULL)
break;
pMidiHdr = (LPMIDIHDR)dwParam1;
data = (unsigned char *)(pMidiHdr->lpData);
@ -320,12 +330,7 @@ fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
(*dev->driver.handler)(dev->driver.data, &event);
}
index = (pMidiHdr - dev->sysExHdrs) / sizeof (MIDIHDR);
fluid_atomic_int_set (&dev->sysExHdrAdd[index], TRUE);
fluid_cond_mutex_lock (dev->mutex); /* ++ lock */
fluid_cond_signal (dev->cond);
fluid_cond_mutex_unlock (dev->mutex); /* -- unlock */
PostThreadMessage(dev->dwThread, MM_MIM_LONGDATA, 0, dwParam1);
break;
case MIM_ERROR:
@ -339,40 +344,8 @@ fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
}
}
/* Thread for re-adding SYSEX buffers */
static fluid_thread_return_t
fluid_winmidi_add_sysex_thread (void *data)
{
fluid_winmidi_driver_t *dev = data;
int i;
while (!fluid_atomic_int_get (&dev->closing))
{
fluid_cond_mutex_lock (dev->mutex); /* ++ lock */
fluid_cond_wait (dev->cond, dev->mutex);
fluid_cond_mutex_unlock (dev->mutex); /* -- unlock */
for (i = 0; i < MIDI_SYSEX_BUF_COUNT; i++)
{
if (fluid_atomic_int_get (&dev->sysExHdrAdd[i]))
{
fluid_atomic_int_set (&dev->sysExHdrAdd[i], FALSE);
midiInAddBuffer (dev->hmidiin, &dev->sysExHdrs[i], sizeof (MIDIHDR));
}
}
}
return FLUID_THREAD_RETURN_VALUE;
}
int
fluid_winmidi_driver_status(fluid_midi_driver_t* p)
{
return 0;
}
static char*
fluid_winmidi_input_error(int no)
fluid_winmidi_input_error(MMRESULT no)
{
midiInGetErrorText(no, fluid_winmidi_error_buffer, 256);
return fluid_winmidi_error_buffer;

View file

@ -94,9 +94,9 @@ void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg)
if (fluid_settings_get_hints (settings, optarg, &hints) == FLUID_OK
&& hints & FLUID_HINT_TOGGLED)
{
if (FLUID_STRCMP (val, "yes") == 0 || FLUID_STRCMP (val, "True") == 0
|| FLUID_STRCMP (val, "TRUE") == 0 || FLUID_STRCMP (val, "true") == 0
|| FLUID_STRCMP (val, "T") == 0)
if (FLUID_STRCASECMP (val, "yes") == 0
|| FLUID_STRCASECMP (val, "true") == 0
|| FLUID_STRCASECMP (val, "t") == 0)
ival = 1;
else ival = atoi (val);
}

View file

@ -126,7 +126,7 @@ delete_fluid_midi_file (fluid_midi_file *mf)
/*
* Gets the next byte in a MIDI file, taking into account previous running status.
*
* returns FLUID_FAILED if EOF or read error
* returns -1 if EOF or read error
*/
int
fluid_midi_file_getc (fluid_midi_file *mf)
@ -138,7 +138,7 @@ fluid_midi_file_getc (fluid_midi_file *mf)
} else {
if (mf->buf_pos >= mf->buf_len) {
mf->eof = TRUE;
return FLUID_FAILED;
return -1;
}
c = mf->buffer[mf->buf_pos++];
mf->trackpos++;
@ -797,7 +797,6 @@ new_fluid_midi_event ()
/**
* Delete MIDI event structure.
* @param evt MIDI event structure
* @return Always returns #FLUID_OK
*/
void
delete_fluid_midi_event(fluid_midi_event_t *evt)
@ -1259,7 +1258,6 @@ new_fluid_player(fluid_synth_t *synth)
/**
* Delete a MIDI player instance.
* @param player MIDI player instance
* @return Always returns #FLUID_OK
*/
void
delete_fluid_player(fluid_player_t *player)
@ -1293,14 +1291,12 @@ fluid_player_settings(fluid_settings_t *settings)
{
/* player.timing-source can be either "system" (use system timer)
or "sample" (use timer based on number of written samples) */
fluid_settings_register_str(settings, "player.timing-source", "sample", 0,
NULL, NULL);
fluid_settings_register_str(settings, "player.timing-source", "sample", 0);
fluid_settings_add_option(settings, "player.timing-source", "sample");
fluid_settings_add_option(settings, "player.timing-source", "system");
/* Selects whether the player should reset the synth between songs, or not. */
fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "player.reset-synth", 1, 0, 1, FLUID_HINT_TOGGLED);
}

View file

@ -263,7 +263,7 @@ int fluid_track_send_events(fluid_track_t* track,
#define fluid_track_eot(track) ((track)->cur == NULL)
/**
/*
* fluid_playlist_item
* Used as the `data' elements of the fluid_player.playlist.
* Represents either a filename or a pre-loaded memory buffer.

View file

@ -28,7 +28,6 @@
*/
#include "fluid_event_priv.h"
#include "fluidsynth_priv.h" // FLUID_NEW, etc
#include "fluid_sys.h" // timer, threads, etc...
#include "fluid_list.h"

View file

@ -48,7 +48,7 @@ enum fluid_loop {
FLUID_LOOP_UNTIL_RELEASE = 3
};
/**
/*
* rvoice ticks-based parameters
* These parameters must be updated even if the voice is currently quiet.
*/
@ -77,7 +77,7 @@ struct _fluid_rvoice_envlfo_t
fluid_real_t viblfo_to_pitch;
};
/**
/*
* rvoice parameters needed for dsp interpolation
*/
struct _fluid_rvoice_dsp_t
@ -129,7 +129,7 @@ struct _fluid_rvoice_dsp_t
ever add surround positioning, or stereo reverb/chorus */
#define FLUID_RVOICE_MAX_BUFS (4)
/**
/*
* rvoice mixer-related parameters
*/
struct _fluid_rvoice_buffers_t
@ -142,7 +142,7 @@ struct _fluid_rvoice_buffers_t
};
/**
/*
* Hard real-time parameters needed to synthesize a voice
*/
struct _fluid_rvoice_t

View file

@ -42,7 +42,7 @@ struct _fluid_rvoice_event_t {
void fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event);
/**
/*
* Bridge between the renderer thread and the midi state thread.
* If is_threadsafe is true, that means fluid_rvoice_eventhandler_fetch_all
* can be called in parallell with fluid_rvoice_eventhandler_push/flush

View file

@ -587,7 +587,7 @@ int delete_fluid_defsfont(fluid_defsfont_t* sfont)
/* Check that no samples are currently used */
for (list = sfont->sample; list; list = fluid_list_next(list)) {
sample = (fluid_sample_t*) fluid_list_get(list);
if (fluid_sample_refcount(sample) != 0) {
if (sample->refcount != 0) {
return FLUID_FAILED;
}
}
@ -1261,7 +1261,7 @@ delete_fluid_preset_zone(fluid_preset_zone_t* zone)
{
tmp = mod;
mod = mod->next;
fluid_mod_delete (tmp);
delete_fluid_mod (tmp);
}
FLUID_FREE (zone->name);
@ -1312,7 +1312,7 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_
for (count = 0, r = sfzone->mod; r != NULL; count++) {
SFMod* mod_src = (SFMod *)r->data;
fluid_mod_t * mod_dest = fluid_mod_new();
fluid_mod_t * mod_dest = new_fluid_mod();
int type;
if (mod_dest == NULL){
@ -1653,7 +1653,7 @@ delete_fluid_inst_zone(fluid_inst_zone_t* zone)
{
tmp = mod;
mod = mod->next;
fluid_mod_delete (tmp);
delete_fluid_mod (tmp);
}
FLUID_FREE (zone->name);
@ -1715,7 +1715,7 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs
int type;
fluid_mod_t* mod_dest;
mod_dest = fluid_mod_new();
mod_dest = new_fluid_mod();
if (mod_dest == NULL){
return FLUID_FAILED;
}

View file

@ -256,7 +256,7 @@ delete_fluid_ramsfont (fluid_ramsfont_t* sfont)
/* Check that no samples are currently used */
for (list = sfont->sample; list; list = fluid_list_next(list)) {
fluid_sample_t* sam = (fluid_sample_t*) fluid_list_get(list);
if (fluid_sample_refcount(sam) != 0) {
if (sam->refcount != 0) {
return -1;
}
}
@ -1211,7 +1211,6 @@ new_fluid_ramsample (void)
/**
* Delete a RAM SoundFont sample.
* @param sample Sample to delete
* @return #FLUID_OK
*/
void
delete_fluid_ramsample (fluid_sample_t* sample)

View file

@ -32,6 +32,8 @@
#define delete_fluid_sfont(_sf) ( ((_sf) && (_sf)->free)? (*(_sf)->free)(_sf) : 0)
#define fluid_sfont_get_id(_sf) ((_sf)->id)
#define fluid_sfont_get_name(_sf) (*(_sf)->get_name)(_sf)
#define fluid_sfont_get_preset(_sf,_bank,_prenum) (*(_sf)->get_preset)(_sf,_bank,_prenum)
#define fluid_sfont_iteration_start(_sf) (*(_sf)->iteration_start)(_sf)

View file

@ -33,7 +33,7 @@ typedef struct _fluid_gen_info_t {
float def; /* The default value (cfr. fluid_gen_set_default_values()) */
} fluid_gen_info_t;
/**
/*
* SoundFont generator structure.
*/
typedef struct _fluid_gen_t
@ -44,7 +44,7 @@ typedef struct _fluid_gen_t
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

View file

@ -383,7 +383,7 @@ fluid_mod_get_value(fluid_mod_t* mod, fluid_channel_t* chan, fluid_voice_t* voic
* @return New allocated modulator or NULL if out of memory
*/
fluid_mod_t*
fluid_mod_new()
new_fluid_mod()
{
fluid_mod_t* mod = FLUID_NEW (fluid_mod_t);
if (mod == NULL) {
@ -398,7 +398,7 @@ fluid_mod_new()
* @param mod Modulator to free
*/
void
fluid_mod_delete (fluid_mod_t *mod)
delete_fluid_mod (fluid_mod_t *mod)
{
FLUID_FREE(mod);
}

View file

@ -24,7 +24,7 @@
#include "fluidsynth_priv.h"
#include "fluid_conv.h"
/**
/*
* Modulator structure. See SoundFont 2.04 PDF section 8.2.
*/
struct _fluid_mod_t

View file

@ -18,8 +18,6 @@
* 02110-1301, USA
*/
#include <math.h>
#include "fluid_synth.h"
#include "fluid_sys.h"
#include "fluid_chan.h"
@ -43,10 +41,6 @@ static int fluid_synth_noteon_LOCAL(fluid_synth_t* synth, int chan, int key,
int vel);
static int fluid_synth_noteoff_LOCAL(fluid_synth_t* synth, int chan, int key);
static int fluid_synth_cc_LOCAL(fluid_synth_t* synth, int channum, int num);
static int fluid_synth_update_device_id (fluid_synth_t *synth, char *name,
int value);
static int fluid_synth_update_overflow (fluid_synth_t *synth, char *name,
fluid_real_t value);
static int fluid_synth_sysex_midi_tuning (fluid_synth_t *synth, const char *data,
int len, char *response,
int *response_len, int avail_response,
@ -71,13 +65,7 @@ fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname
unsigned int banknum, unsigned int prognum);
static void fluid_synth_update_presets(fluid_synth_t* synth);
static int fluid_synth_update_sample_rate(fluid_synth_t* synth,
char* name, double value);
static int fluid_synth_update_gain(fluid_synth_t* synth,
char* name, double value);
static void fluid_synth_update_gain_LOCAL(fluid_synth_t* synth);
static int fluid_synth_update_polyphony(fluid_synth_t* synth,
char* name, int value);
static int fluid_synth_update_polyphony_LOCAL(fluid_synth_t* synth, int new_polyphony);
static void init_dither(void);
static FLUID_INLINE int roundi (float x);
@ -109,6 +97,18 @@ static void fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan,
static void fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id);
static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels);
/* Callback handlers for real-time settings */
static void fluid_synth_handle_sample_rate(void *data, const char *name, double value);
static void fluid_synth_handle_gain(void *data, const char *name, double value);
static void fluid_synth_handle_polyphony(void *data, const char *name, int value);
static void fluid_synth_handle_device_id(void *data, const char *name, int value);
static void fluid_synth_handle_overflow(void *data, const char *name, double value);
static void fluid_synth_handle_important_channels(void *data, const char *name,
const char *value);
/***************************************************************
*
@ -155,77 +155,49 @@ static const fluid_revmodel_presets_t revmodel_preset[] = {
* INITIALIZATION & UTILITIES
*/
static void fluid_synth_register_overflow(fluid_settings_t* settings,
fluid_num_update_t update_func,
void* update_data)
{
fluid_settings_register_num(settings, "synth.overflow.percussion",
4000, -10000, 10000, 0, update_func, update_data);
fluid_settings_register_num(settings, "synth.overflow.sustained",
-1000, -10000, 10000, 0, update_func, update_data);
fluid_settings_register_num(settings, "synth.overflow.released",
-2000, -10000, 10000, 0, update_func, update_data);
fluid_settings_register_num(settings, "synth.overflow.age",
1000, -10000, 10000, 0, update_func, update_data);
fluid_settings_register_num(settings, "synth.overflow.volume",
500, -10000, 10000, 0, update_func, update_data);
}
void fluid_synth_settings(fluid_settings_t* settings)
{
fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_str(settings, "midi.portname", "", 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.verbose", 0, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_int(settings, "synth.reverb.active", 1, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_int(settings, "synth.chorus.active", 1, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_int(settings, "synth.ladspa.active", 0, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_int(settings, "synth.lock-memory", 1, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_str(settings, "midi.portname", "", 0);
#ifdef DEFAULT_SOUNDFONT
fluid_settings_register_str(settings, "synth.default-soundfont",
DEFAULT_SOUNDFONT, 0, NULL, NULL);
fluid_settings_register_str(settings, "synth.default-soundfont", DEFAULT_SOUNDFONT, 0);
#endif
fluid_settings_register_int(settings, "synth.polyphony",
256, 1, 65535, 0, NULL, NULL);
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,
0, NULL, NULL);
fluid_settings_register_int(settings, "synth.audio-channels",
1, 1, 128, 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.audio-groups",
1, 1, 128, 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.effects-channels",
2, 2, 2, 0, NULL, NULL);
fluid_settings_register_num(settings, "synth.sample-rate",
44100.0f, 8000.0f, 96000.0f,
0, NULL, NULL);
fluid_settings_register_int(settings, "synth.device-id",
0, 0, 126, 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.polyphony", 256, 1, 65535, 0);
fluid_settings_register_int(settings, "synth.midi-channels", 16, 16, 256, 0);
fluid_settings_register_num(settings, "synth.gain", 0.2f, 0.0f, 10.0f, 0);
fluid_settings_register_int(settings, "synth.audio-channels", 1, 1, 128, 0);
fluid_settings_register_int(settings, "synth.audio-groups", 1, 1, 128, 0);
fluid_settings_register_int(settings, "synth.effects-channels", 2, 2, 2, 0);
fluid_settings_register_num(settings, "synth.sample-rate", 44100.0f, 8000.0f, 96000.0f, 0);
fluid_settings_register_int(settings, "synth.device-id", 0, 0, 126, 0);
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0);
fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0, NULL, NULL);
fluid_settings_register_int(settings, "synth.min-note-length", 10, 0, 65535, 0);
fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.parallel-render", 1, 0, 1,
FLUID_HINT_TOGGLED, NULL, NULL);
fluid_settings_register_int(settings, "synth.threadsafe-api", 1, 0, 1, FLUID_HINT_TOGGLED);
fluid_settings_register_int(settings, "synth.parallel-render", 1, 0, 1, FLUID_HINT_TOGGLED);
fluid_synth_register_overflow(settings, NULL, NULL);
fluid_settings_register_num(settings, "synth.overflow.percussion", 4000, -10000, 10000, 0);
fluid_settings_register_num(settings, "synth.overflow.sustained", -1000, -10000, 10000, 0);
fluid_settings_register_num(settings, "synth.overflow.released", -2000, -10000, 10000, 0);
fluid_settings_register_num(settings, "synth.overflow.age", 1000, -10000, 10000, 0);
fluid_settings_register_num(settings, "synth.overflow.volume", 500, -10000, 10000, 0);
fluid_settings_register_num(settings, "synth.overflow.important", 5000, -50000, 50000, 0);
fluid_settings_register_str(settings, "synth.overflow.important-channels", "", 0);
fluid_settings_register_str(settings, "synth.midi-bank-select", "gs", 0, NULL, NULL);
fluid_settings_register_str(settings, "synth.midi-bank-select", "gs", 0);
fluid_settings_add_option(settings, "synth.midi-bank-select", "gm");
fluid_settings_add_option(settings, "synth.midi-bank-select", "gs");
fluid_settings_add_option(settings, "synth.midi-bank-select", "xg");
fluid_settings_add_option(settings, "synth.midi-bank-select", "mma");
fluid_settings_register_str(settings, "synth.volenv", "emu", 0, NULL, NULL);
fluid_settings_register_str(settings, "synth.volenv", "emu", 0);
fluid_settings_add_option(settings, "synth.volenv", "emu");
fluid_settings_add_option(settings, "synth.volenv", "compliant");
}
@ -549,11 +521,9 @@ new_fluid_synth(fluid_settings_t *settings)
{
fluid_synth_t* synth;
fluid_sfloader_t* loader;
double gain;
char *important_channels;
int i, nbuf;
int with_ladspa = 0;
int with_reverb = 0;
int with_chorus = 0;
/* initialize all the conversion tables and other stuff */
if (fluid_atomic_int_compare_and_exchange(&fluid_synth_initialized, 0, 1))
@ -594,10 +564,8 @@ new_fluid_synth(fluid_settings_t *settings)
synth->settings = settings;
fluid_settings_getint(settings, "synth.reverb.active", &with_reverb);
fluid_atomic_int_set(&synth->with_reverb, with_reverb);
fluid_settings_getint(settings, "synth.chorus.active", &with_chorus);
fluid_atomic_int_set(&synth->with_chorus, with_chorus);
fluid_settings_getint(settings, "synth.reverb.active", &synth->with_reverb);
fluid_settings_getint(settings, "synth.chorus.active", &synth->with_chorus);
fluid_settings_getint(settings, "synth.verbose", &synth->verbose);
fluid_settings_getint(settings, "synth.polyphony", &synth->polyphony);
@ -606,29 +574,41 @@ new_fluid_synth(fluid_settings_t *settings)
fluid_settings_getint(settings, "synth.audio-channels", &synth->audio_channels);
fluid_settings_getint(settings, "synth.audio-groups", &synth->audio_groups);
fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels);
fluid_settings_getnum(settings, "synth.gain", &gain);
synth->gain = gain;
fluid_settings_getnum_float(settings, "synth.gain", &synth->gain);
fluid_settings_getint(settings, "synth.device-id", &synth->device_id);
fluid_settings_getint(settings, "synth.cpu-cores", &synth->cores);
/* register the callbacks */
fluid_settings_register_num(settings, "synth.sample-rate",
44100.0f, 8000.0f, 96000.0f, 0,
(fluid_num_update_t) fluid_synth_update_sample_rate, synth);
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",
synth->polyphony, 1, 65535, 0,
(fluid_int_update_t) fluid_synth_update_polyphony,
synth);
fluid_settings_register_int(settings, "synth.device-id",
synth->device_id, 126, 0, 0,
(fluid_int_update_t) fluid_synth_update_device_id, synth);
fluid_settings_getnum_float(settings, "synth.overflow.percussion", &synth->overflow.percussion);
fluid_settings_getnum_float(settings, "synth.overflow.released", &synth->overflow.released);
fluid_settings_getnum_float(settings, "synth.overflow.sustained", &synth->overflow.sustained);
fluid_settings_getnum_float(settings, "synth.overflow.volume", &synth->overflow.volume);
fluid_settings_getnum_float(settings, "synth.overflow.age", &synth->overflow.age);
fluid_settings_getnum_float(settings, "synth.overflow.important", &synth->overflow.important);
/* register the callbacks */
fluid_settings_callback_num(settings, "synth.sample-rate",
fluid_synth_handle_sample_rate, synth);
fluid_settings_callback_num(settings, "synth.gain",
fluid_synth_handle_gain, synth);
fluid_settings_callback_int(settings, "synth.polyphony",
fluid_synth_handle_polyphony, synth);
fluid_settings_callback_int(settings, "synth.device-id",
fluid_synth_handle_device_id, synth);
fluid_settings_callback_num(settings, "synth.overflow.percussion",
fluid_synth_handle_overflow, synth);
fluid_settings_callback_num(settings, "synth.overflow.sustained",
fluid_synth_handle_overflow, synth);
fluid_settings_callback_num(settings, "synth.overflow.released",
fluid_synth_handle_overflow, synth);
fluid_settings_callback_num(settings, "synth.overflow.age",
fluid_synth_handle_overflow, synth);
fluid_settings_callback_num(settings, "synth.overflow.volume",
fluid_synth_handle_overflow, synth);
fluid_settings_callback_num(settings, "synth.overflow.important",
fluid_synth_handle_overflow, synth);
fluid_settings_callback_str(settings, "synth.overflow.important-channels",
fluid_synth_handle_important_channels, synth);
fluid_synth_register_overflow(settings,
(fluid_num_update_t) fluid_synth_update_overflow, synth);
/* do some basic sanity checking on the settings */
if (synth->midi_channels % 16 != 0) {
@ -665,7 +645,6 @@ new_fluid_synth(fluid_settings_t *settings)
synth->effects_channels = 2;
}
/* The number of buffers is determined by the higher number of nr
* groups / nr audio channels. If LADSPA is unused, they should be
* the same. */
@ -674,6 +653,16 @@ new_fluid_synth(fluid_settings_t *settings)
nbuf = synth->audio_groups;
}
if (fluid_settings_dupstr(settings, "synth.overflow.important-channels",
&important_channels) == FLUID_OK)
{
if (fluid_synth_set_important_channels(synth, important_channels) != FLUID_OK)
{
FLUID_LOG(FLUID_WARN, "Failed to set overflow important channels");
}
FLUID_FREE(important_channels);
}
/* as soon as the synth is created it starts playing. */
synth->state = FLUID_SYNTH_PLAYING;
synth->sfont_info = NULL;
@ -760,12 +749,10 @@ new_fluid_synth(fluid_settings_t *settings)
}
fluid_synth_set_sample_rate(synth, synth->sample_rate);
fluid_synth_update_overflow(synth, "", 0.0f);
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_polyphony,
synth->polyphony, 0.0f);
fluid_synth_set_reverb_on(synth, fluid_atomic_int_get(&synth->with_reverb));
fluid_synth_set_chorus_on(synth, fluid_atomic_int_get(&synth->with_chorus));
fluid_synth_set_reverb_on(synth, synth->with_reverb);
fluid_synth_set_chorus_on(synth, synth->with_chorus);
synth->cur = FLUID_BUFSIZE;
synth->curmax = 0;
@ -818,7 +805,6 @@ new_fluid_synth(fluid_settings_t *settings)
/**
* Delete a FluidSynth instance.
* @param synth FluidSynth instance to delete
* @return FLUID_OK
*
* @note Other users of a synthesizer instance, such as audio and MIDI drivers,
* should be deleted prior to freeing the FluidSynth instance.
@ -931,9 +917,11 @@ delete_fluid_synth(fluid_synth_t* synth)
while (default_mod != NULL) {
mod = default_mod;
default_mod = mod->next;
fluid_mod_delete(mod);
delete_fluid_mod(mod);
}
FLUID_FREE(synth->overflow.important_channels);
fluid_rec_mutex_destroy(synth->mutex);
FLUID_FREE(synth);
@ -1130,7 +1118,7 @@ fluid_synth_add_default_mod(fluid_synth_t* synth, fluid_mod_t* mod, int mode)
}
/* Add a new modulator (no existing modulator to add / overwrite). */
new_mod = fluid_mod_new();
new_mod = new_fluid_mod();
if (new_mod == NULL)
FLUID_API_RETURN(FLUID_FAILED);
@ -1175,7 +1163,7 @@ fluid_synth_remove_default_mod(fluid_synth_t* synth, const fluid_mod_t* mod)
{
last_mod->next = default_mod->next;
}
fluid_mod_delete(default_mod);
delete_fluid_mod(default_mod);
FLUID_API_RETURN(FLUID_OK);
}
last_mod = default_mod;
@ -1359,13 +1347,15 @@ fluid_synth_get_cc(fluid_synth_t* synth, int chan, int num, int* pval)
/*
* Handler for synth.device-id setting.
*/
static int
fluid_synth_update_device_id (fluid_synth_t *synth, char *name, int value)
static void
fluid_synth_handle_device_id (void *data, const char *name, int value)
{
fluid_synth_t *synth = (fluid_synth_t *)data;
fluid_return_if_fail(synth != NULL);
fluid_synth_api_enter(synth);
synth->device_id = value;
fluid_synth_api_exit(synth);
return 0;
}
/**
@ -2373,11 +2363,11 @@ fluid_synth_update_presets(fluid_synth_t* synth)
}
/* Handler for synth.sample-rate setting. */
static int
fluid_synth_update_sample_rate(fluid_synth_t* synth, char* name, double value)
static void
fluid_synth_handle_sample_rate(void *data, const char* name, double value)
{
fluid_synth_t *synth = (fluid_synth_t *)data;
fluid_synth_set_sample_rate(synth, (float) value);
return 0;
}
/**
@ -2409,11 +2399,11 @@ fluid_synth_set_sample_rate(fluid_synth_t* synth, float sample_rate)
/* Handler for synth.gain setting. */
static int
fluid_synth_update_gain(fluid_synth_t* synth, char* name, double value)
static void
fluid_synth_handle_gain(void *data, const char* name, double value)
{
fluid_synth_t *synth = (fluid_synth_t *)data;
fluid_synth_set_gain(synth, (float) value);
return 0;
}
/**
@ -2470,11 +2460,11 @@ fluid_synth_get_gain(fluid_synth_t* synth)
/*
* Handler for synth.polyphony setting.
*/
static int
fluid_synth_update_polyphony(fluid_synth_t* synth, char* name, int value)
static void
fluid_synth_handle_polyphony(void *data, const char* name, int value)
{
fluid_synth_t *synth = (fluid_synth_t *)data;
fluid_synth_set_polyphony(synth, value);
return 0;
}
/**
@ -3157,34 +3147,45 @@ fluid_synth_render_blocks(fluid_synth_t* synth, int blockcount)
}
static int fluid_synth_update_overflow (fluid_synth_t *synth, char *name,
fluid_real_t value)
/*
* Handler for synth.overflow.* settings.
*/
static void fluid_synth_handle_overflow (void *data, const char *name, double value)
{
double d;
fluid_synth_api_enter(synth);
fluid_settings_getnum(synth->settings, "synth.overflow.percussion", &d);
synth->overflow.percussion = d;
fluid_settings_getnum(synth->settings, "synth.overflow.released", &d);
synth->overflow.released = d;
fluid_settings_getnum(synth->settings, "synth.overflow.sustained", &d);
synth->overflow.sustained = d;
fluid_settings_getnum(synth->settings, "synth.overflow.volume", &d);
synth->overflow.volume = d;
fluid_settings_getnum(synth->settings, "synth.overflow.age", &d);
synth->overflow.age = d;
FLUID_API_RETURN(0);
}
fluid_synth_t *synth = (fluid_synth_t *)data;
fluid_return_if_fail(synth != NULL);
fluid_synth_api_enter(synth);
if (FLUID_STRCMP(name, "synth.overflow.percussion") == 0) {
synth->overflow.percussion = value;
}
else if (FLUID_STRCMP(name, "synth.overflow.released") == 0) {
synth->overflow.released = value;
}
else if (FLUID_STRCMP(name, "synth.overflow.sustained") == 0) {
synth->overflow.sustained = value;
}
else if (FLUID_STRCMP(name, "synth.overflow.volume") == 0) {
synth->overflow.volume = value;
}
else if (FLUID_STRCMP(name, "synth.overflow.age") == 0) {
synth->overflow.age = value;
}
else if (FLUID_STRCMP(name, "synth.overflow.important") == 0) {
synth->overflow.important = value;
}
fluid_synth_api_exit(synth);
}
/* Selects a voice for killing. */
static fluid_voice_t*
fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t* synth)
{
int i;
fluid_real_t best_prio = OVERFLOW_PRIO_CANNOT_KILL-1;
fluid_real_t this_voice_prio;
float best_prio = OVERFLOW_PRIO_CANNOT_KILL-1;
float this_voice_prio;
fluid_voice_t* voice;
int best_voice_index=-1;
unsigned int ticks = fluid_synth_get_ticks(synth);
@ -3311,8 +3312,7 @@ static void
fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t* synth,
fluid_voice_t* new_voice)
{
int excl_class = _GEN(new_voice,GEN_EXCLUSIVECLASS);
fluid_voice_t* existing_voice;
int excl_class = fluid_voice_gen_value(new_voice, GEN_EXCLUSIVECLASS);
int i;
/* Excl. class 0: No exclusive class */
@ -3320,14 +3320,15 @@ fluid_synth_kill_by_exclusive_class_LOCAL(fluid_synth_t* synth,
/* Kill all notes on the same channel with the same exclusive class */
for (i = 0; i < synth->polyphony; i++) {
existing_voice = synth->voice[i];
fluid_voice_t* existing_voice = synth->voice[i];
int existing_excl_class = fluid_voice_gen_value(existing_voice, GEN_EXCLUSIVECLASS);
/* If voice is playing, on the same channel, has same exclusive
* class and is not part of the same noteon event (voice group), then kill it */
if (fluid_voice_is_playing(existing_voice)
&& fluid_voice_get_channel(existing_voice) == fluid_voice_get_channel(new_voice)
&& (int)_GEN (existing_voice, GEN_EXCLUSIVECLASS) == excl_class
&& existing_excl_class == excl_class
&& fluid_voice_get_id (existing_voice) != fluid_voice_get_id(new_voice))
fluid_voice_kill_excl(existing_voice);
}
@ -3810,63 +3811,6 @@ fluid_synth_get_channel_preset(fluid_synth_t* synth, int chan)
return result;
}
/**
* Get information on the currently selected preset on a MIDI channel.
* @param synth FluidSynth instance
* @param chan MIDI channel number (0 to MIDI channel count - 1)
* @param info Caller supplied structure to fill with preset information
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
* @deprecated Provides redundant functionality that can be achieved with
* fluid_synth_get_channel_preset() or fluid_synth_get_program().
* @since 1.1.1
*/
int
fluid_synth_get_channel_info (fluid_synth_t *synth, int chan,
fluid_synth_channel_info_t *info)
{
fluid_channel_t *channel;
fluid_preset_t *preset;
const char *name;
if (info)
{
info->assigned = FALSE;
info->name[0] = '\0';
}
fluid_return_val_if_fail (info != NULL, FLUID_FAILED);
FLUID_API_ENTRY_CHAN(FLUID_FAILED);
channel = synth->channel[chan];
preset = channel->preset;
if (preset)
{
info->assigned = TRUE;
name = fluid_preset_get_name (preset);
if (name)
{
strncpy (info->name, name, FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE);
info->name[FLUID_SYNTH_CHANNEL_INFO_NAME_SIZE - 1] = '\0';
}
else info->name[0] = '\0';
info->sfont_id = preset->sfont->id;
info->bank = fluid_preset_get_banknum (preset);
info->program = fluid_preset_get_num (preset);
}
else
{
info->assigned = FALSE;
fluid_channel_get_sfont_bank_prog (channel, &info->sfont_id, &info->bank, &info->program);
info->name[0] = '\0';
}
fluid_synth_api_exit(synth);
return FLUID_OK;
}
/**
* Get list of currently playing voices.
* @param synth FluidSynth instance
@ -3910,9 +3854,12 @@ fluid_synth_set_reverb_on(fluid_synth_t* synth, int on)
{
fluid_return_if_fail (synth != NULL);
fluid_atomic_int_set (&synth->with_reverb, on != 0);
fluid_synth_api_enter(synth);
synth->with_reverb = (on != 0);
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_reverb_enabled,
on != 0, 0.0f);
fluid_synth_api_exit(synth);
}
/**
@ -4114,7 +4061,7 @@ fluid_synth_set_chorus_on(fluid_synth_t* synth, int on)
fluid_return_if_fail (synth != NULL);
fluid_synth_api_enter(synth);
fluid_atomic_int_set (&synth->with_chorus, on != 0);
synth->with_chorus = (on != 0);
fluid_synth_update_mixer(synth, fluid_rvoice_mixer_set_chorus_enabled,
on != 0, 0.0f);
fluid_synth_api_exit(synth);
@ -4557,30 +4504,6 @@ fluid_synth_update_voice_tuning_LOCAL (fluid_synth_t *synth, fluid_channel_t *ch
}
}
/**
* Set the tuning of the entire MIDI note scale.
* @param synth FluidSynth instance
* @param bank Tuning bank number (0-127), not related to MIDI instrument bank
* @param prog Tuning preset number (0-127), not related to MIDI instrument program
* @param name Label name for this tuning
* @param pitch Array of pitch values (length of 128, each value is number of
* cents, for example normally note 0 is 0.0, 1 is 100.0, 60 is 6000.0, etc).
* Pass NULL to create a equal tempered (normal) scale.
* @return FLUID_OK on success, FLUID_FAILED otherwise
*
* @note Tuning is not applied in realtime to existing notes of the replaced
* tuning (if any), use fluid_synth_activate_key_tuning() instead to specify
* this behavior.
*
* @deprecated Use fluid_synth_activate_key_tuning(synth, bank, prog, name, pitch, FALSE) instead.
*/
int
fluid_synth_create_key_tuning(fluid_synth_t* synth, int bank, int prog,
const char* name, const double* pitch)
{
return fluid_synth_activate_key_tuning (synth, bank, prog, name, pitch, FALSE);
}
/**
* Set the tuning of the entire MIDI note scale.
* @param synth FluidSynth instance
@ -4621,30 +4544,6 @@ fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog,
FLUID_API_RETURN(retval);
}
/**
* Apply an octave tuning to every octave in the MIDI note scale.
* @param synth FluidSynth instance
* @param bank Tuning bank number (0-127), not related to MIDI instrument bank
* @param prog Tuning preset number (0-127), not related to MIDI instrument program
* @param name Label name for this tuning
* @param pitch Array of pitch values (length of 12 for each note of an octave
* starting at note C, values are number of offset cents to add to the normal
* tuning amount)
* @return FLUID_OK on success, FLUID_FAILED otherwise
*
* @note Tuning is not applied in realtime to existing notes of the replaced
* tuning (if any), use fluid_synth_activate_octave_tuning() instead to specify
* this behavior.
*
* @deprecated Use fluid_synth_activate_octave_tuning(synth, bank, prog, name, pitch, FALSE) instead.
*/
int
fluid_synth_create_octave_tuning(fluid_synth_t* synth, int bank, int prog,
const char* name, const double* pitch)
{
return fluid_synth_activate_octave_tuning (synth, bank, prog, name, pitch, FALSE);
}
/**
* Activate an octave tuning on every octave in the MIDI note scale.
* @param synth FluidSynth instance
@ -4739,30 +4638,6 @@ fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog,
FLUID_API_RETURN(retval);
}
/**
* Select a tuning scale on a MIDI channel.
* @param synth FluidSynth instance
* @param chan MIDI channel number (0 to MIDI channel count - 1)
* @param bank Tuning bank number (0-127), not related to MIDI instrument bank
* @param prog Tuning preset number (0-127), not related to MIDI instrument program
* @return FLUID_OK on success, FLUID_FAILED otherwise
*
* @note This function does NOT activate tuning in realtime, use
* fluid_synth_activate_tuning() instead to specify whether tuning change
* should cause existing notes to update.
*
* @note Prior to version 1.1.0 it was an error to select a tuning that didn't
* already exist. Starting with 1.1.0, a default equal tempered scale will be
* created, if no tuning exists for the given bank and prog.
*
* @deprecated Use fluid_synth_activate_tuning(synth, chan, bank, prog, FALSE) instead.
*/
int
fluid_synth_select_tuning(fluid_synth_t* synth, int chan, int bank, int prog)
{
return fluid_synth_activate_tuning (synth, chan, bank, prog, FALSE);
}
/**
* Activate a tuning scale on a MIDI channel.
* @param synth FluidSynth instance
@ -4838,24 +4713,6 @@ fluid_synth_set_tuning_LOCAL (fluid_synth_t *synth, int chan,
return FLUID_OK;
}
/**
* Clear tuning scale on a MIDI channel (set it to the default equal tempered scale).
* @param synth FluidSynth instance
* @param chan MIDI channel number (0 to MIDI channel count - 1)
* @return FLUID_OK on success, FLUID_FAILED otherwise
*
* @note This function does NOT activate tuning change in realtime, use
* fluid_synth_deactivate_tuning() instead to specify whether tuning change
* should cause existing notes to update.
*
* @deprecated Use fluid_synth_deactivate_tuning(synth, chan, FALSE) instead.
*/
int
fluid_synth_reset_tuning(fluid_synth_t* synth, int chan)
{
return fluid_synth_deactivate_tuning (synth, chan, FALSE);
}
/**
* Clear tuning scale on a MIDI channel (use default equal tempered scale).
* @param synth FluidSynth instance
@ -4990,6 +4847,14 @@ fluid_synth_get_settings(fluid_synth_t* synth)
return synth->settings;
}
/**
* Same as calling \c fluid_synth_set_gen2(synth, chan, param, value, FALSE, FALSE)
* @return FLUID_OK on success, FLUID_FAILED otherwise
*/
int fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param, float value)
{
return fluid_synth_set_gen2(synth, chan, param, value, FALSE, FALSE);
}
/**
* Set a SoundFont generator (effect) value on a MIDI channel in real-time.
@ -5002,19 +4867,15 @@ fluid_synth_get_settings(fluid_synth_t* synth)
* TRUE to take the value as a 0.0-1.0 range and apply it to the valid
* generator effect range (scaled and shifted as necessary).
* @return FLUID_OK on success, FLUID_FAILED otherwise
* @since 2.0.0
*
* This function allows for setting all effect parameters in real time on a
* MIDI channel. Setting absolute to non-zero will cause the value to override
* MIDI channel. Setting absolute to non-zero will cause the value to override
* any generator values set in the instruments played on the MIDI channel.
* See SoundFont 2.01 spec, paragraph 8.1.3, page 48 for details on SoundFont
* generator parameters and valid ranges.
*
* @note The old behaviour of fluid_synth_set_gen() assumed \c absolute and \c normalized to
* be FALSE.
*/
int
fluid_synth_set_gen(fluid_synth_t* synth, int chan, int param,
fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param,
float value, int absolute, int normalized)
{
float v;
@ -5301,3 +5162,77 @@ fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
return synth->ladspa_fx;
}
/**
* Set the important channels for voice overflow priority calculation.
*
* @param synth FluidSynth instance
* @param channels comma-separated list of channel numbers
* @return FLUID_OK on success, otherwise FLUID_FAILED
*/
static int fluid_synth_set_important_channels(fluid_synth_t *synth, const char *channels)
{
int i;
int retval = FLUID_FAILED;
int *values = NULL;
int num_values;
fluid_overflow_prio_t *scores;
fluid_return_val_if_fail(synth != NULL, FLUID_FAILED);
scores = &synth->overflow;
if (scores->num_important_channels < synth->midi_channels)
{
scores->important_channels = FLUID_REALLOC(scores->important_channels,
sizeof(*scores->important_channels) * synth->midi_channels);
if (scores->important_channels == NULL)
{
FLUID_LOG(FLUID_ERR, "Out of memory");
goto exit;
}
scores->num_important_channels = synth->midi_channels;
}
FLUID_MEMSET(scores->important_channels, FALSE,
sizeof(*scores->important_channels) * scores->num_important_channels);
if (channels != NULL)
{
values = FLUID_ARRAY(int, synth->midi_channels);
if (values == NULL)
{
FLUID_LOG(FLUID_ERR, "Out of memory");
goto exit;
}
/* Every channel given in the comma-separated list of channel numbers
* is set to TRUE, i.e. flagging it as "important". Channel numbers are
* 1-based. */
num_values = fluid_settings_split_csv(channels, values, synth->midi_channels);
for (i = 0; i < num_values; i++)
{
if (values[i] > 0 && values[i] <= synth->midi_channels)
{
scores->important_channels[values[i] - 1] = TRUE;
}
}
}
retval = FLUID_OK;
exit:
FLUID_FREE(values);
return retval;
}
/*
* Handler for synth.overflow.important-channels setting.
*/
static void fluid_synth_handle_important_channels(void *data, const char *name,
const char *value)
{
fluid_synth_t *synth = (fluid_synth_t *)data;
fluid_synth_api_enter(synth);
fluid_synth_set_important_channels(synth, value);
fluid_synth_api_exit(synth);
}

View file

@ -28,17 +28,13 @@
* INCLUDES
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "fluidsynth_priv.h"
#include "fluid_sys.h"
#include "fluid_list.h"
#include "fluid_rev.h"
#include "fluid_voice.h"
#include "fluid_chorus.h"
#include "fluid_ladspa.h"
#include "fluid_midi_router.h"
#include "fluid_sys.h"
#include "fluid_rvoice_event.h"
/***************************************************************
@ -78,7 +74,7 @@ enum fluid_synth_status
#define SYNTH_REVERB_CHANNEL 0
#define SYNTH_CHORUS_CHANNEL 1
/**
/*
* Structure used for sfont_info field in #fluid_synth_t for each loaded
* SoundFont with the SoundFont instance and additional fields.
*/
@ -113,8 +109,8 @@ struct _fluid_synth_t
fluid_settings_t* settings; /**< the synthesizer settings */
int device_id; /**< Device ID used for SYSEX messages */
int polyphony; /**< Maximum polyphony */
fluid_atomic_int_t with_reverb; /**< Should the synth use the built-in reverb unit? */
fluid_atomic_int_t with_chorus; /**< Should the synth use the built-in chorus unit? */
int with_reverb; /**< Should the synth use the built-in reverb unit? */
int with_chorus; /**< Should the synth use the built-in chorus unit? */
int verbose; /**< Turn verbose mode on? */
double sample_rate; /**< The sample rate */
int midi_channels; /**< the number of MIDI channels (>= 16) */

View file

@ -368,7 +368,7 @@ fluid_voice_gen_get(fluid_voice_t* voice, int gen)
return voice->gen[gen].val;
}
fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num)
fluid_real_t fluid_voice_gen_value(const fluid_voice_t* voice, int num)
{
/* This is an extension to the SoundFont standard. More
* documentation is available at the fluid_synth_set_gen2()
@ -420,7 +420,9 @@ void fluid_voice_start(fluid_voice_t* voice)
fluid_voice_calculate_runtime_synthesis_parameters(voice);
#ifdef WITH_PROFILING
voice->ref = fluid_profile_ref();
#endif
voice->status = FLUID_VOICE_ON;
@ -428,6 +430,17 @@ void fluid_voice_start(fluid_voice_t* voice)
voice->channel->synth->active_voice_count++;
}
/**
* Calculate the amplitude of a voice.
*
* @param gain The gain value in the range [0.0 ; 1.0]
* @return An amplitude used by rvoice_mixer's buffers
*/
static fluid_real_t fluid_voice_calculate_gain_amplitude(const fluid_voice_t* voice, fluid_real_t gain)
{
return gain * voice->synth_gain / 32768.0f;
}
void
fluid_voice_calculate_gen_pitch(fluid_voice_t* voice)
{
@ -438,7 +451,7 @@ fluid_voice_calculate_gen_pitch(fluid_voice_t* voice)
* modulator paradigm. Now the nominal pitch of the key is set.
* Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a
* non-realtime parameter. So we don't allow modulation (as opposed
* to _GEN(voice, GEN_SCALETUNE) When the scale tuning is varied,
* to fluid_voice_gen_value(voice, GEN_SCALETUNE) When the scale tuning is varied,
* one key remains fixed. Here C3 (MIDI number 60) is used.
*/
if (fluid_channel_has_tuning(voice->channel)) {
@ -601,7 +614,7 @@ calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base,
* will cause (60-72)*100=-1200 timecents of time variation.
* The time is cut in half.
*/
timecents = (_GEN(voice, gen_base) + _GEN(voice, gen_key2base) * (60.0 - fluid_voice_get_actual_key(voice)));
timecents = (fluid_voice_gen_value(voice, gen_base) + fluid_voice_gen_value(voice, gen_key2base) * (60.0 - fluid_voice_get_actual_key(voice)));
/* Range checking */
if (is_decay){
@ -649,7 +662,7 @@ calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base,
*
* Note: The generator holds three values: The base value .val, an
* offset caused by modulators .mod, and an offset caused by the
* NRPN system. _GEN(voice, generator_enumerator) returns the sum
* NRPN system. fluid_voice_gen_value(voice, generator_enumerator) returns the sum
* of all three.
*/
/**
@ -663,22 +676,24 @@ calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base,
void
fluid_voice_update_param(fluid_voice_t* voice, int gen)
{
double q_dB;
fluid_real_t x;
fluid_real_t y;
unsigned int count, z;
// Alternate attenuation scale used by EMU10K1 cards when setting the attenuation at the preset or instrument level within the SoundFont bank.
static const float ALT_ATTENUATION_SCALE = 0.4f;
unsigned int count, z;
fluid_real_t q_dB;
fluid_real_t x = fluid_voice_gen_value(voice, gen);
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;
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0, voice->amp_left);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1, voice->amp_right);
voice->pan = x;
/* left amp */
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0, fluid_voice_calculate_gain_amplitude(voice, fluid_pan(x, 1)));
/* right amp */
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1, fluid_voice_calculate_gain_amplitude(voice, fluid_pan(x, 0)));
break;
case GEN_ATTENUATION:
@ -699,26 +714,24 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
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 = (fluid_voice_gen_value(voice, GEN_PITCH)
+ 100.0f * fluid_voice_gen_value(voice, GEN_COARSETUNE)
+ fluid_voice_gen_value(voice, GEN_FINETUNE));
UPDATE_RVOICE_R1(fluid_rvoice_set_pitch, voice->pitch);
break;
case GEN_REVERBSEND:
/* The generator unit is 'tenths of a percent'. */
voice->reverb_send = _GEN(voice, GEN_REVERBSEND) / 1000.0f;
voice->reverb_send = x / 1000.0f;
fluid_clip(voice->reverb_send, 0.0, 1.0);
voice->amp_reverb = voice->reverb_send * voice->synth_gain / 32768.0f;
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 2, voice->amp_reverb);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 2, fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send));
break;
case GEN_CHORUSSEND:
/* The generator unit is 'tenths of a percent'. */
voice->chorus_send = _GEN(voice, GEN_CHORUSSEND) / 1000.0f;
voice->chorus_send = x / 1000.0f;
fluid_clip(voice->chorus_send, 0.0, 1.0);
voice->amp_chorus = voice->chorus_send * voice->synth_gain / 32768.0f;
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 3, voice->amp_chorus);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 3, fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send));
break;
case GEN_OVERRIDEROOTKEY:
@ -754,14 +767,13 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
* modulation. The allowed range is tested in the 'fluid_ct2hz'
* function [PH,20021214]
*/
x = _GEN(voice, GEN_FILTERFC);
UPDATE_RVOICE_FILTER1(fluid_iir_filter_set_fres, x);
break;
case GEN_FILTERQ:
/* The generator contains 'centibels' (1/10 dB) => divide by 10 to
* obtain dB */
q_dB = _GEN(voice, GEN_FILTERQ) / 10.0f;
q_dB = x / 10.0f;
/* Range: SF2.01 section 8.1.3 # 8 (convert from cB to dB => /10) */
fluid_clip(q_dB, 0.0f, 96.0f);
@ -787,25 +799,21 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
break;
case GEN_MODLFOTOPITCH:
x = _GEN(voice, GEN_MODLFOTOPITCH);
fluid_clip(x, -12000.0, 12000.0);
UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_pitch, x);
break;
case GEN_MODLFOTOVOL:
x = _GEN(voice, GEN_MODLFOTOVOL);
fluid_clip(x, -960.0, 960.0);
UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_vol, x);
break;
case GEN_MODLFOTOFILTERFC:
x = _GEN(voice, GEN_MODLFOTOFILTERFC);
fluid_clip(x, -12000, 12000);
UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_fc, x);
break;
case GEN_MODLFODELAY:
x = _GEN(voice, GEN_MODLFODELAY);
fluid_clip(x, -12000.0f, 5000.0f);
z = (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x));
UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, modlfo, z);
@ -815,7 +823,6 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
/* - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples
* - the delay into a sample delay
*/
x = _GEN(voice, GEN_MODLFOFREQ);
fluid_clip(x, -16000.0f, 4500.0f);
x = (4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate);
UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, modlfo, x);
@ -827,21 +834,18 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
* - the frequency is converted into a delta value, per buffer of FLUID_BUFSIZE samples
* - the delay into a sample delay
*/
x = _GEN(voice, GEN_VIBLFOFREQ);
fluid_clip(x, -16000.0f, 4500.0f);
x = 4.0f * FLUID_BUFSIZE * fluid_act2hz(x) / voice->output_rate;
UPDATE_RVOICE_ENVLFO_R1(fluid_lfo_set_incr, viblfo, x);
break;
case GEN_VIBLFODELAY:
x = _GEN(voice,GEN_VIBLFODELAY);
fluid_clip(x, -12000.0f, 5000.0f);
z = (unsigned int) (voice->output_rate * fluid_tc2sec_delay(x));
UPDATE_RVOICE_ENVLFO_I1(fluid_lfo_set_delay, viblfo, z);
break;
case GEN_VIBLFOTOPITCH:
x = _GEN(voice, GEN_VIBLFOTOPITCH);
fluid_clip(x, -12000.0, 12000.0);
UPDATE_RVOICE_R1(fluid_rvoice_set_viblfo_to_pitch, x);
break;
@ -860,7 +864,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
* never be released on a noteoff event
*/
#if 0
x = _GEN(voice, GEN_KEYNUM);
x = fluid_voice_gen_value(voice, GEN_KEYNUM);
if (x >= 0){
voice->key = x;
}
@ -876,12 +880,12 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
* There is a flag, which should indicate, whether a generator is
* enabled or not. But here we rely on the default value of -1.
*/
/* 2017-09-02: do not change the voice's velocity here, user
/* 2017-09-02: do not change the voice's velocity here, use
* fluid_voice_get_actual_velocity() to get the value of this generator
* if active.
*/
#if 0
x = _GEN(voice, GEN_VELOCITY);
x = fluid_voice_gen_value(voice, GEN_VELOCITY);
if (x > 0) {
voice->vel = x;
}
@ -889,14 +893,11 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
break;
case GEN_MODENVTOPITCH:
x = _GEN(voice, GEN_MODENVTOPITCH);
fluid_clip(x, -12000.0, 12000.0);
UPDATE_RVOICE_R1(fluid_rvoice_set_modenv_to_pitch, x);
break;
case GEN_MODENVTOFILTERFC:
x = _GEN(voice,GEN_MODENVTOFILTERFC);
/* Range: SF2.01 section 8.1.3 # 1
* Motivation for range checking:
* Filter is reported to make funny noises now and then
@ -919,39 +920,47 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
*/
case GEN_STARTADDROFS: /* SF2.01 section 8.1.3 # 0 */
case GEN_STARTADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 4 */
if (voice->sample != NULL) {
z = (voice->sample->start
+ (int) _GEN(voice, GEN_STARTADDROFS)
+ 32768 * (int) _GEN(voice, GEN_STARTADDRCOARSEOFS));
UPDATE_RVOICE_I1(fluid_rvoice_set_start, z);
if (voice->sample != NULL)
{
fluid_real_t start_fine = fluid_voice_gen_value(voice, GEN_STARTADDROFS);
fluid_real_t start_coar = fluid_voice_gen_value(voice, GEN_STARTADDRCOARSEOFS);
z = voice->sample->start + (int)start_fine + 32768 * (int)start_coar;
UPDATE_RVOICE_I1(fluid_rvoice_set_start, z);
}
break;
case GEN_ENDADDROFS: /* SF2.01 section 8.1.3 # 1 */
case GEN_ENDADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 12 */
if (voice->sample != NULL) {
z = (voice->sample->end
+ (int) _GEN(voice, GEN_ENDADDROFS)
+ 32768 * (int) _GEN(voice, GEN_ENDADDRCOARSEOFS));
UPDATE_RVOICE_I1(fluid_rvoice_set_end, z);
if (voice->sample != NULL)
{
fluid_real_t end_fine = fluid_voice_gen_value(voice, GEN_ENDADDROFS);
fluid_real_t end_coar = fluid_voice_gen_value(voice, GEN_ENDADDRCOARSEOFS);
z = voice->sample->end + (int)end_fine + 32768 * (int)end_coar;
UPDATE_RVOICE_I1(fluid_rvoice_set_end, z);
}
break;
case GEN_STARTLOOPADDROFS: /* SF2.01 section 8.1.3 # 2 */
case GEN_STARTLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 45 */
if (voice->sample != NULL) {
z = (voice->sample->loopstart
+ (int) _GEN(voice, GEN_STARTLOOPADDROFS)
+ 32768 * (int) _GEN(voice, GEN_STARTLOOPADDRCOARSEOFS));
UPDATE_RVOICE_I1(fluid_rvoice_set_loopstart, z);
if (voice->sample != NULL)
{
fluid_real_t lstart_fine = fluid_voice_gen_value(voice, GEN_STARTLOOPADDROFS);
fluid_real_t lstart_coar = fluid_voice_gen_value(voice, GEN_STARTLOOPADDRCOARSEOFS);
z = voice->sample->loopstart + (int)lstart_fine + 32768 * (int)lstart_coar;
UPDATE_RVOICE_I1(fluid_rvoice_set_loopstart, z);
}
break;
case GEN_ENDLOOPADDROFS: /* SF2.01 section 8.1.3 # 3 */
case GEN_ENDLOOPADDRCOARSEOFS: /* SF2.01 section 8.1.3 # 50 */
if (voice->sample != NULL) {
z = (voice->sample->loopend
+ (int) _GEN(voice, GEN_ENDLOOPADDROFS)
+ 32768 * (int) _GEN(voice, GEN_ENDLOOPADDRCOARSEOFS));
UPDATE_RVOICE_I1(fluid_rvoice_set_loopend, z);
if (voice->sample != NULL)
{
fluid_real_t lend_fine = fluid_voice_gen_value(voice, GEN_ENDLOOPADDROFS);
fluid_real_t lend_coar = fluid_voice_gen_value(voice, GEN_ENDLOOPADDRCOARSEOFS);
z = voice->sample->loopend + (int)lend_fine + 32768 * (int)lend_coar;
UPDATE_RVOICE_I1(fluid_rvoice_set_loopend, z);
}
break;
@ -967,7 +976,6 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
* - attack, decay and release are converted to their increment per sample
*/
case GEN_VOLENVDELAY: /* SF2.01 section 8.1.3 # 33 */
x = _GEN(voice, GEN_VOLENVDELAY);
fluid_clip(x, -12000.0f, 5000.0f);
count = NUM_BUFFERS_DELAY(x);
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVDELAY,
@ -975,7 +983,6 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
break;
case GEN_VOLENVATTACK: /* SF2.01 section 8.1.3 # 34 */
x = _GEN(voice, GEN_VOLENVATTACK);
fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_BUFFERS_ATTACK(x);
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVATTACK,
@ -992,15 +999,14 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
case GEN_VOLENVDECAY: /* SF2.01 section 8.1.3 # 36 */
case GEN_VOLENVSUSTAIN: /* SF2.01 section 8.1.3 # 37 */
case GEN_KEYTOVOLENVDECAY: /* SF2.01 section 8.1.3 # 40 */
y = 1.0f - 0.001f * _GEN(voice, GEN_VOLENVSUSTAIN);
fluid_clip(y, 0.0f, 1.0f);
x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_VOLENVSUSTAIN);
fluid_clip(x , 0.0f, 1.0f);
count = calculate_hold_decay_buffers(voice, GEN_VOLENVDECAY, GEN_KEYTOVOLENVDECAY, 1); /* 1 for decay */
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVDECAY,
count, 1.0f, count ? -1.0f / count : 0.0f, y, 2.0f);
count, 1.0f, count ? -1.0f / count : 0.0f, x, 2.0f);
break;
case GEN_VOLENVRELEASE: /* SF2.01 section 8.1.3 # 38 */
x = _GEN(voice, GEN_VOLENVRELEASE);
fluid_clip(x, FLUID_MIN_VOLENVRELEASE, 8000.0f);
count = 1 + NUM_BUFFERS_RELEASE(x);
fluid_voice_update_volenv(voice, FLUID_VOICE_ENVRELEASE,
@ -1009,14 +1015,12 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
/* Modulation envelope */
case GEN_MODENVDELAY: /* SF2.01 section 8.1.3 # 25 */
x = _GEN(voice, GEN_MODENVDELAY);
fluid_clip(x, -12000.0f, 5000.0f);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVDELAY,
NUM_BUFFERS_DELAY(x), 0.0f, 0.0f, -1.0f, 1.0f);
break;
case GEN_MODENVATTACK: /* SF2.01 section 8.1.3 # 26 */
x = _GEN(voice, GEN_MODENVATTACK);
fluid_clip(x, -12000.0f, 8000.0f);
count = 1 + NUM_BUFFERS_ATTACK(x);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVATTACK,
@ -1034,14 +1038,13 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
case GEN_MODENVSUSTAIN: /* SF 2.01 section 8.1.3 # 29 */
case GEN_KEYTOMODENVDECAY: /* SF 2.01 section 8.1.3 # 32 */
count = calculate_hold_decay_buffers(voice, GEN_MODENVDECAY, GEN_KEYTOMODENVDECAY, 1); /* 1 for decay */
y = 1.0f - 0.001f * _GEN(voice, GEN_MODENVSUSTAIN);
fluid_clip(y, 0.0f, 1.0f);
x = 1.0f - 0.001f * fluid_voice_gen_value(voice, GEN_MODENVSUSTAIN);
fluid_clip(x, 0.0f, 1.0f);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVDECAY,
count, 1.0f, count ? -1.0f / count : 0.0f, y, 2.0f);
count, 1.0f, count ? -1.0f / count : 0.0f, x, 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);
count = 1 + NUM_BUFFERS_RELEASE(x);
fluid_voice_update_modenv(voice, FLUID_VOICE_ENVRELEASE,
@ -1452,7 +1455,7 @@ int fluid_voice_get_channel(const fluid_voice_t* voice)
*/
int fluid_voice_get_actual_key(const fluid_voice_t* voice)
{
fluid_real_t x = _GEN(voice, GEN_KEYNUM);
fluid_real_t x = fluid_voice_gen_value(voice, GEN_KEYNUM);
if (x >= 0)
{
return (int)x;
@ -1485,7 +1488,7 @@ int fluid_voice_get_key(const fluid_voice_t* voice)
*/
int fluid_voice_get_actual_velocity(const fluid_voice_t* voice)
{
fluid_real_t x = _GEN(voice, GEN_VELOCITY);
fluid_real_t x = fluid_voice_gen_value(voice, GEN_VELOCITY);
if (x > 0)
{
return (int)x;
@ -1589,22 +1592,24 @@ int fluid_voice_set_param(fluid_voice_t* voice, int gen, fluid_real_t nrpn_value
int fluid_voice_set_gain(fluid_voice_t* voice, fluid_real_t gain)
{
fluid_real_t left, right, reverb, chorus;
/* avoid division by zero*/
if (gain < 0.0000001){
gain = 0.0000001;
}
voice->synth_gain = 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;
left = fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 1));
right = fluid_voice_calculate_gain_amplitude(voice, fluid_pan(voice->pan, 0));
reverb = fluid_voice_calculate_gain_amplitude(voice, voice->reverb_send);
chorus = fluid_voice_calculate_gain_amplitude(voice, voice->chorus_send);
UPDATE_RVOICE_R1(fluid_rvoice_set_synth_gain, gain);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0, voice->amp_left);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1, voice->amp_right);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 2, voice->amp_reverb);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 3, voice->amp_chorus);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0, left);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 1, right);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 2, reverb);
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 3, chorus);
return FLUID_OK;
}
@ -1681,12 +1686,13 @@ fluid_voice_optimize_sample(fluid_sample_t* s)
return FLUID_OK;
}
fluid_real_t
float
fluid_voice_get_overflow_prio(fluid_voice_t* voice,
fluid_overflow_prio_t* score,
unsigned int cur_time)
{
fluid_real_t this_voice_prio = 0;
float this_voice_prio = 0;
int channel;
/* Are we already overflowing? */
if (!voice->can_access_overflow_rvoice) {
@ -1734,6 +1740,13 @@ fluid_voice_get_overflow_prio(fluid_voice_t* voice,
}
this_voice_prio += score->volume / a;
}
/* Check if this voice is on an important channel. If so, then add the
* score for important channels */
channel = fluid_voice_get_channel(voice);
if (channel < score->num_important_channels && score->important_channels[channel]) {
this_voice_prio += score->important;
}
return this_voice_prio;
}

View file

@ -33,15 +33,19 @@
#define NO_CHANNEL 0xff
typedef struct _fluid_overflow_prio_t fluid_overflow_prio_t;
struct _fluid_overflow_prio_t
{
fluid_real_t percussion; /**< Is this voice on the drum channel? Then add this score */
fluid_real_t released; /**< Is this voice in release stage? Then add this score (usually negative) */
fluid_real_t sustained; /**< Is this voice sustained? Then add this score (usually negative) */
fluid_real_t volume; /**< Multiply current (or future) volume (a value between 0 and 1) */
fluid_real_t age; /**< This score will be divided by the number of seconds the voice has lasted */
float percussion; /**< Is this voice on the drum channel? Then add this score */
float released; /**< Is this voice in release stage? Then add this score (usually negative) */
float sustained; /**< Is this voice sustained? Then add this score (usually negative) */
float volume; /**< Multiply current (or future) volume (a value between 0 and 1) */
float age; /**< This score will be divided by the number of seconds the voice has lasted */
float important; /**< This score will be added to all important channels */
char *important_channels; /**< "important" flags indexed by MIDI channel number */
int num_important_channels; /**< Number of elements in the important_channels array */
};
enum fluid_voice_status
@ -87,16 +91,12 @@ struct _fluid_voice_t
/* pan */
fluid_real_t pan;
fluid_real_t amp_left;
fluid_real_t amp_right;
/* reverb */
fluid_real_t reverb_send;
fluid_real_t amp_reverb;
/* chorus */
fluid_real_t chorus_send;
fluid_real_t amp_chorus;
/* rvoice control */
fluid_rvoice_t* rvoice;
@ -105,8 +105,10 @@ struct _fluid_voice_t
char can_access_overflow_rvoice; /* False if overflow_rvoice is being rendered in separate thread */
char has_noteoff; /* Flag set when noteoff has been sent */
#ifdef WITH_PROFILING
/* for debugging */
double ref;
#endif
};
@ -148,7 +150,7 @@ void fluid_voice_stop(fluid_voice_t* voice);
void fluid_voice_overflow_rvoice_finished(fluid_voice_t* voice);
int fluid_voice_kill_excl(fluid_voice_t* voice);
fluid_real_t fluid_voice_get_overflow_prio(fluid_voice_t* voice,
float fluid_voice_get_overflow_prio(fluid_voice_t* voice,
fluid_overflow_prio_t* score,
unsigned int cur_time);
@ -179,15 +181,9 @@ fluid_voice_unlock_rvoice(fluid_voice_t* voice)
#define _SAMPLEMODE(voice) ((int)(voice)->gen[GEN_SAMPLEMODE].val)
/* FIXME - This doesn't seem to be used anywhere - JG */
fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num);
fluid_real_t fluid_voice_gen_value(const fluid_voice_t* voice, int num);
#define fluid_voice_get_loudness(voice) (fluid_adsr_env_get_max_val(&voice->volenv))
#define _GEN(_voice, _n) \
((fluid_real_t)(_voice)->gen[_n].val \
+ (fluid_real_t)(_voice)->gen[_n].mod \
+ (fluid_real_t)(_voice)->gen[_n].nrpn)
#endif /* _FLUID_VOICE_H */

View file

@ -23,7 +23,7 @@
#include "fluid_sys.h"
/**
/*
* Lockless event queue instance.
*/
struct _fluid_ringbuffer_t
@ -46,7 +46,7 @@ void delete_fluid_ringbuffer (fluid_ringbuffer_t *queue);
/**
* Get pointer to next input array element in queue.
* @param queue Lockless queue instance
* @param count Normally zero, or more if you need to push several items at once
* @param offset Normally zero, or more if you need to push several items at once
* @return Pointer to array element in queue to store data to or NULL if queue is full
*
* This function along with fluid_ringbuffer_next_inptr() form a queue "push"

View file

@ -18,7 +18,6 @@
* 02110-1301, USA
*/
#include "fluidsynth_priv.h"
#include "fluid_sys.h"
#include "fluid_hash.h"
#include "fluid_synth.h"
@ -87,7 +86,7 @@ typedef struct {
} fluid_setting_node_t;
static fluid_setting_node_t*
new_fluid_str_setting(const char* value, const char* def, int hints, fluid_str_update_t fun, void* data)
new_fluid_str_setting(const char* value, const char* def, int hints)
{
fluid_setting_node_t* node;
fluid_str_setting_t* str;
@ -101,14 +100,14 @@ new_fluid_str_setting(const char* value, const char* def, int hints, fluid_str_u
}
node->type = FLUID_STR_TYPE;
str = &node->str;
str->value = value? FLUID_STRDUP(value) : NULL;
str->def = def? FLUID_STRDUP(def) : NULL;
str->hints = hints;
str->options = NULL;
str->update = fun;
str->data = data;
str->update = NULL;
str->data = NULL;
return node;
}
@ -138,8 +137,7 @@ delete_fluid_str_setting(fluid_setting_node_t* node)
static fluid_setting_node_t*
new_fluid_num_setting(double min, double max, double def,
int hints, fluid_num_update_t fun, void* data)
new_fluid_num_setting(double min, double max, double def, int hints)
{
fluid_setting_node_t* node;
fluid_num_setting_t* num;
@ -153,15 +151,15 @@ new_fluid_num_setting(double min, double max, double def,
}
node->type = FLUID_NUM_TYPE;
num = &node->num;
num->value = def;
num->def = def;
num->min = min;
num->max = max;
num->hints = hints;
num->update = fun;
num->data = data;
num->update = NULL;
num->data = NULL;
return node;
}
@ -176,8 +174,7 @@ delete_fluid_num_setting(fluid_setting_node_t* node)
}
static fluid_setting_node_t*
new_fluid_int_setting(int min, int max, int def,
int hints, fluid_int_update_t fun, void* data)
new_fluid_int_setting(int min, int max, int def, int hints)
{
fluid_setting_node_t* node;
fluid_int_setting_t* i;
@ -191,15 +188,15 @@ new_fluid_int_setting(int min, int max, int def,
}
node->type = FLUID_INT_TYPE;
i = &node->i;
i->value = def;
i->def = def;
i->min = min;
i->max = max;
i->hints = hints;
i->update = fun;
i->data = data;
i->update = NULL;
i->data = NULL;
return node;
}
@ -471,13 +468,10 @@ fluid_settings_set(fluid_settings_t* settings, const char *name, fluid_setting_n
* @param name the setting's name
* @param def the default value for the setting
* @param hints the hints for the setting
* @param fun an update function for the setting
* @param data user supplied data
* @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise
*/
int
fluid_settings_register_str(fluid_settings_t* settings, const char* name, const char* def, int hints,
fluid_str_update_t fun, void* data)
fluid_settings_register_str(fluid_settings_t* settings, const char* name, const char* def, int hints)
{
fluid_setting_node_t *node;
int retval = FLUID_FAILED;
@ -489,15 +483,13 @@ fluid_settings_register_str(fluid_settings_t* settings, const char* name, const
fluid_rec_mutex_lock (settings->mutex);
if (fluid_settings_get(settings, name, &node) != FLUID_OK) {
node = new_fluid_str_setting(def, def, hints, fun, data);
node = new_fluid_str_setting(def, def, hints);
retval = fluid_settings_set(settings, name, node);
if (retval != FLUID_OK) delete_fluid_str_setting (node);
} else {
/* if variable already exists, don't change its value. */
if (node->type == FLUID_STR_TYPE) {
fluid_str_setting_t* setting = &node->str;
setting->update = fun;
setting->data = data;
setting->def = def? FLUID_STRDUP(def) : NULL;
setting->hints = hints;
retval = FLUID_OK;
@ -520,14 +512,11 @@ fluid_settings_register_str(fluid_settings_t* settings, const char* name, const
* @param min the smallest allowed value for the setting
* @param max the largest allowed value for the setting
* @param hints the hints for the setting
* @param fun an update function for the setting
* @param data user supplied data
* @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise
*/
int
fluid_settings_register_num(fluid_settings_t* settings, const char* name, double def,
double min, double max, int hints,
fluid_num_update_t fun, void* data)
double min, double max, int hints)
{
fluid_setting_node_t *node;
int retval = FLUID_FAILED;
@ -543,15 +532,13 @@ fluid_settings_register_num(fluid_settings_t* settings, const char* name, double
if (fluid_settings_get(settings, name, &node) != FLUID_OK) {
/* insert a new setting */
node = new_fluid_num_setting(min, max, def, hints, fun, data);
node = new_fluid_num_setting(min, max, def, hints);
retval = fluid_settings_set(settings, name, node);
if (retval != FLUID_OK) delete_fluid_num_setting (node);
} else {
if (node->type == FLUID_NUM_TYPE) {
/* update the existing setting but don't change its value */
fluid_num_setting_t* setting = &node->num;
setting->update = fun;
setting->data = data;
setting->min = min;
setting->max = max;
setting->def = def;
@ -577,14 +564,11 @@ fluid_settings_register_num(fluid_settings_t* settings, const char* name, double
* @param min the smallest allowed value for the setting
* @param max the largest allowed value for the setting
* @param hints the hints for the setting
* @param fun an update function for the setting
* @param data user supplied data
* @return #FLUID_OK if the value has been register correctly, #FLUID_FAILED otherwise
*/
int
fluid_settings_register_int(fluid_settings_t* settings, const char* name, int def,
int min, int max, int hints,
fluid_int_update_t fun, void* data)
int min, int max, int hints)
{
fluid_setting_node_t *node;
int retval = FLUID_FAILED;
@ -600,15 +584,13 @@ fluid_settings_register_int(fluid_settings_t* settings, const char* name, int de
if (fluid_settings_get(settings, name, &node) != FLUID_OK) {
/* insert a new setting */
node = new_fluid_int_setting(min, max, def, hints, fun, data);
node = new_fluid_int_setting(min, max, def, hints);
retval = fluid_settings_set(settings, name, node);
if (retval != FLUID_OK) delete_fluid_int_setting (node);
} else {
if (node->type == FLUID_INT_TYPE) {
/* update the existing setting but don't change its value */
fluid_int_setting_t* setting = &node->i;
setting->update = fun;
setting->data = data;
setting->min = min;
setting->max = max;
setting->def = def;
@ -625,6 +607,114 @@ fluid_settings_register_int(fluid_settings_t* settings, const char* name, int de
return retval;
}
/**
* Registers a callback for the specified string setting.
*
* @param settings a settings object
* @param name the setting's name
* @param callback an update function for the setting
* @param data user supplied data passed to the update function
* @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise
*/
int fluid_settings_callback_str(fluid_settings_t* settings, const char* name,
fluid_str_update_t callback, void* data)
{
fluid_setting_node_t *node;
fluid_str_setting_t *setting;
fluid_return_val_if_fail (settings != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED);
fluid_rec_mutex_lock (settings->mutex);
if ((fluid_settings_get(settings, name, &node) != FLUID_OK)
|| node->type != FLUID_STR_TYPE)
{
fluid_rec_mutex_unlock(settings->mutex);
return FLUID_FAILED;
}
setting = &node->str;
setting->update = callback;
setting->data = data;
fluid_rec_mutex_unlock(settings->mutex);
return FLUID_OK;
}
/**
* Registers a callback for the specified numeric setting.
*
* @param settings a settings object
* @param name the setting's name
* @param callback an update function for the setting
* @param data user supplied data passed to the update function
* @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise
*/
int fluid_settings_callback_num(fluid_settings_t* settings, const char* name,
fluid_num_update_t callback, void* data)
{
fluid_setting_node_t *node;
fluid_num_setting_t *setting;
fluid_return_val_if_fail (settings != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED);
fluid_rec_mutex_lock (settings->mutex);
if ((fluid_settings_get(settings, name, &node) != FLUID_OK)
|| node->type != FLUID_NUM_TYPE)
{
fluid_rec_mutex_unlock(settings->mutex);
return FLUID_FAILED;
}
setting = &node->num;
setting->update = callback;
setting->data = data;
fluid_rec_mutex_unlock(settings->mutex);
return FLUID_OK;
}
/**
* Registers a callback for the specified int setting.
*
* @param settings a settings object
* @param name the setting's name
* @param callback an update function for the setting
* @param data user supplied data passed to the update function
* @return #FLUID_OK if the callback has been set, #FLUID_FAILED otherwise
*/
int fluid_settings_callback_int(fluid_settings_t* settings, const char* name,
fluid_int_update_t callback, void* data)
{
fluid_setting_node_t *node;
fluid_int_setting_t *setting;
fluid_return_val_if_fail (settings != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED);
fluid_rec_mutex_lock (settings->mutex);
if ((fluid_settings_get(settings, name, &node) != FLUID_OK)
|| node->type != FLUID_INT_TYPE)
{
fluid_rec_mutex_unlock(settings->mutex);
return FLUID_FAILED;
}
setting = &node->i;
setting->update = callback;
setting->data = data;
fluid_rec_mutex_unlock(settings->mutex);
return FLUID_OK;
}
/**
* Get the type of the setting with the given name
*
@ -741,55 +831,54 @@ int
fluid_settings_setstr(fluid_settings_t* settings, const char *name, const char *str)
{
fluid_setting_node_t *node;
int retval = FLUID_FAILED;
fluid_str_setting_t *setting;
char *new_value = NULL;
fluid_str_update_t callback = NULL;
void *data = NULL;
fluid_return_val_if_fail (settings != NULL, retval);
fluid_return_val_if_fail (name != NULL, retval);
fluid_return_val_if_fail (name[0] != '\0', retval);
fluid_return_val_if_fail (settings != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED);
fluid_rec_mutex_lock (settings->mutex);
if (fluid_settings_get (settings, name, &node) == FLUID_OK) {
if (node->type == FLUID_STR_TYPE) {
fluid_str_setting_t *setting = &node->str;
if (setting->value) FLUID_FREE (setting->value);
setting->value = str ? FLUID_STRDUP (str) : NULL;
/* Call under lock to keep update() synchronized with the current value */
if (setting->update) (*setting->update)(setting->data, name, str);
retval = FLUID_OK;
}
else if (node->type == FLUID_INT_TYPE) /* Handle yes/no for boolean values for backwards compatibility */
{
fluid_int_setting_t *setting = &node->i;
if (setting->hints & FLUID_HINT_TOGGLED)
{
if (FLUID_STRCMP (str, "yes") == 0)
{
setting->value = TRUE;
if (setting->update) (*setting->update)(setting->data, name, TRUE);
retval = FLUID_OK;
}
else if (FLUID_STRCMP (str, "no") == 0)
{
setting->value = FALSE;
if (setting->update) (*setting->update)(setting->data, name, FALSE);
retval = FLUID_OK;
}
}
}
} else {
/* insert a new setting */
node = new_fluid_str_setting(str, NULL, 0, NULL, NULL);
retval = fluid_settings_set(settings, name, node);
if (retval != FLUID_OK) delete_fluid_str_setting (node);
if ((fluid_settings_get (settings, name, &node) != FLUID_OK)
|| (node->type != FLUID_STR_TYPE)) {
goto error_recovery;
}
setting = &node->str;
if (setting->value) {
FLUID_FREE (setting->value);
}
if (str) {
new_value = FLUID_STRDUP (str);
if (new_value == NULL) {
FLUID_LOG (FLUID_ERR, "Out of memory");
goto error_recovery;
}
}
setting->value = new_value;
callback = setting->update;
data = setting->data;
/* Release the mutex before calling the update callback, to avoid
* possible deadlocks with FluidSynths API lock */
fluid_rec_mutex_unlock (settings->mutex);
return retval;
if (callback) {
(*callback)(data, name, new_value);
}
return FLUID_OK;
error_recovery:
fluid_rec_mutex_unlock (settings->mutex);
return FLUID_FAILED;
}
/**
@ -830,7 +919,6 @@ fluid_settings_copystr(fluid_settings_t* settings, const char *name,
if (setting->value)
{
FLUID_STRNCPY (str, setting->value, len);
str[len - 1] = 0; /* Force terminate, in case of truncation */
}
retval = FLUID_OK;
@ -842,7 +930,6 @@ fluid_settings_copystr(fluid_settings_t* settings, const char *name,
if (setting->hints & FLUID_HINT_TOGGLED)
{
FLUID_STRNCPY (str, setting->value ? "yes" : "no", len);
str[len - 1] = 0; /* Force terminate, in case of truncation */
retval = FLUID_OK;
}
@ -1087,41 +1174,45 @@ int
fluid_settings_setnum(fluid_settings_t* settings, const char *name, double val)
{
fluid_setting_node_t *node;
int retval = FLUID_FAILED;
fluid_num_setting_t *setting;
fluid_num_update_t callback = NULL;
void *data = NULL;
fluid_return_val_if_fail (settings != NULL, retval);
fluid_return_val_if_fail (name != NULL, retval);
fluid_return_val_if_fail (name[0] != '\0', retval);
fluid_return_val_if_fail (settings != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED);
fluid_rec_mutex_lock (settings->mutex);
if (fluid_settings_get(settings, name, &node) == FLUID_OK) {
if (node->type == FLUID_NUM_TYPE) {
fluid_num_setting_t* setting = &node->num;
if (val < setting->min || val > setting->max)
{
FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name);
return retval;
}
setting->value = val;
/* Call under lock to keep update() synchronized with the current value */
if (setting->update) (*setting->update)(setting->data, name, val);
retval = FLUID_OK;
}
} else {
/* insert a new setting */
node = new_fluid_num_setting(-1e10, 1e10, 0.0f, 0, NULL, NULL);
node->num.value = val;
retval = fluid_settings_set(settings, name, node);
if (retval != FLUID_OK) delete_fluid_num_setting (node);
if ((fluid_settings_get (settings, name, &node) != FLUID_OK)
|| (node->type != FLUID_NUM_TYPE)) {
goto error_recovery;
}
setting = &node->num;
if (val < setting->min || val > setting->max) {
FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name);
goto error_recovery;
}
setting->value = val;
callback = setting->update;
data = setting->data;
/* Release the mutex before calling the update callback, to avoid
* possible deadlocks with FluidSynths API lock */
fluid_rec_mutex_unlock (settings->mutex);
return retval;
if (callback) {
(*callback)(data, name, val);
}
return FLUID_OK;
error_recovery:
fluid_rec_mutex_unlock (settings->mutex);
return FLUID_FAILED;
}
/**
@ -1157,6 +1248,27 @@ fluid_settings_getnum(fluid_settings_t* settings, const char *name, double* val)
return retval;
}
/**
* float-typed wrapper for fluid_settings_getnum
*
* @param settings a settings object
* @param name a setting's name
* @param val variable pointer to receive the setting's float value
* @return #FLUID_OK if the value exists, #FLUID_FAILED otherwise
*/
int fluid_settings_getnum_float(fluid_settings_t *settings, const char *name, float *val)
{
double tmp;
if (fluid_settings_getnum(settings, name, &tmp) == FLUID_OK)
{
*val = tmp;
return FLUID_OK;
}
return FLUID_FAILED;
}
/**
* Get the range of values of a numeric setting
*
@ -1239,41 +1351,45 @@ int
fluid_settings_setint(fluid_settings_t* settings, const char *name, int val)
{
fluid_setting_node_t *node;
int retval = FLUID_FAILED;
fluid_int_setting_t *setting;
fluid_int_update_t callback = NULL;
void *data = NULL;
fluid_return_val_if_fail (settings != NULL, retval);
fluid_return_val_if_fail (name != NULL, retval);
fluid_return_val_if_fail (name[0] != '\0', retval);
fluid_return_val_if_fail (settings != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
fluid_return_val_if_fail (name[0] != '\0', FLUID_FAILED);
fluid_rec_mutex_lock (settings->mutex);
if (fluid_settings_get(settings, name, &node) == FLUID_OK) {
if (node->type == FLUID_INT_TYPE) {
fluid_int_setting_t* setting = &node->i;
if (val < setting->min || val > setting->max)
{
FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name);
return retval;
}
setting->value = val;
/* Call under lock to keep update() synchronized with the current value */
if (setting->update) (*setting->update)(setting->data, name, val);
retval = FLUID_OK;
}
} else {
/* insert a new setting */
node = new_fluid_int_setting(INT_MIN, INT_MAX, 0, 0, NULL, NULL);
node->i.value = val;
retval = fluid_settings_set(settings, name, node);
if (retval != FLUID_OK) delete_fluid_int_setting (node);
if ((fluid_settings_get (settings, name, &node) != FLUID_OK)
|| (node->type != FLUID_INT_TYPE)) {
goto error_recovery;
}
setting = &node->i;
if (val < setting->min || val > setting->max) {
FLUID_LOG(FLUID_DBG, "requested set value for %s out of range", name);
goto error_recovery;
}
setting->value = val;
callback = setting->update;
data = setting->data;
/* Release the mutex before calling the update callback, to avoid
* possible deadlocks with FluidSynths API lock */
fluid_rec_mutex_unlock (settings->mutex);
return retval;
if (callback) {
(*callback)(data, name, val);
}
return FLUID_OK;
error_recovery:
fluid_rec_mutex_unlock (settings->mutex);
return FLUID_FAILED;
}
/**
@ -1621,3 +1737,36 @@ fluid_settings_foreach (fluid_settings_t* settings, void* data,
delete_fluid_list (bag.names); /* -- Free names list */
}
/**
* Split a comma-separated list of integers and fill the passed
* in buffer with the parsed values.
*
* @param str the comma-separated string to split
* @param buf user-supplied buffer to hold the parsed numbers
* @param buf_len length of user-supplied buffer
* @return number of parsed values or -1 on failure
*/
int fluid_settings_split_csv(const char *str, int *buf, int buf_len)
{
char *s;
char *tok;
char *tokstr;
int n = 0;
s = tokstr = FLUID_STRDUP(str);
if (s == NULL)
{
FLUID_LOG(FLUID_ERR, "Out of memory");
return -1;
}
while ((tok = fluid_strtok(&tokstr, ",")) && n < buf_len)
{
buf[n++] = atoi(tok);
}
FLUID_FREE(s);
return n;
}

View file

@ -26,22 +26,30 @@ int fluid_settings_add_option(fluid_settings_t* settings, const char* name, cons
int fluid_settings_remove_option(fluid_settings_t* settings, const char* name, const char* s);
typedef int (*fluid_str_update_t)(void* data, const char* name, const char* value);
typedef void (*fluid_str_update_t)(void* data, const char* name, const char* value);
int fluid_settings_register_str(fluid_settings_t* settings, const char* name, const char* def, int hints,
int fluid_settings_register_str(fluid_settings_t* settings, const char* name, const char* def, int hints);
int fluid_settings_callback_str(fluid_settings_t* settings, const char* name,
fluid_str_update_t fun, void* data);
typedef int (*fluid_num_update_t)(void* data, const char* name, double value);
typedef void (*fluid_num_update_t)(void* data, const char* name, double value);
int fluid_settings_register_num(fluid_settings_t* settings, const char* name, double def,
double min, double max, int hints,
double min, double max, int hints);
int fluid_settings_callback_num(fluid_settings_t* settings, const char* name,
fluid_num_update_t fun, void* data);
/* Type specific wrapper for fluid_settings_getnum */
int fluid_settings_getnum_float(fluid_settings_t *settings, const char *name, float *val);
typedef int (*fluid_int_update_t)(void* data, const char* name, int value);
typedef void (*fluid_int_update_t)(void* data, const char* name, int value);
int fluid_settings_register_int(fluid_settings_t* settings, const char* name, int def,
int min, int max, int hints,
int min, int max, int hints);
int fluid_settings_callback_int(fluid_settings_t* settings, const char* name,
fluid_int_update_t fun, void* data);
int fluid_settings_split_csv(const char *str, int *buf, int buf_len);
#endif /* _FLUID_SETTINGS_H */

View file

@ -129,7 +129,6 @@ typedef guint64 uint64_t;
#if defined(WIN32) && HAVE_WINDOWS_H
#include <winsock2.h>
#include <ws2tcpip.h> /* Provides also socklen_t */
#include <windows.h>
/* WIN32 special defines */
#define DSOUND_SUPPORT 1
@ -215,6 +214,7 @@ typedef struct _fluid_sample_timer_t fluid_sample_timer_t;
#define FLUID_MAX_EVENT_QUEUES 16 /**< Maximum number of unique threads queuing events */
#define FLUID_DEFAULT_AUDIO_RT_PRIO 60 /**< Default setting for audio.realtime-prio */
#define FLUID_DEFAULT_MIDI_RT_PRIO 50 /**< Default setting for midi.realtime-prio */
#define FLUID_NUM_MOD 64 /**< Maximum number of modulators in a voice */
/***************************************************************
*