从零写OS内核 | 音频子系统——ALSA 是怎么播放声音的
你有没有想过这个过程:播放一首歌,CPU 怎么把数字信号变成扬声器里的振动? 从 WAV/MP3 文件到耳机里的音乐,中间隔着采样率、位深、alsa-lib、ALSA 驱动、HDA 控制器——这条链路比大多数人想象的深。
本文从 PCM 原理出发,讲解 ALSA 架构、HDA Intel 控制器,给你一张完整的”音频从文件到耳机”地图。
一、声音的数字化:采样率和位深
声音是连续的模拟信号,数字化需要两步:采样(Sampling) 和 量化(Quantization)。
模拟信号(连续)
╭──────────────────────────────╮
│ ╱╲ ╱╲ │
│ ╱╲╱╲ ╱╲ │ ╱╲ │
──╱──────────────────────────╱────→ 时间
│
↓ 采样
╭──────────────────────────────╮
│ ■ ■ ■ ■ ■ ■ ■ │ ← 采样点
────────────────────────────────→ 时间
│ ← 每隔 T 秒采一个幅度值关键参数:
- 采样率(Sample Rate):每秒钟采样点数,单位 Hz。CD 标准是 44100Hz(44.1kHz),足够还原 22kHz 的声音(乃奎斯特定理:采样率 ≥ 2×最高频率)
- 位深(Bit Depth):每个采样点用多少 bit 表示。CD 是 16bit,Hi-Res 是 24bit。位深越大,动态范围越大(SNR = 6.02×bit + 1.76 dB)
- 声道数(Channels):单声道=1,立体声=2,环绕声=6(5.1)
PCM 帧结构:
立体声 44.1kHz 16bit,每帧:
┌──────────┬──────────┐
│ L (16bit)│ R (16bit)│
└──────────┴──────────┘
时域:────────────────────────────────→ 时间
帧N: [L0][R0] [L1][R1] [L2][R2] ...二、ALSA 架构:从 libasound 到 DMA
ALSA(Advanced Linux Sound Architecture)是 Linux 的音频框架,分用户空间和内核空间两层:
应用程序(aplay / Firefox / Spotify)
│
▼
┌──────────────────────────────────┐
│ alsa-lib (libasound.so) │ ← 用户空间
│ PCM API: snd_pcm_open/write │
│ 混音器 API: snd_mixer_ │
└──────────────┬───────────────────┘
│ 写入 PCM ring buffer
┌─────────────┴──────────────────────┐
│ ALSA Core (snd-pcm.ko) │ ← 内核空间
│ 音频流管理、硬件参数协商 │
└──────────────┬───────────────────┘
│ DMA 描述符
┌─────────────┴──────────────────────┐
│ HDA Intel 驱动 (snd-hda-intel) │ ← 硬件驱动
│ Intel HD Audio Codec │
└──────────────┬───────────────────┘
│ I2S / HDA link
┌─────────────┴──────────────────────┐
│ CODEC(Realtek ALC / Cirrus) │ ← 数模转换
│ DAC → 功放 → 扬声器/耳机 │
└────────────────────────────────────┘HDA(High Definition Audio)Link:
HDA 是 Intel 2004 年推出的板载音频标准,通过 HDA link 连接主板南桥和音频 CODEC,支持多声道、192kHz/24bit、jack detection。
三、实战:Linux 音频调试命令
# 1. 查看声卡列表
$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC1220 Analog [ALC1220 Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
# 2. 查看声卡支持的参数
$ aplay -D hw:0,0 --dump-phrase /dev/urandom
Access: RW_INTERLEAVED
Format: S16_LE / S32_LE / S24_LE
Subformat: STD
Channels: 2
Rate: 44100 / 48000 / 88200 / 96000 / 176400 / 192000
Period size: 512 - 8192
Buffer size: 4096 - 32768
# 3. 查看alsa插件配置
$ cat /etc/asound.conf
# 或 ~/.asoundrc
# 4. 录制一段音频
$ arecord -D hw:0,0 -f cd -r 44100 -c 2 /tmp/test.wav
Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
^C # Ctrl+C 停止
# 5. 用 alsamixer 调整音量
$ alsamixer
# 界面显示各声道的音量和静音状态
# 6. 查看 /proc/asound/
$ cat /proc/asound/cards
0 [PCH ]: HDA-Intel - HDA Intel PCH
Intel Corporation Device 9a13
1 [NVidia ]: HDA-Intel - HDA NVidia
NVIDIA Corporation Device 50
$ ls /proc/asound/card0/
codec#0 id pcm0c/ pcm0p/ # pcm0c=录制,pcm0p=播放四、DMA 和环形缓冲区:声音为什么能连续播放
CPU 不能精确控制每个样本的发送时间——它把一批 PCM 数据一次性写入 环形缓冲区(Ring Buffer),然后由 DMA 控制器自动按固定间隔从缓冲区取数据送到 CODEC:
Ring Buffer(2048 样本,8KB @ 44.1kHz ≈ 46ms):
┌────────────────────────────────────────────────┐
│ [样本0] [样本1] [样本2] ... [样本2047] │
└────────────────────────────────────────────────┘
↑
DMA 自动从这里取样
(每帧2个样本×2声道×2字节=4字节)
┌────────────────────────────────────────────────┐
│ DMA 控制器 │
│ • 周期性发送 DMA 请求(以 Sample Rate 为周期) │
│ • 从 RAM 读样本,送往 HDA Codec │
│ • 触发周期性中断,通知 ALSA driver "buffer 消费" │
└────────────────────────────────────────────────┘ALSA 的 period/buffer 概念:
- buffer size:总缓冲区大小(影响延迟)
- period size:每次 DMA 中断传输的数据量(影响 CPU 频率)
buffer_size = period_size × periods
buffer = 8192 × 4 = 32KB
period = 2048 × 4 = 8KB
periods = 4(缓冲 4 次,实际 ~184ms @ 44.1kHz)五、wandos 的音频子系统
wandos 目前没有完整的音频子系统。wandos 的输出以串口/VGA 文本为主。
如果要在 wandos 上实现音频,需要:
- 实现 HDA 控制器驱动(在
arch/x86/core/audio.cpp) - 实现 AC97/I2S 接口
- 实现 DMA 环形缓冲区管理
- 实现基本的 PCM 播放(可参考
demos/audio/)
wandos 的 audio roadmap:
- 阶段 1:串口 beep(PC Speaker)
- 阶段 2:AC97 驱动
- 阶段 3:ALSA 兼容层
公众号 footer
相关阅读:
- 《从零写OS内核 | 总线与地址空间——CPU 是怎么找到每个设备的》(343)
- 《从零写OS内核 | DMA——内存和设备之间的直连高速公路》
动手环节:
运行 aplay -l 看你电脑有几张声卡,然后用 aplay -D hw:0,0 test.wav 播放一个 WAV 文件(如果没有可以先 arecord 录一个)。
仓库地址:
github.com/golang12306/os-kernel-from-scratch
关注公众号「AI不着急」,回复”资料”获取内核学习路线图。
评论