|
本帖最后由 aarwwefdds 于 2017-9-17 09:06 编辑
异步模式:USB声卡的时钟频率固定不变,所以(时钟)质量相当好。但USB控制器时钟是固定的,频率不可调,也不会受USB声卡控制。(二者不同步)解决方法只有一个:(驱动程序)启用速率匹配器,合并一部分数据或对数据插值来减少或增加数据,间接地放慢或加快传数速度,这就意味着原始音频数据已被修改。所以,这个方法保证了时钟的质量却牺牲了原始音频数据的保真
闭源代码不说,开源代码里我从来没见过驱动实现了SRC。而且这种SRC是要竭力避免的
关于ASYNC和其它方式的实现区别我在这个帖子里有说
http://www.erji.net/forum.php?mod=viewthread&tid=1987631&extra=
在代码里可以看到,ASYNC和其它同步方式影响的就是“下一个包大小”
http://lxr.free-electrons.com/source/sound/usb/pcm.c
- 1467 for (i = 0; i < ctx->packets; i++) {
- 1468 if (ctx->packet_size)
- 1469 counts = ctx->packet_size; /* 如果已经有packet_size则使用。一般在ASYNC隐式反馈,或者adaptive或者sync模式下会使用 */
- 1470 else
- 1471 counts = snd_usb_endpoint_next_packet_size(ep); /* 使用来自ASYNC显式反馈的数据决定下一个包的大小 */
复制代码
- 145 int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
- 146 {
- 147 unsigned long flags;
- 148 int ret;
- 149
- 150 if (ep->fill_max)
- 151 return ep->maxframesize;
- 152
- 153 spin_lock_irqsave(&ep->lock, flags);
- 154 ep->phase = (ep->phase & 0xffff)
- 155 + (ep->freqm << ep->datainterval);
- 156 ret = min(ep->phase >> 16, ep->maxframesize);
- 157 spin_unlock_irqrestore(&ep->lock, flags);
- 158
- 159 return ret;
- 160 }
复制代码
这个ep->freqm是由
http://lxr.free-electrons.com/source/sound/usb/endpoint.c的snd_usb_handle_sync_urb设置的,也就是处理反馈数据的函数
并且实际上,每次数据包的大小包含的sample数也是有限制的,代码里有写,XMOS文档里也明确提出来了,不是说你DAC想拿多少就能给多少的。
根据规范每个USB frame的时钟本身还有个最大jitter的限制,超过这个限制USB设备端就会完全无法与主机端沟通(out of sync 失去同步),这个限制设定本身已经考虑到了USB BUS上可能的最大时钟抖动 |
|