[BUG?] Setting (start_threshold > stop_threshold) makes snd_pcm_writei(a_small_buffer) XRUN immediately

Zhang Boyang zhangboyang.id at gmail.com
Mon Oct 4 11:48:49 CEST 2021


On 2021/10/2 12:45, Geraldo Nascimento wrote:
> On Fri, Oct 01, 2021 at 10:01:34PM -0300, Geraldo Nascimento wrote:
>> On Fri, Oct 01, 2021 at 08:33:23PM -0300, Geraldo Nascimento wrote:
>>> On Sat, Oct 02, 2021 at 01:31:12AM +0800, Zhang Boyang wrote:
>>>> Hello,
>>>
>>> Hello, Zhang!
>>>
>>>>
>>>>     I'm using ALSA to develop an audio-streaming application. I try to
>>>> use start_threshold and stop_threshold in combination with small
>>>> buffers. However, I think I probably found a bug about this.
>>>>     I'm setting start_threshold=100 and stop_threshold=50. I'm also using
>>>> a buffer of 44 frames. When I call
>>>> snd_pcm_writei(the_small_44_frames_buffer), pcm state came to XRUN from
>>>> PREPARED directly. I think this is a bug because the stream hasn't
>>>> started. It's hard to say a xrun occurred while stream not started.
>>>>     I'm wondering if this is a ALSA-bug or a misuse of ALSA. A simple bug
>>>> test program is attached.
>>>
>>> No, I don't think it's a bug. You're bound to run into problems with a
>>> period size of only 44 frames.
>>>
>>> Moreover, working with the code you provided, I was able to get a RUNNING
>>> state without XRUNs with a period size of 4410 frames (100 milliseconds of
>>> audio) but I had to comment out snd_pcm_sw_params_set_stop_threshold() for
>>> it to work or I'd have those instant XRUNs.
>>>
>>> That's how snd_pcm_sw_params_set_stop_threshold() is supposed to work by
>>> the way. It creates a XRUN once the threshold is hit.
>>
>> Oh, and snd_pcm_sw_params_set_stop_threshold() is a little
>> counter-intuitive. The threshold you give the function is compared to
>> the available free space in the ring buffer, not the filled space.
>>
>> That's why lowering the stop threshold makes XRUNs more likely...
>>
>> Thanks,
>> Geraldo Nascimento
> 
> Zhang,
> 
> I was able to make your code work in the end, even with 44 frames
> writes, which is unadvisable since it eats too much CPU specially if
> they are low-end like the ARM64 box I'm writing you from.
> 
> The trick was to use high values such as 500000. Lower values such as
> 250000 were enough to trigger XRUNs in my machine. Of course you can set
> it to -1 and it will ignore XRUNs but that's a bit like setting it to
> 16777216 or 4096 * 4096 which is a hardcoded limit in alsa-lib, I
> believe.
> 
> And plainly ignoring XRUNs may sound bad under load, believe me.
> 
> Thank you,
> Geraldo Nascimento
> 
> 

Hi,

Thank you for your reply.

I realized my mistake about the meaning of stop_threshold. The 
stop_threshold should be (bufsz-50), where (bufsz = alsa buffer size). I 
fixed my code and new code is attached.

However, the problem still exists. I'm trying to minimize audio latency, 
so I must use a small buffer. In fact, the problem is not related to the 
absoulte size of buffer, but the relationship between the size of 
start_threshold, stop_threshold and the buffer. The problem still exists 
even using manual start mode (i.e. start_threshold>bufsz).

Currently, I'm using a workaround. After PREPARED or XRUN'd, I manually 
buffer incoming audio frames, and when (n_buffered_frames >= 
start_threshold && n_buffered_frames >= bufsz-stop_threshold), I write 
them in a single write() call. Note that the write must in whole, any 
short write may result in immediate XRUN.

Anyway, Thank you for your advice. Have a nice day. :)

Zhang Boyang
-------------- next part --------------
A non-text attachment was scrubbed...
Name: start_stop_threshold_bug.c
Type: text/x-csrc
Size: 5350 bytes
Desc: not available
URL: <http://mailman.alsa-project.org/pipermail/alsa-devel/attachments/20211004/404509fa/attachment.bin>


More information about the Alsa-devel mailing list