mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 06:51:54 +00:00
Workaround for jack sample rate mismatch (#607)
During the creation of a jack audio driver, it is checked whether the sample-rate of the settings object matches jack's rate. If not, it was adjusted previously via fluid_synth_set_sample_rate(). Due to the deprecation of that function and removal of real-time capability of the synth.sample-rate setting, a regression was introduced in 5fbddcecc3
causing the synth's sample-rate to be not updated.
This workaround obtains the synth via the settings instance and for now calls the deprecated sample-rate set function.
This commit is contained in:
parent
ba71d6ad9e
commit
3610372ae5
7 changed files with 108 additions and 13 deletions
|
@ -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,
|
||||
|
@ -332,7 +334,9 @@ new_fluid_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
|||
*
|
||||
* 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.
|
||||
* \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().
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
@ -492,16 +491,22 @@ fluid_jack_client_register_ports(void *driver, int isaudio, jack_client_t *clien
|
|||
fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
|
||||
|
||||
if((unsigned long)sample_rate != jack_srate)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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 */
|
||||
if(dev->callback == NULL)
|
||||
fluid_synth_process_event_queue(synth);
|
||||
}
|
||||
else
|
||||
{
|
||||
fluid_synth_process_event_queue(dev->data);
|
||||
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;
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
34
test/test_jack_obtaining_synth.c
Normal file
34
test/test_jack_obtaining_synth.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue