织梦CMS - 轻松建站从此开始!

罗索

Introduction to Sound Programming with ALSA

jackyhwei 发布于 2010-10-16 22:31 点击:次 
Make maximum use of all the functionality in the new 2.6 kernel sound architecture using a simple API.
TAG:

原文:http://www.linuxjournal.com/node/6735/print

本文相关的完整源码下载地址:http://bbs.rosoo.net/forum.php?mod=viewthread&tid=1058

本文相关的软件(ALSA,SDL等):http://bbs.rosoo.net/forum.php?mod=viewthread&tid=1059

 

ALSA stands for the Advanced Linux Sound Architecture. It consists of a set of kernel drivers, an application programming interface (API) library and utility programs for supporting sound under Linux. In this article, I present a brief overview of the ALSA Project and its software components. The focus is on programming the PCM interfaces of ALSA, including programming examples with which you can experiment.

You may want to explore ALSA simply because it is new, but it is not the only sound API available. ALSA is a good choice if you are performing low-level audio functions for maximum control and performance or want to make use of special features not supported by other sound APIs. If you already have written an audio application, you may want to add native support for the ALSA sound drivers. If your primary interest isn't audio and you simply want to play sound files, using one of the higher-level sound toolkits, such as SDL, OpenAL or those provided in desktop environments, may be a better choice. By using ALSA you are restricted to using systems running a Linux kernel with ALSA support.

History of ALSA

The ALSA Project was started because the sound drivers in the Linux kernel (OSS/Free drivers) were not being maintained actively and were lagging behind the capabilities of new sound technology. Jaroslav Kysela, who previously had written a sound card driver, started the project. Over time, more developers joined, support for many sound cards was added and the structure of the API was refined.

During development of the 2.5 series of Linux kernel, ALSA was merged into the official kernel source. With the release of the 2.6 kernel, ALSA will be part of the stable Linux kernel and should be in wide use.

Digital Audio Basics

Sound, consisting of waves of varying air pressure, is converted to its electrical form by a transducer, such as a microphone. An analog-to-digital converter (ADC) converts the analog voltages into discrete values, called samples, at regular intervals in time, known as the sampling rate. By sending the samples to a digital-to-analog converter and an output transducer, such as a loudspeaker, the original sound can be reproduced.

The size of the samples, expressed in bits, is one factor that determines how accurately the sound is represented in digital form. The other major factor affecting sound quality is the sampling rate. The Nyquist Theorem states that the highest frequency that can be represented accurately is at most one-half the sampling rate.

ALSA Basics

ALSA consists of a series of kernel device drivers for many different sound cards, and it also provides an API library, libasound. Application developers are encouraged to program using the library API and not the kernel interface. The library provides a higher-level and more developer-friendly programming interface along with a logical naming of devices so that developers do not need to be aware of low-level details such as device files.

In contrast, OSS/Free drivers are programmed at the kernel system call level and require the developer to specify device filenames and perform many functions using ioctl calls. For backward compatibility, ALSA provides kernel modules that emulate the OSS/Free sound drivers, so most existing sound applications continue to run unchanged. An emulation wrapper library, libaoss, is available to emulate the OSS/Free API without kernel modules.

ALSA has a capability called plugins that allows extension to new devices, including virtual devices implemented entirely in software. ALSA provides a number of command-line utilities, including a mixer, sound file player and tools for controlling special features of specific sound cards.

ALSA Architecture

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. The rest of this article focuses on this interface, as 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.

Device Naming

The library API works with logical device names rather than device files. The device names can be real hardware devices or plugins. Hardware devices use the format hw:i,j, where i is the card number and j is the device on that card. The first sound device is hw:0,0. The alias default refers to the first sound device and is used in all of the examples in this article. Plugins use other unique names; plughw:, for example, is a plugin that provides access to the hardware device but provides features, such as sampling rate conversion, in software for hardware that does not directly support it. The dmix and dshare plugins allow you to downmix several streams and split a single stream dynamically among different applications.

Sound Buffers and Data Transfer

A sound card has a hardware buffer that stores recorded samples. When the buffer is sufficiently full, it generates an interrupt. The kernel sound driver then uses direct memory access (DMA) to transfer samples to an application buffer in memory. Similarly, for playback, another application buffer is transferred from memory to the sound card's hardware buffer using DMA.

