前后测试了两个硬件平台:
1.example 1
固件算法基于stm32f407平台,参考了ST官方的usb audio demo
https://github.com/zizimumu/usb_audio
2.example 2
使用Microchip SAME54
反馈值:
反馈值可以是device端实际的播放速率,如48K的音频文件,实际播放速率为47K。也可以根据device端实际算法需求更改成虚假播放速率,但无论哪种方法,前提是反馈机制保证device buff数据的稳定性为目的,即buff中的数据不能出现over run 和 under run 的情况。
反馈值范围:
反馈的播放速率是有范围限制的,过大或者过小host 端的usb driver都会认为反馈值不合理而直接丢弃掉。Linux usb audio驱动中freq反馈值的范围为 min <= freq <= max,其中
Min = normal - normal/8
Max = mormal + normal /4
关于max值与同步OUT端点的最大包长度是有关联的,比如对于2 channel ,16bit,48K 模式下,如果同步out端点最大包长度为192,那么意味值每个微帧内最多传输 192B数据,即48 frames 音频文件,即最大播放速率为48K,此时Max=48K;当包最大长度为256时就不会有这样的限制了。
反馈值格式
反馈值占用3Byte数据,对于usb full speed设备,反馈值格式为 10:14,对于high speed 设备,格式为16:16。
比如48123Hz,在full speed 设备上,转换成反馈值为: ((48123/1000)<<14) | ((48123%1000)<<4)
**反馈算法实现
先看一个简单的反馈情况:
硬件平台数据流向如上图。假定DMA buff总空间32KB, 定义freesize 为dma buffer可以写入的空间.
1.当freesize处于 1/4 dma buff ~ 3/4 dma buff之间时,反馈值为正常的播放频率48000
2.当freesize小于1/4 dma buff ,让反馈值=Min,直到freesize >= 3/5 dma buff,让反馈值=48000
3.当freesize 大于3/4 dma buff,让反馈值=Max,直到freesize <= 1/4 dma buff,让反馈值=48000
以上策略可以让host快速响应device,保持buffer在一定区间。
实际效果:
加入反馈后可用空间的曲线图如下(在linux主机下测试得到,使用SAME54平台),device 预设定播放速率为48K,刚开始freesize较大,反馈最大值,之后马上回落,然后在1/4~3/5区间内震荡(3/5是自定义的,freesize超过3/5后会反馈正常值)。
测试时,如果录、放同时进行,会出现host来不及响应device反馈值的情况: 用usb逻辑分析仪看到host收到反馈值后10多毫秒才更改发送的数据量.。猜测是由于usb host 响应多个URB会存在延迟,按照上面的简单反馈处理,会存在underrun或overrun的风险,因此换了一种反馈策略–让反馈值反应实时的buffer水位情况,下面是free size的曲线图,可以看到基本稳定在水平线。
关于PC端驱动的说明
新版本的Win10/Win7都已经支持异步反馈的audio 1.0,以上example可以直接在windows下测试,Android手机或linux当然更没问题。