Linux ALSA 音频编程
在 Linux 系统中,如果你想开发一个可以录音或播放声音的应用程序,ALSA(Advanced Linux Sound Architecture) 是最常用的音频接口之一。它是 Linux 内核中提供音频支持的主要架构,功能强大,支持低延迟、混音、多通道音频等高级特性。
本文将带你初步了解 ALSA 音频编程的基本概念,包括如何打开音频设备、设置参数、读取与写入音频数据等。我们以 C 语言为主,帮助你快速上手音频采集与播放开发。
什么是 ALSA?
ALSA 是 Linux 下的高级音频系统,取代了早期的 OSS(Open Sound System)。ALSA 提供了:
- 低延迟音频传输能力
- 多通道支持(比如立体声、5.1 声道)
- 多个音频设备同时工作的能力
- Mixer、MIDI、PCM、硬件抽象层等功能
你可以通过使用 libasound(ALSA 的用户空间开发库)进行编程,控制音频播放、录音、音量调节等。
音频重要概念
- PCM:PCM 是最常见的原始音频格式,它描述了音频的采样方式(如 16 位、单声道/立体声、采样率)。
- 通道:通道数决定了你是单声道(1)还是立体声(2)等。
- 采样率:每秒采集多少次声 音样本,常见为 44100Hz(CD 质量)。
- 位宽:每个样本使用多少位,通常为 16 位或 24 位。
ALSA 编程流程概览
使用 ALSA 进行音频编程通常包括以下步骤:
- 打开音频设备
- 配置硬件参数(采样率、通道数、格式等)
- 读取(录音)或写入(播放)音频数据
- 关闭设备,释放资源
ALSA 函数简析:
snd_pcm_open():打开音频设备snd_pcm_hw_params_*:配置硬件参数snd_pcm_writei()/snd_pcm_readi():播放 / 录音snd_pcm_close():关闭设备
示例:播放音频数据(写入 PCM)
你可以使用 snd_pcm_writei() 将音频数据写入 PCM(Pulse Code Modulation)设备,实现播放功能。
示例代码:
alsa_play.c
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
int main() {
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
int rc;
unsigned int sample_rate = 44100;
int dir;
snd_pcm_uframes_t frames = 32;
char *buffer;
int size;
// 打开默认 PCM 播放设备
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr, "无法打开音频设备: %s\n", snd_strerror(rc));
exit(1);
}
// 分配硬件参数对象
snd_pcm_hw_params_malloc(¶ms);
snd_pcm_hw_params_any(handle, params);
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(handle, params, 2); // 立体声
snd_pcm_hw_params_set_rate_near(handle, params, &sample_rate, &dir);
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
// 应用硬件参数
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "无法设置参数: %s\n", snd_strerror(rc));
exit(1);
}
// 计算 buffer 大小
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 2 * 2; // 2字节/样本,2通道
buffer = (char *) malloc(size);
FILE *fp = fopen("audio.raw", "rb"); // 读取 PCM 文件
if (!fp) {
perror("fopen");
exit(1);
}
while (fread(buffer, 1, size, fp) > 0) {
rc = snd_pcm_writei(handle, buffer, frames);
if (rc == -EPIPE) {
fprintf(stderr, "播放 underrun\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr, "写入错误: %s\n", snd_strerror(rc));
}
}
fclose(fp);
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
编译方式:
gcc alsa_play.c -o alsa_play -lasound
你需要准备一个 16bit 立体声、采样率 44100Hz 的 PCM 音频文件,命名为 audio.raw。