mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-23 07:36:33 +11:00
Allow controlling of playback speed
This commit is contained in:
parent
5b1f85a619
commit
9b77ab7587
2 changed files with 44 additions and 44 deletions
|
@ -3,16 +3,14 @@ use super::hw::LeftOrRight;
|
||||||
use super::SoundChannel;
|
use super::SoundChannel;
|
||||||
|
|
||||||
pub struct Mixer {
|
pub struct Mixer {
|
||||||
buffer_l: MixerBuffer,
|
buffer: MixerBuffer,
|
||||||
buffer_r: MixerBuffer,
|
|
||||||
channels: [Option<SoundChannel>; 16],
|
channels: [Option<SoundChannel>; 16],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mixer {
|
impl Mixer {
|
||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
Mixer {
|
Mixer {
|
||||||
buffer_l: MixerBuffer::new(LeftOrRight::Left),
|
buffer: MixerBuffer::new(),
|
||||||
buffer_r: MixerBuffer::new(LeftOrRight::Right),
|
|
||||||
channels: Default::default(),
|
channels: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,33 +21,17 @@ impl Mixer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vblank(&mut self) {
|
pub fn vblank(&mut self) {
|
||||||
self.buffer_l.swap();
|
self.buffer.swap();
|
||||||
self.buffer_r.swap();
|
self.buffer.clear();
|
||||||
self.buffer_l.clear();
|
|
||||||
self.buffer_r.clear();
|
|
||||||
|
|
||||||
for channel in self.channels.iter_mut() {
|
for channel in self.channels.iter_mut() {
|
||||||
let mut has_finished = false;
|
|
||||||
|
|
||||||
if let Some(some_channel) = channel {
|
if let Some(some_channel) = channel {
|
||||||
self.buffer_l.write_channel(some_channel);
|
if self.buffer.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 {
|
|
||||||
channel.take();
|
channel.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn play_sound(&mut self, new_channel: SoundChannel) {
|
pub fn play_sound(&mut self, new_channel: SoundChannel) {
|
||||||
for channel in self.channels.iter_mut() {
|
for channel in self.channels.iter_mut() {
|
||||||
|
@ -71,50 +53,60 @@ const SOUND_FREQUENCY: i32 = 10512;
|
||||||
const SOUND_BUFFER_SIZE: usize = 176;
|
const SOUND_BUFFER_SIZE: usize = 176;
|
||||||
|
|
||||||
struct MixerBuffer {
|
struct MixerBuffer {
|
||||||
buffer1: [i8; SOUND_BUFFER_SIZE],
|
buffer1: [i8; SOUND_BUFFER_SIZE * 2], // first half is left, second is right
|
||||||
buffer2: [i8; SOUND_BUFFER_SIZE],
|
buffer2: [i8; SOUND_BUFFER_SIZE * 2],
|
||||||
|
|
||||||
buffer_1_active: bool,
|
buffer_1_active: bool,
|
||||||
|
|
||||||
lr: LeftOrRight,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MixerBuffer {
|
impl MixerBuffer {
|
||||||
fn new(lr: LeftOrRight) -> Self {
|
fn new() -> Self {
|
||||||
MixerBuffer {
|
MixerBuffer {
|
||||||
buffer1: [0; SOUND_BUFFER_SIZE],
|
buffer1: [0; SOUND_BUFFER_SIZE * 2],
|
||||||
buffer2: [0; SOUND_BUFFER_SIZE],
|
buffer2: [0; SOUND_BUFFER_SIZE * 2],
|
||||||
|
|
||||||
buffer_1_active: true,
|
buffer_1_active: true,
|
||||||
lr,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swap(&mut self) {
|
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(left_buffer, LeftOrRight::Left);
|
||||||
hw::enable_dma_for_sound(&self.buffer1, self.lr);
|
hw::enable_dma_for_sound(right_buffer, LeftOrRight::Right);
|
||||||
} else {
|
|
||||||
hw::enable_dma_for_sound(&self.buffer2, self.lr);
|
self.buffer_1_active = !self.buffer_1_active;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.get_write_buffer().fill(0);
|
self.get_write_buffer().fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_channel(&mut self, channel: &SoundChannel) {
|
fn write_channel(&mut self, channel: &mut SoundChannel) -> bool {
|
||||||
let data_to_copy = &channel.data[channel.pos.floor()..];
|
|
||||||
let place_to_write_to = self.get_write_buffer();
|
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() {
|
for i in 0..SOUND_BUFFER_SIZE {
|
||||||
let v = *v as i8;
|
let v = channel.data[current_point.floor()];
|
||||||
place_to_write_to[i] = place_to_write_to[i].saturating_add(v);
|
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 {
|
if self.buffer_1_active {
|
||||||
&mut self.buffer2
|
&mut self.buffer2
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -22,6 +22,8 @@ pub struct SoundChannel {
|
||||||
data: &'static [u8],
|
data: &'static [u8],
|
||||||
pos: Num<usize, 8>,
|
pos: Num<usize, 8>,
|
||||||
should_loop: bool,
|
should_loop: bool,
|
||||||
|
|
||||||
|
playback_speed: Num<usize, 8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SoundChannel {
|
impl SoundChannel {
|
||||||
|
@ -30,6 +32,7 @@ impl SoundChannel {
|
||||||
data,
|
data,
|
||||||
pos: 0.into(),
|
pos: 0.into(),
|
||||||
should_loop: false,
|
should_loop: false,
|
||||||
|
playback_speed: 1.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,4 +40,9 @@ impl SoundChannel {
|
||||||
self.should_loop = true;
|
self.should_loop = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn playback(mut self, playback_speed: Num<usize, 8>) -> Self {
|
||||||
|
self.playback_speed = playback_speed;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue