[alsa-devel] Default device XRUNs with perriods=2
Hi,
I am trying to debug/fix some problems with Portaudio on Linux platform, and would appreciate assistance from Alsa experts.
The 'default' pcm on the test systems here (Suse 9 and SLED10), is standard for the configuration and includes dmix and plug conversion, with fixed period of 1024 at 48000. Pulseaudio is not on these systems.
When playing data (using a polling mechanism) at 48000 both 3 (or more) and 2 periods of buffer work fine; with the fixed period of 1024 the lowest latency is 2 * 1024 / 48000 = 42.6ms.
However, at 44100, 2 periods does not run properly at all, but 3 does. The periods in this case are (940, 941) due to the rate conversion.
What I see (captured on another machine) from start of the stream is one 21.3ms period of good audio, a discontinuity followed by some variable amount of out-of-sync audio, and a section of silence.
I believe that the discontinuity corresponds to the point at which snd_pcm_poll_descriptors_revents() returns POLLERR and portaudio detects the POLLERR and restarts the stream, so that after a certain delay there is another 21.3ms of audio, POLLERR, now no out-of-sync audio, just silence, before it all repeats. So it stutters only outputting 21.3ms bursts of audio.
The CPU usage during this is about 2%. I am suspecting some mis-configuration, or is it wrong to expect this to work at 2 periods due to the rate conversion etc?
Any pointers etc would be really appreciated. This is the info dump:-
ACCESS: MMAP_INTERLEAVED FORMAT: FLOAT_LE SUBFORMAT: STD SAMPLE_BITS: 32 FRAME_BITS: 64 CHANNELS: 2 RATE: 44100 PERIOD_TIME: (21333 21334) PERIOD_SIZE: (940 941) PERIOD_BYTES: (7520 7528) PERIODS: 2 BUFFER_TIME: (42653 42654) BUFFER_SIZE: 1881 BUFFER_BYTES: 15048 TICK_TIME: 0
start_mode: DATA xrun_mode: STOP tstamp_mode: MMAP period_step: 1 sleep_min: 0 avail_min: 940 xfer_align: 1 silence_threshold: 0 silence_size: 4235635449541951488 boundary: 4235635449541951488 stream : PLAYBACK access : MMAP_INTERLEAVED format : FLOAT_LE subformat : STD channels : 2 rate : 44100 exact rate : 44100 (44100/1) msbits : 32 buffer_size : 1881 period_size : 940 period_time : 21333 tick_time : 0 tstamp_mode : MMAP period_step : 1 sleep_min : 0 avail_min : 940 xfer_align : 1 start_threshold : 940 stop_threshold : 1881 silence_threshold: 0 silence_size : 4235635449541951488 boundary : 4235635449541951488
Regards
Alan
Hi Takashi,
After several days dissecting, mainly with printf's, I have tracked the events that cause the problem I originally posted about with Portaudio playback to the default device at 44100Hz. Could you confirm that the Alsa behaviour is what should be expected, please?
It seems that at a period boundary event snd_pcm_mmap_playback_avail() may not return a full period size, but is a few bytes short. If avail_min is set to one whole period (which Portaudio at present does), snd_pcm_direct_poll_revents() zeroes the revent due to the check of snd_pcm_mmap_playback_avail() against avail_min. POLLOUT is therefore not indicated, and the app does not write any data, causing an Xrun.
However, if the absence of POLLOUT is ignored, calling snd_pcm_avail_update() at that time returns a full period size.
This only seems to happen on the default device when playing at a sample rate not corresponding to the dmix rate of 48000, presumably due to the plugins/conversions?
The solution from the Portaudio point-of-view is to set avail_min lower, but I wanted to check with you that the values being returned are sane.
Thanks
Alan
This is not a top-post - but here is the original posting for reference:-
On Monday 31 October 2011 17:38, I wrote:
I am trying to debug/fix some problems with Portaudio on Linux platform, and would appreciate assistance from Alsa experts.
The 'default' pcm on the test systems here (Suse 9 and SLED10), is standard for the configuration and includes dmix and plug conversion, with fixed period of 1024 at 48000. Pulseaudio is not on these systems.
When playing data (using a polling mechanism) at 48000 both 3 (or more) and 2 periods of buffer work fine; with the fixed period of 1024 the lowest latency is 2 * 1024 / 48000 = 42.6ms.
However, at 44100, 2 periods does not run properly at all, but 3 does. The periods in this case are (940, 941) due to the rate conversion.
What I see (captured on another machine) from start of the stream is one 21.3ms period of good audio, a discontinuity followed by some variable amount of out-of-sync audio, and a section of silence.
I believe that the discontinuity corresponds to the point at which snd_pcm_poll_descriptors_revents() returns POLLERR and portaudio detects the POLLERR and restarts the stream, so that after a certain delay there is another 21.3ms of audio, POLLERR, now no out-of-sync audio, just silence, before it all repeats. So it stutters only outputting 21.3ms bursts of audio.
The CPU usage during this is about 2%. I am suspecting some mis-configuration, or is it wrong to expect this to work at 2 periods due to the rate conversion etc?
Any pointers etc would be really appreciated. This is the info dump:-
ACCESS: MMAP_INTERLEAVED FORMAT: FLOAT_LE SUBFORMAT: STD SAMPLE_BITS: 32 FRAME_BITS: 64 CHANNELS: 2 RATE: 44100 PERIOD_TIME: (21333 21334) PERIOD_SIZE: (940 941) PERIOD_BYTES: (7520 7528) PERIODS: 2 BUFFER_TIME: (42653 42654) BUFFER_SIZE: 1881 BUFFER_BYTES: 15048 TICK_TIME: 0
start_mode: DATA xrun_mode: STOP tstamp_mode: MMAP period_step: 1 sleep_min: 0 avail_min: 940 xfer_align: 1 silence_threshold: 0 silence_size: 4235635449541951488 boundary: 4235635449541951488 stream : PLAYBACK access : MMAP_INTERLEAVED format : FLOAT_LE subformat : STD channels : 2 rate : 44100 exact rate : 44100 (44100/1) msbits : 32 buffer_size : 1881 period_size : 940 period_time : 21333 tick_time : 0 tstamp_mode : MMAP period_step : 1 sleep_min : 0 avail_min : 940 xfer_align : 1 start_threshold : 940 stop_threshold : 1881 silence_threshold: 0 silence_size : 4235635449541951488 boundary : 4235635449541951488
There's been no take-up on this, but I am seeing a consistent issue, with Alsa from 1.0.12 to 1.0.24, on 2 different machines with different audio hardware which will need to be worked around one way or another, and I wonder which is best?
The problem is with poll revents from default device when it includes SR conversion and dmix.
On Thursday 03 November 2011 10:03, I wrote:
After several days dissecting, mainly with printf's, I have tracked the events that cause the problem I originally posted about with Portaudio playback to the default device at 44100Hz. Could you confirm that the Alsa behaviour is what should be expected, please?
It seems that at a period boundary event snd_pcm_mmap_playback_avail() may not return a full period size, but is a few bytes short. If avail_min is set to one whole period (which Portaudio at present does), snd_pcm_direct_poll_revents() zeroes the revent due to the check of snd_pcm_mmap_playback_avail() against avail_min. POLLOUT is therefore not indicated, and the app does not write any data, causing an Xrun.
However, if the absence of POLLOUT is ignored, calling snd_pcm_avail_update() at that time returns a full period size.
This only seems to happen on the default device when playing at a sample rate not corresponding to the dmix rate of 48000, presumably due to the plugins/conversions?
The solution from the Portaudio point-of-view is to set avail_min lower, but I wanted to check with you that the values being returned are sane.
This only works with the older Alsa versions, since avail_min cannot be set to less than period size more rrecently.
It seems the options are:-
1. Use 3 periods and accept worse latency, always filling with avail_frames
2. Use 3 periods, but only fill partially, so there is, for example, always one period of space after filling, and at a poll nearly 2
3. Ignore the absence of POLLOUT or POLLIN flag, and instead treat the zero revent as good, check avail_frames and fill the buffer
4. I have misunderstood some detail in the use of Alsa which is causing this, and when corrected the issue will not occur.
Assistance to solve this would be greatly appreciated, since ultimately I would like to see Portaudio work well without issues on Linux/Alsa. If more info would help, please ask.
Thanks
Alan
2011/11/25 Alan Horstmann gineera@aspect135.co.uk:
There's been no take-up on this, but I am seeing a consistent issue, with Alsa from 1.0.12 to 1.0.24, on 2 different machines with different audio hardware which will need to be worked around one way or another, and I wonder which is best?
The problem is with poll revents from default device when it includes SR conversion and dmix.
On Thursday 03 November 2011 10:03, I wrote:
After several days dissecting, mainly with printf's, I have tracked the events that cause the problem I originally posted about with Portaudio playback to the default device at 44100Hz. Could you confirm that the Alsa behaviour is what should be expected, please?
It seems that at a period boundary event snd_pcm_mmap_playback_avail() may not return a full period size, but is a few bytes short. If avail_min is set to one whole period (which Portaudio at present does), snd_pcm_direct_poll_revents() zeroes the revent due to the check of snd_pcm_mmap_playback_avail() against avail_min. POLLOUT is therefore not indicated, and the app does not write any data, causing an Xrun.
However, if the absence of POLLOUT is ignored, calling snd_pcm_avail_update() at that time returns a full period size.
This only seems to happen on the default device when playing at a sample rate not corresponding to the dmix rate of 48000, presumably due to the plugins/conversions?
The solution from the Portaudio point-of-view is to set avail_min lower, but I wanted to check with you that the values being returned are sane.
This only works with the older Alsa versions, since avail_min cannot be set to less than period size more rrecently.
b0b7d0280f977dee1bbff0a1b4cd0c50068d2371
Do you require the sound card give you accurate playback position ?
snd-ymfpci only update hwptr in 5.3ms intervals
it seem that snd-usb-audio update hwptr in 1ms
It seems the options are:-
- Use 3 periods and accept worse latency, always filling with avail_frames
snd-ymfpci has periods_min 3 and there are sound cards with periods_max = 2
- Use 3 periods, but only fill partially, so there is, for example, always
one period of space after filling, and at a poll nearly 2
- Ignore the absence of POLLOUT or POLLIN flag, and instead treat the zero
revent as good, check avail_frames and fill the buffer
- I have misunderstood some detail in the use of Alsa which is causing this,
and when corrected the issue will not occur.
Assistance to solve this would be greatly appreciated, since ultimately I would like to see Portaudio work well without issues on Linux/Alsa. If more info would help, please ask.
Thanks
Alan
On Sunday 27 November 2011 01:40, Raymond Yau wrote:
2011/11/25 Alan Horstmann gineera@aspect135.co.uk:
There's been no take-up on this, but I am seeing a consistent issue, with Alsa from 1.0.12 to 1.0.24, on 2 different machines with different audio hardware which will need to be worked around one way or another, and I wonder which is best?
The problem is with poll revents from default device when it includes SR conversion and dmix.
<snip>
Thanks Raymond for avoiding this thread becoming a monologue.
b0b7d0280f977dee1bbff0a1b4cd0c50068d2371
Thanks; there are a few threads that discuss problems with avail_min, periods == 2, and timing inconsistencies. The more I read over and again it seems rather a can-of-worms.
Do you require the sound card give you accurate playback position ?
No. Just accurate playback (or capture). But reliably, on any system, without hardware-specific tweaks, 'out-of-the-box'. Ideally with the potential for reasonable latency if the user requests that. And not necessarily only on the 'latest' Alsa versions.
As per this quote from Jaroslav in one of the threads:-
"But it's right that most of simple applications and use cases expect that I/O transfers will work even with 2 periods.
That does not work in the 'default' circumstances I am describing here, on several hardwares on any Alsa version.
snd-ymfpci only update hwptr in 5.3ms intervals
it seem that snd-usb-audio update hwptr in 1ms
It seems the options are:-
- Use 3 periods and accept worse latency, always filling with
avail_frames
snd-ymfpci has periods_min 3 and there are sound cards with periods_max = 2
Yes, this is the sort of thing that makes it more difficult to create a good workaround.
- Use 3 periods, but only fill partially, so there is, for example,
always one period of space after filling, and at a poll nearly 2
- Ignore the absence of POLLOUT or POLLIN flag, and instead treat the
zero revent as good, check avail_frames and fill the buffer
My current thinking (but could change) is for this one; if poll returns successfully, and the revent is not POLLERR or POLLHUP, don't check for non-zero (POLLIN or POLLOUT) but treat it as a valid period event regardless and perform the processing, checking avail_frames etc.
Such an approach effectively removes the check on snd_pcm_mmap_playback_avail() in the function snd_pcm_direct_poll_revents().
- I have misunderstood some detail in the use of Alsa which is causing
this, and when corrected the issue will not occur.
Alan
Alan Horstmann wrote:
It seems that at a period boundary event snd_pcm_mmap_playback_avail() may not return a full period size, but is a few bytes short. If avail_min is set to one whole period (which Portaudio at present does), snd_pcm_direct_poll_revents() zeroes the revent due to the check of snd_pcm_mmap_playback_avail() against avail_min. POLLOUT is therefore not indicated, and the app does not write any data, causing an Xrun.
This sounds like a bug in the rate plugin. snd_pcm_rate_sync_hwptr() tries to properly align pointer values at period boundaries, but its algorithm doesn't work when a period does not start at the buffer start (i.e., when the number of periods is not an integer), and this restriction is not actually enforced by snd_pcm_rate_hw_refine_cchange().
As a workaround, try snd_pcm_hw_params_set_periods_integer().
Regards, Clemens
On Monday 28 November 2011 21:12, Clemens Ladisch wrote:
Alan Horstmann wrote:
It seems that at a period boundary event snd_pcm_mmap_playback_avail() may not return a full period size, but is a few bytes short. If avail_min is set to one whole period (which Portaudio at present does), snd_pcm_direct_poll_revents() zeroes the revent due to the check of snd_pcm_mmap_playback_avail() against avail_min. POLLOUT is therefore not indicated, and the app does not write any data, causing an Xrun.
This sounds like a bug in the rate plugin. snd_pcm_rate_sync_hwptr() tries to properly align pointer values at period boundaries, but its algorithm doesn't work when a period does not start at the buffer start (i.e., when the number of periods is not an integer), and this restriction is not actually enforced by snd_pcm_rate_hw_refine_cchange().
As a workaround, try snd_pcm_hw_params_set_periods_integer().
Thanks Clemens. Integer period for the pcm is actually already being set. Since the Alsa docs are unclear, can you confirm that this refers to integer number_of_periods, not integer frames_per_period?
I have experimented removing that setting. Then the hw_params shows
PERIODS:[2 3) (with square bracket!)
whereas with integer periods this was just 2. However, there seems no change in the problematic behaviour. Also the buffer size is 1881 in both cases.
Can you also explain how the non-integer period *size* is handled? In the test case, dmix is set to 48000 with period 1024. So at 44100 the rate conversion means the corresponding period size is 940.8. I am not sure how that gets handled. From the params dump giving period as (940 941) I had anticipated that a mixture of 4 * 941 and one 940 period would occur. However, what I see is that at a period boundary there is always just 940 avail_frames - is that correct? How does that get converted to the 1024 frames at 48000? Will there be irregular timing?
I had also tried not quite filling the buffer completely - eg deducting 10 from avail_frames. This is effective in ensuring the POLLOUTs are mostly not cancelled out, since the avail_frames is 950 not 940 each period, and this seems to be enough that snd_pcm_mmap_playback_avail() is larger than the period size. However at start-up this on it's own did not avoid xruns.
Regards
Alan
Alan Horstmann wrote:
On Monday 28 November 2011 21:12, Clemens Ladisch wrote:
As a workaround, try snd_pcm_hw_params_set_periods_integer().
Integer period for the pcm is actually already being set.
Strange; there's a bug somewhere ...
Can you also explain how the non-integer period *size* is handled?
There are no non-integer period sizes.
In the test case, dmix is set to 48000 with period 1024. So at 44100 the rate conversion means the corresponding period size is 940.8. I am not sure how that gets handled. From the params dump giving period as (940 941) I had anticipated that a mixture of 4 * 941 and one 940 period would occur. However, what I see is that at a period boundary there is always just 940 avail_frames - is that correct?
Have a look in /proc/asound/cardX/pcm0p/sub0/hw_params.
How does that get converted to the 1024 frames at 48000? Will there be irregular timing?
The rate plugin uses the proportion of the two period sizes for rate conversion. In your example, 940 samples are always converted into 1024 samples; the actual sample rate is 48000/1024*940 = 44062.5.
Regards, Clemens
On Tuesday 29 November 2011 15:21, Clemens Ladisch wrote:
Alan Horstmann wrote:
On Monday 28 November 2011 21:12, Clemens Ladisch wrote:
As a workaround, try snd_pcm_hw_params_set_periods_integer().
Integer period for the pcm is actually already being set.
Strange; there's a bug somewhere ...
Is there any useful debug I can do?
Can you also explain how the non-integer period *size* is handled?
There are no non-integer period sizes.
That is very enlightening.
How does that get converted to the 1024 frames at 48000? Will there be irregular timing?
The rate plugin uses the proportion of the two period sizes for rate conversion. In your example, 940 samples are always converted into 1024 samples; the actual sample rate is 48000/1024*940 = 44062.5.
So when snd_pcm_hw_params_get_rate_numden() gives a rate of 44100 it is not being completely accurate? Is there a better way to discover what the exact effective rate will be (ideally after configuring but before starting the stream)? In this case, it looks like period size 941 would give closer (44109)?
On the matter of work-arounds (for the missing POLLOUT), does it seem safe to just check the revents (after poll() returns) for POLLERR and POLLHUP, and if neither occurred then continue as if POLLIN or POLLOUT were present, checking avail_frames and mmapping data? Or is that likely to cause other issues on some occasions?
Regards
Alan
participants (3)
-
Alan Horstmann
-
Clemens Ladisch
-
Raymond Yau