diff --git a/tracker/agb-tracker/src/lib.rs b/tracker/agb-tracker/src/lib.rs index fb524b4d..199da58f 100644 --- a/tracker/agb-tracker/src/lib.rs +++ b/tracker/agb-tracker/src/lib.rs @@ -68,7 +68,7 @@ extern crate alloc; mod lookups; mod mixer; -use agb_tracker_interop::{PatternEffect, Sample}; +use agb_tracker_interop::{PatternEffect, Sample, Waveform}; use alloc::vec::Vec; pub use mixer::{Mixer, SoundChannel}; @@ -119,12 +119,38 @@ struct TrackerChannel { base_speed: Num, volume: Num, + vibrato: Waves, + current_volume: Num, current_speed: Num, current_panning: Num, is_playing: bool, } +#[derive(Default)] +struct Waves { + waveform: Waveform, + frame: usize, + speed: usize, + amount: Num, +} + +impl Waves { + fn value(&self) -> Num { + assert!(self.amount.abs() <= 1.into()); + + let lookup = match self.waveform { + Waveform::Sine => lookups::SINE_LOOKUP, + Waveform::Saw => lookups::SAW_LOOKUP, + Waveform::Square => lookups::SQUARE_LOOKUP, + }; + + (self.amount * lookup[self.frame] + 1) + .try_change_base() + .unwrap() + } +} + struct EnvelopeState { frame: usize, envelope_id: usize, @@ -247,12 +273,19 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> { } fn realise>(&mut self, mixer: &mut M) { - for (mixer_channel, tracker_channel) in self.mixer_channels.iter().zip(&self.channels) { + for (mixer_channel, tracker_channel) in self.mixer_channels.iter().zip(&mut self.channels) { + tracker_channel.tick(); + if let Some(channel) = mixer_channel .as_ref() .and_then(|channel_id| mixer.channel(channel_id)) { - channel.playback(tracker_channel.current_speed.change_base()); + let mut current_speed = tracker_channel.current_speed; + if tracker_channel.vibrato.speed != 0 { + current_speed *= tracker_channel.vibrato.value().change_base(); + } + + channel.playback(current_speed.change_base()); channel.volume(tracker_channel.current_volume.try_change_base().unwrap()); channel.panning(tracker_channel.current_panning.try_change_base().unwrap()); @@ -487,6 +520,10 @@ impl TrackerChannel { self.volume != 0.into() } + + fn tick(&mut self) { + self.vibrato.frame = (self.vibrato.frame + self.vibrato.speed) % 64; + } } #[cfg(all(test, feature = "agb"))] diff --git a/tracker/agb-tracker/src/lookups.rs b/tracker/agb-tracker/src/lookups.rs index 48aa0119..0f20e646 100644 --- a/tracker/agb-tracker/src/lookups.rs +++ b/tracker/agb-tracker/src/lookups.rs @@ -1,3 +1 @@ -pub(crate) mod lookups { - include!(concat!(env!("OUT_DIR"), "/lookups.rs")); -} +include!(concat!(env!("OUT_DIR"), "/lookups.rs"));