[alsa-devel] My issues with the ALSA API
Heya!
A while back I compiled a list of issues I found with the ALSA API while I was hacking PulseAudio. I kept it up to date ever since. It has the title "Why I hate ALSA", but this is merely a catchy title, I am not trying to offend anyone, nor do I think that the ALSA API is particularly bad.
Back at FOMS in January this year, I showed this list to James. He acknowledged most of those issues. But I am sure that the other ALSA devs might be interested too:
http://pulseaudio.org/wiki/WhyIHateALSA
Comments welcome!
Thank you,
Lennart
On Thu, 10 Apr 2008, Lennart Poettering wrote:
I started to work on some issues. Note that your requirements are a bit more complex than normal applications need and we're mostly driven by user requests. Some things are misleading (or they are already implemented) in your comments:
Mixer =====
Please explain this question (why you need the dB <-> value conversion, we assumed that application works in dB or integer range not both):
'It is possible to query the dB range of a smixer element. And it is possible to query and set the current dB level. However, it is not possible to have a dB value converted to an integer level or vice versa, without touching the actual setting. i.e. a question like "What is the integer level 0 dB corresponds to?" can not be answered by ALSA. Which happens to be a serious limitation.'
PCM ===
Timestamps - since 1.0.16 monotonic clocks are usable
plughw: issue - since 1.0.16 you can pass SND_PCM_NO_AUTO flags to open function to disable specific conversions
buffer mananagement - I think we already discussed this - use sw_params or PCM timer to be updated when buffer position changes (interrupt was processed), you can use poll() as well
What do you mean with 'There is no API to query the granularity of snd_pcm_delay()' ? Application should not know details about bottom implementation.
General =======
Documentantion - if you ask specific questions, we try to update documentantion for other developers.. unfortunately, saying that whole documentantion is bad is not productive
stderr output - you can redirect all outputs via snd_lib_error_set_handler().
========================================
My plans for near future are to implement a better PCM device enumeration and try to simplify mixer and add the mixer <-> PCM relationship.
Also, could you explain why current device enumeration is not useful to hotplug? There is information which card will be used (CARD=).
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
On Thu, 10.04.08 10:16, Jaroslav Kysela (perex@perex.cz) wrote:
Mixer
Please explain this question (why you need the dB <-> value conversion, we assumed that application works in dB or integer range not both):
'It is possible to query the dB range of a smixer element. And it is possible to query and set the current dB level. However, it is not possible to have a dB value converted to an integer level or vice versa, without touching the actual setting. i.e. a question like "What is the integer level 0 dB corresponds to?" can not be answered by ALSA. Which happens to be a serious limitation.'
I can think of many reasons, they all have to do with the fact that the dB scale is not integral, i.e. in contrast for the normal integer scale you won't always get what you are asking for, because the hardware only supports a value below or above what you asked for: a) a volume control tool might want to show a slider that is linear to the dB scale, but also shows which dB values are actually selectable from it via small black lines on the side (or suchlike) b) PA doesn't make use of positive dB values -- it limits itself to attenuation via the mixer. However, right now there is no way to find out which actually supported dB value is the nearest one to 0dB. c) Several different dB values may refer to the same actual hw setting. It would be good if a specific dB value actually maps to the same integer hw setting as some other value, to surpress redundant "volume change" events.
And I am pretty sure people could think of more cases.
PCM
Timestamps - since 1.0.16 monotonic clocks are usable
Hmm, not really, as I hope I made clear in my other posting.
plughw: issue - since 1.0.16 you can pass SND_PCM_NO_AUTO flags to open function to disable specific conversions
Awesome, thank you very much! This is exactly what I need. I updated the page accordingly.
buffer mananagement - I think we already discussed this - use sw_params or PCM timer to be updated when buffer position changes (interrupt was processed), you can use poll() as well
I am doing this now. I'd still love to see an API for naked interrupts, though.
What do you mean with 'There is no API to query the granularity of snd_pcm_delay()' ? Application should not know details about bottom implementation.
As far as I understood there are a few soundcards around where the playback sample index is only known each time the hw changes to the next fragment. It would be good to know about this, to tweak the time interpolation in timer-based scheduling.
Documentantion - if you ask specific questions, we try to update documentantion for other developers.. unfortunately, saying that whole documentantion is bad is not productive
Sorry. I'll make sure I'll ask for clarifications more clearly on alsa-devel from now on.
Here's my first batch of questions:
I am not sure I get what the "transfer align" is about.
It is not clear how snd_pcm_update_avail() and snd_pcm_hwsync() actually play together, why they exist at all, and how exactly the optimization they are apparently useful for should be used.
It would be good to have an explanation what a "card", what an "id", what a "name", what a "device" and what a "subdevice" actually refers to, with examples.
regarding hw params: What exactly is "double buffering", "sample-resolution mmap", "block transfer", "batch", "sync_start" , "fifo_size", "subformat", "export buffer", "min align"; why there is a need for a seperate can_pause() and can_resume()? When and how should all these options be used?
BTW: the doc for is_batch is copied 1:1 from the double_buffer text.
The docs speak of "blocked" and "non-blocked" open. It should be "blocking", I believe.
regarding sw params: What exactly is a "boundary"? Difference between tstamp modes? how do silence_size and silence_threshold relate?
What is snd_pcm_xrun_t useful for? (I think it is obsolete, should also be removed from docs, then)
Why is snd_pcm_scope included in the normal PCM docs?
stderr output - you can redirect all outputs via snd_lib_error_set_handler().
Ah, awesome, didn't find that one. Thanks.
My plans for near future are to implement a better PCM device enumeration and try to simplify mixer and add the mixer <-> PCM relationship.
That would be great.
Also, could you explain why current device enumeration is not useful to hotplug? There is information which card will be used (CARD=).
It's an API that returns a static list. That's all.
Thanks,
Lennart
At Thu, 10 Apr 2008 17:20:38 +0200, Lennart Poettering wrote:
What do you mean with 'There is no API to query the granularity of snd_pcm_delay()' ? Application should not know details about bottom implementation.
As far as I understood there are a few soundcards around where the playback sample index is only known each time the hw changes to the next fragment. It would be good to know about this, to tweak the time interpolation in timer-based scheduling.
We may add some hints to the PCM information, but I think maybe this isn't only the question about granualrity. For example, on some hardwares, the query of the current position costs much due to the hardware design.
Documentantion - if you ask specific questions, we try to update documentantion for other developers.. unfortunately, saying that whole documentantion is bad is not productive
Sorry. I'll make sure I'll ask for clarifications more clearly on alsa-devel from now on.
Here's my first batch of questions:
I am not sure I get what the "transfer align" is about.
Just ignore, this is obsoleted in the latest version :)
It is not clear how snd_pcm_update_avail() and snd_pcm_hwsync() actually play together, why they exist at all, and how exactly the optimization they are apparently useful for should be used.
The detailed description is found in PCM documentation.
It would be good to have an explanation what a "card", what an "id", what a "name", what a "device" and what a "subdevice" actually refers to, with examples.
The card (index) is the index number of the sound card instance. Each card has an id string and name string(s). One card instance may have several belonging components. And each component has (usually) a device index. Some components (e.g. PCM or rawmidi) can have multiple subdevices (or substreams). Each subdevice has a subdevice index.
regarding hw params: What exactly is "double buffering", "sample-resolution mmap", "block transfer", "batch", "sync_start" , "fifo_size", "subformat", "export buffer", "min align";
Most of them can be ignored, at least for PA :) I'd love to get rid of most of them in future, too.
sync_start might be interesting, though. This indicates that the full-duplex streams can start synchronously.
why there is a need for a seperate can_pause() and can_resume()?
can_pause() means the ability to pause/restart the stream.
can_resume() means the ability to resume the suspended/hibernated stream by the driver natively.
When and how should all these options be used?
Well, these indicate the hardware functionalities that no one actually cares much as originally expected. You see similar cases in any industry fields. So, just don't disturb, keep them rest in peace. Then we'll be able to gracefully obsolete them.
BTW: the doc for is_batch is copied 1:1 from the double_buffer text.
The docs speak of "blocked" and "non-blocked" open. It should be "blocking", I believe.
Patch please.
regarding sw params: What exactly is a "boundary"? Difference between tstamp modes?
The boundary defines the limit PCM position (frames) can reach. When the PCM position reaches to the boundary size, then it backs to 0 at next. The boundary size is aligned to the buffer size, and it's not LONG_MAX (although close to it).
how do silence_size and silence_threshold relate?
The PCM driver core has a feature to clear the samples automatically at each period elapse call. The silence_size and silence_threshold defines this behavior.
What is snd_pcm_xrun_t useful for? (I think it is obsolete, should also be removed from docs, then)
Right. Maybe should be classified to the section "obsoleted functions". A part of the problem is that the reference document is generated via doxygen, and it seems a bit confusing to arrange the sections in a single file.
Why is snd_pcm_scope included in the normal PCM docs?
I guess it was thought it'd be pretty useful.
Takashi
On Tue, 15.04.08 14:19, Takashi Iwai (tiwai@suse.de) wrote:
As far as I understood there are a few soundcards around where the playback sample index is only known each time the hw changes to the next fragment. It would be good to know about this, to tweak the time interpolation in timer-based scheduling.
We may add some hints to the PCM information, but I think maybe this isn't only the question about granualrity. For example, on some hardwares, the query of the current position costs much due to the hardware design.
What is "much" if I may ask?
Documentantion - if you ask specific questions, we try to update documentantion for other developers.. unfortunately, saying that whole documentantion is bad is not productive
Sorry. I'll make sure I'll ask for clarifications more clearly on alsa-devel from now on.
Here's my first batch of questions:
I am not sure I get what the "transfer align" is about.
Just ignore, this is obsoleted in the latest version :)
Please remove from the docs, then!
Also the part in the "Managing parameters" chapter in the PCM introduction text.
It is not clear how snd_pcm_update_avail() and snd_pcm_hwsync() actually play together, why they exist at all, and how exactly the optimization they are apparently useful for should be used.
The detailed description is found in PCM documentation.
Uh, and that's the part I don't get. I did read it, and didn't get it. What exactly does _hwsync() do that _update_avail() doesnt?
It would be good to have an explanation what a "card", what an "id", what a "name", what a "device" and what a "subdevice" actually refers to, with examples.
The card (index) is the index number of the sound card instance. Each card has an id string and name string(s). One card instance may have several belonging components. And each component has (usually) a device index. Some components (e.g. PCM or rawmidi) can have multiple subdevices (or substreams). Each subdevice has a subdevice index.
The question remains: what exactly is is a "device" and what is a "subdevice"? Examples?
For a while I thought that for those sound cards wich can output to SPDIF and analog at the same time we have two different device indexes, but a single card index. However, for my HDA card that is listed in /proc/asound/pcm as "04-00 ALC882 Analog" and "04-01 ALC882 Digital", aplay -L suggests to use "ec958:CARD=Intel,DEV=0" for spdif and "front:CARD=Intel,DEV=0" for analog -- both times with DEV=0! Since then I have no idea what devices, subdevices and stuff should actually be.
So again, what exactly qualifies subdevices? Do they share a single crystal? Are they usually combined for multi-channel output? What's the story?
regarding hw params: What exactly is "double buffering", "sample-resolution mmap", "block transfer", "batch", "sync_start" , "fifo_size", "subformat", "export buffer", "min align";
Most of them can be ignored, at least for PA :) I'd love to get rid of most of them in future, too.
Really? "block transfer" sounds to me like something that would be interesting for mmap playback for cases where i randomly seek around in my mmap buffer, with frame granularity. Which is exactly what I do all the time in PA.
why there is a need for a seperate can_pause() and can_resume()?
can_pause() means the ability to pause/restart the stream.
can_resume() means the ability to resume the suspended/hibernated stream by the driver natively.
Uh. This has very confusing naming.
regarding sw params: What exactly is a "boundary"? Difference between tstamp modes?
The boundary defines the limit PCM position (frames) can reach. When the PCM position reaches to the boundary size, then it backs to 0 at next. The boundary size is aligned to the buffer size, and it's not LONG_MAX (although close to it).
But what is this interesting for? I mean, I cannot read the raw hardware pointer index anyway from ALSA, so why should I care?
Or is it all for the case where I create a *major* buffer underrun with disabled stop_threshold and the value of _update_avail() keeps increasing but eventually wraps around?
how do silence_size and silence_threshold relate?
The PCM driver core has a feature to clear the samples automatically at each period elapse call. The silence_size and silence_threshold defines this behavior.
But in which way? Please elaborate!
What is snd_pcm_xrun_t useful for? (I think it is obsolete, should also be removed from docs, then)
Right. Maybe should be classified to the section "obsoleted functions". A part of the problem is that the reference document is generated via doxygen, and it seems a bit confusing to arrange the sections in a single file.
You can use stuff like \cond in doxygen to hide certain parts of the API pretty easily.
Why is snd_pcm_scope included in the normal PCM docs?
I guess it was thought it'd be pretty useful.
Maybe the plugin is useful. But why is it part of the API docs?
Thanks,
Lennart
At Sun, 20 Apr 2008 03:31:32 +0200, Lennart Poettering wrote:
On Tue, 15.04.08 14:19, Takashi Iwai (tiwai@suse.de) wrote:
As far as I understood there are a few soundcards around where the playback sample index is only known each time the hw changes to the next fragment. It would be good to know about this, to tweak the time interpolation in timer-based scheduling.
We may add some hints to the PCM information, but I think maybe this isn't only the question about granualrity. For example, on some hardwares, the query of the current position costs much due to the hardware design.
What is "much" if I may ask?
10 to 100 msec, IIRC. Maybe depends on HZ and system loads.
Documentantion - if you ask specific questions, we try to update documentantion for other developers.. unfortunately, saying that whole documentantion is bad is not productive
Sorry. I'll make sure I'll ask for clarifications more clearly on alsa-devel from now on.
Here's my first batch of questions:
I am not sure I get what the "transfer align" is about.
Just ignore, this is obsoleted in the latest version :)
Please remove from the docs, then!
Patch please :)
Also the part in the "Managing parameters" chapter in the PCM introduction text.
It is not clear how snd_pcm_update_avail() and snd_pcm_hwsync() actually play together, why they exist at all, and how exactly the optimization they are apparently useful for should be used.
The detailed description is found in PCM documentation.
Uh, and that's the part I don't get. I did read it, and didn't get it. What exactly does _hwsync() do that _update_avail() doesnt?
There are two PCM pointers in ALSA implementation: hw-pointer and appl-poiter. The former is a kind of DMA position, and the latter the position the app filled. In principle, hwsync() updates the former. When you use normal read/write method (snd_pcm_wrieti(), etc), the latter is updated automatically. But, in the case of mmap mode, you have to update it manually. This is snd_pcm_avail_update() for.
The hw and appl pointers may be updated by some other methods, but the above two calls are ones that (are supposed to) update directly.
It would be good to have an explanation what a "card", what an "id", what a "name", what a "device" and what a "subdevice" actually refers to, with examples.
The card (index) is the index number of the sound card instance. Each card has an id string and name string(s). One card instance may have several belonging components. And each component has (usually) a device index. Some components (e.g. PCM or rawmidi) can have multiple subdevices (or substreams). Each subdevice has a subdevice index.
The question remains: what exactly is is a "device" and what is a "subdevice"? Examples?
For a while I thought that for those sound cards wich can output to SPDIF and analog at the same time we have two different device indexes, but a single card index. However, for my HDA card that is listed in /proc/asound/pcm as "04-00 ALC882 Analog" and "04-01 ALC882 Digital", aplay -L suggests to use "ec958:CARD=Intel,DEV=0" for spdif and "front:CARD=Intel,DEV=0" for analog -- both times with DEV=0!
Because actually both of these point to the same device. They are exclusive.
Since then I have no idea what devices, subdevices and stuff should actually be. So again, what exactly qualifies subdevices? Do they share a single crystal? Are they usually combined for multi-channel output? What's the story?
There is so strict definition at all for device/subdevice classification. The multiple subdevices are often provided to handle the multi-playback streams (not multi-channels), such as emu10k1, or multiplexing streams for captures. With such a system, you can open multiple streams for the same purpose, mixed or multiplexed on the hardware for the same I/O. In the case of PCM, subdevice is often referred as "substream", BTW.
Note that the multi-channel is often a different story. On many systems, the multi-channel output is implemented only as a single interleaved stream, thus has only one subdevice.
regarding hw params: What exactly is "double buffering", "sample-resolution mmap", "block transfer", "batch", "sync_start" , "fifo_size", "subformat", "export buffer", "min align";
Most of them can be ignored, at least for PA :) I'd love to get rid of most of them in future, too.
Really? "block transfer" sounds to me like something that would be interesting for mmap playback for cases where i randomly seek around in my mmap buffer, with frame granularity. Which is exactly what I do all the time in PA.
If it were implemented correctly through all devices, some information might be useful. But currently not, unfortunately.
why there is a need for a seperate can_pause() and can_resume()?
can_pause() means the ability to pause/restart the stream.
can_resume() means the ability to resume the suspended/hibernated stream by the driver natively.
Uh. This has very confusing naming.
Yes.
regarding sw params: What exactly is a "boundary"? Difference between tstamp modes?
The boundary defines the limit PCM position (frames) can reach. When the PCM position reaches to the boundary size, then it backs to 0 at next. The boundary size is aligned to the buffer size, and it's not LONG_MAX (although close to it).
But what is this interesting for? I mean, I cannot read the raw hardware pointer index anyway from ALSA, so why should I care?
If you run a program for a long time, it much overwrap at some point. The boundary defines that point.
Or is it all for the case where I create a *major* buffer underrun with disabled stop_threshold and the value of _update_avail() keeps increasing but eventually wraps around?
Unlikely.
how do silence_size and silence_threshold relate?
The PCM driver core has a feature to clear the samples automatically at each period elapse call. The silence_size and silence_threshold defines this behavior.
But in which way? Please elaborate!
Later.
What is snd_pcm_xrun_t useful for? (I think it is obsolete, should also be removed from docs, then)
Right. Maybe should be classified to the section "obsoleted functions". A part of the problem is that the reference document is generated via doxygen, and it seems a bit confusing to arrange the sections in a single file.
You can use stuff like \cond in doxygen to hide certain parts of the API pretty easily.
Hm, but what about to put these obsoleted functions to a dedicate section? Removing the API functions from a reference is a bad idea, IMHO.
Why is snd_pcm_scope included in the normal PCM docs?
I guess it was thought it'd be pretty useful.
Maybe the plugin is useful. But why is it part of the API docs?
Because the feature is included in alsa-lib.
thanks,
Takashi
On Thu, 10 Apr 2008, Lennart Poettering wrote:
On Thu, 10.04.08 10:16, Jaroslav Kysela (perex@perex.cz) wrote:
Mixer
Please explain this question (why you need the dB <-> value conversion, we assumed that application works in dB or integer range not both):
'It is possible to query the dB range of a smixer element. And it is possible to query and set the current dB level. However, it is not possible to have a dB value converted to an integer level or vice versa, without touching the actual setting. i.e. a question like "What is the integer level 0 dB corresponds to?" can not be answered by ALSA. Which happens to be a serious limitation.'
I can think of many reasons, they all have to do with the fact that the dB scale is not integral, i.e. in contrast for the normal integer scale you won't always get what you are asking for, because the hardware only supports a value below or above what you asked for: a) a volume control tool might want to show a slider that is linear to the dB scale, but also shows which dB values are actually selectable from it via small black lines on the side (or suchlike) b) PA doesn't make use of positive dB values -- it limits itself to attenuation via the mixer. However, right now there is no way to find out which actually supported dB value is the nearest one to 0dB. c) Several different dB values may refer to the same actual hw setting. It would be good if a specific dB value actually maps to the same integer hw setting as some other value, to surpress redundant "volume change" events.
OK. I see your points. I've added these functions to alsa-lib's API:
snd_mixer_selem_ask_playback_vol_dB snd_mixer_selem_ask_capture_vol_dB snd_mixer_selem_ask_playback_dB_vol snd_mixer_selem_ask_capture_dB_vol
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
On Thu, 10 Apr 2008, Lennart Poettering wrote:
Also, could you explain why current device enumeration is not useful to hotplug? There is information which card will be used (CARD=).
It's an API that returns a static list. That's all.
Sure. but this list will update once new hardware is registered in system. So, if you know new card number of ID, you can ask again.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
On Thu, 10 Apr 2008, Lennart Poettering wrote:
buffer mananagement - I think we already discussed this - use sw_params or PCM timer to be updated when buffer position changes (interrupt was processed), you can use poll() as well
I am doing this now. I'd still love to see an API for naked interrupts, though.
I've added snd_pcm_sw_params_set_period_event() function to ALSA API now. Actually, it uses PCM timer internally, but at least public API is defined so applications are not forced to use PCM timers explicitly. We can optimize this feature later.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
Greetings,
re Lennart's mixer comments (basically no way to find out grouping or connectivity between elements, some other constraints)
Does the info exposed by the intel-hda driver http://helllabs.org/codecgraph/ meet some or all of these requirements?
Would it be possible for a) other drivers to export info in the same format b) this info to be made part of the control api. I.e. adding nodes and connections to the control info -- Eliot
participants (4)
-
Eliot Blennerhassett
-
Jaroslav Kysela
-
Lennart Poettering
-
Takashi Iwai