Use the new mixer in the example

This commit is contained in:
Gwilym Kuiper 2021-06-06 12:44:32 +01:00
parent f126c7f4f4
commit 106e53f917
2 changed files with 73 additions and 16 deletions

View file

@ -3,18 +3,25 @@
extern crate agb; extern crate agb;
use core::mem; use agb::sound::mixer::SoundChannel;
use agb::Gba;
// Music - "I will not let you let me down" by Josh Woodward, free download at http://joshwoodward.com // Music - "I will not let you let me down" by Josh Woodward, free download at http://joshwoodward.com
const I_WILL_NOT_LET_YOU_LET_ME_DOWN: &[u8] = include_bytes!("i-will-not-let-you-let-me-down.raw"); const I_WILL_NOT_LET_YOU_LET_ME_DOWN: &[u8] = include_bytes!("i-will-not-let-you-let-me-down.raw");
#[no_mangle] #[no_mangle]
pub fn main() -> ! { pub fn main() -> ! {
let gba = agb::Gba::new(); let mut gba = Gba::new();
let mixer = gba.mixer; let vblank_provider = gba.display.vblank.get();
let mut mixer = gba.mixer.mixer();
mixer.enable(); mixer.enable();
mixer.play_sound_starting_at(I_WILL_NOT_LET_YOU_LET_ME_DOWN); let channel = SoundChannel::new(I_WILL_NOT_LET_YOU_LET_ME_DOWN);
mixer.play_sound(channel);
loop {} loop {
vblank_provider.wait_for_VBlank();
mixer.vblank();
}
} }

View file

@ -27,28 +27,54 @@ impl Mixer {
} }
pub fn enable(&self) { pub fn enable(&self) {
set_sound_control_register_for_mixer();
set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY); set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY);
set_sound_control_register_for_mixer();
} }
pub fn vblank(&mut self) { pub fn vblank(&mut self) {
self.buffer.swap(); 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.write_channel(&some_channel);
some_channel.pos += SOUND_BUFFER_SIZE;
if some_channel.pos >= some_channel.data.len() {
has_finished = true;
}
}
if has_finished {
channel.take();
}
}
}
pub fn play_sound(&mut self, new_channel: SoundChannel) {
for channel in self.channels.iter_mut() {
if channel.is_some() {
continue;
}
channel.replace(new_channel);
return;
}
panic!("Cannot play more than 16 sounds at once");
} }
} }
pub struct SoundChannel { pub struct SoundChannel {
data: &'static [u8], data: &'static [u8],
pos: usize, pos: usize,
should_loop: bool,
} }
impl SoundChannel { impl SoundChannel {
pub fn new(data: &'static [u8], should_loop: bool) -> Self { pub fn new(data: &'static [u8]) -> Self {
SoundChannel { SoundChannel { data, pos: 0 }
data,
pos: 0,
should_loop,
}
} }
} }
@ -75,13 +101,37 @@ impl MixerBuffer {
} }
fn swap(&mut self) { fn swap(&mut self) {
self.buffer_1_active = !self.buffer_1_active;
if self.buffer_1_active { if self.buffer_1_active {
enable_dma1_for_sound(&self.buffer1); enable_dma1_for_sound(&self.buffer1);
} else { } else {
enable_dma1_for_sound(&self.buffer2); enable_dma1_for_sound(&self.buffer2);
} }
}
self.buffer_1_active = !self.buffer_1_active; fn clear(&mut self) {
if self.buffer_1_active {
self.buffer2.fill(0);
} else {
self.buffer1.fill(0);
}
}
fn write_channel(&mut self, channel: &SoundChannel) {
let data_to_copy = &channel.data[channel.pos..(channel.pos + SOUND_BUFFER_SIZE)];
if self.buffer_1_active {
for (i, v) in data_to_copy.iter().enumerate() {
let v = *v as i8;
self.buffer2[i] = self.buffer2[i].saturating_add(v);
}
} else {
for (i, v) in data_to_copy.iter().enumerate() {
let v = *v as i8;
self.buffer1[i] = self.buffer1[i].saturating_add(v);
}
}
} }
} }
@ -107,8 +157,8 @@ fn enable_dma1_for_sound(sound_memory: &[i8]) {
let dma_start_timing: u16 = 3 << 12; // sound fifo timing let dma_start_timing: u16 = 3 << 12; // sound fifo timing
let enable: u16 = 1 << 15; // enable let enable: u16 = 1 << 15; // enable
let address: *const i8 = &sound_memory[0]; DMA1_CONTROL.set(0);
DMA1_SOURCE_ADDR.set(address as u32); DMA1_SOURCE_ADDR.set(sound_memory.as_ptr() as u32);
DMA1_DEST_ADDR.set(FIFOA_DEST_ADDR); DMA1_DEST_ADDR.set(FIFOA_DEST_ADDR);
DMA1_CONTROL.set(dest_fixed | repeat | transfer_type | dma_start_timing | enable); DMA1_CONTROL.set(dest_fixed | repeat | transfer_type | dma_start_timing | enable);
} }