维护状态(2026-10-13):现行音频/速率契约;预览和回放长 KS 中途恢复已实现。原生准备完成调度经独立功能、有限客户端对照与用户暂未发现异常的反馈后合入源码;读取缓存随后也已合入,详见读取缓存记录及音频合入记录。 文档职责与最新状态入口见索引。
更新:2026-10-06。当前目标为 osu!lazer 2026.1005.0;历史音频专项最初在 2026.921.0 验证, 当前版本已通过收尾过滤回归;暂停和声道生命周期对照了本地 osu!framework 源码。自动测试不等于实际音频设备上的同步和听感验收。
O2Jam 音乐事件以谱面时间安排。HT/DT 默认保留音高,Adjust Pitch 同时影响 BGM 与玩家键音;DC/NC 使用 Mania 的固定变调语义,NC 保留原生节拍音。WU/WD/AS 暴露实时 SpeedChange,宿主绑定同一速度到事件轨和视觉流速。普通 O2Jam 判定仍由谱面位置驱动;MS 的 HT/DC/DT/NC 判定窗口则复用原生 Mania 速率补偿。不能对回放时间或音符时间再乘一次速率。背景音与 KeySound 不受全局效果音量影响。
| 路径 | 当前实现 | 应验证的区别 |
|---|---|---|
| BGM 与较大自动音 | O2JamPreviewTrack、O2JamBeatmapSkin 用原生 Track;自动音 ≥512 KiB 走流式轨 |
连续音源须跟随速率、可寻址并在暂停/恢复后对齐事件钟 |
| 小型自动 KeySound | 原生 Sample/Channel,按事件钟触发 | 其一次性包络不因 Tempo 属性自动拉伸;未来若要求全部键音体拉伸,属于新行为设计 |
| 玩家触发 KeySound | O2JamHitSoundRateAdjustments 限定 O2Jam endpoint 的原生可调音频 |
Frequency/Adjust Pitch 与实时速度一致,不改全局 UI/效果音 |
| 视觉下落 | O2JamDrawableRuleset 读取原生 Mod 的速度 bindable |
BPM 与 rate 的视觉补偿不反向改变判定 |
O2JamPreviewSchedule 仅从已转换的谱面构造音频事件;它保留 SampleId = 0 与缺失 OJM 音色的原有路径,不重新映射音符。O2JamPreviewTrack 拥有预览与游玩的共同事件钟,并按谱面时间派发 BGM、自动 KS 和可演奏 KS。某个流的解码尚未完成时,该流保持顺序等待,其他已就绪流仍可派发。启动时则先等待所有到期音源准备好,以免开头静音。较大的自动音按原有 512 KiB 门槛走可寻址原生 Track;较小的自动音和可演奏键音仍走原生 SampleChannel。
选曲预览自动播放可演奏键音;普通游玩与回放由原生命中路径触发,回放漏掉的音符不会补播。预留的 GameplayAutomatic 策略改为按谱面时间自动播放可演奏键音,并只对当前 OJM 皮肤关闭判定音查找,避免重复播放。O2JamDrawableRuleset.AutomaticallyPlayKeySounds 是未来 Mod 可接入的宿主入口,目前没有可选的 Mod 或用户界面,也不改变计分规则。全局“谱面打击音效”开关无法静音普通 OJM 键音;其他皮肤和音效仍服从原生开关。
玩家触发的游玩 KS 按 OJM 样本身份在当前游玩内停旧重播:未判定物件的误触、连续误触与首次命中共享替换策略;单点/LN 头判定后不可再被列级空击选中。另一个未判定物件使用同 KS 仍可触发。策略位于 Host.Audio,复用原生声道,不改 Core、映射或零/缺失样本处置;MS 也保留这套音乐播放策略,其他 ruleset 不变。预览、背景与预留自动 KS 路径保留原有并发。
选曲与游玩暂停会停止共同事件钟和 BGM,并在原声道上冻结正在播放的小型 KS;恢复时不从头触发。跳转重建 BGM 所处的谱面位置,让后续事件按目标时间重新派发。原生 SampleChannel 无法按内部偏移寻址,预览因此使用原生 Track 补播覆盖当前位置的历史采样。回放先停止旧 KS,待原生判定重演到目标时间后,依据实际命中恢复仍有效的长采样;漏判不补播。冷缓存异步准备仍可能短暂缺少某一音层,详见下方专项文档。实时游玩没有增加历史补播策略。
同曲不同难度只在背景编排兼容时转移原生轨道。Integration 的 O2JamExternalChartResources 懒加载外部 OJN/OJM 并核对 OJM 文件戳,Host 的 O2JamWorkingBeatmap 负责原生轨道及皮肤接入。缓存失效、取消和释放已按问题 A09完成定向检查及有界客户端复测,边界与剩余限制如下。
资源所有权按以下边界处理:
| 资源 | 持有与创建 | 失效与释放 |
|---|---|---|
| OJN 文档、OJM 索引 | 进程级 OjnDocumentCache(最多 128 文档)和 OjmArchiveCache(最多 12 归档,按已登记解码字节设 384 MiB 上限)按文件戳复用;集合与索引冻结,公开字节复制,轨道流只读且不复制音频块 |
失败读入从缓存剔除;成功导入或显式刷新写入后,按 OJN 源路径清除两类缓存。已交给工作谱面的对象不会热替换 |
| OJM 延迟载荷 | 独立 Formats 记录索引来源;首次实际读前/后校验原生句柄长度/时间戳,成功字节仍由原 Lazy 拥有 | 变化/IO失败单向失效,已加载旧字节继续有效,其他未加载载荷拒绝;下一次获取重建索引,不热替换在途声音 |
| 工作谱面与 OJM 皮肤 | O2JamWorkingBeatmapCache 最多强引用六个包装谱面;选中后才开始 OJM 索引和皮肤预加载 |
原生 WorkingBeatmapCache.OnInvalidated 或本地逐出时请求释放皮肤;OJM 读取失败或文件戳变化的包装谱面下次选中不再复用,也不向新谱面转移旧轨 |
| 预加载工作 | 此 ruleset 共用四槽 O2JamPreloadScheduler,O2JamAudioPreparationHost 分开发布资源获取与原生准备尝试结束;槽位保留到后者 |
排队消费者立即取消;在途 Getter/原生准备仍占槽至完成或原生关闭。Skin 关闭先排空在途任务,无消费者结果释放 |
| 正在播放的事件轨 | O2JamPreviewTrack 持有皮肤租约和自己的原生子轨、声道;协调器只保留弱引用 |
事件轨先释放子轨,再归还租约;皮肤等最后一个播放租约归还后才释放原生 Sample/Track 存储 |
仅 OJM 内容变化而文件长度与时间戳均未变时,选曲不会自动识别;手动刷新会失效已导入谱面的 OJM 缓存,即使 OJN 被判定为未变化。已加载的工作谱面在下次选中时不再复用旧归档,正在播放的曲目不会热切换音源。用户于 2026-09-29 确认手动刷新表现正常;此前有界音频复测除上述小型 KS 尾音限制外未报告异常。全曲库听感不在这些验证范围内。
相关实现:Host/Audio/O2JamPreviewTrack.cs、O2JamBeatmapSkin.cs、O2JamHitSoundRateAdjustments.cs、Integration/Beatmaps/O2JamExternalChartResources.cs、Host/Beatmaps/O2JamWorkingBeatmap.cs。自动测试覆盖速率与通道绑定、事件顺序、暂停与跳转;有界客户端复测无其他异常,不代表所有实际设备、长曲或谱面均已验收。可选音频追踪只记录观测,不自动调整偏移。
本轮按用户实测后的选择实现 C06 的限定策略,没有新增判定算法、调整 KS 映射或
改变预览/背景混音。原 O2JamHeldKeySoundPatch 改为 O2JamResolvedKeySoundPatch,
继续使用同一个原生选音接缝,并覆盖单点末尾回退及 MS 的 OJM 物件。
最终 201 项音频/游玩/回放过滤回归通过,另在独立进程验证 BMS 两种载入顺序各一项,
共 203 个不同用例,无失败或跳过。报告位于忽略目录 .artifacts/test-results/:
keysound-retrigger-final.trx、keysound-bms-first.trx、keysound-bms-last.trx。
模块、存储、计分及语义依赖检查通过,无新增分层例外;没有运行 benchmark 或
未过滤测试集,也没有改写客户端谱面/成绩数据库。
原生 BASS 无声设备测试检查新声道起始偏移为 0、停掉旧声道、三个暂停/恢复周期 保持新声道句柄和位置,并确认 seek/恢复不会复活旧尾音。其余用例覆盖误触与命中 跨实例替换、不同 KS/游玩隔离、原生 Mania 选音不变、判定后禁用及 rewind 恢复, 以及已有预览、自动音、全局开关、变速、LN 视效和正式 v5 回放路径。
客户端已关闭后备份并安装 DLL;SHA-256 为 A6E41944DF25657C7ACF1F53A1210F636A567EE8AB4089EDA62B3B2F4325B63B,
旧版保存在 D:/o2lazer/.artifacts/client-backups/keysound-retrigger-20261004-235113。
用户于 2026-10-05 回复本轮测试没有问题,确认 KS 重触发改动通过有界客户端验收。
这次反馈不等同于所有谱面、音频设备或未来自动 KS Mod 的完整听感验证。
该次历史验证仍暂缓中段尾音恢复;2026-10-08 的预览与回放工作已覆盖所选范围,见下文。
原生 SampleStore.GetAsync 返回时,采样 factory 的解码仍可能在原生音频队列中。 因此仅限制 Get 并发不能限制本 ruleset 未完成的准备工作。Host 的准备组件继续 使用原生 store、factory、decoder、mixer 和设备恢复,补上这两个状态间的边界: Drawable 能在获取后取得独立 Sample,预览就绪及长度则等待完整 store 更新后的 准备尝试结束;Track 等待公开 StopAsync。Getter 在更新中途完成不能误通过 当前帧屏障。不 patch 私有解码方法、不自写 codec、不轮询 IsLoaded 或添加固定等待。
缺失采样有限结束,合法 ID 0 和原 note/KS 映射不变。无效 Sample 尝试结束后 仍保留 factory 供原生设备恢复;准备结束不等于资源一定有效。关闭先取消消费者, 在途任务继续持槽;原生 AudioThread 退出的最终 manager 更新清理 stores,晚到 Getter 结束不要求另一个音频帧。旧 O2JamTrackPreparation 已移除。
预览索引就绪后,根据首个存在且音量非零的音频事件汇集 urgent 请求,完成整个 批次再派发远期请求;缺失/静音事件不能选择首音优先窗口。预取范围覆盖首事件 之后十秒,长谱面引导段不移动时间线,采样内部低信号前奏不裁剪。
四槽只约束本 ruleset 的在途准备,不是全部 ruleset 的全局解码/PCM/单帧预算。 一个原生解码仍可能很慢,资源释放也不承诺设备上每一时刻都有可听声音。 源码合入后的 158 项定向回归、197 份正式输入的分层检查和无测试桥/探针产物 核对通过;实际听感仅按本轮用户反馈的范围接受,未穷举所有设备、曲目和 Mod。
HT/DC/DT/NC 继承对应的原生 Mania Mod,保留其设置、变调及 NC 节拍覆盖层。 原生 IManiaRateAdjustmentMod 会把每个 Note 或 LN 首尾窗口直接转成 ManiaHitWindows,因此不能直接用于普通 O2Jam 物件。ManiaScore/Mods 的 O2JamManiaRateAdjustment 只将已转换的原生毫秒窗口交给该原生接口;每个 Mod 复用一个轻量适配器和原来的 SpeedChange bindable,不复制窗口公式或逐帧修改。
MS 的 DT/NC 原先只改变时钟,遗漏了窗口补偿,导致实际判定变严且 Legacy 误差条未变宽;现在两者随原生窗口一起调整,HT/DC 同步恢复原生语义。普通 O2Jam 的 tick 判定、固定显示宽度、音符时间和音频速率政策保持原有契约。 WU/WD/AS 并没有对应的原生 Mania 窗口补偿,本轮不扩展其判定政策。 Classic 仍按原生对外部 ruleset 的转换谱面政策处理,不改成 Mania 原生谱面政策。
本轮普通配置 178 项、监听配置 118 项定向测试及 BMS 两载入顺序均通过;对应 报告与客户端安装状态见误差条记录。 MS 判定窗口修复会改变真实窗口,并非仅改变绘制。曾在窗口补偿遗漏版本录制的 MS 变速回放,边界输入在新版本重算时可能产生不同判定;本轮不改写存量回放 或成绩文件。序列化、导入及默认/自定义速率测试不等同于旧窗口行为的兼容验收。
测试前已确认本地干净且 GitHub master 与本地同为
ab07d019a80faf69878184ae8c66776b91044236;原安装 DLL 与记录保留于
.artifacts/preview-transfer-baseline,可独立回退。本节记录第一阶段;后续预览补播见下文。
在既有源路径、OJM 资源与背景编排兼容的轨道转移中,只对 Preview 路线匹配活跃 SampleChannel。身份使用事件起点、采样编号、音量、声像和自动/可演奏用途;资源身份由 已有转移边界及同一资源租约保证。目标事件多重集按数量消费,避免重复采样越量保留。 共同事件保留原生声道和音频播放位置,无重新读取、解码或创建 Track;其他声道停止。 第一阶段未重建目标独有的历史采样;后续只对 Preview 增加异步补播。Gameplay 与 GameplayAutomatic 保持原来的清理政策。
匹配索引随事件表在调度动作提交前构建,预计构建 O(N)、额外空间 O(N),音频线程匹配 预计 O(A),N 为目标 KS 事件数、A 为活跃声道数。延续声道也保留其本应存在的混音负载, 不能将避免解码等同于零开销。未运行 benchmark;客户端听感与性能对照待验收。
可搜索 O2Lazer preview schedule transfer:prepare_ms 为本次事件表/索引准备耗时;
match_index_ms 是其中的匹配索引构建耗时;apply_ms 为音频线程应用耗时,未包含日志写入;
retained/stopped 为声道数量。prepare_ms 不包含此前 CanTransferSchedule 或谱面加载,
也不包含调度队列等待,因此不能作为完整切换延迟或实际音频首声时间。
实机测试:同曲播放中跨难度切换并往返,重点观察长自动音/KS 的延续、暂停后切换再恢复, 以及切换后进游玩无重复键音;发现问题时可恢复上述 DLL 或代码基线。
自动验证:62 项音频/预览/回放输入过滤测试通过;语义分层检查零编译错误、零违规、零过期例外。测试版已安装,部署记录在 .artifacts/preview-transfer-baseline/test-installation.json,实际听感与耗时尚待客户端反馈。
共同声道截断已获得用户初步确认。针对目标难度中仍覆盖当前位置的历史 KS,新增原生 SampleStore 时长查询与 TrackStore 中途补播,分批异步准备,不暂停已有预览等待历史采样。 预览 seek 同样使用该路径;本节的第一阶段未包含 Gameplay/Replay 补播。 冷缓存仍有后台解码及缓存成本,不能承诺完全没有局部音层等待。设计、边界与验收清单见 预览采样补播。
回放通过原生 NewResult/RevertResult 重建有效命中历史,等待帧稳定时钟追上目标位置后, 复用原生 TrackStore/Track.Seek 恢复仍在播放区间的采样。漏判不补播,同一 KS 使用最后 一次有效命中;后续新命中会替换补播声部。实时游玩不启用此历史恢复入口,现有 OJM 映射与零采样处理保持原路径。详细边界及听感验收见回放采样补播。
本轮 85 项音频、游玩与回放定向回归通过,语义分层检查无编译错误、违规或过期例外。 用户确认后台音量及回放跳转表现正常;预览曾报告的切换间断采用有界声部衔接,不能 将这些有界反馈扩展为全部谱面与音频设备的保证。测试版已安装;正式构建排除本地测试桥。
R03 的 OJM 字节预算负责格式输入和 archive 所持载荷,
不进入本层计量原生 PCM。O2JamArchiveResourceStore.Get 保留独立数组副本,
GetStream 保留原有 readonly MemoryStream。SampleStore 用自己的工厂共享
同一采样的解码结果,TrackStore 通过原生 TrackBass 流式解码;自动采样的
512 KiB 分流门槛和可演奏 KS 的原生 Sample 行为不变。
已核对本地参考源码及当前 Framework 2026.921.1 的接口和关键 IL。参考仓库
9bb017b(2026-08-24)早于安装包声明的 37c3e328,不将其当作完全相同版本;
实际 DLL 元数据/IL 在 .artifacts/ojm-lazy-budget-20261013/results/ 留存,只读
解析;检查器不加载/执行该 DLL,也不改动参考 checkout。宿主回归仍按
正常测试进程使用原生 Framework,不能把只读检查范围扩大为全部测试。
当前路径的结论:SampleBassFactory 用 Bass.SampleLoad 建立采样,普通完成后 释放其编码数组;原生未初始化时可保留数组供设备恢复。其 NativeMemoryTracker 登记的是输入数组长度,不是 PCM 字节。工厂 Dispose 用原生 SampleFree, TrackBass Dispose 释放原生流和输入 Stream;Skin 的播放租约及 Host 的在途 准备关闭边界继续保证资源不会在活跃声音/原生准备完成前被提前销毁。
所用 ISampleStore/ISample/ITrackStore 没有解码前 PCM 配额入口;Sample.Length 需要原生准备后才可用。事后依据时长拒绝无法避免此前分配;以压缩字节或 NativeMemoryTracker 猜测也不准确。本轮不新增私有工厂补丁、自写解码、整曲 额外预解码或在流关闭时误归还 archive 配额。原生编码/PCM 副本、变速缓冲、 多个 Skin/store/活跃资源和其他 ruleset 的占用仍不是本 ruleset 的全局上限。
格式预算与本层四槽/流式/释放的保护目标不同。完整资源风险明确保留,未来有 有效高膨胀实例或宿主可用的预分配接口时再针对设计;不能为了关闭清单而添加 会让正常声音静音、影响设备恢复或首音等待的配额。212 项格式/153 项宿主 过滤回归通过,正式构建无桥/探针;没有本轮 benchmark 或新客户端听感验收。
R08 的 KS、短自动音、流式 BGM 原生对象和 BASS Volume 检查已补齐;新增 21 项、相关 174 项过滤回归通过,生产路由无改动。Master/Music/后台调整 生效,Effect 和命中音开关不静音音乐层,后台创建与暂停恢复不回跳前台增益。 普通效果音的 native store 对照保留。范围、夹具、失败修正和剩余听感/设备 边界统一见音频增益验证,不在本页重复整个矩阵。