当前位置:首页>Linux>Linux多媒体进阶之旅(十一):module-alsa-source如何从ALSA设备采集音频?

Linux多媒体进阶之旅(十一):module-alsa-source如何从ALSA设备采集音频?

  • 2026-08-28 06:09:49
Linux多媒体进阶之旅(十一):module-alsa-source如何从ALSA设备采集音频?

点击下方👇关注 Android系统攻城狮

第204篇原创文章

持续迭代 | Android+Linux多媒体进阶体系

专栏·课程 知识体系持续更新


学习理念:一次理解一个知识点
所属系列:Linux多媒体进阶实战(第11篇)
框架分类:PulseAudio篇
源码环境:PulseAudio17
硬件平台:RK3588
主题内容:module-alsa-source模块
难度等级:★★★★☆
阅读时间:3.8分钟

1

前言

上一篇我们梳理了module-alsa-sink如何把播放数据写入ALSA播放设备,本篇我们继续分析录音链路,录音链路的数据方向相反,声音先由ALSA采集,再送进PulseAudio,最后交给录音应用。

录音无声时,使用命令pactl list sources可以看到麦克风对应的Source,录出来的录音文件,却没有声音。Source出现在列表里,说明PulseAudio已经创建了录音设备对象,还需要检查ALSA capture PCM是否启动、IO线程是否读到数据、Source Output是否收到音频。

本篇继续探索如何采集ALSA录音设备,先分析module-alsa-source从哪里获取设备信息,再分析IO线程如何读取音频,以及采集数据如何进入录音应用。

2

录音链路从哪开始?

第九篇分析了的Card路径进入时,module-alsa-card已经选中了当前Profile。Profile中存在input mapping,初始加载会在init_profile()里调用pa_alsa_source_new(),运行时切换Profile则由card_set_profile()创建新Source,或者释放旧Profile不再使用的Source。

input mapping记录当前Profile使用的ALSA录音设备、采样格式、声道布局和Port信息。pa_alsa_source_new()读取这些配置后开始建立录音数据通道。

module-alsa-source也支持单独加载,入口函数是pa__init()。模块参数解析完成后直接调用pa_alsa_source_new(),后面的ALSA设备打开、Source创建和数据采集使用同一套实现。

录音链路从加载Profile配置开始:

Card路径先检查当前Profile有没有input mapping,单独加载路径检查模块参数中的device_id或device是否指向正确设备。

3

ALSA设备和Source创建顺序?

创建顺序是先打开ALSA录音设备,再创建PulseAudio Source。

pa_alsa_source_new()先整理采样格式、采样率、声道数、fragment、buffer、mmap和tsched参数。带有mapping时调用pa_alsa_open_by_device_id_mapping(),只有device_id时调用pa_alsa_open_by_device_id_auto(),直接传入device字符串时调用pa_alsa_open_by_device_string()。三条路径打开的都是录音方向PCM:SND_PCM_STREAM_CAPTURE

PCM打开成功后,PulseAudio得到pcm_handle以及ALSA最终接受的采样参数。pa_alsa_source_new()接着初始化pa_source_new_data结构,写入Source名称、Profile、Port、采样参数和设备属性,再调用pa_source_new()创建Source。

Source创建完成后,pa_alsa_source_new()设置状态和端口回调,创建入口为thread_func()的IO线程,最后调用pa_source_put()发布Source。

pactl list sources能够看到Source,说明初始化阶段已经打开ALSA PCM并完成Source发布,IO线程决定录音过程中是否持续读到数据。

4

IO线程如何读录音数据?

IO线程先检查Source是否处于打开状态。第一次进入采集路径时,ALSA Source私有运行数据中的first标志为真,线程调用snd_pcm_start()启动capture PCM。声卡开始向ALSA buffer写入录音数据后,IO线程进入读取过程。

读取方式由同一份运行数据中的use_mmap标志决定。

普通模式进入unix_read()。函数查询ALSA当前可读取的frame数量,申请PulseAudio memblock,再调用snd_pcm_readi()把数据从capture PCM复制到memblock中,最后组成memchunk,看下流程图所示。

mmap模式进入mmap_read()。函数通过snd_pcm_mmap_begin()获取ALSA已经采集的内存区域,把这段区域包装成memchunk,交给pa_source_post()处理,最后调用snd_pcm_mmap_commit()提交已经消费的frame,流程图如下。

播放方向先由PulseAudio准备数据,再写入ALSA,录音方向先启动ALSA capture PCM,再由PulseAudio服务读取录音数据。

5

数据怎样交给录音应用?

snd_pcm_readi()和mmap接口负责从ALSA buffer读取数据,IO线程得到memchunk后,调用pa_source_post()把数据交给Source。

pa_source_post()遍历连接在当前Source上的普通Source Output。录音应用在PulseAudio里对应一个Source Output,Source采集到的数据通过这个对象发送给录音应用。Source设置了软件静音或软件音量时,pa_source_post()先处理memchunk,再把结果推给Source Output。

Source表示录音设备,Source Output表示正在使用这台设备的录音流。Source存在,说明设备通道已经建立。Source Output存在并连接到目标Source,说明录音应用已经接入采集链路,链路如下:

module-alsa-source负责启动ALSA采集并读取数据,Source负责把数据分发给录音流。

6

故障定位部分

录音无声时,按以下顺序定位:

1.确认当前Profile是否提供录音通道

pactl list cards

关键字段:Active Profile,当前Profile需要包含输入能力,module-alsa-card才会根据input mapping创建硬件Source。

2.确认Source是否已经创建

pactl list sources

关键字段:Source名称、State、Sample Specification、Active Port和Properties

1.device.string对应ALSA设备2.device.profile.name对应来源Profile3.device.access_mode表示普通读取或mmap读取

3.确认录音应用是否接入目标Source

保持录音应用正在采集,再执行:

pactl list source-outputs

关键字段:Source Output编号和Source。

1.Source字段需要指向目标Source。2.没有Source Output,说明应用还没有创建PulseAudio录音流。

4.确认ALSA是否提供capture PCM

arecord -lcat /proc/asound/pcm

关键字段:目标声卡、PCM设备号和capture标记。

5.确认录音设备的占用和权限

fuser -v /dev/snd/pcmC*D*cls -l /dev/snd/pcmC*D*c

capture PCM被其他进程占用,或者PulseAudio运行用户没有访问权限时,pa_alsa_source_new()无法正常打开设备,后续Source创建和数据采集也不会执行。

7

总结

1.播放时

module-alsa-sink从Sink Input获取音频,再写入ALSA playback 。

2.录音时

module-alsa-source先启动ALSA capture PCM,通过普通读取或mmap获取数据,再调用pa_source_post()把音频发送给Source Output。

3.PulseAudio录音无声时

1.先确认Profile有没有input mapping2.再检查Source和Source Output3.最后确认ALSA capture PCM是否存在、设备能否打开。4.检查结果可以把问题定位到对象创建、录音应用接入或ALSA采集。

若读者朋友发现有错误、疑问的地方,或者好的建议,欢迎拍砖!!!

★★★★★★★★★< END >★★★★★★★★★

欢迎加入知识星球:Android+Linux多媒体进阶体系2.0
专栏推荐
☞ 【专栏一】 基础原理系列
☞ 【专栏二】 Android车载音频系列
☞ 【专栏三】 Android编解码系列
☞ 【专栏四】 Android相机系列
☞ 【专栏五】 Android图形系列
☞ 【专栏六】 Android系统系列
☞ 【专栏七】 Linux车载多媒体系列
原创不易,谢谢支持~~

最新文章

随机文章