引言
上一篇文章对演奏系统发送数据包的部分进行了分析,本文将测试并分析客户端接收到数据包到播放音频中发生了什么。非常残念的是截至目前发稿为止,仍有大量实验缺乏环境没有做完,导致在本文中结论多为猜想,有待后续验证。
文章主要围绕下面两点进行实验及分析,分别是
1.客户端接收数据包的处理方式
2.音源播放的处理方式
同样地,嫌太长不看可以直接跳到第三章 猜想、结论与对策
1.客户端接收数据包的处理方式
※本章节的内容仍在实验中,如果您有意帮助我完善实验请联系
邮箱/QQ shiro#ffxiv.cat
1.1 客户端如何接收数据
在上一篇文章中笔者分析了发送数据包与接收数据包的式样,关于各路豪杰提出的“服务器处理演奏数据”这一说法,进行了实验验证,结果证明服务器应该没有任何处理,仅仅是更改ID后进行数据包的转发。
实验为A B两名玩家,两名玩家使用同一服务器进行NTP时间同步,测得A发出演奏包后,B在约70\~100ms时接收到,通过ping -t 得出AB到服务器的ping为30\~40ms,因此服务器处理时间约为10ms左右,等效视为没有任何处理时间。
同样地,玩家A的数据包发送间隔为500ms,玩家B在接收到A的第一条数据包后,其余包间隔也为500ms左右。因此得出的结论为服务器进行相同的处理或不处理演奏数据包,该处理对延迟几乎无影响。
1.2 客户端何时播放收到的数据
※此章节在实验过程中发生问题,因此只能提供简单的猜想并将实验记录附上。※
在1.1中B的客户端已经收到了玩家A发送的数据包,数据包内容完全一致,因此假设玩家A发送的数据包内容为:[间隔200ms] 按下Note30 [间隔300ms]按下Note32 [间隔200ms]的话,笔者理所应当的认为玩家B将在收到数据包的200ms后听到第一个Note,再间隔300ms后听到第二个Note。
然而多次试验发现事实并非如此,笔者使用了屏幕录像,收到数据包的log出现到声音播放的间隔作为实验时间。结果如下
数据包中的Note延迟(ms) | 数据包的播放延迟(ms) | 误差(ms) |
---|---|---|
78 | 1114 | 1036 |
106 | 1175 | 1069 |
195 | 1503 | 1308 |
127 | 770 | 643 |
96 | 360~560* | 264~464 |
*由于实验设计问题,此处测定的播放延迟有误差,但是耳听在500ms以内
从上表可以看出,客户端在收到数据包后会进行约500ms~1500ms左右的处理才会开始播放,目前该播放规律笔者仍未找到,与发送包的休眠模式一样,无法准确预测。
但是根据目前游戏中观察到的结果,总结的规律如下
-
客户端存在统一的处理逻辑,延迟并非随机产生。
证据是本地双开客户端时,听其他玩家演奏是同时发声而没有延迟
因此猜想同一时间收到的数据包会在相同的处理时间后进行播放
-
客户端存在类似播放队列的处理方式
在实验过程中,本地抓包发现数据包并非严格按照500ms间隔收到,偶尔会有先后两包同时收到的情形,而此时对播放却没有影响,结合上述的延迟,推测客户端对每个角色的播放有相应的队列,数据包仅将数据发送到队列中,异步进行播放
2.音源播放的处理方式
通过对客户端进行拆包,笔者将乐器的音源文件拆了出来,
进行简单的波形分析后发现
拨弦乐器/击弦乐器中 鲁特琴的音源相较竖琴,钢琴等有约10ms的滞后
木管乐中,长笛比其他乐器稍微滞后
但以上仅为wav文件的样子,实际的处理应当会有起始offset和循环,因此笔者暂且认为合奏中音源间最多会存在几十ms级的偏移,且该偏移为固定值,不需要做额外处理。
3.猜想、结论与对策
客户端的本地处理部分总结如下
-
服务器不对演奏数据包做额外处理,仅为单纯转发
-
客户端对于同时收到的数据包,会在同一时间进行播放处理
结论:合奏时主要保证的是演奏者这一侧的同步,而不需要额外考虑观众侧
-
客户端的播放队列机制使网络波动不大时也能保证演奏的流畅性
结论:合奏时对于演奏者的网络要求可以稍微放宽
-
音源部分目前认为对演奏效果无太大影响