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 screen1 on the computer connected to your DAC and copy-and-paste or type the line below in the terminal screen, followed by pressing ENTER:

bash <(wget -q -O - "https://lacocina.nl/alsa-capabilities")

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 (it’s process id or PID), so may you examine, stop or kill it, and run the script again.

Downloading the script locally

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

wget https://lacocina.nl/alsa-capabilities
bash alsa-capabilities

Or, manually ‘install’ it and make it executable, ie:

# 1. let's get a writable directory in your PATH and move the script there
while IFS=":" read -r dir; do \[\[ -w "${dir}" ]] && ( echo "${dir} is ok"; break ); done
# 2. download the script 
wget -O "${dir}/alsa-capabilities" https://lacocina.nl/alsa-capabilities
# 3. make it executable
chmod +x "${dir}/alsa-capabilities"

Next time you can just type alsa-capabilities in any terminal window.

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):

bash alsa-capabilities -l usb -s

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

bash alsa-capabilities -h

Source code and development

The script is written in bash for the mpd-configure project. The source code is hosted at gitlab:

More advanced usage

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:

bash <(wget -q -O - "https://lacocina.nl/alsa-capabilities") -l usb -s

This will output something like:

0) USB Audio Class Digital alsa audio output interface `hw:1,0'
 - device name       = Pink Faun USB 32/384 USB receiv                             
 - interface name    = USB Audio                                                   
 - usb audio class   = 2 - isochronous asynchronous                                
 - character device  = /dev/snd/pcmC1D0p                                           
 - rates per format  = S32_LE            : 32000Hz 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 352800Hz 384000Hz
 - monitor file      = /proc/asound/card1/stream0 

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:

bash alsa-capabilities -l usb

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.

# source the local script or, if it's available in the current directory,
# straight from the upstream url
source alsa-capabilities 2>/dev/null || \
   source <(wget -q -O - "https://lacocina.nl/alsa-capabilities")
# run the function return_alsa_interface to fill up the array
[[ $? -eq 0 ]] && return_alsa_interface -l usb
# store the first item in the array in your own variable
myvar="${ALSA_AIF_HWADDRESSES[0]}"
# do something with it 
echo "${myvar}"
# display the corresponding character device: `/dev/snd/pcmCxDyp`:
echo "${ALSA_AIF_CHARDEVS[0]}"

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

grep 'declare -a ALSA_AIF' alsa-capabilities  | awk '{ print $3}'

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. 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:

sudo ./alsa-capabilities -s
 0) Analog alsa audio output interface `hw:0,0'
 - device name       = HDA Intel PCH                                               
 - interface name    = ALC887-VD Analog                                            
 - usb audio class   = (none)                                                      
 - character device  = /dev/snd/pcmC0D0p (in use by `mpd' with pid `37679')        
 - rates per format  = (error: can't determine)                                    
 - monitor file      = /proc/asound/card0/pcm0p/sub0/hw_params                     

 1) Digital alsa audio output interface `hw:0,1'
 - device name       = HDA Intel PCH                                               
 - interface name    = ALC887-VD Digital                                           
 - usb audio class   = (none)                                                      
 - character device  = /dev/snd/pcmC0D1p                                           
 - rates per format  = S16_LE            : 44100Hz 48000Hz 88200Hz 96000Hz 192000Hz 
		       S32_LE            : 44100Hz 48000Hz 88200Hz 96000Hz 192000Hz 
 - monitor file      = /proc/asound/card0/pcm1p/sub0/hw_params                     

 2) Digital alsa audio output interface `hw:0,3'
 - device name       = HDA Intel PCH                                               
 - interface name    = HDMI 0                                                      
 - usb audio class   = (none)                                                      
 - character device  = /dev/snd/pcmC0D3p                                           
 - rates per format  = S16_LE            : 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 
		       S32_LE            : 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 
		       IEC958_SUBFRAME_LE: 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 
 - monitor file      = /proc/asound/card0/pcm3p/sub0/hw_params                     

 3) USB Audio Class Digital alsa audio output interface `hw:1,0'
 - device name       = Peachtree 24/192 USB X                                      
 - interface name    = USB Audio                                                   
 - usb audio class   = 2 - isochronous asynchronous                                
 - character device  = /dev/snd/pcmC1D0p                                           
 - rates per format  = S32_LE            : 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 
 - monitor file      = /proc/asound/card1/stream0  

 4) USB Audio Class Digital alsa audio output interface `hw:2,0'
 - device name       = Pink Faun USB 32/384 USB receiv                                  
 - interface name    = USB Audio                                                   
 - usb audio class   = 2 - isochronous asynchronous                                
 - character device  = /dev/snd/pcmC2D0p                                           
 - rates per format  = S32_LE            : 32000Hz 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 352800Hz 384000Hz
 - monitor file      = /proc/asound/card2/stream0  

