diff src/audio/alsa/SDL_alsa_audio.c @ 4333:55717a755897 SDL-1.2

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.
author Sam Lantinga <slouken@libsdl.org>
date Tue, 13 Oct 2009 09:56:15 +0000
parents 67e799ffcadf
children afadcd7d2319
line wrap: on
line diff
--- a/src/audio/alsa/SDL_alsa_audio.c	Tue Oct 13 09:35:37 2009 +0000
+++ b/src/audio/alsa/SDL_alsa_audio.c	Tue Oct 13 09:56:15 2009 +0000
@@ -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_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 @@
 	{ "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 @@
 	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 @@
 	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 @@
 	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 @@
 	}
 
 /* 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 @@
 		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));