Skip to content

Commit d2924db

Browse files
committed
APU: reduce allocation by re-using old audio buffers
Only give reference to the user, as they don't need the actual Vec
1 parent bd91a5f commit d2924db

File tree

4 files changed

+60
-24
lines changed

4 files changed

+60
-24
lines changed

mizu-core/src/apu.rs

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,45 @@ use wave_channel::WaveChannel;
1717
/// The main buffer `all` is the summation of all of the other buffers/channels.
1818
/// If you want a combination of different channels, you can just add them together.
1919
/// All volume control is done before pushing to the buffers.
20-
pub struct AudioBuffers {
21-
pub pulse1: Vec<f32>,
22-
pub pulse2: Vec<f32>,
23-
pub wave: Vec<f32>,
24-
pub noise: Vec<f32>,
20+
pub struct AudioBuffers<'a> {
21+
pulse1: &'a mut Vec<f32>,
22+
pulse2: &'a mut Vec<f32>,
23+
wave: &'a mut Vec<f32>,
24+
noise: &'a mut Vec<f32>,
2525

26-
pub all: Vec<f32>,
26+
all: &'a mut Vec<f32>,
27+
}
28+
29+
impl AudioBuffers<'_> {
30+
pub fn pulse1(&self) -> &[f32] {
31+
self.pulse1
32+
}
33+
34+
pub fn pulse2(&self) -> &[f32] {
35+
self.pulse2
36+
}
37+
38+
pub fn wave(&self) -> &[f32] {
39+
self.wave
40+
}
41+
42+
pub fn noise(&self) -> &[f32] {
43+
self.noise
44+
}
45+
46+
pub fn all(&self) -> &[f32] {
47+
self.all
48+
}
49+
}
50+
51+
impl Drop for AudioBuffers<'_> {
52+
fn drop(&mut self) {
53+
self.pulse1.clear();
54+
self.pulse2.clear();
55+
self.wave.clear();
56+
self.noise.clear();
57+
self.all.clear();
58+
}
2759
}
2860

2961
bitflags! {
@@ -353,14 +385,14 @@ impl Apu {
353385
(p2 << 4) | p1
354386
}
355387

356-
pub fn get_buffers(&mut self) -> AudioBuffers {
388+
pub fn get_buffers(&mut self) -> AudioBuffers<'_> {
357389
AudioBuffers {
358-
pulse1: std::mem::take(&mut self.pulse1_buffers),
359-
pulse2: std::mem::take(&mut self.pulse2_buffers),
360-
wave: std::mem::take(&mut self.wave_buffers),
361-
noise: std::mem::take(&mut self.noise_buffers),
390+
pulse1: &mut self.pulse1_buffers,
391+
pulse2: &mut self.pulse2_buffers,
392+
wave: &mut self.wave_buffers,
393+
noise: &mut self.noise_buffers,
362394

363-
all: std::mem::take(&mut self.buffer),
395+
all: &mut self.buffer,
364396
}
365397
}
366398

mizu-core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ impl GameBoy {
187187
}
188188

189189
/// Return the audio buffer of the APU at the current state.
190+
///
191+
/// We use `&mut` as it will also reset the buffers after using them
190192
pub fn audio_buffers(&mut self) -> AudioBuffers {
191193
self.bus.audio_buffers()
192194
}

mizu-core/src/memory.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ impl Bus {
318318
self.ppu.raw_screen_buffer()
319319
}
320320

321-
pub fn audio_buffers(&mut self) -> AudioBuffers {
321+
pub fn audio_buffers(&mut self) -> AudioBuffers<'_> {
322322
self.apu.get_buffers()
323323
}
324324

src/main.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -179,17 +179,19 @@ impl GameboyFront {
179179

180180
self.gameboy.clock_for_frame();
181181

182-
let buffers = self.gameboy.audio_buffers();
183-
184-
if let Some(audio_player) = self.audio_player.as_mut() {
185-
let audio_buffer = match self.audio_output {
186-
AudioBufferOutput::All => buffers.all,
187-
AudioBufferOutput::Pulse1 => buffers.pulse1,
188-
AudioBufferOutput::Pulse2 => buffers.pulse2,
189-
AudioBufferOutput::Wave => buffers.wave,
190-
AudioBufferOutput::Noise => buffers.noise,
191-
};
192-
audio_player.queue(&audio_buffer);
182+
{
183+
let buffers = self.gameboy.audio_buffers();
184+
185+
if let Some(audio_player) = self.audio_player.as_mut() {
186+
let audio_buffer = match self.audio_output {
187+
AudioBufferOutput::All => buffers.all(),
188+
AudioBufferOutput::Pulse1 => buffers.pulse1(),
189+
AudioBufferOutput::Pulse2 => buffers.pulse2(),
190+
AudioBufferOutput::Wave => buffers.wave(),
191+
AudioBufferOutput::Noise => buffers.noise(),
192+
};
193+
audio_player.queue(audio_buffer);
194+
}
193195
}
194196

195197
self.window.clear(Color::BLACK);

0 commit comments

Comments
 (0)