1. ALSA音频子系统概述

ALSA(Advanced Linux Sound Architecture)是 Linux 内核中用于替代旧式 OSS(Open Sound System)的音频子系统。它提供了从底层硬件驱动到上层用户空间 API 的完整音频处理栈,是嵌入式 Linux 音频开发的核心基础设施。

1.1 ALSA 整体架构

ALSA 采用分层设计,从上到下依次为:用户空间应用程序、ALSA 库(libasound)、ALSA 内核核心层、硬件驱动层。每一层都封装了特定的职责,并通过标准接口进行交互。

架构要点: ALSA 的分层设计使得应用程序无需关心底层硬件细节,驱动开发者只需实现内核层的 ops 回调,即可完成音频设备适配。
ALSA 音频子系统分层架构 ALSA 音频子系统分层架构 用户空间 (User Space) 应用程序 (aplay / arecord / 多媒体框架) ALSA 用户空间库 (libasound) PCM 接口 / 混音 / 设备枚举 / 插件系统 内核空间 (Kernel Space) ALSA 核心框架 (snd / pcm / control / timer) 硬件驱动层 (Hardware Driver) DMA 引擎 / I2S 控制器 / Codec 驱动 / 中断处理

1.2 用户空间与内核空间接口

ALSA 的用户空间与内核空间通过 字符设备文件 和 ioctl 系统调用 进行通信。设备文件通常位于 /dev/snd/ 目录下,包括 pcmC0D0p(播放)、pcmC0D0c(录音)等。

接口类型 设备文件示例 说明
PCM 播放 /dev/snd/pcmC0D0p Card 0, Device 0, Playback
PCM 录音 /dev/snd/pcmC0D0c Card 0, Device 0, Capture
Control 接口 /dev/snd/controlC0 音量控制、混音器、路由
Timer 接口 /dev/snd/timer 音频定时器
MIDI 接口 /dev/snd/midiC0D0 MIDI 输入/输出

用户空间通过 open() 打开设备文件,然后使用 ioctl() 传递 SNDRV_PCM_IOCTL_* 命令字来配置采样率、声道数、数据格式、缓冲区大小等参数。内核中的 ALSA 核心层解析这些命令,并调用底层驱动的回调函数。

性能提示: 在嵌入式系统中,频繁的 ioctl 调用会增加上下文切换开销。建议在初始化阶段一次性配置好 PCM 参数,运行时尽量减少控制命令的发送频率。

1.3 PCM 设备模型

PCM(Pulse Code Modulation)是 ALSA 中最核心的音频数据流模型。一个 PCM 设备代表一个数字音频输入或输出通道,它管理着音频数据的缓冲区、DMA 传输、中断触发和指针更新。

1.3.1 PCM 设备的核心组件

  • snd_pcm 结构体: 内核中表示 PCM 设备的核心对象,包含硬件参数、运行时状态、ops 回调函数指针。
  • snd_pcm_substream: 每个 PCM 设备可以包含多个 substream,用于支持多路并发播放/录音。
  • snd_pcm_hardware: 描述硬件能力,如支持的采样率范围、缓冲区大小限制、DMA 对齐要求。
  • snd_pcm_ops: 驱动开发者需要实现的回调函数集合,包括 open、close、hw_params、prepare、trigger、pointer 等。
  • DMA 缓冲区: 用于在内存和音频硬件之间传输音频数据的环形缓冲区。
PCM 设备模型内部结构 PCM 设备模型内部结构 snd_pcm (PCM 设备) card / device / streams snd_pcm_substream number / stream (playback/capture) snd_pcm_runtime hw/sw params / status snd_pcm_ops open / trigger / pointer DMA 环形缓冲区 (Ring Buffer) dma_area / dma_bytes / period_size / buffer_size 音频硬件 (I2S / DMA / Codec) FIFO / 中断 / 时钟

1.3.2 PCM 操作流程

  1. open: 创建 substream 实例,分配运行时数据结构。
  2. hw_params: 设置硬件参数(采样率、格式、声道数、缓冲区大小)。
  3. sw_params: 设置软件参数(中断触发阈值、起始阈值、静音阈值)。
  4. prepare: 重置 DMA 指针,清空缓冲区,准备硬件传输。
  5. trigger (START): 启动 DMA 传输,音频数据开始流动。
  6. 中断处理: 每次 period 完成时触发中断,更新 appl_ptr,唤醒等待队列。
  7. trigger (STOP): 停止 DMA 传输。
  8. close: 释放资源,关闭设备。
常见陷阱: 在嵌入式平台上,hw_params 阶段分配的 DMA 缓冲区必须满足硬件对齐要求(如 32 字节对齐)。如果缓冲区地址或大小不对齐,可能导致 DMA 传输失败或数据错位。

1.3.3 关键数据结构关系

数据结构 所属层次 主要字段 作用
snd_card 核心层 number, driver, devices 声卡实例,管理所有设备
snd_pcm 核心层 card, streams, ops PCM 设备,包含 playback/capture 流
snd_pcm_substream 核心层 runtime, number, stream 单个音频流实例
snd_pcm_runtime 核心层 hw/sw_params, status, dma_area 运行时状态和缓冲区管理
snd_dma_buffer 驱动层 area, addr, bytes, type DMA 缓冲区描述

1.4 本章小结