diff --git a/README.md b/README.md index 2b46e04..8bc6b67 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Chip 8 emulator/interpreter. - [X] Timer - [X] Super chip8 compatibility. - [X] Audio - - Audio seems to be broken on my device. I will check with other devices. + - Audio seems to stutter, but working - [X] Keyboard ### More information on CHIP-8 diff --git a/src/device/timer.rs b/src/device/timer.rs index 2e0f382..5ea3869 100644 --- a/src/device/timer.rs +++ b/src/device/timer.rs @@ -43,7 +43,7 @@ impl TimerManager { *timer_lock -= 1; } if *sound_lock > 0 { - log::info!("Beep!"); + log::trace!("Beep!"); *sound_lock -= 1; } } diff --git a/src/main.rs b/src/main.rs index bb54cfa..eaf12a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ use crate::device::Device; use crate::device::keyboard::Keyboard; use crate::util::EmulatorResult; 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_keyboard_adapter::SdlKeyboardAdapter; @@ -41,9 +41,11 @@ fn main() -> EmulatorResult<()> { let mut timer = TimerManager::new(); - let audio_state = timer.start(); - let (mut canvas, mut event_pump) = try_initiate_sdl(audio_state,draw_scale)?; + let (mut canvas, mut event_pump,audio_queue) = try_initiate_sdl(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(); @@ -91,7 +93,7 @@ fn main() -> EmulatorResult<()> { sdl_graphics_adapter.draw_screen(lock, &mut canvas)?; } canvas.present(); - + sdl_aud_adapter.process_push_audio()?; // 60fps - small offset to consider for cpu cycle time thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)); } @@ -139,22 +141,18 @@ fn load_rom(rom_file_location: String) -> [u8; ROM_SIZE] { rom_slice } -fn try_initiate_sdl(audio_state: Arc>, draw_scale: f32) -> EmulatorResult<(WindowCanvas, EventPump)> { +fn try_initiate_sdl(draw_scale: f32) -> EmulatorResult<(WindowCanvas, EventPump, AudioQueue)> { let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); let audio_subsystem = sdl_context.audio().unwrap(); let wanted_spec = AudioSpecDesired { channels: Some(1), samples: None, - freq: Some(44100), + freq: Some(SdlAudioAdapter::SAMPLING_FREQ), }; - let device = audio_subsystem.open_playback(None, &wanted_spec, |spec| { - // initialize the audio callback - SquareWave ::new(audio_state,440.0/spec.freq as f32,0.5) - }).unwrap(); - device.resume(); - + let audio_queue = audio_subsystem.open_queue::(None, &wanted_spec)?; + 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; @@ -169,8 +167,7 @@ fn try_initiate_sdl(audio_state: Arc>, draw_scale: f32) -> EmulatorRes canvas.clear(); canvas.present(); let event_pump = sdl_context.event_pump()?; - Ok((canvas, event_pump - )) + Ok((canvas, event_pump,audio_queue)) } diff --git a/src/sdl_audio_adapter.rs b/src/sdl_audio_adapter.rs index 8e80252..f4f0757 100644 --- a/src/sdl_audio_adapter.rs +++ b/src/sdl_audio_adapter.rs @@ -1,46 +1,59 @@ -use std::sync::{Arc, Mutex, RwLock}; -use log::warn; -use sdl2::audio::AudioCallback; +use std::sync::{Arc, Mutex}; +use sdl2::audio::AudioQueue; +use crate::util::EmulatorResult; -pub struct SquareWave { +pub struct SdlAudioAdapter { sound_timer: Arc>, phase_inc: f32, phase: f32, volume: f32, + audio_queue: AudioQueue, + buf: Vec, } -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>, - phase_inc: f32, - volume: f32)->SquareWave { - SquareWave { + freq: f32, + volume: f32, + audio_queue: AudioQueue) -> SdlAudioAdapter { + audio_queue.resume(); + SdlAudioAdapter { sound_timer, + buf: vec![0f32; Self::SAMPLES_PER_FRAME], phase: 0f32, - phase_inc, + phase_inc: freq/Self::SAMPLING_FREQ as f32, 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 { - type Channel = f32; + fn fill_audio(&mut self) { + 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 for x in out.iter_mut() { - *x = if sound_timer > 0 { - if self.phase <= 0.5 { - self.volume - } else { - -self.volume - } + *x = if self.phase <= 0.5 { + self.volume } else { - 0f32 + -self.volume }; + self.phase = (self.phase + self.phase_inc) % 1.0; } } -} \ No newline at end of file +}