diff --git a/tracker/agb-tracker-interop/src/lib.rs b/tracker/agb-tracker-interop/src/lib.rs index cf655e05..54cc4758 100644 --- a/tracker/agb-tracker-interop/src/lib.rs +++ b/tracker/agb-tracker-interop/src/lib.rs @@ -8,6 +8,7 @@ pub struct Track<'a> { pub pattern_data: &'a [PatternSlot], pub patterns: &'a [Pattern], + pub num_channels: usize, pub frames_per_step: u16, } @@ -19,7 +20,6 @@ pub struct Sample<'a> { #[derive(Debug)] pub struct Pattern { - pub num_channels: usize, pub length: usize, pub start_position: usize, } @@ -42,6 +42,7 @@ impl<'a> quote::ToTokens for Track<'a> { pattern_data, patterns, frames_per_step, + num_channels, } = self; tokens.append_all(quote! { @@ -58,6 +59,7 @@ impl<'a> quote::ToTokens for Track<'a> { patterns: PATTERNS, frames_per_step: #frames_per_step, + num_channels: #num_channels, } } }) @@ -136,7 +138,6 @@ impl quote::ToTokens for Pattern { use quote::{quote, TokenStreamExt}; let Pattern { - num_channels, length, start_position, } = self; @@ -146,7 +147,6 @@ impl quote::ToTokens for Pattern { use agb_tracker_interop::*; Pattern { - num_channels: #num_channels, length: #length, start_position: #start_position, } diff --git a/tracker/agb-tracker/examples/basic.rs b/tracker/agb-tracker/examples/basic.rs index 2581f1e0..2913a4d0 100644 --- a/tracker/agb-tracker/examples/basic.rs +++ b/tracker/agb-tracker/examples/basic.rs @@ -5,7 +5,7 @@ use agb::sound::mixer::Frequency; use agb::Gba; use agb_tracker::{import_xm, Track, Tracker}; -const AJOJ: Track = import_xm!("examples/ajoj.xm"); +const AJOJ: Track = import_xm!("examples/db_toffe.xm"); #[agb::entry] fn main(mut gba: Gba) -> ! { diff --git a/tracker/agb-tracker/examples/db_toffe.xm b/tracker/agb-tracker/examples/db_toffe.xm new file mode 100644 index 00000000..b2b22a10 Binary files /dev/null and b/tracker/agb-tracker/examples/db_toffe.xm differ diff --git a/tracker/agb-tracker/examples/final_countdown.xm b/tracker/agb-tracker/examples/final_countdown.xm new file mode 100644 index 00000000..51031553 Binary files /dev/null and b/tracker/agb-tracker/examples/final_countdown.xm differ diff --git a/tracker/agb-tracker/src/lib.rs b/tracker/agb-tracker/src/lib.rs index f7bbc700..066bd00d 100644 --- a/tracker/agb-tracker/src/lib.rs +++ b/tracker/agb-tracker/src/lib.rs @@ -7,7 +7,7 @@ extern crate alloc; -use alloc::{vec, vec::Vec}; +use alloc::vec::Vec; use agb::sound::mixer::{ChannelId, Mixer, SoundChannel}; @@ -29,11 +29,12 @@ pub struct Tracker { impl Tracker { pub fn new(track: &'static Track<'static>) -> Self { - agb::println!("{}", track.frames_per_step); + let mut channels = Vec::new(); + channels.resize_with(track.num_channels, || None); Self { track, - channels: vec![], + channels, step: 0, current_row: 0, @@ -49,16 +50,21 @@ impl Tracker { let current_pattern = &self.track.patterns[self.current_pattern]; - let channels_to_play = current_pattern.num_channels; - self.channels.resize_with(channels_to_play, || None); - - let pattern_data_pos = current_pattern.start_position + self.current_row * channels_to_play; + let pattern_data_pos = + current_pattern.start_position + self.current_row * self.track.num_channels; let pattern_slots = - &self.track.pattern_data[pattern_data_pos..pattern_data_pos + channels_to_play]; + &self.track.pattern_data[pattern_data_pos..pattern_data_pos + self.track.num_channels]; for (channel_id, pattern_slot) in self.channels.iter_mut().zip(pattern_slots) { if pattern_slot.sample == 0 { - // do nothing + if pattern_slot.speed == 0.into() { + if let Some(channel) = channel_id + .take() + .and_then(|channel_id| mixer.channel(&channel_id)) + { + channel.stop(); + } + } } else { if let Some(channel) = channel_id .take() diff --git a/tracker/agb-xm-core/src/lib.rs b/tracker/agb-xm-core/src/lib.rs index ca643010..b701080c 100644 --- a/tracker/agb-xm-core/src/lib.rs +++ b/tracker/agb-xm-core/src/lib.rs @@ -99,7 +99,6 @@ pub fn parse_module(module: &Module) -> TokenStream { let mut pattern_data = vec![]; for pattern in &module.pattern { - let mut num_channels = 0; let start_pos = pattern_data.len(); for row in pattern.iter() { @@ -122,19 +121,21 @@ pub fn parse_module(module: &Module) -> TokenStream { } }; - let volume = Num::new( - if slot.volume == 0 { - 64 - } else { - slot.volume as i16 - } / 64, - ); + let volume = Num::new(if slot.volume == 0 { + 64 + } else { + slot.volume as i16 + }) / 64; if sample == 0 { // TODO should take into account previous sample played on this channel pattern_data.push(agb_tracker_interop::PatternSlot { volume: Num::new(0), - speed: Num::new(0), + speed: if matches!(slot.note, Note::KeyOff) { + 0.into() + } else { + note_to_speed(slot.note, 0.0, 0) + }, panning: Num::new(0), sample: 0, }) @@ -156,12 +157,9 @@ pub fn parse_module(module: &Module) -> TokenStream { }); } } - - num_channels = row.len(); } patterns.push(agb_tracker_interop::Pattern { - num_channels, length: pattern.len(), start_position: start_pos, }); @@ -175,15 +173,13 @@ pub fn parse_module(module: &Module) -> TokenStream { }) .collect(); - let frames_per_step = - ((60.0 * 60.0) / module.default_bpm as f64 / module.default_tempo as f64) as u16; - let interop = agb_tracker_interop::Track { samples: &samples, pattern_data: &pattern_data, patterns: &patterns, + num_channels: module.get_num_channels(), - frames_per_step, + frames_per_step: 2, // TODO calculate this correctly }; quote!(#interop) diff --git a/tracker/agb-xm-core/src/main.rs b/tracker/agb-xm-core/src/main.rs index 2e2ba88f..026485eb 100644 --- a/tracker/agb-xm-core/src/main.rs +++ b/tracker/agb-xm-core/src/main.rs @@ -1,6 +1,6 @@ fn main() -> Result<(), Box> { let module = agb_xm_core::load_module_from_file(&std::path::Path::new( - "../agb-tracker/examples/ajoj.xm", + "../agb-tracker/examples/final_countdown.xm", ))?; let output = agb_xm_core::parse_module(&module);