mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Handle vibrato in the instrument too
This commit is contained in:
parent
d15063373d
commit
3bd8b9019d
|
@ -358,6 +358,10 @@ pub fn parse_midi(midi_info: &MidiInfo) -> Track {
|
||||||
sustain: Some(envelope.amounts.len() - 1),
|
sustain: Some(envelope.amounts.len() - 1),
|
||||||
loop_start: None,
|
loop_start: None,
|
||||||
loop_end: None,
|
loop_end: None,
|
||||||
|
|
||||||
|
vib_waveform: Default::default(),
|
||||||
|
vib_amount: Default::default(),
|
||||||
|
vib_speed: Default::default(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,10 @@ pub struct Envelope {
|
||||||
pub sustain: Option<usize>,
|
pub sustain: Option<usize>,
|
||||||
pub loop_start: Option<usize>,
|
pub loop_start: Option<usize>,
|
||||||
pub loop_end: Option<usize>,
|
pub loop_end: Option<usize>,
|
||||||
|
|
||||||
|
pub vib_waveform: Waveform,
|
||||||
|
pub vib_amount: Num<u16, 12>,
|
||||||
|
pub vib_speed: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||||
|
@ -80,7 +84,7 @@ pub enum PatternEffect {
|
||||||
PitchBend(Num<u32, 8>),
|
PitchBend(Num<u32, 8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Waveform {
|
pub enum Waveform {
|
||||||
#[default]
|
#[default]
|
||||||
Sine,
|
Sine,
|
||||||
|
@ -146,6 +150,9 @@ impl quote::ToTokens for Envelope {
|
||||||
sustain,
|
sustain,
|
||||||
loop_start,
|
loop_start,
|
||||||
loop_end,
|
loop_end,
|
||||||
|
vib_amount,
|
||||||
|
vib_speed,
|
||||||
|
vib_waveform,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let amount = amount.iter().map(|value| {
|
let amount = amount.iter().map(|value| {
|
||||||
|
@ -153,6 +160,11 @@ impl quote::ToTokens for Envelope {
|
||||||
quote! { agb_tracker::__private::Num::from_raw(#value) }
|
quote! { agb_tracker::__private::Num::from_raw(#value) }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let vib_amount = {
|
||||||
|
let value = vib_amount.to_raw();
|
||||||
|
quote! { agb_tracker::__private::Num::from_raw(#value) }
|
||||||
|
};
|
||||||
|
|
||||||
let sustain = match sustain {
|
let sustain = match sustain {
|
||||||
Some(value) => quote!(Some(#value)),
|
Some(value) => quote!(Some(#value)),
|
||||||
None => quote!(None),
|
None => quote!(None),
|
||||||
|
@ -175,6 +187,10 @@ impl quote::ToTokens for Envelope {
|
||||||
sustain: #sustain,
|
sustain: #sustain,
|
||||||
loop_start: #loop_start,
|
loop_start: #loop_start,
|
||||||
loop_end: #loop_end,
|
loop_end: #loop_end,
|
||||||
|
|
||||||
|
vib_waveform: #vib_waveform,
|
||||||
|
vib_amount: #vib_amount,
|
||||||
|
vib_speed: #vib_speed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -141,23 +141,27 @@ impl Waves {
|
||||||
fn value(&self) -> Num<u32, 8> {
|
fn value(&self) -> Num<u32, 8> {
|
||||||
assert!(self.amount.abs() <= 1.into());
|
assert!(self.amount.abs() <= 1.into());
|
||||||
|
|
||||||
let lookup = match self.waveform {
|
calculate_wave(self.waveform, self.amount, self.frame)
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calculate_wave(waveform: Waveform, amount: Num<i32, 12>, frame: usize) -> Num<u32, 8> {
|
||||||
|
let lookup = match waveform {
|
||||||
|
Waveform::Sine => lookups::SINE_LOOKUP,
|
||||||
|
Waveform::Saw => lookups::SAW_LOOKUP,
|
||||||
|
Waveform::Square => lookups::SQUARE_LOOKUP,
|
||||||
|
};
|
||||||
|
|
||||||
|
(amount * lookup[frame] + 1).try_change_base().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
struct EnvelopeState {
|
struct EnvelopeState {
|
||||||
frame: usize,
|
frame: usize,
|
||||||
envelope_id: usize,
|
envelope_id: usize,
|
||||||
finished: bool,
|
finished: bool,
|
||||||
fadeout: Num<i32, 8>,
|
fadeout: Num<i32, 8>,
|
||||||
|
|
||||||
|
vibrato_pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -249,6 +253,8 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
|
||||||
envelope_id,
|
envelope_id,
|
||||||
finished: false,
|
finished: false,
|
||||||
fadeout: sample.fadeout,
|
fadeout: sample.fadeout,
|
||||||
|
|
||||||
|
vibrato_pos: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +283,12 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn realise<M: Mixer<ChannelId = TChannelId>>(&mut self, mixer: &mut M) {
|
fn realise<M: Mixer<ChannelId = TChannelId>>(&mut self, mixer: &mut M) {
|
||||||
for (mixer_channel, tracker_channel) in self.mixer_channels.iter().zip(&mut self.channels) {
|
for (i, (mixer_channel, tracker_channel)) in self
|
||||||
|
.mixer_channels
|
||||||
|
.iter()
|
||||||
|
.zip(&mut self.channels)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
tracker_channel.tick();
|
tracker_channel.tick();
|
||||||
|
|
||||||
if let Some(channel) = mixer_channel
|
if let Some(channel) = mixer_channel
|
||||||
|
@ -288,6 +299,19 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
|
||||||
|
|
||||||
if tracker_channel.vibrato.speed != 0 && tracker_channel.vibrato.enable {
|
if tracker_channel.vibrato.speed != 0 && tracker_channel.vibrato.enable {
|
||||||
current_speed *= tracker_channel.vibrato.value().change_base();
|
current_speed *= tracker_channel.vibrato.value().change_base();
|
||||||
|
} else if let Some(envelope) = &mut self.envelopes[i] {
|
||||||
|
let track_envelope = &self.track.envelopes[envelope.envelope_id];
|
||||||
|
|
||||||
|
if track_envelope.vib_speed != 0 {
|
||||||
|
current_speed *= calculate_wave(
|
||||||
|
track_envelope.vib_waveform,
|
||||||
|
track_envelope.vib_amount.change_base(),
|
||||||
|
envelope.vibrato_pos,
|
||||||
|
)
|
||||||
|
.change_base();
|
||||||
|
envelope.vibrato_pos =
|
||||||
|
(envelope.vibrato_pos + track_envelope.vib_speed as usize) % 64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
channel.playback(current_speed.change_base());
|
channel.playback(current_speed.change_base());
|
||||||
|
|
|
@ -31,7 +31,12 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
||||||
|
|
||||||
let envelope = &instrument.volume_envelope;
|
let envelope = &instrument.volume_envelope;
|
||||||
let envelope_id = if envelope.enabled {
|
let envelope_id = if envelope.enabled {
|
||||||
let envelope = EnvelopeData::new(envelope, module.default_bpm as u32);
|
let envelope = EnvelopeData::new(
|
||||||
|
envelope,
|
||||||
|
instrument,
|
||||||
|
module.frequency_type,
|
||||||
|
module.default_bpm as u32,
|
||||||
|
);
|
||||||
let id = existing_envelopes
|
let id = existing_envelopes
|
||||||
.entry(envelope)
|
.entry(envelope)
|
||||||
.or_insert_with_key(|envelope| {
|
.or_insert_with_key(|envelope| {
|
||||||
|
@ -461,6 +466,10 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
||||||
sustain: envelope.sustain,
|
sustain: envelope.sustain,
|
||||||
loop_start: envelope.loop_start,
|
loop_start: envelope.loop_start,
|
||||||
loop_end: envelope.loop_end,
|
loop_end: envelope.loop_end,
|
||||||
|
|
||||||
|
vib_amount: envelope.vib_amount.try_change_base().unwrap(),
|
||||||
|
vib_waveform: envelope.vib_waveform,
|
||||||
|
vib_speed: envelope.vib_speed,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -541,10 +550,19 @@ struct EnvelopeData {
|
||||||
sustain: Option<usize>,
|
sustain: Option<usize>,
|
||||||
loop_start: Option<usize>,
|
loop_start: Option<usize>,
|
||||||
loop_end: Option<usize>,
|
loop_end: Option<usize>,
|
||||||
|
|
||||||
|
vib_waveform: Waveform,
|
||||||
|
vib_speed: u8,
|
||||||
|
vib_amount: Num<u32, 12>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnvelopeData {
|
impl EnvelopeData {
|
||||||
fn new(e: &xmrs::envelope::Envelope, bpm: u32) -> Self {
|
fn new(
|
||||||
|
e: &xmrs::envelope::Envelope,
|
||||||
|
instrument: &xmrs::instr_default::InstrDefault,
|
||||||
|
frequency_type: FrequencyType,
|
||||||
|
bpm: u32,
|
||||||
|
) -> Self {
|
||||||
let mut amounts = vec![];
|
let mut amounts = vec![];
|
||||||
|
|
||||||
for frame in 0..=(Self::envelope_frame_to_gba_frame(e.point.last().unwrap().frame, bpm)) {
|
for frame in 0..=(Self::envelope_frame_to_gba_frame(e.point.last().unwrap().frame, bpm)) {
|
||||||
|
@ -587,11 +605,29 @@ impl EnvelopeData {
|
||||||
(None, None)
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let vib_waveform = match instrument.vibrato.waveform {
|
||||||
|
xmrs::instr_vibrato::Waveform::Sine => Waveform::Sine,
|
||||||
|
xmrs::instr_vibrato::Waveform::Square => Waveform::Square,
|
||||||
|
xmrs::instr_vibrato::Waveform::RampUp => Waveform::Saw,
|
||||||
|
xmrs::instr_vibrato::Waveform::RampDown => Waveform::Saw,
|
||||||
|
};
|
||||||
|
|
||||||
|
let vib_speed = (instrument.vibrato.speed * 64.0) as u8;
|
||||||
|
let vib_depth = instrument.vibrato.depth * 16.0;
|
||||||
|
|
||||||
|
let c4_speed = note_to_speed(Note::C4, 0.0, 0, frequency_type);
|
||||||
|
let vib_amount =
|
||||||
|
note_to_speed(Note::C4, vib_depth.into(), 0, frequency_type) / c4_speed - 1;
|
||||||
|
|
||||||
EnvelopeData {
|
EnvelopeData {
|
||||||
amounts,
|
amounts,
|
||||||
sustain,
|
sustain,
|
||||||
loop_start,
|
loop_start,
|
||||||
loop_end,
|
loop_end,
|
||||||
|
|
||||||
|
vib_waveform,
|
||||||
|
vib_speed,
|
||||||
|
vib_amount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue