编辑器(ds-editor-lite)通过 srt::extract::MidiExtractor 的 GAME 插件从音频提取 MIDI 音符,但目前接口输出的是基于单一固定 BPM 折算的480 PPQ tick(MidiExtractOptions::tempo),无法正确处理变速曲。
对比 PitchExtractor:其输出 PitchFrame { offset(ms), f0, uv } 是纯时间域,编辑器侧用自己的 Timeline 换算到工程tick,变速天然正确(RMVPE 链路已实现)。而 MidiExtractor 把"绝对时间 → 固定曲速 tick"的折算放在了 synthrt 内,编辑器拿到 tick后无法无损还原秒域,导致变速工程错位。
另有一处固定曲速隐含假设:std::max(chunkStartTicks, previousEndTick)(:297-306)用 tick域手写切片拼接,只在单一固定曲速下自洽——若改为绝对时间输出,这段逻辑可直接消除。
期望行为
MidiExtractor 输出绝对时间,与 PitchExtractor 对齐:
• 方案 A(推荐):MidiNote 的 start/duration 改为秒(或毫秒)域;MidiExtractOptions::tempo 移除或降级为可选(仅影响 tick换算、不再参与模型输出)。
• 方案 B:在保持 tick 输出的同时,额外暴露切片/音符的绝对秒偏移,供编辑器还原。
编辑器侧改动对称且已完成大半:MathUtils::resample(values, sourcePositions, targetPositions)(非均匀重采样,含端点钳位)配合Timeline::msToTick/tickToMs 即可把秒域音符精确落回变速 timeline,与 RMVPE 链路复用同一套算法。
编辑器(ds-editor-lite)通过 srt::extract::MidiExtractor 的 GAME 插件从音频提取 MIDI 音符,但目前接口输出的是基于单一固定 BPM 折算的480 PPQ tick(MidiExtractOptions::tempo),无法正确处理变速曲。
对比 PitchExtractor:其输出 PitchFrame { offset(ms), f0, uv } 是纯时间域,编辑器侧用自己的 Timeline 换算到工程tick,变速天然正确(RMVPE 链路已实现)。而 MidiExtractor 把"绝对时间 → 固定曲速 tick"的折算放在了 synthrt 内,编辑器拿到 tick后无法无损还原秒域,导致变速工程错位。
另有一处固定曲速隐含假设:std::max(chunkStartTicks, previousEndTick)(:297-306)用 tick域手写切片拼接,只在单一固定曲速下自洽——若改为绝对时间输出,这段逻辑可直接消除。
期望行为
MidiExtractor 输出绝对时间,与 PitchExtractor 对齐:
• 方案 A(推荐):MidiNote 的 start/duration 改为秒(或毫秒)域;MidiExtractOptions::tempo 移除或降级为可选(仅影响 tick换算、不再参与模型输出)。
• 方案 B:在保持 tick 输出的同时,额外暴露切片/音符的绝对秒偏移,供编辑器还原。
编辑器侧改动对称且已完成大半:MathUtils::resample(values, sourcePositions, targetPositions)(非均匀重采样,含端点钳位)配合Timeline::msToTick/tickToMs 即可把秒域音符精确落回变速 timeline,与 RMVPE 链路复用同一套算法。