2011
1/21/2011
A Tutorial on Using the ALSA Audio API
A Tutorial on Using the ALSA Audio API/ALSA Audio API 使用指南
A Tutorial on Using the ALSA Audio API
ALSA Audio API 使用指南
Author: Paul Davis
Translate: kang_liang
Sort out: Zhao lijun
Added: Zhao lijun
HISTORY OF THE REVISIONS
Version
Date
Name
Comment:
V1.0
2011.01.20
Zhaolijun
Create this document for avocation
V1.1
2011.01.21
Zhaolijun
Add the Red part and the API part
A Tutorial on Using the ALSA Audio API/ALSA Audio API 使用指南
This document attempts to provide an introduction to the ALSA Audio API. It is
not a complete reference manual for the API, and it does not cover many specific
issues that more complex software will need to address. However, it does try to
provide enough background and information for a reasonably skilled programmer but
who is new to ALSA to write a simple program that uses the API.
All code in the document is licensed under the GNU Public License. If you plan
to write software using ALSA under some other license, then I suggest you find some
other documentation.
Contents
Understanding Audio Interface
What a Typical Audio Application Does
A Minimal Playback Program
A Minimal Capture Program
A Minimal interrupt-driven Program
A Minimal Duplex Program
How To Do It
o Opening The Device
o Setting The Parameters
o Receiving And Delivering Data
Why You Might Want To Forget About All Of This
A Tutorial on Using the ALSA Audio API/ALSA Audio API 使用指南
Understanding Audio Interfaces
Let us first review the basic design of an audio interface. As an application
developer, you don't need to worry about this level of operation - its all taken care of
by the device driver (which is one of the components that ALSA provides). But you
do need to understand what is going at a conceptual level if you want to write efficient
and flexible software.
An audio interface is a device that allows a computer to receive and to send
audio data from/to the outside world. Inside of the computer, audio data is represented
a stream of bits, just like any other kind of data. However, the audio interface may
send and receive audio as either an analog signal (a time-varying voltage) or as a
digital signal (some stream of bits). In either case, the set of bits that the computer
uses to represent a particular sound will need to be transformed before it is delivered
to the outside world, and likewise, the external signal received by the interface will
need to be transformed before it is useful to the computer. These two transformations
are the raison d'etre of the audio interface.
Within the audio interface is an area referred to as the "hardware buffer". As an
audio signal arrives from the outside world, the interface converts it into a stream of
bits usable by the computer and stores it in the part hardware buffer used to send data
to the computer. When it has collected enough data in the hardware buffer, the
interface interrupts the computer to tell it that it has data ready for it. A similar
process happens in reverse for data being sent from the computer to the outside world.
The interface interrupts the computer to tell it that there is space in the hardware
buffer, and the computer proceeds to store data there. The interface later converts
these bits into whatever form is needed to deliver it to the outside world, and delivers
it. It is very important to understand that the interface uses this buffer as a "circular
buffer". When it gets to the end of the buffer, it continues by wrapping around to the
start.
For this process to work correctly, there are a number of variables that need to be
configured. They include:
what format should the interface use when converting between the bitstream
used by the computer and the signal used in the outside world?
at what rate should samples be moved between the interface and the
computer?
how much data (and/or space) should there be before the device interrupts the
computer?
how big should the hardware buffer be?
The first two questions are fundamental in governing the quality of the audio data.
The second two questions affect the "latency" of the audio signal. This term refers to
the delay between
1. data arriving at the audio interface from the outside world, and it being
available to the computer ("input latency")
2. data being delivered by the computer, and it being delivered to the outside
world ("output latency")
Both of these are very important for many kinds of audio software, though some
programs do not need be concerned with such matters.
What a typical audio application does
A typical audio application has this rough structure:
A Tutorial on Using the ALSA Audio API/ALSA Audio API 使用指南
open_the_device();
set_the_parameters_of_the_device();
while (!done) {
/* one or both of these */
receive_audio_data_from_the_device();
deliver_audio_data_to_the_device();
}
close the device
A Minimal Playback Program
This program opens an audio interface for playback, configures it for stereo, 16
bit, 44.1kHz, interleaved conventional read/write access. Then its delivers a chunk of
random data to it, and exits. It represents about the simplest possible use of the ALSA
Audio API, and isn't meant to be a real program.
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
main (int argc, char *argv[])
{
int i;
int err;
short buf[128];
snd_pcm_t *playback_handle;
snd_pcm_hw_params_t *hw_params;
if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
fprintf (stderr, "cannot open audio device %s (%s)\n", argv[1],snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
{
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0)
{
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
fprintf (stderr, "cannot set access type (%s)\n",snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params,
SND_PCM_FORMAT_S16_LE)) < 0)
{
fprintf (stderr, "cannot set sample format (%s)\n",snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, 44100, 0)) < 0)
{
fprintf (stderr, "cannot set sample rate (%s)\n",snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0)
{
fprintf (stderr, "cannot set channel count (%s)\n",snd_strerror (err));
exit (1);
}