From 7a24c80011d50c1716e84ab70de097caa201746f Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 21 Jun 2008 17:14:57 +0000 Subject: Rework period/buffer size setting git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4768 c046a42c-6fe2-441c-8c8c-71466251a162 --- audio/alsaaudio.c | 190 +++++++++++++++--------------------------------------- 1 file changed, 52 insertions(+), 138 deletions(-) (limited to 'audio/alsaaudio.c') diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 43cfa258d7..7d488859d1 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -58,37 +58,15 @@ static struct { int period_size_out_overridden; int verbose; } conf = { -#define DEFAULT_BUFFER_SIZE 1024 -#define DEFAULT_PERIOD_SIZE 256 -#ifdef HIGH_LATENCY - .size_in_usec_in = 1, - .size_in_usec_out = 1, -#endif .pcm_name_out = "default", .pcm_name_in = "default", -#ifdef HIGH_LATENCY - .buffer_size_in = 400000, - .period_size_in = 400000 / 4, - .buffer_size_out = 400000, - .period_size_out = 400000 / 4, -#else - .buffer_size_in = DEFAULT_BUFFER_SIZE * 4, - .period_size_in = DEFAULT_PERIOD_SIZE * 4, - .buffer_size_out = DEFAULT_BUFFER_SIZE, - .period_size_out = DEFAULT_PERIOD_SIZE, - .buffer_size_in_overridden = 0, - .buffer_size_out_overridden = 0, - .period_size_in_overridden = 0, - .period_size_out_overridden = 0, -#endif - .threshold = 0, - .verbose = 0 }; struct alsa_params_req { int freq; snd_pcm_format_t fmt; int nchannels; + int size_in_usec; unsigned int buffer_size; unsigned int period_size; }; @@ -286,17 +264,16 @@ static int alsa_open (int in, struct alsa_params_req *req, snd_pcm_t *handle; snd_pcm_hw_params_t *hw_params; int err; + int size_in_usec; unsigned int freq, nchannels; const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out; - unsigned int period_size, buffer_size; snd_pcm_uframes_t obt_buffer_size; const char *typ = in ? "ADC" : "DAC"; snd_pcm_format_t obtfmt; freq = req->freq; - period_size = req->period_size; - buffer_size = req->buffer_size; nchannels = req->nchannels; + size_in_usec = req->size_in_usec; snd_pcm_hw_params_alloca (&hw_params); @@ -356,130 +333,61 @@ static int alsa_open (int in, struct alsa_params_req *req, goto err; } - if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) { - if (!buffer_size) { - buffer_size = DEFAULT_BUFFER_SIZE; - period_size= DEFAULT_PERIOD_SIZE; - } - } - - if (buffer_size) { - if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) { - if (period_size) { - err = snd_pcm_hw_params_set_period_time_near ( - handle, - hw_params, - &period_size, - 0 - ); - if (err < 0) { - alsa_logerr2 (err, typ, - "Failed to set period time %d\n", - req->period_size); - goto err; - } - } + if (req->buffer_size) { + if (size_in_usec) { + int dir = 0; + unsigned int btime = req->buffer_size; err = snd_pcm_hw_params_set_buffer_time_near ( handle, hw_params, - &buffer_size, - 0 + &btime, + &dir ); - - if (err < 0) { - alsa_logerr2 (err, typ, - "Failed to set buffer time %d\n", - req->buffer_size); - goto err; - } } else { - int dir; - snd_pcm_uframes_t minval; - - if (period_size) { - minval = period_size; - dir = 0; - - err = snd_pcm_hw_params_get_period_size_min ( - hw_params, - &minval, - &dir - ); - if (err < 0) { - alsa_logerr ( - err, - "Could not get minmal period size for %s\n", - typ - ); - } - else { - if (period_size < minval) { - if ((in && conf.period_size_in_overridden) - || (!in && conf.period_size_out_overridden)) { - dolog ("%s period size(%d) is less " - "than minmal period size(%ld)\n", - typ, - period_size, - minval); - } - period_size = minval; - } - } + snd_pcm_uframes_t bsize = req->buffer_size; - err = snd_pcm_hw_params_set_period_size ( - handle, - hw_params, - period_size, - 0 - ); - if (err < 0) { - alsa_logerr2 (err, typ, "Failed to set period size %d\n", - req->period_size); - goto err; - } - } + err = snd_pcm_hw_params_set_buffer_size_near ( + handle, + hw_params, + &bsize + ); + } + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set buffer %s to %d\n", + size_in_usec ? "time" : "size", req->buffer_size); + goto err; + } + } + + if (req->period_size) { + if (size_in_usec) { + int dir = 0; + unsigned int ptime = req->period_size; - minval = buffer_size; - err = snd_pcm_hw_params_get_buffer_size_min ( + err = snd_pcm_hw_params_set_period_time_near ( + handle, hw_params, - &minval + &ptime, + &dir ); - if (err < 0) { - alsa_logerr (err, "Could not get minmal buffer size for %s\n", - typ); - } - else { - if (buffer_size < minval) { - if ((in && conf.buffer_size_in_overridden) - || (!in && conf.buffer_size_out_overridden)) { - dolog ( - "%s buffer size(%d) is less " - "than minimal buffer size(%ld)\n", - typ, - buffer_size, - minval - ); - } - buffer_size = minval; - } - } + } + else { + snd_pcm_uframes_t psize = req->period_size; - err = snd_pcm_hw_params_set_buffer_size ( + err = snd_pcm_hw_params_set_buffer_size_near ( handle, hw_params, - buffer_size + &psize ); - if (err < 0) { - alsa_logerr2 (err, typ, "Failed to set buffer size %d\n", - req->buffer_size); - goto err; - } } - } - else { - dolog ("warning: Buffer size is not set\n"); + + if (err < 0) { + alsa_logerr2 (err, typ, "Failed to set period %s to %d\n", + size_in_usec ? "time" : "size", req->period_size); + goto err; + } } err = snd_pcm_hw_params (handle, hw_params); @@ -697,6 +605,7 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as) req.nchannels = as->nchannels; req.period_size = conf.period_size_out; req.buffer_size = conf.buffer_size_out; + req.size_in_usec = conf.size_in_usec_in; if (alsa_open (0, &req, &obt, &handle)) { return -1; @@ -774,6 +683,7 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as) req.nchannels = as->nchannels; req.period_size = conf.period_size_in; req.buffer_size = conf.buffer_size_in; + req.size_in_usec = conf.size_in_usec_in; if (alsa_open (1, &req, &obt, &handle)) { return -1; @@ -953,16 +863,20 @@ static struct audio_option alsa_options[] = { {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out, "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0}, {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out, - "DAC period size", &conf.period_size_out_overridden, 0}, + "DAC period size (0 to go with system default)", + &conf.period_size_out_overridden, 0}, {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out, - "DAC buffer size", &conf.buffer_size_out_overridden, 0}, + "DAC buffer size (0 to go with system default)", + &conf.buffer_size_out_overridden, 0}, {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in, "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0}, {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in, - "ADC period size", &conf.period_size_in_overridden, 0}, + "ADC period size (0 to go with system default)", + &conf.period_size_in_overridden, 0}, {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in, - "ADC buffer size", &conf.buffer_size_in_overridden, 0}, + "ADC buffer size (0 to go with system default)", + &conf.buffer_size_in_overridden, 0}, {"THRESHOLD", AUD_OPT_INT, &conf.threshold, "(undocumented)", NULL, 0}, -- cgit v1.2.1