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),
|
||||
loop_start: None,
|
||||
loop_end: None,
|
||||
|
||||
vib_waveform: Default::default(),
|
||||
vib_amount: Default::default(),
|
||||
vib_speed: Default::default(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -49,6 +49,10 @@ pub struct Envelope {
|
|||
pub sustain: Option<usize>,
|
||||
pub loop_start: 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)]
|
||||
|
@ -80,7 +84,7 @@ pub enum PatternEffect {
|
|||
PitchBend(Num<u32, 8>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Waveform {
|
||||
#[default]
|
||||
Sine,
|
||||
|
@ -146,6 +150,9 @@ impl quote::ToTokens for Envelope {
|
|||
sustain,
|
||||
loop_start,
|
||||
loop_end,
|
||||
vib_amount,
|
||||
vib_speed,
|
||||
vib_waveform,
|
||||
} = self;
|
||||
|
||||
let amount = amount.iter().map(|value| {
|
||||
|
@ -153,6 +160,11 @@ impl quote::ToTokens for Envelope {
|
|||
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 {
|
||||
Some(value) => quote!(Some(#value)),
|
||||
None => quote!(None),
|
||||
|
@ -175,6 +187,10 @@ impl quote::ToTokens for Envelope {
|
|||
sustain: #sustain,
|
||||
loop_start: #loop_start,
|
||||
loop_end: #loop_end,
|
||||
|
||||
vib_waveform: #vib_waveform,
|
||||
vib_amount: #vib_amount,
|
||||
vib_speed: #vib_speed,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -141,16 +141,18 @@ impl Waves {
|
|||
fn value(&self) -> Num<u32, 8> {
|
||||
assert!(self.amount.abs() <= 1.into());
|
||||
|
||||
let lookup = match self.waveform {
|
||||
calculate_wave(self.waveform, self.amount, self.frame)
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
(self.amount * lookup[self.frame] + 1)
|
||||
.try_change_base()
|
||||
.unwrap()
|
||||
}
|
||||
(amount * lookup[frame] + 1).try_change_base().unwrap()
|
||||
}
|
||||
|
||||
struct EnvelopeState {
|
||||
|
@ -158,6 +160,8 @@ struct EnvelopeState {
|
|||
envelope_id: usize,
|
||||
finished: bool,
|
||||
fadeout: Num<i32, 8>,
|
||||
|
||||
vibrato_pos: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -249,6 +253,8 @@ impl<'track, TChannelId> TrackerInner<'track, TChannelId> {
|
|||
envelope_id,
|
||||
finished: false,
|
||||
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) {
|
||||
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();
|
||||
|
||||
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 {
|
||||
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());
|
||||
|
|
|
@ -31,7 +31,12 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
|||
|
||||
let envelope = &instrument.volume_envelope;
|
||||
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
|
||||
.entry(envelope)
|
||||
.or_insert_with_key(|envelope| {
|
||||
|
@ -461,6 +466,10 @@ pub fn parse_module(module: &Module) -> agb_tracker_interop::Track {
|
|||
sustain: envelope.sustain,
|
||||
loop_start: envelope.loop_start,
|
||||
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<_>>();
|
||||
|
||||
|
@ -541,10 +550,19 @@ struct EnvelopeData {
|
|||
sustain: Option<usize>,
|
||||
loop_start: Option<usize>,
|
||||
loop_end: Option<usize>,
|
||||
|
||||
vib_waveform: Waveform,
|
||||
vib_speed: u8,
|
||||
vib_amount: Num<u32, 12>,
|
||||
}
|
||||
|
||||
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![];
|
||||
|
||||
for frame in 0..=(Self::envelope_frame_to_gba_frame(e.point.last().unwrap().frame, bpm)) {
|
||||
|
@ -587,11 +605,29 @@ impl EnvelopeData {
|
|||
(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 {
|
||||
amounts,
|
||||
sustain,
|
||||
loop_start,
|
||||
loop_end,
|
||||
|
||||
vib_waveform,
|
||||
vib_speed,
|
||||
vib_amount,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue