alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* Problem when using silence 'trick'
@ 2011-02-24  8:11 Bryan Ischo
  2011-02-25 20:37 ` Bryan Ischo
  2011-02-28  8:34 ` Clemens Ladisch
  0 siblings, 2 replies; 3+ messages in thread
From: Bryan Ischo @ 2011-02-24  8:11 UTC (permalink / raw)
  To: alsa-devel

Hi ALSA developers!

I am working on my first project that uses sound under Linux, and I've 
chosen to implement directly to the ALSA API.  I am amazed that I was 
able to get sound working in so few lines of code with ALSA.  I like the 
API and its performance alot but I have a problem!

My program, early in its development, wanted to play just one sound 
stream at a time; and it is a sound stream which normally delivers audio 
at a sufficent rate to avoid XRUN but in some circumstances the thread 
generating audio cannot keep up and it falls behind, resulting in XRUN.  
Well I found that in cases where the audio thread is 'almost' keeping 
up, the standard behavior of allowing an XRUN to occur, detecting it on 
the next call to snd_pcm_writei, and 'fixing' it by calling 
snd_pcm_prepare() and then proceeding to continue delivering audio 
frames, had the following unfortunate problems:

1. The audio sounds crackly and awful (which is to be expected to some 
degree with XRUN)
2. The time taken to re-prepare the ALSA device is counterproductive; it 
takes even more time away from the thread that is delivering audio and 
thus makes the case where the audio is very marginally behind 'real 
time' much worse.

I thought, if only I could tell ALSA to just play silence if it has run 
out of frames of audio instead of XRUNning, and then I can add real 
frames of audio back in as soon as they are available and pick up the 
audio stream where it left off.

Some digging into the ALSA API and I found that someone on the ALSA team 
had already beaten me to the thought!  The API docs kind of hint at how 
you would go about doing this, and I found this technique to be very 
successful:

1. Use snd_pcm_sw_params_set_stop_threshold to set the stop threshold to 
0.  Now, no XRUN - ALSA will keep looping in the circular buffer and 
play whatever is there; and if you haven't updated quickly enough, you 
just get looping snippets of audio.

2. Use snd_pcm_sw_params_set_silence_threshold to 0 and 
snd_pcm_sw_params_set_silence_size to set the silence 'size' to the 
boundary value obtained by calling snd_pcm_sw_params_get_boundary().  
Now ALSA is instructed to fill the already-played portions of the 
circular buffer with silence, which means that even when looping due to 
XRUN, no sound is played over and over, instead silence is played.

Hey presto - works perfectly!

Then later on I needed to play more than one sound simultaneously.  It 
turns out that I had been opening the "plughw:0,0" device originally and 
this had been working great with my sound trick.  The problem is, you 
cannot use plughw:0,0 and open it more than once to play more than one 
sound simultaneously; the second open will fail.

So after some digging I found that the device I really should have been 
using all along is called "default" (hey, you'd think it would be 
obvious, but somehow I never found ALSA documentation that told me to do 
this).

Now the real problem: when I use the "default" device with my silence 
technique, I have no problem playing multiple audio streams 
simultaneously by opening the "default" device multiple times and 
simultaneously playing streams into the different devices.  BUT, 
whenever I cannot deliver audio fast enough to a stream, and the silence 
trick takes over and the stream plays some silence - boom, the device 
goes silent forever.  I don't get any errors from any ALSA function, I 
just get silence no matter what I write into the device after that 
point.  This is in sharp contrast to the plughw:0,0 device, which does 
play silence if I don't deliver audio fast enough but immediately plays 
whatever audio I do end up delivering to it when I finally have audio to 
deliver.

Am I using an invalid technique with this silence trick?
Is this a known and expected behavior of the "default" device?
Or could something else be going on?

Thanks for any advice you can give!

Best wishes,
Bryan

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Problem when using silence 'trick'
  2011-02-24  8:11 Problem when using silence 'trick' Bryan Ischo
@ 2011-02-25 20:37 ` Bryan Ischo
  2011-02-28  8:34 ` Clemens Ladisch
  1 sibling, 0 replies; 3+ messages in thread
From: Bryan Ischo @ 2011-02-25 20:37 UTC (permalink / raw)
  To: alsa-devel

On 02/24/11 00:11, Bryan Ischo wrote:
> Hi ALSA developers!
>
> I am working on my first project that uses sound under Linux, and I've 
> chosen to implement directly to the ALSA API.  I am amazed that I was 
> able to get sound working in so few lines of code with ALSA.  I like 
> the API and its performance alot but I have a problem!
>

My apologies for sending this to the wrong mailing list.  When I read 
that alsa-devel was for "work on ... an ALSA application", I assumed 
that this was any application; but now I realize that it is probably for 
official ALSA tools, not general third party applications that are not 
associated with the ALSA project.  I will send my question to alsa-user.

Sorry again, and best wishes,
Bryan

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Problem when using silence 'trick'
  2011-02-24  8:11 Problem when using silence 'trick' Bryan Ischo
  2011-02-25 20:37 ` Bryan Ischo
@ 2011-02-28  8:34 ` Clemens Ladisch
  1 sibling, 0 replies; 3+ messages in thread
From: Clemens Ladisch @ 2011-02-28  8:34 UTC (permalink / raw)
  To: Bryan Ischo; +Cc: alsa-devel

Bryan Ischo wrote:
> [...] when I use the "default" device with my silence
> technique, I have no problem playing multiple audio streams
> simultaneously by opening the "default" device multiple times and
> simultaneously playing streams into the different devices.  BUT,
> whenever I cannot deliver audio fast enough to a stream, and the silence
> trick takes over and the stream plays some silence - boom, the device
> goes silent forever.

I tried to reproduce this with mplayer (which uses the same technique),
but couldn't.

Have a look at mplayer's ALSA output driver here:
<http://git.ffmpeg.org/?p=mplayer;a=blob;hb=master;f=libao2/ao_alsa.c>
It regularly calls get_delay() before writing samples, and there uses
snd_pcm_forward() to catch up if an underrun has occurred.

> My apologies for sending this to the wrong mailing list.  When I read
> that alsa-devel was for "work on ... an ALSA application", I assumed
> that this was any application; but now I realize that it is probably for
> official ALSA tools, not general third party applications that are not
> associated with the ALSA project.

This list is correct for questions about the ALSA API.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-02-28  8:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-24  8:11 Problem when using silence 'trick' Bryan Ischo
2011-02-25 20:37 ` Bryan Ischo
2011-02-28  8:34 ` Clemens Ladisch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).