学历代表过去、能力代表现在、学习力代表将来。 一个良好的学习方法是通过输出来倒逼自己输入。写博客既是对过去零散知识点的总结和复盘,也是参加了 零声教育 写博客活动。
零声教育体验课:https://xxetb.xetslk.com/s/3fbO81
本文是开发过程中的知识点总结,供大家学习交流使用,如有任何错误或不足之处,请在评论区指出。
Linux 音频架构OSS (Open Sound System):是 Linux 系统上最早的音频接口系统之一。它提供了一个统一的接口来管理音频设备和音频数据的输入输出。但在发展过程中逐渐被 ALSA 替代。
ALSA (Advanced Linux Sound Architecture):
Linux 内核中的音频驱动架构,提供了对各种音频设备的支持,包括声卡、数字音频接口等。ALSA 提供了一组 API 和工具,用于在 Linux 上进行音频编程和音频流处理。2002 年它被引进入Linux内核的开发版本(2.5.4-2.5.5)。2.6 版本开始 ALSA 成为 Linux 内核中默认的标准音频驱动程序集,OSS 则被标记为废弃。ALSA 提供内核模块来模拟 OSS,这样之前的许多在 OSS 基础上开发的应用程序不需要任何改动就可以在 ALSA 上运行。libaoss 库也可以模拟 OSS,而它不需要内核模块。ASoC (ALSA System on Chip):
ALSA 的一个子系统,专门用于在嵌入式系统中管理和配置与硬件集成的音频设备。ASoC 提供了一种灵活的框架,使得开发者能够轻松地将 ALSA 应用于各种嵌入式系统中的音频硬件。ASoC 是 ALSA 在 SoC 方面的发展和演变,它在本质上仍然属于 ALSA,但是在 ALSA 架构的基础上对 CPU 相关的代码和 CODEC 相关的代码进行了分离。其原因是,采用传统 ALSA 架构的情况下,同一型号的 CODEC 工作于不同的 CPU 时,需要不同的驱动,这不符合代码重用的要求。ALSA 简介目前 linux 的主流音频体系架构,官网:http://www.alsa-project.org/
| 软件包名称 | 描述 |
|---|---|
alsa-driver | 内核驱动程序,包括硬件相关的和一些公共代码。 |
alsa-lib | ALSA 核心库,提供 ALSA API 的实现和访问接口。需要包含头文件 asoundlib.h,链接共享库 libasound.so |
alsa-utils | 包含 ALSA 工具,用于配置和管理 ALSA 音频设备。 |
alsa-tools | 包含用于测试和调试 ALSA 音频设备的工具。 |
alsa-plugins | 包含用于扩展 ALSA 功能的插件。用 jack 模拟 alsa 接口。用 oss 来模拟 alsa 接口。 |
alsa-firmware | 包含用于 ALSA 音频设备的固件文件。 |
alsa-ucm-conf | ALSA UCM (Use Case Manager) 配置文件,用于管理音频设备的用例。 |
alsa-topology-conf | ALSA 拓扑配置文件,用于配置音频设备的拓扑结构。 |
alsa-oss | ALSA OSS (Open Sound System) 兼容层,用于支持使用 OSS 接口的应用程序。 |
pyalsa | Python 绑定,用于在 Python 中访问 ALSA API。 |
tinycompress | ALSA 压缩库,用于与压缩音频硬件进行交互。 |

ASoC 驱动

