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?

not2qubit
  • 1,407
  • 2
  • 14
  • 23

1 Answers1

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:

ernstkl
  • 105
  • 3
not2qubit
  • 1,407
  • 2
  • 14
  • 23
  • 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 – Mike 'Pomax' Kamermans Apr 11 '19 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 Apr 11 '19 at 22:51
  • I tested it with one of the bog-standard test audio files in /usr/share/sounds/alsa (specifically, Front_Center.wav) – Mike 'Pomax' Kamermans Apr 11 '19 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 Apr 16 '19 at 06:44
  • 3
    It is criminal that there are so few upvotes. – BradChesney79 Apr 29 '19 at 21:58
  • And in 2020 this is still the clearest ALSA config article for all Linuxes out there. Enough to make me simply give up tbh. What a mess. All I want to do is see my external USB inputs in ALSA without losing pulse which is necessary for a functioning multimedia desktop. – RichieHH Jul 20 '20 at 09:56
  • Just FYI - uninstalling pulse audio causes bluetooth headphones to not work. I had things working (ie recording over USB and playing over bluetooth headphones) but then uninstalled pulseaudio and headphones are then not available as input devices anymore. – Renier Botha Jan 30 '22 at 16:04
  • You're my savior @not2qubit . I hope this would be put in the first page of any RPi Tutorial, especially AdaFruit outdated ones! You saved me from going down the rabbit hole of unsoldering everything just to integrate some I2S amp, when in fact, the USB audio was configurable. – Myoch Jan 23 '23 at 16:38