Switched from setting the period size and count to setting the buffer size directly, based on feedback from the ALSA development list: SDL-1.2
authorSam Lantinga <slouken@libsdl.org>
Tue, 13 Oct 2009 09:56:15 +0000
branchSDL-1.2
changeset 433355717a755897
parent 4332 67e799ffcadf
child 4334 afadcd7d2319
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
     1.1 --- a/src/audio/alsa/SDL_alsa_audio.c	Tue Oct 13 09:35:37 2009 +0000
     1.2 +++ b/src/audio/alsa/SDL_alsa_audio.c	Tue Oct 13 09:56:15 2009 +0000
     1.3 @@ -46,6 +46,10 @@
     1.4  /* The default ALSA audio driver */
     1.5  #define DEFAULT_DEVICE	"default"
     1.6  
     1.7 +/* Whether we should set the buffer size or the period size */
     1.8 +/*#define SET_PERIOD_SIZE*/
     1.9 +/*#define DEBUG_PERIOD_SIZE*/
    1.10 +
    1.11  /* Audio driver functions */
    1.12  static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec);
    1.13  static void ALSA_WaitAudio(_THIS);
    1.14 @@ -78,13 +82,13 @@
    1.15  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);
    1.16  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);
    1.17  static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
    1.18 +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);
    1.19  static int (*SDL_NAME(snd_pcm_hw_params_get_buffer_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
    1.20  static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
    1.21  /*
    1.22  */
    1.23  static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams);
    1.24  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);
    1.25 -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);
    1.26  static int (*SDL_NAME(snd_pcm_sw_params))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
    1.27  static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock);
    1.28  #define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof)
    1.29 @@ -114,11 +118,11 @@
    1.30  	{ "snd_pcm_hw_params_get_period_size",	(void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_period_size)	},
    1.31  	{ "snd_pcm_hw_params_set_periods_near",	(void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near)	},
    1.32  	{ "snd_pcm_hw_params_get_periods",	(void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_periods)	},
    1.33 +	{ "snd_pcm_hw_params_set_buffer_size_near",	(void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_buffer_size_near) },
    1.34  	{ "snd_pcm_hw_params_get_buffer_size",	(void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_buffer_size) },
    1.35  	{ "snd_pcm_hw_params",	(void**)(char*)&SDL_NAME(snd_pcm_hw_params)	},
    1.36  	{ "snd_pcm_sw_params_current",	(void**)(char*)&SDL_NAME(snd_pcm_sw_params_current)	},
    1.37  	{ "snd_pcm_sw_params_set_start_threshold",	(void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_start_threshold)	},
    1.38 -	{ "snd_pcm_sw_params_set_avail_min",	(void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_avail_min)	},
    1.39  	{ "snd_pcm_sw_params",	(void**)(char*)&SDL_NAME(snd_pcm_sw_params)	},
    1.40  	{ "snd_pcm_nonblock",	(void**)(char*)&SDL_NAME(snd_pcm_nonblock)	},
    1.41  };
    1.42 @@ -368,8 +372,10 @@
    1.43  	snd_pcm_format_t     format;
    1.44  	snd_pcm_uframes_t    frames;
    1.45  	unsigned int         rate;
    1.46 +#ifdef SET_PERIOD_SIZE
    1.47  	unsigned int         periods;
    1.48 -	unsigned int 		 channels;
    1.49 +#endif
    1.50 +	unsigned int 	     channels;
    1.51  	Uint16               test_format;
    1.52  
    1.53  	/* Open the audio device */
    1.54 @@ -464,10 +470,11 @@
    1.55  	spec->freq = rate;
    1.56  
    1.57  	/* Set the buffer size, in samples */
    1.58 +#ifdef SET_PERIOD_SIZE
    1.59  	frames = spec->samples;
    1.60  	status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL);
    1.61  	if ( status < 0 ) {
    1.62 -		SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status));
    1.63 +		SDL_SetError("Couldn't set period size: %s", SDL_NAME(snd_strerror)(status));
    1.64  		ALSA_CloseAudio(this);
    1.65  		return(-1);
    1.66  	}
    1.67 @@ -475,7 +482,16 @@
    1.68  	spec->samples = frames;
    1.69  
    1.70  	periods = 2;
    1.71 -	SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL);
    1.72 +	status = SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL);
    1.73 +	if ( status < 0 ) {
    1.74 +		SDL_SetError("Couldn't set period count: %s", SDL_NAME(snd_strerror)(status));
    1.75 +		ALSA_CloseAudio(this);
    1.76 +		return(-1);
    1.77 +	}
    1.78 +#else
    1.79 +	frames = spec->samples * 2;
    1.80 +	status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames);
    1.81 +#endif
    1.82  
    1.83  	/* "set" the hardware with the desired parameters */
    1.84  	status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams);
    1.85 @@ -486,7 +502,7 @@
    1.86  	}
    1.87  
    1.88  /* This is useful for debugging... */
    1.89 -#if 0
    1.90 +#ifdef DEBUG_PERIOD_SIZE
    1.91  { snd_pcm_uframes_t bufsize; snd_pcm_sframes_t persize; unsigned int periods; int dir;
    1.92     SDL_NAME(snd_pcm_hw_params_get_buffer_size)(hwparams, &bufsize);
    1.93     SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, &dir);
    1.94 @@ -510,12 +526,6 @@
    1.95  		ALSA_CloseAudio(this);
    1.96  		return(-1);
    1.97  	}
    1.98 -	status = SDL_NAME(snd_pcm_sw_params_set_avail_min)(pcm_handle, swparams, frames);
    1.99 -	if ( status < 0 ) {
   1.100 -		SDL_SetError("Couldn't set avail min: %s", SDL_NAME(snd_strerror)(status));
   1.101 -		ALSA_CloseAudio(this);
   1.102 -		return(-1);
   1.103 -	}
   1.104  	status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams);
   1.105  	if ( status < 0 ) {
   1.106  		SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status));