异常处理
这里记录了一些可能的异常情况以及处理方式。
非法值:即 -nan(ind)
或 inf
相当于 JS 的 NaN
或 Infinity
。
事件之间的关系分析
以下内容基于版本 123
实测,不同版本可能存在差异。
预处理:自动排序
事件读取时,开始时间不同的自动按照时间从小到大排序;相同的不自动排序。
合法:相离和相切
相离和相切时,事件内正常插值,事件外采用上一个事件的结束值。
异常 1:初始时间
非速度事件:第一个事件开始时间
不为 时, ~ 区间将采用第一个事件的解析延拓。 举例:若第一个事件为正弦缓动,在该事件开始时间之前的行为将是正弦曲线。
可能计算出非法值,让线不可见。
速度事件:第一个事件开始时间
不为 时, ~ 区间将视为值为 0
的速度事件。
异常 2:重叠和包含
速度事件和非速度事件对重叠和包含的处理方式有所不同。
非速度事件:后来居上,即后事件值覆盖前事件值。
这里的覆盖准确来说是截断,即前事件在后事件开始时间之后的部分均被削除。
即使后事件结束时间比前事件小也是如此,不存在后事件结束时恢复前事件值的情况。
举例:设两相邻的
, 非速度事件的起止时间分别为 ~ , ~ ( ) 则
~ 时间仅计算 事件,不受 事件影响 时间以后仅计算 事件,不受 事件影响
速度事件:先入为主,即前事件值覆盖后事件值。
重叠部分视为负向的时间间隔“正常”计算,不会影响音符的相对位置。
举例:设两相邻的
, 速度事件的起止时间分别为 ~ , ~ ( ) 则
~ 时间仅计算 事件,不受 事件影响 时间以后既累计了完整的 事件 + 正常累计 事件,还累计了 事件结尾值对 ~ 负向“间隔”的积分。
若
事件起止值相同,可以更简单地视为累计了 ~ 的 事件 + 正常累计 事件。 在因此产生的瞬移时刻,音符位置采用前值。
根据 @点缀星空 花费了十几根头发的代价得出的结论,在此感谢 w
异常 3:起止时间
开始时间大于结束时间
非速度事件:视为起止时间均为开始时间,起止值均为结束值的瞬间事件。
速度事件:视为起止时间均为开始时间,起止值均为结束值的瞬间事件,还累计了结束值与开始值的相反数对时间负向“间隔”的积分,即
。
异常 4:缓动切割
easingLeft
等于easingRight
:可能计算出非法值。easingLeft
或easingRight
值小于0
或大于1
:可能计算出非法值。- RPE 点击该事件时将自动归位至
0
或1
- RPE 点击该事件时将自动归位至
异常 5:线不透明度
由于 RPE 的刻意设计,任何负数 alpha 都会使该线的音符完全隐藏
- 打击特效/音效在编辑页也被隐藏,但在预览页仍然正常显示/播放。
因为 alpha 为
int
类型,超过int
类型的限制将使 RPE 崩溃缓动事件结果会被取整,表现按取整结果计算。
例如
-0.999
=0
,1.999
=1
非法值会被转换为
-2147483648
。
因为 alpha 最大值
255
,超过255
表现为该值对 255 进行位与运算的结果。- 例如
256
=0
,2559
=255
- 例如
由于 RPE 编辑页自带不透明度
0.6x
(该值可在设置修改),编辑页实际还要先对结果乘以0.6
再进行位与运算。- 例如
426
=255
,4266667
=0
(仅编辑页)
- 例如
WARNING
- 注意:RPE 的 音符距离会随 bpm 变化而变化,但编辑页不会实时更新距离。