Question

I am working on an ALSA capture routine on a quad core debian box and I am baffled.

Basic ALSA capture, hw:0 interface, 16 bits, 44.1 KHz, using a blocking thread with poll(), controlled by snd_pcm_start() and snd_pcm_drop(). I check the return values of all ALSA API calls. Basic capture is working fine but I cannot figure out how to set the poll rate (that is, how often ALSA notifies my poll() routine to return because frames are available to be read).

I use snd_pcm_sw_params_set_avail_min() to set this to 2048 frames and poll() returns when there are about 2048 frames available to read. I call snd_pcm_avail_delay() before I call snd_pcm_readi() and it all appears reasonable. But if I set it to anything less than 2048 I get inconsistent results. If I set the avail_min to 1024 half of the time poll() returns when there is around 1024 frames available and half of the time not until 1500 frames are available. When I set the avail_min to 512, the very 1st read is 512 but then 95% of the subsequent reads are 1024 frames or larger. When I call snd_pcm_hw_params_get_period_size_min/max() this device reports a valid range of 16-8192 frames, so a period of 512 frames does not seem unreasonable--the driver reports that the hw supports it.

I have tried every combination of snd_pcm_sw_params_set_avail_min(), snd_pcm_hw_params_set_period_size() and snd_pcm_sw_params_set_start_threshold(), but still cannot get reasonable results.

I have tried nailing this thread up to a single CPU core with the pthread setaffinity. I have tried sched_setschedule() to give the process 'soft' real time priorities. Nothing seems to allow me to get consistent poll() returns except setting the avail_min to at least 2048.

So here are some ALSA questions:

  1. Is the start threshold (using snd_pcm_sw_params_set_start_threshold() only relevant for async capture? That is, the start threshold does not seem applicable for poll() based capture. Is this correct?

  2. What is the difference between the period size in frames and the avail_min size in frames? The documentation seems to imply that the avail_min sets the point at which the poll() will return because there are at least that many frames available to be read. The period size is a hw parameter but the API still provides a minimum and maximum value and a way to set it. It seems to me that they are really the same thing but I cannot get my poll() to return according to the period I set.

  3. Have I misread the documentation when I interpret the intent of the snd_pcm_sw_params_set_avail_min() to set the target number of available captured frames for triggering the poll() routine?

  4. Is it reasonable for me to expect that poll() should return more consistently than whenever there is anywhere between 500 and 1500 frames available for reading? or is this normal behavior and I should expect wide variations in the number of frames that are available for reading?

  5. If wide variations are to be expected, is it best to always read the total available frames as reported by snd_pcm_avail() or is it best to read a set number of frames each time poll() returns?

Was it helpful?

Solution

The start threshold does not make much sense for capture devices; just set it to 1.

The hardware fills the capture buffer continuously, but raises an interrupt only at the end of each period. When ALSA is waiting for some data to be available (in poll or in snd_pcm_read*), it will not return before avail_min frames are available. However, this check is done only at the start of the function, or when it is woken up by the interrupt.

Therefore, if you do not want to wait for too long, you have to make the period size short enough.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top