From ce1e75c61d35ba6e40cdde862fb462b853e3b456 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 13 Oct 2009 09:56:15 +0000 Subject: [PATCH] Switched from setting the period size and count to setting the buffer size directly, based on feedback from the ALSA development list: http://mailman.alsa-project.org/pipermail/alsa-devel/2009-October/022267.html This has the nice side effect of reducing latency on my SBLive! card. --- src/audio/alsa/SDL_alsa_audio.c | 34 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 17e035639..812cd6fca 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -46,6 +46,10 @@ /* The default ALSA audio driver */ #define DEFAULT_DEVICE "default" +/* Whether we should set the buffer size or the period size */ +/*#define SET_PERIOD_SIZE*/ +/*#define DEBUG_PERIOD_SIZE*/ + /* Audio driver functions */ static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec); static void ALSA_WaitAudio(_THIS); @@ -78,13 +82,13 @@ static int (*SDL_NAME(snd_pcm_hw_params_set_period_size_near))(snd_pcm_t *pcm, s static int (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir); static int (*SDL_NAME(snd_pcm_hw_params_set_periods_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); +static int (*SDL_NAME(snd_pcm_hw_params_set_buffer_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); static int (*SDL_NAME(snd_pcm_hw_params_get_buffer_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); /* */ static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams); static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); -static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); static int (*SDL_NAME(snd_pcm_sw_params))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock); #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) @@ -114,11 +118,11 @@ static struct { { "snd_pcm_hw_params_get_period_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_period_size) }, { "snd_pcm_hw_params_set_periods_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near) }, { "snd_pcm_hw_params_get_periods", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_periods) }, + { "snd_pcm_hw_params_set_buffer_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_buffer_size_near) }, { "snd_pcm_hw_params_get_buffer_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_buffer_size) }, { "snd_pcm_hw_params", (void**)(char*)&SDL_NAME(snd_pcm_hw_params) }, { "snd_pcm_sw_params_current", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_current) }, { "snd_pcm_sw_params_set_start_threshold", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_start_threshold) }, - { "snd_pcm_sw_params_set_avail_min", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_avail_min) }, { "snd_pcm_sw_params", (void**)(char*)&SDL_NAME(snd_pcm_sw_params) }, { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, }; @@ -368,8 +372,10 @@ static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) snd_pcm_format_t format; snd_pcm_uframes_t frames; unsigned int rate; +#ifdef SET_PERIOD_SIZE unsigned int periods; - unsigned int channels; +#endif + unsigned int channels; Uint16 test_format; /* Open the audio device */ @@ -464,10 +470,11 @@ static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) spec->freq = rate; /* Set the buffer size, in samples */ +#ifdef SET_PERIOD_SIZE frames = spec->samples; status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL); if ( status < 0 ) { - SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status)); + SDL_SetError("Couldn't set period size: %s", SDL_NAME(snd_strerror)(status)); ALSA_CloseAudio(this); return(-1); } @@ -475,7 +482,16 @@ static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) spec->samples = frames; periods = 2; - SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL); + status = SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL); + if ( status < 0 ) { + SDL_SetError("Couldn't set period count: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } +#else + frames = spec->samples * 2; + status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames); +#endif /* "set" the hardware with the desired parameters */ status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams); @@ -486,7 +502,7 @@ static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) } /* This is useful for debugging... */ -#if 0 +#ifdef DEBUG_PERIOD_SIZE { snd_pcm_uframes_t bufsize; snd_pcm_sframes_t persize; unsigned int periods; int dir; SDL_NAME(snd_pcm_hw_params_get_buffer_size)(hwparams, &bufsize); SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, &dir); @@ -510,12 +526,6 @@ static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) ALSA_CloseAudio(this); return(-1); } - status = SDL_NAME(snd_pcm_sw_params_set_avail_min)(pcm_handle, swparams, frames); - if ( status < 0 ) { - SDL_SetError("Couldn't set avail min: %s", SDL_NAME(snd_strerror)(status)); - ALSA_CloseAudio(this); - return(-1); - } status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams); if ( status < 0 ) { SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status));