mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Get closer to some reasonable sounding
This commit is contained in:
parent
308cb3a19c
commit
436b49c80d
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) -> ! {
|
||||||
|
|
BIN
tracker/agb-tracker/examples/db_toffe.xm
Normal file
BIN
tracker/agb-tracker/examples/db_toffe.xm
Normal file
Binary file not shown.
BIN
tracker/agb-tracker/examples/final_countdown.xm
Normal file
BIN
tracker/agb-tracker/examples/final_countdown.xm
Normal file
Binary file not shown.
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue