This sounds pretty decent now

This commit is contained in:
Gwilym Inzani 2023-08-05 00:24:11 +01:00
parent 47455a0377
commit aabfb1b083
2 changed files with 28 additions and 9 deletions

View file

@ -112,6 +112,7 @@ struct TrackerChannel {
struct EnvelopeState { struct EnvelopeState {
frame: usize, frame: usize,
envelope_id: usize, envelope_id: usize,
finished: bool,
} }
#[derive(Clone)] #[derive(Clone)]
@ -167,10 +168,16 @@ impl Tracker {
let pattern_slots = let pattern_slots =
&self.track.pattern_data[pattern_data_pos..pattern_data_pos + self.track.num_channels]; &self.track.pattern_data[pattern_data_pos..pattern_data_pos + self.track.num_channels];
for (channel, pattern_slot) in self.channels.iter_mut().zip(pattern_slots) { for (i, (channel, pattern_slot)) in self.channels.iter_mut().zip(pattern_slots).enumerate()
{
if pattern_slot.sample != 0 && self.tick == 0 { if pattern_slot.sample != 0 && self.tick == 0 {
let sample = &self.track.samples[pattern_slot.sample as usize - 1]; let sample = &self.track.samples[pattern_slot.sample as usize - 1];
channel.play_sound(mixer, sample); channel.play_sound(mixer, sample);
self.envelopes[i] = sample.volume_envelope.map(|envelope_id| EnvelopeState {
frame: 0,
envelope_id,
finished: false,
});
} }
if self.tick == 0 { if self.tick == 0 {
@ -182,12 +189,14 @@ impl Tracker {
&pattern_slot.effect1, &pattern_slot.effect1,
self.tick, self.tick,
&mut self.global_settings, &mut self.global_settings,
&mut self.envelopes[i],
); );
channel.apply_effect( channel.apply_effect(
mixer, mixer,
&pattern_slot.effect2, &pattern_slot.effect2,
self.tick, self.tick,
&mut self.global_settings, &mut self.global_settings,
&mut self.envelopes[i],
); );
} }
@ -204,11 +213,13 @@ impl Tracker {
} else { } else {
envelope_state.frame += 1; envelope_state.frame += 1;
if !envelope_state.finished {
if let Some(sustain) = envelope.sustain { if let Some(sustain) = envelope.sustain {
if envelope_state.frame >= sustain { if envelope_state.frame >= sustain {
envelope_state.frame = sustain; envelope_state.frame = sustain;
} }
} }
}
if let Some(loop_end) = envelope.loop_end { if let Some(loop_end) = envelope.loop_end {
if envelope_state.frame >= loop_end { if envelope_state.frame >= loop_end {
@ -304,6 +315,7 @@ impl TrackerChannel {
effect: &PatternEffect, effect: &PatternEffect,
tick: u32, tick: u32,
global_settings: &mut GlobalSettings, global_settings: &mut GlobalSettings,
envelope_state: &mut Option<EnvelopeState>,
) { ) {
if let Some(channel) = self if let Some(channel) = self
.channel_id .channel_id
@ -314,6 +326,9 @@ impl TrackerChannel {
PatternEffect::None => {} PatternEffect::None => {}
PatternEffect::Stop => { PatternEffect::Stop => {
channel.volume(0); channel.volume(0);
if let Some(envelope_state) = envelope_state {
envelope_state.finished = true;
}
} }
PatternEffect::Arpeggio(first, second) => { PatternEffect::Arpeggio(first, second) => {
match tick % 3 { match tick % 3 {
@ -345,6 +360,10 @@ impl TrackerChannel {
PatternEffect::NoteCut(wait) => { PatternEffect::NoteCut(wait) => {
if tick == *wait { if tick == *wait {
channel.volume(0); channel.volume(0);
if let Some(envelope_state) = envelope_state {
envelope_state.finished = true;
}
} }
} }
PatternEffect::Portamento(amount) => { PatternEffect::Portamento(amount) => {

View file

@ -490,21 +490,21 @@ struct EnvelopeData {
impl From<&xmrs::envelope::Envelope> for EnvelopeData { impl From<&xmrs::envelope::Envelope> for EnvelopeData {
fn from(e: &xmrs::envelope::Envelope) -> Self { fn from(e: &xmrs::envelope::Envelope) -> Self {
let mut amounts = vec![Num::new(e.point[0].value as i16) / 0xff]; let mut amounts = vec![];
// it should be sampled at 50fps, but we're sampling at 60fps, so need to do a bit of cheating here. // it should be sampled at 50fps, but we're sampling at 60fps, so need to do a bit of cheating here.
for frame in 1..(e.point.last().unwrap().frame * 60 / 50) { for frame in 0..(e.point.last().unwrap().frame * 60 / 50) {
let xm_frame = (frame * 50 / 60).max(1); let xm_frame = frame * 50 / 60;
let index = e let index = e
.point .point
.iter() .iter()
.rposition(|point| point.frame < xm_frame) .rposition(|point| point.frame < xm_frame)
.unwrap(); .unwrap_or(0);
let first_point = &e.point[index]; let first_point = &e.point[index];
let second_point = &e.point[index + 1]; let second_point = &e.point[index + 1];
let amount = EnvelopePoint::lerp(first_point, second_point, xm_frame) / 255.0; let amount = EnvelopePoint::lerp(first_point, second_point, xm_frame) / 64.0;
let amount = Num::from_raw((amount * (1 << 8) as f32) as i16); let amount = Num::from_raw((amount * (1 << 8) as f32) as i16);
amounts.push(amount); amounts.push(amount);