SVS 编辑器在音符编辑事件下参数静默干预失效及其解决思路思考

Final
Qy

相关仓库: EquinoxEditor

上下文

首先介绍一下这个问题是怎么来的。

我在高中期间有一系列想法,笼统来说就是编一个歌声合成(恕下文用 SVS 代替)编辑器以及引擎,并且确定了一套基于「基于生理学的中间参数」的适配协议(参见 Qy 项目介绍)。

开发背景

我本以为这个 idea 会束之高阁,但在 24 年的下半年,因为一些个人变故我选择重新开始推进它。 并且编写了一些简单的代码以及脚手架,但因为编码水平的限制没有什么实际进展,后续因为准备毕业加之尝试搭建 DiffSinger 推理管线失败的关系也被搁置了。

在 25 年的下半年,我突然想继续推进,并且基于此完成了 Orchid ,以及及其相关的 OrchidSymbiontOrchidStratum 以及 OrchidIntervention 。也通过了 Livebook 跑通了 DiffSinger 的管线。

至少就我最开始的想法而言,是实现了。但是并没有和目前的 SVS 编辑器的横向对比以及对其他用户而言所见即所得的效果。因此我想要继续开发完成编辑器。

经过了几个原型的编写后,我想依照 DDD (领域驱动设计)的思路开发。我当时的思路是这样的:

  1. 完成领域建模并编写代码
  2. 绑定此前编写的 Orchid 调度引擎并设计歌声合成编辑器的引擎协议并且自己写几个
  3. 实现 UI

但是在编写领域代码的时候,碰到问题了。更具体一点的话,是参数序列在音符编辑(诸如修改歌词、批量断开/连接等复杂场景)时的保留与否。

Equinox(旧QyEditor)的思想

我需要介绍一下我开发的思路,从某种意义上讲,这个脱胎于 Qy 的思想,不过更原始、更不泛用。

大概包含几点:

  • SVS 本质上是从及其抽象的符号到一段音频的过程,但是这个过程中存在大量(可量化)的中间参数
  • 不能是黑箱——用户对中间参数有着完全的控制权(intervention)
  • 复杂的模型的推理管线可以抽象成 DAG1 (有向无环图)
  • (不是约束而是想法/特征)需要设计增量生成,特别是基于 ML 的模型/管线

问题描述

考虑一个日常操作:用户在编辑器中画了一条 pitch 曲线、手调了几个辅音的 preutterance(提前量),然后发现歌词打错了——“着”应该读 zhuo 不是 zhao。

改完歌词之后,G2P(歌词转音素)重新运行。原来的音素序列 [tʂ, a, ʊ] 变成了 [tʂ, u, ɔ]。但用户之前对 /a/ 的 timing 调整,现在静默地应用到了 /u/ 上。

这就是 干预静默失效(Silent Intervention Staleness):上游参数变化导致下游用户编辑失效,且失效过程没有反馈、没有警告、没有回滚。用户听出来不对劲时,已经不知道是哪次编辑出的问题。

以上片段由 AI 总结,实际上我的原始想法是很多个 scenarios

原始场景I

sol la ti -> sol la si

原始场景II

音素批量变化——以多音字的替换为例

他山之石?

其实本节主要介绍其他的 SVS 编辑器是怎么解决类似情况的,但我貌似没找到直接解决这个的。

新的问题:音符边界不匹配

单独看 preutterance(辅音提前量)的问题,似乎只是一个参数溢出的边界 case:

歌词从 ti 改成 si,/s/ 的 preutterance 比 /t/ 长。如果前面的音符很短,这个辅音就溢出了——它的 onset 时间早于前一个音符的结束时间。

但这不是参数问题,是模型问题。在所有 SVS 编辑器里,音符边界和音素边界是耦合的:一个音符 = 一个音素单元。preutterance 溢出意味着一个音素的时间范围跨过了音符边界——这个音素到底属于哪个音符?属于前面的音符(声学上下文的一部分)还是后面的音符(发音的一部分)?

更极端的是 melisma(一字多音)。比方说一个很极端的花腔女高音,一个音节横跨很多个音符。更不要说 Vocaloid 常见的操作技法:拆音。

这两个问题的共同根源:slot-indexed data has no identity when the index is recomputed。preutterance 溢出是因为”音素的时间范围”不是 slot 能表达的;melisma 是因为”一个音素跨多个音符”时 slot 根本不唯一。

以上片段依旧由 AI 总结,实际怎么样容我想一想该怎么写

解决方案

基于时间线的 Delta-Map

Projection -> Artifact -> Resolution -> Adopt 循环

操作边界的重新梳理以及解耦

乐谱与语音学领域的区分

参数身份的重定义

感悟

放弃对于「绝对简洁」的执念

Footnotes

  1. 原始想法是「可编辑的节点图」 ↩︎