diff --git a/src/drivers/fluid_adriver.c b/src/drivers/fluid_adriver.c index 2374def0..b03a701c 100644 --- a/src/drivers/fluid_adriver.c +++ b/src/drivers/fluid_adriver.c @@ -294,7 +294,9 @@ find_fluid_audio_driver(fluid_settings_t *settings) * @return The new audio driver instance. * * Creates a new audio driver for a given \p synth instance with a defined set - * of configuration \p settings. + * of configuration \p settings. The \p settings instance must be the same that + * you have passed to new_fluid_synth() when creating the \p synth instance. + * Otherwise the behaviour is undefined. * * @note As soon as an audio driver is created, the \p synth starts rendering audio. * This means that all necessary sound-setup should be completed after this point, @@ -331,8 +333,10 @@ new_fluid_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth) * @return The new audio driver instance. * * Like new_fluid_audio_driver() but allows for custom audio processing before - * audio is sent to audio driver. It is the responsibility of the callback - * \p func to render the audio into the buffers. + * audio is sent to audio driver. It is the responsibility of the callback + * \p func to render the audio into the buffers. If \p func uses a fluid_synth_t \p synth, + * the \p settings instance must be the same that you have passed to new_fluid_synth() + * when creating the \p synth instance. Otherwise the behaviour is undefined. * * @note Not as efficient as new_fluid_audio_driver(). * diff --git a/src/drivers/fluid_adriver.h b/src/drivers/fluid_adriver.h index 3c1a8296..ebd66521 100644 --- a/src/drivers/fluid_adriver.h +++ b/src/drivers/fluid_adriver.h @@ -119,6 +119,7 @@ fluid_audio_driver_t *new_fluid_jack_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data); void delete_fluid_jack_audio_driver(fluid_audio_driver_t *p); void fluid_jack_audio_driver_settings(fluid_settings_t *settings); +int fluid_jack_obtain_synth(fluid_settings_t *settings, fluid_synth_t **synth); #endif #if SNDMAN_SUPPORT diff --git a/src/drivers/fluid_jack.c b/src/drivers/fluid_jack.c index 31706ae8..1d85994f 100644 --- a/src/drivers/fluid_jack.c +++ b/src/drivers/fluid_jack.c @@ -484,7 +484,6 @@ fluid_jack_client_register_ports(void *driver, int isaudio, jack_client_t *clien } } - /* Adjust sample rate to match JACK's */ jack_srate = jack_get_sample_rate(client); FLUID_LOG(FLUID_DBG, "Jack engine sample rate: %lu", jack_srate); @@ -493,15 +492,21 @@ fluid_jack_client_register_ports(void *driver, int isaudio, jack_client_t *clien if((unsigned long)sample_rate != jack_srate) { - FLUID_LOG(FLUID_INFO, "Jack sample rate mismatch, adjusting." + fluid_synth_t* synth; + if(fluid_jack_obtain_synth(settings, &synth) == FLUID_OK) + { + FLUID_LOG(FLUID_INFO, "Jack sample rate mismatch, adjusting." " (synth.sample-rate=%lu, jackd=%lu)", (unsigned long)sample_rate, jack_srate); - fluid_settings_setnum(settings, "synth.sample-rate", jack_srate); - } - - /* Changing sample rate is non RT, so make sure we process it and/or other things now */ - if(dev->callback == NULL) - { - fluid_synth_process_event_queue(dev->data); + fluid_synth_set_sample_rate(synth, jack_srate); + /* Changing sample rate is non RT, so make sure we process it and/or other things now */ + fluid_synth_process_event_queue(synth); + } + else + { + FLUID_LOG(FLUID_WARN, "Jack sample rate mismatch (synth.sample-rate=%lu, jackd=%lu)" + " impossible to adjust, because the settings object provided to new_fluid_audio_driver2() was not used to create a synth." + , (unsigned long)sample_rate, jack_srate); + } } return FLUID_OK; @@ -865,7 +870,7 @@ new_fluid_jack_midi_driver(fluid_settings_t *settings, } return (fluid_midi_driver_t *)dev; - + error_recovery: delete_fluid_jack_midi_driver((fluid_midi_driver_t *)dev); return NULL; @@ -887,4 +892,18 @@ delete_fluid_jack_midi_driver(fluid_midi_driver_t *p) FLUID_FREE(dev); } +int fluid_jack_obtain_synth(fluid_settings_t *settings, fluid_synth_t **synth) +{ + void *data; + + if(!fluid_settings_is_realtime(settings, "synth.gain") || + (data = fluid_settings_get_user_data(settings, "synth.gain")) == NULL) + { + return FLUID_FAILED; + } + + *synth = data; + return FLUID_OK; +} + #endif /* JACK_SUPPORT */ diff --git a/src/utils/fluid_settings.c b/src/utils/fluid_settings.c index 78532ad2..75248f42 100644 --- a/src/utils/fluid_settings.c +++ b/src/utils/fluid_settings.c @@ -791,6 +791,40 @@ int fluid_settings_callback_int(fluid_settings_t *settings, const char *name, return FLUID_OK; } +void* fluid_settings_get_user_data(fluid_settings_t * settings, const char *name) +{ + fluid_setting_node_t *node; + void* retval = NULL; + + fluid_return_val_if_fail(settings != NULL, NULL); + fluid_return_val_if_fail(name != NULL, NULL); + fluid_return_val_if_fail(name[0] != '\0', NULL); + + fluid_rec_mutex_lock(settings->mutex); + + if(fluid_settings_get(settings, name, &node) == FLUID_OK) + { + if(node->type == FLUID_NUM_TYPE) + { + fluid_num_setting_t *setting = &node->num; + retval = setting->data; + } + else if(node->type == FLUID_STR_TYPE) + { + fluid_str_setting_t *setting = &node->str; + retval = setting->data; + } + else if(node->type == FLUID_INT_TYPE) + { + fluid_int_setting_t *setting = &node->i; + retval = setting->data; + } + } + + fluid_rec_mutex_unlock(settings->mutex); + return retval; +} + /** * Get the type of the setting with the given name * diff --git a/src/utils/fluid_settings.h b/src/utils/fluid_settings.h index 4a952f1b..c05e0ed0 100644 --- a/src/utils/fluid_settings.h +++ b/src/utils/fluid_settings.h @@ -52,4 +52,6 @@ int fluid_settings_callback_int(fluid_settings_t *settings, const char *name, int fluid_settings_split_csv(const char *str, int *buf, int buf_len); +void* fluid_settings_get_user_data(fluid_settings_t * settings, const char *name); + #endif /* _FLUID_SETTINGS_H */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d3105d36..4d6d4f8d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,6 +19,7 @@ ADD_FLUID_TEST(test_synth_process) ADD_FLUID_TEST(test_ct2hz) ADD_FLUID_TEST(test_seq_event_queue_sort) ADD_FLUID_TEST(test_seq_scale) +ADD_FLUID_TEST(test_jack_obtaining_synth) # if ( LIBSNDFILE_HASVORBIS ) # ADD_FLUID_TEST(test_sf3_sfont_loading) diff --git a/test/test_jack_obtaining_synth.c b/test/test_jack_obtaining_synth.c new file mode 100644 index 00000000..9fac88aa --- /dev/null +++ b/test/test_jack_obtaining_synth.c @@ -0,0 +1,34 @@ + +#include "test.h" +#include "fluidsynth.h" +#include "fluid_adriver.h" + +// The jack driver may need the synth instance to adjust the sample-rate in case it mismatches with +// the sample-rate of the jack driver. However, new_fluid_audio_driver2() does not receive a synth pointer. +// Thus looking up the synth instance must be done via the settings object. +int main(void) +{ +#if JACK_SUPPORT + fluid_synth_t *obtained_synth; + fluid_synth_t *expected_synth; + fluid_settings_t *settings = new_fluid_settings(); + TEST_ASSERT(settings != NULL); + + expected_synth = new_fluid_synth(settings); + TEST_ASSERT(expected_synth != NULL); + + TEST_SUCCESS(fluid_jack_obtain_synth(settings, &obtained_synth)); + TEST_ASSERT(obtained_synth == expected_synth); + + delete_fluid_synth(obtained_synth); + delete_fluid_settings(settings); + + obtained_synth = expected_synth = NULL; + + settings = new_fluid_settings(); + TEST_ASSERT(settings != NULL); + TEST_ASSERT(fluid_jack_obtain_synth(settings, &obtained_synth) == FLUID_FAILED); + delete_fluid_settings(settings); +#endif + return EXIT_SUCCESS; +}