MachineMachine上的硬件实现可能都不一样,CPU不一样,Codec不一样,音频的输入、输出设备也不一样。Machine为CPU、Codec、输入输出设备提供了一个载体。Platform和Codec驱动是不能工作的,它必须由Machine驱动把它们结合在一起才能完成整个设备的音频处理工作。Rockchip_es8323就是一个Machine:
PlatformRK3229,S3c4430,MT6795等等。DMA、I2S、PCM等等。SoC,那么我们可以认为它会有一个对应的Platform,它只与SoC相关,与Machine无关,这样我们就可以把Platform抽象出来。SoC不用做任何的改动,就可以用在不同的Machine中。Platform认为是某个SoC更好理解。
CodecCodec里面包含了I2S接口、D/A、A/D、Mixer、PA(功放),通常包含多种输入(Mic、Line-in、I2S、PCM)和多个输出(耳机、喇叭、听筒,Line-out)。Codec和Platform一样,是可重用的部件,同一个Codec可以被不同的Machine使用。Codec通常通过I2C对内部的寄存器进行控制。Controls就是对Codec输入输出的寄存器进行操作。
ASoC 驱动 PCM
snd_card的时候进行创建,一个pcm实例由一个playback stream和一个capture stream组成,stream又分别有一个或多个substreams组成。pcm实例,pcm下面有一个playback stream和capture stream,playback和capture下面各自有一个substream。ALSA设备文件结构声卡初始化之后,会生成设备节点,以供上层调用,alsa驱动的设备文件结构,可以在/dev/snd下用ls查看,如下所示:
controlC0 --> 用于声卡的控制,例如通道选择,混音,麦克风的控制等
pcmC0D0c --> 用于录音的pcm设备
pcmC0D0p --> 用于播放的pcm设备
timer --> 定时器
alsa-driver中的命名规则:
C0代表的是声卡0,D0代表声卡中的设备0,pcmC0D0c最后一个c代表capture,pcmC0D0p最后一个p代表`playbackALSA 使用sample, format): 样本是记录音频数据最基本的单位,计算机对每个通道采样量化时数字比特位数,常见的有16、24和32位,也就是format。channel): 1表示单声道/Mono,2则是立体声/Stereo。frame): 构成一个完整的声音单元,Frame = Sample(format) * channel。rate): 又称 sample rate,采样率,即每秒的采样次数,针对帧而言;常用的采样率如8KHz的人声, 44.1KHz的mp3音乐, 96Khz的蓝光音频。period): 每次硬件中断处理音频数据的帧数,对于音频设备的数据读写,以此为单位。runtime 的 buffer size,而不是结构图 snd_pcm_hardware 中定义的 buffer_bytes_max;一般来说 buffer_size = period_size * period_count, period_count 相当于处理完一个 buffer 数据所需的硬件中断次数,一般就是DMA的中断。Bits Per Second): 比特率表示每秒的比特数,比特率=采样率×通道数×样本长度。interleaved): 是一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。不过多数情况下,我们只需要使用交错模式就可以了。
alsa-libasoundlib.h。并使用共享库libasound.solibasound而不是内核中的 ALSA接口。因为libasound提供最高级并且编程方便的编程接口。并且提供一个设备逻辑命名功能,这样开发者甚至不需要知道类似设备文件这样的低层接口。OSS/Free驱动是在内核系统调用级上编程,它要求开发者提供设备文件名并且利用ioctrl来实现相应的功能。ALSA包含插件功能,使用插件可以扩展新的声卡驱动,包括完全用软件实现的虚拟声卡。ALSA提供一系列基于命令行的工具集,比如:
mixer),aplay),AlSA本身也提供混音的plugin,dmix .ALSA Open 流程通过alsa lib的snd_pcm_open函数打开音频设备,这样间接会调用到驱动提供的接口:
open(fn, "/dev/snd/pcmC0D0p"):
PCM设备, 建立与驱动的联系。ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS):
format,channels,rate等。mmap(NULL, buffer_size):
ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE):
widget更新电源状态,包括设置codec,platform相关寄存器,准备好进行播放。ALSA Write 流程应用通过 alsa-lib 里面的 API 函数 snd_pcm_writei 写入数据。
copy_form_user 把应用的音频数据拷贝到 DMA 中,然后通过 DMA 把数据发送到 SoC 的 I2S 控制器的 FIFO,再到 codec,最后由喇叭或者手机播放。
mmap 建立内存映射,应用直接操作映射好的内存区域,相当于直接写到 DMA 中,然后通过 DMA 把数据发送到 SoC 的 I2S 控制器的FIFO,再到codec,最后由喇叭或者手机播放。
与写入一样有两种方法:
copy_to_user。mmap。
Ring Bufferdma buffer 中, 然后相应 platform 的 dma 操作则不停地从该 buffer 中取出数据,经 dai 送往 codec 中。codec 源源不断地把 A/D 转换好的音频数据经过 dai 送入 dma buffer 中,而应用程序则不断地从该 buffer 中读走音频数据。
Ring buffer 管理alsa driver 使用 Ring Buffer 对 dma buffer 进行管理:
Buffer size: 就是一个 HW buffer(虚拟),相当于应用的 period * count,实际的 Buffer 大小。snd_pcm_runtime.hw_ptr_base: 环形缓冲区每一圈的基地址,当读写指针越过一圈后,它按 buffer size 进行移动;snd_pcm_runtime.status->hw_ptr: 硬件逻辑位置,播放时相当于读指针,录音时相当于写指针;snd_pcm_runtime.control->appl_ptr: 应用逻辑位置,播放时相当于写指针,录音时相当于读指针;snd_pcm_runtime.boundary: 扩展后的逻辑缓冲区大小,通常是(2^n)*size, runtime->boundary一般都是较大的数。 不是真实的缓冲区的地址 偏移,经过转换才得到 物理缓冲的偏移。