# Linux Audio - PCMs [TOC] ## PCMs: The common currency of audio streams in ALSA ==A PCM is an inferface where audio data could flow through in a certain direction.== It is the fundamental unit when speaking of audio data pipeline in user space aspects of ALSA. For example, to output sound to speakers, you would write the audio data (e.g. an audio frame with both left and right channels) to a **playback** PCM, and the sound would magically appears on the front left and front right channel of the speakers; or if you want to record from microphone, you can (after proper setups) read from the corresponding **capture** PCM, and recorded audio data would magically appears accordingly. PCMs are (by design) direction-sensitive. A PCM only handle audio data flow of a single direction, either "playback" or "capture". It is the fundamental unit describing sources of audio data, or sinks where audio data can be fed in. ### Working on PCMs with `aplay` and `arecord` The `aplay` and `arecord` commands can be used for working on audio input and output. They also speak of the language of PCMs. Let's say we'd like to play some sound. In this case, we'll have to list the available "playback" PCMs. This can be done by `aplay -L` ``` $ aplay -L ``` To have aplay do playback to a given playback PCM, use `-D` options. For example, for some reason I'd like my laptop to playback random noise from `/dev/urandom` on the `hw:0,0` PCM, I'd use: ``` $ aplay -D hw:0,0 /dev/urandom ``` To have `aplay` or `arecord` doing playback or capture, you have to pass the PCMs where you'd like to feed data in or extract data from (with the `-D` option). ## PCMs backed by actual hardware Hardware interfaces on the audio devices are abstracted as PCMs. When speaking of playing sound or recording sound, we are speaking of writing data to a "playback" PCM or reading data from a "capture" PCM. ### The `hw` type in `-L` option PCMs backed by actual hardware are those PCMs with `hw` type. If you use the `aplay -L` or `arecord -L`, thoss PCM whose names takes the form of `hw:x,y` are PCMs backed by harware. They are different in that the `/dev/snd` actually contains device files for those PCM. Those PCMs are exposed by sound card. That's also the reason if you use the `-l` option of `aplay` and `arecord`, you see the match exactly with the devices on the sound card. ### The `/dev/snd` directoy *...Generally the file is named as aaaCxDy, where aaa is the service name, x the card number (0-7) and y the device number (0-).* ``` controlC? control devices (i.e. mixer, etc.) hwC?D? hwdep devices midiC?D? rawmidi devices pcmC?D?p pcm playback devices pcmC?D?c pcm capture devices seq sequencer device timer timer device ``` ---- [*Device files under /proc/asound/dev*](https://alsa.opensrc.org/AlsaTips#Alsa_layers) of alsa.opensrc.org Another way to find out those hardware based PCMs is going straight to the `/dev/snd` directory. This is the actual device files that alsa-lib works on. The naming scheme is the same as what being used in the `/proc/asound/`. Note that `/proc/asound/dev` is symlinked to the `/dev/snd`. ## PCMs backed by plugins ==Other than harware PCMs, ALSA provide a mechanism called "plugin" to create software-defined PCMs==. Those PCMs are created by alsa-lib, and are not backed by actual hardware, but can be treated as if there were. There's no difference in using those PCMs than the ones backed by hardware. This abstraction makes manipulating audio data trivial. Audio data can be passed to those "virtual" PCMs for duplicating, mixing, or some other fancy processing before being fed into actual hardware PCMs. ### Instantiation of plugin-based PCMs The plugin based PCMs are instantiated using the ALSA configuration files. That's why you may see the following description: > *pcm: the pcm interface is very flexible and allows the definition of virtual and hardware devices via a relatively easy to understand configuration file (\~/.asoundrc, /usr/share/alsa/alsa.conf).* ---- [*Alsa layers*](https://alsa.opensrc.org/AlsaTips#Alsa_layers) of alsa.opensrc.org The alsa-lib instantiates those software-defined PCMs by parsing the ALSA configuration files. Examples for those files are the `/etc/asound.conf` and the `~/.asoundrc`. See [.asoundrc](https://alsa.opensrc.org/Asoundrc) for information. See [*Plugin Documentation*](https://alsa.opensrc.org/Plugin_Documentation) in alsa.opensrc.org for how this process work. ### Syntax of configuration files Those configuration file have their own syntax. Documentation for the syntax is rather scattered. The follow 1. [Asoundrc](https://www.alsa-project.org/wiki/Asoundrc) in ASLA wiki 2. [Configuration files](https://www.alsa-project.org/alsa-doc/alsa-lib/conf.html) in alsa-lib documentation for basic syntax 3. The [Configurate](https://www.alsa-project.org/alsa-doc/alsa-lib/) section of this page lists usage of other functionalities. 4. [Advanced Linux Sound Architecture](https://wiki.archlinux.org/title/Advanced_Linux_Sound_Architecture) in Arch Wiki 5. alsa.opensrc.org itself can be used as a dictionary for searching plugin usages. The configuration files may varies from user to user, so PCMs user see may varies. ### Example: sound services In modern day, sound devices on computers are often designed in the way that there's only a single hardware PCM. One can imagine that it is likely to have race condition if multiple application try to access this single PCM. So instead, sound service is used. A sound service monopolize the hardware PCM and is the only application that can access it. Every application wanting to output can audio data to the software PCM setup by the sound service, and the sound service dictate what is eventually sent to the actual hardware PCM. For example, pipewire set up a software PCM called "pipewire". Applications can send audio data to Pipewire service and let it decide what to do with those audio data. ## Gotchas for the PCM abstractions There are some oddities in terms of PCMs, compared to other subsystems in Linux. ### NOT-everything-is-a-file abstraction ==PCMs don't fully endorsed the everything-is-a-file philosophy of Linux.== Normally you'd expect things can be found all PCMs being some files under `/proc`, `/sys` or `/dev`, and expect the user space library do file operations on those files.But no. This is not how PCMs work, at least not all of them. The reason is that not all PCMs are created by kernel. ==PCMs in user space are abstractions maintained by the alsa-lib, not the kernel==. While some PCM, notably the `hw` PCMs, have corresponding device file under `/dev/snd`, some don't. You can find any trace of them in those special file systems. For example the `null` PCM. This PCM consume all audio data being fed into, like how `/dev/null` works. This is partialy because those PCMs are instantiated by user space using configuration APIs of `alsa-lib`. Meddling the special files from user space may not be the most maintanable design. That being said, you can still find PCM in kenrel code. This is kernel implementation for providing harware PCMs and doesn't account for those created by plugins. ### PCMs are user-specific, not system-wide visible Because some PCMs are instantiated according ALSA configuration files in user space, different user may see different PCMs. The implication is that `aplay` and `sudo aplay` may behave differently. ### The name "PCM" itself may be misleading PCM may have different meanings in various fields of audio engineering. PCM here means none of those. It's more of a name by convention. Like, when we refer to a "sound card", it may not be an card-shaped thing where you can plug into you computer, but rather an IP block integrated into the SoC, or an external DSP chip. Yet we still call it a "card". ### PCMs are not channels Also note that ==PCMs here doesn't mean channels (as channel in "left/right channel")==. Otherwise you'll have to split left/right channel of an audio file before sending them to hardware. That obviously doesn't happen. See [*ALSA PCM channel-mapping API*](https://docs.kernel.org/sound/designs/channel-mapping-api.html).