Allow controlling of playback speed

This commit is contained in:
Gwilym Kuiper 2021-06-10 23:00:00 +01:00
parent 5b1f85a619
commit 9b77ab7587
2 changed files with 44 additions and 44 deletions

View file

@ -3,16 +3,14 @@ use super::hw::LeftOrRight;
use super::SoundChannel;
pub struct Mixer {
buffer_l: MixerBuffer,
buffer_r: MixerBuffer,
buffer: MixerBuffer,
channels: [Option<SoundChannel>; 16],
}
impl Mixer {
pub(super) fn new() -> Self {
Mixer {
buffer_l: MixerBuffer::new(LeftOrRight::Left),
buffer_r: MixerBuffer::new(LeftOrRight::Right),
buffer: MixerBuffer::new(),
channels: Default::default(),
}
}
@ -23,33 +21,17 @@ impl Mixer {
}
pub fn vblank(&mut self) {
self.buffer_l.swap();
self.buffer_r.swap();
self.buffer_l.clear();
self.buffer_r.clear();
self.buffer.swap();
self.buffer.clear();
for channel in self.channels.iter_mut() {
let mut has_finished = false;
if let Some(some_channel) = channel {
self.buffer_l.write_channel(some_channel);
self.buffer_r.write_channel(some_channel);
some_channel.pos += SOUND_BUFFER_SIZE;
if some_channel.pos.floor() >= some_channel.data.len() {
if some_channel.should_loop {
some_channel.pos = 0.into();
} else {
has_finished = true;
}
}
}
if has_finished {
if self.buffer.write_channel(some_channel) {
channel.take();
}
}
}
}
pub fn play_sound(&mut self, new_channel: SoundChannel) {
for channel in self.channels.iter_mut() {
@ -71,50 +53,60 @@ const SOUND_FREQUENCY: i32 = 10512;
const SOUND_BUFFER_SIZE: usize = 176;
struct MixerBuffer {
buffer1: [i8; SOUND_BUFFER_SIZE],
buffer2: [i8; SOUND_BUFFER_SIZE],
buffer1: [i8; SOUND_BUFFER_SIZE * 2], // first half is left, second is right
buffer2: [i8; SOUND_BUFFER_SIZE * 2],
buffer_1_active: bool,
lr: LeftOrRight,
}
impl MixerBuffer {
fn new(lr: LeftOrRight) -> Self {
fn new() -> Self {
MixerBuffer {
buffer1: [0; SOUND_BUFFER_SIZE],
buffer2: [0; SOUND_BUFFER_SIZE],
buffer1: [0; SOUND_BUFFER_SIZE * 2],
buffer2: [0; SOUND_BUFFER_SIZE * 2],
buffer_1_active: true,
lr,
}
}
fn swap(&mut self) {
self.buffer_1_active = !self.buffer_1_active;
let (left_buffer, right_buffer) = self.get_write_buffer().split_at(SOUND_BUFFER_SIZE);
if self.buffer_1_active {
hw::enable_dma_for_sound(&self.buffer1, self.lr);
} else {
hw::enable_dma_for_sound(&self.buffer2, self.lr);
}
hw::enable_dma_for_sound(left_buffer, LeftOrRight::Left);
hw::enable_dma_for_sound(right_buffer, LeftOrRight::Right);
self.buffer_1_active = !self.buffer_1_active;
}
fn clear(&mut self) {
self.get_write_buffer().fill(0);
}
fn write_channel(&mut self, channel: &SoundChannel) {
let data_to_copy = &channel.data[channel.pos.floor()..];
fn write_channel(&mut self, channel: &mut SoundChannel) -> bool {
let place_to_write_to = self.get_write_buffer();
let mut current_point = channel.pos;
for (i, v) in data_to_copy.iter().take(SOUND_BUFFER_SIZE).enumerate() {
let v = *v as i8;
place_to_write_to[i] = place_to_write_to[i].saturating_add(v);
for i in 0..SOUND_BUFFER_SIZE {
let v = channel.data[current_point.floor()];
current_point += channel.playback_speed;
if current_point.floor() >= channel.data.len() {
if channel.should_loop {
channel.pos -= channel.data.len();
} else {
return true;
}
}
fn get_write_buffer(&mut self) -> &mut [i8; SOUND_BUFFER_SIZE] {
place_to_write_to[i] = place_to_write_to[i].saturating_add(v as i8);
place_to_write_to[i + SOUND_BUFFER_SIZE] =
place_to_write_to[i + SOUND_BUFFER_SIZE].saturating_add(v as i8);
}
false
}
fn get_write_buffer(&mut self) -> &mut [i8; SOUND_BUFFER_SIZE * 2] {
if self.buffer_1_active {
&mut self.buffer2
} else {

View file

@ -22,6 +22,8 @@ pub struct SoundChannel {
data: &'static [u8],
pos: Num<usize, 8>,
should_loop: bool,
playback_speed: Num<usize, 8>,
}
impl SoundChannel {
@ -30,6 +32,7 @@ impl SoundChannel {
data,
pos: 0.into(),
should_loop: false,
playback_speed: 1.into(),
}
}
@ -37,4 +40,9 @@ impl SoundChannel {
self.should_loop = true;
self
}
pub fn playback(mut self, playback_speed: Num<usize, 8>) -> Self {
self.playback_speed = playback_speed;
self
}
}