Panning working?

This commit is contained in:
Gwilym Kuiper 2021-06-10 23:34:03 +01:00
parent 9b77ab7587
commit 063af3fc40
3 changed files with 48 additions and 23 deletions

View file

@ -103,6 +103,15 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> From<I> for Num<I, N> {
} }
} }
impl<I, const N: usize> Default for Num<I, N>
where
I: FixedWidthUnsignedInteger,
{
fn default() -> Self {
Num(I::zero())
}
}
impl<I, T, const N: usize> Add<T> for Num<I, N> impl<I, T, const N: usize> Add<T> for Num<I, N>
where where
I: FixedWidthUnsignedInteger, I: FixedWidthUnsignedInteger,

View file

@ -1,6 +1,7 @@
use super::hw; use super::hw;
use super::hw::LeftOrRight; use super::hw::LeftOrRight;
use super::SoundChannel; use super::SoundChannel;
use crate::number::Num;
pub struct Mixer { pub struct Mixer {
buffer: MixerBuffer, buffer: MixerBuffer,
@ -24,13 +25,8 @@ impl Mixer {
self.buffer.swap(); self.buffer.swap();
self.buffer.clear(); self.buffer.clear();
for channel in self.channels.iter_mut() { self.buffer
if let Some(some_channel) = channel { .write_channels(self.channels.iter_mut().flatten());
if self.buffer.write_channel(some_channel) {
channel.take();
}
}
}
} }
pub fn play_sound(&mut self, new_channel: SoundChannel) { pub fn play_sound(&mut self, new_channel: SoundChannel) {
@ -82,28 +78,37 @@ impl MixerBuffer {
self.get_write_buffer().fill(0); self.get_write_buffer().fill(0);
} }
fn write_channel(&mut self, channel: &mut SoundChannel) -> bool { fn write_channels<'a>(&mut self, channels: impl Iterator<Item = &'a mut SoundChannel>) {
let place_to_write_to = self.get_write_buffer(); let mut buffer: [Num<i16, 4>; SOUND_BUFFER_SIZE * 2] = [Num::new(0); SOUND_BUFFER_SIZE * 2];
let mut current_point = channel.pos;
for i in 0..SOUND_BUFFER_SIZE { for channel in channels {
let v = channel.data[current_point.floor()]; let mut current_point = channel.pos;
current_point += channel.playback_speed;
if current_point.floor() >= channel.data.len() { let right_amount = (channel.panning - 1) / 2;
if channel.should_loop { let left_amount = -right_amount + 1;
channel.pos -= channel.data.len();
} else { for i in 0..SOUND_BUFFER_SIZE {
return true; let v = (channel.data[current_point.floor()] as i8) as i16;
let v: Num<i16, 4> = v.into();
current_point += channel.playback_speed;
if current_point.floor() >= channel.data.len() {
if channel.should_loop {
channel.pos -= channel.data.len();
} else {
continue;
}
} }
}
place_to_write_to[i] = place_to_write_to[i].saturating_add(v as i8); buffer[i] += v * left_amount;
place_to_write_to[i + SOUND_BUFFER_SIZE] = buffer[i + SOUND_BUFFER_SIZE] += v * right_amount;
place_to_write_to[i + SOUND_BUFFER_SIZE].saturating_add(v as i8); }
} }
false let write_buffer = self.get_write_buffer();
for i in 0..SOUND_BUFFER_SIZE * 2 {
write_buffer[i] = buffer[i].floor().clamp(i8::MIN as i16, i8::MAX as i16) as i8
}
} }
fn get_write_buffer(&mut self) -> &mut [i8; SOUND_BUFFER_SIZE * 2] { fn get_write_buffer(&mut self) -> &mut [i8; SOUND_BUFFER_SIZE * 2] {

View file

@ -24,6 +24,8 @@ pub struct SoundChannel {
should_loop: bool, should_loop: bool,
playback_speed: Num<usize, 8>, playback_speed: Num<usize, 8>,
panning: Num<i16, 4>, // between -1 and 1
} }
impl SoundChannel { impl SoundChannel {
@ -33,6 +35,7 @@ impl SoundChannel {
pos: 0.into(), pos: 0.into(),
should_loop: false, should_loop: false,
playback_speed: 1.into(), playback_speed: 1.into(),
panning: 0.into(),
} }
} }
@ -45,4 +48,12 @@ impl SoundChannel {
self.playback_speed = playback_speed; self.playback_speed = playback_speed;
self self
} }
pub fn panning(mut self, panning: Num<i16, 4>) -> Self {
debug_assert!(panning >= Num::new(-1), "panning value must be >= -1");
debug_assert!(panning <= Num::new(1), "panning value must be <= 1");
self.panning = panning;
self
}
} }