Added a "Whats new in 1.1.0?" section to the developer doc.

Added fluid_settings_option_concat() to concatenate string setting options.
Removed fluid_audio_driver_get_names() and fluid_midi_driver_get_names(), since fluid_settings_option_concat() can be used in their place.
Renamed fluid_synth_program_select2() to fluid_synth_program_select_by_sfont_name().
Added fluid_synth_program_select_by_sfont_name(), fluid_synth_get_sfont_by_name() and fluid_synth_set_gen2() to public API.
Re-organized fluid_file_renderer_process_block() since it wasn't being picked up by Doxygen due to #if preprocessor stuff.
All integer and number settings now have FLUID_HINT_BOUNDED_BELOW and FLUID_HINT_BOUNDED_ABOVE hints set.
This commit is contained in:
Josh Green 2009-10-23 02:18:26 +00:00
parent 93ddc1fc5f
commit bcec3dc993
11 changed files with 189 additions and 114 deletions

View file

@ -19,6 +19,7 @@ All the source code examples in this document are in the public domain; you can
- \ref Disclaimer
- \ref Introduction
- \ref NewIn1_1_0
- \ref CreatingSettings
- \ref CreatingSynth
- \ref CreatingAudioDriver
@ -54,6 +55,57 @@ What is FluidSynth?
- FluidSynth is open source, in active development. For more details, take a look at http://www.fluidsynth.org
\section NewIn1_1_0 Whats new in 1.1.0?
Overview of changes in FluidSynth 1.1.0 concerning developers:
- Extensive work to make FluidSynth thread safe. Previous versions had many multi-thread
issues which could lead to crashes or synthesis glitches. Some of the API additions,
deprecations and function recommended conditions of use are related to this work.
- File renderer object for rendering audio to files.
- Sequencer objects can now use the system timer or the sample clock. When using the sample
clock, events are triggered based on the current output audio sample position. This means
that MIDI is synchronized with the audio and identical output will be achieved for the same
MIDI event input.
- libsndfile support for rendering audio to different formats and file types.
- API for using the MIDI router subsystem.
- MIDI Tuning Standard functions were added for specifying whether to activate tuning changes
in realtime or not.
- SYSEX support (MIDI Tuning Standard only at the moment).
- Changed all yes/no boolean string settings to integer #FLUID_HINT_TOGGLED settings with
backwards compatibility (assignment and query of boolean values as strings).
- Many other improvements and bug fixes.
API additions:
- A file renderer can be created with new_fluid_file_renderer(), deleted with
delete_fluid_file_renderer() and a block of audio processed with fluid_file_renderer_process_block().
- Additional functions were added for using the MIDI router subsystem.
To clear all rules from a router use fluid_midi_router_clear_rules() and to set a router to default rules
use fluid_midi_router_set_default_rules().
To create a router rule use new_fluid_midi_router_rule() and to delete a rule use
delete_fluid_midi_router_rule() (seldom used). Set values of a router rule with
fluid_midi_router_rule_set_chan(), fluid_midi_router_rule_set_param1() and fluid_midi_router_rule_set_param2().
fluid_midi_router_add_rule() can be used to add a rule to a router.
- New MIDI event functions were added, including fluid_event_channel_pressure(), fluid_event_system_reset(),
and fluid_event_unregistering(). Additional sequencer functions include fluid_sequencer_add_midi_event_to_buffer(),
fluid_sequencer_get_use_system_timer() and fluid_sequencer_process(). new_fluid_sequencer2() was added to
allow for the timer type to be specified (system or sample clock).
- The settings subsystem has some new functions for thread safety: fluid_settings_copystr() and fluid_settings_dupstr().
Also there are new convenience functions to count the number of string options for a setting: fluid_settings_option_count()
and for concatenating setting options with a separator: fluid_settings_option_concat().
- MIDI Tuning Standard functions added include: fluid_synth_activate_key_tuning(), fluid_synth_activate_octave_tuning(),
fluid_synth_activate_tuning() and fluid_synth_deactivate_tuning(). All of which provide a parameter for specifying if
tuning changes should occur in realtime (affect existing voices) or not.
- Additional synthesizer API: fluid_synth_get_sfont_by_name() to get a SoundFont by name,
fluid_synth_program_select_by_sfont_name() to select an instrument by SoundFont name/bank/program,
fluid_synth_set_gen2() for specifying additional parameters when assigning a generator value,
and fluid_synth_sysex() for sending SYSEX messages to the synth.
- Miscellaneous additions: fluid_player_set_loop() to set playlist loop count.
\section CreatingSettings Creating and changing the settings
Before you can use the synthesizer, you have to create a settings object. The settings objects is used by many components of the FluidSynth library. It gives a unified API to set the parameters of the audio drivers, the midi drivers, the synthesizer, and so forth. A number of default settings are defined by the current implementation.

