侃侃F7探索板怎样消除SPDIF/USB界面传输环节的时钟抖动

来源:bbs.hifidiy.net 发布者:JiangWZ 版权:原创

咱们用F7探索板来实现非常有效的降抖动机制,那就是对SPDIF或I2S数据进行FIFO缓冲和对USB数据作异步接收来隔离输入时钟抖动的影响。最终结果只取决于本地时钟的性能。

本主题是延续《固件分享,菜鸟都能玩转的F7探索板WAV/FLAC/DSD播放器输出SPDIF/DOP/I2S/SDIF/耳机》

从CD/DVD/手机/计算机/数字转盘等数字信号经过同轴,光纤或USB界面传输到解码器会引入从几百到数千pS不等的时钟抖动,较常用的优质SPDIF接收芯片如WM8805和DIR9001等使用了锁相环时钟重建电路可以得到50pS左右的基准时钟。若要更低的抖动率可以使用本地低抖动时钟基准来做异步重新采样(ASRS)来去除接收时钟抖动的影响,不过这样做会产生轻微的数据不确定性而丢失导致音质劣化。

这儿咱们用F7探索板来实现非常有效的降抖动机制,那就是对SPDIF或I2S数据进行FIFO缓冲和对USB数据作异步接收来隔离输入时钟抖动的影响。

最终结果只取决于本地时钟的性能,若提供良好的电源和电路板走线布局合理,一枚几元钱的廉价晶振的抖动率大约是5pS, 这已经比WM8875/DIR9001的50pS低了一个数量级,可以满足一般的需求了,若要更好一点以及愿意付出更高的成本,可以使用几百元一枚的优质晶振,其自身抖动可以低至0.5pS以下。再加上经过几个高速逻辑门电路后引入的几个pS的抖动,几元钱的晶振可以得到10pS以下的性能,而几百元的晶振能得到2至3个pS. 使用哪一种晶振丰俭由人。  

当然,这只是基准时钟输出的抖动率,时钟和信号连接到解码器后最终输出性能还得瞅其设计和制作功力。可以使用Jtest 来测试模拟信号输出的频谱来观察抖动率。

1、先入先出 FIFO 缓冲机制

F7探索板提供了一个RCA插座接收SPDIF信号,单片机捕获和接收到数据后不是即时输出到解码芯片而是先把数据保存在一个叫做 FIFO (先入先出) 的缓冲内存里,等缓冲达到半满时才开始以本地低抖动时钟触发输出I2S格式的数据流给解码芯片。

若信号源的时钟比本地时钟快,缓冲的写入指针会跑在读出指针的前面越来越远,直到所配置内存的尽头,这时写入指针会跳回去内存的起始点反过来追赶读出指针,假如写入指针已经追赶上读出指针而播放的曲子还没结束,还没来得及读出的数据就会被新的数据所覆盖而产生爆音,这也叫数据溢出。

若信号源的时钟比本地时钟慢,缓冲的读出指针会在写入指针的后面追赶越来越近,如果到了所配置内存的尽头还没追上,写入指针会跳回去内存的起始点而读出指针继续在后面追赶,假如读出指针已经追赶上写入指针而播放的曲子还没结束,读出的数据是还没来得及更新的旧数据而产生爆音,这就是内存被拉破了。

所以配置内存时必须保证有足够的容量可用而不溢出或被拉破。 

当曲子播放完毕后,单片机检测到出现静音片段就会把指针重新复位,也可以根据上一首曲子计算出2个晶振中的哪一个较快和快多少而动态调整指针的起始点和缓冲的大小,不用固定在半满的起始点而浪费一半的内存容量。 频率误差很小的话也可以减小缓冲的时间,这样播放视频时声音和口形的时差就不会相差太远。

现在咱们以CD的采样率来计算一下需要多长的缓冲时间和多大的缓冲内存:

假设 F7探索板的晶振频率误差是100ppm, CD转盘的晶振频率误差是100ppm, 总误差是200ppm。一首连续不停播放最长时间的交响乐是整个CD光盘的容量74分钟=4440秒,200ppm误差的话需要缓冲时间=(4440*200)/1,000,000 =0.888秒,16/44100采样率,双声道一秒钟的数据是44100*2*2 =176.4KB。0.888秒所需要的内存=176.4KB *0.888 =157KB,如果是从缓冲半满时开始播放,所需内存=157*2 =334KB。

SPDIF支持最高 24/192K 采样率,F7探索板有板载外扩的8MB SDRAM, 足够应付有余了。

可以根据最长的曲目时间,晶振误差和播放的采样率相应调整缓冲内存的大小和开始播放时的读取指针的起始位置。适当的缓冲大小可以防止数据溢出或被拉破,减少输入信号和声音输出之间的延时,这对于视频来说延时是越短越好。

2、USB 异步声卡接收机制

目前的USB音频应用界面有2种类别:USB UAC1和USB UAC2,微软视窗只提供UAC1 驱动,若要使用UAC2 则需要安装第三方驱动,这是相当麻烦的一件事,所以我只给F7探索板写了UAC1 声卡异步接收程序,可以支持到96K 采样率。 