After this, the watch command may be used with the monitor file, which resides in the /proc pseudo file system, 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 stream 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.

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:

LANG=C watch -n 0.1 cat ${monitor_file}

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

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 DAC 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:

# contents of /proc/asound/card0/stream0
# while playing 16bit/44.1kHz audio 
# while playing 24bit/96kHz audio 
# while playing 16/44.1 and 24/96 audio
Playback:
 Status: Running
 Interface = 3
  Altset = 1
  URBs = 3 [ 8 8 8 ]
  Packet Size = 388
  Momentary freq = 44100 Hz (0x2c.199a)
 Interface 3
  Altset 1
  Format: S16_LE
  Channels: 2
  Endpoint: 3 OUT (ADAPTIVE)
  Rates: 44100, 48000, 96000
 Interface 3
  Altset 2
  Format: S24_3LE
  Channels: 2
  Endpoint: 3 OUT (ADAPTIVE)
  Rates: 44100, 48000, 96000

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`).

# contents of /proc/asound/card0/stream0
Playback:
 Status: Running
 Interface = 3
  Altset = 2
  URBs = 3 [ 8 8 8 ]
  Packet Size = 582
  Momentary freq = 96000 Hz (0x60.0000)
 Interface 3
  Altset 1
  Format: S16_LE
  Channels: 2
  Endpoint: 3 OUT (ADAPTIVE)
  Rates: 44100, 48000, 96000
 Interface 3
  Altset 2
  Format: S24_3LE
  Channels: 2
  Endpoint: 3 OUT (ADAPTIVE)
  Rates: 44100, 48000, 96000

The story above is summed up in the following diff:

# difference in contents of /proc/asound/card0/stream0 
--- /tmp/16bit	2013-08-24 12:21:22.363570848 +0200
+++ /tmp/24bit	2013-08-24 12:21:33.659570623 +0200
@@ -1,10 +1,10 @@
 Playback:
  Status: Running
  Interface = 3

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.

-  Altset = 1
+  Altset = 2
   URBs = 3 [ 8 8 8 ]
-  Packet Size = 388
-  Momentary freq = 44100 Hz (0x2c.199a)
+  Packet Size = 582
+  Momentary freq = 96000 Hz (0x60.0000)
  Interface 3
   Altset 1
   Format: S16_LE

With USB Audio Class 2 in isochronous asynchronous mode, like my 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:

Pink Faun Pink Faun USB 32/384 USB receiv at usb-0000:00:1d.0-1.5, high speed : USB Audio

Playback:
  Status: Running
    Interface = 2
    Altset = 1
    URBs = 3 [ 64 64 64 ]
    Packet Size = 1024
    Momentary freq = 44100 Hz (0x5.8332)
    Feedback Format = 16.16
  Interface 2
    Altset 1
    Format: S32_LE
    Channels: 2
    Endpoint: 5 OUT (ASYNC)
    Rates: 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
    Data packet interval: 125 us

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

Playback:
  Status: Running
    Interface = 2
    Altset = 1
    URBs = 3 [ 64 64 64 ]
    Packet Size = 1024
    Momentary freq = 96000 Hz (0xb.fffc)
    Feedback Format = 16.16
  Interface 2
    Altset 1
    Format: S32_LE
    Channels: 2
    Endpoint: 5 OUT (ASYNC)
    Rates: 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
    Data packet interval: 125 us

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

Playback:
  Status: Running
    Interface = 2
    Altset = 1
    URBs = 3 [ 64 64 64 ]
    Packet Size = 1024
    Momentary freq = 192000 Hz (0x18.0000)
    Feedback Format = 16.16
  Interface 2
    Altset 1
    Format: S32_LE
    Channels: 2
    Endpoint: 5 OUT (ASYNC)
    Rates: 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
    Data packet interval: 125 us

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`):

