25

I've got an external USB sound-card from C-Media running on my RPi3. I can play some recordings using aplay/arecord by specifying the card index and ALSA plugin. However, many other sound files does not play at all, or not as expected. Some other player software does not work either.

Q: How can I set up ALSA to use it by default?

1 Answer 1

53

Background

It's amazing to see how much effort has been put in to trying to resolve various sound related problems for the Raspberry Pi. Apparently it must be the weakest spot for new users to successfully develop with and use ALSA under Raspbian. Having spent considerable time and effort trying to get my own RPi3 sound working in different OS versions and in other Linux distributions as well, I've decided to write the conclusive to-go-to solution page. At least for the topic of using an external sound card on the latest Raspbian Stretch.

The ALSA sound system

ALSA is meant to support any kind of *nix based device, regardless of its hardware configuration and regardless how old is the hardware. Needless, there is little point in trying to get into the details of 20 years of its development. We simply apply the essence to a current situation.

However, at no time in history has mankind produced such an amount of useless and dysfunctional diagrams, as for trying to explain ALSA. The only ones remotely informative are these two:

enter image description here enter image description here

Getting the system info

The first step is to figure out what sound, if any, works and what hardware you already have. There are all sorts of ways to find out details, but for the average person, most of those details are meaningless. We show the most important.

What do we want to know about our (sound) system?

We want to know:

  • the built-in sound hardware name and versions
  • the external sound hardware name and versions
  • what kernel drivers (modules) it uses
  • what other sound related kernel drivers/modules are loaded
  • what sound cards are available
  • in what order the sound cards are used and selected by the OS and programs
  • if there are any conflicting hardware or sound system programs

From where do you want to play and record sound on your system?

Your options for playing sounds, can be:

  1. From the internal 3.5 mm audio headphone jack (analog audio)
  2. From the HDMI connected screen/monitor
  3. From an external USB sound card
  4. From a GPIO port

Your options for recording sounds, can be:

  • a. From an external USB sound-card (with at least one type of input)
  • b. From a file or stream
  • c. From a GPIO

In this post, we will tell you how to play and record using the external USB sound card.

A future proof success plan?

With RPi's updates there is a constant flow of new changes and improvements, often breaking old solutions. The idea here is to make as few changes to the system as possible or making them obvious if needed. That means, we prefer to use a by-user configuration to a system wide one. I.e. you should try to use configuration files in your home directory, rather than in root owned system files.


