Chapter 5 ALSA
ALSA (last modified v0.9)
- Resources
- User space tools
- Programming ALSA
- Mixing audio
- Writing an ALSA device driver
- Conclusion
Upto: Table of Contents of full book "Linux Sound"
ALSA
ALSA is a low-level interface to the sound cards. If you are building your own sound server system, or writing device drivers, then you would be interested in ALSA. It sits at the bottom of most of the current Linux systems so to understand them you may need to understand aspects of ALSA. Otherwise, you are probably not interested so should move on.
Resources
- Introduction to Sound Programming with ALSA by Jeff Tranter
- A close look at ALSA by Volker Schatz
- ALSA API
- ALSA Programming HOWTO by Matthias Nagorni
- Linux sound HOWTO for ALSA users from Tech Patterns
User space tools
alsamixer
alsamixer
runs within a terminal window and allows you to select sound cards and controls interfaces on those cards. It looks like
amixer
is a command line applications with similar functions.
Compared to the general mixer functions described in the Basic chapter , the mixer functions are quite limited:
- Setting the playback and capture volumes on output and input channels
- Muting or unmuting a card
The document Sound configuration on Raspberry Pi with ALSA by Stephen C Phillips is applicable to all other ALSA systems and not just the Raspberry Pi.
alsactl
Simple control programs for ALSA configurations.
speaker-test
This command allows you to test which outputs go where. For e.g. 5 channel sound, running
speaker-test -t wav -c 5
will produce on my default sound card the text and audio of
speaker-test 1.0.25
Playback device is default
Stream parameters are 48000Hz, S16_LE, 5 channels
WAV file(s)
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 39 to 419430
Period size range from 12 to 139810
Using max buffer size 419428
Periods = 4
was set period_size = 104857
was set buffer_size = 419428
0 - Front Left
1 - Front Right
2 - Rear Left
3 - Rear Right
4 - Center
Time per period = 12.948378
It will also play the phrases "Front Left" etc to the relevant spekaer.
aplay/arecord
Play a file or record to a file. To play the microphone to the speaker,
arecord -r 44100 --buffer-size=128 | aplay --buffer-size=128
Identifying ALSA cards
The simplest ways are to run aplay
and arecord
with the '-l' option:
arecord -l
**** List of CAPTURE Hardware Devices **** card 0: PCH [HDA Intel PCH], device 0: STAC92xx Analog [STAC92xx Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: Pro [SB X-Fi Surround 5.1 Pro], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0
aplay -l
**** List of PLAYBACK Hardware Devices **** card 0: PCH [HDA Intel PCH], device 0: STAC92xx Analog [STAC92xx Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: NVidia [HDA NVidia], device 8: HDMI 2 [HDMI 2] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: Pro [SB X-Fi Surround 5.1 Pro], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: Pro [SB X-Fi Surround 5.1 Pro], device 1: USB Audio [USB Audio #1] Subdevices: 1/1 Subdevice #0: subdevice #0
Device names
The cards are often given names such as "hw:0" or "hw:2.2" in programs such as qjackctl
(see the chapter on Jack). The term "hw" refers to hardware devices. The major number refers to the card number, the minor number to the device number. The name of the device is in [...] brackets.
Devices may also be known by aliases. The command aplay -L
lists device aliases. For example, the "hdmi" alias is defined on my system in the configuration file /etc/asound.conf
pcm.hdmi0 {
type hw
card 1
device 3 }
pcm.hdmi1 {
type hw
card 1
device 7 }
pcm.hdmi2 {
type hw
card 1
device 8 }
so that "hdmi:0" is really "hw:1,3": card 1, device 3.
Other aliases may be defined to cover a range of devices, parameterised by card and device. For example, /usr/share/alsa/pcm/surround40.conf
defines
pcm.!surround40 {
@args [ CARD DEV ]
@args.CARD {
type string
default {
@func getenv
vars [
ALSA_SURROUND40_CARD
ALSA_PCM_CARD
ALSA_CARD
]
default {
@func refer
name defaults.pcm.surround40.card
}
}
}
@args.DEV {
type integer
default {
@func igetenv
vars [
ALSA_SURROUND40_DEVICE
]
default {
@func refer
name defaults.pcm.surround40.device
}
}
}
...
}
defines for example "surround40:CARD=PCH,DEV=0" as an alias for hw:0,0 on my system (PCH is card 0).
I don't know an easy programmatic way to go from "card 1, device 3" to "hdmi:0".
- The output from
aplay -L
on my system isdefault Default sysdefault:CARD=PCH HDA Intel PCH, STAC92xx Analog Default Audio Device front:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog Front speakers surround40:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 4.0 Surround output to Front and Rear speakers surround41:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 4.1 Surround output to Front, Rear and Subwoofer speakers surround50:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 5.0 Surround output to Front, Center and Rear speakers surround51:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 5.1 Surround output to Front, Center, Rear and Subwoofer speakers surround71:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 7.1 Surround output to Front, Center, Side, Rear and Woofer speakers hdmi:CARD=NVidia,DEV=0 HDA NVidia, HDMI 0 HDMI Audio Output hdmi:CARD=NVidia,DEV=1 HDA NVidia, HDMI 1 HDMI Audio Output hdmi:CARD=NVidia,DEV=2 HDA NVidia, HDMI 2 HDMI Audio Output sysdefault:CARD=Pro SB X-Fi Surround 5.1 Pro, USB Audio Default Audio Device front:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio Front speakers surround40:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 4.0 Surround output to Front and Rear speakers surround41:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 4.1 Surround output to Front, Rear and Subwoofer speakers surround50:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 5.0 Surround output to Front, Center and Rear speakers surround51:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 5.1 Surround output to Front, Center, Rear and Subwoofer speakers surround71:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 7.1 Surround output to Front, Center, Side, Rear and Woofer speakers iec958:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio IEC958 (S/PDIF) Digital Audio Output
- The output from
arecord -L
isdefault Default sysdefault:CARD=PCH HDA Intel PCH, STAC92xx Analog Default Audio Device front:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog Front speakers surround40:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 4.0 Surround output to Front and Rear speakers surround41:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 4.1 Surround output to Front, Rear and Subwoofer speakers surround50:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 5.0 Surround output to Front, Center and Rear speakers surround51:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 5.1 Surround output to Front, Center, Rear and Subwoofer speakers surround71:CARD=PCH,DEV=0 HDA Intel PCH, STAC92xx Analog 7.1 Surround output to Front, Center, Side, Rear and Woofer speakers sysdefault:CARD=Pro SB X-Fi Surround 5.1 Pro, USB Audio Default Audio Device front:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio Front speakers surround40:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 4.0 Surround output to Front and Rear speakers surround41:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 4.1 Surround output to Front, Rear and Subwoofer speakers surround50:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 5.0 Surround output to Front, Center and Rear speakers surround51:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 5.1 Surround output to Front, Center, Rear and Subwoofer speakers surround71:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio 7.1 Surround output to Front, Center, Side, Rear and Woofer speakers iec958:CARD=Pro,DEV=0 SB X-Fi Surround 5.1 Pro, USB Audio IEC958 (S/PDIF) Digital Audio Output
ALSA configuration files
This tutorial by Volker Schatz explains what is going on in ALSA configuration files and looks really good: A close look at ALSA
We just note one thing: the default ALSA device is "hw:0". This is hard-coded into ALSA. But it can be overridden in configuration files. This is done for example by PulseAudio - see next chapter.
alsa-info
This will collect information about your system and save it in a file. It is a shell script that gives an enormous amount of information. Here is a heavily elided subset of the information:
upload=true&script=true&cardinfo=
!!################################
!!ALSA Information Script v 0.4.60
!!################################
!!Script ran on: Tue Jun 12 04:50:22 UTC 2012
!!Linux Distribution
!!------------------
Fedora release 16 (Verne) Fedora release 16 (Verne) Fedora release 16 (Verne) Fedora release 16 (Verne)
...
!!ALSA Version
!!------------
Driver version: 1.0.24
Library version: 1.0.25
Utilities version: 1.0.25
!!Loaded ALSA modules
!!-------------------
snd_hda_intel
snd_hda_intel
!!Sound Servers on this system
!!----------------------------
Pulseaudio:
Installed - Yes (/usr/bin/pulseaudio)
Running - Yes
Jack:
Installed - Yes (/usr/bin/jackd)
Running - No
!!Soundcards recognised by ALSA
!!-----------------------------
0 [PCH ]: HDA-Intel - HDA Intel PCH
HDA Intel PCH at 0xe6e60000 irq 47
1 [NVidia ]: HDA-Intel - HDA NVidia
HDA NVidia at 0xe5080000 irq 17
!!PCI Soundcards installed in the system
!!--------------------------------------
00:1b.0 Audio device: Intel Corporation 6 Series/C200 Series Chipset Family High Definition Audio Controller (rev 04)
01:00.1 Audio device: nVidia Corporation HDMI Audio stub (rev a1)
...
!!HDA-Intel Codec information
!!---------------------------
...
Default PCM:
rates [0x5e0]: 44100 48000 88200 96000 192000
bits [0xe]: 16 20 24
formats [0x1]: PCM
Node 0x0a [Pin Complex] wcaps 0x400583: Stereo Amp-In
Control: name="Mic Jack Mode", index=0, device=0
ControlAmp: chs=0, dir=In, idx=0, ofs=0
Control: name="Mic Capture Volume", index=0, device=0
ControlAmp: chs=3, dir=In, idx=0, ofs=0
Control: name="Mic Jack", index=0, device=0
Amp-In caps: N/A
Amp-In vals: [0x01 0x01]
Pincap 0x0001173c: IN OUT HP EAPD Detect
Vref caps: HIZ 50 GRD 80
EAPD 0x2: EAPD
Pin Default 0x03a11020: [Jack] Mic at Ext Left
Conn = 1/8, Color = Black
DefAssociation = 0x2, Sequence = 0x0
Pin-ctls: 0x24: IN VREF_80
Unsolicited: tag=03, enabled=1
Power: setting=D0, actual=D0
Connection: 3
0x13* 0x14 0x1c
!!ALSA configuration files
!!------------------------
!!System wide config file (/etc/asound.conf)
#
# Place your global alsa-lib configuration here...
#
@hooks [
{
func load
files [
"/etc/alsa/pulse-default.conf"
]
errors false
}
]
pcm.hdmi0 {
type hw
card 1
device 3 }
pcm.hdmi1 {
type hw
card 1
device 7 }
pcm.hdmi2 {
type hw
card 1
device 8 }
!!Aplay/Arecord output
!!------------
APLAY
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: STAC92xx Analog [STAC92xx Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 8: HDMI 2 [HDMI 2]
Subdevices: 1/1
Subdevice #0: subdevice #0
ARECORD
**** List of CAPTURE Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: STAC92xx Analog [STAC92xx Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
!!Amixer output
!!-------------
!!-------Mixer controls for card 0 [PCH]
Card hw:0 'PCH'/'HDA Intel PCH at 0xe6e60000 irq 47'
Mixer name : 'IDT 92HD90BXX'
Components : 'HDA:111d76e7,10280494,00100102'
Controls : 19
Simple ctrls : 10
Simple mixer control 'Master',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined penum
Playback channels: Mono
Limits: Playback 0 - 64
Mono: Playback 62 [97%] [-1.50dB] [on]
Simple mixer control 'Headphone',0
Capabilities: pvolume pswitch penum
Playback channels: Front Left - Front Right
Limits: Playback 0 - 64
Mono:
Front Left: Playback 64 [100%] [0.00dB] [on]
Front Right: Playback 64 [100%] [0.00dB] [on]
Simple mixer control 'PCM',0
Capabilities: pvolume penum
Playback channels: Front Left - Front Right
Limits: Playback 0 - 255
Mono:
Front Left: Playback 254 [100%] [0.20dB]
Front Right: Playback 254 [100%] [0.20dB]
Simple mixer control 'Front',0
Capabilities: pvolume pswitch penum
Playback channels: Front Left - Front Right
Limits: Playback 0 - 64
Mono:
Front Left: Playback 64 [100%] [0.00dB] [on]
Front Right: Playback 64 [100%] [0.00dB] [on]
Simple mixer control 'Mic',0
Capabilities: cvolume penum
Capture channels: Front Left - Front Right
Limits: Capture 0 - 3
Front Left: Capture 1 [33%] [10.00dB]
Front Right: Capture 1 [33%] [10.00dB]
Simple mixer control 'Mic Jack Mode',0
Capabilities: enum
Items: 'Mic In' 'Line In'
Item0: 'Mic In'
Simple mixer control 'Beep',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined penum
Playback channels: Mono
Limits: Playback 0 - 3
Mono: Playback 1 [33%] [-12.00dB] [on]
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch penum
Capture channels: Front Left - Front Right
Limits: Capture 0 - 46
Front Left: Capture 46 [100%] [30.00dB] [on]
Front Right: Capture 46 [100%] [30.00dB] [on]
Simple mixer control 'Dock Mic',0
Capabilities: cvolume penum
Capture channels: Front Left - Front Right
Limits: Capture 0 - 3
Front Left: Capture 0 [0%] [0.00dB]
Front Right: Capture 0 [0%] [0.00dB]
Simple mixer control 'Internal Mic',0
Capabilities: cvolume penum
Capture channels: Front Left - Front Right
Limits: Capture 0 - 3
Front Left: Capture 0 [0%] [0.00dB]
Front Right: Capture 0 [0%] [0.00dB]
!!-------Mixer controls for card 1 [NVidia]
Card hw:1 'NVidia'/'HDA NVidia at 0xe5080000 irq 17'
Mixer name : 'Nvidia GPU 1c HDMI/DP'
Components : 'HDA:10de001c,10281494,00100100'
Controls : 18
Simple ctrls : 3
Simple mixer control 'IEC958',0
Capabilities: pswitch pswitch-joined penum
Playback channels: Mono
Mono: Playback [on]
Simple mixer control 'IEC958',1
Capabilities: pswitch pswitch-joined penum
Playback channels: Mono
Mono: Playback [off]
Simple mixer control 'IEC958',2
Capabilities: pswitch pswitch-joined penum
Playback channels: Mono
Mono: Playback [off]
!!Alsactl output
!!-------------
--startcollapse--
state.PCH {
control.1 {
iface MIXER
name 'Front Playback Volume'
value.0 64
value.1 64
comment {
access 'read write'
type INTEGER
count 2
range '0 - 64'
dbmin -4800
dbmax 0
dbvalue.0 0
dbvalue.1 0
}
}
...
Programming ALSA
There are several tutorials, including A Tutorial on Using the ALSA Audio API by Paul Davis (who is the lead on Jack).
An overview of the API is at PCM (digital audio) interface . The ALSA API is large and complex. It is not clear to me how it all hangs together or what part to use where. Jeff Tranter Introduction to Sound Programming with ALSA states
The ALSA API can be broken down into the major interfaces it supports:
- Control interface: a general-purpose facility for managing registers of sound cards and querying the available devices.
- PCM interface: the interface for managing digital audio capture and playback. [...] it is the one most commonly used for digital audio applications.
- Raw MIDI interface: supports MIDI (Musical Instrument Digital Interface), a standard for electronic musical instruments. This API provides access to a MIDI bus on a sound card. The raw interface works directly with the MIDI events, and the programmer is responsible for managing the protocol and timing.
- Timer interface: provides access to timing hardware on sound cards used for synchronizing sound events.
- Sequencer interface: a higher-level interface for MIDI programming and sound synthesis than the raw MIDI interface. It handles much of the MIDI protocol and timing.
- Mixer interface: controls the devices on sound cards that route signals and control volume levels. It is built on top of the control interface.
Hardware device information
Finding information about hardware cards and devices is a multi-step operation. The hardware cards first have to be identified. This is done using the Control interface functions. The ones used are
snd_card_next
snd_ctl_open
snd_ctl_pcm_next_device
snd_ctl_card_info_get_id
snd_ctl_card_info_get_name
Cards are identified by an integer from zero upwards. The next card number is found using snd_card_next
, and the first card is found using a seed value of -1. The card is then opened using its ALSA name such as hw:0, hw:1, etc by snd_ctl_open
which fills in a handle
value. In turn, this handle is used to fill in card information using snd_ctl_card_info
and fields are extracted from that using functions such as snd_ctl_card_info_get_name
. In the program that follows, this gives information such as
card 0: PCH [HDA Intel PCH]
For further information you need to switch to the PCM functions for the card. The function linking the control and PCM interfaces is snd_ctl_pcm_info
which fills in a structure of type snd_pcm_info_t
with PCM-related information. Unfortunately, this function is documented neither in the Control Interface nor the PCM interface sections of the ALSA documentation but is instead in the Files section under control.c The structure snd_pcm_info_t
is barely documented in the PCM Interface section, and only has a few fields of interest. (see here for the structure). These fields are accessed using the PCM functions snd_pcm_info_get_id
and snd_pcm_info_get_name
.
The main value of the snd_pcm_info_t
structure is that it is the principal parameter into the functions of the PCM Stream . In particular this allows you to get devices and subdevices and information about them.