mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-09 08:31:33 +11:00
Add vibrato
This commit is contained in:
parent
f6e7625bb1
commit
31ca8f631f
|
@ -69,6 +69,7 @@ pub enum PatternEffect {
|
||||||
Portamento(Num<u16, 12>),
|
Portamento(Num<u16, 12>),
|
||||||
/// Slide each tick the first amount to at most the second amount
|
/// Slide each tick the first amount to at most the second amount
|
||||||
TonePortamento(Num<u16, 12>, Num<u16, 12>),
|
TonePortamento(Num<u16, 12>, Num<u16, 12>),
|
||||||
|
Vibrato(Waveform, Num<u16, 12>, u8),
|
||||||
SetTicksPerStep(u32),
|
SetTicksPerStep(u32),
|
||||||
SetFramesPerTick(Num<u32, 8>),
|
SetFramesPerTick(Num<u32, 8>),
|
||||||
SetGlobalVolume(Num<i32, 8>),
|
SetGlobalVolume(Num<i32, 8>),
|
||||||
|
@ -77,7 +78,7 @@ pub enum PatternEffect {
|
||||||
PitchBend(Num<u32, 8>),
|
PitchBend(Num<u32, 8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Waveform {
|
pub enum Waveform {
|
||||||
#[default]
|
#[default]
|
||||||
Sine,
|
Sine,
|
||||||
|
@ -334,6 +335,10 @@ impl quote::ToTokens for PatternEffect {
|
||||||
let amount = amount.to_raw();
|
let amount = amount.to_raw();
|
||||||
quote! { PitchBend(agb_tracker::__private::Num::from_raw(#amount)) }
|
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! {
|
tokens.append_all(quote! {
|
||||||
|
|
|
@ -5,17 +5,17 @@ use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
fn main() {
|
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| {
|
let square = (0..64).map(|i| {
|
||||||
if i < 32 {
|
if i < 32 {
|
||||||
Num::<i32, 8>::new(-1)
|
Num::<i32, 12>::new(-1)
|
||||||
} else {
|
} 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 out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
let dest_path = Path::new(&out_dir).join("lookups.rs");
|
let dest_path = Path::new(&out_dir).join("lookups.rs");
|
||||||
|
@ -24,9 +24,9 @@ fn main() {
|
||||||
&dest_path,
|
&dest_path,
|
||||||
format!(
|
format!(
|
||||||
"
|
"
|
||||||
pub(crate) static SINE_LOOKUP: [agb_fixnum::Num<i32, 8>; 64] = [{sine_lookup}];
|
pub(crate) static SINE_LOOKUP: [agb_fixnum::Num<i32, 12>; 64] = [{sine_lookup}];
|
||||||
pub(crate) static SQUARE_LOOKUP: [agb_fixnum::Num<i32, 8>; 64] = [{square_lookup}];
|
pub(crate) static SQUARE_LOOKUP: [agb_fixnum::Num<i32, 12>; 64] = [{square_lookup}];
|
||||||
pub(crate) static SAW_LOOKUP: [agb_fixnum::Num<i32, 8>; 64] = [{saw_lookup}];
|
pub(crate) static SAW_LOOKUP: [agb_fixnum::Num<i32, 12>; 64] = [{saw_lookup}];
|
||||||
",
|
",
|
||||||
sine_lookup = gen_lookup(sine),
|
sine_lookup = gen_lookup(sine),
|
||||||
square_lookup = gen_lookup(square),
|
square_lookup = gen_lookup(square),
|
||||||
|
@ -38,7 +38,7 @@ fn main() {
|
||||||
println!("cargo::rerun-if-changed=build.rs");
|
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
|
let output: Vec<_> = input
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|v| format!("agb_fixnum::Num::from_raw({})", v.to_raw()))
|
.map(|v| format!("agb_fixnum::Num::from_raw({})", v.to_raw()))
|
||||||
|
|
|
@ -132,7 +132,7 @@ struct Waves {
|
||||||
waveform: Waveform,
|
waveform: Waveform,
|
||||||
frame: usize,
|
frame: usize,
|
||||||
speed: usize,
|
speed: usize,
|
||||||
amount: Num<i32, 8>,
|
amount: Num<i32, 12>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Waves {
|
impl Waves {
|
||||||
|
@ -281,6 +281,7 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
|
||||||
.and_then(|channel_id| mixer.channel(channel_id))
|
.and_then(|channel_id| mixer.channel(channel_id))
|
||||||
{
|
{
|
||||||
let mut current_speed = tracker_channel.current_speed;
|
let mut current_speed = tracker_channel.current_speed;
|
||||||
|
|
||||||
if tracker_channel.vibrato.speed != 0 {
|
if tracker_channel.vibrato.speed != 0 {
|
||||||
current_speed *= tracker_channel.vibrato.value().change_base();
|
current_speed *= tracker_channel.vibrato.value().change_base();
|
||||||
}
|
}
|
||||||
|
@ -498,6 +499,11 @@ impl TrackerChannel {
|
||||||
global_settings.volume =
|
global_settings.volume =
|
||||||
(global_settings.volume + *volume_delta).clamp(0.into(), 1.into());
|
(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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use agb_fixnum::Num;
|
use agb_fixnum::Num;
|
||||||
use agb_tracker_interop::PatternEffect;
|
use agb_tracker_interop::{PatternEffect, Waveform};
|
||||||
|
|
||||||
use xmrs::prelude::*;
|
use xmrs::prelude::*;
|
||||||
|
|
||||||
|
@ -277,6 +277,22 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
||||||
PatternEffect::None
|
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 => {
|
0x8 => {
|
||||||
PatternEffect::Panning(Num::new(slot.effect_parameter as i16 - 128) / 128)
|
PatternEffect::Panning(Num::new(slot.effect_parameter as i16 - 128) / 128)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue