Add vibrato

This commit is contained in:
Gwilym Inzani 2024-07-10 11:48:09 +01:00
parent f6e7625bb1
commit 31ca8f631f
4 changed files with 38 additions and 11 deletions

View file

@ -69,6 +69,7 @@ pub enum PatternEffect {
Portamento(Num<u16, 12>),
/// Slide each tick the first amount to at most the second amount
TonePortamento(Num<u16, 12>, Num<u16, 12>),
Vibrato(Waveform, Num<u16, 12>, u8),
SetTicksPerStep(u32),
SetFramesPerTick(Num<u32, 8>),
SetGlobalVolume(Num<i32, 8>),
@ -77,7 +78,7 @@ pub enum PatternEffect {
PitchBend(Num<u32, 8>),
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum Waveform {
#[default]
Sine,
@ -334,6 +335,10 @@ impl quote::ToTokens for PatternEffect {
let amount = amount.to_raw();
quote! { PitchBend(agb_tracker::__private::Num::from_raw(#amount)) }
}
PatternEffect::Vibrato(waveform, amount, speed) => {
let amount = amount.to_raw();
quote! { Vibrato(#waveform, #amount, #speed) }
}
};
tokens.append_all(quote! {

View file

@ -5,17 +5,17 @@ use std::fs;
use std::path::Path;
fn main() {
let sine = (0..64).map(|i| (Num::<i32, 8>::new(i) / 64).sin());
let sine = (0..64).map(|i| (Num::<i32, 12>::new(i) / 64).sin());
let square = (0..64).map(|i| {
if i < 32 {
Num::<i32, 8>::new(-1)
Num::<i32, 12>::new(-1)
} else {
Num::<i32, 8>::new(1)
Num::<i32, 12>::new(1)
}
});
let saw = (0..64).map(|i| (Num::<i32, 8>::new(i) - 32) / 32);
let saw = (0..64).map(|i| (Num::<i32, 12>::new(i) - 32) / 32);
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("lookups.rs");
@ -24,9 +24,9 @@ fn main() {
&dest_path,
format!(
"
pub(crate) static SINE_LOOKUP: [agb_fixnum::Num<i32, 8>; 64] = [{sine_lookup}];
pub(crate) static SQUARE_LOOKUP: [agb_fixnum::Num<i32, 8>; 64] = [{square_lookup}];
pub(crate) static SAW_LOOKUP: [agb_fixnum::Num<i32, 8>; 64] = [{saw_lookup}];
pub(crate) static SINE_LOOKUP: [agb_fixnum::Num<i32, 12>; 64] = [{sine_lookup}];
pub(crate) static SQUARE_LOOKUP: [agb_fixnum::Num<i32, 12>; 64] = [{square_lookup}];
pub(crate) static SAW_LOOKUP: [agb_fixnum::Num<i32, 12>; 64] = [{saw_lookup}];
",
sine_lookup = gen_lookup(sine),
square_lookup = gen_lookup(square),
@ -38,7 +38,7 @@ fn main() {
println!("cargo::rerun-if-changed=build.rs");
}
fn gen_lookup(input: impl IntoIterator<Item = Num<i32, 8>>) -> String {
fn gen_lookup(input: impl IntoIterator<Item = Num<i32, 12>>) -> String {
let output: Vec<_> = input
.into_iter()
.map(|v| format!("agb_fixnum::Num::from_raw({})", v.to_raw()))

View file

@ -132,7 +132,7 @@ struct Waves {
waveform: Waveform,
frame: usize,
speed: usize,
amount: Num<i32, 8>,
amount: Num<i32, 12>,
}
impl Waves {
@ -281,6 +281,7 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
.and_then(|channel_id| mixer.channel(channel_id))
{
let mut current_speed = tracker_channel.current_speed;
if tracker_channel.vibrato.speed != 0 {
current_speed *= tracker_channel.vibrato.value().change_base();
}
@ -498,6 +499,11 @@ impl TrackerChannel {
global_settings.volume =
(global_settings.volume + *volume_delta).clamp(0.into(), 1.into());
}
PatternEffect::Vibrato(waveform, amount, speed) => {
self.vibrato.waveform = *waveform;
self.vibrato.amount = amount.change_base();
self.vibrato.speed = *speed as usize;
}
}
}

View file

@ -1,7 +1,7 @@
use std::collections::HashMap;
use agb_fixnum::Num;
use agb_tracker_interop::PatternEffect;
use agb_tracker_interop::{PatternEffect, Waveform};
use xmrs::prelude::*;
@ -277,6 +277,22 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
PatternEffect::None
}
}
0x4 => {
let vibrato_speed = effect_parameter >> 4;
let depth = effect_parameter & 0xF;
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);
let amount = speed / c4_speed - 1;
PatternEffect::Vibrato(
Waveform::Sine,
amount.try_change_base().unwrap(),
vibrato_speed,
)
}
0x8 => {
PatternEffect::Panning(Num::new(slot.effect_parameter as i16 - 128) / 128)
}