mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Retrigger with volume
This commit is contained in:
parent
48f7020f2c
commit
fee2575cb7
|
@ -39,6 +39,14 @@ pub enum Jump {
|
|||
Combined { pattern: u8, row: u8 },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RetriggerVolumeChange {
|
||||
/// Decrease the volume by one each retrigger
|
||||
DecreaseByOne,
|
||||
/// Don't change it
|
||||
NoChange,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Pattern {
|
||||
pub length: usize,
|
||||
|
@ -94,7 +102,8 @@ pub enum PatternEffect {
|
|||
PitchBend(Num<u32, 8>),
|
||||
Jump(Jump),
|
||||
SampleOffset(u16),
|
||||
Retrigger(u8),
|
||||
/// Retrigger the note every u8 ticks with the volume change specified
|
||||
Retrigger(RetriggerVolumeChange, u8),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -130,6 +139,22 @@ impl quote::ToTokens for Jump {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "quote")]
|
||||
impl quote::ToTokens for RetriggerVolumeChange {
|
||||
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||
use quote::{quote, TokenStreamExt};
|
||||
|
||||
let type_bit = match self {
|
||||
RetriggerVolumeChange::DecreaseByOne => quote!(DecreaseByOne),
|
||||
RetriggerVolumeChange::NoChange => quote!(NoChange),
|
||||
};
|
||||
|
||||
tokens.append_all(quote! {
|
||||
agb_tracker::__private::agb_tracker_interop::RetriggerVolumeChange::#type_bit
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "quote")]
|
||||
impl quote::ToTokens for Track {
|
||||
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||
|
@ -404,7 +429,9 @@ impl quote::ToTokens for PatternEffect {
|
|||
quote! { Jump(#jump) }
|
||||
}
|
||||
PatternEffect::SampleOffset(offset) => quote! { SampleOffset(#offset) },
|
||||
PatternEffect::Retrigger(ticks) => quote! { Retrigger(#ticks) },
|
||||
PatternEffect::Retrigger(retrigger_volume_change, ticks) => {
|
||||
quote! { Retrigger(#retrigger_volume_change, #ticks) }
|
||||
}
|
||||
};
|
||||
|
||||
tokens.append_all(quote! {
|
||||
|
|
|
@ -613,8 +613,18 @@ impl TrackerChannel {
|
|||
self.current_pos = Some(*offset);
|
||||
}
|
||||
}
|
||||
PatternEffect::Retrigger(ticks) => {
|
||||
PatternEffect::Retrigger(volume_change, ticks) => {
|
||||
if tick % *ticks as u32 == 0 {
|
||||
match volume_change {
|
||||
agb_tracker_interop::RetriggerVolumeChange::DecreaseByOne => {
|
||||
self.volume = (self.volume - Num::new(1) / 64).max(0.into());
|
||||
self.current_volume = (self.volume * global_settings.volume)
|
||||
.try_change_base()
|
||||
.unwrap();
|
||||
}
|
||||
agb_tracker_interop::RetriggerVolumeChange::NoChange => {}
|
||||
}
|
||||
|
||||
self.current_pos = Some(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use agb_fixnum::Num;
|
||||
use agb_tracker_interop::{Jump, PatternEffect, Waveform};
|
||||
use agb_tracker_interop::{Jump, PatternEffect, RetriggerVolumeChange, Waveform};
|
||||
|
||||
use xmrs::prelude::*;
|
||||
|
||||
|
@ -99,7 +99,8 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
|||
let mut effect_parameters: [u8; 255] = [0; u8::MAX as usize];
|
||||
let mut tone_portamento_directions = vec![0; module.get_num_channels()];
|
||||
let mut note_and_sample = vec![None; module.get_num_channels()];
|
||||
let mut previous_retriggers: Vec<Option<u8>> = vec![None; module.get_num_channels()];
|
||||
let mut previous_retriggers: Vec<Option<(RetriggerVolumeChange, u8)>> =
|
||||
vec![None; module.get_num_channels()];
|
||||
|
||||
for row in pattern.iter() {
|
||||
// the combined jump for each row
|
||||
|
@ -411,7 +412,7 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
|||
0x9 => {
|
||||
let retrigger_amount = slot.effect_parameter & 0xf;
|
||||
let modified_amount = if retrigger_amount == 0 {
|
||||
if let Some(previous_retrigger) =
|
||||
if let Some((_, previous_retrigger)) =
|
||||
previous_retriggers[channel_number]
|
||||
{
|
||||
previous_retrigger
|
||||
|
@ -419,11 +420,15 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
|||
1
|
||||
}
|
||||
} else {
|
||||
previous_retriggers[channel_number] = Some(retrigger_amount);
|
||||
previous_retriggers[channel_number] =
|
||||
Some((RetriggerVolumeChange::NoChange, retrigger_amount));
|
||||
retrigger_amount
|
||||
};
|
||||
|
||||
PatternEffect::Retrigger(modified_amount)
|
||||
PatternEffect::Retrigger(
|
||||
RetriggerVolumeChange::NoChange,
|
||||
modified_amount,
|
||||
)
|
||||
}
|
||||
0xA => PatternEffect::FineVolumeSlide(
|
||||
Num::new((slot.effect_parameter & 0xf) as i16) / 128,
|
||||
|
@ -465,22 +470,32 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
|||
let first = effect_parameter >> 4;
|
||||
let second = effect_parameter & 0xF;
|
||||
|
||||
if first != 0 {
|
||||
let previous_retrigger = &mut previous_retriggers[channel_number];
|
||||
let volume_type = match first {
|
||||
0 => previous_retrigger
|
||||
.map(|retrigger| retrigger.0)
|
||||
.unwrap_or(RetriggerVolumeChange::NoChange),
|
||||
1 => RetriggerVolumeChange::DecreaseByOne,
|
||||
8 => RetriggerVolumeChange::NoChange,
|
||||
_ => {
|
||||
eprintln!("Unsupported retrigger effect volume {first}");
|
||||
RetriggerVolumeChange::NoChange
|
||||
}
|
||||
};
|
||||
|
||||
let ticks_between_retriggers = if second == 0 {
|
||||
if let Some(previous_retrigger) = previous_retriggers[channel_number] {
|
||||
previous_retrigger
|
||||
if let Some((_, previous_retrigger)) = previous_retrigger {
|
||||
*previous_retrigger
|
||||
} else {
|
||||
1
|
||||
}
|
||||
} else {
|
||||
previous_retriggers[channel_number] = Some(second);
|
||||
second
|
||||
};
|
||||
|
||||
PatternEffect::Retrigger(ticks_between_retriggers)
|
||||
*previous_retrigger = Some((volume_type, ticks_between_retriggers));
|
||||
|
||||
PatternEffect::Retrigger(volume_type, ticks_between_retriggers)
|
||||
}
|
||||
e => {
|
||||
let effect_char = char::from_digit(e as u32, 36)
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue