diff --git a/tracker/agb-tracker-interop/src/lib.rs b/tracker/agb-tracker-interop/src/lib.rs index f31509c0..eee21c00 100644 --- a/tracker/agb-tracker-interop/src/lib.rs +++ b/tracker/agb-tracker-interop/src/lib.rs @@ -93,6 +93,7 @@ pub enum PatternEffect { /// Increase / decrease the pitch by the specified amount immediately PitchBend(Num), Jump(Jump), + SampleOffset(u16), } #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] @@ -401,6 +402,7 @@ impl quote::ToTokens for PatternEffect { PatternEffect::Jump(jump) => { quote! { Jump(#jump) } } + PatternEffect::SampleOffset(offset) => quote! { SampleOffset(#offset) }, }; tokens.append_all(quote! { diff --git a/tracker/agb-tracker/src/lib.rs b/tracker/agb-tracker/src/lib.rs index 9edd20fa..527766bf 100644 --- a/tracker/agb-tracker/src/lib.rs +++ b/tracker/agb-tracker/src/lib.rs @@ -126,6 +126,9 @@ struct TrackerChannel { current_speed: Num, current_panning: Num, is_playing: bool, + + // if some, should set the current position to this + current_pos: Option, } #[derive(Default)] @@ -337,6 +340,10 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> { channel.volume(tracker_channel.current_volume.try_change_base().unwrap()); channel.panning(tracker_channel.current_panning.try_change_base().unwrap()); + if let Some(offset) = tracker_channel.current_pos.take() { + channel.set_pos(offset as u32); + } + if tracker_channel.is_playing { channel.resume(); } else { @@ -601,6 +608,11 @@ impl TrackerChannel { PatternEffect::Jump(jump) => { *current_jump = Some(jump.clone()); } + PatternEffect::SampleOffset(offset) => { + if tick == 0 { + self.current_pos = Some(*offset); + } + } } } @@ -677,6 +689,10 @@ impl SoundChannel for agb::sound::mixer::SoundChannel { fn panning(&mut self, panning: impl Into>) -> &mut Self { self.panning(panning) } + + fn set_pos(&mut self, pos: impl Into>) -> &mut Self { + self.set_pos(pos) + } } #[cfg(feature = "agb")] diff --git a/tracker/agb-tracker/src/mixer.rs b/tracker/agb-tracker/src/mixer.rs index 110627e9..dcb1cc60 100644 --- a/tracker/agb-tracker/src/mixer.rs +++ b/tracker/agb-tracker/src/mixer.rs @@ -17,6 +17,8 @@ pub trait SoundChannel { fn restart_point(&mut self, value: impl Into>) -> &mut Self; fn playback(&mut self, playback_speed: impl Into>) -> &mut Self; fn panning(&mut self, panning: impl Into>) -> &mut Self; + + fn set_pos(&mut self, pos: impl Into>) -> &mut Self; } pub trait Mixer { diff --git a/tracker/agb-xm-core/src/lib.rs b/tracker/agb-xm-core/src/lib.rs index 8b5d1aab..018aa540 100644 --- a/tracker/agb-xm-core/src/lib.rs +++ b/tracker/agb-xm-core/src/lib.rs @@ -324,6 +324,7 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track { ) } } + 0x9 => PatternEffect::SampleOffset(effect_parameter as u16 * 256), 0xB => { let pattern_idx = slot.effect_parameter; diff --git a/tracker/desktop-player/src/mixer.rs b/tracker/desktop-player/src/mixer.rs index 990e56e9..69a928fd 100644 --- a/tracker/desktop-player/src/mixer.rs +++ b/tracker/desktop-player/src/mixer.rs @@ -171,6 +171,11 @@ impl agb_tracker::SoundChannel for SoundChannel { self.panning = panning.into(); self } + + fn set_pos(&mut self, pos: impl Into>) -> &mut Self { + self.pos = pos.into(); + self + } } impl agb_tracker::Mixer for Mixer { diff --git a/tracker/desktop-player/tests/delay.xm b/tracker/desktop-player/tests/delay.xm new file mode 100644 index 00000000..a41345a3 Binary files /dev/null and b/tracker/desktop-player/tests/delay.xm differ