Playing Audio over an USB Audio Interface on a Raspberry Pi from the Command-line
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.