From 6ec90c426aae3e6c108ca69706f5012a8200665b Mon Sep 17 00:00:00 2001 From: Mischa Spiegelmock Date: Sat, 2 Nov 2024 23:21:53 -0700 Subject: [PATCH 1/4] Using SDL3 audio stream API better --- .cargo/config.toml | 2 +- Cargo.lock | 2 - Cargo.toml | 4 +- src/app/audio.rs | 205 ++++++++++++++++++++++++--------------------- 4 files changed, 113 insertions(+), 100 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index a627181..fa9631c 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,3 +1,3 @@ [env] # use pipewire for audio -SDL_AUDIODRIVER = "pipewire" +#SDL_AUDIODRIVER = "pipewire" diff --git a/Cargo.lock b/Cargo.lock index f6306b4..c257fb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,8 +338,6 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "sdl3" version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276a8d8f65325969aa59f1b10671bf450fc068401075085fa0c9f87c791ab6d7" dependencies = [ "bitflags 1.3.2", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index b1079de..6cf2314 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,8 @@ rust-version = "1.68.2" libc = "*" #projectm = { path = "../projectm-rs", version = "2.0.2", features = ["playlist"] } projectm = { version = "2.0.2", features = ['playlist'] } -sdl3 = { version = "0.10.8", features = ["build-from-source"] } -#sdl3 = { path = "../../sdl3-rs", version = "0", features = ["build-from-source"] } +#sdl3 = { version = "0.10.8", features = ["build-from-source"] } +sdl3 = { path = "../../sdl3-rs", version = "0", features = ["build-from-source"] } rand = "0.8.5" include_dir = "0.7" diff --git a/src/app/audio.rs b/src/app/audio.rs index 5e9e6eb..660b681 100644 --- a/src/app/audio.rs +++ b/src/app/audio.rs @@ -1,13 +1,9 @@ -use projectm::core::ProjectM; -use sdl3::audio::{ - AudioDevice, AudioDeviceID, AudioRecordingCallback, AudioSpec, AudioStreamWithCallback, -}; +use sdl3::audio::{AudioDevice, AudioDeviceID, AudioSpec, AudioStream}; +use std::io::Read; use super::config::FrameRate; use super::ProjectMWrapped; -use std::rc::Rc; - // let the user cycle through audio devices type AudioDeviceIndex = usize; @@ -15,16 +11,14 @@ type SampleFormat = f32; // format of audio samples pub struct Audio { audio_subsystem: sdl3::AudioSubsystem, - - current_recording_device: Option, - capture_stream: Option>>, + recording_stream: Option>, is_capturing: bool, - frame_rate: Option, projectm: ProjectMWrapped, + current_device_id: Option, } -/// Wrapper around the audio subsystem to capture audio and pass it to projectM. +/// Wrapper around the audio subsystem to record audio and pass it to projectM. impl Audio { pub fn new(sdl_context: &sdl3::Sdl, projectm: ProjectMWrapped) -> Self { let audio_subsystem = sdl_context.audio().unwrap(); @@ -36,9 +30,9 @@ impl Audio { Self { is_capturing: false, audio_subsystem, - current_recording_device: None, frame_rate: None, - capture_stream: None, + current_device_id: None, + recording_stream: None, projectm, } } @@ -49,7 +43,7 @@ impl Audio { self.frame_rate = frame_rate.into(); #[cfg(not(feature = "dummy_audio"))] - self.begin_audio_capture(self.get_default_recording_device().id()); + self.begin_audio_capture(None); } pub fn list_devices(&self) { @@ -62,47 +56,20 @@ impl Audio { } /// Start capturing audio from device_id. - pub fn capture_device(&mut self, device_id: AudioDeviceID) { + pub fn begin_audio_capture(&mut self, device_id: Option) { + // stop capturing from current stream/device self.stop_audio_capture(); - self.begin_audio_capture(device_id); - } - - fn get_default_recording_device(&self) -> AudioDevice { - self.audio_subsystem.default_recording_device() - } - /// Select a new audio device and start capturing audio from it. - pub fn open_next_device(&mut self) { - let device_list = self.get_device_list(); - let current_device = self.current_recording_device.as_ref().unwrap(); - let current_device_id = current_device.id(); - let current_device_index = device_list - .iter() - .position(|d| d.eq(¤t_device_id)) - .unwrap(); - let next_device_index = (current_device_index + 1) % device_list.len(); - let next_device_id = device_list[next_device_index]; - self.capture_device(next_device_id); - } - - fn get_device_list(&self) -> Vec { - let audio_subsystem = &self.audio_subsystem; - - audio_subsystem.audio_recording_device_ids().unwrap() - } - - pub fn begin_audio_capture(&mut self, device_id: AudioDeviceID) { let sample_rate: u32 = 44100; let frame_rate = self.frame_rate.unwrap(); // how many samples to capture at a time // should be enough for 1 frame or less // should not be larger than max_samples / channels - let max_samples: usize = ProjectM::pcm_get_max_samples().try_into().unwrap(); - let samples_per_frame = (sample_rate / frame_rate) as usize; - let buffer_size = std::cmp::min(max_samples / 2, samples_per_frame); - println!("Capturing audio from device {}", device_id.name()); - println!("Buffer size: {}", buffer_size); + // let max_samples: usize = ProjectM::pcm_get_max_samples().try_into().unwrap(); + // let samples_per_frame = (sample_rate / frame_rate) as usize; + // let buffer_size = std::cmp::min(max_samples / 2, samples_per_frame); + // println!("Buffer size: {}", buffer_size); let desired_spec = AudioSpec { freq: Some(sample_rate.try_into().unwrap()), @@ -110,17 +77,25 @@ impl Audio { format: Some(sdl3::audio::AudioFormat::f32_sys()), }; - // open audio device for capture - let device = AudioDevice::new(device_id); - let audio_stream = device - // move this to open_recording_device - .open_recording_stream_with_callback( - &desired_spec, - AudioCaptureCallback { - pm: Rc::clone(&self.projectm), - }, - ) - .unwrap(); + // open audio device for capture (use default device if none specified) + let device_id = (device_id + .or_else(|| Some(self.get_default_recording_device().id())) + .unwrap()); + + let audio_stream = match AudioStream::open_device_stream(device_id, Some(&desired_spec)) { + Ok(stream) => stream, + Err(e) => { + println!("Failed to open audio stream: {}", e); + return; + } + }; + println!("Capturing audio from device {:?}", audio_stream); + + let device_id = audio_stream.device_id(); + if device_id.is_none() { + println!("Failed to get begin audio capture: {:?}", audio_stream); + return; + } // start capturing audio_stream @@ -128,58 +103,98 @@ impl Audio { .expect("Failed to start audio capture"); // take ownership of device - self.capture_stream = Some(Box::new(audio_stream)); - self.current_recording_device = Some(device); + self.recording_stream = Some(Box::new(audio_stream)); + self.current_device_id = device_id; self.is_capturing = true; } + fn get_default_recording_device(&self) -> AudioDevice { + self.audio_subsystem.default_recording_device() + } + + /// Select a new audio device and start capturing audio from it. + pub fn open_next_device(&mut self) { + let current_device_id = self.current_device_id; + if current_device_id.is_none() { + self.begin_audio_capture(None); + return; + } + let current_device_id = current_device_id.unwrap(); + + // get list of devices + let device_list = self.get_device_list(); + + println!("Device list: {:?}", device_list); + println!("Current device: {:?}", current_device_id); + + // find current device in list + let mut current_device_index = device_list.iter().position(|d| d.eq(¤t_device_id)); + + // if current device not found, start from the beginning + if current_device_index.is_none() { + println!("Current device not found in device list"); + self.begin_audio_capture(None); + return; + } + + // select next device + let next_device_index = (current_device_index.unwrap() + 1) % device_list.len(); + let next_device_id = device_list[next_device_index]; + + // start capturing from next device + self.begin_audio_capture(Some(next_device_id)); + } + + fn get_device_list(&self) -> Vec { + let audio_subsystem = &self.audio_subsystem; + + audio_subsystem.audio_recording_device_ids().unwrap() + } + pub fn recording_device_name(&self) -> Option { - self.current_recording_device - .as_ref() - .map(|device| device.name()) + self.current_device_id.and_then(|id| Some(id.name())) } pub fn stop_audio_capture(&mut self) { - if self.current_recording_device.is_none() { + let mut recording_stream = &mut self.recording_stream; + if recording_stream.is_none() { return; } - let current_device_name = self.recording_device_name(); + // take ownership of stream + let stream = recording_stream.take().unwrap(); + + let current_device_name = stream.device_name(); println!( "Stopping audio capture for device {}", - current_device_name.unwrap_or("unknown".to_string()) + current_device_name.unwrap_or_else(|| "unknown".to_string()) ); - // take ownership of device - // capture device will be dropped when this function returns - // and the audio callback will stop being called - let device = self.capture_stream.take().unwrap(); - device.pause().expect("Failed to stop audio capture"); - + // the recording device will be closed when the stream is dropped self.is_capturing = false; - drop(device); + drop(stream); } } -struct AudioCaptureCallback { - // we need to keep a reference to the projectm instance to - // add the audio data to it - pm: ProjectMWrapped, -} -unsafe impl Send for AudioCaptureCallback {} -unsafe impl Sync for AudioCaptureCallback {} - -impl AudioRecordingCallback for AudioCaptureCallback { - // we are receiving some chunk of audio data - // we need to pass it to projectm - fn callback(&mut self, out: &[SampleFormat]) { - println!("Received {} samples", out.len()); - let mut out = out; - let max_samples = ProjectM::pcm_get_max_samples() as usize; - if (out.len() > max_samples) { - // remove some samples - out = &out[..max_samples]; - } - self.pm.pcm_add_float(out.to_vec(), 2); - } -} +// struct AudioCaptureCallback { +// // we need to keep a reference to the projectm instance to +// // add the audio data to it +// pm: ProjectMWrapped, +// } +// unsafe impl Send for AudioCaptureCallback {} +// unsafe impl Sync for AudioCaptureCallback {} +// +// impl AudioRecordingCallback for AudioCaptureCallback { +// // we are receiving some chunk of audio data +// // we need to pass it to projectm +// fn callback(&mut self, out: &[SampleFormat]) { +// println!("Received {} samples", out.len()); +// let mut out = out; +// let max_samples = ProjectM::pcm_get_max_samples() as usize; +// if (out.len() > max_samples) { +// // remove some samples +// out = &out[..max_samples]; +// } +// self.pm.pcm_add_float(out.to_vec(), 2); +// } +// } From 543530b07a945dc4582dc5b4145729422587fb91 Mon Sep 17 00:00:00 2001 From: Mischa Spiegelmock Date: Sun, 3 Nov 2024 08:41:20 -0800 Subject: [PATCH 2/4] fix cycling between audio devices, using device name not ID since ID changes when opening --- src/app/audio.rs | 166 ++++++++++++++++++++--------------------------- 1 file changed, 69 insertions(+), 97 deletions(-) diff --git a/src/app/audio.rs b/src/app/audio.rs index 660b681..5d1f027 100644 --- a/src/app/audio.rs +++ b/src/app/audio.rs @@ -1,13 +1,9 @@ use sdl3::audio::{AudioDevice, AudioDeviceID, AudioSpec, AudioStream}; -use std::io::Read; use super::config::FrameRate; use super::ProjectMWrapped; -// let the user cycle through audio devices -type AudioDeviceIndex = usize; - -type SampleFormat = f32; // format of audio samples +type SampleFormat = f32; // Format of audio samples pub struct Audio { audio_subsystem: sdl3::AudioSubsystem, @@ -16,9 +12,9 @@ pub struct Audio { frame_rate: Option, projectm: ProjectMWrapped, current_device_id: Option, + current_device_name: Option, // Store device name for comparison } -/// Wrapper around the audio subsystem to record audio and pass it to projectM. impl Audio { pub fn new(sdl_context: &sdl3::Sdl, projectm: ProjectMWrapped) -> Self { let audio_subsystem = sdl_context.audio().unwrap(); @@ -32,6 +28,7 @@ impl Audio { audio_subsystem, frame_rate: None, current_device_id: None, + current_device_name: None, recording_stream: None, projectm, } @@ -40,7 +37,7 @@ impl Audio { pub fn init(&mut self, frame_rate: FrameRate) { self.list_devices(); - self.frame_rate = frame_rate.into(); + self.frame_rate = Some(frame_rate); #[cfg(not(feature = "dummy_audio"))] self.begin_audio_capture(None); @@ -57,30 +54,21 @@ impl Audio { /// Start capturing audio from device_id. pub fn begin_audio_capture(&mut self, device_id: Option) { - // stop capturing from current stream/device + // Stop capturing from current stream/device self.stop_audio_capture(); let sample_rate: u32 = 44100; - let frame_rate = self.frame_rate.unwrap(); - - // how many samples to capture at a time - // should be enough for 1 frame or less - // should not be larger than max_samples / channels - // let max_samples: usize = ProjectM::pcm_get_max_samples().try_into().unwrap(); - // let samples_per_frame = (sample_rate / frame_rate) as usize; - // let buffer_size = std::cmp::min(max_samples / 2, samples_per_frame); - // println!("Buffer size: {}", buffer_size); let desired_spec = AudioSpec { - freq: Some(sample_rate.try_into().unwrap()), + freq: Some(sample_rate as i32), channels: Some(2), - format: Some(sdl3::audio::AudioFormat::f32_sys()), + format: Some(sdl3::audio::AudioFormat::f32_sys()), // Assuming F32SYS is the correct format }; - // open audio device for capture (use default device if none specified) - let device_id = (device_id + // Open audio device for capture (use default device if none specified) + let device_id = device_id .or_else(|| Some(self.get_default_recording_device().id())) - .unwrap()); + .unwrap(); // Ensure device_id is Some let audio_stream = match AudioStream::open_device_stream(device_id, Some(&desired_spec)) { Ok(stream) => stream, @@ -91,20 +79,28 @@ impl Audio { }; println!("Capturing audio from device {:?}", audio_stream); - let device_id = audio_stream.device_id(); - if device_id.is_none() { - println!("Failed to get begin audio capture: {:?}", audio_stream); + // Get the actual device ID and name from the stream + let actual_device_id = audio_stream.device_id(); + let actual_device_name = audio_stream.device_name(); + + if actual_device_id.is_none() { + println!("Failed to get device ID from audio stream: {:?}", audio_stream); return; } - // start capturing - audio_stream - .resume() - .expect("Failed to start audio capture"); + let actual_device_id = actual_device_id.unwrap(); + let actual_device_name = actual_device_name.unwrap_or_else(|| "unknown".to_string()); - // take ownership of device + // Start capturing + if let Err(e) = audio_stream.resume() { + println!("Failed to start audio capture: {}", e); + return; + } + + // Take ownership of the stream and store device information self.recording_stream = Some(Box::new(audio_stream)); - self.current_device_id = device_id; + self.current_device_id = Some(actual_device_id); + self.current_device_name = Some(actual_device_name); self.is_capturing = true; } @@ -114,87 +110,63 @@ impl Audio { /// Select a new audio device and start capturing audio from it. pub fn open_next_device(&mut self) { - let current_device_id = self.current_device_id; - if current_device_id.is_none() { - self.begin_audio_capture(None); - return; - } - let current_device_id = current_device_id.unwrap(); + let current_device_name = self.recording_device_name(); - // get list of devices let device_list = self.get_device_list(); println!("Device list: {:?}", device_list); - println!("Current device: {:?}", current_device_id); - - // find current device in list - let mut current_device_index = device_list.iter().position(|d| d.eq(¤t_device_id)); - - // if current device not found, start from the beginning - if current_device_index.is_none() { - println!("Current device not found in device list"); - self.begin_audio_capture(None); - return; - } - - // select next device - let next_device_index = (current_device_index.unwrap() + 1) % device_list.len(); + println!("Current device name: {:?}", current_device_name); + + // Find the index of the current device by name + let current_device_index = current_device_name.as_ref().and_then(|name| { + device_list + .iter() + .position(|d| d.name() == *name) + }); + + let current_device_index = current_device_index.unwrap_or_else(|| { + println!("Current device not found in device list. Starting from the first device."); + 0 + }); + + // Select next device index + let next_device_index = (current_device_index + 1) % device_list.len(); let next_device_id = device_list[next_device_index]; - // start capturing from next device + println!( + "Switching from device '{}' to '{}'", + current_device_name.unwrap_or_else(|| "unknown".to_string()), + next_device_id.name() + ); + + // Start capturing from next device self.begin_audio_capture(Some(next_device_id)); } fn get_device_list(&self) -> Vec { - let audio_subsystem = &self.audio_subsystem; - - audio_subsystem.audio_recording_device_ids().unwrap() + self.audio_subsystem.audio_recording_device_ids().unwrap_or_else(|e| { + println!("Failed to get audio device list: {}", e); + Vec::new() + }) } pub fn recording_device_name(&self) -> Option { - self.current_device_id.and_then(|id| Some(id.name())) + self.current_device_name.clone() } pub fn stop_audio_capture(&mut self) { - let mut recording_stream = &mut self.recording_stream; - if recording_stream.is_none() { - return; + if let Some(stream) = self.recording_stream.take() { + // Retrieve the device name before dropping the stream + let current_device_name = stream.device_name().unwrap_or_else(|| "unknown".to_string()); + + println!( + "Stopping audio capture for device {}", + current_device_name + ); + + // The recording device will be closed when the stream is dropped + self.is_capturing = false; + drop(stream); } - - // take ownership of stream - let stream = recording_stream.take().unwrap(); - - let current_device_name = stream.device_name(); - println!( - "Stopping audio capture for device {}", - current_device_name.unwrap_or_else(|| "unknown".to_string()) - ); - - // the recording device will be closed when the stream is dropped - self.is_capturing = false; - drop(stream); } -} - -// struct AudioCaptureCallback { -// // we need to keep a reference to the projectm instance to -// // add the audio data to it -// pm: ProjectMWrapped, -// } -// unsafe impl Send for AudioCaptureCallback {} -// unsafe impl Sync for AudioCaptureCallback {} -// -// impl AudioRecordingCallback for AudioCaptureCallback { -// // we are receiving some chunk of audio data -// // we need to pass it to projectm -// fn callback(&mut self, out: &[SampleFormat]) { -// println!("Received {} samples", out.len()); -// let mut out = out; -// let max_samples = ProjectM::pcm_get_max_samples() as usize; -// if (out.len() > max_samples) { -// // remove some samples -// out = &out[..max_samples]; -// } -// self.pm.pcm_add_float(out.to_vec(), 2); -// } -// } +} \ No newline at end of file From b436ccc086fdda27ce221fc222117a4d1a150d8d Mon Sep 17 00:00:00 2001 From: Mischa Spiegelmock Date: Sun, 3 Nov 2024 09:46:28 -0800 Subject: [PATCH 3/4] reading samples each frame --- Cargo.lock | 4 +-- Cargo.toml | 4 +-- src/app/audio.rs | 85 +++++++++++++++++++++++++++++++++++--------- src/app/main_loop.rs | 4 +++ src/dummy_audio.rs | 2 +- 5 files changed, 76 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c257fb8..7bd7e47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,9 +224,7 @@ dependencies = [ [[package]] name = "projectm" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40bd522bb3162cb2aa72d899d7e77c197fdca2ca7b08d70001e6ca06015af2e6" +version = "3.0.0" dependencies = [ "libc", "projectm-sys", diff --git a/Cargo.toml b/Cargo.toml index 6cf2314..9b81019 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,8 @@ rust-version = "1.68.2" [dependencies] libc = "*" -#projectm = { path = "../projectm-rs", version = "2.0.2", features = ["playlist"] } -projectm = { version = "2.0.2", features = ['playlist'] } +projectm = { path = "../projectm-rs", version = "3", features = ["playlist"] } +#projectm = { version = "2.0.2", features = ['playlist'] } #sdl3 = { version = "0.10.8", features = ["build-from-source"] } sdl3 = { path = "../../sdl3-rs", version = "0", features = ["build-from-source"] } rand = "0.8.5" diff --git a/src/app/audio.rs b/src/app/audio.rs index 5d1f027..ddaf408 100644 --- a/src/app/audio.rs +++ b/src/app/audio.rs @@ -1,9 +1,11 @@ +use projectm::core::ProjectM; use sdl3::audio::{AudioDevice, AudioDeviceID, AudioSpec, AudioStream}; use super::config::FrameRate; use super::ProjectMWrapped; type SampleFormat = f32; // Format of audio samples +const CHANNELS: u32 = 2; // Number of audio channels pub struct Audio { audio_subsystem: sdl3::AudioSubsystem, @@ -40,7 +42,7 @@ impl Audio { self.frame_rate = Some(frame_rate); #[cfg(not(feature = "dummy_audio"))] - self.begin_audio_capture(None); + self.begin_audio_recording(None); } pub fn list_devices(&self) { @@ -53,19 +55,19 @@ impl Audio { } /// Start capturing audio from device_id. - pub fn begin_audio_capture(&mut self, device_id: Option) { + pub fn begin_audio_recording(&mut self, device_id: Option) { // Stop capturing from current stream/device - self.stop_audio_capture(); + self.stop_audio_recording(); let sample_rate: u32 = 44100; let desired_spec = AudioSpec { freq: Some(sample_rate as i32), - channels: Some(2), + channels: Some(CHANNELS.try_into().unwrap()), format: Some(sdl3::audio::AudioFormat::f32_sys()), // Assuming F32SYS is the correct format }; - // Open audio device for capture (use default device if none specified) + // Open audio device for recording (use default device if none specified) let device_id = device_id .or_else(|| Some(self.get_default_recording_device().id())) .unwrap(); // Ensure device_id is Some @@ -140,21 +142,11 @@ impl Audio { ); // Start capturing from next device - self.begin_audio_capture(Some(next_device_id)); + self.begin_audio_recording(Some(next_device_id)); } - fn get_device_list(&self) -> Vec { - self.audio_subsystem.audio_recording_device_ids().unwrap_or_else(|e| { - println!("Failed to get audio device list: {}", e); - Vec::new() - }) - } - - pub fn recording_device_name(&self) -> Option { - self.current_device_name.clone() - } - pub fn stop_audio_capture(&mut self) { + pub fn stop_audio_recording(&mut self) { if let Some(stream) = self.recording_stream.take() { // Retrieve the device name before dropping the stream let current_device_name = stream.device_name().unwrap_or_else(|| "unknown".to_string()); @@ -169,4 +161,63 @@ impl Audio { drop(stream); } } + + /// Read all available audio samples from the recording stream and feed them to ProjectM. + /// This method should be called once per frame. + pub fn process_frame_samples(&mut self) { + if !self.is_capturing || self.recording_stream.is_none() { + return; + } + + let stream = self.recording_stream.as_mut().unwrap(); + let available_bytes = stream.available_bytes(); + if available_bytes.is_err() || available_bytes.unwrap() == 0 { + // nothing to read + return; + } + + // Retrieve the maximum number of PCM samples ProjectM can handle + let max_samples: usize = ProjectM::pcm_get_max_samples() + .try_into() + .expect("Failed to convert max samples to usize"); + + // Allocate the sample buffer once to reuse in the loop + let mut sample_buf = vec![0.0f32; max_samples]; + + // Start the loop to read and process samples + loop { + // Attempt to read samples into the buffer + match stream.read_f32_samples(&mut sample_buf) { + Ok(samples_read) => { + if samples_read == 0 { + // No more data to read; exit the loop + // println!("No more audio data to read. Exiting loop."); + break; + } + + // println!("Read {} samples", samples_read); + // Add the read samples to ProjectM for processing + self.projectm + .pcm_add_float(&sample_buf[..samples_read], CHANNELS); + } + Err(e) => { + // Handle any read errors + println!("Failed to read audio samples: {}", e); + break; // Exit the loop on error + } + } + } + + } + + fn get_device_list(&self) -> Vec { + self.audio_subsystem.audio_recording_device_ids().unwrap_or_else(|e| { + println!("Failed to get audio device list: {}", e); + Vec::new() + }) + } + + pub fn recording_device_name(&self) -> Option { + self.current_device_name.clone() + } } \ No newline at end of file diff --git a/src/app/main_loop.rs b/src/app/main_loop.rs index eca0636..bc143ba 100644 --- a/src/app/main_loop.rs +++ b/src/app/main_loop.rs @@ -97,6 +97,10 @@ impl App { // generate random audio #[cfg(feature = "dummy_audio")] dummy_audio::generate_random_audio_data(&self.pm); + + // Feed audio data from capture device to projectM + #[cfg(not(feature = "dummy_audio"))] + self.audio.process_frame_samples(); // render a frame self.pm.render_frame(); diff --git a/src/dummy_audio.rs b/src/dummy_audio.rs index ed34045..83a177c 100644 --- a/src/dummy_audio.rs +++ b/src/dummy_audio.rs @@ -13,5 +13,5 @@ pub fn generate_random_audio_data(pm: &ProjectMWrapped) { } } - pm.pcm_add_int16(pcm_data, 2); + pm.pcm_add_int16(&pcm_data, 2); } From 953b73b5fa7623f2282b53f5119ab13ab7c2867a Mon Sep 17 00:00:00 2001 From: Mischa Spiegelmock Date: Sun, 22 Dec 2024 22:15:00 -0800 Subject: [PATCH 4/4] sdl3 and projectm updates --- Cargo.lock | 58 +++++++++++++++++++++++------------------------- Cargo.toml | 8 +++---- src/app/audio.rs | 2 -- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bd7e47..a4dd6f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cexpr", "clang-sys", "itertools", @@ -31,12 +31,6 @@ dependencies = [ "syn", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" @@ -51,9 +45,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.34" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "shlex", ] @@ -86,9 +80,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -152,15 +146,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets", @@ -215,16 +209,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "projectm" -version = "3.0.0" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ea270346057465a68f573e4d1c35b2b30abeb479d3622e0c882ea7a6891516" dependencies = [ "libc", "projectm-sys", @@ -233,9 +229,9 @@ dependencies = [ [[package]] name = "projectm-sys" -version = "1.0.10" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09dae2ff07b700fd48dcc2a58108865da9c2aa576dcd1bb05e1297e3f361886" +checksum = "6365f7261b468baa8f1d1e2ae98be4000514ab94733e8de37fdf03450602d10c" dependencies = [ "bindgen", "cmake", @@ -306,9 +302,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -335,9 +331,11 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "sdl3" -version = "0.10.8" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3862047756c6f79a6acfc8a83bdd940d114725b78462e5fa7c746a0db46bfc3b" dependencies = [ - "bitflags 1.3.2", + "bitflags", "lazy_static", "libc", "sdl3-sys", @@ -351,9 +349,9 @@ checksum = "6cd923f539b7738e631de0c729f548da2d764cd45c3a480aaab65296dfa66e1f" [[package]] name = "sdl3-sys" -version = "0.1.1+SDL3-preview-3.1.6" +version = "0.1.3+SDL3-preview-3.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d814a5030bcbeb04be50e8026cd538eee842005da844accc987880c191f5d2" +checksum = "5c47498b18bcdb59a4f59af2923b3c5b4c921482e6e3579a2ab19a0e2c813f56" dependencies = [ "cmake", "rpkg-config", @@ -368,9 +366,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" dependencies = [ "proc-macro2", "quote", @@ -379,9 +377,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasi" diff --git a/Cargo.toml b/Cargo.toml index 9b81019..1de8e57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,10 @@ rust-version = "1.68.2" [dependencies] libc = "*" -projectm = { path = "../projectm-rs", version = "3", features = ["playlist"] } -#projectm = { version = "2.0.2", features = ['playlist'] } -#sdl3 = { version = "0.10.8", features = ["build-from-source"] } -sdl3 = { path = "../../sdl3-rs", version = "0", features = ["build-from-source"] } +#projectm = { path = "../projectm-rs", version = "3", features = ["playlist"] } +projectm = { version = "3", features = ['playlist'] } +sdl3 = { version = "0.11", features = ["build-from-source-static"] } +#sdl3 = { path = "../../sdl3-rs", version = "0", features = ["build-from-source"] } rand = "0.8.5" include_dir = "0.7" diff --git a/src/app/audio.rs b/src/app/audio.rs index ddaf408..622f9f1 100644 --- a/src/app/audio.rs +++ b/src/app/audio.rs @@ -191,11 +191,9 @@ impl Audio { Ok(samples_read) => { if samples_read == 0 { // No more data to read; exit the loop - // println!("No more audio data to read. Exiting loop."); break; } - // println!("Read {} samples", samples_read); // Add the read samples to ProjectM for processing self.projectm .pcm_add_float(&sample_buf[..samples_read], CHANNELS);