Get closer to some reasonable sounding

This commit is contained in:
Gwilym Inzani 2023-07-12 18:52:29 +01:00
parent 308cb3a19c
commit 436b49c80d
7 changed files with 32 additions and 30 deletions

View file

@ -8,6 +8,7 @@ pub struct Track<'a> {
pub pattern_data: &'a [PatternSlot], pub pattern_data: &'a [PatternSlot],
pub patterns: &'a [Pattern], pub patterns: &'a [Pattern],
pub num_channels: usize,
pub frames_per_step: u16, pub frames_per_step: u16,
} }
@ -19,7 +20,6 @@ pub struct Sample<'a> {
#[derive(Debug)] #[derive(Debug)]
pub struct Pattern { pub struct Pattern {
pub num_channels: usize,
pub length: usize, pub length: usize,
pub start_position: usize, pub start_position: usize,
} }
@ -42,6 +42,7 @@ impl<'a> quote::ToTokens for Track<'a> {
pattern_data, pattern_data,
patterns, patterns,
frames_per_step, frames_per_step,
num_channels,
} = self; } = self;
tokens.append_all(quote! { tokens.append_all(quote! {
@ -58,6 +59,7 @@ impl<'a> quote::ToTokens for Track<'a> {
patterns: PATTERNS, patterns: PATTERNS,
frames_per_step: #frames_per_step, frames_per_step: #frames_per_step,
num_channels: #num_channels,
} }
} }
}) })
@ -136,7 +138,6 @@ impl quote::ToTokens for Pattern {
use quote::{quote, TokenStreamExt}; use quote::{quote, TokenStreamExt};
let Pattern { let Pattern {
num_channels,
length, length,
start_position, start_position,
} = self; } = self;
@ -146,7 +147,6 @@ impl quote::ToTokens for Pattern {
use agb_tracker_interop::*; use agb_tracker_interop::*;
Pattern { Pattern {
num_channels: #num_channels,
length: #length, length: #length,
start_position: #start_position, start_position: #start_position,
} }

View file

@ -5,7 +5,7 @@ use agb::sound::mixer::Frequency;
use agb::Gba; use agb::Gba;
use agb_tracker::{import_xm, Track, Tracker}; 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] #[agb::entry]
fn main(mut gba: Gba) -> ! { fn main(mut gba: Gba) -> ! {

Binary file not shown.

Binary file not shown.

View file

@ -7,7 +7,7 @@
extern crate alloc; extern crate alloc;
use alloc::{vec, vec::Vec}; use alloc::vec::Vec;
use agb::sound::mixer::{ChannelId, Mixer, SoundChannel}; use agb::sound::mixer::{ChannelId, Mixer, SoundChannel};
@ -29,11 +29,12 @@ pub struct Tracker {
impl Tracker { impl Tracker {
pub fn new(track: &'static Track<'static>) -> Self { 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 { Self {
track, track,
channels: vec![], channels,
step: 0, step: 0,
current_row: 0, current_row: 0,
@ -49,16 +50,21 @@ impl Tracker {
let current_pattern = &self.track.patterns[self.current_pattern]; let current_pattern = &self.track.patterns[self.current_pattern];
let channels_to_play = current_pattern.num_channels; let pattern_data_pos =
self.channels.resize_with(channels_to_play, || None); current_pattern.start_position + self.current_row * self.track.num_channels;
let pattern_data_pos = current_pattern.start_position + self.current_row * channels_to_play;
let pattern_slots = 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) { for (channel_id, pattern_slot) in self.channels.iter_mut().zip(pattern_slots) {
if pattern_slot.sample == 0 { 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 { } else {
if let Some(channel) = channel_id if let Some(channel) = channel_id
.take() .take()

View file

@ -99,7 +99,6 @@ pub fn parse_module(module: &Module) -> TokenStream {
let mut pattern_data = vec![]; let mut pattern_data = vec![];
for pattern in &module.pattern { for pattern in &module.pattern {
let mut num_channels = 0;
let start_pos = pattern_data.len(); let start_pos = pattern_data.len();
for row in pattern.iter() { for row in pattern.iter() {
@ -122,19 +121,21 @@ pub fn parse_module(module: &Module) -> TokenStream {
} }
}; };
let volume = Num::new( let volume = Num::new(if slot.volume == 0 {
if slot.volume == 0 {
64 64
} else { } else {
slot.volume as i16 slot.volume as i16
} / 64, }) / 64;
);
if sample == 0 { if sample == 0 {
// TODO should take into account previous sample played on this channel // TODO should take into account previous sample played on this channel
pattern_data.push(agb_tracker_interop::PatternSlot { pattern_data.push(agb_tracker_interop::PatternSlot {
volume: Num::new(0), 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), panning: Num::new(0),
sample: 0, sample: 0,
}) })
@ -156,12 +157,9 @@ pub fn parse_module(module: &Module) -> TokenStream {
}); });
} }
} }
num_channels = row.len();
} }
patterns.push(agb_tracker_interop::Pattern { patterns.push(agb_tracker_interop::Pattern {
num_channels,
length: pattern.len(), length: pattern.len(),
start_position: start_pos, start_position: start_pos,
}); });
@ -175,15 +173,13 @@ pub fn parse_module(module: &Module) -> TokenStream {
}) })
.collect(); .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 { let interop = agb_tracker_interop::Track {
samples: &samples, samples: &samples,
pattern_data: &pattern_data, pattern_data: &pattern_data,
patterns: &patterns, patterns: &patterns,
num_channels: module.get_num_channels(),
frames_per_step, frames_per_step: 2, // TODO calculate this correctly
}; };
quote!(#interop) quote!(#interop)

View file

@ -1,6 +1,6 @@
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let module = agb_xm_core::load_module_from_file(&std::path::Path::new( 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); let output = agb_xm_core::parse_module(&module);