http://0pointer.de/blog/projects/guide-to-sound-apis.html If we want PulseAudio to work well, we have to limit ourselves to the safe subset of the ALSA API. DONTS: * Do not use "async handlers", e.g. via snd_async_add_pcm_handler() and friends. Asynchronous handlers are implemented using POSIX signals, which is a very questionable use of them, especially from libraries and plugins. Even when you don't want to limit yourself to the safe ALSA subset it is highly recommended not to use this functionality. Read this for a longer explanation why signals for audio IO are evil. * Do not parse the ALSA configuration file yourself or with any of the ALSA functions such as snd_config_xxx(). If you need to enumerate audio devices use snd_device_name_hint() (and related functions). That is the only API that also supports enumerating non-hardware audio devices and audio devices with drivers implemented in userspace. * Do not parse any of the files from /proc/asound/. Those files only include information about kernel sound drivers -- user-space plugins are not listed there. Also, the set of kernel devices might differ from the way they are presented in user-space. (i.e. sub-devices are mapped in different ways to actual user-space devices such as surround51 an suchlike. * Do not rely on stable device indexes from ALSA. Nowadays they depend on the initialization order of the drivers during boot-up time and are thus not stable. * Do not use the snd_card_xxx() APIs. For enumerating use snd_device_name_hint() (and related functions). snd_card_xxx() is obsolete. It will only list kernel hardware devices. User-space devices such as sound servers, Bluetooth audio are not included. snd_card_load() is completely obsolete in these days. * Do not hard-code device strings, especially not hw:0 or plughw:0 or even dmix -- these devices define no channel mapping and are mapped to raw kernel devices. It is highly recommended to use exclusively default as device string. If specific channel mappings are required the correct device strings should be front for stereo, surround40 for Surround 4.0, surround41, surround51, and so on. Unfortunately at this point ALSA does not define standard device names with channel mappings for non-kernel devices. This means default may only be used safely for mono and stereo streams. You should probably prefix your device string with plug: to make sure ALSA transparently reformats/remaps/resamples your PCM stream for you if the hardware/backend does not support your sampling parameters natively. * Do not assume that any particular sample type is supported except the following ones: U8, S16_LE, S16_BE, S32_LE, S32_BE, FLOAT_LE, FLOAT_BE, MU_LAW, A_LAW. * Do not use snd_pcm_avail_update() for synchronization purposes. It should be used exclusively to query the amount of bytes that may be written/read right now. Do not use snd_pcm_delay() to query the fill level of your playback buffer. It should be used exclusively for synchronisation purposes. Make sure you fully understand the difference, and note that the two functions return values that are not necessarily directly connected! * Do not assume that the mixer controls always know dB information. * Do not assume that all devices support MMAP style buffer access. * Do not assume that the hardware pointer inside the (possibly mmaped) playback buffer is the actual position of the sample in the DAC. There might be an extra latency involved. * Do not try to recover with your own code from ALSA error conditions such as buffer under-runs. Use snd_pcm_recover() instead. * Do not touch buffering/period metrics unless you have specific latency needs. Develop defensively, handling correctly the case when the backend cannot fulfill your buffering metrics requests. Be aware that the buffering metrics of the playback buffer only indirectly influence the overall latency in many cases. i.e. setting the buffer size to a fixed value might actually result in practical latencies that are much higher. * Do not assume that snd_pcm_rewind() is available and works and to which degree. * Do not assume that the time when a PCM stream can receive new data is strictly dependant on the sampling and buffering parameters and the resulting average throughput. Always make sure to supply new audio data to the device when it asks for it by signalling "writability" on the fd. (And similarly for capturing) * Do not use the "simple" interface snd_spcm_xxx(). * Do not use any of the functions marked as "obsolete". * Do not use the timer, midi, rawmidi, hwdep subsystems. DOS: * Use snd_device_name_hint() for enumerating audio devices. * Use snd_smixer_xx() instead of raw snd_ctl_xxx() * For synchronization purposes use snd_pcm_delay(). * For checking buffer playback/capture fill level use snd_pcm_update_avail(). * Use snd_pcm_recover() to recover from errors returned by any of the ALSA functions. * If possible use the largest buffer sizes the device supports to maximize power saving and drop-out safety. Use snd_pcm_rewind() if you need to react to user input quickly. Even if this is impossible, it would be nice to meet PulseAudio half way and make as small of a feature request as possible. Just telling them "do everything ALSA does" isn't very helpful, and even if they do have that goal it'll be more efficient if they implement what we really need first.