babalae/better-genshin-impact · error · FormatException
BPM 和音符时值必须大于 0
Error message
BPM 和音符时值必须大于 0
What it means
A FormatException from GetNoteDuration guarding against non-positive BPM or note denominator. The duration formula 60000/bpm*beatDenominator/noteDenominator requires both inputs strictly positive to avoid division by zero or negative durations. This is a downstream precondition failure, usually caused by bad upstream values rather than user input directly.
Source
Thrown at BetterGenshinImpact/GameTask/Music/Service/MusicScoreParser.cs:655
previousDown[item.Key] = item.Time;
}
else
{
previousUpIndex[item.Key] = i;
}
}
return events
.OrderBy(x => x.Time)
.ThenBy(x => x.Type == PerformanceEventType.KeyUp ? 0 : 1)
.ToList();
}
private static TimeSpan GetNoteDuration(double bpm, int beatDenominator, double noteDenominator)
{
if (bpm <= 0 || noteDenominator <= 0)
{
throw new FormatException("BPM 和音符时值必须大于 0");
}
return TimeSpan.FromMilliseconds(60000d / bpm * beatDenominator / noteDenominator);
}
private static int ParseBeatDenominator(string timeSignature)
{
var parts = timeSignature.Split('/');
return parts.Length == 2 && int.TryParse(parts[1], out var denominator) && denominator > 0
? denominator
: 4;
}
private static TimeSpan ToTimeSpan(MetricTimeSpan time)
{
return TimeSpan.FromMicroseconds(time.TotalMicroseconds);
}
View on GitHub (pinned to a7cb36712d)
Solutions
- Ensure the score's "bpm" field is a positive number (e.g. 120).
- Ensure every note denominator is positive.
- Validate bpm and denominators at the ParseJsonAsync entry before dispatching to timeline builders.
- Route through ParseAsync so the file is reported as InvalidScore.Error.
Example fix
// before
{"bpm":0,"notes":[...]}
// after
{"bpm":120,"notes":[...]} Defensive patterns
Strategy: validation
Validate before calling
static bool PositiveBpmAndNotes(double bpm, IEnumerable<double> denominators)
=> bpm > 0 && denominators.All(d => d > 0); Type guard
static bool IsValidBpm(double bpm) => bpm > 0;
Try / catch
var score = await parser.ParseAsync(path, root, ct);
if (!string.IsNullOrEmpty(score.Error)) { Log.Warning(score.Error); continue; } Prevention
- Ensure the score's bpm and every note denominator are positive.
- Validate at ParseJsonAsync entry before dispatching to timeline builders.
- Use ParseAsync for graceful InvalidScore handling.
When it happens
Trigger: GetNoteDuration is called with bpm <= 0 or noteDenominator <= 0. This happens when a score's bpm field is missing/zero/non-positive, or a note's denominator parsed as <= 0.
Common situations: A yuanqin score with bpm set to 0 or a negative value; a note with a fractional type that rounds to <= 0; upstream GetDouble returning its fallback only when the value is non-positive, but a direct caller bypassing that guard.
Related errors
- yuanqin 音符对象缺少 note 字段
- 无法解析音符 {keys} 的时值
- 无法解析 MIDI JSON 变速标记:{rawPart}
- 无法解析 MIDI JSON 事件:{rawPart}
- 键谱出现不匹配的括号:{current}
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/b7d0ec8633a763a6.
Report an issue: GitHub.