From 352b352b27ecf0d4aba013cff1e0f45cb3a0384d Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Thu, 16 May 2024 00:27:20 +0100 Subject: [PATCH] Properly implement delay and envelopes --- tracker/agb-tracker/src/lib.rs | 7 ++++--- tracker/agb-xm-core/src/lib.rs | 34 ++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/tracker/agb-tracker/src/lib.rs b/tracker/agb-tracker/src/lib.rs index 9e1b55ab..ba5570f3 100644 --- a/tracker/agb-tracker/src/lib.rs +++ b/tracker/agb-tracker/src/lib.rs @@ -406,11 +406,12 @@ impl TrackerChannel { } } PatternEffect::NoteDelay(wait) => { - if tick <= *wait { - channel.volume(0); + if tick < *wait { + channel.pause(); } - if tick == *wait + 1 { + if tick == *wait { + channel.resume(); channel.volume((self.volume * global_settings.volume).try_change_base().unwrap()); } } diff --git a/tracker/agb-xm-core/src/lib.rs b/tracker/agb-xm-core/src/lib.rs index ce224809..5181ca80 100644 --- a/tracker/agb-xm-core/src/lib.rs +++ b/tracker/agb-xm-core/src/lib.rs @@ -524,33 +524,41 @@ impl EnvelopeData { fn new(e: &xmrs::envelope::Envelope, bpm: u32) -> Self { let mut amounts = vec![]; - // FT2 manual says number of ticks / second = BPM * 0.4 = BPM * 4 / 10. GBA runs at 60Hz - for frame in 0..(e.point.last().unwrap().frame as u32 * 60 * 10 / bpm / 4) { - let xm_frame = frame * bpm * 4 / 60 / 10; + for frame in 0..=(Self::envelope_frame_to_gba_frame(e.point.last().unwrap().frame, bpm)) { + let xm_frame = Self::gba_frame_to_envelope_frame(frame, bpm); let index = e .point .iter() - .rposition(|point| point.frame < xm_frame as u16) + .rposition(|point| point.frame < xm_frame) .unwrap_or(0); let first_point = &e.point[index]; let second_point = &e.point[index + 1]; - let amount = EnvelopePoint::lerp(first_point, second_point, xm_frame as u16) / 64.0; + let amount = EnvelopePoint::lerp(first_point, second_point, xm_frame) / 64.0; let amount = Num::from_f32(amount); amounts.push(amount); } let sustain = if e.sustain_enabled { - Some(e.point[e.sustain_point as usize].frame as usize * 60 / 50) + Some( + Self::envelope_frame_to_gba_frame(e.point[e.sustain_point as usize].frame, bpm) + as usize, + ) } else { None }; let (loop_start, loop_end) = if e.loop_enabled { ( - Some(e.point[e.loop_start_point as usize].frame as usize * 60 / 50), - Some(e.point[e.loop_end_point as usize].frame as usize * 60 / 50), + Some(Self::envelope_frame_to_gba_frame( + e.point[e.loop_start_point as usize].frame, + bpm, + ) as usize), + Some(Self::envelope_frame_to_gba_frame( + e.point[e.loop_end_point as usize].frame, + bpm, + ) as usize), ) } else { (None, None) @@ -563,4 +571,14 @@ impl EnvelopeData { loop_end, } } + + fn envelope_frame_to_gba_frame(envelope_frame: u16, bpm: u32) -> u16 { + // FT2 manual says number of ticks / second = BPM * 0.4 + // somehow this works as a good approximation :/ + (envelope_frame as u32 * 250 / bpm) as u16 + } + + fn gba_frame_to_envelope_frame(gba_frame: u16, bpm: u32) -> u16 { + (gba_frame as u32 * bpm / 250) as u16 + } }