ref: faabf4330b3983cc36908b906f2e1f4af1b810d2
parent: 5c98974dd758b400569414f613258155b5caf403
author: cbagwell <cbagwell>
date: Sat Nov 5 18:52:12 EST 2005
Updating period/buffer setting based on suggestions from xine-lib alsa author.
--- a/src/alsa.c
+++ b/src/alsa.c
@@ -43,7 +43,7 @@
int fmt = SND_PCM_FORMAT_S16;
int err;
alsa_priv_t alsa = (alsa_priv_t)ft->priv;
- snd_pcm_hw_params_t *hw_params;
+ snd_pcm_hw_params_t *hw_params = NULL;
#if 0
snd_pcm_sw_params_t *sw_params;
#endif
@@ -50,34 +50,16 @@
unsigned int min_rate, max_rate;
unsigned int min_chan, max_chan;
unsigned int rate;
-#if 1
- unsigned int periods;
-#endif
- snd_pcm_uframes_t buffer_size;
+ snd_pcm_uframes_t buffer_size, buffer_size_min, buffer_size_max;
+ snd_pcm_uframes_t period_size, period_size_min, period_size_max;
int dir;
- snd_pcm_format_mask_t *fmask;
-#if 0
- unsigned int buffer_time = 500000;
- unsigned int period_time = 100000;
- snd_pcm_sframes_t period_size;
-#endif
+ snd_pcm_format_mask_t *fmask = NULL;
- /* FIXME: Whats a good size? */
- alsa->buf_size = (ST_BUFSIZ / sizeof(st_sample_t)) * ft->info.size;
-
- if ((alsa->buf = malloc(alsa->buf_size)) == NULL)
- {
- st_fail_errno(ft,ST_ENOMEM,
- "unable to allocate output buffer of size %d",
- ft->file.size);
- return(ST_EOF);
- }
-
if ((err = snd_pcm_open(&(alsa->pcm_handle), ft->filename,
mode, 0)) < 0)
{
st_fail_errno(ft, ST_EPERM, "cannot open audio device");
- return ST_EOF;
+ goto open_error;
}
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
@@ -84,7 +66,7 @@
{
st_fail_errno(ft, ST_ENOMEM,
"cannot allocate hardware parameter structure");
- return ST_EOF;
+ goto open_error;
}
if ((err = snd_pcm_hw_params_any(alsa->pcm_handle, hw_params)) < 0)
@@ -91,7 +73,7 @@
{
st_fail_errno(ft, ST_EPERM,
"cannot initialize hardware parameter structure");
- return ST_EOF;
+ goto open_error;
}
#if SND_LIB_VERSION >= 0x010009
@@ -101,7 +83,7 @@
rate);
if (err < 0) {
st_fail_errno(ft, ST_EPERM, "Resampling setup failed for playback");
- return ST_EOF;
+ goto open_error;
}
#endif
@@ -110,7 +92,7 @@
{
st_fail_errno(ft, ST_EPERM,
"cannot set access type");
- return ST_EOF;
+ goto open_error;
}
snd_pcm_hw_params_get_channels_min(hw_params, &min_chan);
@@ -127,15 +109,16 @@
snd_pcm_hw_params_get_format_mask(hw_params, fmask);
if (get_format(ft, fmask, &fmt) < 0)
- return (ST_EOF);
+ goto open_error;
snd_pcm_format_mask_free(fmask);
+ fmask = NULL;
if ((err = snd_pcm_hw_params_set_format(alsa->pcm_handle,
hw_params, fmt)) < 0)
{
st_fail_errno(ft, ST_EPERM, "cannot set sample format");
- return ST_EOF;
+ goto open_error;
}
rate = ft->info.rate;
@@ -159,7 +142,7 @@
&dir)) < 0)
{
st_fail_errno(ft, ST_EPERM, "cannot set sample rate");
- return ST_EOF;
+ goto open_error;
}
snd_pcm_hw_params_get_rate(hw_params,
&rate,
@@ -178,114 +161,105 @@
ft->info.channels)) < 0)
{
st_fail_errno(ft, ST_EPERM, "cannot set channel count");
- return ST_EOF;
+ goto open_error;
}
-#if 0
- /* set the buffer time */
- err = snd_pcm_hw_params_set_buffer_time_near(alsa->pcm_handle, hw_params, &buffer_time, &dir);
- if (err < 0) {
- printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
- return err;
- }
- err = snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
- if (err < 0) {
- printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
- return err;
- }
+ buffer_size = (ST_BUFSIZ / sizeof(st_sample_t) / ft->info.channels);
- /* set the period time */
- err = snd_pcm_hw_params_set_period_time_near(alsa->pcm_handle, hw_params, &period_time, &dir);
- if (err < 0) {
- printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
- return err;
+ if (snd_pcm_hw_params_get_buffer_size_min(hw_params, &buffer_size_min) < 0)
+ {
+ st_fail_errno(ft, ST_EPERM, "Error getting min buffer size.");
+ goto open_error;
}
- err = snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir);
- if (err < 0) {
- printf("Unable to get period size for playback: %s\n", snd_strerror(err));
- return err;
+
+ if (snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size_max) < 0)
+ {
+ st_fail_errno(ft, ST_EPERM, "Error getting max buffer size.");
+ goto open_error;
}
-#endif
-#if 1
- /* Set number of periods. Periods used to be called fragments. */
- periods = 16;
- if (snd_pcm_hw_params_set_periods_near(alsa->pcm_handle, hw_params,
- &periods, &dir) < 0)
+ dir = 0;
+ if (snd_pcm_hw_params_get_period_size_min(hw_params,
+ &period_size_min, &dir) < 0)
{
+ st_fail_errno(ft, ST_EPERM, "Error getting min period size.");
+ goto open_error;
+ }
+
+ dir = 0;
+ if (snd_pcm_hw_params_get_period_size_max(hw_params,
+ &period_size_max, &dir) < 0)
+ {
+ st_fail_errno(ft, ST_EPERM, "Error getting max buffer size.");
+ goto open_error;
+ }
+
+ if (buffer_size_max < buffer_size)
+ buffer_size = buffer_size_max;
+ else if (buffer_size_min > buffer_size)
+ buffer_size = buffer_size_min;
+
+ period_size = buffer_size / 8;
+ buffer_size = period_size * 8;
+
+ dir = 0;
+ if (snd_pcm_hw_params_set_period_size_near(alsa->pcm_handle, hw_params,
+ &period_size, &dir) < 0)
+ {
st_fail_errno(ft, ST_EPERM, "Error setting periods.");
- return ST_EOF;
+ goto open_error;
}
- snd_pcm_hw_params_get_periods(hw_params, &periods, &dir);
+ snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir);
- buffer_size = alsa->buf_size;
+ dir = 0;
if (snd_pcm_hw_params_set_buffer_size_near(alsa->pcm_handle, hw_params,
&buffer_size) < 0) {
- st_fail_errno(ft, ST_EPERM, "Error setting buffersize.");
- return ST_EOF;
+ st_fail_errno(ft, ST_EPERM, "Error setting buffersize.");
+ goto open_error;
}
-#endif
+ snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
+ if (period_size*2 > buffer_size)
+ {
+ st_fail_errno(ft, ST_EPERM, "Buffer to small. Could not use.");
+ goto open_error;
+ }
+
if ((err = snd_pcm_hw_params(alsa->pcm_handle, hw_params)) < 0)
{
st_fail_errno(ft, ST_EPERM, "cannot set parameters");
- return ST_EOF;
+ goto open_error;
}
snd_pcm_hw_params_free(hw_params);
+ hw_params = NULL;
-#if 0
- if ((err = snd_pcm_sw_params_malloc(&sw_params)) < 0)
+ if ((err = snd_pcm_prepare(alsa->pcm_handle)) < 0)
{
- st_fail_errno(ft, ST_ENOMEM,
- "cannot allocate software parameter structure");
- return ST_EOF;
+ st_fail_errno(ft, ST_EPERM, "cannot prepare audio interface for use");
+ goto open_error;
}
- /* get the current swparams */
- err = snd_pcm_sw_params_current(alsa->pcm_handle, sw_params);
- if (err < 0) {
- printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
- return err;
- }
- /* start the transfer when the buffer is almost full: */
- /* (buffer_size / avail_min) * avail_min */
- err = snd_pcm_sw_params_set_start_threshold(alsa->pcm_handle, sw_params,
- (buffer_size / period_size) * period_size);
- if (err < 0) {
- printf("Unable to set start threshold mode for playback: %s\n",
- snd_strerror(err));
- return err;
- }
- /* allow the transfer when at least period_size samples can be processed */
- err = snd_pcm_sw_params_set_avail_min(alsa->pcm_handle, sw_params, period_size);
- if (err < 0) {
- printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
- return err;
- }
- /* align all transfers to 1 sample */
- err = snd_pcm_sw_params_set_xfer_align(alsa->pcm_handle, sw_params, 1);
- if (err < 0) {
- printf("Unable to set transfer align for playback: %s\n", snd_strerror(err));
- return err;
- }
- /* write the parameters to the playback device */
- err = snd_pcm_sw_params(alsa->pcm_handle, sw_params);
- if (err < 0) {
- printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
- return err;
- }
+ alsa->buf_size = buffer_size * ft->info.size * ft->info.channels;
- snd_pcm_sw_params_free(sw_params);
-#endif
-
- if ((err = snd_pcm_prepare(alsa->pcm_handle)) < 0)
+ if ((alsa->buf = malloc(alsa->buf_size)) == NULL)
{
- st_fail_errno(ft, ST_EPERM, "cannot prepare audio interface for use");
- return ST_EOF;
+ st_fail_errno(ft,ST_ENOMEM,
+ "unable to allocate output buffer of size %d",
+ ft->file.size);
+ return(ST_EOF);
}
return (ST_SUCCESS);
+
+open_error:
+ if (fmask)
+ snd_pcm_format_mask_free(fmask);
+ if (hw_params)
+ snd_pcm_hw_params_free(hw_params);
+
+ return ST_EOF;
+
}
/*
--- a/src/sox.c
+++ b/src/sox.c
@@ -1142,8 +1142,19 @@
if (efftab[e].odone == efftab[e].olen)
efftab[e].odone = efftab[e].olen = 0;
- if (efftab[e].odone < efftab[e].olen) {
- havedata = 1;
+ if (efftab[e].odone < efftab[e].olen)
+ {
+ /* Only mark that we have more data if a full
+ * frame that can be written.
+ * FIXME: If this error case happens for the
+ * input buffer then the data will be lost and
+ * will cause stereo channels to be inversed.
+ */
+ if ((efftab[e].olen - efftab[e].odone) >=
+ file_desc[file_count-1]->info.channels)
+ havedata = 1;
+ else
+ st_warn("Received buffer with incomplete amount of samples.");
/* Don't break out because other things are being
* done in loop.
*/