From: James Courtier-Dutton <James@superbug.demon.co.uk>
To: Jaroslav Kysela <perex@suse.cz>
Cc: alsa-devel <alsa-devel@lists.sourceforge.net>
Subject: Re: dmix bugs. sounds very broken up.
Date: Tue, 02 Sep 2003 00:08:11 +0100 [thread overview]
Message-ID: <3F53D15B.3090507@superbug.demon.co.uk> (raw)
In-Reply-To: <Pine.LNX.4.44.0309010807230.14319-100000@pnote.perex-int.cz>
[-- Attachment #1: Type: text/plain, Size: 999 bytes --]
Jaroslav Kysela wrote:
> On Mon, 1 Sep 2003, James Courtier-Dutton wrote:
>
>
>>I have found two problems with using the dmix alsa device name.
>>1) snd_pcm_hw_params_can_pause (params) causes alsa-lib to assert!
>>
>>2) Sound is broken up.
>>a) It can only function with 2 periods, why is that? Having 8 periods
>>might be better, although "front" works fine with 2 periods, but "dmix"
>>with 2 periods fails.
See attachment dmix-fail.c
compile with
gcc -g -DDEBUG -lasound a.c
Shows problem (1) and (2)
>>b) Of the 2 periods, it sounds like sound is only being played from one
>>of the periods, with silence for the other period.
>>
I don't have a small compilable example for this yet. The problem
application is the latest xine cvs. (xine.sf.net)
>>Summary: -
>>If I use device name "front", there are no problems with sound output.
>>If I use device name "dmix", there are the above problems.
>
>
> Show me your code, please (compilable example).
>
> Jaroslav
>
Cheers
James
[-- Attachment #2: dmix-fail.c --]
[-- Type: text/plain, Size: 10176 bytes --]
/*
* Copyright (C) 2000-2002 the xine project
*
* This file is part of xine, a free video player.
*
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Credits go
* - for the SPDIF A/52 sync part
* - frame size calculation added (16-08-2001)
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
* for initial ALSA 0.9.x support.
* adding MONO/STEREO/4CHANNEL/5CHANNEL/5.1CHANNEL analogue support.
* (c) 2001 James Courtier-Dutton <James@superbug.demon.co.uk>
*
*
* $Id: audio_alsa_out.c,v 1.106 2003/09/01 04:08:41 jcdutton Exp $
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
#include <alloca.h>
#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
#include <alsa/asoundlib.h>
#include <sys/ioctl.h>
#include <inttypes.h>
#include <pthread.h>
/*
#define ALSA_LOG
*/
/*
#define LOG_DEBUG
*/
#define AO_OUT_ALSA_IFACE_VERSION 7
#define BUFFER_TIME 1000*1000
#define PERIOD_TIME 100*1000
#define GAP_TOLERANCE 5000
#define MIXER_MASK_LEFT (1 << 0)
#define MIXER_MASK_RIGHT (1 << 1)
#define MIXER_MASK_STEREO (MIXER_MASK_LEFT|MIXER_MASK_RIGHT)
typedef struct alsa_driver_s {
snd_pcm_t *audio_fd;
int capabilities;
int open_mode;
int has_pause_resume;
int32_t output_sample_rate, input_sample_rate;
double sample_rate_factor;
uint32_t num_channels;
uint32_t bits_per_sample;
uint32_t bytes_per_frame;
uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
snd_pcm_uframes_t buffer_size;
int32_t mmap;
} alsa_driver_t;
static snd_output_t *jcd_out;
/*
* open the audio device for writing to
*/
int main (int argc, char **argv) {
alsa_driver_t variables;
alsa_driver_t *this = &variables;
char *pcm_device;
snd_pcm_stream_t direction = SND_PCM_STREAM_PLAYBACK;
snd_pcm_hw_params_t *params;
snd_pcm_sw_params_t *swparams;
snd_pcm_access_mask_t *mask;
snd_pcm_uframes_t period_size;
uint32_t periods;
uint32_t buffer_time=BUFFER_TIME;
int err, dir;
int open_mode=1; /* NONBLOCK */
/* int open_mode=0; BLOCK */
int rate = 48000;
int bits = 16;
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_sw_params_alloca(&swparams);
err = snd_output_stdio_attach(&jcd_out, stdout, 0);
pcm_device = "dmix";
#ifdef ALSA_LOG
printf("audio_alsa_out: Audio Device name = %s\n",pcm_device);
printf("audio_alsa_out: Number of channels = %d\n",this->num_channels);
#endif
this->audio_fd = NULL;
this->open_mode = open_mode;
this->input_sample_rate = rate;
this->bits_per_sample = bits;
this->num_channels = 2;
this->bytes_in_buffer = 0;
/*
* open audio device
*/
err=snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode);
if(err <0 ) {
printf ("audio_alsa_out: snd_pcm_open() of %s failed: %s\n", pcm_device, snd_strerror(err));
printf ("audio_alsa_out: >>> check if another program don't already use PCM <<<\n");
return 0;
}
/* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */
/* We wanted non blocking open but now put it back to normal */
//snd_pcm_nonblock(this->audio_fd, 0);
snd_pcm_nonblock(this->audio_fd, 1);
/*
* configure audio device
*/
err = snd_pcm_hw_params_any(this->audio_fd, params);
if (err < 0) {
printf ("audio_alsa_out: broken configuration for this PCM: no configurations available\n");
goto __close;
}
/* set interleaved access */
if (this->mmap != 0) {
mask = alloca(snd_pcm_access_mask_sizeof());
snd_pcm_access_mask_none(mask);
snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
err = snd_pcm_hw_params_set_access_mask(this->audio_fd, params, mask);
if (err < 0) {
printf ("audio_alsa_out: mmap not availiable, falling back to compatiblity mode\n");
this->mmap=0;
err = snd_pcm_hw_params_set_access(this->audio_fd, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
}
} else {
err = snd_pcm_hw_params_set_access(this->audio_fd, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
}
if (err < 0) {
printf ("audio_alsa_out: access type not available\n");
goto __close;
}
/* set the sample format ([SU]{8,16{LE,BE}})*/
err = snd_pcm_hw_params_set_format(this->audio_fd, params, (bits == 16) ?
#ifdef WORDS_BIGENDIAN
SND_PCM_FORMAT_S16_BE
#else
SND_PCM_FORMAT_S16_LE
#endif
: SND_PCM_FORMAT_U8);
if (err < 0) {
printf ("audio_alsa_out: sample format non available\n");
goto __close;
}
/* set the number of channels */
err = snd_pcm_hw_params_set_channels(this->audio_fd, params, this->num_channels);
if (err < 0) {
printf ("audio_alsa_out: Cannot set number of channels to %d (err=%d)\n", this->num_channels, err);
goto __close;
}
/* set the stream rate [Hz] */
dir=0;
err = snd_pcm_hw_params_set_rate_near(this->audio_fd, params, &rate, &dir);
if (err < 0) {
printf ("audio_alsa_out: rate not available\n");
goto __close;
}
this->output_sample_rate = (uint32_t)rate;
if (this->input_sample_rate != this->output_sample_rate) {
printf ("audio_alsa_out: audio rate : %d requested, %d provided by device/sec\n",
this->input_sample_rate, this->output_sample_rate);
}
/* Set period to buffer size ratios at 8 periods to 1 buffer */
dir=-1;
periods=8;
err = snd_pcm_hw_params_set_periods_near(this->audio_fd, params, &periods ,&dir);
if (err < 0) {
printf ("audio_alsa_out: unable to set any periods\n");
goto __close;
}
printf ("audio_alsa_out: Requested 8 periods, got %d\n", periods);
/* set the ring-buffer time [us] (large enough for x us|y samples ...) */
dir=0;
err = snd_pcm_hw_params_set_buffer_time_near(this->audio_fd, params, &buffer_time, &dir);
if (err < 0) {
printf ("audio_alsa_out: buffer time not available\n");
goto __close;
}
err = snd_pcm_hw_params_get_buffer_size(params, &(this->buffer_size));
#if 0
/* set the period time [us] (interrupt every x us|y samples ...) */
dir=0;
period_size=this->buffer_size/8;
err = snd_pcm_hw_params_set_period_size_near(this->audio_fd, params, &period_size, &dir);
if (err < 0) {
printf ("audio_alsa_out: period time not available");
goto __close;
}
#endif
dir=0;
err = snd_pcm_hw_params_get_period_size(params, &period_size, &dir);
if (2*period_size > this->buffer_size) {
printf ("audio_alsa_out: buffer to small, could not use\n");
goto __close;
}
/* write the parameters to device */
err = snd_pcm_hw_params(this->audio_fd, params);
if (err < 0) {
printf ("audio_alsa_out: pcm hw_params failed: %s\n", snd_strerror(err));
goto __close;
}
/* Check for pause/resume support */
this->has_pause_resume = ( snd_pcm_hw_params_can_pause (params)
&& snd_pcm_hw_params_can_resume (params) );
this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate;
this->bytes_per_frame = snd_pcm_frames_to_bytes (this->audio_fd, 1);
/*
* audio buffer size handling
*/
/* Copy current parameters into swparams */
err = snd_pcm_sw_params_current(this->audio_fd, swparams);
if (err < 0) {
printf ("audio_alsa_out: Unable to determine current swparams: %s\n", snd_strerror(err));
goto __close;
}
/* align all transfers to 1 sample */
err = snd_pcm_sw_params_set_xfer_align(this->audio_fd, swparams, 1);
if (err < 0) {
printf ("audio_alsa_out: Unable to set transfer alignment: %s\n", snd_strerror(err));
goto __close;
}
/* allow the transfer when at least period_size samples can be processed */
err = snd_pcm_sw_params_set_avail_min(this->audio_fd, swparams, period_size);
if (err < 0) {
printf ("audio_alsa_out: Unable to set available min: %s\n", snd_strerror(err));
goto __close;
}
/* start the transfer when the buffer contains at least period_size samples */
err = snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, period_size);
if (err < 0) {
printf ("audio_alsa_out: Unable to set start threshold: %s\n", snd_strerror(err));
goto __close;
}
/* never stop the transfer, even on xruns */
err = snd_pcm_sw_params_set_stop_threshold(this->audio_fd, swparams, this->buffer_size);
if (err < 0) {
printf ("audio_alsa_out: Unable to set stop threshold: %s\n", snd_strerror(err));
goto __close;
}
/* Install swparams into current parameters */
err = snd_pcm_sw_params(this->audio_fd, swparams);
if (err < 0) {
printf ("audio_alsa_out: Unable to set swparams: %s\n", snd_strerror(err));
goto __close;
}
#ifdef ALSA_LOG
snd_pcm_dump_setup(this->audio_fd, jcd_out);
snd_pcm_sw_params_dump(swparams, jcd_out);
#endif
// return this->output_sample_rate;
__close:
snd_pcm_close (this->audio_fd);
this->audio_fd=NULL;
return 0;
}
next prev parent reply other threads:[~2003-09-01 23:08 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-09-01 0:59 dmix bugs. sounds very broken up James Courtier-Dutton
2003-09-01 6:08 ` Jaroslav Kysela
2003-09-01 23:08 ` James Courtier-Dutton [this message]
[not found] ` <Pine.LNX.4.53.0309021232410.29300@pnote.perex-int.cz>
2003-09-02 11:50 ` James Courtier-Dutton
2003-09-04 9:46 ` Jaroslav Kysela
2003-09-09 8:05 ` Safe to call snd_pcm_close after failed snd_pcm_open? Arve Knudsen
2003-09-09 9:04 ` Jaroslav Kysela
2003-09-02 13:20 ` dmix bugs. sounds very broken up James Courtier-Dutton
2003-09-02 15:19 ` Jaroslav Kysela
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3F53D15B.3090507@superbug.demon.co.uk \
--to=james@superbug.demon.co.uk \
--cc=alsa-devel@lists.sourceforge.net \
--cc=perex@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.