MacOS 音频驱动开发一:理论篇(内核扩展)

前言

本篇是基于内核扩展理论的学习,主要框架使用IOAudioFamily。此部分已经被苹果抛弃,在新的macOS中已经正常情况已经无法使用。最新系统音频的驱动的开发使用AudioDriverKit,这个是dext系统扩展的形式,这里留着后续学习。但是音频驱动的原理基本没变,所以以前内核扩展的理论还是值得学习。

一、数字音频和PCM

我们目前所有电子设备听到的声音本质上都是由数字信号模拟的。所以听到的声波就是由数字信号进行模拟的,由计算机系统进行存储和维护。数字音频的中的音频数据主要是通过PCM(Pulse Code Modulation, 脉冲编码调制 )从模拟声波信号中获取到的。PCM以固定时间间隔对模拟声波进行采样和测量,每秒的测量数就称为采样率。例如你可能看到44.1kHz 、48kHz 类似的参数,这个就是指每秒采样的次数(采样率),48kHz 意味着每秒进行48000次声波信号测量。每次测量称为采样。采样是测量声波信号的振幅,然后量化为具体的数字标度,该标度范围称为位深度或采样深度。比如目前很多采样位深度是16位,那么每次采样的可能值范围就是 -32768 ~ 32767.采样率和采样宽度越高,表示声波信号测量越精确。

  • PCM的采样数据根据通道数进行交错存储。例如2通道的采样,一对左/右就是一个采样组,每个采样都是16位(意味着每个采样占2字节存储)。如果有8个通道(如HDMI)则每个采样组就是(1~8)。大部分数字音频系统都是要求这样的音频数据。硬件播放的时候也要以这种数据方式,如果是MP3这种压缩了的音频数据,在硬件播放前也要进行解压还原成前面的数据格式。
  • PCM采样数据存储计算。例如44.1kHz的采样率,2通道,这就代表着每秒44100个采样组,采样深度是16位,那么每秒的数据量就为44100X(16/8)X2 = 176400字节。采样深度还可能是 8、20、24或32 。另外采样存储可以是无符号数或有符号数,还有可能是浮点数(Core Audio就是使用32位浮点)。常用PCM格式如下图:

二、音频设备音频驱动

音频设备音频驱动核心概率采样缓存区:采样缓存区一般是驱动程序分配的一个内存空间,用来存储PCM采样数据。对于音频播放(输出),音频播放设备会连续直接访问(DMA)该缓存区而不需要CPU调度,并且按照固定时间间隔发送中断,使驱动程序知道当前设备读取的位置。这是非常必要的,可以保证新生成的音频数据可以写入到正确位置,而且不需要和设备进行交互。一段时间后,设备播放了一些采样数据,驱动程序会删除已经播放的采样数据,这时如果没有新的数据写入设备就会保持静音。音频输入就恰好相反,音频设备将采样数据写入缓存区,同时会发出一个中断,这样驱动程序可以知道正确的数据读取位置。一些音频设备也可以有多个输入输出,每个输入输出都会有自己独立的采样缓存区。

三、Core Audio和HAL

Core Audio:这个是macOS处理音频的一个最重要框架,需要单独一篇学习。本篇主要针对内核扩展学习,core audio主要是用于用户空间应用程序处理音频相关。

core audio是音频HAL(hardware abstraction layer,硬件抽象层)的核心。 HAL像是一个中间层,把Core Audio内部的framework,应用程序,音频设备,驱动程序连接起来。

  • 以前 OS9,以前应用程序可以直接写入驱动程序采样缓存区中,因此在这以前只能处理单个应用程序的音频输出。
  • 当下 OSX和iOS,有了HAL,应用程序不能直接和驱动程序进行交互,而是和HAL进行交互(主要也就是和Core Audio进行交互),Core Audio会把所有的应用程序和多线程的音频放入一个缓存区,应用程序可以选择任意HAL支持的音频格式存储,Core Audio会先把缓存区数据转换为32位浮点格式的数据,然后交给驱动程序,驱动程序负责将32位浮点格式数据转换为音频硬件支持的格式进行播放。音频输入也是如此
  • Core Audio中包含一些非常重要的框架:
    • Audio Toolbox
    • Audio Unit

四、I/O Kit音频支持

在内核中主要是IOAudioFamily处理音频(通过此内核扩展的形式苹果已经不支持)。我们开发内核扩展音频驱动主要就是用它。概念及功能相对比较简单。主要是和硬件进行数据传输,以及一些基本功能,例如静音,控制音量及其他可配置的属性。下图为IOAudioFamily的结构,其中IOAudioDevice,IOAudioEngine比较重要。

  • IOAudioDevice: 它是音频驱动程序的功能核心,和硬件的交互功能一般都放在这里,比如条件音量,初始化硬件设备等。它不负责音频数据I/O(这个由 IOAudioEngine负责)
  • IOAudioEngine:音频驱动程序主要实现I/O部分(也是主要使用DMA的部分)。一个音频可能存在多个独立输入和输出。IOAudioEngine至少分配一个IOAudioStream。这是一个抽象类。
  • IOAudioStream:表示采样缓存区。采样缓冲区有一个与其相关的方向,可以是输人或输出。IOAudiostream还包含描述它所支持格式的元数据,如采样的数宇格式、采样率、支持的通道数。该类并不是抽象的,可以直接实例化。该类不为采样缓存区本身分配内存,必须告知它缓冲区的位置。它负责将采样缓冲区提供给用户空间用户。该音频流还维护一个内部混合缓冲区,将多个源的音频混合成一个流.
  • IOAudioControl:表示设备的可调参数,如输人音量、输出音量和静音。IOAudioControl类无法直接使用,但可以将其子类化,创建自定义的控制。IOAudioControl的3个子类为IOAudiolevelControlIOAudioselectorControl 和IOAudioTogg1eControl。一个控制可能属于设备本身、引擎或IOAudioPort.
  • IOAudioPort:表示逻辑端口或物理端口,如音频输出或耳麦输出。并不要求音频驱动程序使用该类。
  • Core Audio框架通过IOAudioEngineUserClient与 IOAudioEngine进行通信,从而可以与引擎 的采样缓冲区交互,以播放或捕获音频。
  • IOAudiocontrolUserClient作为IOAudiocontrol实例的用户客户端,可以进行操作。这是 应用程序(如System Preferences)控制音量或静音的方式。
相关推荐
Stark-C6 小时前
万物皆可Docker,在NAS上一键部署最新苹果MacOS 15系统
macos·docker·策略模式
Roc.Chang6 小时前
macos 使用 nvm 管理 node 并自定义安装目录
macos·node.js·nvm
三劫散仙10 小时前
Mac vscode 激活列编辑模式
macos
endingCode14 小时前
45.坑王驾到第九期:Mac安装typescript后tsc命令无效的问题
javascript·macos·typescript
soulteary15 小时前
突破内存限制:Mac Mini M2 服务器化实践指南
运维·服务器·redis·macos·arm·pika
小江村儿的文杰1 天前
XCode Build时遇到 .entitlements could not be opened 的问题
ide·macos·ue4·xcode
天涯倦客的美丽人生1 天前
2024年11月最新 Alfred 5 Powerpack (MACOS)下载
macos
SoraLuna1 天前
「Mac玩转仓颉内测版24」基础篇4 - 浮点类型详解
开发语言·算法·macos·cangjie
总爱写点小BUG1 天前
VM虚拟机装MAC后无法联网,如何解决?
macos
Cod_Next1 天前
Mac系统下配置 Tomcat 运行环境
java·macos·tomcat