View file

@ -64,8 +64,6 @@ FLUIDSYNTH_API fluid_audio_driver_t* new_fluid_audio_driver2(fluid_settings_t* s
FLUIDSYNTH_API void delete_fluid_audio_driver(fluid_audio_driver_t* driver);
FLUIDSYNTH_API void fluid_audio_driver_get_names(char* buf, size_t buflen, const char* separator);
FLUIDSYNTH_API fluid_file_renderer_t *new_fluid_file_renderer(fluid_synth_t* synth);
FLUIDSYNTH_API int fluid_file_renderer_process_block(fluid_file_renderer_t* dev);
FLUIDSYNTH_API void delete_fluid_file_renderer(fluid_file_renderer_t* dev);

View file

@ -108,8 +108,6 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings,
FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t* driver);
FLUIDSYNTH_API void fluid_midi_driver_get_names(char* buf, size_t buflen, const char* separator);
/**
* MIDI player status enum.

View file

@ -196,6 +196,9 @@ void fluid_settings_foreach_option(fluid_settings_t* settings,
fluid_settings_foreach_option_t func);
FLUIDSYNTH_API
int fluid_settings_option_count (fluid_settings_t* settings, char* name);
FLUIDSYNTH_API char *fluid_settings_option_concat (fluid_settings_t* settings,
const char* name,
const char* separator);
/**
* Callback function type used with fluid_settings_foreach()

View file

@ -70,6 +70,10 @@ FLUIDSYNTH_API int fluid_synth_sfont_select(fluid_synth_t* synth, int chan, unsi
FLUIDSYNTH_API
int fluid_synth_program_select(fluid_synth_t* synth, int chan, unsigned int sfont_id,
unsigned int bank_num, unsigned int preset_num);
FLUIDSYNTH_API int
fluid_synth_program_select_by_sfont_name (fluid_synth_t* synth, int chan,
char* sfont_name, unsigned int bank_num,
unsigned int preset_num);
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);
@ -96,6 +100,8 @@ FLUIDSYNTH_API void fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t
FLUIDSYNTH_API int fluid_synth_sfcount(fluid_synth_t* synth);
FLUIDSYNTH_API fluid_sfont_t* fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num);
FLUIDSYNTH_API fluid_sfont_t* fluid_synth_get_sfont_by_id(fluid_synth_t* synth, unsigned int id);
FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont_by_name (fluid_synth_t* synth,
char *name);
FLUIDSYNTH_API int fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset);
FLUIDSYNTH_API int fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id);
@ -179,6 +185,9 @@ enum fluid_interp {
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);

View file

@ -289,35 +289,6 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
}
}
/**
* Write a list of audio driver names into a buffer.
* (A buffer length of 256 characters should be more than enough.)
* @param buf buffert to write names into
* @param buflen maximum amount of characters in buf.
* @param separator separator string, written between names.
* @since 1.1.0
*/
void
fluid_audio_driver_get_names(char* buf, size_t buflen, const char* separator)
{
int i;
if (buflen <= 0) {
return;
}
buf[0] = '\0';
buflen--;
for (i = 0; fluid_audio_drivers[i].name != NULL; i++) {
if (i > 0) {
strncat(buf, separator, buflen - strlen(buf));
}
strncat(buf, fluid_audio_drivers[i].name, buflen - strlen(buf));
}
buf[buflen] = '\0';
}
/**
* Create a new audio driver.
* @param settings Configuration settings used to select and create the audio
@ -334,7 +305,7 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
int i;
fluid_audio_driver_t* driver = NULL;
char* name;
char allnames[256];
char *allnames;
for (i = 0; fluid_audio_drivers[i].name != NULL; i++) {
if (fluid_settings_str_equal(settings, "audio.driver", fluid_audio_drivers[i].name)) {
@ -347,11 +318,12 @@ new_fluid_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
}
}
fluid_audio_driver_get_names(allnames, sizeof(allnames), ", ");
fluid_settings_dupstr(settings, "audio.driver", &name); /* ++ alloc name */
allnames = fluid_settings_option_concat (settings, "audio.driver", NULL);
fluid_settings_dupstr (settings, "audio.driver", &name); /* ++ alloc name */
FLUID_LOG(FLUID_ERR, "Couldn't find the requested audio driver %s. Valid drivers are: %s.",
name ? name : "NULL", allnames);
name ? name : "NULL", allnames ? allnames : "ERROR");
if (name) FLUID_FREE (name);
if (allnames) FLUID_FREE (allnames);
return NULL;
}

