From e50b5463f222a87dee720ce5816acb9dae002201 Mon Sep 17 00:00:00 2001 From: Alula Date: Sat, 19 Sep 2020 00:39:26 +0200 Subject: [PATCH] an attempt to make pixtone less clicky --- src/sound/pixtone.rs | 62 ++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/src/sound/pixtone.rs b/src/sound/pixtone.rs index b08aeaf..fceb847 100644 --- a/src/sound/pixtone.rs +++ b/src/sound/pixtone.rs @@ -175,7 +175,7 @@ impl PixToneParameters { return Vec::new(); } - let mut samples = vec![0; length]; + let mut samples = vec![0i16; length + 100]; for channel in self.channels.iter() { if !channel.enabled { continue; } @@ -189,19 +189,30 @@ impl PixToneParameters { let carrier_wave = channel.carrier.get_waveform(); let frequency_wave = channel.frequency.get_waveform(); let amplitude_wave = channel.amplitude.get_waveform(); + let mut last_wave = 0; for (i, result) in samples.iter_mut().enumerate() { - if i == channel.length as usize { - break; + if i >= channel.length as usize { + if i == channel.length as usize { + last_wave = *result; + } else if i == (channel.length as usize + 100) { + break; + } + + let fac = (i - channel.length as usize) as i16 / 2 + 1; + + last_wave /= fac; + *result = last_wave; + continue; + } else { + let carrier = carrier_wave[0xff & phase as usize] as i32 * channel.carrier.level; + let freq = frequency_wave[0xff & (channel.frequency.offset as f32 + s(channel.frequency.pitch, i, channel.length)) as usize] as i32 * channel.frequency.level; + let amp = amplitude_wave[0xff & (channel.amplitude.offset as f32 + s(channel.amplitude.pitch, i, channel.length)) as usize] as i32 * channel.amplitude.level; + + *result = clamp((*result as i32) + (carrier * (amp + 4096) / 4096 * channel.envelope.evaluate(s(1.0, i, channel.length) as i32) / 4096) * 192, -32767, 32767) as i16; + + phase += delta * (1.0 + (freq as f32 / (if freq < 0 { 8192.0 } else { 2048.0 }))); } - - let carrier = carrier_wave[0xff & phase as usize] as i32 * channel.carrier.level; - let freq = frequency_wave[0xff & (channel.frequency.offset as f32 + s(channel.frequency.pitch, i, channel.length)) as usize] as i32 * channel.frequency.level; - let amp = amplitude_wave[0xff & (channel.amplitude.offset as f32 + s(channel.amplitude.pitch, i, channel.length)) as usize] as i32 * channel.amplitude.level; - - *result = clamp((*result as i32) + (carrier * (amp + 4096) / 4096 * channel.envelope.evaluate(s(1.0, i, channel.length) as i32) / 4096) * 256, -32767, 32767) as i16; - - phase += delta * (1.0 + (freq as f32 / (if freq < 0 { 8192.0 } else { 2048.0 }))); } } @@ -210,7 +221,7 @@ impl PixToneParameters { } #[derive(Copy, Clone, PartialEq)] -pub struct PlaybackState(u8, f32, u32); +pub struct PlaybackState(u8, f32, f32, u32); pub struct PixTonePlayback { pub samples: HashMap>, @@ -233,17 +244,17 @@ impl PixTonePlayback { pub fn play_sfx(&mut self, id: u8) { for state in self.playback_state.iter_mut() { - if state.0 == id && state.2 == 0 { - state.1 = 0.0; - return; + if state.0 == id && state.3 == 0 { + state.2 = 200.0; + state.3 = 0xffffffff; } } - self.playback_state.push(PlaybackState(id, 0.0, 0)); + self.playback_state.push(PlaybackState(id, 0.0, 0.0, 0)); } pub fn play_concurrent(&mut self, id: u8, tag: u32) { - self.playback_state.push(PlaybackState(id, 0.0, tag)); + self.playback_state.push(PlaybackState(id, 0.0, 0.0, tag)); } pub fn mix(&mut self, dst: &mut [u16], sample_rate: f32) { @@ -271,10 +282,21 @@ impl PixTonePlayback { let s3 = (sample[clamp(pos + 2, 0, sample.len() - 1)] as f32) / 32768.0; let s4 = (sample[pos.saturating_sub(1)] as f32) / 32768.0; - let s = cubic_interp(s1, s2, s4, s3, state.1.fract()) * 32768.0; - let sam = (*result ^ 0x8000) as i16; + let mut s = cubic_interp(s1, s2, s4, s3, state.1.fract()) * 32768.0; - *result = sam.saturating_add(s as i16) as u16 ^ 0x8000; + if state.2 > 0.0 { + s *= (state.2 / 200.0); + + state.2 -= delta; + + if state.2 <= 0.0 { + remove = true; + break; + } + } + + let sam = (*result ^ 0x8000) as i16; + *result = sam.wrapping_add(s as i16) as u16 ^ 0x8000; state.1 += delta; }