TL;DR (Let's get going already!)

Reboot and plugin your external USB sound-card, so we start on the same page...

A. Collect some info

# Check ALSA modules
cat /proc/asound/modules

 0 snd_bcm2835
 1 snd_usb_audio

# Check sound hardware
cat /proc/asound/cards

 0 [ALSA           ]: bcm2835 - bcm2835 ALSA
                      bcm2835 ALSA
 1 [Set            ]: USB-Audio - C-Media USB Headphone Set
                      C-Media USB Headphone Set at usb-3f980000.usb-1.5, full speed

# Check info on card-1
amixer -c 1
 
Simple mixer control 'Headphone',0
  Capabilities: pvolume pswitch pswitch-joined
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 151
  Mono:
  Front Left: Playback 104 [69%] [-8.88dB] [on]
  Front Right: Playback 104 [69%] [-8.88dB] [on]
Simple mixer control 'Mic',0
  Capabilities: pvolume pvolume-joined cvolume cvolume-joined pswitch pswitch-joined cswitch cswitch-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: Playback 0 - 32 Capture 0 - 16
  Mono: Playback 23 [72%] [34.36dB] [off] Capture 0 [0%] [0.00dB] [on]
Simple mixer control 'Auto Gain Control',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [on]

Here we see that the system default (card 0) is using the bcm2835 ALSA module. Although we can usually specify what card to use, some software like omxplayer doesn't have this option, and will fail to produce any sound in various ways.

At this point you could already attempt to configure your ALSA config files. Some are successful, while many others aren't because it is not obvious how and where this should be done. What we ultimately want, is to tell our system to use our external USB sound card.

B. Remove Audio Bloat

Unless you have very good reasons to keep PulseAudio (PA) or additional JACK server software, you should uninstall them, if they are there. They tend to interfere with ALSA, as they take control of many ALSA functions, and all the additional configurations necessary by those make things incredibly confusing!

sudo apt-get remove pulseaudio

# You can keep `jack*`, but make sure it is not running.
# If it is running you need to stop it, disble it or remove it.
service --status-all
# Disable the running service with:
sudo systemctl disable xxxxx

C. Disable the internal (Broadcom) sound card

The internal soundcard is driven by the kernel module in: /lib/modules/4.9.59-v7+/kernel/sound/arm/snd-bcm2835.ko Unless you are planning to use the audio jack (in 1) or HDMI (in 2), you should disable this kernel module. There are two methods to do this.

  1. Disable it with a boot config flag
  2. Prevent it from getting loaded into kernel by the modprobe.d daemon

Trying to stay with our minimalistic approach, we choose (1).

# Edit boot config with:
sudo nano /boot/config.txt
# so that:
cat /boot/config.txt
...
# Enable audio (loads snd_bcm2835)
#dtparam=audio=on
dtparam=audio=off
...
# You need to reboot!
sudo reboot now

If for some reason, you prefer to use method (2), then you need to blacklist the kernel module. To do this, you simply enter the the word blacklist, followed by name of the module in any *.conf file under /etc/modprobe.d/. However, there is already an empty, reserved file there, called raspi-blacklist.conf for this purpose. However, after 6 months, you will have forgotten about this, and what it contains, so you are better off naming it after the module you are blacklisting.

cd /etc/modprobe.d/
# Manually edit a new file:  blacklist-snd_bcm2835.conf
#sudo nano blacklist-snd_bcm2835.conf
# And add the line: blacklist snd_bcm2835
## OR directly with:
sudo tee /etc/modprobe.d/blacklist-snd_bcm2835.conf <<EOF
blacklist snd_bcm2835
EOF
# You need to reboot!
sudo reboot now

What's the difference? None, AFAICT.

After reboot, re-check your sound modules.

$ cat /proc/asound/modules
 1 snd_usb_audio

$ cat /proc/asound/cards
 1 [Set            ]: USB-Audio - C-Media USB Headphone Set
                      C-Media USB Headphone Set at usb-3f980000.usb-1.5, full speed

Bom! Your annoying bcm2835 (card 0) is gone, but the index of the USB card is the same! This is actually good.

Configure your ALSA

As I already mentioned, we want ALSA to use our own USB sound card as the default. This also means that we want it to have the first available index in the list of the kernel sound modules. Since the module was removed above and the index is the same (card 1), we are good. But in case we need to load bcm2835 again, we are not, as that module would re-appear as the first one (card 0).

We simply need to tell ALSA what our defaults PCM card index should be and in what order they should be prioritized in the kernel.

There are 3 places where you can configure your ALSA.

  • the user config in: ~/.asoundrc
  • the system config in: /usr/share/alsa/alsa.conf
  • the system module conf in: /lib/modprobe.d/aliases.conf

The first 2 changes the default devices, whereas the last, ensure the order of appearance.

We first fix our user specific config to use card 1. If you have more than one cards shown, then select the index of one you want to be default.

#cat ~/.asoundrc
cat << EOF | tee ~/.asoundrc

pcm.!default {
        type hw
        card 1
}

ctl.!default {
        type hw
        card 1
}
EOF

Next, we fix the system config, using the same card index numbers as above. We need to do this, because some system packages would never see your user config file.

sudo nano /usr/share/alsa/alsa.conf
# then replace:
#defaults.ctl.card 0
#defaults.pcm.card 0
# with:
defaults.ctl.card 1
defaults.pcm.card 1

Now reboot for the changes to take effect.

You should now have a working audio system.


Let's test it!

To perform a proper test, you need proper files to test with. So before anything, make sure all your sound and video files are actually working.

(I spent considerable time trying to get some h264/mp4 test video to play audio, only to discover later, that it never had any audio encoded! Duh!)

WARNING If you are trying to test videos that use the MPEG-2 or VC-1 codecs, you have to buy (!) a codec key from the RPi organization to be able to fully decode it with the built-in hardware decoders. Otherwise, you need to convert the files first.

You can check if your codec is enabled with:

# Check with:
vcgencmd codec_enabled MPG2
vcgencmd codec_enabled WVC1

You will need some verified files to test with. You can download and use these if you don't have any.

# get some demo sound and video files
cd ~/Music

wget -Lk http://rpf.io/lamp3 -O example_11k.mp3
wget -Lk http://www.kozco.com/tech/piano2-CoolEdit.mp3 -O pianoTest_48k.mp3
wget -Lk http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4 -O bbb_720p_2mb.mp4
wget -Lk https://raw.githubusercontent.com/mediaelement/mediaelement-files/master/big_buck_bunny.mp4 -O bbb_360_22k.mp4

Next, let's PLAY!!

# Double-check! 
aplay -l && arecord -l

**** List of PLAYBACK Hardware Devices ****
card 1: Set [C-Media USB Headphone Set], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

**** List of CAPTURE Hardware Devices ****
card 1: Set [C-Media USB Headphone Set], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0


# Play white noise on 2-channels (L/R) on Card-1 
speaker-test -c2 -D hw:1,0

# Play a WAV sound file
speaker-test -c2 -D hw:1,0 --test=wav -w /usr/share/sounds/alsa/Front_Center.wav

# Once the correct default card+device is set, and after reboot, 
# then full left/right voice test (above) is performed, just by:
speaker-test -c2 -twav

# Record some sounds (with a VU bar):
arecord --device=hw:1,0 --format S16_LE --rate 44100 -c1 -V mono test.wav

# Play recorded sounds
aplay -D plughw:1,0 test.wav

# Play recorded sounds (sample rate have to be equal) 
speaker-test -c2 -D plughw:1,0 -r 44100 --test=wav -W $HOME -w test.wav

# Install an MP3 player
sudo apt-get install mpg123

# Play some MP3 file
mpg123 -v -r 44100 some.mp3

# Play an MP3 sound stream
mpg123 http://ice1.somafm.com/u80s-128-mp3


# This plays video, but no sound!
omxplayer -o alsa /opt/vc/src/hello_pi/hello_video/test.h264

# This plays video and sound!
omxplayer -o alsa bbb_720p_2mb.mp4

# The following plays sometimes (!?) and at the wrong speed!
omxplayer -o alsa some.mp3

YOU ARE GOOD TO GO!


[optional] Order of Additional Audio Hardware

NOTE If you use this section you need to change all the card index values in the above sections!

If you have attached additional audio hardware, and it doesn't show up as you want, you can force to re-arrange the order in which the modules appear, in the /lib/modprobe.d/aliases.conf file.

Some solutions have proposed to make changes in this file. Unfortunately, they are not aware that the RPi default USB sound module is misspelled! So the changes never take effect. The sound kernel module we are concerned with, is called snd_usb_audio and not snd-usb-audio. The filename is snd-usb-audio.ko and located in: /lib/modules/4.9.59-v7+/kernel/sound/usb/.

Funny enough, the text in the file says it doesn't need to be modified!

sudo nano /lib/modprobe.d/aliases.conf

#--------------------------------------
# For original (out-of-box) use
#--------------------------------------
# replace this: 
options snd-usb-audio index=-2
# with this:
options snd_usb_audio index=-2

#--------------------------------------
# To change the index & order
#--------------------------------------
# Set the index value of the cards:
options snd_usb_audio index=0
options snd_bcm2835 index=1
# Set the order:
options snd slots=snd_usb_audio,snd_bcm2835

References:

8
  • Using a raspi 3B+ with Raspian, aplay consistently did nothing after all of this work, until I used -D plughw:0,0 instead of -D hw:0,0 (based on shttps://raspberrypi.stackexchange.com/a/89162). Unfortunately, while almost everything can now play audio over USB, the utility I need to work most (vban_receptor) still doesn't work, but at this point it's almost certainly not the setup's fault anymore Commented Apr 11, 2019 at 19:20
  • 2
    Yes, this is a bloody nightmare. Please have look at the list of different PCM plugins here. Then read the 1st section named "ALSA devices and plugins" here. Perhaps that would help shed some light on why you need to use plughw instead of hw. BTW. Since hw is straight to hardware, whereas plughw does some processing, you may want to check what you're actually trying to play.
    – not2qubit
    Commented Apr 11, 2019 at 22:51
  • I tested it with one of the bog-standard test audio files in /usr/share/sounds/alsa (specifically, Front_Center.wav) Commented Apr 11, 2019 at 23:03
  • 1
    You absolute star. I wasn't expecting that getting sound out of a raspberry pi would be a multi-day project with no clear guidance on what to do. All the +1s for you.
    – Kieran
    Commented Apr 16, 2019 at 6:44
  • 3
    It is criminal that there are so few upvotes. Commented Apr 29, 2019 at 21:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.