From 0ede26f5bcb98b3ef7b28baee3a436cd86483158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Mittelst=C3=A4dt?= <62167861+TheGalitube@users.noreply.github.com> Date: Thu, 29 Oct 2026 09:05:48 +0000 Subject: [PATCH] Clamp the minimum beat before conversion Found while testing crates/time/src/tempo.rs:304 Co-Authored-By: GPT-6-Luna --- crates/time/src/tempo.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/time/src/tempo.rs b/crates/time/src/tempo.rs index 6aaa50b8..46c05064 100644 --- a/crates/time/src/tempo.rs +++ b/crates/time/src/tempo.rs @@ -301,7 +301,7 @@ impl TempoMap { pub fn tick_at_bar_beat(&self, bb: BarBeat) -> i64 { let start = self.bar_start_tick(bb.bar); let m = self.meter_at_tick(start); - start.saturating_add((bb.beat - 1).max(0).saturating_mul(m.ticks_per_beat())).saturating_add(bb.tick) + start.saturating_add(bb.beat.saturating_sub(1).max(0).saturating_mul(m.ticks_per_beat())).saturating_add(bb.tick) } pub fn bar_beat_at(&self, s: Samples, sr: SampleRate) -> BarBeat { @@ -344,6 +344,12 @@ mod tests { assert_eq!(m.bar_start_tick(0), -TICKS_PER_QUARTER * 4); } + #[test] + fn minimum_beat_is_clamped_without_overflow() { + let m = TempoMap::default(); + assert_eq!(m.tick_at_bar_beat(BarBeat { bar: 1, beat: i64::MIN, tick: 0 }), 0); + } + #[test] fn bar_beat_at_min_tick_does_not_overflow() { let m = TempoMap::default();