[aud] Use Audio queue

This commit is contained in:
2024-03-06 08:02:15 +05:30
parent 5fc961a155
commit ed7c6d3e1c
4 changed files with 50 additions and 40 deletions

View File

@@ -20,7 +20,7 @@ Chip 8 emulator/interpreter.
- [X] Timer - [X] Timer
- [X] Super chip8 compatibility. - [X] Super chip8 compatibility.
- [X] Audio - [X] Audio
- Audio seems to be broken on my device. I will check with other devices. - Audio seems to stutter, but working
- [X] Keyboard - [X] Keyboard
### More information on CHIP-8 ### More information on CHIP-8

View File

@@ -43,7 +43,7 @@ impl TimerManager {
*timer_lock -= 1; *timer_lock -= 1;
} }
if *sound_lock > 0 { if *sound_lock > 0 {
log::info!("Beep!"); log::trace!("Beep!");
*sound_lock -= 1; *sound_lock -= 1;
} }
} }

View File

@@ -21,7 +21,7 @@ use crate::device::Device;
use crate::device::keyboard::Keyboard; use crate::device::keyboard::Keyboard;
use crate::util::EmulatorResult; use crate::util::EmulatorResult;
use crate::kb_map::get_key_index; use crate::kb_map::get_key_index;
use crate::sdl_audio_adapter::SquareWave; use crate::sdl_audio_adapter::SdlAudioAdapter;
use crate::sdl_graphics_adapter::SdlGraphicsAdapter; use crate::sdl_graphics_adapter::SdlGraphicsAdapter;
use crate::sdl_keyboard_adapter::SdlKeyboardAdapter; use crate::sdl_keyboard_adapter::SdlKeyboardAdapter;
@@ -41,9 +41,11 @@ fn main() -> EmulatorResult<()> {
let mut timer = TimerManager::new(); let mut timer = TimerManager::new();
let audio_state = timer.start(); let (mut canvas, mut event_pump,audio_queue) = try_initiate_sdl(draw_scale)?;
let (mut canvas, mut event_pump) = try_initiate_sdl(audio_state,draw_scale)?;
let audio_state = timer.start();
let mut sdl_aud_adapter = SdlAudioAdapter::new(audio_state,440.0,0.5,audio_queue);
let (frame_buffer_for_display, frame_buffer_for_device) = get_frame_buffer_references(); let (frame_buffer_for_display, frame_buffer_for_device) = get_frame_buffer_references();
@@ -91,7 +93,7 @@ fn main() -> EmulatorResult<()> {
sdl_graphics_adapter.draw_screen(lock, &mut canvas)?; sdl_graphics_adapter.draw_screen(lock, &mut canvas)?;
} }
canvas.present(); canvas.present();
sdl_aud_adapter.process_push_audio()?;
// 60fps - small offset to consider for cpu cycle time // 60fps - small offset to consider for cpu cycle time
thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)); thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
} }
@@ -139,21 +141,17 @@ fn load_rom(rom_file_location: String) -> [u8; ROM_SIZE] {
rom_slice rom_slice
} }
fn try_initiate_sdl(audio_state: Arc<Mutex<u8>>, draw_scale: f32) -> EmulatorResult<(WindowCanvas, EventPump)> { fn try_initiate_sdl(draw_scale: f32) -> EmulatorResult<(WindowCanvas, EventPump, AudioQueue<f32>)> {
let sdl_context = sdl2::init().unwrap(); let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap(); let video_subsystem = sdl_context.video().unwrap();
let audio_subsystem = sdl_context.audio().unwrap(); let audio_subsystem = sdl_context.audio().unwrap();
let wanted_spec = AudioSpecDesired { let wanted_spec = AudioSpecDesired {
channels: Some(1), channels: Some(1),
samples: None, samples: None,
freq: Some(44100), freq: Some(SdlAudioAdapter::SAMPLING_FREQ),
}; };
let device = audio_subsystem.open_playback(None, &wanted_spec, |spec| { let audio_queue = audio_subsystem.open_queue::<f32,_>(None, &wanted_spec)?;
// initialize the audio callback
SquareWave ::new(audio_state,440.0/spec.freq as f32,0.5)
}).unwrap();
device.resume();
let window_width = (Device::FRAME_BUFFER_WIDTH as f32 * draw_scale) as u32; let window_width = (Device::FRAME_BUFFER_WIDTH as f32 * draw_scale) as u32;
let window_height = (Device::FRAME_BUFFER_HEIGHT as f32 * draw_scale) as u32; let window_height = (Device::FRAME_BUFFER_HEIGHT as f32 * draw_scale) as u32;
@@ -169,8 +167,7 @@ fn try_initiate_sdl(audio_state: Arc<Mutex<u8>>, draw_scale: f32) -> EmulatorRes
canvas.clear(); canvas.clear();
canvas.present(); canvas.present();
let event_pump = sdl_context.event_pump()?; let event_pump = sdl_context.event_pump()?;
Ok((canvas, event_pump Ok((canvas, event_pump,audio_queue))
))
} }

View File

@@ -1,45 +1,58 @@
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex};
use log::warn; use sdl2::audio::AudioQueue;
use sdl2::audio::AudioCallback; use crate::util::EmulatorResult;
pub struct SquareWave { pub struct SdlAudioAdapter {
sound_timer: Arc<Mutex<u8>>, sound_timer: Arc<Mutex<u8>>,
phase_inc: f32, phase_inc: f32,
phase: f32, phase: f32,
volume: f32, volume: f32,
audio_queue: AudioQueue<f32>,
buf: Vec<f32>,
} }
impl SquareWave { /// An Audio adapter using `AudioQueue`.
impl SdlAudioAdapter {
pub const SAMPLING_FREQ:i32 = 15360;
pub const SAMPLES_PER_FRAME: usize = Self::SAMPLING_FREQ as usize / 60 + 2;
pub fn new(sound_timer: Arc<Mutex<u8>>, pub fn new(sound_timer: Arc<Mutex<u8>>,
phase_inc: f32, freq: f32,
volume: f32)->SquareWave { volume: f32,
SquareWave { audio_queue: AudioQueue<f32>) -> SdlAudioAdapter {
audio_queue.resume();
SdlAudioAdapter {
sound_timer, sound_timer,
buf: vec![0f32; Self::SAMPLES_PER_FRAME],
phase: 0f32, phase: 0f32,
phase_inc, phase_inc: freq/Self::SAMPLING_FREQ as f32,
volume, volume,
audio_queue,
} }
} }
} pub fn process_push_audio(&mut self) -> EmulatorResult<()> {
// fill the audio vector.
let sound_timer = {
let sound_timer = self.sound_timer.lock().expect("Could not lock to play audio");
sound_timer.clone()
};
if sound_timer>0 {
self.fill_audio();
self.audio_queue.queue_audio(&self.buf)?;
}
Ok(())
}
impl AudioCallback for SquareWave { fn fill_audio(&mut self) {
type Channel = f32; let out = &mut self.buf;
fn callback(&mut self, out: &mut [f32]) {
let sound_timer = self.sound_timer.lock().expect("Could not lock to play audio");
let sound_timer = sound_timer.clone();
// log::info!("Processing audio buffer length {}",out.len());
// Generate a square wave // Generate a square wave
for x in out.iter_mut() { for x in out.iter_mut() {
*x = if sound_timer > 0 { *x = if self.phase <= 0.5 {
if self.phase <= 0.5 { self.volume
self.volume
} else {
-self.volume
}
} else { } else {
0f32 -self.volume
}; };
self.phase = (self.phase + self.phase_inc) % 1.0; self.phase = (self.phase + self.phase_inc) % 1.0;
} }
} }