diff --git a/tracker/agb-tracker-interop/src/lib.rs b/tracker/agb-tracker-interop/src/lib.rs index d2c92533..ba7aa5f5 100644 --- a/tracker/agb-tracker-interop/src/lib.rs +++ b/tracker/agb-tracker-interop/src/lib.rs @@ -49,6 +49,7 @@ pub enum PatternEffect { Volume(Num), VolumeSlide(Num), NoteCut(u32), + Portamento(Num), } #[cfg(feature = "quote")] @@ -204,6 +205,10 @@ impl quote::ToTokens for PatternEffect { quote! { VolumeSlide(agb_tracker::__private::Num::from_raw(#amount))} } PatternEffect::NoteCut(wait) => quote! { NoteCut(#wait) }, + PatternEffect::Portamento(amount) => { + let amount = amount.to_raw(); + quote! { Portamento(agb_tracker::__private::Num::from_raw(#amount))} + } }; tokens.append_all(quote! { diff --git a/tracker/agb-tracker/src/lib.rs b/tracker/agb-tracker/src/lib.rs index 79875f2b..8a31fa69 100644 --- a/tracker/agb-tracker/src/lib.rs +++ b/tracker/agb-tracker/src/lib.rs @@ -61,7 +61,7 @@ impl Tracker { tick: 0, current_row: 0, - current_pattern: 0, + current_pattern: 31, } } @@ -78,7 +78,7 @@ impl Tracker { let pattern_slots = &self.track.pattern_data[pattern_data_pos..pattern_data_pos + self.track.num_channels]; - for (channel, pattern_slot) in self.channels.iter_mut().zip(pattern_slots) { + for (channel, pattern_slot) in self.channels.iter_mut().zip(pattern_slots).skip(3) { if pattern_slot.sample != 0 && self.tick == 0 { let sample = &self.track.samples[pattern_slot.sample as usize - 1]; channel.play_sound(mixer, sample); @@ -214,6 +214,12 @@ impl TrackerChannel { self.volume = 0.into(); } } + PatternEffect::Portamento(amount) => { + if tick != 0 { + self.base_speed *= amount.change_base(); + channel.playback(self.base_speed); + } + } } } } diff --git a/tracker/agb-xm-core/src/lib.rs b/tracker/agb-xm-core/src/lib.rs index dcf343a0..f33d0f95 100644 --- a/tracker/agb-xm-core/src/lib.rs +++ b/tracker/agb-xm-core/src/lib.rs @@ -197,6 +197,32 @@ pub fn parse_module(module: &Module) -> TokenStream { PatternEffect::None } } + 0x1 => { + let c4_speed = note_to_speed(Note::C4, 0.0, 0, module.frequency_type); + let speed = note_to_speed( + Note::C4, + slot.effect_parameter as f64, + 0, + module.frequency_type, + ); + + let portamento_amount = speed / c4_speed; + + PatternEffect::Portamento(portamento_amount.try_change_base().unwrap()) + } + 0x2 => { + let c4_speed = note_to_speed(Note::C4, 0.0, 0, module.frequency_type); + let speed = note_to_speed( + Note::C4, + -(slot.effect_parameter as f64), + 0, + module.frequency_type, + ); + + let portamento_amount = speed / c4_speed; + + PatternEffect::Portamento(portamento_amount.try_change_base().unwrap()) + } 0x8 => { PatternEffect::Panning(Num::new(slot.effect_parameter as i16 - 128) / 128) }