This blog post is tutorial which describes how to select a default sound card and run multiple playbacks simultaneously, using ALSA on Linux, without a sound server.
The quick trick is having
defaults.pcm.!card Headset
defaults.ctl.!card Headset
defaults.pcm.!device 0
defaults.ctl.!device 0
in your
~/.asoundrc
. (Replace
Headset
with the name of the card on which you want to hear sound. Get the list of available sound cards with
aplay -l | awk '/^card/{print$3}'|sort|uniq
. To apply this setting for all users, add the lines above to
/etc/asound.conf
instead.) If this doesn't work for you, please continue reading.
Let's suppose you have a Linux system and many sound cards with an
ALSA (>= 0.9) driver, and you don't use any sound server (e.g.
pulse,
ESD == esound or
artsd). The
dmix feature of ALSA does software sound mixing, so it makes it possible to run multiple playbacks simultaneously on the same card. ALSA, by default, enables dmix for all cards which don't support concurrent playback of more than one sound stream.
So you just run
mplayer -ao alsa file1.mp3
, and simultaneously (possibly in another terminal window)
mplayer -ao alsa file2.mp3
. You should hear both playbacks at the same time. (Please note that you can omit =-ao alsa= from the mplayer command line if you add
ao=alsa
to your
~/.mplayer/config
file.) If the second mplayer doesn't start playback, but exists with an error message containing
Device or resource busy
, this means there is something wrong with your settings – this tutorial will help to fix that.
If even the first mplayer produces the
Device or resource busy error, then close or kill all applications that might play sound. This includes the web browser (with flash), pulse, esd, artsd, mplayer, Skype, MPD and system sounds (disable everything in Gnome / System / Preferences / Sound / Sound). After that,
mplayer -ao alsa file1.mp3
should start the first playback, and simultaneously,
mplayer -ao alsa file2.mp3
should start the second playback.
If you have multiple sound cards (possibly the sound card in your computer, and an external USB headset), you can set the environment variable
ALSA_CARD
to direct playback to a specific card. Example 1:
ALSA_CARD=Headset mplayer -ao alsa file1.mp3
. Example 2: start Firefox as
ALSA_CARD=Headset firefox
to have the sound Flash movies played on the card named
Headset
.
You can get a list of sound cards (with some extra information) with
aplay -l
. For example, on my system, I get
$ aplay -l
card 0: Intel [HDA Intel], device 0: CONEXANT Analog [CONEXANT Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: Intel [HDA Intel], device 1: Conexant Digital [Conexant Digital]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: TuxDroid [TuxDroid], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: TuxDroid [TuxDroid], device 1: USB Audio [USB Audio #1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: Headset [Plantronics Headset], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
Here is how I can select each card and device:
card 0: Intel [HDA Intel], device 0: CONEXANT Analog [CONEXANT Analog]
ALSA_CARD=0
ALSA_CARD=Intel
card 0: Intel [HDA Intel], device 1: Conexant Digital [Conexant Digital]
ALSA_CARD=0 ALSA_PCM_CARD=1
ALSA_CARD=Intel ALSA_PCM_CARD=1
card 1: TuxDroid [TuxDroid], device 0: USB Audio [USB Audio]
ALSA_CARD=1
ALSA_CARD=TuxDroid
card 1: TuxDroid [TuxDroid], device 1: USB Audio [USB Audio #1]
ALSA_CARD=1 ALSA_PCM_CARD=1
ALSA_CARD=TuxDroid ALSA_PCM_CARD=1
card 2: Headset [Plantronics Headset], device 0: USB Audio [USB Audio]
ALSA_CARD=2
ALSA_CARD=Headset
Once you have the proper
ALSA_CARD
and
ALSA_PCM_CARD
setting, you can add them to your
~/.bashrc
and
~/.gnomerc
and
~/.xprofile
(and possibly to
/etc/environment
and
/etc/X11/Xsession.d/*
and
/etc/gdm/Xsession
). If you log out and log in to your graphic session, you'll have these environment variables by default.
It is possible to select the default sound card without changing setting the
ALSA_CARD
or
ALSA_PCM_CARD
environment variables. To do so, add these lines to your
~/.asoundrc
:
defaults.pcm.!card Headset
defaults.ctl.!card Headset
defaults.pcm.!device 0
defaults.ctl.!device 0
Each
!card
line corresponds to the
ALSA_CARD
value, and each
!device
line corresponds to the
ALSA_PCM_CARD
value.
If you set the default in
~/.asoundrc
and set the environment variables as well, then the environment variables take effect.
Please note that if you specify any specific ALSA device to any program (other than
default
), and the program starts playback, then automatic dmix would not work until that program finishes playback and closes the device. This implies that no other program will be able to start playback (but will yield
Device or resource busy) until that happens. For example, Skype keeps the sound card open while it is running. So if you want to play sound not coming from Skype while Skype is running, you have to select
Default device (default) in Options / Sound Devices for both Sound Out and Ringing. A similar restriction applies to music players and other software: if you specify the playback device for them in their command line or preferences, then the software will lock the sound card, and you lose dmix and concurrent playback. The only dmix-safe ways to select a sound card are the
ALSA_CARD
etc. environment variables and
~/asoundrc
.
To get information about the ALSA cards, run
aplay -l
and
aplay -v -v -L
.
ALSA provides OSS emulation (i.e.
/dev/dsp
,
/dev/dsp1
), but dmix doesn't work with OSS emulation. To get it work, please run the software which needs OSS using the
aoss wrapper, e.g.
aoss mplayer -ao oss file1.oss
, and concurrently,
aoss mplayer -ao oss file2.oss
or
mplayer -ao alsa file2.oss
. If you get the error message
/dev/dsp: Device or resource busy
from a program, then you'll either have to change it to use ALSA, or run it within
aoss.
Here are some sine wave sound generators if you don't have an MP3 ready to test playback with:
perl -e 'print pack("v",32000*sin($_/34))."\0\0"; ++$_ while 1' | aplay -f dat # Left ear
perl -e 'print "\0\0".pack("v",32000*sin($_/34)); ++$_ while 1' | aplay -f dat # Right ear
If you have the
asoundconf utility, you can use it to set up the default sound card in your
~/.asoundrc
. For example, after removing
~/.asoundrc
and running
asoundconf set-default-card Headset
, you'll get a line
<:/home/USERNAME/.asoundrc.asoundconf>
in file
~/.asoundrc
, and the file
~/.asoundrc.asoundconf
would contain more than 50 config lines, the essential ones being
!defaults.pcm.card Headset
defaults.ctl.card Headset
defaults.pcm.device 0
defaults.pcm.subdevice -1
defaults.pcm.nonblock 1
defaults.pcm.ipc_key 5678293
defaults.pcm.ipc_gid audio
defaults.pcm.ipc_perm 0660
defaults.pcm.dmix.max_periods 0
defaults.pcm.dmix.rate 48000
defaults.pcm.dmix.format S16_LE
defaults.pcm.dmix.card defaults.pcm.card
defaults.pcm.dmix.device defaults.pcm.device
defaults.pcm.dsnoop.card defaults.pcm.card
defaults.pcm.dsnoop.device defaults.pcm.device
defaults.namehint.extended off
This seems to be too much compared to the 4 lines the beginning of this tutorial suggests.
Random notes
With ALSA 1.0.15, only
plughw:
works for tuxdroid (so it cannot be used with
ALSA_CARD
, which implies
hw:
). Here is how to play:
mplayer -ao alsa:device=plughw=TuxDroid file1.mp3
or
aplay -D plughw:TuxDroid </dev/urandom
. Please note that this restriction applies to both mplayer and aplay. (Maybe that's because dmix was busy when the tuxdroid was connected -- and if we reload ALSA, maybe it will work if I connect the tuxdroid first, and then load the ALSA modules?) The reason why it doesn't work seems to be that the U8 sample format needed by the tuxdroid was introduced only in ALSA 1.0.16. I've verified with libasound 1.0.16 installed (with the same old ALSA kernel) in a chroot, and dmix works with the tuxdroid.
The setting
ALSA_CARD=Foo ALSA_PCM_CARD=2
corresponds to
aplay -D hw:Foo,2
and
mplayer -ao alsa:device=hw=Foo.2
. Please note that there is no corresponding environment variable setting for
plughw
instead of
hw
. Please also note that mplayer won't use dmix (thus it won't be able to run multiple playbacks concurrently) if you specify any other ALSA setting than
mplayer -ao alsa
or
mplayer -ao alsa:device=default
. A similar restriction applies to
aplay -D
: if you specify any device other than
default
there, it won't use dmix.
An example full mplayer error message when dmix didn't work:
[AO_ALSA] alsa-lib: pcm_hw.c:1099:(snd_pcm_hw_open) open /dev/snd/pcmC2D0p failed: Device or resource busy
[AO_ALSA] Playback open error: Device or resource busy
Could not open/initialize audio device -> no sound.
Audio: no sound