根据最新消息,微软正在windows10上面测试着UAC2 驱动,等补丁出来后再给F7探索板加上 UAC2 的部分。

UAC1和UAC2的程序基本能共用,只是在参数上要做一些更改,而初始化设置和界面描述语句configuration interface descriptor则有很大的不同。

要USB主机能及时送出音频数据,需采用isochronous传输模式,这个模式是固定在每一个数据包里送出最多1024个字节的数据,UAC1 FS全速是通过出口端点out endpoint固定每毫秒送出一个数据包,而 HS 高速是每125微妙送出一个数据包,一毫秒可以送出最多8个数据包,比全速多了8倍,可以支持更高的采样率,不过有些播放软件对 UAC1使用高速不是支持得很好,因而咱们选用全速,最高支持到1024个字节每毫秒;16/192K:192*2*2 =768个字节每毫秒;32/96K:96*4*2 =768个字节每毫秒;24/96K:96*3*2 =576个字节每毫秒。 

以上这些都在1024个字节以内。24/192K:192*3*2 =1152个字节每毫秒,超出1024个字节而不能使用了。

咱们给F7探索板设定为最高24/96K ,计算机/平板/手机等是工作于USB主机host模式,而F7探索板是工作于USB设备device模式。

一般的声卡接收芯片会按照以下来操作:

a、主机和设备的时钟会有一些差距导致不同步,当主机时钟比设备时钟快的话,接收到的数据还来不及全部输出给解码芯片新的数据就来到,设备只能丢弃一个采样来避免旧的数据被覆盖。 

当主机的时钟比设备慢的话,旧的数据输出完毕后新的数据还没来到,设备只能重复最后那一个采样以避免当下的数据不是毗邻的旧数据产生较大的骤变而出现爆音,这样的话音质就会劣化。

b、较好的方法是设备增加一个硬件锁相环电路来重建主机的时钟,主机和设备工作于同步时钟就可以避免以上的数据丢失和插值。 

数据开始传输后主机会在每毫秒定时输出一个帧起始信号 SOF、USB音频协议规定这个1KHz的SOF信号的频率漂移需低于1000ppm,这个信号的触发边沿用来提供基准给设备的锁相环得出同步的时钟,不过因为间隔是一毫秒一次,这个对比spdif的微秒以下的解析度差了几个数量级,一般这个锁相环出来的时钟抖动率对比spdif接收芯片DIR的抖动率较差。

c、可以使用前面所说的FIFO缓冲机制来解决主机和设备时钟不同步的问题,不过会有一些时差。

d、较理想的方法是使用异步接收,只需使用很小的缓冲(只有几个毫秒的时差),一般2倍出口端点数据包的最大数据字节数就足够了,24/96K 所需的字节数是96*3*2 =576再加一个调节采样576+3*2 =582, 2倍是1164 个字节的缓冲长度。

当设备检测到接收的数据比所需要的较快时,设备会以入口端点in endpoint发出一个较慢的采样率反馈信息给主机(这个纠正过的采样率是预设的采样率减去很小的几百个ppm左右,这就出现小数点问题,因为数据发送的最小解析度是一个完整的采样,所以主机会作出计算,交替着发送n次额定采样个数的数据包,然后发一个少了或多了一个采样个数的数据包)。

主机收到后就会按照这个新的和较慢的采样率来调整输出数据的速度。 当设备检测到接收的数据比所需要的较慢时,设备会发出一个较快的采样率反馈信息给主机,主机收到后就会按照这个新的和较快的采样率来调整输出数据的速度,这样就解决了不同步的时钟而导致数据过多或欠缺的问题。

一般的计算机播放软件如foobar2000 选择DS 或DSOUND 驱动的话,会将所播放的采样率转换为48K的倍数,F7探索板的声卡模式是全速UAC1, 最高可以接收的采样率是96K, 所以foobar会以96K的采样率输出数据,不管所播放曲目是啥采样率。

若选择使用WASAPI驱动播放PCM格式的话,foobar将不作出任何处理,原汁原味根据曲目的采样率输出数据。不过播放DSD格式时,会先转换为PCM格式再输出。

各位手上有F7探索板的若有兴趣尝试以上功能,可以论坛联系我,我可以无偿提供固件。

刷完固件后,给探索板的RCA插座插上 SPDIF 输入信号就可以测试 FIFO 缓冲。

测试异步声卡功能就请在探索板的 CN13 USB_FS 连接USB线到计算机的USB口,计算机检测到设备后会自动安装驱动。

你可以在屏幕右下角指着喇叭图标摁着鼠标的右键选播放设备,打开以下窗口查看设备是否到位。

声音配置窗口

打开foobar2000, 打开以下窗口设置完后就可以开始播放音乐了。

foorbar2000设置窗口

F7声卡

也可以用安卓手机或平板的OTG USB口连接到 F7探索板声卡,从手机或平板播放歌曲。 

后记:以后可以做成一个小板子,焊上单片机和晶振就可以替代DIR接收芯片和异步USB界面。

关注【HIFI音响】公众平台

    ID:HIFI中国音响网 ID:hifidiy_2016