NAS 有趣的 Docker 推荐
已迁移到notion page,请访问:NAS 有趣的 Docker 推荐
UAC(九)UAC 常见问题
修改UAC配置参数后无法正常通信
如果修改了UAC的配置后出现UAC无法正常通信的问题,可以通过修改设备的idVendor和idProduct来解决,只有设备的idVendor和idProduct发生改变Windows才会重新读取设备的配置描述符。
Kernel 5.4内核配置某些参数后UAC通信异常
例如在44100采样率、4channel、32bit参数下Device到Host端通信异常,而Host端到Device端通信正常。 问题的原因是由于Linux的UAC驱动计算的每次传输的usb包大小不正确,导致USB传输格式不匹配出现了通信异常。详细原因如下:
该参数下每秒钟的数据量为44100 * 4 * 4 = 705600
USB每秒传输一千个包,则每个包的大小为 705600 / 1000 = 705.6
Linux下UAC驱动的做法是每次传输705字节数据,当余数足够多的时候传输705+16=721字节,然后依次循环下去。但是这种方式存在一个问题就是705不是frames大小的整数倍,即705 / (4 * 4) = 44.0625,那么USB每次传输的数据不能完全送到声卡 ...
UAC(八)PPM 评估
USB sof统计方法
打时间戳方式
ktime_get_raw_ns() Linux标准接口。
meson_timestamp() Amlogic实现的硬件定时器接口。
sof打时间戳的时机
直接在SOF中断handle里打时间戳,然后将其保存到一个fifo里。
通过一个hrtimer,主动查询SOF中断寄存器查看是否有SOF包,如果有SOF包则打上时间戳保存到fifo里。
sof时间戳导出到应用层
通过seq file创建一个proc(/proc/sof_ts)文件,应用通过读取该文件来获取sof时间戳。
USB sof统计数据方案验证
中断handle里用ktime_get_raw_ns()打时间戳统计数据
数据:
| 样本数量 | 平均值(ns) | 最小值(ns) | 最大值(ns) | 方差 | 标准差 | | --- | --- | --- | --- | --- | --- | | 8192 | 125001.0327 | 94125 | 156125 | 2281694.791 | 1510.5279 |
sof间隔图表:
统计直方图(124-126us) ...
UAC(七)Async Feedback
buffer 统计
采样间隔 1ms、采样 buffer 里的数据长度
可以看到整体上 buffer 里的数据是不断增多的,将其放大可以看下细节:
符合数据变化规律,usb 会每隔 1ms 往 buffer 里放一次数据,audiobridge 会每 period_size 间隔将数据发给 dsp(buffer 里的数据会突然减少,这里是 1024 个 period_size),然后由于 tdmb 的实际采样率要低一些,因此每隔一段时间会出现只有 usb 数据传输过来,而 audiobridge 不会将数据送到 dsp 的情况发生,这样就造成了 buffer 里的数据不断累计。
这里其实可以通过每次只采样 audiobridge 发送完数据的时刻的 buffer 大小,这样可以大大减少数据采样的次数同时还能采样到局部数据最小值。,如下图这样的:
改用这种方式采样得到的数据曲线如下:
Async 反馈阈值设定
Async 反馈 srate 给 host 后统计的数据
通过设置阈值来调整 uac 的 feedback 速率,得到 buffer 里的数据长度曲线如下:
参考文献 ...
Linux 驱动之基础(二)DMA-API
😊 There are two types of DMA mappings
Consistent DM(硬件保证 cache 一致性) mappings which are usually mapped at driver initialization, unmapped at the end and for which the hardware should guarantee that the device and the CPU can access the data in parallel and will see updates made by each other without any explicit software flushing.
Streaming DMA(需要软件来维护 cache 一致性) mappings which are usually mapped for one DMA transfer, unmapped right after it (unless you use dma_sync_* below) and for which hardwa ...
Linux 驱动之基础(一)Device-I/O
Memory Mapped IO
Getting Access to the Device
This address should not be used directly. Instead, to get an address suitable for passing to the accessor functions described below, you should call ioremap(). An address suitable for accessing the device will be returned to you.
After you've finished using the device (say, in your module's exit routine), call iounmap() in order to return the address space to the kernel. Most architectures allocate new address space each time you call ioremap(), and ...
UAC(六)UAC 同步方式
同步问题原因
USB Isochronous 传输(协议无问题)
Isochronous Transfer 同步问题
电脑播放器播放音乐时:是按一个固定的速率,比如 44.1KHZ,电脑内有一个晶振,可分频出一个 44.1KHZ,进行音乐播放,发给 USB 的数据流速率固定。USB 声卡自己得有一个晶振才能工作,它也可分频出一个 44.1KHZ,供给 I2S 信号或 DAC。
问题来了,晶振是有误差的,这两个 44.1KHZ 不可能完全一模一样,电脑可能是 44.100KHZ,USB 声卡可能是 44.098KHZ,误差约 50ppm,很正常的情况。虽然声卡晶振分频出来是 44.098KHZ,但声卡认为它就是工作在 44.100KHZ 下。好吧,如果二者时钟独立运行,那么 1 个小时会误差 0.2 秒,会出现不同步! 即电脑播了 1 个小时的数据,USB 声卡实际是无法播完的,要多 0.2 秒才能播完。 如果声卡也要 1 小时播完,那这 1 小时就需要丢掉 0.2 秒的数据。
所以二者的时钟必须要同步一致才行,这就是 UAC 同步问题的原因,因此 USB 音频规定了一是采用“等时传输 ...
UAC(五)Feature Unit
音量基本概念
声学中的分贝
因为人耳的特性,我们对声音的大小感知呈对数关系。所以我们通常用分贝描述声音大小,分贝(decibel)是量度两个相同单位之数量比例的单位,主要用于度量声音强度,常用 dB 表示。声学中,声音的强度定义为声压。计算分贝值时采用 20 微帕斯卡为参考值(通常被认为是人类的最少听觉响应值,大约是 3 米以外飞行的蚊子声音)。这一参考值是人类对声音能够感知的 阈值 下限。声压是场量,因此使用声压计算分贝时使用下述版本的公式:
\[
L_p = 20log_{10}(\frac{p_{rms}}{p_{ref}})dB
\]
其中的 pref 是标准参考声压值 20 微帕。
分贝声音变化范围
在编程中,我们可以用以下公式计算两个声音之间的动态范围,单位为分贝:
\[
dB = 20 * log(A1 / A2)
\]
其中 A1 和 A2 是两个声音的振幅,在程序中表示每个声音样本的大小。声音采样大小(也就是量化深度)为 1bit 时,动态范围为 0,因为只可能有一个振幅。采样大小为 8bit 也就是一个字节时,最大振幅是最小振幅的 256 倍。因此,动态范围是 48 ...
UAC(四)HID
HID 相关概念
报表描述符由描述 HID 设备的数据项目(Item)组成,Item 的第一个字节(项目前缀)由三部分构成,即项目类型(item type)、项目标签(item tag)和项目长度(item size)。
HID 的项目有短项目和长项目两种,其中短项目的格式如下图:
bSize 定义 short Item 的数据字节数,为 0、1、2、3 时 Data 部分的字节数分别为 0、1、2、4 个字节
bType 是 short Item 的类型,为 0、1、2 时分别为 Main、Global 和 Local 类型
bTag 是 Item 标志,有 Input、Output、Collection、Usage Page、Usage 等
长项目可以携带较多的数据,其格式如下图(用的少):
item 中的第一个字节为上图中的特定值时表明该项目是一个长项目
bDataSize 说明 Data 部分的字节数
bLongItemTag 在 HID 规范中没有定义
下面以 0x05, 0x0c 为例来说明一下:
0x05(0b00000101)其中 bit2-3 代表 s ...
UAC(三)Spec-Interrupt
Interrupts
中断用于通知 host 音频功能的当前状态发生了变化。本规范目前定义了两种不同类型的中断:
Memory Change: 某些内部实体的内存位置已更新。可以通知主机软件,以便采取适当的行动。
Control Change: 音频函数内部的某些可寻址控件更改了其一个或多个属性值
时钟实体、单元或终端内部的音频控件可以是中断的源。同样,AudioControl 接口中的任何可寻址 Control 或任何 AudioStreaming 接口都可以生成中断。最后所有与音频端点相关的可寻址控件都可能是中断的源。
音频功能的状态变化通常是由发生的特定事件引起的。事件可以是用户发起的,也可以是设备发起的。用户发起的插孔插入或移除是用户发起事件的典型示例。主机可以切换选择器或混音器,以便从刚刚插入的设备 (例如耳机)播放音频,并停止从当前设备(例如扬声器) 播放音频。设备启动事件的示例如下:一个外部设备 (例如 A/V 接收器可以在其光学数字输出上从 PCM 转换为 AC-3 编码数据,这取决于当前正在播放的材料如果此设备连接到具有自动检测功能的音频功能的光学数字输入,则该音 ...