pixtone fixes
This commit is contained in:
parent
bd3f91c1b1
commit
bc0a33cd7e
|
@ -1,10 +1,12 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use num_traits::clamp;
|
||||
use vec_mut_scan::VecMutScan;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::sound::pixtone_sfx::PIXTONE_TABLE;
|
||||
use crate::sound::stuff::cubic_interp;
|
||||
|
||||
lazy_static! {
|
||||
static ref WAVEFORMS: [[i8; 0x100]; 6] = {
|
||||
|
@ -26,7 +28,7 @@ lazy_static! {
|
|||
}
|
||||
|
||||
// todo i can't get this shit right
|
||||
/*
|
||||
/*
|
||||
let mut seed = 0i32;
|
||||
|
||||
for i in 0..255 {
|
||||
|
@ -36,7 +38,7 @@ lazy_static! {
|
|||
saw_up[i] = (-0x40i32).wrapping_add(i as i32 / 2) as i8;
|
||||
saw_down[i] = (0x40i32.wrapping_sub(i as i32 / 2)) as i8;
|
||||
square[i] = (0x40i32.wrapping_sub(i as i32 & 0x80)) as i8;
|
||||
random[i] = ((seed >> 16) / 2) as i8;
|
||||
random[i] = (seed >> 16) as i8 / 2;
|
||||
}*/
|
||||
|
||||
[sine, triangle, saw_up, saw_down, square, random]
|
||||
|
@ -79,17 +81,6 @@ pub struct Envelope {
|
|||
|
||||
impl Envelope {
|
||||
pub fn evaluate(&self, i: i32) -> i32 {
|
||||
let (prev_time, prev_val) = {
|
||||
if i >= self.time_a {
|
||||
(self.time_a, self.value_a)
|
||||
} else if i >= self.time_b {
|
||||
(self.time_b, self.value_b)
|
||||
} else if i >= self.time_c {
|
||||
(self.time_c, self.value_c)
|
||||
} else {
|
||||
(0, self.initial)
|
||||
}
|
||||
};
|
||||
let (next_time, next_val) = {
|
||||
if i < self.time_c {
|
||||
(self.time_c, self.value_c)
|
||||
|
@ -102,6 +93,18 @@ impl Envelope {
|
|||
}
|
||||
};
|
||||
|
||||
let (prev_time, prev_val) = {
|
||||
if i >= self.time_a {
|
||||
(self.time_a, self.value_a)
|
||||
} else if i >= self.time_b {
|
||||
(self.time_b, self.value_b)
|
||||
} else if i >= self.time_c {
|
||||
(self.time_c, self.value_c)
|
||||
} else {
|
||||
(0, self.initial)
|
||||
}
|
||||
};
|
||||
|
||||
if next_time <= prev_time {
|
||||
return prev_val;
|
||||
}
|
||||
|
@ -188,11 +191,15 @@ impl PixToneParameters {
|
|||
let amplitude_wave = channel.amplitude.get_waveform();
|
||||
|
||||
for (i, result) in samples.iter_mut().enumerate() {
|
||||
if i == channel.length as usize {
|
||||
break;
|
||||
}
|
||||
|
||||
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 += ((carrier * (amp + 4096) / 4096 * channel.envelope.evaluate(s(1.0, i, channel.length) as i32) / 4096) * 256) as i16;
|
||||
*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 })));
|
||||
}
|
||||
|
@ -258,7 +265,17 @@ impl PixTonePlayback {
|
|||
remove = true;
|
||||
break;
|
||||
} else {
|
||||
*result = ((*result as u16 ^ 0x8000u16) as i16).saturating_add(sample[state.1 as usize]) as u16 ^ 0x8000u16;
|
||||
let pos = state.1 as usize;
|
||||
let s1 = (sample[pos] as f32) / 32768.0;
|
||||
let s2 = (sample[clamp(pos + 1, 0, sample.len() - 1)] as f32) / 32768.0;
|
||||
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;
|
||||
|
||||
*result = sam.saturating_add(s as i16) as u16 ^ 0x8000;
|
||||
|
||||
state.1 += delta;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::sound::organya::Song as Organya;
|
|||
use crate::sound::stuff::*;
|
||||
use crate::sound::wav::*;
|
||||
use crate::sound::wave_bank::SoundBank;
|
||||
use num_traits::real::Real;
|
||||
|
||||
pub struct PlaybackEngine {
|
||||
song: Organya,
|
||||
|
@ -328,7 +329,7 @@ impl PlaybackEngine {
|
|||
}
|
||||
|
||||
// TODO: Create a MixingBuffer or something...
|
||||
fn mix(dst: &mut [u16], dst_fmt: WavFormat, srcs: &mut [RenderBuffer]) {
|
||||
pub fn mix(dst: &mut [u16], dst_fmt: WavFormat, srcs: &mut [RenderBuffer]) {
|
||||
let freq = dst_fmt.sample_rate as f64;
|
||||
|
||||
for buf in srcs {
|
||||
|
@ -354,21 +355,6 @@ fn mix(dst: &mut [u16], dst_fmt: WavFormat, srcs: &mut [RenderBuffer]) {
|
|||
}
|
||||
}
|
||||
|
||||
// s1: sample 1
|
||||
// s2: sample 2
|
||||
// sp: previous sample (before s1)
|
||||
// sn: next sample (after s2)
|
||||
// mu: position to interpolate for
|
||||
fn cubic_interp(s1: f32, s2: f32, sp: f32, sn: f32, mu: f32) -> f32 {
|
||||
let mu2 = mu * mu;
|
||||
let a0 = sn - s2 - sp + s1;
|
||||
let a1 = sp - s1 - a0;
|
||||
let a2 = s2 - sp;
|
||||
let a3 = s1;
|
||||
|
||||
a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
|
||||
for frame in dst.iter_mut() {
|
||||
|
|
|
@ -34,3 +34,18 @@ pub fn org_vol_to_vol(vol: u8) -> i32 {
|
|||
pub fn org_key_to_oct_pitch(key: u8) -> (u8, u8) {
|
||||
(key/12, key%12)
|
||||
}
|
||||
|
||||
// s1: sample 1
|
||||
// s2: sample 2
|
||||
// sp: previous sample (before s1)
|
||||
// sn: next sample (after s2)
|
||||
// mu: position to interpolate for
|
||||
pub fn cubic_interp(s1: f32, s2: f32, sp: f32, sn: f32, mu: f32) -> f32 {
|
||||
let mu2 = mu * mu;
|
||||
let a0 = sn - s2 - sp + s1;
|
||||
let a1 = sp - s1 - a0;
|
||||
let a2 = s2 - sp;
|
||||
let a3 = s1;
|
||||
|
||||
a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue