diff --git a/tracker/agb-tracker-interop/src/lib.rs b/tracker/agb-tracker-interop/src/lib.rs index 54cc4758..73bdcbea 100644 --- a/tracker/agb-tracker-interop/src/lib.rs +++ b/tracker/agb-tracker-interop/src/lib.rs @@ -7,6 +7,7 @@ pub struct Track<'a> { pub samples: &'a [Sample<'a>], pub pattern_data: &'a [PatternSlot], pub patterns: &'a [Pattern], + pub patterns_to_play: &'a [usize], pub num_channels: usize, pub frames_per_step: u16, @@ -43,6 +44,7 @@ impl<'a> quote::ToTokens for Track<'a> { patterns, frames_per_step, num_channels, + patterns_to_play, } = self; tokens.append_all(quote! { @@ -52,11 +54,13 @@ impl<'a> quote::ToTokens for Track<'a> { const SAMPLES: &[Sample<'static>] = &[#(#samples),*]; const PATTERN_DATA: &[PatternSlot] = &[#(#pattern_data),*]; const PATTERNS: &[Pattern] = &[#(#patterns),*]; + const PATTERNS_TO_PLAY: &[usize] = &[#(#patterns_to_play),*]; Track { samples: SAMPLES, pattern_data: PATTERN_DATA, patterns: PATTERNS, + patterns_to_play: PATTERNS_TO_PLAY, frames_per_step: #frames_per_step, num_channels: #num_channels, diff --git a/tracker/agb-tracker/src/lib.rs b/tracker/agb-tracker/src/lib.rs index 066bd00d..d49963d8 100644 --- a/tracker/agb-tracker/src/lib.rs +++ b/tracker/agb-tracker/src/lib.rs @@ -48,7 +48,8 @@ impl Tracker { return; // TODO: volume / pitch slides } - let current_pattern = &self.track.patterns[self.current_pattern]; + let pattern_to_play = self.track.patterns_to_play[self.current_pattern]; + let current_pattern = &self.track.patterns[pattern_to_play]; let pattern_data_pos = current_pattern.start_position + self.current_row * self.track.num_channels; @@ -94,12 +95,18 @@ impl Tracker { fn increment_step(&mut self) { self.step += 1; - if self.step == self.track.frames_per_step * 2 { + if self.step == self.track.frames_per_step { self.current_row += 1; - if self.current_row > self.track.patterns[self.current_pattern].length { + if self.current_row + >= self.track.patterns[self.track.patterns_to_play[self.current_pattern]].length + { self.current_pattern += 1; self.current_row = 0; + + if self.current_pattern >= self.track.patterns_to_play.len() { + self.current_pattern = 0; + } } self.step = 0; diff --git a/tracker/agb-xm-core/src/lib.rs b/tracker/agb-xm-core/src/lib.rs index b701080c..3055a1d1 100644 --- a/tracker/agb-xm-core/src/lib.rs +++ b/tracker/agb-xm-core/src/lib.rs @@ -53,6 +53,7 @@ pub fn parse_module(module: &Module) -> TokenStream { should_loop: bool, fine_tune: f64, relative_note: i8, + volume: f64, } let mut samples = vec![]; @@ -64,6 +65,7 @@ pub fn parse_module(module: &Module) -> TokenStream { let should_loop = !matches!(sample.flags, LoopType::No); let fine_tune = sample.finetune as f64; let relative_note = sample.relative_note; + let volume = sample.volume as f64; let mut sample = match &sample.data { SampleDataType::Depth8(depth8) => { @@ -91,6 +93,7 @@ pub fn parse_module(module: &Module) -> TokenStream { should_loop, fine_tune, relative_note, + volume, }); } } @@ -121,11 +124,11 @@ pub fn parse_module(module: &Module) -> TokenStream { } }; - let volume = Num::new(if slot.volume == 0 { - 64 + let volume = if slot.volume == 0 { + 64.0 } else { - slot.volume as i16 - }) / 64; + slot.volume as f64 + } / 64.0; if sample == 0 { // TODO should take into account previous sample played on this channel @@ -149,6 +152,9 @@ pub fn parse_module(module: &Module) -> TokenStream { ); let panning = Num::new(0); + let overall_volume = volume * sample_played.volume; + let volume = Num::from_raw((overall_volume * (1 << 4) as f64) as i16); + pattern_data.push(agb_tracker_interop::PatternSlot { volume, speed, @@ -173,13 +179,20 @@ pub fn parse_module(module: &Module) -> TokenStream { }) .collect(); + let patterns_to_play = module + .pattern_order + .iter() + .map(|order| *order as usize) + .collect::>(); + let interop = agb_tracker_interop::Track { samples: &samples, pattern_data: &pattern_data, patterns: &patterns, num_channels: module.get_num_channels(), + patterns_to_play: &patterns_to_play, - frames_per_step: 2, // TODO calculate this correctly + frames_per_step: 4, // TODO calculate this correctly }; quote!(#interop)