Alsa-capabilities shows which digital audio formats your USB DA-converter supports

alsa-capabilities shows digital audio formats and sample rates alsa supports with your USB DAC

Have you ever wondered which digital audio format your Linux and alsa based music computer, for example one that runs Music Player Daemon in bit perfect / audiophile mode, is actually sending to your sound card or USB DAC when playing a high resolution digital audio file? Especially when your external DAC doesn’t indicate the sample rate or resolution of the incoming stream with LEDs or a display? Or maybe you are curious about the digital audio formats and sample rates your soundcard or USB DAC handles natively? This article and the accompanying script try to assist you with that daunting task.

The alsa-capabilities script –which can be executed on any computer running Linux and alsa– will show the available alsa interfaces for audio playback, and the digital audio formats each sound card or external USB DAC supports.

Instructions for running it straight from the web

Open a terminal screen* on the computer connected to your DAC and copy-and-paste or type the line below in the terminal screen, followed by pressing ENTER:

That’s it!

This will display a list of each alsa audio output interface with its details. When an interface is in use by another program, it will display the name and identifier (pid), so may you examine, stop or kill it, and run the script again.

The script also supports some options. For example, to display the sample rates for each encoding format supported by each USB Audio Class audio interface on your computer, run the script together with the '-l usb' (show only usb interfaces) and the '-s' (show sample rates) options:

This will output something like:

Downloading the script locally

When you want to download it to your computer, you could do the following:

Options can simply be added to the command line like in the following example, which limits the output to only devices which support USB Audio Class 1 or 2 (using -l usb) while adding the listing of supported sample rates for each supported encoding format (the -s option):

To display all options run the script with the -h option:

Opening a terminal screen

For these tasks you need to start a terminal screen on your desktop computer. Linux users may press and hold CTRL+ALT while typing T from within their desktop environment. Both users of Linux and Mac desktops may search for the text "Terminal" in their applications menu.

Windows users can use putty to perform the step below, filling in the appropriate values for username and network address in the connection screen of putty.

When your music computer is remote, you should first make a ssh-connection to that remote computer. For such an connection, you need to know the following:

  • the username and password of a user account on the remote computer, as configured by you or instructed by your manufacturer, and
  • the network address of the music computer, in the form of an ip address (ie 192.168.1.10) or a hostname (ie vortexbox).

To make a SSH connection to the linux based audio computer, first open a terminal screen, and copy-and-paste or type the line below, followed by the ENTER key:

… and fill in the proper password for the "${username}"-user when asked for, for example:

In this remote terminal screen, you may enter any command like you would do on your local computer, including the commands in the instructions above.

Watching an interface reacting on different audio formats

To see how an audio interface reacts when you play different digital audio formats, you can use the output of the script with the watch command. Replace the value of the ${monitor file} below with the name of the file displayed by the script:

Now try throwing audio files of different formats at your player and see what your digital interface makes of it.

Automated usage in scripts etc.

The script supports some features which could be handy in other scripts, like limiting the output to certain classes of audio interfaces, or interfaces with a certain name. To do this, you may use the limit option '-l' with an argument, either 'a' or 'analog', 'd' or 'digital' or 'u', 'usb' or 'uac' to only show interfaces fitting that limit. In addition, a custom regular expression filter may be specified as an argument for the 'c' option.To list only interfaces that support USB Audio Class you should execute:

Furthermore the script can be sourced. That way one may automate and store certain properties for use in other scripts or config files, like mpd-configure does. Here’s a rough example.

To see all properties that can be accessed this way see the scripts source or grep for the following:

The working of the script explained

To detect which digital interfaces your computer has, the script filters the output of the command 'aplay -l' to list interfaces which have one of the words "usb", "digital", "hdmi", "i2s", "spdif", "toslink" or "adat" in them. However, before it does that, it temporary pauses pulseaudio, which would otherwise block the interface exclusively. It then reformats the output of the "aplay" command to show a clear listing of each alsa interface, consisting of a "hw:X,Y" hardware addresses, its human readable name, the character device it uses, the digital formats it supports natively, and –in case of a USB Audio Class device, the class (1 or 2) and its stream file.

After an interface is selected, either by the script (in case of single interface) or you (in the case of multiple interfaces), the script will play random noise to the interface, in order to force alsa to display the native digital formats the interface accepts. To keep this test silent, the sound output of the interface is redirected to /dev/null.

NOTE: for this to work one should temporary stop or pause any program using that interface, like mpd. However, the script will detect and show you which processes/programs are accessing which device while performing this test, so you may abort the script and stop the listed program, using pkill ${process_name} or kill -9 ${process_id}, before re-running the script.

The output below is that of my own system, with a sound card embedded on an Intel motherboard and two USB DACs connected:

After this, the watch command may be used with the monitor file, which resides in the pseudo file system /proc, which allows for inspecting the snd_usb_audio kernel module’s parameters and their values, see the source of /tree/sound/usb. The script does this by translating the selected interface address hw:X,Y to the associated filename /proc/asound/cardX/streamY, where X is the number of the sound card and Y that of the output interface. Because this steam file is created by the kernel module, it only exists when you have interfaces that support a USB Audio Class, see the source of sound/usb/proc.c). In such cases, the file contains the actual values of the snd_usb_audio kernel module associated with the specific interface.

The script displays the changing contents of this file with a 100ms refresh rate (0.1s) using the watch command.

The script

The script is written in bash and part of my mpd-configure project hosted at github:

Contents of the alsa stream files for USB Audio Class 1 & 2 DAC’s

Alsa stream file in adaptive UAC1 mode

I used to have a Pink Faun 3.24 USB DAC, fitted with a USB Audio Class (UAC) 1 transceiver chip from Tenor. With these UAC1 devices, the communication with the host computer runs in isochronous adaptive mode, meaning the data transfer type is isochronous and the audio synchronization type adaptive. See the official USB Audio Class 2 specification “A Device Class for Audio” from the USB consortium.

The contents of the stream file /proc/asound/card0/stream0 look like this when playing a 16bit/44.1kHz CD-ripped file:

When playing a 24bit/96kHz file, the output of the file changes to the following.

Note that the Altset value has changed from 1 to 2 and Momentary freq from 44100 to 96000, indicating that the second interface (Altset = 2) is activated with a 24bit format (Format = S24_3LE) and 96kHz sample rate (Momentary freq = 96000).

The story above is summed up in the following diff:

Alsa stream file in asynchronous UAC2 mode

With UAC1 device in isochronous adaptive mode, the DAC and computer negotiate a shared sample rate, mostly using a PLL mechanism. The Momentary freq value shows the result of that negotation which should be equal to that of the file being played.

With USB Audio Class 2 in isochronous asynchronous mode, like new Pink Faun DAC2 with an Amanero(?) supports, every 125us the DAC tells the computer how many SPDIF-packets it should sent in one USB Request Block (URB).

In the output you can actually see that happening when playing high resolution files; the Momentary freq flips from 192.000Hz to something like 191.999Hz and back again.

Other differences with the UAC1 device output are:

Field UAC1 UAC2
URBs 8 64
Packet Size 582 1024
Feedback Format (non-existent) 16.16
Endpoint 3 OUT (ADAPTIVE) 5 OUT (ASYNC)
Data packet interval 1ms (1000us) 125us

The output looks like this when playing a 16bit/44.1kHz file:

It changes to the following when playing a 24bit/96kHz file:

And, finally, this is what it looks like when playing a 24bit/192kHz file:

As you can see below, this device pads each sample (with zeroes) until it fills up 32bits, regardless of the resolution of the source file. Therefore, it needs only a single AltSet and doesn’t change anything when changing from 16bit/44.1kHz to 24bit/192kHz, apart from the sampling frequency (MomentaryFreq):

Changelog

Jan 26, 2016: enhanced handling of pulseaudio:

Jan 4, 2016: Enhanced program flow and optimized display of supported sample rates for UAC type interfaces:

Jan 3, 2016: Added support for accurate but (very) slow displaying of supported sample rates for each format an interface supports:

Dec 9, 2015: Fixed a (rather long running) error in the script:

May 13, 2015: Added a lot of extra error checking:

  • modified alsa-capabilities to make the script more robust

Jan 26, 2015: Added a temporary hack to address issue #8:

  • modified alsa-capabilities to skip checking for unset variables and brake on errors

Apr 18, 2014: Major rewrite of the script:

  • moved tests/detect-alsa-output-capabilities.sh to alsa-capabilities
  • modified alsa-capabilities to make it suitable to be sourced or run by itself from the command line
  • added simple and regexp filtering to alsa-capabilities

Apr 8, 2014: Script updated:

  • added functionality to monitor non-UAC devices using its hw_params file and a few improvements in UI.

Apr 3, 2014: Small script changes and moved PCM information:

  • introduced some more bashims to make the script faster and simpler.
  • Moved the background information on the PCM format to The PCM format explained.

Apr 2, 2014: full rewrite of the script

  • to minimize user interaction and making it a bit more robust.

Mar 21, 2014: Small changes to the article:

  • Reformatted the introduction and added some technical background about the script

Mar 20, 2014: Completely rewritten the article

  • the previous version of the article assumed you already had your (default) music player set up for using a alsa hardware playback interface, which most readers are trying to figure out.
  • created a script (detect-alsa-output-capabilities.sh) to quickly list the available interfaces and supported audio formats

Related articles