《最终幻想14》中实现高精度合奏

1.演奏模型

​ 结合前两篇文章的内容,让我们思考一个问题:玩家A与玩家B站在同一个位置,玩家A在T~0~ 时刻演奏1个音符,B在什么时候能听到呢?

​ 根据最开始的网络理解,B听到的时间就应该是玩家A到服务器的网络延迟PingA 加上玩家B到服务器的网络延迟PingB 。考虑到国内目前的网络状况,两者相加P约等于200ms,即玩家B在T0 +200ms左右即可听到A的演奏

T0 ------->T0 +100ms----->T0 +200ms
A演奏---->演奏包到服务器----->服务器到B

​ 但是实际上各位玩家自己测试也会发现,实际上玩家B大约在T~0~ +500ms~1.5秒左右后才听到A的演奏,说明演奏模型并不如我们想的那么理想

笔者在这里提出了下列的演奏包发送顺序

  1. 玩家在T0 时刻按下了键盘的Z键
  2. 客户端在T0时刻识别到了Z键
  3. 客户端在T0 +500ms+O时刻将过去500ms+T时刻内的演奏信息打包,发送给服务器
  4. 服务器在T0 +500ms+O+玩家延迟P去 时刻收到了数据包,包中记录着玩家A的演奏信息
  5. 服务器将数据包整理后,发送给A附近的玩家,A附近的玩家B在T0 +500ms+O+P去A +P回B 的时间收到了数据包
  6. 玩家B的客户端在处理时间P后开始进行播放声音

其中的影响因素如下

2.影响因素

  • 玩家到服务器延迟P去 和P回

  • 系统机制造成的500ms周期延迟T

  • 因采集休眠造成的实际数据包发送延迟误差O

  • 服务器处理时间窗(忽略不计)

  • 客户端本地播放的处理时间P

  • 乐器本身音源的误差Q

​ 关于系统机制的延迟T休眠误差O请参考文章《诗人演奏的通信过程》

​ 关于处理时间P和播放的误差Q请参考文章《演奏数据包的本地播放》

​ 服务器的处理时间窗在《演奏数据包的本地播放中》已经进行了分析,结论是当前版本(4.5)中服务器没有任何额外处理,仅仅是转发数据包并且更改ID

​ 在上述影响因素中,网络延迟P去和P回在网络稳定时可以等效成常量,客户端侧的处理时间P和误差Q目前结论是对于演奏者来说无影响,因此在多人合奏时主要面临的问题是由于乐谱中的空白段落造成的发送包休眠及因此产生的休眠误差O

​ 举个例子:北京的演奏者A和上海的演奏者B在现实时间T~0~ 同时按键,因为休眠机制,A的数据包在T0 +600ms后发送,B的数据包在T0 +800ms 后发送。假设北京到服务器的延迟为40,上海到服务器延迟为80,路人延迟为100,此时的路人观众C分别会在T0 +740ms和T0 +980ms收到二者的数据包。两个同时演奏的音则会在听觉上延迟了240ms,约等于120BPM下的一个8分音符。

3.实现高精度合奏的对策

​ 如第2章中描述,笔者认为解决了休眠产生的数据包误差,就可以在很大程度上改善合奏的问题。即最大限度地保证观众收到的数据包中,两个音应当被同时演奏。对策有以下几种

※以下对策的前提是要保证所有演奏者们能够同时按键,可以采用战斗倒计时,YY语音等方式