These hardware buffers are ring buffers, meaning the data wraps back to the start when the end of the buffer is reached. A pointer is maintained to keep track of the current positions in both the hardware buffer and the application buffer. Outside of the kernel, only the application buffer is of interest, so from here on we discuss only the application buffer.

The size of the buffer can be programmed by ALSA library calls. The buffer can be quite large, and transferring it in one operation could result in unacceptable delays, called latency. To solve this, ALSA splits the buffer up into a series of periods (called fragments in OSS/Free) and transfers the data in units of a period.

A period stores frames, each of which contains the samples captured at one point in time. For a stereo device, the frame would contain samples for two channels. Figure 1 illustrates the breakdown of a buffer into periods, frames and samples with some hypothetical values. Here, left and right channel information is stored alternately within a frame; this is called interleaved mode. A non-interleaved mode, where all the sample data for one channel is stored followed by the data for the next channel, also is supported.

Figure 1. The Application Buffer

Over and Under Run

When a sound device is active, data is transferred continuously between the hardware and application buffers. In the case of data capture (recording), if the application does not read the data in the buffer rapidly enough, the circular buffer is overwritten with new data. The resulting data loss is known as overrun. During playback, if the application does not pass data into the buffer quickly enough, it becomes starved for data, resulting in an error called underrun. The ALSA documentation sometimes refers to both of these conditions using the term XRUN. Properly designed applications can minimize XRUN and recover if it occurs.

A Typical Sound Application

Programs that use the PCM interface generally follow this pseudo-code:

open interface for capture or playback
set hardware parameters
(access mode, data format, channels, rate, etc.)
while there is data to be processed:
   read PCM data (capture)
   or write PCM data (playback)
close interface

We look at some working code in the following sections. I recommend you compile and run these on your Linux system, look at the output and try some of the suggested modifications. The full listings for the example programs that accompany this article are available for download from ftp.linuxjournal.com/pub/lj/listings/issue126/6735.tgz.

Listing 1. Display Some PCM Types and Formats

Listing 1 displays some of the PCM data types and parameters used by ALSA. The first requirement is to include the header file that brings in the definitions for all of the ALSA library functions. One of the definitions is the version of ALSA, which is displayed.

The remainder of the program iterates through a number of PCM data types, starting with the stream types. ALSA provides symbolic names for the last enumerated value and a utility function that returns a descriptive string for a value. As you can see in the output, ALSA supports many different data formats, 38 for the version of ALSA on my system.

The program must be linked with the ALSA library, libasound, to run. Typically, you would add the option -lasound on the linker command line. Some ALSA library functions use the dlopen function and floating-point operations, so you also may need to add -ldl and -lm.

Listing 2 opens the default PCM device, sets some parameters and then displays the values of most of the hardware parameters. It does not perform any sound playback or recording. The call to snd_pcm_open opens the default PCM device and sets the access mode to PLAYBACK. This function returns a handle in the first function argument that is used in subsequent calls to manipulate the PCM stream. Like most ALSA library calls, the function returns an integer return status, a negative value indicating an error condition. In this case, we check the return code; if it indicates failure, we display the error message using the snd_strerror function and exit. In the interest of clarity, I have omitted most of the error checking from the example programs. In a production application, one should check the return code of every API call and provide appropriate error handling.

In order to set the hardware parameters for the stream, we need to allocate a variable of type snd_pcm_hw_params_t. We do this with the macro snd_pcm_hw_params_alloca. Next, we initialize the variable using the function snd_pcm_hw_params_any, passing the previously opened PCM stream.

We now set the desired hardware parameters using API calls that take the PCM stream handle, the hardware parameters structure and the parameter value. We set the stream to interleaved mode, 16-bit sample size, 2 channels and a 44,100 bps sampling rate. In the case of the sampling rate, sound hardware is not always able to support every sampling rate exactly. We use the function snd_pcm_hw_params_set_rate_near to request the nearest supported sampling rate to the requested value. The hardware parameters are not actually made active until we call the function snd_pcm_hw_params.

The rest of the program obtains and displays a number of the PCM stream parameters, including the period and buffer sizes. The results displayed vary somewhat depending on the sound hardware.

After running the program on your system, experiment and make some changes. Change the device name from default to hw:0,0 or plughw: and see whether the results change. Change the hardware parameter values and observe how the displayed results change. (Jeff Tranter )

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201010/10318.html]
本文出处:linuxjournal.com 作者:Jeff Tranter
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容