View file

@ -337,16 +337,16 @@ void delete_fluid_file_renderer(fluid_file_renderer_t* dev)
return;
}
#if LIBSNDFILE_SUPPORT
/**
* Write period_size samples to file.
* @param dev File renderer instance
* @return FLUID_OK or FLUID_FAILED if an error occurred
* @return #FLUID_OK or #FLUID_FAILED if an error occurred
* @since 1.1.0
*/
int
fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
{
#if LIBSNDFILE_SUPPORT
int n;
fluid_synth_write_float(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
@ -359,11 +359,9 @@ fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
return FLUID_FAILED;
}
return FLUID_OK;
}
#else /* No libsndfile support */
int
fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
{
int n, offset;
fluid_synth_write_s16(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
@ -378,9 +376,8 @@ fluid_file_renderer_process_block(fluid_file_renderer_t* dev)
}
}
return FLUID_OK;
}
#endif
}
#if LIBSNDFILE_SUPPORT

View file

@ -195,36 +195,6 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
}
}
/**
* Write a list of MIDI driver names into a buffer.
* (A buffer length of 256 characters should be more than enough.)
* @param buf Buffer to write names into
* @param buflen Maximum amount of characters in buf.
* @param separator Separator string, written between names.
* @since 1.1.0
*/
void
fluid_midi_driver_get_names(char* buf, size_t buflen, const char* separator)
{
int i;
if (buflen <= 0) {
return;
}
buf[0] = '\0';
buflen--;
for (i = 0; fluid_midi_drivers[i].name != NULL; i++) {
if (i > 0) {
strncat(buf, separator, buflen - strlen(buf));
}
strncat(buf, fluid_midi_drivers[i].name, buflen - strlen(buf));
}
buf[buflen] = '\0';
}
/**
* Create a new MIDI driver instance.
* @param settings Settings used to configure new MIDI driver.
@ -235,9 +205,10 @@ fluid_midi_driver_get_names(char* buf, size_t buflen, const char* separator)
*/
fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
{
int i;
char allnames[256];
fluid_midi_driver_t* driver = NULL;
char *allnames;
int i;
for (i = 0; fluid_midi_drivers[i].name != NULL; i++) {
if (fluid_settings_str_equal(settings, "midi.driver", fluid_midi_drivers[i].name)) {
FLUID_LOG(FLUID_DBG, "Using '%s' midi driver", fluid_midi_drivers[i].name);
@ -249,8 +220,11 @@ fluid_midi_driver_t* new_fluid_midi_driver(fluid_settings_t* settings, handle_mi
}
}
fluid_midi_driver_get_names(allnames, sizeof(allnames), ", ");
FLUID_LOG(FLUID_ERR, "Couldn't find the requested midi driver. Valid drivers are: %s.", allnames);
allnames = fluid_settings_option_concat (settings, "midi.driver", NULL);
FLUID_LOG(FLUID_ERR, "Couldn't find the requested midi driver. Valid drivers are: %s.",
allnames ? allnames : "ERROR");
if (allnames) FLUID_FREE (allnames);
return NULL;
}

View file

@ -38,7 +38,7 @@ extern void fluid_file_renderer_settings (fluid_settings_t* settings);
static void fluid_settings_init(fluid_settings_t* settings);
static void fluid_settings_key_destroy_func(void* value);
static void fluid_settings_value_destroy_func(void* value);
static int fluid_settings_tokenize(char* s, char *buf, char** ptr);
static int fluid_settings_tokenize(const char *s, char *buf, char **ptr);
/* Common structure to all settings nodes */
typedef struct {
@ -302,7 +302,7 @@ fluid_settings_init(fluid_settings_t* settings)
}
static int
fluid_settings_tokenize(char* s, char *buf, char** ptr)
fluid_settings_tokenize(const char *s, char *buf, char **ptr)
{
char *tokstr, *tok;
int n = 0;
@ -341,7 +341,7 @@ fluid_settings_tokenize(char* s, char *buf, char** ptr)
* @return 1 if the node exists, 0 otherwise
*/
static int
fluid_settings_get(fluid_settings_t* settings, char* name,
fluid_settings_get(fluid_settings_t* settings, const char *name,
fluid_setting_node_t **value)
{
fluid_hashtable_t* table = settings;
@ -489,6 +489,9 @@ fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
fluid_return_val_if_fail (settings != NULL, 0);
fluid_return_val_if_fail (name != NULL, 0);
/* For now, all floating point settings are bounded below and above */
hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
fluid_rec_mutex_lock (settings->mutex);
if (!fluid_settings_get(settings, name, &node)) {
@ -521,7 +524,7 @@ fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
}
/** returns 1 if the value has been register correctly, zero
otherwise */
otherwise. */
int
fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
int min, int max, int hints,
@ -533,6 +536,9 @@ fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
fluid_return_val_if_fail (settings != NULL, 0);
fluid_return_val_if_fail (name != NULL, 0);
/* For now, all integer settings are bounded below and above */
hints |= FLUID_HINT_BOUNDED_BELOW | FLUID_HINT_BOUNDED_ABOVE;
fluid_rec_mutex_lock (settings->mutex);
if (!fluid_settings_get(settings, name, &node)) {
@ -1399,6 +1405,80 @@ fluid_settings_option_count (fluid_settings_t *settings, char *name)
return (count);
}
/**
* Concatenate options for a string setting together with a separator between.
* @param settings Settings object
* @param name Settings name
* @param separator String to use between options (NULL to use ", ")
* @return Newly allocated string or NULL on error (out of memory, not a valid
* setting \a name or not a string setting). Free the string when finished with it.
* @since 1.1.0
*/
char *
fluid_settings_option_concat (fluid_settings_t *settings, const char *name,
const char *separator)
{
fluid_setting_node_t *node;
fluid_str_setting_t *setting;
fluid_list_t *p, *newlist = NULL;
int count, len;
char *str, *option;
fluid_return_val_if_fail (settings != NULL, NULL);
fluid_return_val_if_fail (name != NULL, NULL);
if (!separator) separator = ", ";
fluid_rec_mutex_lock (settings->mutex); /* ++ lock */
if (!fluid_settings_get (settings, name, &node) || node->type != FLUID_STR_TYPE)
{
fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
return (NULL);
}
setting = (fluid_str_setting_t*)node;
/* Duplicate option list, count options and get total string length */
for (p = setting->options, count = 0, len = 0; p; p = p->next, count++)
{
option = fluid_list_get (p);
if (option)
{
newlist = fluid_list_append (newlist, option);
len += strlen (option);
}
}
if (count > 1) len += (count - 1) * strlen (separator);
len++; /* For terminator */
/* Sort by name */
newlist = fluid_list_sort (newlist, fluid_list_str_compare_func);
str = FLUID_MALLOC (len);
str[0] = 0;
if (str)
{
for (p = newlist; p; p = p->next)
{
option = fluid_list_get (p);
strcat (str, option);
if (p->next) strcat (str, separator);
}
}
fluid_rec_mutex_unlock (settings->mutex); /* -- unlock */
delete_fluid_list (newlist);
if (!str) FLUID_LOG (FLUID_ERR, "Out of memory");
return (str);
}
/* Structure passed to fluid_settings_foreach_iter recursive function */
typedef struct
{

View file

@ -133,26 +133,6 @@ static void fluid_synth_stop_LOCAL (fluid_synth_t *synth, unsigned int id);
fluid_sfloader_t* new_fluid_defsfloader(void);
/************************************************************************
*
* These functions were added after the v1.0 API freeze. They are not
* in synth.h. They should be added as soon as a new development
* version is started.
*
************************************************************************/
int fluid_synth_program_select2(fluid_synth_t* synth,
int chan,
char* sfont_name,
unsigned int bank_num,
unsigned int preset_num);
fluid_sfont_t* fluid_synth_get_sfont_by_name(fluid_synth_t* synth, char *name);
int fluid_synth_set_gen2(fluid_synth_t* synth, int chan,
int param, float value,
int absolute, int normalized);
/***************************************************************
*
@ -2456,10 +2436,12 @@ fluid_synth_program_select(fluid_synth_t* synth, int chan, unsigned int sfont_id
* @param bank_num MIDI bank number
* @param preset_num MIDI program number
* @return FLUID_OK on success, FLUID_FAILED otherwise
* @since 1.1.0
*/
int
fluid_synth_program_select2(fluid_synth_t* synth, int chan, char* sfont_name,
unsigned int bank_num, unsigned int preset_num)
fluid_synth_program_select_by_sfont_name (fluid_synth_t* synth, int chan,
char* sfont_name, unsigned int bank_num,
unsigned int preset_num)
{
fluid_preset_t* preset = NULL;
fluid_channel_t* channel;
@ -4063,6 +4045,7 @@ fluid_synth_get_sfont_by_id(fluid_synth_t* synth, unsigned int id)
* @param synth FluidSynth instance
* @param name Name of SoundFont
* @return SoundFont instance or NULL if invalid name
* @since 1.1.0
*
* NOTE: Caller should be certain that SoundFont is not deleted (unloaded) for
* the duration of use of the returned pointer.
@ -5449,10 +5432,11 @@ fluid_synth_set_gen_LOCAL (fluid_synth_t* synth, int chan, int param, float valu
* @param param SoundFont generator ID (#fluid_gen_type)
* @param value Offset or absolute generator value to assign to the MIDI channel
* @param absolute 0 to assign a relative value, non-zero to assign an absolute value
* @param normalize 0 if value is specified in the native units of the generator,
* @param normalized 0 if value is specified in the native units of the generator,
* non-zero 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 1.1.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

View file

@ -54,7 +54,7 @@
#endif
void print_usage(void);
void print_help(void);
void print_help(fluid_settings_t *settings);
void print_welcome(void);
static fluid_cmd_handler_t* newclient(void* data, char* addr);
@ -443,7 +443,7 @@ int main(int argc, char** argv)
fluid_settings_setnum(settings, "synth.gain", atof(optarg));
break;
case 'h':
print_help();
print_help(settings);
break;
case 'i':
interactive = 0;
@ -831,17 +831,20 @@ print_welcome()
* print_help
*/
void
print_help()
print_help (fluid_settings_t *settings)
{
char allnames[256];
char *audio_options;
char *midi_options;
audio_options = fluid_settings_option_concat (settings, "audio.driver", NULL);
midi_options = fluid_settings_option_concat (settings, "midi.driver", NULL);
printf("Usage: \n");
printf(" fluidsynth [options] [soundfonts] [midifiles]\n");
printf("Possible options:\n");
fluid_audio_driver_get_names(allnames, sizeof(allnames), ", ");
printf(" -a, --audio-driver=[label]\n"
" The name of the audio driver to use.\n"
" Valid values: %s\n", allnames);
" Valid values: %s\n", audio_options ? audio_options : "ERROR");
printf(" -c, --audio-bufcount=[count]\n"
" Number of audio buffers\n");
printf(" -C, --chorus\n"
@ -872,10 +875,9 @@ print_help()
#endif
printf(" -L, --audio-channels=[num]\n"
" The number of stereo audio channels [default = 1]\n");
fluid_midi_driver_get_names(allnames, sizeof(allnames), ", ");
printf(" -m, --midi-driver=[label]\n"
" The name of the midi driver to use.\n"
" Valid values: %s\n", allnames);
" Valid values: %s\n", midi_options ? midi_options : "ERROR");
printf(" -n, --no-midi-in\n"
" Don't create a midi driver to read MIDI input events [default = yes]\n");
printf(" -o\n"
@ -898,5 +900,11 @@ print_help()
" Show version of program\n");
printf(" -z, --audio-bufsize=[size]\n"
" Size of each audio buffer\n");
if (audio_options) FLUID_FREE (audio_options);
if (midi_options) FLUID_FREE (midi_options);
delete_fluid_settings (settings);
exit(0);
}