Consider the global volume

This commit is contained in:
Gwilym Inzani 2023-07-18 21:36:37 +01:00
parent de085fc1ff
commit a91069eac2
3 changed files with 58 additions and 19 deletions

View file

@ -19,6 +19,7 @@ pub struct Sample<'a> {
pub data: &'a [u8], pub data: &'a [u8],
pub should_loop: bool, pub should_loop: bool,
pub restart_point: u32, pub restart_point: u32,
pub volume: Num<i16, 4>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -104,10 +105,16 @@ impl<'a> quote::ToTokens for Sample<'a> {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
use quote::{quote, TokenStreamExt}; use quote::{quote, TokenStreamExt};
let self_as_u8s: Vec<_> = self.data.iter().map(|i| *i as u8).collect(); let Sample {
data,
should_loop,
restart_point,
volume,
} = self;
let self_as_u8s: Vec<_> = data.iter().map(|i| *i as u8).collect();
let samples = ByteString(&self_as_u8s); let samples = ByteString(&self_as_u8s);
let should_loop = self.should_loop; let volume = volume.to_raw();
let restart_point = self.restart_point;
tokens.append_all(quote! { tokens.append_all(quote! {
{ {
@ -115,7 +122,12 @@ impl<'a> quote::ToTokens for Sample<'a> {
struct AlignmentWrapper<const N: usize>([u8; N]); struct AlignmentWrapper<const N: usize>([u8; N]);
const SAMPLE_DATA: &[u8] = &AlignmentWrapper(*#samples).0; const SAMPLE_DATA: &[u8] = &AlignmentWrapper(*#samples).0;
agb_tracker::__private::agb_tracker_interop::Sample { data: SAMPLE_DATA, should_loop: #should_loop, restart_point: #restart_point } agb_tracker::__private::agb_tracker_interop::Sample {
data: SAMPLE_DATA,
should_loop: #should_loop,
restart_point: #restart_point,
volume: agb_tracker::__private::Num::from_raw(#volume),
}
} }
}); });
} }

View file

@ -148,6 +148,8 @@ impl TrackerChannel {
let mut new_channel = SoundChannel::new(sample.data); let mut new_channel = SoundChannel::new(sample.data);
new_channel.volume(sample.volume);
if sample.should_loop { if sample.should_loop {
new_channel new_channel
.should_loop() .should_loop()

View file

@ -55,6 +55,7 @@ pub fn parse_module(module: &Module) -> TokenStream {
fine_tune: f64, fine_tune: f64,
relative_note: i8, relative_note: i8,
restart_point: u32, restart_point: u32,
volume: Num<i16, 4>,
} }
let mut samples = vec![]; let mut samples = vec![];
@ -73,6 +74,8 @@ pub fn parse_module(module: &Module) -> TokenStream {
usize::MAX usize::MAX
}; };
let volume = Num::from_raw((sample.volume * (1 << 4) as f32) as i16);
let sample = match &sample.data { let sample = match &sample.data {
SampleDataType::Depth8(depth8) => depth8 SampleDataType::Depth8(depth8) => depth8
.iter() .iter()
@ -93,6 +96,7 @@ pub fn parse_module(module: &Module) -> TokenStream {
fine_tune, fine_tune,
relative_note, relative_note,
restart_point, restart_point,
volume,
}); });
} }
} }
@ -127,50 +131,62 @@ pub fn parse_module(module: &Module) -> TokenStream {
} }
}; };
let mut effect1 = match slot.volume { let mut effect1 = PatternEffect::None;
0x10..=0x50 => {
PatternEffect::Volume(Num::new((slot.volume - 0x10) as i16) / 64)
}
0xC0..=0xCF => PatternEffect::Panning(
Num::new(slot.volume as i16 - (0xC0 + (0xCF - 0xC0) / 2)) / 64,
),
_ => PatternEffect::None,
};
if matches!(slot.note, Note::KeyOff) { let maybe_note_and_sample = if matches!(slot.note, Note::KeyOff) {
effect1 = PatternEffect::Stop; effect1 = PatternEffect::Stop;
note_and_sample[channel_number] = None; note_and_sample[channel_number] = None;
&None
} else if !matches!(slot.note, Note::None) { } else if !matches!(slot.note, Note::None) {
if sample != 0 { if sample != 0 {
note_and_sample[channel_number] = Some((slot.note, &samples[sample - 1])); note_and_sample[channel_number] = Some((slot.note, &samples[sample - 1]));
} else if let Some((note, _)) = &mut note_and_sample[channel_number] { } else if let Some((note, _)) = &mut note_and_sample[channel_number] {
*note = slot.note; *note = slot.note;
} }
&note_and_sample[channel_number]
} else {
&note_and_sample[channel_number]
};
if matches!(effect1, PatternEffect::None) {
effect1 = match slot.volume {
0x10..=0x50 => PatternEffect::Volume(
(Num::new((slot.volume - 0x10) as i16) / 64)
* maybe_note_and_sample
.map(|note_and_sample| note_and_sample.1.volume)
.unwrap_or(1.into()),
),
0xC0..=0xCF => PatternEffect::Panning(
Num::new(slot.volume as i16 - (0xC0 + (0xCF - 0xC0) / 2)) / 64,
),
_ => PatternEffect::None,
};
} }
let effect2 = match slot.effect_type { let effect2 = match slot.effect_type {
0x0 => { 0x0 => {
if slot.effect_parameter == 0 { if slot.effect_parameter == 0 {
PatternEffect::None PatternEffect::None
} else if let Some((note, sample)) = note_and_sample[channel_number] { } else if let Some((note, sample)) = maybe_note_and_sample {
let first_arpeggio = slot.effect_parameter >> 4; let first_arpeggio = slot.effect_parameter >> 4;
let second_arpeggio = slot.effect_parameter & 0xF; let second_arpeggio = slot.effect_parameter & 0xF;
let note_speed = note_to_speed( let note_speed = note_to_speed(
note, *note,
sample.fine_tune, sample.fine_tune,
sample.relative_note, sample.relative_note,
module.frequency_type, module.frequency_type,
); );
let first_arpeggio_speed = note_to_speed( let first_arpeggio_speed = note_to_speed(
note, *note,
sample.fine_tune, sample.fine_tune,
sample.relative_note + first_arpeggio as i8, sample.relative_note + first_arpeggio as i8,
module.frequency_type, module.frequency_type,
); );
let second_arpeggio_speed = note_to_speed( let second_arpeggio_speed = note_to_speed(
note, *note,
sample.fine_tune, sample.fine_tune,
sample.relative_note + second_arpeggio as i8, sample.relative_note + second_arpeggio as i8,
module.frequency_type, module.frequency_type,
@ -207,7 +223,15 @@ pub fn parse_module(module: &Module) -> TokenStream {
PatternEffect::VolumeSlide(Num::new(first as i16) / 16) PatternEffect::VolumeSlide(Num::new(first as i16) / 16)
} }
} }
0xC => PatternEffect::Volume(Num::new(slot.effect_parameter as i16) / 255), 0xC => {
if let Some((_, sample)) = maybe_note_and_sample {
PatternEffect::Volume(
(Num::new(slot.effect_parameter as i16) / 255) * sample.volume,
)
} else {
PatternEffect::None
}
}
_ => PatternEffect::None, _ => PatternEffect::None,
}; };
@ -250,6 +274,7 @@ pub fn parse_module(module: &Module) -> TokenStream {
data: &sample.data, data: &sample.data,
should_loop: sample.should_loop, should_loop: sample.should_loop,
restart_point: sample.restart_point, restart_point: sample.restart_point,
volume: sample.volume,
}) })
.collect(); .collect();