From c50542889554a1c79c116916568e9c28b1c23f50 Mon Sep 17 00:00:00 2001 From: lifning <> Date: Tue, 2 Nov 2021 23:43:48 -0700 Subject: [PATCH] WIP messier shit figuring out audio format changing that the sdl2 crate generics currently make impossible --- .../src/provided/sdl2/audio_ratecontrol.rs | 80 ++++++++++++++++--- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/ferretro_components/src/provided/sdl2/audio_ratecontrol.rs b/ferretro_components/src/provided/sdl2/audio_ratecontrol.rs index 2b604d1..466b613 100644 --- a/ferretro_components/src/provided/sdl2/audio_ratecontrol.rs +++ b/ferretro_components/src/provided/sdl2/audio_ratecontrol.rs @@ -6,22 +6,75 @@ use std::path::Path; use core::time::Duration; use sdl2::Sdl; -use sdl2::audio::{AudioCallback, AudioDevice, AudioFormat, AudioSpec, AudioSpecDesired, AudioCVT, AudioFormatNum}; +use sdl2::audio::{AudioCallback, AudioDevice, AudioFormat, AudioSpec, AudioSpecDesired, AudioCVT, AudioFormatNum, AudioQueue}; + +enum AudioQueueEnum { + U8(AudioQueue), + S8(AudioQueue), + U16(AudioQueue), + S16(AudioQueue), + S32(AudioQueue), + F32(AudioQueue), +} + +impl AudioQueueEnum { + fn sample_size(&self) -> usize { + match self { + AudioQueueEnum::U8(_) => size_of::(), + AudioQueueEnum::S8(_) => size_of::(), + AudioQueueEnum::U16(_) => size_of::(), + AudioQueueEnum::S16(_) => size_of::(), + AudioQueueEnum::S32(_) => size_of::(), + AudioQueueEnum::F32(_) => size_of::(), + } + } + + fn queue(&mut self, samples_i16: &[i16], cvt: &AudioCVT) -> bool { + let data = samples_i16.as_mut_ptr() as *mut u8; + let src_len = samples_i16.len() * size_of::(); + let samples_u8 = unsafe { core::slice::from_raw_parts(data, src_len) }; + + let src = Vec::with_capacity(cvt.capacity(src_len)); + src.copy_from_slice(samples_u8); + let resampled_u8 = cvt.convert(src); + + fn reinterp(data_u8: Vec) -> Vec { + const BYTE_SIZE: usize = size_of::(); + let ptr = data_u8.as_mut_ptr() as *mut Self::Channel; + let length = (data_u8.len() + (BYTE_SIZE - 1)) / BYTE_SIZE; + let capacity = (data_u8.capacity() + (BYTE_SIZE - 1)) / BYTE_SIZE; + std::mem::forget(data_u8); + unsafe { Vec::from_raw_parts(ptr, length, capacity) } + } + + match self { + AudioQueueEnum::U8(q) => q.queue(reinterp(resampled_u8)), + AudioQueueEnum::S8(q) => q.queue(reinterp(resampled_u8)), + AudioQueueEnum::U16(q) => q.queue(reinterp(resampled_u8)), + AudioQueueEnum::S16(q) => q.queue(reinterp(resampled_u8)), + AudioQueueEnum::S32(q) => q.queue(reinterp(resampled_u8)), + AudioQueueEnum::F32(q) => q.queue(reinterp(resampled_u8)), + } + } +} /// Trivially sends the core's audio data to the SDL audio subsystem for playback. pub struct Sdl2RateControlledAudioComponent { sample_rate: f64, - audio_buffer: Vec, - dest_spec: AudioSpec, - audio_device: AudioDevice<>, - cvt_send: crossbeam_channel::Sender, - send: crossbeam_channel::Sender>, + //audio_buffer: Vec, + queue: AudioQueueEnum, + spec: AudioSpec, + convert: AudioCVT, + //audio_device: AudioDevice<>, + //cvt_send: crossbeam_channel::Sender, + //send: crossbeam_channel::Sender>, } impl RetroCallbacks for Sdl2RateControlledAudioComponent { fn audio_samples(&mut self, stereo_pcm: &[i16]) -> usize { + let samples = stereo_pcm.len() / 2; + self.audio_buffer.extend(stereo_pcm); - self.send_audio_samples(); stereo_pcm.len() / 2 } @@ -64,7 +117,8 @@ impl Sdl2RateControlledAudioComponent { channels: Some(2), samples: None, }; - let mut dest_spec_opt = None; + let queue = audio.open_queue::(None, &desired_spec)?; + /*let mut dest_spec_opt = None; let audio_device = audio .open_playback(None, &desired_spec, |dest_spec| { dest_spec_opt = Some(dest_spec.clone()); @@ -90,16 +144,20 @@ impl Sdl2RateControlledAudioComponent { ), }; callback - }) - .unwrap(); + })?; + */ Ok(Sdl2RateControlledAudioComponent { sample_rate: src_freq, + queue, + spec, + convert, + /* audio_buffer: Default::default(), dest_spec: dest_spec_opt.unwrap(), audio_device, cvt_send, - send, + send,*/ }) }