Refresh real curves after phrase rendering#2175
Conversation
Introduce RenderPhraseEvents to report rendered real-curve fragments during phrase rendering and propagate the new optional parameter through IRenderer and concrete renderers (Classic, Worldline, DiffSinger, Enunu, Vogen, Voicevox). Add a DiffSingerRealCurveScheduler that coalesces curve-edit commands (200ms debounce) and schedules RealCurvesUpdated notifications only for variance-offset curves (ene, brec, voic, tenc). Wire scheduling into DocManager (on execute/undo/redo/undo-group) and make RenderEngine consume RenderPhraseEvents to publish incremental updates when available. Also add small ExpCommand.Key assignments to enable detection, refactor DiffSinger real-curve build logic, and include unit tests for the scheduler and RenderPhraseEvents behavior.
|
原实现只在 phrase 完整渲染结束后刷新 real curve。DiffSinger 中 variance 曲线实际在 acoustic model 开始前已经确定,因此 pitch 修改后不应该等 acoustic/vocoder 完成才显示更新。 另外,用户只修改 ENE/BREC/VOIC/TENC 这些 variance offset 曲线时,base variance 通常不变,显示曲线可以更早刷新,不必等待整段音频渲染结束。 设计原则 通用层只建立干净的 hook/API,不放 DiffSinger 业务逻辑:
DiffSinger 独有逻辑留在 DiffSinger 责任区:
改动逻辑
DiffSinger 在 variancePredictor.Process(phrase) 完成后,立即构造 real curve 并通过 RenderPhraseEvents.ReportRealCurves(...) 发布。 这样 real curve 会在 acoustic model 开始前刷新,而不是等整段 phrase 渲染结束。
新增 DiffSinger 专用去抖调度器: DiffSingerRealCurveScheduler 它只响应 DiffSinger 下列曲线:
不会响应:
调度器使用 200ms debounce 合并拖拽绘制产生的连续曲线命令,避免做真正鼠标级预览。
RenderEngine 仍保留原来的 phrase 渲染完成后刷新逻辑。 如果 renderer 没有提前报告 real curve,例如命中整段 wav cache,仍会在渲染结束后尝试加载并刷新 real curve。 改动文件
影响范围 实际功能影响限定在 DiffSinger:
|
The existing scheduler hook only fires for curve-edit ExpCommands, so undoing a note move or phoneme edit left the rendered variance baseline stale: PreRenderProject would hit the wav cache, skip InvokeDiffsinger, and renderEvents.ReportRealCurves never ran. Even when the render-engine fallback did run, ApplyUpdate only cleared the new phrase's tick range, leaving stale tail segments visible whenever undo shrank the phrase. Add IRenderer.ScheduleFullRealCurveRefresh (DiffSinger implements it via DiffSingerRealCurveScheduler.ScheduleForUndo, bypassing the command-type and abbr filters) and call it for every voice part the undone/redone group touched. The notification carries an isFullRefresh flag; on the receiving side RealCurveUpdater.ApplyFullRefresh wipes every realXs/realYs entry in the part before applying the freshly loaded baseline so no ghost ranges survive. Depends on DiffSingerTensorCache being enabled — that is the documented prerequisite for variance baselines and we don't try to re-enable the disabled-cache path here.
The previous undo hook (Force real curve refresh on undo and redo) wiped every realXs/realYs in the part and re-applied whatever the renderer returned. When the curve scheduler ran during a phonemizer rebuild it saw an empty renderPhrases list and returned no updates, so the wipe deleted all curves and they only came back after the next render finished. Replace it with a coverage-based trim. RenderEngine accumulates the per- phrase real-curve updates as each phrase finishes, and when every phrase in the part has produced samples it posts a RealCurveCoverageNotification. DocManager handles it by removing realXs entries that fall outside the union of [startTick, endTick] for each abbr that was actually covered, clearing stale tail data from earlier renders with wider phrase ranges while leaving untouched abbrs alone.
This reverts commit 4f3755f.
This reverts commit 6f223bf.
本改动解决的问题是:DiffSinger 等支持 real curve 的 renderer 在渲染完成后,UCurve.realXs / realYs 不会自动更新,用户必须手动点击“Refresh Real Curves”批量编辑功能才能看到最新 variance/real curve。现在每个
phrase 渲染完成后会自动尝试刷新对应 phrase 的 real curve,减少手动操作。
改动逻辑
新增了 phrase 级渲染完成 API:
渲染流程变为:
自动刷新失败时不会影响渲染;异常只被跳过/记录,不弹窗、不打断音频渲染。
保留的行为
文件变更
OpenUtau.Core/Commands/Notifications.cs
新增 PhraseRenderedNotification 和 RealCurvesUpdatedNotification。
OpenUtau.Core/Render/RenderEngine.cs
phrase 渲染完成后发送 phrase 通知,并尝试生成 real curve 更新。
OpenUtau.Core/Render/RealCurveUpdater.cs
新增 real curve 转换和局部替换逻辑,包含 phrase hash stale-check。
OpenUtau.Core/DocManager.cs
处理 RealCurvesUpdatedNotification,在发布通知前应用 real curve 数据。
OpenUtau/ViewModels/NotesViewModel.cs
收到 real curve 更新后触发表达曲线重绘。
OpenUtau.Core/Properties/AssemblyInfo.cs
开放 internal 给测试项目。
OpenUtau.Test/Core/Render/RealCurveUpdaterTest.cs
测试坐标转换、局部替换、stale hash 跳过逻辑。