mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-28 06:52:57 +00:00
Added public API functions: fluid_synth_sysex, fluid_synth_activate_key_tuning, fluid_synth_activate_octave_tuning, fluid_synth_tune_notes, fluid_synth_activate_tuning and fluid_synth_deactivate_tuning.
Added audio.realtime, audio.realtime-prio, midi.realtime and midi.realtime-prio (only ALSA updated to use them at this point). Fixed bug in new_fluid_channel() where tuning field was not initialized. fluid_settings.h had wrong field order in prototypes for fluid_settings_register_num and fluid_settings_register_int. Added multi core support: "synth.cpu-cores" setting, fluid_synth_core_thread_func() and many core_ variables to fluid_synth_t. Switched fluid_mutex_t back to a normal non-recursive mutex and added fluid_rec_mutex_t. Added fluid_cond_t thread synchronization stuff. Added fluid_cond_mutex_t which is a dynamically allocated regular mutex for use with fluid_cond_t. fluid_settings_t and fluid_synth_t are now using fluid_rec_mutex_t (same as before, just name change). Added platform specific fluid_thread_self_set_prio() functions to fluid_sys.c for activating high priority for the calling thread. Modified new_fluid_thread() to take a prio and prio_level parameters. Added missing fluid_atomic_pointer_set(). fluid_voice_write() changed to only take a voice audio buffer to render to, mixing is done separately with new fluid_voice_mix(). fluid_voice_write() now returns the count of samples rendered. fluid_voice_effects() split into fluid_voice_filter() and fluid_voice_mix(). Added dsp_buf_count field to fluid_voice_t to keep track of last count of samples rendered to dsp_buf. fluid_voice_get_channel() converted to a macro. Added FLUID_DEFAULT_AUDIO_RT_PRIO and FLUID_DEFAULT_MIDI_RT_PRIO in fluidsynth_priv.h, set to 90 and 80 respectively which get used for audio.realtime-prio and midi.realtime-prio (was 90 and 90 before).
This commit is contained in:
parent
012f627017
commit
43a9923dff
16 changed files with 727 additions and 331 deletions
|
@ -56,6 +56,8 @@ FLUIDSYNTH_API int fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, i
|
|||
FLUIDSYNTH_API int fluid_synth_noteoff(fluid_synth_t* synth, int chan, int key);
|
||||
FLUIDSYNTH_API int fluid_synth_cc(fluid_synth_t* synth, int chan, int ctrl, int val);
|
||||
FLUIDSYNTH_API int fluid_synth_get_cc(fluid_synth_t* synth, int chan, int ctrl, int* pval);
|
||||
FLUIDSYNTH_API int fluid_synth_sysex(fluid_synth_t *synth, char *data, int len,
|
||||
char *response, int *response_len, int *handled, int dryrun);
|
||||
FLUIDSYNTH_API int fluid_synth_pitch_bend(fluid_synth_t* synth, int chan, int val);
|
||||
FLUIDSYNTH_API int fluid_synth_get_pitch_bend(fluid_synth_t* synth, int chan, int* ppitch_bend);
|
||||
FLUIDSYNTH_API int fluid_synth_pitch_wheel_sens(fluid_synth_t* synth, int chan, int val);
|
||||
|
@ -187,22 +189,33 @@ FLUIDSYNTH_API float fluid_synth_get_gen(fluid_synth_t* synth, int chan, int par
|
|||
/* Tuning */
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_create_key_tuning(fluid_synth_t* synth, int tuning_bank, int tuning_prog,
|
||||
char* name, double* pitch);
|
||||
int fluid_synth_create_key_tuning(fluid_synth_t* synth, int bank, int prog,
|
||||
char* name, double* pitch);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog,
|
||||
char* name, double* pitch, int apply);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_create_octave_tuning(fluid_synth_t* synth, int tuning_bank, int tuning_prog,
|
||||
char* name, double* pitch);
|
||||
int fluid_synth_create_octave_tuning(fluid_synth_t* synth, int bank, int prog,
|
||||
char* name, double* pitch);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog,
|
||||
char* name, double* pitch, int apply);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_tune_notes(fluid_synth_t* synth, int tuning_bank, int tuning_prog,
|
||||
int len, int *keys, double* pitch, int apply);
|
||||
int fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog,
|
||||
int len, int *keys, double* pitch, int apply);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_select_tuning(fluid_synth_t* synth, int chan, int tuning_bank, int tuning_prog);
|
||||
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 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
|
||||
int fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog);
|
||||
FLUIDSYNTH_API int fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog,
|
||||
char* name, int len, double* pitch);
|
||||
char* name, int len, double* pitch);
|
||||
|
||||
/* Misc */
|
||||
|
||||
|
|
|
@ -221,6 +221,12 @@ void fluid_audio_driver_settings(fluid_settings_t* settings)
|
|||
fluid_settings_register_int(settings, "audio.periods", 16, 2, 64, 0, NULL, NULL);
|
||||
#endif
|
||||
|
||||
fluid_settings_register_str (settings, "audio.realtime", "yes", 0, NULL, NULL);
|
||||
fluid_settings_add_option (settings, "audio.realtime", "yes");
|
||||
fluid_settings_add_option (settings, "audio.realtime", "no");
|
||||
fluid_settings_register_int (settings, "audio.realtime-prio",
|
||||
FLUID_DEFAULT_AUDIO_RT_PRIO, 1, 99, 0, NULL, NULL);
|
||||
|
||||
/* Set the default driver */
|
||||
#if JACK_SUPPORT
|
||||
fluid_settings_register_str(settings, "audio.driver", "jack", 0, NULL, NULL);
|
||||
|
|
|
@ -49,11 +49,6 @@
|
|||
|
||||
#define BUFFER_LENGTH 512
|
||||
|
||||
/* SCHED_FIFO priorities for ALSA threads (see pthread_attr_setschedparam) */
|
||||
#define ALSA_PCM_SCHED_PRIORITY 90
|
||||
#define ALSA_RAWMIDI_SCHED_PRIORITY 90
|
||||
#define ALSA_SEQ_SCHED_PRIORITY 90
|
||||
|
||||
/** fluid_alsa_audio_driver_t
|
||||
*
|
||||
* This structure should not be accessed directly. Use audio port
|
||||
|
@ -174,8 +169,9 @@ new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
|
|||
int periods, period_size;
|
||||
char* device = NULL;
|
||||
pthread_attr_t attr;
|
||||
int sched = SCHED_FIFO;
|
||||
int sched;
|
||||
struct sched_param priority;
|
||||
int realtime_prio = 0;
|
||||
int i, err, dir = 0;
|
||||
snd_pcm_hw_params_t* hwparams;
|
||||
snd_pcm_sw_params_t* swparams = NULL;
|
||||
|
@ -192,7 +188,12 @@ new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
|
|||
fluid_settings_getint(settings, "audio.periods", &periods);
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
|
||||
fluid_settings_dupstr(settings, "audio.alsa.device", &device); /* ++ dup device name */
|
||||
fluid_settings_dupstr(settings, "audio.alsa.device", &device); /* ++ dup device name */
|
||||
fluid_settings_getint (settings, "audio.realtime-prio", &realtime_prio);
|
||||
|
||||
if (fluid_settings_str_equal (settings, "audio.realtime", "yes"))
|
||||
sched = SCHED_FIFO;
|
||||
else sched = SCHED_OTHER;
|
||||
|
||||
dev->data = data;
|
||||
dev->callback = func;
|
||||
|
@ -297,22 +298,6 @@ new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
|
|||
FLUID_LOG(FLUID_ERR, "Failed to set start threshold.");
|
||||
}
|
||||
|
||||
/* FIXME - Any of these calls important? One of them was causing massive
|
||||
ALSA CPU consumption! */
|
||||
|
||||
// if (snd_pcm_sw_params_set_stop_threshold(dev->pcm, swparams, ~0u) != 0) {
|
||||
// FLUID_LOG(FLUID_ERR, "Cannot turn off stop threshold.");
|
||||
// }
|
||||
|
||||
// if (snd_pcm_sw_params_set_silence_threshold(dev->pcm, swparams, 0) != 0) {
|
||||
// FLUID_LOG(FLUID_ERR, "Cannot set 0 silence threshold.");
|
||||
// }
|
||||
|
||||
// if (snd_pcm_sw_params_set_silence_size(dev->pcm, swparams, 0) != 0) {
|
||||
// FLUID_LOG(FLUID_ERR, "Cannot set 0 silence size.");
|
||||
// }
|
||||
|
||||
// if (snd_pcm_sw_params_set_avail_min(dev->pcm, swparams, period_size / 2) != 0) {
|
||||
if (snd_pcm_sw_params_set_avail_min(dev->pcm, swparams, period_size) != 0) {
|
||||
FLUID_LOG(FLUID_ERR, "Software setup for minimum available frames failed.");
|
||||
}
|
||||
|
@ -348,7 +333,7 @@ new_fluid_alsa_audio_driver2(fluid_settings_t* settings,
|
|||
}
|
||||
|
||||
/* SCHED_FIFO will not be active without setting the priority */
|
||||
priority.sched_priority = (sched == SCHED_FIFO) ? ALSA_PCM_SCHED_PRIORITY : 0;
|
||||
priority.sched_priority = (sched == SCHED_FIFO) ? realtime_prio : 0;
|
||||
pthread_attr_setschedparam(&attr, &priority);
|
||||
|
||||
err = pthread_create(&dev->thread, &attr, fluid_alsa_formats[i].run, (void*) dev);
|
||||
|
@ -636,8 +621,9 @@ new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
|
|||
int i, err;
|
||||
fluid_alsa_rawmidi_driver_t* dev;
|
||||
pthread_attr_t attr;
|
||||
int sched = SCHED_FIFO;
|
||||
int sched;
|
||||
struct sched_param priority;
|
||||
int realtime_prio = 0;
|
||||
int count;
|
||||
struct pollfd *pfd = NULL;
|
||||
char* device = NULL;
|
||||
|
@ -666,6 +652,12 @@ new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
fluid_settings_getint (settings, "midi.realtime-prio", &realtime_prio);
|
||||
|
||||
if (fluid_settings_str_equal (settings, "midi.realtime", "yes"))
|
||||
sched = SCHED_FIFO;
|
||||
else sched = SCHED_OTHER;
|
||||
|
||||
/* get the device name. if none is specified, use the default device. */
|
||||
fluid_settings_dupstr(settings, "midi.alsa.device", &device); /* ++ alloc device name */
|
||||
|
||||
|
@ -734,7 +726,7 @@ new_fluid_alsa_rawmidi_driver(fluid_settings_t* settings,
|
|||
}
|
||||
|
||||
/* SCHED_FIFO will not be active without setting the priority */
|
||||
priority.sched_priority = (sched == SCHED_FIFO) ? ALSA_RAWMIDI_SCHED_PRIORITY : 0;
|
||||
priority.sched_priority = (sched == SCHED_FIFO) ? realtime_prio : 0;
|
||||
pthread_attr_setschedparam (&attr, &priority);
|
||||
|
||||
err = pthread_create(&dev->thread, &attr, fluid_alsa_midi_run, (void*) dev);
|
||||
|
@ -901,8 +893,9 @@ new_fluid_alsa_seq_driver(fluid_settings_t* settings,
|
|||
int i, err;
|
||||
fluid_alsa_seq_driver_t* dev;
|
||||
pthread_attr_t attr;
|
||||
int sched = SCHED_FIFO;
|
||||
int sched;
|
||||
struct sched_param priority;
|
||||
int realtime_prio = 0;
|
||||
int count;
|
||||
struct pollfd *pfd = NULL;
|
||||
char *device = NULL;
|
||||
|
@ -929,6 +922,11 @@ new_fluid_alsa_seq_driver(fluid_settings_t* settings,
|
|||
dev->driver.data = data;
|
||||
dev->driver.handler = handler;
|
||||
|
||||
fluid_settings_getint (settings, "midi.realtime-prio", &realtime_prio);
|
||||
|
||||
if (fluid_settings_str_equal (settings, "midi.realtime", "yes"))
|
||||
sched = SCHED_FIFO;
|
||||
else sched = SCHED_OTHER;
|
||||
|
||||
/* get the device name. if none is specified, use the default device. */
|
||||
if (fluid_settings_dupstr(settings, "midi.alsa_seq.device", &device) == 0) /* ++ alloc device name */
|
||||
|
@ -1056,7 +1054,7 @@ new_fluid_alsa_seq_driver(fluid_settings_t* settings,
|
|||
}
|
||||
|
||||
/* SCHED_FIFO will not be active without setting the priority */
|
||||
priority.sched_priority = (sched == SCHED_FIFO) ? ALSA_SEQ_SCHED_PRIORITY : 0;
|
||||
priority.sched_priority = (sched == SCHED_FIFO) ? realtime_prio : 0;
|
||||
pthread_attr_setschedparam (&attr, &priority);
|
||||
|
||||
err = pthread_create(&dev->thread, &attr, fluid_alsa_seq_run, (void*) dev);
|
||||
|
|
|
@ -55,6 +55,7 @@ new_fluid_channel(fluid_synth_t* synth, int num)
|
|||
chan->synth = synth;
|
||||
chan->channum = num;
|
||||
chan->preset = NULL;
|
||||
chan->tuning = NULL;
|
||||
|
||||
fluid_channel_init(chan);
|
||||
fluid_channel_init_ctrl(chan, 0);
|
||||
|
|
|
@ -223,7 +223,8 @@ fluid_shell_t* new_fluid_shell(fluid_settings_t* settings, fluid_cmd_handler_t*
|
|||
fluid_shell_init(shell, settings, handler, in, out);
|
||||
|
||||
if (thread) {
|
||||
shell->thread = new_fluid_thread((fluid_thread_func_t) fluid_shell_run, shell, 1);
|
||||
shell->thread = new_fluid_thread((fluid_thread_func_t) fluid_shell_run, shell,
|
||||
FLUID_THREAD_PRIO_NORMAL, 0, TRUE);
|
||||
if (shell->thread == NULL) {
|
||||
delete_fluid_shell(shell);
|
||||
return NULL;
|
||||
|
@ -1813,7 +1814,8 @@ new_fluid_client(fluid_server_t* server, fluid_settings_t* settings,
|
|||
client->settings = settings;
|
||||
client->handler = handler;
|
||||
|
||||
client->thread = new_fluid_thread((fluid_thread_func_t) fluid_client_run, client, 0);
|
||||
client->thread = new_fluid_thread((fluid_thread_func_t) fluid_client_run, client,
|
||||
FLUID_THREAD_PRIO_NORMAL, 0, FALSE);
|
||||
|
||||
if (client->thread == NULL) {
|
||||
fluid_socket_close(sock);
|
||||
|
|
|
@ -68,7 +68,7 @@ struct _fluid_hashtable_t
|
|||
volatile int ref_count;
|
||||
fluid_destroy_notify_t key_destroy_func;
|
||||
fluid_destroy_notify_t value_destroy_func;
|
||||
fluid_mutex_t mutex; // Optionally used in other modules (fluid_settings.c for example)
|
||||
fluid_rec_mutex_t mutex; // Optionally used in other modules (fluid_settings.c for example)
|
||||
};
|
||||
|
||||
struct _fluid_hashtable_iter_t
|
||||
|
|
|
@ -145,6 +145,12 @@ void fluid_midi_driver_settings(fluid_settings_t* settings)
|
|||
{
|
||||
int i;
|
||||
|
||||
fluid_settings_register_str (settings, "midi.realtime", "yes", 0, NULL, NULL);
|
||||
fluid_settings_add_option (settings, "midi.realtime", "yes");
|
||||
fluid_settings_add_option (settings, "midi.realtime", "no");
|
||||
fluid_settings_register_int (settings, "midi.realtime-prio",
|
||||
FLUID_DEFAULT_MIDI_RT_PRIO, 1, 99, 0, NULL, NULL);
|
||||
|
||||
/* Set the default driver */
|
||||
#if ALSA_SUPPORT
|
||||
fluid_settings_register_str(settings, "midi.driver", "alsa_seq", 0, NULL, NULL);
|
||||
|
|
|
@ -238,7 +238,7 @@ new_fluid_settings(void)
|
|||
fluid_settings_value_destroy_func);
|
||||
if (settings == NULL) return NULL;
|
||||
|
||||
fluid_mutex_init (settings->mutex);
|
||||
fluid_rec_mutex_init (settings->mutex);
|
||||
fluid_settings_init(settings);
|
||||
return settings;
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ delete_fluid_settings(fluid_settings_t* settings)
|
|||
{
|
||||
fluid_return_if_fail (settings != NULL);
|
||||
|
||||
fluid_mutex_destroy (settings->mutex);
|
||||
fluid_rec_mutex_destroy (settings->mutex);
|
||||
delete_fluid_hashtable(settings);
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,7 @@ fluid_settings_get(fluid_settings_t* settings, char** name, int len,
|
|||
fluid_setting_node_t **value)
|
||||
{
|
||||
fluid_hashtable_t* table = settings;
|
||||
fluid_setting_node_t *node;
|
||||
fluid_setting_node_t *node = NULL;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < len; n++) {
|
||||
|
@ -445,7 +445,7 @@ fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, i
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (!fluid_settings_get(settings, tokens, ntokens, &node)) {
|
||||
setting = new_fluid_str_setting(def, def, hints, fun, data);
|
||||
|
@ -466,7 +466,7 @@ fluid_settings_register_str(fluid_settings_t* settings, char* name, char* def, i
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -489,7 +489,7 @@ fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (!fluid_settings_get(settings, tokens, ntokens, &node)) {
|
||||
/* insert a new setting */
|
||||
|
@ -515,7 +515,7 @@ fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -538,7 +538,7 @@ fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (!fluid_settings_get(settings, tokens, ntokens, &node)) {
|
||||
/* insert a new setting */
|
||||
|
@ -564,7 +564,7 @@ fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -590,9 +590,9 @@ fluid_settings_get_type(fluid_settings_t* settings, char* name)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
type = fluid_settings_get (settings, tokens, ntokens, &node) ? node->type : FLUID_NO_TYPE;
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return (type);
|
||||
}
|
||||
|
@ -618,7 +618,7 @@ fluid_settings_get_hints(fluid_settings_t* settings, char* name)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)) {
|
||||
if (node->type == FLUID_NUM_TYPE) {
|
||||
|
@ -630,7 +630,7 @@ fluid_settings_get_hints(fluid_settings_t* settings, char* name)
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return hints;
|
||||
}
|
||||
|
@ -656,7 +656,7 @@ fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)) {
|
||||
if (node->type == FLUID_NUM_TYPE) {
|
||||
|
@ -668,7 +668,7 @@ fluid_settings_is_realtime(fluid_settings_t* settings, char* name)
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return isrealtime;
|
||||
}
|
||||
|
@ -696,7 +696,7 @@ fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
|||
|
||||
ntokens = fluid_settings_tokenize (name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get (settings, tokens, ntokens, &node)) {
|
||||
if (node->type == FLUID_STR_TYPE) {
|
||||
|
@ -717,7 +717,7 @@ fluid_settings_setstr(fluid_settings_t* settings, char* name, char* str)
|
|||
if (retval != 1) delete_fluid_str_setting (setting);
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -753,7 +753,7 @@ fluid_settings_copystr(fluid_settings_t* settings, char* name, char* str, int le
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -768,7 +768,7 @@ fluid_settings_copystr(fluid_settings_t* settings, char* name, char* str, int le
|
|||
retval = 1;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -799,7 +799,7 @@ fluid_settings_dupstr(fluid_settings_t* settings, char* name, char** str)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -814,7 +814,7 @@ fluid_settings_dupstr(fluid_settings_t* settings, char* name, char** str)
|
|||
if (!setting->value || *str) retval = 1; /* Don't set to 1 if out of memory */
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -850,7 +850,7 @@ fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -860,7 +860,7 @@ fluid_settings_getstr(fluid_settings_t* settings, char* name, char** str)
|
|||
}
|
||||
else *str = NULL;
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -888,7 +888,7 @@ fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -896,7 +896,7 @@ fluid_settings_str_equal(fluid_settings_t* settings, char* name, char* s)
|
|||
if (setting->value) retval = FLUID_STRCMP (setting->value, s) == 0;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -923,7 +923,7 @@ fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -931,7 +931,7 @@ fluid_settings_getstr_default(fluid_settings_t* settings, char* name)
|
|||
retval = setting->def;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -958,7 +958,7 @@ fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -968,7 +968,7 @@ fluid_settings_add_option(fluid_settings_t* settings, char* name, char* s)
|
|||
retval = 1;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -995,7 +995,7 @@ fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -1015,7 +1015,7 @@ fluid_settings_remove_option(fluid_settings_t* settings, char* name, char* s)
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1043,7 +1043,7 @@ fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)) {
|
||||
if (node->type == FLUID_NUM_TYPE) {
|
||||
|
@ -1067,7 +1067,7 @@ fluid_settings_setnum(fluid_settings_t* settings, char* name, double val)
|
|||
if (retval != 1) delete_fluid_num_setting (setting);
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1095,7 +1095,7 @@ fluid_settings_getnum(fluid_settings_t* settings, char* name, double* val)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_NUM_TYPE)) {
|
||||
|
@ -1104,7 +1104,7 @@ fluid_settings_getnum(fluid_settings_t* settings, char* name, double* val)
|
|||
retval = 1;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1132,7 +1132,7 @@ fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double* min,
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_NUM_TYPE)) {
|
||||
|
@ -1141,7 +1141,7 @@ fluid_settings_getnum_range(fluid_settings_t* settings, char* name, double* min,
|
|||
*max = setting->max;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1165,7 +1165,7 @@ fluid_settings_getnum_default(fluid_settings_t* settings, char* name)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_NUM_TYPE)) {
|
||||
|
@ -1173,7 +1173,7 @@ fluid_settings_getnum_default(fluid_settings_t* settings, char* name)
|
|||
retval = setting->def;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1201,7 +1201,7 @@ fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)) {
|
||||
if (node->type == FLUID_INT_TYPE) {
|
||||
|
@ -1225,7 +1225,7 @@ fluid_settings_setint(fluid_settings_t* settings, char* name, int val)
|
|||
if (retval != 1) delete_fluid_int_setting (setting);
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1253,7 +1253,7 @@ fluid_settings_getint(fluid_settings_t* settings, char* name, int* val)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_INT_TYPE)) {
|
||||
|
@ -1262,7 +1262,7 @@ fluid_settings_getint(fluid_settings_t* settings, char* name, int* val)
|
|||
retval = 1;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1289,7 +1289,7 @@ fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* min, in
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_INT_TYPE)) {
|
||||
|
@ -1298,7 +1298,7 @@ fluid_settings_getint_range(fluid_settings_t* settings, char* name, int* min, in
|
|||
*max = setting->max;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1322,7 +1322,7 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_INT_TYPE)) {
|
||||
|
@ -1330,7 +1330,7 @@ fluid_settings_getint_default(fluid_settings_t* settings, char* name)
|
|||
retval = setting->def;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -1359,7 +1359,7 @@ fluid_settings_foreach_option (fluid_settings_t* settings, char* name, void* dat
|
|||
|
||||
ntokens = fluid_settings_tokenize(name, buf, tokens);
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
|
||||
if (fluid_settings_get(settings, tokens, ntokens, &node)
|
||||
&& (node->type == FLUID_STR_TYPE)) {
|
||||
|
@ -1374,7 +1374,7 @@ fluid_settings_foreach_option (fluid_settings_t* settings, char* name, void* dat
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
}
|
||||
|
||||
/* Structure passed to fluid_settings_foreach_iter recursive function */
|
||||
|
@ -1440,7 +1440,7 @@ fluid_settings_foreach(fluid_settings_t* settings, void* data, fluid_settings_fo
|
|||
bag.data = data;
|
||||
bag.path[0] = 0;
|
||||
|
||||
fluid_mutex_lock (settings->mutex);
|
||||
fluid_rec_mutex_lock (settings->mutex);
|
||||
fluid_hashtable_foreach(settings, fluid_settings_foreach_iter, &bag);
|
||||
fluid_mutex_unlock (settings->mutex);
|
||||
fluid_rec_mutex_unlock (settings->mutex);
|
||||
}
|
||||
|
|
|
@ -42,14 +42,15 @@ int fluid_settings_register_str(fluid_settings_t* settings, char* name, char* de
|
|||
|
||||
/** returns 0 if the value has been registered correctly, non-zero
|
||||
otherwise */
|
||||
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double min, double max,
|
||||
double def, int hints, fluid_num_update_t fun, void* data);
|
||||
|
||||
int fluid_settings_register_num(fluid_settings_t* settings, char* name, double def,
|
||||
double min, double max, int hints,
|
||||
fluid_num_update_t fun, void* data);
|
||||
|
||||
/** returns 0 if the value has been registered correctly, non-zero
|
||||
otherwise */
|
||||
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int min, int max,
|
||||
int def, int hints, fluid_int_update_t fun, void* data);
|
||||
int fluid_settings_register_int(fluid_settings_t* settings, char* name, int def,
|
||||
int min, int max, int hints,
|
||||
fluid_int_update_t fun, void* data);
|
||||
|
||||
|
||||
#endif /* _FLUID_SETTINGS_H */
|
||||
|
|
|
@ -93,6 +93,7 @@ static int fluid_synth_set_polyphony_LOCAL(fluid_synth_t* synth, int polyphony);
|
|||
static void init_dither(void);
|
||||
static inline int roundi (float x);
|
||||
static int fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out);
|
||||
static void fluid_synth_core_thread_func (void* data);
|
||||
static FLUID_INLINE void fluid_synth_process_event_queue_LOCAL
|
||||
(fluid_synth_t *synth, fluid_event_queue_t *queue);
|
||||
static fluid_voice_t* fluid_synth_free_voice_by_kill_LOCAL(fluid_synth_t* synth);
|
||||
|
@ -222,6 +223,7 @@ void fluid_synth_settings(fluid_settings_t* settings)
|
|||
0, NULL, NULL);
|
||||
fluid_settings_register_int(settings, "synth.device-id",
|
||||
0, 126, 0, 0, NULL, NULL);
|
||||
fluid_settings_register_int(settings, "synth.cpu-cores", 1, 1, 256, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -517,7 +519,7 @@ new_fluid_synth(fluid_settings_t *settings)
|
|||
}
|
||||
FLUID_MEMSET(synth, 0, sizeof(fluid_synth_t));
|
||||
|
||||
fluid_mutex_init(synth->mutex);
|
||||
fluid_rec_mutex_init(synth->mutex);
|
||||
fluid_private_init(synth->thread_queues);
|
||||
|
||||
synth->return_queue = fluid_event_queue_new (FLUID_MAX_RETURN_EVENTS);
|
||||
|
@ -542,6 +544,7 @@ new_fluid_synth(fluid_settings_t *settings)
|
|||
fluid_settings_getint(settings, "synth.effects-channels", &synth->effects_channels);
|
||||
fluid_settings_getnum(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.gain",
|
||||
|
@ -729,6 +732,57 @@ new_fluid_synth(fluid_settings_t *settings)
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
/* Initialize multi-core variables if multiple cores enabled */
|
||||
if (synth->cores > 1)
|
||||
{
|
||||
int prio, prio_level;
|
||||
|
||||
synth->core_mutex = new_fluid_cond_mutex ();
|
||||
synth->core_cond = new_fluid_cond ();
|
||||
synth->core_wait_last_cond = new_fluid_cond ();
|
||||
|
||||
synth->core_threads = FLUID_ARRAY (fluid_thread_t *, synth->cores - 1);
|
||||
synth->core_voice_processed = FLUID_ARRAY (fluid_voice_t *, synth->polyphony);
|
||||
synth->core_bufs = FLUID_MALLOC (synth->polyphony * FLUID_BUFSIZE * sizeof (fluid_real_t));
|
||||
|
||||
if (!synth->core_mutex || !synth->core_cond || !synth->core_wait_last_cond
|
||||
|| !synth->core_threads || !synth->core_voice_processed
|
||||
|| !synth->core_bufs)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
synth->cores_active = TRUE;
|
||||
synth->core_work = FALSE;
|
||||
synth->core_inprogress = 0;
|
||||
synth->core_waiting_for_last = FALSE;
|
||||
|
||||
for (i = 0; i < synth->polyphony; i++)
|
||||
synth->core_voice_processed[i] = NULL;
|
||||
|
||||
prio = fluid_settings_str_equal (synth->settings, "audio.realtime", "yes");
|
||||
|
||||
if (prio)
|
||||
{
|
||||
prio = FLUID_THREAD_PRIO_HIGH;
|
||||
fluid_settings_getint (synth->settings, "audio.realtime-prio", &prio_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
prio = FLUID_THREAD_PRIO_NORMAL;
|
||||
prio_level = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < synth->cores - 1; i++)
|
||||
{
|
||||
synth->core_threads[i] = new_fluid_thread (fluid_synth_core_thread_func,
|
||||
synth, prio, prio_level, FALSE);
|
||||
if (!synth->core_threads[i])
|
||||
FLUID_LOG(FLUID_ERR, "Failed to create a synthesis core thread");
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
synth->start = fluid_curtime();
|
||||
|
||||
|
@ -755,26 +809,26 @@ fluid_synth_return_event_process_callback (void* data, unsigned int msec)
|
|||
switch (event->type)
|
||||
{
|
||||
case FLUID_EVENT_QUEUE_ELEM_GAIN: /* Sync gain variable */
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock gain variable */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock gain variable */
|
||||
synth->gain = event->dval;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
break;
|
||||
case FLUID_EVENT_QUEUE_ELEM_REVERB: /* Sync reverb shadow variables */
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock reverb shadow variables */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock reverb shadow variables */
|
||||
synth->reverb_roomsize = event->reverb.roomsize;
|
||||
synth->reverb_damping = event->reverb.damping;
|
||||
synth->reverb_width = event->reverb.width;
|
||||
synth->reverb_level = event->reverb.level;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
break;
|
||||
case FLUID_EVENT_QUEUE_ELEM_CHORUS: /* Sync chorus shadow variables */
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock chorus shadow variables */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock chorus shadow variables */
|
||||
synth->chorus_nr = event->chorus.nr;
|
||||
synth->chorus_level = event->chorus.level;
|
||||
synth->chorus_speed = event->chorus.speed;
|
||||
synth->chorus_depth = event->chorus.depth;
|
||||
synth->chorus_type = event->chorus.type;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
break;
|
||||
case FLUID_EVENT_QUEUE_ELEM_FREE_PRESET: /* Preset free event */
|
||||
preset = (fluid_preset_t *)(event->pval);
|
||||
|
@ -823,6 +877,26 @@ delete_fluid_synth(fluid_synth_t* synth)
|
|||
fluid_event_queue_free(synth->return_queue);
|
||||
}
|
||||
|
||||
/* Free multi-core resources (if multi-core enabled) */
|
||||
if (synth->cores > 1)
|
||||
{
|
||||
/* Signal slave core threads to exit and wait for them to finish */
|
||||
fluid_cond_mutex_lock (synth->core_mutex); /* ++ Lock */
|
||||
synth->cores_active = FALSE;
|
||||
fluid_cond_broadcast (synth->core_cond);
|
||||
fluid_cond_mutex_unlock (synth->core_mutex); /* -- Unlock */
|
||||
|
||||
for (i = 0; i < synth->cores - 1; i++)
|
||||
if (synth->core_threads[i])
|
||||
fluid_thread_join (synth->core_threads[i]);
|
||||
|
||||
delete_fluid_cond_mutex (synth->core_mutex);
|
||||
delete_fluid_cond (synth->core_cond);
|
||||
delete_fluid_cond (synth->core_wait_last_cond);
|
||||
FLUID_FREE (synth->core_voice_processed);
|
||||
FLUID_FREE (synth->core_bufs);
|
||||
}
|
||||
|
||||
/* turn off all voices, needed to unload SoundFont data */
|
||||
if (synth->voice != NULL) {
|
||||
for (i = 0; i < synth->nvoice; i++) {
|
||||
|
@ -959,7 +1033,7 @@ delete_fluid_synth(fluid_synth_t* synth)
|
|||
delete_fluid_list (synth->queue_pool);
|
||||
fluid_private_free (synth->thread_queues);
|
||||
|
||||
fluid_mutex_destroy(synth->mutex);
|
||||
fluid_rec_mutex_destroy(synth->mutex);
|
||||
|
||||
FLUID_FREE(synth);
|
||||
|
||||
|
@ -992,7 +1066,7 @@ fluid_synth_get_event_queue (fluid_synth_t* synth)
|
|||
|
||||
if (!queue) /* This thread has no queue yet? */
|
||||
{
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock queue_pool */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock queue_pool */
|
||||
|
||||
/* Use an unclaimed queue, if any (it will already be in synth->queues[] in that case) */
|
||||
if (synth->queue_pool)
|
||||
|
@ -1007,7 +1081,7 @@ fluid_synth_get_event_queue (fluid_synth_t* synth)
|
|||
delete1_fluid_list (p);
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock queue_pool */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock queue_pool */
|
||||
|
||||
if (!queue) /* Create event queue, if one wasn't re-claimed */
|
||||
{
|
||||
|
@ -1180,9 +1254,9 @@ fluid_synth_thread_queue_destroy_notify (void *data)
|
|||
|
||||
/* Queues are not freed (can't be thread safe without locking in synth thread),
|
||||
* added to pool for potential future use */
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock queue_pool */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock queue_pool */
|
||||
synth->queue_pool = fluid_list_prepend (synth->queue_pool, queue);
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock queue_pool */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock queue_pool */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2101,7 +2175,7 @@ fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
|
|||
fluid_sfont_info_t *sfont_info;
|
||||
fluid_list_t *list;
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
|
||||
sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
|
||||
|
@ -2115,7 +2189,7 @@ fluid_synth_get_preset(fluid_synth_t* synth, unsigned int sfontnum,
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
return preset;
|
||||
}
|
||||
|
@ -2134,7 +2208,7 @@ fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname
|
|||
fluid_sfont_info_t *sfont_info;
|
||||
fluid_list_t *list;
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
|
||||
sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
|
||||
|
@ -2148,7 +2222,7 @@ fluid_synth_get_preset_by_sfont_name(fluid_synth_t* synth, const char *sfontname
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
return preset;
|
||||
}
|
||||
|
@ -2167,7 +2241,7 @@ fluid_synth_find_preset(fluid_synth_t* synth, unsigned int banknum,
|
|||
fluid_list_t *list;
|
||||
int ofs;
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont list, bank offset list and sfont */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next (list)) {
|
||||
sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
|
||||
|
@ -2181,7 +2255,7 @@ fluid_synth_find_preset(fluid_synth_t* synth, unsigned int banknum,
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
return preset;
|
||||
}
|
||||
|
@ -2483,9 +2557,9 @@ fluid_synth_get_gain(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex);
|
||||
fluid_rec_mutex_lock (synth->mutex);
|
||||
gain = synth->gain;
|
||||
fluid_mutex_unlock (synth->mutex);
|
||||
fluid_rec_mutex_unlock (synth->mutex);
|
||||
|
||||
return (gain);
|
||||
}
|
||||
|
@ -2511,7 +2585,7 @@ int
|
|||
fluid_synth_set_polyphony(fluid_synth_t* synth, int polyphony)
|
||||
{
|
||||
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (polyphony >= 1 && polyphony <= synth->nvoice, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (polyphony >= 16 && polyphony <= synth->nvoice, FLUID_FAILED);
|
||||
|
||||
if (fluid_synth_should_queue (synth))
|
||||
return fluid_synth_queue_int_event (synth, FLUID_EVENT_QUEUE_ELEM_POLYPHONY,
|
||||
|
@ -2923,7 +2997,8 @@ fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin,
|
|||
static int
|
||||
fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out)
|
||||
{
|
||||
int i, auchan;
|
||||
fluid_real_t local_voice_buf[FLUID_BUFSIZE];
|
||||
int i, auchan, start_index, voice_index;
|
||||
fluid_voice_t* voice;
|
||||
fluid_real_t* left_buf;
|
||||
fluid_real_t* right_buf;
|
||||
|
@ -2931,6 +3006,8 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out)
|
|||
fluid_real_t* chorus_buf;
|
||||
int byte_size = FLUID_BUFSIZE * sizeof(fluid_real_t);
|
||||
double prof_ref = fluid_profile_ref();
|
||||
double prof_ref_voice;
|
||||
int count;
|
||||
|
||||
/* Assign ID of synthesis thread, if not already set */
|
||||
if (synth->synth_thread_id == FLUID_THREAD_ID_NULL)
|
||||
|
@ -2970,12 +3047,99 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out)
|
|||
|
||||
fluid_profile(FLUID_PROF_ONE_BLOCK_CLEAR, prof_ref);
|
||||
|
||||
/* call all playing synthesis processes */
|
||||
for (i = 0; i < synth->polyphony; i++) {
|
||||
voice = synth->voice[i];
|
||||
if (synth->cores > 1)
|
||||
{
|
||||
/* Look for first active voice to process */
|
||||
for (voice_index = 0; voice_index < synth->polyphony; voice_index++)
|
||||
{
|
||||
voice = synth->voice[voice_index];
|
||||
if (_PLAYING (voice)) break;
|
||||
}
|
||||
|
||||
if (_PLAYING(voice)) {
|
||||
double prof_ref_voice = fluid_profile_ref();
|
||||
/* Was there a voice to process? */
|
||||
if (voice_index < synth->polyphony)
|
||||
{
|
||||
fluid_cond_mutex_lock (synth->core_mutex); /* ++ Lock core variables */
|
||||
|
||||
synth->core_voice_index = voice_index + 1; /* Set the next core_voice_index */
|
||||
|
||||
/* Tell the other core threads that there is work to do */
|
||||
synth->core_work = TRUE;
|
||||
synth->core_waiting_for_last = FALSE;
|
||||
fluid_cond_broadcast (synth->core_cond);
|
||||
|
||||
fluid_cond_mutex_unlock (synth->core_mutex); /* -- Unlock core variables */
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
got_voice: /* We got a voice to process */
|
||||
count = fluid_voice_write (voice, &synth->core_bufs[voice_index * FLUID_BUFSIZE]);
|
||||
|
||||
if (count > 0) synth->core_voice_processed[voice_index] = voice;
|
||||
|
||||
/* Look for next active voice to process (in a lock free manner) */
|
||||
do
|
||||
{
|
||||
voice_index = fluid_atomic_int_get (&synth->core_voice_index);
|
||||
|
||||
for (start_index = voice_index; voice_index < synth->polyphony; voice_index++)
|
||||
{
|
||||
voice = synth->voice[voice_index];
|
||||
|
||||
if (_PLAYING (voice))
|
||||
{
|
||||
if (fluid_atomic_int_compare_and_exchange (&synth->core_voice_index,
|
||||
start_index, voice_index + 1))
|
||||
goto got_voice;
|
||||
|
||||
break; /* compare and exchange failed (another thread grabbed the voice first) */
|
||||
}
|
||||
}
|
||||
}
|
||||
while (voice_index < synth->polyphony);
|
||||
|
||||
/* No more voices to process */
|
||||
fluid_cond_mutex_lock (synth->core_mutex); /* ++ Lock core variables */
|
||||
synth->core_work = FALSE;
|
||||
|
||||
/* If there are still other core threads in progress, wait for last one */
|
||||
if (synth->core_inprogress > 0)
|
||||
{
|
||||
synth->core_waiting_for_last = TRUE;
|
||||
|
||||
while (synth->core_inprogress > 0)
|
||||
fluid_cond_wait (synth->core_wait_last_cond, synth->core_mutex);
|
||||
}
|
||||
|
||||
fluid_cond_mutex_unlock (synth->core_mutex); /* -- Unlock core variables */
|
||||
break; /* We're done */
|
||||
} /* while (TRUE) - Process voices loop */
|
||||
|
||||
/* Mix all voices */
|
||||
for (i = 0; i < synth->polyphony; i++)
|
||||
{
|
||||
voice = synth->core_voice_processed[i];
|
||||
if (!voice) continue;
|
||||
|
||||
synth->core_voice_processed[i] = NULL;
|
||||
|
||||
auchan = fluid_channel_get_num (fluid_voice_get_channel (voice));
|
||||
auchan %= synth->audio_groups;
|
||||
left_buf = synth->left_buf[auchan];
|
||||
right_buf = synth->right_buf[auchan];
|
||||
|
||||
fluid_voice_mix (voice, left_buf, right_buf, reverb_buf, chorus_buf);
|
||||
} /* while (TRUE) - Mix processed voices loop */
|
||||
} /* if (i < synth->polyphony) - Are there any voices to process? */
|
||||
}
|
||||
else /* synth->cores < 1 - Not multi-core enabled */
|
||||
{
|
||||
/* call all playing synthesis processes */
|
||||
for (i = 0; i < synth->polyphony; i++) {
|
||||
voice = synth->voice[i];
|
||||
if (!_PLAYING(voice)) continue;
|
||||
|
||||
prof_ref_voice = fluid_profile_ref();
|
||||
|
||||
/* The output associated with a MIDI channel is wrapped around
|
||||
* using the number of audio groups as modulo divider. This is
|
||||
|
@ -2994,7 +3158,8 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out)
|
|||
left_buf = synth->left_buf[auchan];
|
||||
right_buf = synth->right_buf[auchan];
|
||||
|
||||
fluid_voice_write(voice, left_buf, right_buf, reverb_buf, chorus_buf);
|
||||
fluid_voice_write (voice, local_voice_buf);
|
||||
fluid_voice_mix (voice, left_buf, right_buf, reverb_buf, chorus_buf);
|
||||
|
||||
fluid_profile(FLUID_PROF_ONE_BLOCK_VOICE, prof_ref_voice);
|
||||
}
|
||||
|
@ -3066,6 +3231,84 @@ fluid_synth_one_block(fluid_synth_t* synth, int do_not_mix_fx_to_out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Core thread function (processes voices in parallel to primary synthesis thread) */
|
||||
static void
|
||||
fluid_synth_core_thread_func (void* data)
|
||||
{
|
||||
fluid_synth_t *synth = data;
|
||||
fluid_voice_t *voice;
|
||||
int i, count, start_index;
|
||||
|
||||
/* We do this, rather than adding an "if (first_run)" statement to the while loop */
|
||||
fluid_cond_mutex_lock (synth->core_mutex); /* ++ Lock core variables */
|
||||
synth->core_inprogress++;
|
||||
fluid_cond_mutex_unlock (synth->core_mutex); /* -- Unlock core variables */
|
||||
|
||||
/* Loop until delete_fluid_synth() kills off core threads */
|
||||
while (synth->cores_active)
|
||||
{
|
||||
fluid_cond_mutex_lock (synth->core_mutex); /* ++ Lock core variables */
|
||||
|
||||
synth->core_inprogress--;
|
||||
|
||||
/* Wakeup primary synthesis thread if it is waiting for last and we are it */
|
||||
if (synth->core_waiting_for_last && synth->core_inprogress == 0)
|
||||
fluid_cond_signal (synth->core_wait_last_cond);
|
||||
|
||||
/* Wait until there is core work */
|
||||
while (!synth->core_work && synth->cores_active)
|
||||
fluid_cond_wait (synth->core_cond, synth->core_mutex);
|
||||
|
||||
if (!synth->cores_active)
|
||||
{
|
||||
fluid_cond_mutex_unlock (synth->core_mutex); /* -- Unlock core variables */
|
||||
break;
|
||||
}
|
||||
|
||||
synth->core_inprogress++;
|
||||
|
||||
fluid_cond_mutex_unlock (synth->core_mutex); /* -- Unlock core variables */
|
||||
|
||||
/* Voice processing loop (lock free) */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Look for next active voice to process (in a lock free manner) */
|
||||
do
|
||||
{
|
||||
i = fluid_atomic_int_get (&synth->core_voice_index);
|
||||
|
||||
for (start_index = i; i < synth->polyphony; i++)
|
||||
{
|
||||
voice = synth->voice[i];
|
||||
|
||||
if (_PLAYING (voice))
|
||||
{
|
||||
if (fluid_atomic_int_compare_and_exchange (&synth->core_voice_index,
|
||||
start_index, i + 1))
|
||||
goto got_voice;
|
||||
|
||||
break; /* compare and exchange failed (another thread grabbed the voice first) */
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i < synth->polyphony);
|
||||
|
||||
/* No more voices to process */
|
||||
fluid_atomic_int_set (&synth->core_voice_index, synth->polyphony);
|
||||
fluid_atomic_int_set (&synth->core_work, FALSE);
|
||||
break;
|
||||
|
||||
got_voice:
|
||||
|
||||
/* Synthesize the voice */
|
||||
count = fluid_voice_write (voice, &synth->core_bufs[i * FLUID_BUFSIZE]);
|
||||
|
||||
/* Assign the processed voice to the same voicebuf index (if there was any audio) */
|
||||
if (count > 0) synth->core_voice_processed[i] = voice;
|
||||
} /* while (TRUE) - Lock free voice processing loop */
|
||||
} /* while (synth->cores_active) */
|
||||
}
|
||||
|
||||
/* Process events in an event queue */
|
||||
static FLUID_INLINE void
|
||||
fluid_synth_process_event_queue_LOCAL (fluid_synth_t *synth,
|
||||
|
@ -3401,9 +3644,9 @@ fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader)
|
|||
sfont_already_loaded = synth->sfont_info != NULL;
|
||||
fluid_return_if_fail (!sfont_already_loaded);
|
||||
|
||||
fluid_mutex_lock (synth->mutex);
|
||||
fluid_rec_mutex_lock (synth->mutex);
|
||||
synth->loaders = fluid_list_prepend(synth->loaders, loader);
|
||||
fluid_mutex_unlock (synth->mutex);
|
||||
fluid_rec_mutex_unlock (synth->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3445,11 +3688,11 @@ fluid_synth_sfload(fluid_synth_t* synth, const char* filename, int reset_presets
|
|||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock sfont_id and sfont list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock sfont_id and sfont list */
|
||||
sfont->id = sfont_id = ++synth->sfont_id;
|
||||
synth->sfont_info = fluid_list_prepend(synth->sfont_info, sfont_info); /* prepend to list */
|
||||
fluid_hashtable_insert (synth->sfont_hash, sfont, sfont_info); /* Hash sfont->sfont_info */
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
/* reset the presets for all channels if requested */
|
||||
if (reset_presets) fluid_synth_program_reset(synth);
|
||||
|
@ -3500,7 +3743,7 @@ fluid_synth_sfunload(fluid_synth_t* synth, unsigned int id, int reset_presets)
|
|||
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
|
||||
|
||||
/* remove the SoundFont from the list */
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock sfont list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock sfont list */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
|
||||
sfont_info = (fluid_sfont_info_t*) fluid_list_get(list);
|
||||
|
@ -3512,7 +3755,7 @@ fluid_synth_sfunload(fluid_synth_t* synth, unsigned int id, int reset_presets)
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
if (!list) {
|
||||
FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
|
||||
|
@ -3536,7 +3779,7 @@ fluid_synth_sfont_unref (fluid_synth_t *synth, fluid_sfont_t *sfont)
|
|||
fluid_sfont_info_t *sfont_info;
|
||||
int refcount = 0;
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock sfont_hash */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock sfont_hash */
|
||||
|
||||
sfont_info = fluid_hashtable_lookup (synth->sfont_hash, sfont);
|
||||
|
||||
|
@ -3549,7 +3792,7 @@ fluid_synth_sfont_unref (fluid_synth_t *synth, fluid_sfont_t *sfont)
|
|||
fluid_hashtable_remove (synth->sfont_hash, sfont_info->sfont);
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock sfont_hash */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock sfont_hash */
|
||||
|
||||
fluid_return_if_fail (sfont_info != NULL); /* Shouldn't happen, programming error if so */
|
||||
|
||||
|
@ -3598,7 +3841,7 @@ fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont list */
|
||||
|
||||
/* Search for SoundFont and get its index */
|
||||
for (list = synth->sfont_info, index = 0; list; list = fluid_list_next (list), index++) {
|
||||
|
@ -3607,7 +3850,7 @@ fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id)
|
|||
}
|
||||
|
||||
if (!list) {
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
FLUID_LOG(FLUID_ERR, "No SoundFont with id = %d", id);
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
@ -3615,7 +3858,7 @@ fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id)
|
|||
/* keep a copy of the SoundFont's filename */
|
||||
FLUID_STRCPY (filename, fluid_sfont_get_name (old_sfont_info->sfont));
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
if (fluid_synth_sfunload (synth, id, FALSE) != FLUID_OK)
|
||||
return FLUID_FAILED;
|
||||
|
@ -3638,10 +3881,10 @@ fluid_synth_sfreload(fluid_synth_t* synth, unsigned int id)
|
|||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock sfont list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock sfont list */
|
||||
synth->sfont_info = fluid_list_insert_at(synth->sfont_info, index, sfont_info); /* insert the sfont at the same index */
|
||||
fluid_hashtable_insert (synth->sfont_hash, sfont, sfont_info); /* Hash sfont->sfont_info */
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
/* reset the presets for all channels */
|
||||
fluid_synth_update_presets(synth);
|
||||
|
@ -3672,11 +3915,11 @@ fluid_synth_add_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont)
|
|||
sfont_info = new_fluid_sfont_info (synth, sfont);
|
||||
if (!sfont_info) return (FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont_id and sfont_info list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont_id and sfont_info list */
|
||||
sfont->id = sfont_id = ++synth->sfont_id;
|
||||
synth->sfont_info = fluid_list_prepend (synth->sfont_info, sfont_info); /* prepend to list */
|
||||
fluid_hashtable_insert (synth->sfont_hash, sfont, sfont_info); /* Hash sfont->sfont_info */
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
/* reset the presets for all channels */
|
||||
fluid_synth_program_reset (synth);
|
||||
|
@ -3705,7 +3948,7 @@ fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont)
|
|||
fluid_return_if_fail (sfont != NULL);
|
||||
|
||||
/* remove the SoundFont from the list */
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock sfont_info list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock sfont_info list */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
|
||||
sfont_info = (fluid_sfont_info_t*) fluid_list_get(list);
|
||||
|
@ -3720,7 +3963,7 @@ fluid_synth_remove_sfont(fluid_synth_t* synth, fluid_sfont_t* sfont)
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
/* reset the presets for all channels */
|
||||
fluid_synth_program_reset (synth);
|
||||
|
@ -3738,9 +3981,9 @@ fluid_synth_sfcount(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
count = fluid_list_size (synth->sfont_info);
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -3762,10 +4005,10 @@ fluid_synth_get_sfont(fluid_synth_t* synth, unsigned int num)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, NULL);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont list */
|
||||
list = fluid_list_nth (synth->sfont_info, num);
|
||||
if (list) sfont = ((fluid_sfont_info_t *)fluid_list_get (list))->sfont;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
return sfont;
|
||||
}
|
||||
|
@ -3787,7 +4030,7 @@ fluid_synth_get_sfont_by_id(fluid_synth_t* synth, unsigned int id)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, NULL);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
|
||||
sfont = ((fluid_sfont_info_t *)fluid_list_get (list))->sfont;
|
||||
|
@ -3795,7 +4038,7 @@ fluid_synth_get_sfont_by_id(fluid_synth_t* synth, unsigned int id)
|
|||
break;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
return list ? sfont : NULL;
|
||||
}
|
||||
|
@ -3818,7 +4061,7 @@ fluid_synth_get_sfont_by_name(fluid_synth_t* synth, char *name)
|
|||
fluid_return_val_if_fail (synth != NULL, NULL);
|
||||
fluid_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
|
||||
sfont = ((fluid_sfont_info_t *)fluid_list_get (list))->sfont;
|
||||
|
@ -3826,7 +4069,7 @@ fluid_synth_get_sfont_by_name(fluid_synth_t* synth, char *name)
|
|||
break;
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
return list ? sfont : NULL;
|
||||
}
|
||||
|
@ -4015,9 +4258,9 @@ fluid_synth_get_reverb_roomsize(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
value = synth->reverb_roomsize;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4034,9 +4277,9 @@ fluid_synth_get_reverb_damp(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
value = synth->reverb_damping;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4053,9 +4296,9 @@ fluid_synth_get_reverb_level(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
value = synth->reverb_level;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4072,9 +4315,9 @@ fluid_synth_get_reverb_width(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock reverb value */
|
||||
value = synth->reverb_width;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4197,9 +4440,9 @@ fluid_synth_get_chorus_nr(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
value = synth->chorus_nr;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4216,9 +4459,9 @@ fluid_synth_get_chorus_level(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
value = synth->chorus_level;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4235,9 +4478,9 @@ fluid_synth_get_chorus_speed_Hz(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
value = synth->chorus_speed;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4254,9 +4497,9 @@ fluid_synth_get_chorus_depth_ms(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
value = synth->chorus_depth;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4273,9 +4516,9 @@ fluid_synth_get_chorus_type(fluid_synth_t* synth)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0.0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock chorus value */
|
||||
value = synth->chorus_type;
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock */
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -4599,7 +4842,7 @@ fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog,
|
|||
fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
|
||||
tuning = new_fluid_tuning (name, bank, prog);
|
||||
|
||||
|
@ -4611,7 +4854,7 @@ fluid_synth_activate_key_tuning(fluid_synth_t* synth, int bank, int prog,
|
|||
}
|
||||
else retval = FLUID_FAILED;
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -4665,7 +4908,7 @@ fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog,
|
|||
fluid_return_val_if_fail (name != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (pitch != NULL, FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
|
||||
tuning = new_fluid_tuning (name, bank, prog);
|
||||
|
||||
|
@ -4677,7 +4920,7 @@ fluid_synth_activate_octave_tuning(fluid_synth_t* synth, int bank, int prog,
|
|||
}
|
||||
else retval = FLUID_FAILED;
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -4714,7 +4957,7 @@ fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog,
|
|||
fluid_return_val_if_fail (key != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (pitch != NULL, FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
|
||||
old_tuning = fluid_synth_get_tuning (synth, bank, prog);
|
||||
|
||||
|
@ -4732,7 +4975,7 @@ fluid_synth_tune_notes(fluid_synth_t* synth, int bank, int prog,
|
|||
}
|
||||
else retval = FLUID_FAILED;
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -4786,7 +5029,7 @@ fluid_synth_activate_tuning(fluid_synth_t* synth, int chan, int bank, int prog,
|
|||
fluid_return_val_if_fail (bank >= 0 && bank < 128, FLUID_FAILED);
|
||||
fluid_return_val_if_fail (prog >= 0 && prog < 128, FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ Lock tunings */
|
||||
|
||||
tuning = fluid_synth_get_tuning (synth, bank, prog);
|
||||
|
||||
|
@ -4800,7 +5043,7 @@ fluid_synth_activate_tuning(fluid_synth_t* synth, int chan, int bank, int prog,
|
|||
|
||||
if (tuning) fluid_tuning_ref (tuning); /* ++ ref for outside of lock */
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- Unlock tunings */
|
||||
|
||||
if (!tuning) return (FLUID_FAILED);
|
||||
|
||||
|
@ -4957,11 +5200,11 @@ fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog)
|
|||
b = (p >> 8) & 0xFF;
|
||||
p &= 0xFF;
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock tunings */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock tunings */
|
||||
|
||||
if (!synth->tuning)
|
||||
{
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock tunings */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4981,12 +5224,12 @@ fluid_synth_tuning_iteration_next(fluid_synth_t* synth, int* bank, int* prog)
|
|||
else fluid_private_set (synth->tuning_iter,
|
||||
FLUID_INT_TO_POINTER ((b + 1) << 8), NULL);
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock tunings */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock tunings */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5007,7 +5250,7 @@ fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog,
|
|||
{
|
||||
fluid_tuning_t* tuning;
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock tunings */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock tunings */
|
||||
|
||||
tuning = fluid_synth_get_tuning (synth, bank, prog);
|
||||
|
||||
|
@ -5023,7 +5266,7 @@ fluid_synth_tuning_dump(fluid_synth_t* synth, int bank, int prog,
|
|||
FLUID_MEMCPY (pitch, fluid_tuning_get_all (tuning), 128 * sizeof (double));
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* unlock tunings */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* unlock tunings */
|
||||
|
||||
return tuning ? FLUID_OK : FLUID_FAILED;
|
||||
}
|
||||
|
@ -5228,6 +5471,7 @@ fluid_synth_set_gen2(fluid_synth_t* synth, int chan, int param,
|
|||
* @param param SoundFont generator ID (#fluid_gen_type)
|
||||
* @return Current generator value assigned to MIDI channel
|
||||
*/
|
||||
/* FIXME - Not currently SMP multi-thread safe (need atomic set/get of gen) */
|
||||
float
|
||||
fluid_synth_get_gen(fluid_synth_t* synth, int chan, int param)
|
||||
{
|
||||
|
@ -5379,7 +5623,7 @@ fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
|
||||
sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
|
||||
|
@ -5391,7 +5635,7 @@ fluid_synth_set_bank_offset(fluid_synth_t* synth, int sfont_id, int offset)
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
if (!list)
|
||||
{
|
||||
|
@ -5417,7 +5661,7 @@ fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id)
|
|||
|
||||
fluid_return_val_if_fail (synth != NULL, 0);
|
||||
|
||||
fluid_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
fluid_rec_mutex_lock (synth->mutex); /* ++ lock sfont_info list */
|
||||
|
||||
for (list = synth->sfont_info; list; list = fluid_list_next(list)) {
|
||||
sfont_info = (fluid_sfont_info_t *)fluid_list_get (list);
|
||||
|
@ -5429,7 +5673,7 @@ fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_id)
|
|||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
fluid_rec_mutex_unlock (synth->mutex); /* -- unlock */
|
||||
|
||||
if (!list)
|
||||
{
|
||||
|
|
|
@ -110,6 +110,8 @@ typedef struct _fluid_sfont_info_t {
|
|||
* left_buf[], right_buf[] (Contents change)
|
||||
* fx_left_buf[], fx_right_buf[] (Contents change)
|
||||
* LADSPA_FxUnit (Contents change)
|
||||
* cores
|
||||
* core_threads[]
|
||||
*
|
||||
* Single thread use only (modify only prior to synthesis):
|
||||
* loaders<>
|
||||
|
@ -152,7 +154,7 @@ struct _fluid_synth_t
|
|||
fluid_private_t thread_queues; /**< Thread private data for event queues for each non-synthesis thread queuing events */
|
||||
fluid_event_queue_t *queues[FLUID_MAX_EVENT_QUEUES]; /**< Thread event queues (NULL for unused elements) */
|
||||
|
||||
fluid_mutex_t mutex; /**< Lock for multi-thread sensitive variables (not used by synthesis process) */
|
||||
fluid_rec_mutex_t mutex; /**< Lock for multi-thread sensitive variables (not used by synthesis process) */
|
||||
fluid_list_t *queue_pool; /**< List of event queues whose threads have been destroyed and which can be re-used */
|
||||
fluid_event_queue_t *return_queue; /**< Event queue for events from synthesis thread to non-synthesis threads (memory frees, etc) */
|
||||
fluid_timer_t *return_queue_timer; /**< Timer thread to process return event queue */
|
||||
|
@ -219,6 +221,23 @@ struct _fluid_synth_t
|
|||
fluid_midi_router_t* midi_router; /**< The midi router. Could be done nicer. */
|
||||
fluid_sample_timer_t* sample_timers; /**< List of timers triggered after a block has been processed */
|
||||
|
||||
int cores; /**< Number of CPU cores (1 by default) */
|
||||
fluid_thread_t **core_threads; /**< Array of core threads (cores - 1 in length) */
|
||||
unsigned char cores_active; /**< TRUE if core slave threads should remain active, FALSE to terminate them */
|
||||
|
||||
/* Multi-core variables (protected by core_mutex) */
|
||||
fluid_cond_mutex_t *core_mutex; /**< Mutex to protect all core_ variables and use with core_cond and core_wait_last_cond */
|
||||
fluid_cond_t *core_cond; /**< Thread condition for signaling core slave threads */
|
||||
int core_work; /**< Boolean: TRUE if there is work, FALSE otherwise */
|
||||
|
||||
/* Used in a lockless atomic fashion */
|
||||
int core_voice_index; /**< Next voice index to process */
|
||||
fluid_voice_t **core_voice_processed; /**< Array for processed voices */
|
||||
fluid_real_t *core_bufs; /**< Block containing audio buffers for each voice (FLUID_BUFSIZE in length each) */
|
||||
int core_inprogress; /**< Count of secondary core threads in progress */
|
||||
int core_waiting_for_last; /**< Boolean: Set to TRUE if primary synthesis thread is waiting for last slave thread to finish */
|
||||
fluid_cond_t *core_wait_last_cond; /**< Thread condition for signaling primary synthesis thread when last slave thread finishes */
|
||||
|
||||
#ifdef LADSPA
|
||||
fluid_LADSPA_FxUnit_t* LADSPA_FxUnit; /**< Effects unit for LADSPA support */
|
||||
#endif
|
||||
|
|
|
@ -364,6 +364,13 @@ fluid_utime (void)
|
|||
/* */
|
||||
/*=============================================================*/
|
||||
|
||||
void
|
||||
fluid_thread_self_set_prio (fluid_thread_prio_t prio, int prio_level)
|
||||
{
|
||||
if (prio == FLUID_THREAD_PRIO_HIGH)
|
||||
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Timer
|
||||
|
@ -488,6 +495,13 @@ fluid_timer_join(fluid_timer_t* timer)
|
|||
/* */
|
||||
/*=============================================================*/
|
||||
|
||||
void
|
||||
fluid_thread_self_set_prio (fluid_thread_prio_t prio, int prio_level)
|
||||
{
|
||||
if (prio == FLUID_THREAD_PRIO_HIGH)
|
||||
DosSetPriority (PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Timer
|
||||
|
@ -610,6 +624,19 @@ fluid_timer_join(fluid_timer_t* timer)
|
|||
/* */
|
||||
/*=============================================================*/
|
||||
|
||||
void
|
||||
fluid_thread_self_set_prio (fluid_thread_prio_t prio, int prio_level)
|
||||
{
|
||||
struct sched_param priority;
|
||||
|
||||
if (prio == FLUID_THREAD_PRIO_HIGH)
|
||||
{
|
||||
priority.sched_priority = prio_level;
|
||||
|
||||
if (pthread_setschedparam (pthread_self (), SCHED_FIFO, &priority) != 0)
|
||||
FLUID_LOG(FLUID_WARN, "Failed to set thread to high priority");
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
|
@ -871,16 +898,61 @@ void fluid_profiling_print(void)
|
|||
*
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fluid_thread_func_t func;
|
||||
void *data;
|
||||
int prio_level;
|
||||
} fluid_thread_info_t;
|
||||
|
||||
static gpointer
|
||||
fluid_thread_high_prio (gpointer data)
|
||||
{
|
||||
fluid_thread_info_t *info = data;
|
||||
|
||||
fluid_thread_self_set_prio (FLUID_THREAD_PRIO_HIGH, info->prio_level);
|
||||
|
||||
info->func (info->data);
|
||||
FLUID_FREE (info);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new thread.
|
||||
* @param func Function to execute in new thread context
|
||||
* @param data User defined data to pass to func
|
||||
* @param prio Priority class
|
||||
* @param prio_level Priority level (used only for high priority on Posix currently, 1-99)
|
||||
* @param detach If TRUE, 'join' does not work and the thread destroys itself when finished.
|
||||
* @return New thread pointer or NULL on error
|
||||
*/
|
||||
fluid_thread_t *
|
||||
new_fluid_thread (fluid_thread_func_t func, void *data, int detach)
|
||||
new_fluid_thread (fluid_thread_func_t func, void *data,
|
||||
fluid_thread_prio_t prio, int prio_level, int detach)
|
||||
{
|
||||
GThread *thread;
|
||||
fluid_thread_info_t *info;
|
||||
GError *err = NULL;
|
||||
|
||||
g_return_val_if_fail (func != NULL, NULL);
|
||||
|
||||
thread = g_thread_create ((GThreadFunc)func, data, detach == FALSE, &err);
|
||||
if (prio == FLUID_THREAD_PRIO_HIGH)
|
||||
{
|
||||
info = FLUID_NEW (fluid_thread_info_t);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->func = func;
|
||||
info->data = data;
|
||||
info->prio_level = prio_level;
|
||||
thread = g_thread_create (fluid_thread_high_prio, info, detach == FALSE, &err);
|
||||
}
|
||||
else thread = g_thread_create ((GThreadFunc)func, data, detach == FALSE, &err);
|
||||
|
||||
if (!thread)
|
||||
{
|
||||
|
@ -892,12 +964,23 @@ new_fluid_thread (fluid_thread_func_t func, void *data, int detach)
|
|||
return thread;
|
||||
}
|
||||
|
||||
int delete_fluid_thread(fluid_thread_t* thread)
|
||||
/**
|
||||
* Frees data associated with a thread (does not actually stop thread).
|
||||
* @param thread Thread to free
|
||||
*/
|
||||
void
|
||||
delete_fluid_thread(fluid_thread_t* thread)
|
||||
{
|
||||
return FLUID_OK;
|
||||
/* Threads free themselves when they quit, nothing to do */
|
||||
}
|
||||
|
||||
int fluid_thread_join(fluid_thread_t* thread)
|
||||
/**
|
||||
* Join a thread (wait for it to terminate).
|
||||
* @param thread Thread to join
|
||||
* @return FLUID_OK
|
||||
*/
|
||||
int
|
||||
fluid_thread_join(fluid_thread_t* thread)
|
||||
{
|
||||
g_thread_join (thread);
|
||||
|
||||
|
@ -1136,7 +1219,8 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
|
|||
server_socket->data = data;
|
||||
server_socket->cont = 1;
|
||||
|
||||
server_socket->thread = new_fluid_thread(fluid_server_socket_run, server_socket, 0);
|
||||
server_socket->thread = new_fluid_thread(fluid_server_socket_run, server_socket,
|
||||
FLUID_THREAD_PRIO_NORMAL, 0, FALSE);
|
||||
if (server_socket->thread == NULL) {
|
||||
FLUID_FREE(server_socket);
|
||||
fluid_socket_close(sock);
|
||||
|
|
|
@ -122,18 +122,38 @@ int delete_fluid_timer(fluid_timer_t* timer);
|
|||
int fluid_timer_join(fluid_timer_t* timer);
|
||||
int fluid_timer_stop(fluid_timer_t* timer);
|
||||
|
||||
/**
|
||||
/* Muteces */
|
||||
|
||||
Muteces
|
||||
/* Regular mutex */
|
||||
typedef GStaticMutex fluid_mutex_t;
|
||||
#define fluid_mutex_init(_m) g_static_mutex_init(&(_m))
|
||||
#define fluid_mutex_destroy(_m) g_static_mutex_free(&(_m))
|
||||
#define fluid_mutex_lock(_m) g_static_mutex_lock(&(_m))
|
||||
#define fluid_mutex_unlock(_m) g_static_mutex_unlock(&(_m))
|
||||
|
||||
*/
|
||||
/* Recursive lock capable mutex */
|
||||
typedef GStaticRecMutex fluid_rec_mutex_t;
|
||||
#define fluid_rec_mutex_init(_m) g_static_rec_mutex_init(&(_m))
|
||||
#define fluid_rec_mutex_destroy(_m) g_static_rec_mutex_free(&(_m))
|
||||
#define fluid_rec_mutex_lock(_m) g_static_rec_mutex_lock(&(_m))
|
||||
#define fluid_rec_mutex_unlock(_m) g_static_rec_mutex_unlock(&(_m))
|
||||
|
||||
/* Recursive locks allowed */
|
||||
typedef GStaticRecMutex fluid_mutex_t;
|
||||
#define fluid_mutex_init(_m) g_static_rec_mutex_init(&(_m))
|
||||
#define fluid_mutex_destroy(_m) g_static_rec_mutex_free(&(_m))
|
||||
#define fluid_mutex_lock(_m) g_static_rec_mutex_lock(&(_m))
|
||||
#define fluid_mutex_unlock(_m) g_static_rec_mutex_unlock(&(_m))
|
||||
/* Dynamically allocated mutex suitable for fluid_cond_t use */
|
||||
typedef GMutex fluid_cond_mutex_t;
|
||||
#define new_fluid_cond_mutex g_mutex_new
|
||||
#define delete_fluid_cond_mutex g_mutex_free
|
||||
#define fluid_cond_mutex_lock g_mutex_lock
|
||||
#define fluid_cond_mutex_unlock g_mutex_unlock
|
||||
|
||||
|
||||
/* Thread condition signaling */
|
||||
|
||||
typedef GCond fluid_cond_t;
|
||||
#define new_fluid_cond g_cond_new
|
||||
#define delete_fluid_cond g_cond_free
|
||||
#define fluid_cond_signal g_cond_signal
|
||||
#define fluid_cond_broadcast g_cond_broadcast
|
||||
#define fluid_cond_wait g_cond_wait
|
||||
|
||||
|
||||
/* Atomic operations */
|
||||
|
@ -148,7 +168,8 @@ typedef GStaticRecMutex fluid_mutex_t;
|
|||
#define fluid_atomic_int_exchange_and_add(_pi, _add) \
|
||||
g_atomic_int_exchange_and_add(_pi, _add)
|
||||
|
||||
#define fluid_atomic_pointer_get(_pp) g_atomic_pointer_get(_pp)
|
||||
#define fluid_atomic_pointer_get(_pp) g_atomic_pointer_get(_pp)
|
||||
#define fluid_atomic_pointer_set(_pp, val) g_atomic_pointer_set(_pp, val)
|
||||
#define fluid_atomic_pointer_compare_and_exchange(_pp, _old, _new) \
|
||||
g_atomic_pointer_compare_and_exchange(_pp, _old, _new)
|
||||
|
||||
|
@ -180,37 +201,40 @@ typedef GStaticPrivate fluid_private_t;
|
|||
#define fluid_private_free(_priv) g_static_private_free(&(_priv))
|
||||
|
||||
|
||||
/**
|
||||
Threads
|
||||
|
||||
*/
|
||||
/* Threads */
|
||||
|
||||
typedef GThread fluid_thread_t;
|
||||
typedef void (*fluid_thread_func_t)(void* data);
|
||||
|
||||
/** When detached, 'join' does not work and the thread destroys itself
|
||||
when finished. */
|
||||
fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void* data, int detach);
|
||||
int delete_fluid_thread(fluid_thread_t* thread);
|
||||
int fluid_thread_join(fluid_thread_t* thread);
|
||||
/**
|
||||
* Thread priorities.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FLUID_THREAD_PRIO_NORMAL, /**< Normal thread priority */
|
||||
FLUID_THREAD_PRIO_HIGH /**< High priority thread */
|
||||
} fluid_thread_prio_t;
|
||||
|
||||
#define FLUID_THREAD_ID_NULL NULL /* A NULL "ID" value */
|
||||
#define fluid_thread_id_t GThread * /* Data type for a thread ID */
|
||||
#define fluid_thread_get_id() g_thread_self() /* Get unique "ID" for current thread */
|
||||
|
||||
/**
|
||||
Sockets and I/O
|
||||
fluid_thread_t* new_fluid_thread(fluid_thread_func_t func, void *data,
|
||||
fluid_thread_prio_t prio, int prio_level, int detach);
|
||||
void delete_fluid_thread(fluid_thread_t* thread);
|
||||
void fluid_thread_self_set_prio (fluid_thread_prio_t prio, int prio_level);
|
||||
int fluid_thread_join(fluid_thread_t* thread);
|
||||
|
||||
*/
|
||||
/* Sockets and I/O */
|
||||
|
||||
fluid_istream_t fluid_get_stdin (void);
|
||||
fluid_ostream_t fluid_get_stdout (void);
|
||||
int fluid_istream_readline(fluid_istream_t in, char* prompt, char* buf, int len);
|
||||
int fluid_ostream_printf (fluid_ostream_t out, char* format, ...);
|
||||
|
||||
/** The function should return 0 if no error occured, non-zero
|
||||
otherwise. If the function return non-zero, the socket will be
|
||||
closed by the server. */
|
||||
/* The function should return 0 if no error occured, non-zero
|
||||
otherwise. If the function return non-zero, the socket will be
|
||||
closed by the server. */
|
||||
typedef int (*fluid_server_func_t)(void* data, fluid_socket_t client_socket, char* addr);
|
||||
|
||||
fluid_server_socket_t* new_fluid_server_socket(int port, fluid_server_func_t func, void* data);
|
||||
|
@ -222,17 +246,14 @@ fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
|
|||
|
||||
|
||||
|
||||
/**
|
||||
/* Profiling */
|
||||
|
||||
Profiling
|
||||
|
||||
/**
|
||||
* Profile numbers. List all the pieces of code you want to profile
|
||||
* here. Be sure to add an entry in the fluid_profile_data table in
|
||||
* fluid_sys.c
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
Profile numbers. List all the pieces of code you want to profile
|
||||
here. Be sure to add an entry in the fluid_profile_data table in
|
||||
fluid_sys.c
|
||||
*/
|
||||
enum {
|
||||
FLUID_PROF_WRITE_S16,
|
||||
FLUID_PROF_ONE_BLOCK,
|
||||
|
|
|
@ -48,11 +48,7 @@
|
|||
static int fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice);
|
||||
static int calculate_hold_decay_buffers(fluid_voice_t* voice, int gen_base,
|
||||
int gen_key2base, int is_decay);
|
||||
static inline void fluid_voice_effects (fluid_voice_t *voice, int count,
|
||||
fluid_real_t* dsp_left_buf,
|
||||
fluid_real_t* dsp_right_buf,
|
||||
fluid_real_t* dsp_reverb_buf,
|
||||
fluid_real_t* dsp_chorus_buf);
|
||||
static inline void fluid_voice_filter (fluid_voice_t *voice);
|
||||
static fluid_real_t
|
||||
fluid_voice_get_lower_boundary_for_attenuation(fluid_voice_t* voice);
|
||||
static void fluid_voice_check_sample_sanity(fluid_voice_t* voice);
|
||||
|
@ -236,44 +232,38 @@ fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* fluid_voice_write
|
||||
/**
|
||||
* Synthesize a voice to a buffer.
|
||||
*
|
||||
* This is where it all happens. This function is called by the
|
||||
* synthesizer to generate the sound samples. The synthesizer passes
|
||||
* four audio buffers: left, right, reverb out, and chorus out.
|
||||
* @param voice Voice to synthesize
|
||||
* @param dsp_buf Audio buffer to synthesize to (#FLUID_BUFSIZE in length)
|
||||
* @return Count of samples written to dsp_buf (can be 0)
|
||||
*
|
||||
* The biggest part of this function sets the correct values for all
|
||||
* the dsp parameters (all the control data boil down to only a few
|
||||
* dsp parameters). The dsp routine is #included in several places (fluid_dsp_core.c).
|
||||
* Panning, reverb and chorus are processed separately. The dsp interpolation
|
||||
* routine is in (fluid_dsp_float.c).
|
||||
*/
|
||||
int
|
||||
fluid_voice_write(fluid_voice_t* voice,
|
||||
fluid_real_t* dsp_left_buf, fluid_real_t* dsp_right_buf,
|
||||
fluid_real_t* dsp_reverb_buf, fluid_real_t* dsp_chorus_buf)
|
||||
fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf)
|
||||
{
|
||||
unsigned int i;
|
||||
fluid_real_t incr;
|
||||
fluid_real_t fres;
|
||||
fluid_real_t target_amp; /* target amplitude */
|
||||
int count;
|
||||
|
||||
int dsp_interp_method = voice->interp_method;
|
||||
|
||||
fluid_real_t dsp_buf[FLUID_BUFSIZE];
|
||||
fluid_env_data_t* env_data;
|
||||
fluid_real_t x;
|
||||
int count = 0;
|
||||
|
||||
|
||||
/* make sure we're playing and that we have sample data */
|
||||
if (!_PLAYING(voice)) return FLUID_OK;
|
||||
/* Other routines (such as fluid_voice_effects) use the last dsp_buf assigned */
|
||||
voice->dsp_buf = dsp_buf;
|
||||
voice->dsp_buf_count = 0;
|
||||
|
||||
/******************* sample **********************/
|
||||
|
||||
if (voice->sample == NULL)
|
||||
{
|
||||
fluid_voice_off(voice);
|
||||
return FLUID_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fluid_check_fpe ("voice_write startup");
|
||||
|
@ -319,7 +309,7 @@ fluid_voice_write(fluid_voice_t* voice,
|
|||
{
|
||||
fluid_profile (FLUID_PROF_VOICE_RELEASE, voice->ref);
|
||||
fluid_voice_off (voice);
|
||||
return FLUID_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fluid_check_fpe ("voice_write vol env");
|
||||
|
@ -593,8 +583,6 @@ fluid_voice_write(fluid_voice_t* voice,
|
|||
* Depending on the position in the loop and the loop size, this
|
||||
* may require several runs. */
|
||||
|
||||
voice->dsp_buf = dsp_buf;
|
||||
|
||||
switch (voice->interp_method)
|
||||
{
|
||||
case FLUID_INTERP_NONE:
|
||||
|
@ -614,9 +602,10 @@ fluid_voice_write(fluid_voice_t* voice,
|
|||
|
||||
fluid_check_fpe ("voice_write interpolation");
|
||||
|
||||
if (count > 0)
|
||||
fluid_voice_effects (voice, count, dsp_left_buf, dsp_right_buf,
|
||||
dsp_reverb_buf, dsp_chorus_buf);
|
||||
voice->dsp_buf_count = count;
|
||||
|
||||
/* Apply filter */
|
||||
if (count > 0) fluid_voice_filter (voice);
|
||||
|
||||
/* turn off voice if short count (sample ended and not looping) */
|
||||
if (count < FLUID_BUFSIZE)
|
||||
|
@ -628,27 +617,19 @@ fluid_voice_write(fluid_voice_t* voice,
|
|||
post_process:
|
||||
voice->ticks += FLUID_BUFSIZE;
|
||||
fluid_check_fpe ("voice_write postprocess");
|
||||
return FLUID_OK;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/* Purpose:
|
||||
*
|
||||
* - filters (applies a lowpass filter with variable cutoff frequency and quality factor)
|
||||
* - mixes the processed sample to left and right output using the pan setting
|
||||
* - sends the processed sample to chorus and reverb
|
||||
*
|
||||
/**
|
||||
* Applies a lowpass filter with variable cutoff frequency and quality factor.
|
||||
* @param voice Voice to apply filter to
|
||||
* @param count Count of samples in voice->dsp_buf
|
||||
*/
|
||||
/*
|
||||
* Variable description:
|
||||
* - dsp_data: Pointer to the original waveform data
|
||||
* - dsp_left_buf: The generated signal goes here, left channel
|
||||
* - dsp_right_buf: right channel
|
||||
* - dsp_reverb_buf: Send to reverb unit
|
||||
* - dsp_chorus_buf: Send to chorus unit
|
||||
* - dsp_a1: Coefficient for the filter
|
||||
* - dsp_a2: same
|
||||
* - dsp_b0: same
|
||||
* - dsp_b1: same
|
||||
* - dsp_b2: same
|
||||
* - dsp_buf: Pointer to the synthesized audio data
|
||||
* - dsp_a1, dsp_a2, dsp_b0, dsp_b1, dsp_b2: Filter coefficients
|
||||
* - voice holds the voice structure
|
||||
*
|
||||
* A couple of variables are used internally, their results are discarded:
|
||||
|
@ -660,12 +641,9 @@ fluid_voice_write(fluid_voice_t* voice,
|
|||
* - dsp_centernode: delay line for the IIR filter
|
||||
* - dsp_hist1: same
|
||||
* - dsp_hist2: same
|
||||
*
|
||||
*/
|
||||
static inline void
|
||||
fluid_voice_effects (fluid_voice_t *voice, int count,
|
||||
fluid_real_t* dsp_left_buf, fluid_real_t* dsp_right_buf,
|
||||
fluid_real_t* dsp_reverb_buf, fluid_real_t* dsp_chorus_buf)
|
||||
fluid_voice_filter (fluid_voice_t *voice)
|
||||
{
|
||||
/* IIR filter sample history */
|
||||
fluid_real_t dsp_hist1 = voice->hist1;
|
||||
|
@ -685,6 +663,7 @@ fluid_voice_effects (fluid_voice_t *voice, int count,
|
|||
fluid_real_t *dsp_buf = voice->dsp_buf;
|
||||
|
||||
fluid_real_t dsp_centernode;
|
||||
int count = voice->dsp_buf_count;
|
||||
int dsp_i;
|
||||
float v;
|
||||
|
||||
|
@ -729,50 +708,6 @@ fluid_voice_effects (fluid_voice_t *voice, int count,
|
|||
}
|
||||
}
|
||||
|
||||
/* pan (Copy the signal to the left and right output buffer) The voice
|
||||
* panning generator has a range of -500 .. 500. If it is centered,
|
||||
* it's close to 0. voice->amp_left and voice->amp_right are then the
|
||||
* same, and we can save one multiplication per voice and sample.
|
||||
*/
|
||||
if ((-0.5 < voice->pan) && (voice->pan < 0.5))
|
||||
{
|
||||
/* The voice is centered. Use voice->amp_left twice. */
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
{
|
||||
v = voice->amp_left * dsp_buf[dsp_i];
|
||||
dsp_left_buf[dsp_i] += v;
|
||||
dsp_right_buf[dsp_i] += v;
|
||||
}
|
||||
}
|
||||
else /* The voice is not centered. Stereo samples have one side zero. */
|
||||
{
|
||||
if (voice->amp_left != 0.0)
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
dsp_left_buf[dsp_i] += voice->amp_left * dsp_buf[dsp_i];
|
||||
}
|
||||
|
||||
if (voice->amp_right != 0.0)
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
dsp_right_buf[dsp_i] += voice->amp_right * dsp_buf[dsp_i];
|
||||
}
|
||||
}
|
||||
|
||||
/* reverb send. Buffer may be NULL. */
|
||||
if ((dsp_reverb_buf != NULL) && (voice->amp_reverb != 0.0))
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
dsp_reverb_buf[dsp_i] += voice->amp_reverb * dsp_buf[dsp_i];
|
||||
}
|
||||
|
||||
/* chorus send. Buffer may be NULL. */
|
||||
if ((dsp_chorus_buf != NULL) && (voice->amp_chorus != 0))
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
dsp_chorus_buf[dsp_i] += voice->amp_chorus * dsp_buf[dsp_i];
|
||||
}
|
||||
|
||||
voice->hist1 = dsp_hist1;
|
||||
voice->hist2 = dsp_hist2;
|
||||
voice->a1 = dsp_a1;
|
||||
|
@ -781,16 +716,76 @@ fluid_voice_effects (fluid_voice_t *voice, int count,
|
|||
voice->b1 = dsp_b1;
|
||||
voice->filter_coeff_incr_count = dsp_filter_coeff_incr_count;
|
||||
|
||||
fluid_check_fpe ("voice_effects");
|
||||
fluid_check_fpe ("voice_filter");
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_voice_get_channel
|
||||
/**
|
||||
* Mix voice data to left/right (panning), reverb and chorus buffers.
|
||||
* @param voice Voice to mix
|
||||
* @param left_buf Left audio buffer
|
||||
* @param right_buf Right audio buffer
|
||||
* @param reverb_buf Reverb buffer
|
||||
* @param chorus_buf Chorus buffer
|
||||
*
|
||||
* NOTE: Uses voice->dsp_buf and voice->dsp_buf_count which were assigned
|
||||
* by fluid_voice_write(). This is therefore meant to be called only after
|
||||
* that function.
|
||||
*/
|
||||
fluid_channel_t*
|
||||
fluid_voice_get_channel(fluid_voice_t* voice)
|
||||
void
|
||||
fluid_voice_mix (fluid_voice_t *voice,
|
||||
fluid_real_t* left_buf, fluid_real_t* right_buf,
|
||||
fluid_real_t* reverb_buf, fluid_real_t* chorus_buf)
|
||||
{
|
||||
return voice->channel;
|
||||
fluid_real_t *dsp_buf = voice->dsp_buf;
|
||||
int count = voice->dsp_buf_count;
|
||||
int dsp_i;
|
||||
float v;
|
||||
|
||||
/* pan (Copy the signal to the left and right output buffer) The voice
|
||||
* panning generator has a range of -500 .. 500. If it is centered,
|
||||
* it's close to 0. voice->amp_left and voice->amp_right are then the
|
||||
* same, and we can save one multiplication per voice and sample.
|
||||
*/
|
||||
if ((-0.5 < voice->pan) && (voice->pan < 0.5))
|
||||
{
|
||||
/* The voice is centered. Use voice->amp_left twice. */
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
{
|
||||
v = voice->amp_left * dsp_buf[dsp_i];
|
||||
left_buf[dsp_i] += v;
|
||||
right_buf[dsp_i] += v;
|
||||
}
|
||||
}
|
||||
else /* The voice is not centered. Stereo samples have one side zero. */
|
||||
{
|
||||
if (voice->amp_left != 0.0)
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
left_buf[dsp_i] += voice->amp_left * dsp_buf[dsp_i];
|
||||
}
|
||||
|
||||
if (voice->amp_right != 0.0)
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
right_buf[dsp_i] += voice->amp_right * dsp_buf[dsp_i];
|
||||
}
|
||||
}
|
||||
|
||||
/* reverb send. Buffer may be NULL. */
|
||||
if ((reverb_buf != NULL) && (voice->amp_reverb != 0.0))
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
reverb_buf[dsp_i] += voice->amp_reverb * dsp_buf[dsp_i];
|
||||
}
|
||||
|
||||
/* chorus send. Buffer may be NULL. */
|
||||
if ((chorus_buf != NULL) && (voice->amp_chorus != 0))
|
||||
{
|
||||
for (dsp_i = 0; dsp_i < count; dsp_i++)
|
||||
chorus_buf[dsp_i] += voice->amp_chorus * dsp_buf[dsp_i];
|
||||
}
|
||||
|
||||
fluid_check_fpe ("voice_mix");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -116,6 +116,7 @@ struct _fluid_voice_t
|
|||
fluid_real_t phase_incr; /* the phase increment for the next 64 samples */
|
||||
fluid_real_t amp_incr; /* amplitude increment value */
|
||||
fluid_real_t *dsp_buf; /* buffer to store interpolated sample data to */
|
||||
int dsp_buf_count; /* Number of audio samples in dsp_buf */
|
||||
|
||||
/* End temporary variables */
|
||||
|
||||
|
@ -219,9 +220,7 @@ int delete_fluid_voice(fluid_voice_t* voice);
|
|||
void fluid_voice_start(fluid_voice_t* voice);
|
||||
void fluid_voice_calculate_gen_pitch(fluid_voice_t* voice);
|
||||
|
||||
int fluid_voice_write(fluid_voice_t* voice,
|
||||
fluid_real_t* left, fluid_real_t* right,
|
||||
fluid_real_t* reverb_buf, fluid_real_t* chorus_buf);
|
||||
int fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf);
|
||||
|
||||
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
|
||||
fluid_channel_t* channel, int key, int vel,
|
||||
|
@ -246,9 +245,14 @@ void fluid_voice_update_param(fluid_voice_t* voice, int gen);
|
|||
|
||||
int fluid_voice_noteoff(fluid_voice_t* voice);
|
||||
int fluid_voice_off(fluid_voice_t* voice);
|
||||
fluid_channel_t* fluid_voice_get_channel(fluid_voice_t* voice);
|
||||
void fluid_voice_mix (fluid_voice_t *voice,
|
||||
fluid_real_t* left_buf, fluid_real_t* right_buf,
|
||||
fluid_real_t* reverb_buf, fluid_real_t* chorus_buf);
|
||||
int fluid_voice_kill_excl(fluid_voice_t* voice);
|
||||
|
||||
#define fluid_voice_get_channel(voice) ((voice)->channel)
|
||||
|
||||
|
||||
#define fluid_voice_set_id(_voice, _id) { (_voice)->id = (_id); }
|
||||
#define fluid_voice_get_chan(_voice) (_voice)->chan
|
||||
|
||||
|
@ -265,7 +269,7 @@ int fluid_voice_kill_excl(fluid_voice_t* voice);
|
|||
#define _SAMPLEMODE(voice) ((int)(voice)->gen[GEN_SAMPLEMODE].val)
|
||||
|
||||
|
||||
/* FIXME - Josh Green - This doesn't seem to be used anywhere */
|
||||
/* FIXME - This doesn't seem to be used anywhere - JG */
|
||||
fluid_real_t fluid_voice_gen_value(fluid_voice_t* voice, int num);
|
||||
|
||||
#define _GEN(_voice, _n) \
|
||||
|
|
|
@ -202,6 +202,8 @@ typedef struct _fluid_sample_timer_t fluid_sample_timer_t;
|
|||
#define FLUID_MAX_EVENTS_PER_BUFSIZE 1024 /**< Maximum queued MIDI events per #FLUID_BUFSIZE */
|
||||
#define FLUID_MAX_RETURN_EVENTS 1024 /**< Maximum queued synthesis thread return events */
|
||||
#define FLUID_MAX_EVENT_QUEUES 16 /**< Maximum number of unique threads queuing events */
|
||||
#define FLUID_DEFAULT_AUDIO_RT_PRIO 90 /**< Default setting for audio.realtime-prio */
|
||||
#define FLUID_DEFAULT_MIDI_RT_PRIO 80 /**< Default setting for midi.realtime-prio */
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.141592654
|
||||
|
|
Loading…
Reference in a new issue