Playing Audio over an USB Audio Interface on a Raspberry Pi from the Command-line

#How-To, #Raspberry Pi


The Raspberry Pi powering our status screen is also connected to our office doorbell: Everytime someone rings the bell, the Pi plays a short audio file.

The Pi features an onboard audio output, but its quality is rather poor. So we decided to use an external USB audio interface instead. But how do we make the Pi use the external interface instead of its own audio output?

You’ll find a lot of posts about this, most being targeted at older versions of Raspian and/or incomplete in other ways.

Also, all these tutorials talk about changing the Pi’s default audio output. This may be necessary in some circumstances, but often it’s not: Insteads simply specify the desired output each time a command to play some audio is run, and boom – we don’t have to care about the defaults at all.

Now let’s see how this works (note that this guide is for the current – November 2017 – version of Raspian Stretch Lite, but it should also work with Raspian Stretch Desktop).

Find the Correct “PCM Device”

The “PCM device” is the argument we’ll need to provide to aplay, telling it which audio interface to use. How do we find it? Let’s have a look at the full list of devices aplay knows about:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ aplay -L

null
    Discard all samples (playback) or generate zero samples (capture)
default:CARD=ALSA
    bcm2835 ALSA, bcm2835 ALSA
    Default Audio Device
sysdefault:CARD=ALSA
    bcm2835 ALSA, bcm2835 ALSA
    Default Audio Device
dmix:CARD=ALSA,DEV=0
    bcm2835 ALSA, bcm2835 ALSA
    Direct sample mixing device
[…]
default:CARD=Device
    USB Audio Device, USB Audio
    Default Audio Device
sysdefault:CARD=Device
    USB Audio Device, USB Audio
    Default Audio Device
front:CARD=Device,DEV=0
    USB Audio Device, USB Audio
    Front speakers
[…]

One of the entries should look like default:CARD=Device with an explanation like “USB Audio Device, Default Audio Device” next to is – that’s the one you’re looking for. Remember its name.

Play Sound from the Command-line

Once the correct PCM device is known, use aplay to play a wave file over this interface:

1
$ aplay -D default:CARD=Device doorbell.wav

Adjusting the Volume from the Command-line

For adjusting the volume we’ll use amixer. Unfortunately, you can’t use the same PCM device here – instead you have to provide the “card number”. This will most probably be “1” (“0” being the Pi’s internal audio device), but just try it out and check the device description:

1
2
3
4
5
6
7
$ amixer -c 1 info

Card hw:1 'Device'/'C-Media Electronics Inc. USB Audio Device at usb-3f980000.usb-1.5, full speed'
  Mixer name    : 'USB Mixer'
  Components    : 'USB0d8c:0014'
  Controls      : 9
  Simple ctrls  : 3

If the device description does not look like the audio interface you want to use, try -c 2 instead (and so on).

Now we need to find out the correct “control” (most soundcards have multiple controls for things like “playback volume”, “microphone volume” etc.):

1
2
3
4
5
6
7
8
9
10
11
$ amixer -c 1 controls

numid=3,iface=MIXER,name='Mic Playback Switch'
numid=4,iface=MIXER,name='Mic Playback Volume'
numid=7,iface=MIXER,name='Mic Capture Switch'
numid=8,iface=MIXER,name='Mic Capture Volume'
numid=9,iface=MIXER,name='Auto Gain Control'
numid=5,iface=MIXER,name='Speaker Playback Switch'
numid=6,iface=MIXER,name='Speaker Playback Volume'
numid=2,iface=PCM,name='Capture Channel Map'
numid=1,iface=PCM,name='Playback Channel Map'

We’re interested in the “Speaker Playback Volume” control. Note that it’s named numid=6. Let’s have a look at its current value:

1
2
3
4
5
6
$ amixer -c 1 cget numid=6

numid=6,iface=MIXER,name='Speaker Playback Volume'
  ; type=INTEGER,access=rw---R--,values=2,min=0,max=37,step=0
  : values=16,16
  | dBminmaxmute-min=-37.00dB,max=0.00dB

Parsing this we understand that this control has two integer values with an allowed range of 0 to 37. Currently both values are set to 16. Apparently this control lets us set the volume for both stereo channels separately, and currently the volume is set to about 50%.

Now we know everything needed to construct a single command to set the volume to 100%:

1
$ amixer -c 1 cset numid=6 37,37

This tells amixer to set the volume control (numid=6) of the second sound card (-c 1) to the values 37, 37 (100%).

TL;DR: Just Turn up the Volume and Play me a Sound!

Simply combine both commands from the previous sections:

1
$ amixer -c 1 cset numid=6 37,37; aplay -D default:CARD=Device doorbell.wav

And this is exactly what we use in our doorbell application.


Thinking about an IoT project, needing a prototype? We can do both, hardware and software.

Let’s talk!