audioOutput_alsa: better period_size auto-configuration

We'll try setting an initial value of 50ms, and halve it each
time snd_pcm_hw_params fails with -EPIPE.

This way we'll can use a larger (50ms) period_size whenever a device
supports it, and automatically pick smaller ones if we can't set
larger ones.

This removes the calculation borrowed from libao (svn) as well.

Other minor things:
"Alsa" => "ALSA" in error messages
_US appended to *_TIME constants so we won't get confused
(shank's request)

git-svn-id: https://svn.musicpd.org/mpd/trunk@4438 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
Eric Wong 2006-07-24 01:38:51 +00:00
parent 76528555dc
commit 24c1f46353

View File

@ -25,12 +25,12 @@
#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
#define MPD_ALSA_BUFFER_TIME 500000
#define MPD_ALSA_BUFFER_TIME_US 500000
/* the default period time of xmms is 50 ms, so let's use that as well.
* a user can tweak this parameter via the "period_time" config parameter.
*/
#define MPD_ALSA_PERIOD_TIME 50000
#define MPD_ALSA_SAMPLE_XFER 256
#define MPD_ALSA_PERIOD_TIME_US 50000
#define MPD_ALSA_RETRY_NR 5
#include "../conf.h"
#include "../log.h"
@ -65,8 +65,8 @@ static AlsaData *newAlsaData(void)
ret->pcmHandle = NULL;
ret->writei = snd_pcm_writei;
ret->useMmap = 0;
ret->buffer_time = MPD_ALSA_BUFFER_TIME;
ret->period_time = MPD_ALSA_PERIOD_TIME;
ret->buffer_time = MPD_ALSA_BUFFER_TIME_US;
ret->period_time = MPD_ALSA_PERIOD_TIME_US;
return ret;
}
@ -139,7 +139,9 @@ static int alsa_openDevice(AudioOutput * audioOutput)
snd_pcm_uframes_t alsa_buffer_size;
snd_pcm_uframes_t alsa_period_size;
int err;
char *cmd = NULL;
const char *cmd = NULL;
unsigned int period_time;
int retry = MPD_ALSA_RETRY_NR;
switch (audioFormat->bits) {
case 8:
@ -155,7 +157,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
bitformat = SND_PCM_FORMAT_S32;
break;
default:
ERROR("Alsa device \"%s\" doesn't support %i bit audio\n",
ERROR("ALSA device \"%s\" doesn't support %i bit audio\n",
ad->device, audioFormat->bits);
return -1;
}
@ -173,6 +175,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
if (err < 0)
goto error;
configure_hw:
/* configure HW params */
snd_pcm_hw_params_alloca(&hwparams);
@ -204,7 +207,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat);
if (err < 0) {
ERROR("Alsa device \"%s\" does not support %i bit audio: "
ERROR("ALSA device \"%s\" does not support %i bit audio: "
"%s\n", ad->device, (int)bitformat, snd_strerror(-err));
goto fail;
}
@ -212,7 +215,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
err = snd_pcm_hw_params_set_channels_near(ad->pcmHandle, hwparams,
&channels);
if (err < 0) {
ERROR("Alsa device \"%s\" does not support %i channels: "
ERROR("ALSA device \"%s\" does not support %i channels: "
"%s\n", ad->device, (int)audioFormat->channels,
snd_strerror(-err));
goto fail;
@ -222,7 +225,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
err = snd_pcm_hw_params_set_rate_near(ad->pcmHandle, hwparams,
&sampleRate, NULL);
if (err < 0 || sampleRate == 0) {
ERROR("Alsa device \"%s\" does not support %i Hz audio\n",
ERROR("ALSA device \"%s\" does not support %i Hz audio\n",
ad->device, (int)audioFormat->sampleRate);
goto fail;
}
@ -234,8 +237,7 @@ static int alsa_openDevice(AudioOutput * audioOutput)
if (err < 0)
goto error;
if (!ad->period_time && sampleRate > 0)
ad->period_time = 1000000 * MPD_ALSA_SAMPLE_XFER / sampleRate;
period_time = ad->period_time;
cmd = "snd_pcm_hw_params_set_period_time_near";
err = snd_pcm_hw_params_set_period_time_near(ad->pcmHandle, hwparams,
&ad->period_time, NULL);
@ -244,8 +246,13 @@ static int alsa_openDevice(AudioOutput * audioOutput)
cmd = "snd_pcm_hw_params";
err = snd_pcm_hw_params(ad->pcmHandle, hwparams);
if (err < 0)
if (err == -EPIPE && --retry > 0) {
ad->period_time = period_time >> 1;
goto configure_hw;
} else if (err < 0)
goto error;
if (retry != MPD_ALSA_RETRY_NR)
DEBUG("ALSA period_time set to %d\n", ad->period_time);
cmd = "snd_pcm_hw_params_get_buffer_size";
err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size);