Implement vibrato correctly and add a small test case

This commit is contained in:
Gwilym Inzani 2024-07-10 14:15:04 +01:00
parent 431833b216
commit d15063373d
4 changed files with 38 additions and 16 deletions

View file

@ -62,7 +62,8 @@ pub enum PatternEffect {
Arpeggio(Num<u16, 8>, Num<u16, 8>),
Panning(Num<i16, 4>),
Volume(Num<i16, 8>),
VolumeSlide(Num<i16, 8>),
// bool = maintain vibrato?
VolumeSlide(Num<i16, 8>, bool),
FineVolumeSlide(Num<i16, 8>),
NoteCut(u32),
NoteDelay(u32),
@ -298,9 +299,9 @@ impl quote::ToTokens for PatternEffect {
let volume = volume.to_raw();
quote! { Volume(agb_tracker::__private::Num::from_raw(#volume))}
}
PatternEffect::VolumeSlide(amount) => {
PatternEffect::VolumeSlide(amount, vibrato) => {
let amount = amount.to_raw();
quote! { VolumeSlide(agb_tracker::__private::Num::from_raw(#amount))}
quote! { VolumeSlide(agb_tracker::__private::Num::from_raw(#amount), #vibrato)}
}
PatternEffect::FineVolumeSlide(amount) => {
let amount = amount.to_raw();

View file

@ -133,6 +133,8 @@ struct Waves {
frame: usize,
speed: usize,
amount: Num<i32, 12>,
enable: bool,
}
impl Waves {
@ -254,6 +256,8 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
channel.set_speed(pattern_slot.speed.change_base());
}
channel.vibrato.enable = false;
channel.apply_effect(
&pattern_slot.effect1,
self.tick,
@ -282,7 +286,7 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
{
let mut current_speed = tracker_channel.current_speed;
if tracker_channel.vibrato.speed != 0 {
if tracker_channel.vibrato.speed != 0 && tracker_channel.vibrato.enable {
current_speed *= tracker_channel.vibrato.value().change_base();
}
@ -419,13 +423,15 @@ impl TrackerChannel {
self.volume = volume.change_base();
}
PatternEffect::VolumeSlide(amount) => {
PatternEffect::VolumeSlide(amount, keep_vibrato) => {
if tick != 0 {
self.volume = (self.volume + amount.change_base()).max(0.into());
self.current_volume = (self.volume * global_settings.volume)
.try_change_base()
.unwrap();
}
self.vibrato.enable = *keep_vibrato;
}
PatternEffect::FineVolumeSlide(amount) => {
if tick == 0 {
@ -506,10 +512,17 @@ impl TrackerChannel {
(global_settings.volume + *volume_delta).clamp(0.into(), 1.into());
}
PatternEffect::Vibrato(waveform, amount, speed) => {
self.vibrato.waveform = *waveform;
if *amount != 0.into() {
self.vibrato.amount = amount.change_base();
}
if *speed != 0 {
self.vibrato.speed = *speed as usize;
}
self.vibrato.waveform = *waveform;
self.vibrato.enable = true;
}
}
}

View file

@ -147,12 +147,14 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
.map(|note_and_sample| note_and_sample.1.volume)
.unwrap_or(1.into()),
),
0x60..=0x6F => {
PatternEffect::VolumeSlide(-Num::new((slot.volume - 0x60) as i16) / 64)
}
0x70..=0x7F => {
PatternEffect::VolumeSlide(Num::new((slot.volume - 0x70) as i16) / 64)
}
0x60..=0x6F => PatternEffect::VolumeSlide(
-Num::new((slot.volume - 0x60) as i16) / 64,
false,
),
0x70..=0x7F => PatternEffect::VolumeSlide(
Num::new((slot.volume - 0x70) as i16) / 64,
false,
),
0x80..=0x8F => PatternEffect::FineVolumeSlide(
-Num::new((slot.volume - 0x80) as i16) / 128,
),
@ -283,7 +285,7 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
let c4_speed = note_to_speed(Note::C4, 0.0, 0, module.frequency_type);
let speed =
note_to_speed(Note::C4, depth as f64 * 8.0, 0, module.frequency_type);
note_to_speed(Note::C4, depth as f64 * 16.0, 0, module.frequency_type);
let amount = speed / c4_speed - 1;
@ -301,9 +303,15 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
let second = effect_parameter & 0xF;
if first == 0 {
PatternEffect::VolumeSlide(-Num::new(second as i16) / 64)
PatternEffect::VolumeSlide(
-Num::new(second as i16) / 64,
slot.effect_type == 0x6,
)
} else {
PatternEffect::VolumeSlide(Num::new(first as i16) / 64)
PatternEffect::VolumeSlide(
Num::new(first as i16) / 64,
slot.effect_type == 0x6,
)
}
}
0xC => {

Binary file not shown.