※在第一篇文章中的结论中提到过Note Off事件产生的数据包,因此在弦乐器/打击乐器轨道中空白时间小于6秒时可以视作连续,但是要求演奏者注意保持按键的时间。

  1. 人工节拍器

    ​ 由于误差相对随机,在这里引入观察者的角色,每位演奏者通过现实中的节拍器进行等间隔的演奏,观察者通过语音,聊天等方式进行反馈使演奏者进行自行调整,直到所有人同步后,在3秒内进行下一步的演奏。

    问题点: 对演奏者要求较高,且如果乐谱中间出现长时间空白,还是可能会导致不同步的出现

  2. 确保演奏包同时发送

    ​ 在前期调查中,笔者发现在开启演奏UI后第一次按键是没有休眠状态的(未证实),因此可以将第一步的人工节拍器省略,第一次开启演奏UI后,同步进行演奏即可。

    问题点:同1

  3. 演奏不要停

    ​ 如果全程没有任何休眠,那么就不需要解决延迟问题啦,与对策2合并后可以保证所有轨全程同步。

    问题点:做谱子好麻烦

  4. 实时调整按键时间

    ※这里主要针对自动演奏,对手动党要求较高。

    ​ 即通过软件实时抓包,当产生休眠误差时,数据包中的间隔长度一定是大于500ms的,因此将后续的演奏按键均提前一个offset,即可实现在观众侧的同步。

    问题点:由于会将后续按键提前演奏,因此不管手动还是自动,都会吃掉若干ms的音,使演奏效果造成割裂。

  5. 实时调整演奏时间·升级版

    ​ 在3的基础上,使用Note Off的机制,在轨道的空白期间一直按住按键,直到下一个按键的1.5秒前松开,通过无声的数据包来调整按键。

    问题点:对于管乐器没有Note off可以利用,只能应用到弦乐器上。对于谱子要求空白期间大于8秒为佳。

  6. 演奏时间调整 升级版2

    对不起我编不下去了,一想到5.1要开合奏模式暂时没动力去解决4的问题了,就这样吧。

猝不及防的广告:针对对策方案5笔者已经实现了软件,支持自动演奏,外接键盘演奏和手动演奏的调整同步。目前正在内测中,请加群获取。

4.一些Q&A

  1. 使用战斗倒计时可以实现同步合奏吗

    ​ 战斗倒计时与使用NTP进行时间同步效果相同,目的是为了使所有玩家的按键时间同步

    ​ 但是并不能使演奏的数据包达到同步的效果,因此对于多人情况下效果不会明显

  2. 网吧五连坐同时按键演奏可以同步合奏吗

    ​ 由于上面提到的[数据包发送延迟]的存在,我们不能保证每台电脑的延迟误差T都是一样的,因此即使网吧五连坐在不进行特殊处理的前提下也无法做到每次都同步,请参考第2章的栗子。

  3. 我们X个人使用XXX软件就实现了同步的合奏诶

    ​ 由于误差T的范围在1-500ms间,所以会出现两人的误差相同或者接近的情况,在这种情况下确实能够实现同步的合奏,但是因为T的不确定性,我暂且认为演奏100次不会每次都是同步的。另外轨道上没有空白时间也是同步的。

  4. 5.1马上就出合奏系统了,你说这些有什么用

    ​ 考虑到数据包发送的逻辑是很底层的东西,个人认为数据包的发送不会有什么变化,还是会以500ms为单位进行发送,那么上述的延迟问题有可能还会存在。

    ​ 另外,官方目前的宣称为将小队内的乐器音频进行まとめ,很可能是在接收端对id进行判断,如果是同一小队则延迟播放的处理。

    ​ 不过如果官方解决掉了延迟问题那大家都应该开心才对嘛,这系列文章就作为调查记录保存好了。

5.附录及致谢

​ 本文的诞生主要感谢Ultima服务器的Aster Almayard,他在4.3左右就提出了演奏的一些模型,包括战斗倒计时等。但是并没有挖掘到数据包本身,最新关于4.5的文章中提到的高精度合奏也为人肉节拍器方案提出了一些启发。

​ 本系列的创作同样感谢下列玩家的贡献

  • ​ 酒酿和歌子@神意之地 (这是我的CP)
  • ​ 松本一木@紫水栈桥 (或者什么什么@Tonberry)
  • ​ 科洛斯公主@幻影群岛
  • ​ 鸡@白银乡
  • ​ 超威老炮@神意之地
  • ​ 野生喵@神意之地

​ 参考资料及软件项目如下

知识共享许可协议
本文采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