From 8191de35460753ba294ddaa3eb5c1f74d137e95f Mon Sep 17 00:00:00 2001 From: Gwilym Inzani Date: Sat, 15 Jul 2023 21:07:55 +0100 Subject: [PATCH] Try a pure rust implementation to allow for looping correctly --- agb/src/sound/mixer/sw_mixer.rs | 87 ++++++++++++--------------------- tracker/agb-xm-core/src/lib.rs | 11 +---- 2 files changed, 32 insertions(+), 66 deletions(-) diff --git a/agb/src/sound/mixer/sw_mixer.rs b/agb/src/sound/mixer/sw_mixer.rs index cc9b2f15..ae411fb0 100644 --- a/agb/src/sound/mixer/sw_mixer.rs +++ b/agb/src/sound/mixer/sw_mixer.rs @@ -412,65 +412,31 @@ impl MixerBuffer { working_buffer: &mut [Num], channels: impl Iterator, ) { + working_buffer.fill(0.into()); + let mut channels = channels .filter(|channel| !channel.is_done) .filter_map(|channel| { let playback_speed = if channel.is_stereo { + if (channel.pos + 2 * self.frequency.buffer_size() as u32).floor() + >= channel.data.len() as u32 + { + if channel.should_loop { + channel.pos = 0.into(); + } else { + channel.is_done = true; + return None; + } + } + 2.into() } else { channel.playback_speed }; - if (channel.pos + playback_speed * self.frequency.buffer_size() as u32).floor() - >= channel.data.len() as u32 - { - // TODO: This should probably play what's left rather than skip the last bit - if channel.should_loop { - channel.pos = 0.into(); - } else { - channel.is_done = true; - return None; - } - } - Some((channel, playback_speed)) }); - if let Some((channel, playback_speed)) = channels.next() { - if channel.volume != 0.into() { - if channel.is_stereo { - unsafe { - agb_rs__mixer_add_stereo_first( - channel.data.as_ptr().add(channel.pos.floor() as usize), - working_buffer.as_mut_ptr(), - channel.volume, - self.frequency.buffer_size(), - ); - } - } else { - let right_amount = ((channel.panning + 1) / 2) * channel.volume; - let left_amount = ((-channel.panning + 1) / 2) * channel.volume; - - unsafe { - agb_rs__mixer_add_first( - channel.data.as_ptr().add(channel.pos.floor() as usize), - working_buffer.as_mut_ptr(), - playback_speed, - left_amount, - right_amount, - self.frequency.buffer_size(), - ); - } - } - } else { - working_buffer.fill(0.into()); - } - - channel.pos += playback_speed * self.frequency.buffer_size() as u32; - } else { - working_buffer.fill(0.into()); - } - for (channel, playback_speed) in channels { if channel.volume != 0.into() { if channel.is_stereo { @@ -486,15 +452,24 @@ impl MixerBuffer { let right_amount = ((channel.panning + 1) / 2) * channel.volume; let left_amount = ((-channel.panning + 1) / 2) * channel.volume; - unsafe { - agb_rs__mixer_add( - channel.data.as_ptr().add(channel.pos.floor() as usize), - working_buffer.as_mut_ptr(), - playback_speed, - left_amount, - right_amount, - self.frequency.buffer_size(), - ); + let channel_len = Num::::new(channel.data.len() as u32); + + 'outer: for i in 0..self.frequency.buffer_size() { + while channel.pos >= channel_len { + if channel.should_loop { + channel.pos -= channel_len; + } else { + channel.is_done = true; + break 'outer; + } + } + + let value = channel.data[channel.pos.floor() as usize] as i8 as i16; + + working_buffer[2 * i] += left_amount * value; + working_buffer[2 * i + 1] += right_amount * value; + + channel.pos += playback_speed; } } } diff --git a/tracker/agb-xm-core/src/lib.rs b/tracker/agb-xm-core/src/lib.rs index 073988a7..9e09c095 100644 --- a/tracker/agb-xm-core/src/lib.rs +++ b/tracker/agb-xm-core/src/lib.rs @@ -67,7 +67,7 @@ pub fn parse_module(module: &Module) -> TokenStream { let relative_note = sample.relative_note; let volume = sample.volume as f64; - let mut sample = match &sample.data { + let sample = match &sample.data { SampleDataType::Depth8(depth8) => { depth8.iter().map(|value| *value as u8).collect::>() } @@ -77,15 +77,6 @@ pub fn parse_module(module: &Module) -> TokenStream { .collect::>(), }; - if should_loop { - sample.append(&mut sample.clone()); - sample.append(&mut sample.clone()); - sample.append(&mut sample.clone()); - sample.append(&mut sample.clone()); - sample.append(&mut sample.clone()); - sample.append(&mut sample.clone()); - } - instruments_map.insert((instrument_index, sample_index), samples.len()); samples.push(SampleData { data: sample,