--- /home/ronalde/16b-44.1k-bituac2	2014-03-20 16:38:40.475172541 +0100
+++ /home/ronalde/24b-192k-bituac2	2014-03-20 16:38:40.476172541 +0100
@@ -6,7 +6,7 @@
     Altset = 1
     URBs = 3 [ 64 64 64 ]
     Packet Size = 1024
-    Momentary freq = 44100 Hz (0x5.8330)
+    Momentary freq = 191998 Hz (0x17.fff0)
     Feedback Format = 16.16
   Interface 2
     Altset 1

Footnotes:

1 

: 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.

To use a remote Linux computer, Windows users can install Git for Windows to get a terminal screen and bash, with which they can perform the steps below.

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 its hostname (like muscicomputer.local).

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:

ssh ${username}@${networkaddress}

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

ssh root@mymusicconmputer.local

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.

48 thoughts on “Alsa-capabilities shows which digital audio formats your USB DA-converter supports

  1. Hi, A wonderful script !!!!!

    One question : I have only one USB audio device
    I get
    ” – digital formats = (can’t detect: device in use”
    I have killed all programs I can think of that are using my soundcard. But I still get the “error”.

    Full output
    0) USB Audio Class Digital alsa audio output interface `hw:0,0′
    – card/device name = SB Live! 24-bit External
    – interface name = USB Audio
    – usb audio class =
    – digital formats = (can’t detect: device in use, run as root to display process.)
    – character device = /dev/snd/pcmC0D0p
    – monitor file = /proc/asound/card0/stream0

    Any ideas?

    Thanks!

    1. Did you try to run it as root like the script suggests? You might use sudo or su, like so:

      # run the script with elevated privileges using the sudo mechanism,
      # this will prompt you for the password of the currently logged on user, 
      # which has to be part of the `sudoers` group
      sudo bash alsa-capabilities
      

      or

      # logon as the root user inside a terminal screen
      su
      # run the script as the root user
      bash alsa-capabilities
      # when it's done, logoff the root user
      exit
      
  2. I get the following error when running ./alsa-capabilities on a Fedora 20

    [root@localhost mpd-configure]# ./alsa-capabilities
    ./alsa-capabilities: line 189: UO_EP_LABELS[${alsa_if_uac_ep}]: unbound variable

    1. Hi Adrian,

      This problem is fixed in the latest version.

      Thanks for reporting and sorry for the inconvience.

      Regards,
      Ronald

  3. Hi.

    I experience the following error in the latest version.

    sudo bash alsa-capabilities -l u
    alsa-capabilities: line 296: UO_EP_LABELS[${alsa_if_uac_ep}]: unbound variable

    Ubuntu 14.04 LTS
    Bash 4.3.11(1)-release

    Regards,
    George

    1. Hi George,

      Sorry for the inconvenience.

      The error you’re receiving should be fixed in the latest version. To make sure you’re using the current version, could you please try to run the script like so:

      sudo bash < (wget -q -O - "http://lacocina.nl/alsa-capabilities")

      I hope this helps, otherwise could you post the output of:

      aplay -l

      Thanks,
      Ronald

      1. I get the exact same error message, just downloaded your script today. Here is my aplay -l:

        **** List of PLAYBACK Hardware Devices ****
        card 0: HDMI [HDA Intel HDMI], device 3: HDMI 0 [HDMI 0]
        Subdevices: 1/1
        Subdevice #0: subdevice #0
        card 0: HDMI [HDA Intel HDMI], device 7: HDMI 1 [HDMI 1]
        Subdevices: 1/1
        Subdevice #0: subdevice #0
        card 0: HDMI [HDA Intel HDMI], device 8: HDMI 2 [HDMI 2]
        Subdevices: 1/1
        Subdevice #0: subdevice #0
        card 1: USB [Scarlett 2i2 USB], device 0: USB Audio [USB Audio]
        Subdevices: 1/1
        Subdevice #0: subdevice #0
        card 2: PCH [HDA Intel PCH], device 0: CS4208 Analog [CS4208 Analog]
        Subdevices: 1/1
        Subdevice #0: subdevice #0
        card 2: PCH [HDA Intel PCH], device 1: CS4208 Digital [CS4208 Digital]
        Subdevices: 1/1
        Subdevice #0: subdevice #0

        1. Canistel, confirmed that the issues still exists.

          Could you please follow the issue at:
          https://github.com/ronalde/mpd-configure/issues/11

          or, when you don’t have or want a github account, try to run the following (all one single line, followed by ENTER):

          cd /tmp/ && bash < (wget -q -O - "https://raw.githubusercontent.com/ronalde/mpd-configure/nomapfile/alsa-capabilities")

          Thanks,
          Ronald

    1. Hello Ishmael,

      Could you please post the output of `aplay -l`?

      Thanks and sorry for the inconvenience.
      Ronald

  4. Nice script and article, thank you! However, I had to add as “cat” in front of the monitor file’s name in order to observe my DAC’s behaviour:

    LANG=C watch -n 0.1 cat ${monitor_file}

    other wise I get a “permission denied” message concerning this file.

    How can I find out how my DAC handles dsd files, though? I can play them through mpd,
    but I’m unsure if DoP (DSD over PCM) is being used, of whether the DAC can handle the format natively (the documentation is unclear in this respect). Playing a dsd64 file the monitor file does show a sample frequency of 176400. But perhaps mpd performed some conversion already?

    1. Thanks Jürgen.

      Of course you’re right regarding the use of cat. Thanks for pointing that out.

      Regarding your DSD question, I refer to the MPD documentation on DSD support:

      “Native DSD playback is used automatically if available. DoP is only used if enabled explicitly using the dop option, because there is no way for MPD to find out whether the DAC supports it. DSD to PCM conversion is the fallback if DSD cannot be used directly.”

      Apparently “if available” is determined by support for native DSD regarding:

      1. your DAC,
      2. the alsa libraries,
      3. the alsa driver used for your DAC (`snd_usb_audio`) and
      4. mpd itself.

      While temporary alsa versions support common DSD encodings by default, the alsa driver (snd_usb_audio) only supports certain XMOS-receiver based DACs (see sound/usb/quirks.c). Another limitation is presented by stock mpd versions (at least up to the current 0.19.12) which only support a single DSD-format DSD-U8 (unsigned 8 bit). Apparently ‘common’ DSD files use DSD_U32LE (unsigned 32bit little endian) formats.

      To check whether the required alsa support is there (item 2), you could use the output of aplay like this:

      printf "`DSD_U32' support in alsa: "; LANG=C res="$(aplay 2>&1 | grep "DSD_U32")" && printf "OKn" || printf "Non"
      

      For item 3, you could use alsa-capabilities with the new -a hw:x,y switch as follows (remember to fill in the proper hw address:

      sudo systemctl stop mpd || echo "manually stop or kill mpd" && printf "`DSD_U32' support in alsa-driver: "; LANG=C res="$(./alsa-capabilities -a hw:1,0 2>&1 | grep "DSD_U32")" && printf "OKn" || printf "Non"
      

      For item 3, and to see what the combination alsa+mpd+snd_usb_audio+DAC make of a file, you could raise the verbosity of the mpd logging to `verbose`, restart mpd and play a DSD file, while checking the mpd log (using watch and cat ;).

      In my test setup it indicates the following rather interesting information when playing a 24bit 192kHz file:

      playlist: queue song 2:"Johann Sebastian Bach; De Nederlandse Bachvereniging, Jos van Veldhoven, Gerd Türk, Stephan MacLeod, Caroline Stam, Peter de Groot, Charles Daniels, Bas Ramselaar - St. John Passion/35 Part 2. No. 35. Arie. Zerfließe, mein Herze, in Fluten der Zähren.flac"
      decoder_thread: probing plugin flac
      ...
      decoder: audio_format=192000:24:2, seekable=true
      alsa_output: opened hw:1,0 type=HW
      alsa_output: format=S32_LE (Signed 32 bit Little Endian)
      alsa_output: buffer: size=48..131072 time=250..682667
      alsa_output: period: size=24..65536 time=125..341334
      alsa_output: default period_time = buffer_time/4 = 500000/4 = 125000
      alsa_output: buffer_size=96000 period_size=24000
      output: opened plugin=alsa name="Peachtree 24/192 USB X" audio_format=192000:32:2
      output: converting from 192000:24:2
      

      To see what happens to the audio stream after mpd handles it (after the last line in the mpd log, eg output) and hands it over to alsa, you could watch the stream file for the specified alsa interface.

      In your case I suppose mpd “falls back” to DoP (maybe because the file is not encoded in DSD_U8). So to get support for (real) native DSD, you will have to use the patched mpd version at https://github.com/lintweaker/mpd-dsd-019. In your current setup, I guess mpd instructs the alsa driver to pack the 1bit DSD samples (with a rate of 2.822.400Hz) in 16bit PCM samples (in a rate of 176.400Hz).

      Hope this helps, although I must admit I’ve never had the opportunity to use or test DSD-capable hardware.

      Regards,
      Ronald

      1. Thanks for the detailed reply! I’ve just asked the manufacturer of my amp/dac how it handles DSD files. In early 2014, before the amp/dac became available, there was a suggestion that it may use DoP, but it is not specified in the technical data, as far as I can see. Recently, I have been experimenting with a new DSD-aware version of sox that includes a DoP effect, with somewhat strange results, though. Some further experiments seem to be necessary ;-)

        All the best for 2016, and keep up the good work

        — Jürgen

  5. Hello, i have X-FI HD USB card and i still don’t understand does my card support 24 bit output in ubuntu? your script shows this, please explain:

    - rates per format  = S16_LE:             44100Hz 
    S16_LE:             44100Hz 
    S16_LE:             48000Hz 
    S16_LE:             48000Hz 
    S16_LE:             96000Hz 
    S16_LE:             96000Hz 
    S16_LE:             48000Hz 
    S16_LE:             48000Hz 
    S16_LE:             96000Hz 
    S16_LE:             96000Hz 
     - monitor file      = /proc/asound/card1/stream1
    

    but in stream 1 file i see Format: S24_3LE!! i’m completely frustrated, audacious can’t play 24 bit, but deadbeef can with alsa HW, but i don’t know is it 24 bit or 16 after all, please help

    1. Hi Serj,

      It seems you’re using a non-current version: could you please try it with:

      bash <(wget -q -O - "http://lacocina.nl/alsa-capabilities") -s
      

      and see if `S24_3LE: …` is listed as one of the formats (with `…` being the samplerates)?

      Regards,
      Ronald

      1. thank you reply, did this – absolutely the same

        here is complete result

        fominator@Player:~$ bash <(wget -q -O - "http://lacocina.nl/alsa-capabilities") -s
         0) Analog alsa audio output interface `hw:0,0'
         - device name       = HDA Intel PCH                                               
         - interface name    = ALC269VC Analog                                             
         - usb audio class   = (none)                                                      
         - character device  = /dev/snd/pcmC0D0p                                           
         - rates per format  = S16_LE:             44100Hz 48000Hz 96000Hz 192000Hz        
                               S32_LE:             44100Hz 48000Hz 96000Hz 192000Hz        
         - monitor file      = /proc/asound/card0/pcm0p/sub0/hw_params                     
        
         1) Digital alsa audio output interface `hw:0,3'
         - device name       = HDA Intel PCH                                               
         - interface name    = HDMI 0                                                      
         - usb audio class   = (none)                                                      
         - character device  = /dev/snd/pcmC0D3p                                           
         - rates per format  = S16_LE:             32000Hz 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 
                               S32_LE:             32000Hz 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 
                               IEC958_SUBFRAME_LE: 32000Hz 44100Hz 48000Hz 88200Hz 96000Hz 176400Hz 192000Hz 
         - monitor file      = /proc/asound/card0/pcm3p/sub0/hw_params                     
        
         2) USB Audio Class Digital alsa audio output interface `hw:1,0'
         - device name       = USB Sound Blaster HD                                        
         - interface name    = USB Audio                                                   
         - usb audio class   = 2 - isochronous asynchronous                                
         - character device  = /dev/snd/pcmC1D0p                                           
         - rates per format  = S16_LE:             48000Hz
                               S16_LE:             48000Hz
                               S16_LE:             96000Hz
                               S16_LE:             96000Hz
                               S16_LE:             44100Hz
                               S16_LE:             44100Hz
                               S16_LE:             48000Hz
                               S16_LE:             48000Hz
                               S16_LE:             96000Hz
                               S16_LE:             96000Hz 
         - monitor file      = /proc/asound/card1/stream0                                  
        
         3) USB Audio Class Digital alsa audio output interface `hw:1,1'
         - device name       = USB Sound Blaster HD                                        
         - interface name    = USB Audio #1                                                
         - usb audio class   = 2 - isochronous asynchronous                                
         - character device  = /dev/snd/pcmC1D1p                                           
         - rates per format  = S16_LE:             44100Hz
                               S16_LE:             44100Hz
                               S16_LE:             48000Hz
                               S16_LE:             48000Hz
                               S16_LE:             96000Hz
                               S16_LE:             96000Hz
                               S16_LE:             48000Hz
                               S16_LE:             48000Hz
                               S16_LE:             96000Hz
                               S16_LE:             96000Hz 
         - monitor file      = /proc/asound/card1/stream1                                  
        
         4) USB Audio Class Digital alsa audio output interface `hw:1,2'
         - device name       = USB Sound Blaster HD                                        
         - interface name    = USB Audio #2                                                
         - usb audio class   = 2 - isochronous asynchronous                                
         - character device  = /dev/snd/pcmC1D2p                                           
         - rates per format  = S16_LE:             44100Hz
                               S16_LE:             48000Hz     
         - monitor file      = /proc/asound/card1/stream2
        
        1. Hi Serj, thanks.

          It clearly is a (regression) bug in the detection of formats and sample rates in my script (each samplerate should only be listed once).

          If the stream file of the card states `Format: S24_3LE` then the interface *does* support playing back 24bit files.

          The stream file indicates the current operating mode (or “altset”) for the USB device with `Altset = X` (third line from the top). The `X` refers to an `Altset X` (notice the absence of the equal `=` sign), which is fixed at a certain output encoding, indicated by the `Format: XXX` line.

          In your case I guess the USB receiver in the device has two “interfaces”, each with its own “altset”;

          • one with `Format: S16_LE` (which my script lists) and
          • one with `Format: S24_3LE` (which my script ignores).

          To see if it works use the following command to observe the changing `AltSet = X`, when you switch from playing a 16bit file to playing a 24bit file using deadbeef (configured to use `hw:x,y`):

          ## replace streamX with the proper one
          watch -n 1 "cat /proc/asound/card1/streamX"
          

          Sorry for the confusion!
          Ronald

      2. stream 1 file for card 1
        you can see S24_3LE

          Status: Stop
          Interface 2
            Altset 1
            Format: S16_LE
            Channels: 2
            Endpoint: 4 OUT (ASYNC)
            Rates: 44100
            Data packet interval: 1000 us
          Interface 2
            Altset 2
            Format: S24_3LE
            Channels: 2
            Endpoint: 4 OUT (ASYNC)
            Rates: 44100
            Data packet interval: 1000 us
          Interface 2
            Altset 3
            Format: S16_LE
            Channels: 2
            Endpoint: 4 OUT (ASYNC)
            Rates: 48000
            Data packet interval: 1000 us
          Interface 2
            Altset 4
            Format: S24_3LE
            Channels: 2
            Endpoint: 4 OUT (ASYNC)
            Rates: 48000
            Data packet interval: 1000 us
          Interface 2
            Altset 5
            Format: S16_LE
            Channels: 2
            Endpoint: 4 OUT (ASYNC)
            Rates: 96000
            Data packet interval: 1000 us
          Interface 2
            Altset 6
            Format: S24_3LE
            Channels: 2
            Endpoint: 4 OUT (ASYNC)
            Rates: 96000
            Data packet interval: 1000 us
        
        Capture:
          Status: Stop
          Interface 3
            Altset 1
            Format: S16_LE
            Channels: 2
            Endpoint: 2 IN (ASYNC)
            Rates: 48000
            Data packet interval: 1000 us
          Interface 3
            Altset 2
            Format: S24_3LE
            Channels: 2
            Endpoint: 2 IN (ASYNC)
            Rates: 48000
            Data packet interval: 1000 us
          Interface 3
            Altset 3
            Format: S16_LE
            Channels: 2
            Endpoint: 2 IN (ASYNC)
            Rates: 96000
            Data packet interval: 1000 us
          Interface 3
            Altset 4
            Format: S24_3LE
            Channels: 2
            Endpoint: 2 IN (ASYNC)
            Rates: 96000
            Data packet interval: 1000 us
        
        1. Yup, just what I thought. See my previous comment regarding watching which operating mode/format is actually used when you play back a 24bit file.

          Ronald

        2. Serj, the problem should be solved in the latest version.

          Could you try it again and post the output of the following command::

          bash <(wget -q -O - "http://lacocina.nl/alsa-capabilities") -l usb -s
          

          Thanks,
          Ronald

          1. sorry for late answer, YES now it’s OK, thank you

            fominator@Player:~$ bash <(wget -q -O - "http://lacocina.nl/alsa-capabilities") -l usb -s
             0) USB Audio Class Digital alsa audio output interface `hw:1,0'
             - device name       = USB Sound Blaster HD                                        
             - interface name    = USB Audio                                                   
             - usb audio class   = 2 - isochronous asynchronous                                
             - character device  = /dev/snd/pcmC1D0p                                           
             - rates per format  = S24_3LE:             48000Hz 96000Hz                        
                                   S16_LE:              48000Hz 96000Hz                        
             - monitor file      = /proc/asound/card1/stream0                                  
            
             1) USB Audio Class Digital alsa audio output interface `hw:1,1'
             - device name       = USB Sound Blaster HD                                        
             - interface name    = USB Audio #1                                                
             - usb audio class   = 2 - isochronous asynchronous                                
             - character device  = /dev/snd/pcmC1D1p                                           
             - rates per format  = S24_3LE:             44100Hz 48000Hz 96000Hz                
                                   S16_LE:              44100Hz 48000Hz 96000Hz                
             - monitor file      = /proc/asound/card1/stream1                                  
            
             2) USB Audio Class Digital alsa audio output interface `hw:1,2'
             - device name       = USB Sound Blaster HD                                        
             - interface name    = USB Audio #2                                                
             - usb audio class   = 2 - isochronous asynchronous                                
             - character device  = /dev/snd/pcmC1D2p                                           
             - rates per format  = S16_LE:              44100Hz 48000Hz                        
             - monitor file      = /proc/asound/card1/stream2
            
  6. and one question to you
    what is “feedback format”? i had 15.17, but now it’s 10.14, why has it changed? and what this digits mean? and another question how to know i have UAC1 or UAC2? thank you

    1. > “and one question to you: what is “feedback format”? i had 15.17, but now it’s 10.14, why has it changed? and what this digits mean? ”

      The digits are a representation of the Q number format, a complex way to let (embedded) DSP systems, like a USB DAC, do fixed point calculations using cheap and simple IC’s or processors, that can’t rely on floating point precision. In the linux kernel it is defined as `Qfreqn.freqm` where `n` is the “nominal sampling rate in fs/fps in Q16.16 format” and `m` the “momentary sampling rate in fs/fps in Q16.16 format”. The values you see in `/proc/asound/cardx/stream0` represent “how much to shift the feedback value to get Q16.16” and are calculated in `./sound/usb/proc.c`.

      To be short, the fact that you see a “feedback format” is another proof of the fact that your card is UAC2 capable.

      Regards,
      Ronald

        1. Hi Serj,

          Sorry for replying so late. I don’t know why it changed. Could be an updated kernel or updated firmware in the DAC.

          As far as I know it’s just a means to get proper communication between the kernel (modules) and the USB receiver inside the DAC, but I must admit I really don’t understand the implications. I would recommend asking that on the proper alsa mailing list.

          Regards,
          Ronald

          1. Hello again, thank you for answer. And again about UAC, in your script I see that my device is UAC2 compatible, but in stream files I see that it’s connected at FULL SPEED, am I understand right that it uses UAC1! if so, why it doesn’t use UAC2? In windows after installing drivers it’s connected at high speed, but I thought if it UAC2 compatible it should be native in Linux

          2. Hi Serj,

            The script uses the streamfile (eg `/proc/asound/cardx/stream0` generated by ./sound/usb/proc.c) to determine the UAC type. So in your case it should state `Endpoint: x OUT (ASYNC)`.

            As far as the source code reveals the streamfile doesn’t contain information on the USB (speed) class. Could you once again post the contents of your streamfile?

            Regards,
            Ronald

  7. Hallo Ronald,
    I am trying to use your script on a raspberry pi connected to a Cambridge Audio DAC, but it does not detect any cards:

    # bash <(wget -q -O - "https://lacocina.nl/alsa-capabilities")
    
    Error:
    0 soundcards found
    
    # aplay -l
    **** List of PLAYBACK Hardware Devices ****
    card 0: C20 [CA CXA80 2.0], device 0: USB Audio [USB Audio]
      Subdevices: 1/1
      Subdevice #0: subdevice #0
    

    Any idea what could be wrong?

    Cheers, Leon

    1. Hi Leon,

      Yup; had the same problem here. My script apparently didn’t work with recent software so pasuspender caused a problem.

      I think I fixed this so I would like to ask you to try it again.

      Regards,
      Ronald

      1. Hi Ronald,

        Seems to be fixed, except for a message ‘Connection failure’:

        # bash <(wget -q -O - "https://lacocina.nl/alsa-capabilities")
        Connection failure: Connection refused
        pa_context_connect() failed: Invalid argument
         1) USB Audio Class Digital alsa audio output interface `hw:0,0'
         - device name       = C20                                                         
         - interface name    = USB Audio                                                   
         - usb audio class   = 2 - isochronous asynchronous                                
         - character device  = /dev/snd/pcmC0D0p                                           
         - encoding formats  = S32_LE                                                      
         - monitor file      = /proc/asound/card0/pcm0p/sub0/hw_params                     
         - stream file       = /proc/asound/card0/stream0
        

        FYI: If I run the script on my PC connected to an Audioquest Dragonfly DAC I only get the ‘Connection failure’ message when I run it as root, not when I run it as a regular user. On the raspberry pi I get it both as root and as regular user. I connect to the pi through ssh.

        Cheers, Leon.

        1. Yes, I’m afraid it was a rather {n,h}asty hack; it seems that with it, on proper configured systems, users receive all kinds of pulse messages, like

          I: [pulseaudio] client.c: Created 9 "Native client (UNIX socket client)"
          I: [pulseaudio] protocol-native.c: Got credentials: uid=1000 gid=1000 success=1
          I: [pulseaudio] client.c: Freed 9 "pasuspender"
          I: [pulseaudio] protocol-native.c: Connection died.

          I’ll have to review that portion of the script soon, or maybe get rid of it, as pulseaudio seems to behave very nice nowadays (it suspends immediately when nothing is playing).

          Cheers,
          Ronald

Leave a Reply

Your email address will not be published. Required fields are marked *