From 7c2e944867d93e4088634688775c610895b397ad Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Sun, 26 Mar 2023 17:48:33 +0200 Subject: [PATCH 1/7] Improve Ndsp API and docs --- ctru-rs/examples/audio-filters.rs | 19 ++--- ctru-rs/src/services/ndsp/mod.rs | 130 +++++++++++++++++++++--------- ctru-rs/src/services/ndsp/wave.rs | 47 +++++------ 3 files changed, 122 insertions(+), 74 deletions(-) diff --git a/ctru-rs/examples/audio-filters.rs b/ctru-rs/examples/audio-filters.rs index 616b8d4..48b65a7 100644 --- a/ctru-rs/examples/audio-filters.rs +++ b/ctru-rs/examples/audio-filters.rs @@ -5,13 +5,13 @@ use std::f32::consts::PI; use ctru::linear::LinearAllocator; use ctru::prelude::*; use ctru::services::ndsp::{ - wave::{WaveInfo, WaveStatus}, - AudioFormat, InterpolationType, Ndsp, OutputMode, + wave::{Wave, WaveStatus}, + AudioFormat, AudioMix, InterpolationType, Ndsp, OutputMode, }; const SAMPLE_RATE: usize = 22050; const SAMPLES_PER_BUF: usize = SAMPLE_RATE / 10; // 2205 -const BYTES_PER_SAMPLE: usize = 4; +const BYTES_PER_SAMPLE: usize = AudioFormat::PCM16Stereo.size(); const AUDIO_WAVE_LENGTH: usize = SAMPLES_PER_BUF * BYTES_PER_SAMPLE; // Note Frequencies @@ -65,8 +65,8 @@ fn main() { let audio_data2 = audio_data1.clone(); - let mut wave_info1 = WaveInfo::new(audio_data1, AudioFormat::PCM16Stereo, false); - let mut wave_info2 = WaveInfo::new(audio_data2, AudioFormat::PCM16Stereo, false); + let mut wave_info1 = Wave::new(audio_data1, AudioFormat::PCM16Stereo, false); + let mut wave_info2 = Wave::new(audio_data2, AudioFormat::PCM16Stereo, false); let mut ndsp = Ndsp::init().expect("Couldn't obtain NDSP controller"); @@ -79,10 +79,7 @@ fn main() { channel_zero.set_format(AudioFormat::PCM16Stereo); // Output at 100% on the first pair of left and right channels. - - let mut mix: [f32; 12] = [0f32; 12]; - mix[0] = 1.0; - mix[1] = 1.0; + let mix = AudioMix::default(); channel_zero.set_mix(&mix); channel_zero.queue_wave(&mut wave_info1).unwrap(); @@ -142,13 +139,13 @@ fn main() { } } - let current: &mut WaveInfo = if altern { + let current: &mut Wave = if altern { &mut wave_info1 } else { &mut wave_info2 }; - let status = current.get_status(); + let status = current.status(); if let WaveStatus::Done = status { fill_buffer(current.get_buffer_mut().unwrap(), NOTEFREQ[note]); diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index ee366d4..ee6605a 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -1,12 +1,13 @@ //! NDSP (Audio) service pub mod wave; -use wave::{WaveInfo, WaveStatus}; +use wave::{Wave, WaveStatus}; use crate::error::ResultCode; use crate::services::ServiceReference; use std::cell::{RefCell, RefMut}; +use std::default::Default; use std::error; use std::fmt; use std::sync::Mutex; @@ -30,6 +31,18 @@ pub enum AudioFormat { PCM16Stereo = ctru_sys::NDSP_FORMAT_STEREO_PCM16, } +/// Representation of volume mix for a channel. +/// Each member is made up of 2 values, the first is for the "left" channel, while the second is for the "right" channel. +#[derive(Copy, Clone, Debug)] +pub struct AudioMix { + pub front: (f32, f32), + pub back: (f32, f32), + pub aux1_front: (f32, f32), + pub aux1_back: (f32, f32), + pub aux2_front: (f32, f32), + pub aux2_back: (f32, f32), +} + #[derive(Copy, Clone, Debug)] #[repr(u32)] pub enum InterpolationType { @@ -47,7 +60,7 @@ pub enum NdspError { /// Channel ID WaveBusy(u8), /// Sample amount requested, Max sample amount - SampleCountOutOfBounds(u32, u32), + SampleCountOutOfBounds(usize, usize), } pub struct Channel<'ndsp> { @@ -141,17 +154,19 @@ impl Channel<'_> { } // Returns the channel's id - pub fn get_id(&self) -> u8 { + pub fn id(&self) -> u8 { self.id } - /// Returns the channel's current sample's position. - pub fn get_sample_position(&self) -> u32 { - unsafe { ctru_sys::ndspChnGetSamplePos(self.id.into()) } + /// Returns the index of the currently played sample. + /// + /// Because of how fast this value changes, it should only be used as a rough estimate of the current progress. + pub fn sample_position(&self) -> usize { + (unsafe { ctru_sys::ndspChnGetSamplePos(self.id.into()) }) as usize } /// Returns the channel's current wave sequence's id. - pub fn get_wave_sequence_id(&self) -> u16 { + pub fn wave_sequence_id(&self) -> u16 { unsafe { ctru_sys::ndspChnGetWaveBufSeq(self.id.into()) } } @@ -172,19 +187,8 @@ impl Channel<'_> { } /// Set the channel's volume mix. - /// - /// # Notes - /// - /// The buffer's format is read as: - /// - /// Index 0: Front left volume
- /// Index 1: Front right volume
- /// Index 2: Back left volume
- /// Index 3: Back right volume
- /// Index 4..7: Same as 0..3 but for auxiliary output 0
- /// Index 8..11: Same as 0..3 but for auxiliary output 1
- pub fn set_mix(&self, mix: &[f32; 12]) { - unsafe { ctru_sys::ndspChnSetMix(self.id.into(), mix.as_ptr().cast_mut()) } + pub fn set_mix(&self, mix: &AudioMix) { + unsafe { ctru_sys::ndspChnSetMix(self.id.into(), mix.to_raw().as_mut_ptr()) } } /// Set the channel's rate of sampling. @@ -206,10 +210,10 @@ impl Channel<'_> { /// /// # Warning /// - /// `libctru` expects the user to manually keep the info data (in this case [WaveInfo]) alive during playback. - /// To ensure safety, checks within [WaveInfo] will clear the whole channel queue if any queued [WaveInfo] is dropped prematurely. - pub fn queue_wave(&self, wave: &mut WaveInfo) -> std::result::Result<(), NdspError> { - match wave.get_status() { + /// `libctru` expects the user to manually keep the info data (in this case [Wave]) alive during playback. + /// To ensure safety, checks within [Wave] will clear the whole channel queue if any queued [Wave] is dropped prematurely. + pub fn queue_wave(&self, wave: &mut Wave) -> std::result::Result<(), NdspError> { + match wave.status() { WaveStatus::Playing | WaveStatus::Queued => return Err(NdspError::WaveBusy(self.id)), _ => (), } @@ -302,14 +306,70 @@ impl Channel<'_> { impl AudioFormat { /// Returns the amount of bytes needed to store one sample + /// /// Eg. - /// 8 bit formats return 1 (byte) - /// 16 bit formats return 2 (bytes) - pub fn sample_size(self) -> u8 { + /// 8 bit mono formats return 1 (byte) + /// 16 bit stereo (dual-channel) formats return 4 (bytes) + pub const fn size(self) -> usize { match self { - AudioFormat::PCM8Mono => 1, - AudioFormat::PCM16Mono | AudioFormat::PCM8Stereo => 2, - AudioFormat::PCM16Stereo => 4, + Self::PCM8Mono => 1, + Self::PCM16Mono | Self::PCM8Stereo => 2, + Self::PCM16Stereo => 4, + } + } +} + +impl AudioMix { + pub fn zeroed() -> Self { + Self { + front: (0., 0.), + back: (0., 0.), + aux1_front: (0., 0.), + aux1_back: (0., 0.), + aux2_front: (0., 0.), + aux2_back: (0., 0.), + } + } + + pub fn from_raw(data: [f32; 12]) -> Self { + Self { + front: (data[0], data[1]), + back: (data[2], data[3]), + aux1_front: (data[4], data[5]), + aux1_back: (data[6], data[7]), + aux2_front: (data[8], data[9]), + aux2_back: (data[10], data[11]), + } + } + + pub fn to_raw(&self) -> [f32; 12] { + [ + self.front.0, + self.front.1, + self.back.0, + self.back.1, + self.aux1_front.0, + self.aux1_front.1, + self.aux1_back.0, + self.aux1_back.1, + self.aux2_front.0, + self.aux2_front.1, + self.aux2_back.0, + self.aux2_back.1, + ] + } +} + +/// Returns an [AudioMix] object with front left and front right volumes set to max, and all other volumes set to 0. +impl Default for AudioMix { + fn default() -> Self { + Self { + front: (1., 1.), + back: (0., 0.), + aux1_front: (0., 0.), + aux1_back: (0., 0.), + aux2_front: (0., 0.), + aux2_back: (0., 0.), } } } @@ -319,7 +379,7 @@ impl fmt::Display for NdspError { match self { Self::InvalidChannel(id) => write!(f, "audio Channel with ID {id} doesn't exist. Valid channels have an ID between 0 and 23"), Self::ChannelAlreadyInUse(id) => write!(f, "audio Channel with ID {id} is already being used. Drop the other instance if you want to use it here"), - Self::WaveBusy(id) => write!(f, "the selected WaveInfo is busy playing on channel {id}"), + Self::WaveBusy(id) => write!(f, "the selected Wave is busy playing on channel {id}"), Self::SampleCountOutOfBounds(samples_requested, max_samples) => write!(f, "the sample count requested is too big (requested = {samples_requested}, maximum = {max_samples})"), } } @@ -327,16 +387,10 @@ impl fmt::Display for NdspError { impl error::Error for NdspError {} -impl<'ndsp> Drop for Channel<'ndsp> { - fn drop(&mut self) { - self.reset(); - } -} - impl Drop for Ndsp { fn drop(&mut self) { for i in 0..NUMBER_OF_CHANNELS { - self.channel(i).unwrap().clear_queue(); + self.channel(i).unwrap().reset(); } } } diff --git a/ctru-rs/src/services/ndsp/wave.rs b/ctru-rs/src/services/ndsp/wave.rs index 4a5de98..a47c113 100644 --- a/ctru-rs/src/services/ndsp/wave.rs +++ b/ctru-rs/src/services/ndsp/wave.rs @@ -1,8 +1,8 @@ use super::{AudioFormat, NdspError}; use crate::linear::LinearAllocator; -/// Informational struct holding the raw audio data and playback info. This corresponds to [ctru_sys::ndspWaveBuf] -pub struct WaveInfo { +/// Informational struct holding the raw audio data and playback info. This corresponds to [ctru_sys::ndspWaveBuf]. +pub struct Wave { /// Data block of the audio wave (and its format information). buffer: Box<[u8], LinearAllocator>, audio_format: AudioFormat, @@ -13,7 +13,7 @@ pub struct WaveInfo { #[derive(Copy, Clone, Debug)] #[repr(u8)] -/// Enum representing the playback status of a [WaveInfo]. +/// Enum representing the playback status of a [Wave]. pub enum WaveStatus { Free = ctru_sys::NDSP_WBUF_FREE as u8, Queued = ctru_sys::NDSP_WBUF_QUEUED as u8, @@ -21,14 +21,14 @@ pub enum WaveStatus { Done = ctru_sys::NDSP_WBUF_DONE as u8, } -impl WaveInfo { +impl Wave { /// Build a new playable wave object from a raw buffer on LINEAR memory and a some info. pub fn new( buffer: Box<[u8], LinearAllocator>, audio_format: AudioFormat, looping: bool, ) -> Self { - let sample_count: usize = buffer.len() / (audio_format.sample_size() as usize); + let sample_count = buffer.len() / audio_format.size(); // Signal to the DSP processor the buffer's RAM sector. // This step may seem delicate, but testing reports failure most of the time, while still having no repercussions on the resulting audio. @@ -69,10 +69,10 @@ impl WaveInfo { /// /// # Errors /// - /// This function will return an error if the [WaveInfo] is currently busy, + /// This function will return an error if the [Wave] is currently busy, /// with the id to the channel in which it's queued. pub fn get_buffer_mut(&mut self) -> Result<&mut [u8], NdspError> { - match self.get_status() { + match self.status() { WaveStatus::Playing | WaveStatus::Queued => { Err(NdspError::WaveBusy(self.played_on_channel.unwrap())) } @@ -81,7 +81,7 @@ impl WaveInfo { } /// Return this wave's playback status. - pub fn get_status(&self) -> WaveStatus { + pub fn status(&self) -> WaveStatus { self.raw_data.status.try_into().unwrap() } @@ -90,12 +90,12 @@ impl WaveInfo { /// # Notes /// /// This value varies depending on [Self::set_sample_count]. - pub fn get_sample_count(&self) -> u32 { - self.raw_data.nsamples + pub fn sample_count(&self) -> usize { + self.raw_data.nsamples as usize } /// Get the format of the audio data. - pub fn get_format(&self) -> AudioFormat { + pub fn format(&self) -> AudioFormat { self.audio_format } @@ -117,25 +117,22 @@ impl WaveInfo { /// # Errors /// /// This function will return an error if the sample size exceeds the buffer's capacity - /// or if the WaveInfo is currently queued. - pub fn set_sample_count(&mut self, sample_count: u32) -> Result<(), NdspError> { - match self.get_status() { + /// or if the [Wave] is currently queued. + pub fn set_sample_count(&mut self, sample_count: usize) -> Result<(), NdspError> { + match self.status() { WaveStatus::Playing | WaveStatus::Queued => { return Err(NdspError::WaveBusy(self.played_on_channel.unwrap())); } _ => (), } - let max_count: usize = self.buffer.len() / (self.audio_format.sample_size() as usize); + let max_count = self.buffer.len() / self.audio_format.size(); - if sample_count > max_count as u32 { - return Err(NdspError::SampleCountOutOfBounds( - sample_count, - max_count as u32, - )); + if sample_count > max_count { + return Err(NdspError::SampleCountOutOfBounds(sample_count, max_count)); } - self.raw_data.nsamples = sample_count; + self.raw_data.nsamples = sample_count as u32; Ok(()) } @@ -150,16 +147,16 @@ impl TryFrom for WaveStatus { 1 => Ok(Self::Queued), 2 => Ok(Self::Playing), 3 => Ok(Self::Done), - _ => Err("Invalid WaveInfo Status code"), + _ => Err("Invalid Wave Status code"), } } } -impl Drop for WaveInfo { +impl Drop for Wave { fn drop(&mut self) { - // This was the only way I found I could check for improper drops of `WaveInfos`. + // This was the only way I found I could check for improper drops of `Wave`. // A panic was considered, but it would cause issues with drop order against `Ndsp`. - match self.get_status() { + match self.status() { WaveStatus::Free | WaveStatus::Done => (), // If the status flag is "unfinished" _ => { From 912ff07ec1d765321d044cf767406b01994f3897 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Mon, 27 Mar 2023 19:20:21 +0200 Subject: [PATCH 2/7] Avoid data cloning in AudioMix --- ctru-rs/src/services/ndsp/mod.rs | 127 ++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 43 deletions(-) diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index ee6605a..4b4e1a7 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -35,12 +35,7 @@ pub enum AudioFormat { /// Each member is made up of 2 values, the first is for the "left" channel, while the second is for the "right" channel. #[derive(Copy, Clone, Debug)] pub struct AudioMix { - pub front: (f32, f32), - pub back: (f32, f32), - pub aux1_front: (f32, f32), - pub aux1_back: (f32, f32), - pub aux2_front: (f32, f32), - pub aux2_back: (f32, f32), + raw: [f32;12] } #[derive(Copy, Clone, Debug)] @@ -188,7 +183,7 @@ impl Channel<'_> { /// Set the channel's volume mix. pub fn set_mix(&self, mix: &AudioMix) { - unsafe { ctru_sys::ndspChnSetMix(self.id.into(), mix.to_raw().as_mut_ptr()) } + unsafe { ctru_sys::ndspChnSetMix(self.id.into(), mix.as_raw().as_ptr().cast_mut()) } } /// Set the channel's rate of sampling. @@ -320,56 +315,102 @@ impl AudioFormat { } impl AudioMix { + /// Creates a new [AudioMix] with all volumes set to 0. pub fn zeroed() -> Self { Self { - front: (0., 0.), - back: (0., 0.), - aux1_front: (0., 0.), - aux1_back: (0., 0.), - aux2_front: (0., 0.), - aux2_back: (0., 0.), + raw: [0.;12], } } - pub fn from_raw(data: [f32; 12]) -> Self { - Self { - front: (data[0], data[1]), - back: (data[2], data[3]), - aux1_front: (data[4], data[5]), - aux1_back: (data[6], data[7]), - aux2_front: (data[8], data[9]), - aux2_back: (data[10], data[11]), + /// Returns a reference to the raw data. + pub fn as_raw(&self) -> &[f32; 12] { + &self.raw + } + + /// Returns a mutable reference to the raw data. + pub fn as_raw_mut(&mut self) -> &mut [f32; 12] { + &mut self.raw + } + + /// Returns a reference to the "front" volume mix (left and right channel). + pub fn front(&self) -> &[f32] { + &self.raw[..2] + } + + /// Returns a reference to the "back" volume mix (left and right channel). + pub fn back(&self) -> &[f32] { + &self.raw[2..4] + } + + /// Returns a reference to the "front" volume mix (left and right channel) for the specified auxiliary output device. + pub fn aux_front(&self, id: usize) -> &[f32] { + if id > 1 { + panic!("invalid auxiliary output device index") + } + + let index = 4 + id * 4; + + &self.raw[index..index+2] + } + + /// Returns a reference to the "back" volume mix (left and right channel) for the specified auxiliary output device. + pub fn aux_back(&self, id: usize) -> &[f32] { + if id > 1 { + panic!("invalid auxiliary output device index") + } + + let index = 6 + id * 4; + + &self.raw[index..index+2] + } + + /// Returns a mutable reference to the "front" volume mix (left and right channel). + pub fn front_mut(&mut self) -> &mut [f32] { + &mut self.raw[..2] + } + + /// Returns a mutable reference to the "back" volume mix (left and right channel). + pub fn back_mut(&mut self) -> &mut [f32] { + &mut self.raw[2..4] + } + + /// Returns a mutable reference to the "front" volume mix (left and right channel) for the specified auxiliary output device. + pub fn aux_front_mut(&mut self, id: usize) -> &mut [f32] { + if id > 1 { + panic!("invalid auxiliary output device index") } + + let index = 4 + id * 4; + + &mut self.raw[index..index+2] } - pub fn to_raw(&self) -> [f32; 12] { - [ - self.front.0, - self.front.1, - self.back.0, - self.back.1, - self.aux1_front.0, - self.aux1_front.1, - self.aux1_back.0, - self.aux1_back.1, - self.aux2_front.0, - self.aux2_front.1, - self.aux2_back.0, - self.aux2_back.1, - ] + /// Returns a mutable reference to the "back" volume mix (left and right channel) for the specified auxiliary output device. + pub fn aux_back_mut(&mut self, id: usize) -> &mut [f32] { + if id > 1 { + panic!("invalid auxiliary output device index") + } + + let index = 6 + id * 4; + + &mut self.raw[index..index+2] } } -/// Returns an [AudioMix] object with front left and front right volumes set to max, and all other volumes set to 0. +/// Returns an [AudioMix] object with "front left" and "front right" volumes set to max, and all other volumes set to 0. impl Default for AudioMix { fn default() -> Self { + let mut mix = AudioMix::zeroed(); + mix.front_mut().fill(1.); + + mix + } +} + +impl From<[f32; 12]> for AudioMix { + fn from(value: [f32; 12]) -> Self { Self { - front: (1., 1.), - back: (0., 0.), - aux1_front: (0., 0.), - aux1_back: (0., 0.), - aux2_front: (0., 0.), - aux2_back: (0., 0.), + raw: value, } } } From c849f947fe4bf569b92640c0d9f763322eb86546 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Mon, 27 Mar 2023 19:23:13 +0200 Subject: [PATCH 3/7] fmt --- ctru-rs/src/services/ndsp/mod.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index 4b4e1a7..5873fcb 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -35,7 +35,7 @@ pub enum AudioFormat { /// Each member is made up of 2 values, the first is for the "left" channel, while the second is for the "right" channel. #[derive(Copy, Clone, Debug)] pub struct AudioMix { - raw: [f32;12] + raw: [f32; 12], } #[derive(Copy, Clone, Debug)] @@ -317,9 +317,7 @@ impl AudioFormat { impl AudioMix { /// Creates a new [AudioMix] with all volumes set to 0. pub fn zeroed() -> Self { - Self { - raw: [0.;12], - } + Self { raw: [0.; 12] } } /// Returns a reference to the raw data. @@ -347,10 +345,10 @@ impl AudioMix { if id > 1 { panic!("invalid auxiliary output device index") } - + let index = 4 + id * 4; - &self.raw[index..index+2] + &self.raw[index..index + 2] } /// Returns a reference to the "back" volume mix (left and right channel) for the specified auxiliary output device. @@ -358,10 +356,10 @@ impl AudioMix { if id > 1 { panic!("invalid auxiliary output device index") } - + let index = 6 + id * 4; - &self.raw[index..index+2] + &self.raw[index..index + 2] } /// Returns a mutable reference to the "front" volume mix (left and right channel). @@ -379,10 +377,10 @@ impl AudioMix { if id > 1 { panic!("invalid auxiliary output device index") } - + let index = 4 + id * 4; - &mut self.raw[index..index+2] + &mut self.raw[index..index + 2] } /// Returns a mutable reference to the "back" volume mix (left and right channel) for the specified auxiliary output device. @@ -390,10 +388,10 @@ impl AudioMix { if id > 1 { panic!("invalid auxiliary output device index") } - + let index = 6 + id * 4; - &mut self.raw[index..index+2] + &mut self.raw[index..index + 2] } } @@ -409,9 +407,7 @@ impl Default for AudioMix { impl From<[f32; 12]> for AudioMix { fn from(value: [f32; 12]) -> Self { - Self { - raw: value, - } + Self { raw: value } } } From 9832c8a45024d9d60f3bf77d9e30316c8698fd9b Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Mon, 27 Mar 2023 19:35:44 +0200 Subject: [PATCH 4/7] Remove obsolete docs --- ctru-rs/src/services/ndsp/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index 5873fcb..4c0ad37 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -32,7 +32,6 @@ pub enum AudioFormat { } /// Representation of volume mix for a channel. -/// Each member is made up of 2 values, the first is for the "left" channel, while the second is for the "right" channel. #[derive(Copy, Clone, Debug)] pub struct AudioMix { raw: [f32; 12], From e1000916d3af7affcd9a8d0006f1b5b76faf69d9 Mon Sep 17 00:00:00 2001 From: Ian Chamberlain Date: Mon, 27 Mar 2023 13:11:34 -0400 Subject: [PATCH 5/7] Remove extern "C" process stubs from test runner --- ctru-rs/src/test_runner.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/ctru-rs/src/test_runner.rs b/ctru-rs/src/test_runner.rs index 192483f..8b3f117 100644 --- a/ctru-rs/src/test_runner.rs +++ b/ctru-rs/src/test_runner.rs @@ -76,25 +76,3 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn { _ => panic!("non-static tests passed to test::test_main_static"), } } - -/// The following functions are stubs needed to link the test library, -/// but do nothing because we don't actually need them for the runner to work. -mod link_fix { - #[no_mangle] - extern "C" fn execvp( - _argc: *const libc::c_char, - _argv: *mut *const libc::c_char, - ) -> libc::c_int { - -1 - } - - #[no_mangle] - extern "C" fn pipe(_fildes: *mut libc::c_int) -> libc::c_int { - -1 - } - - #[no_mangle] - extern "C" fn sigemptyset(_arg1: *mut libc::sigset_t) -> ::libc::c_int { - -1 - } -} From e9ad80a84a80b7a140e8b3391636103f5eb17e01 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Wed, 29 Mar 2023 19:37:05 +0200 Subject: [PATCH 6/7] New attempt at a standard AudioMix interface --- ctru-rs/src/services/ndsp/mod.rs | 74 +++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index 4c0ad37..6616bd9 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -329,68 +329,92 @@ impl AudioMix { &mut self.raw } - /// Returns a reference to the "front" volume mix (left and right channel). - pub fn front(&self) -> &[f32] { - &self.raw[..2] + /// Returns the values set for the "front" volume mix (left and right channel). + pub fn front(&self) -> (f32, f32) { + (self.raw[0], self.raw[1]) } - /// Returns a reference to the "back" volume mix (left and right channel). - pub fn back(&self) -> &[f32] { - &self.raw[2..4] + /// Returns the values set for the "back" volume mix (left and right channel). + pub fn back(&self) -> (f32, f32) { + (self.raw[2], self.raw[3]) } - /// Returns a reference to the "front" volume mix (left and right channel) for the specified auxiliary output device. - pub fn aux_front(&self, id: usize) -> &[f32] { + /// Returns the values set for the "front" volume mix (left and right channel) for the specified auxiliary output device (either 0 or 1). + pub fn aux_front(&self, id: usize) -> (f32, f32) { if id > 1 { panic!("invalid auxiliary output device index") } let index = 4 + id * 4; - &self.raw[index..index + 2] + (self.raw[index], self.raw[index + 1]) } - /// Returns a reference to the "back" volume mix (left and right channel) for the specified auxiliary output device. - pub fn aux_back(&self, id: usize) -> &[f32] { + /// Returns the values set for the "back" volume mix (left and right channel) for the specified auxiliary output device (either 0 or 1). + pub fn aux_back(&self, id: usize) -> (f32, f32) { if id > 1 { panic!("invalid auxiliary output device index") } let index = 6 + id * 4; - &self.raw[index..index + 2] + (self.raw[index], self.raw[index + 1]) } - /// Returns a mutable reference to the "front" volume mix (left and right channel). - pub fn front_mut(&mut self) -> &mut [f32] { - &mut self.raw[..2] + /// Sets the values for the "front" volume mix (left and right channel). + /// + /// # Notes + /// + /// [Channel] will normalize the mix values to be within 0 and 1. + /// However, an [AudioMix] instance with larger/smaller values is valid. + pub fn set_front(&mut self, left: f32, right: f32) { + self.raw[0] = left; + self.raw[1] = right; } - /// Returns a mutable reference to the "back" volume mix (left and right channel). - pub fn back_mut(&mut self) -> &mut [f32] { - &mut self.raw[2..4] + /// Sets the values for the "back" volume mix (left and right channel). + /// + /// # Notes + /// + /// [Channel] will normalize the mix values to be within 0 and 1. + /// However, an [AudioMix] instance with larger/smaller values is valid. + pub fn set_back(&mut self, left: f32, right: f32) { + self.raw[2] = left; + self.raw[3] = right; } - /// Returns a mutable reference to the "front" volume mix (left and right channel) for the specified auxiliary output device. - pub fn aux_front_mut(&mut self, id: usize) -> &mut [f32] { + /// Sets the values for the "front" volume mix (left and right channel) for the specified auxiliary output device (either 0 or 1). + /// + /// # Notes + /// + /// [Channel] will normalize the mix values to be within 0 and 1. + /// However, an [AudioMix] instance with larger/smaller values is valid. + pub fn set_aux_front(&mut self, left: f32, right: f32, id: usize) { if id > 1 { panic!("invalid auxiliary output device index") } let index = 4 + id * 4; - &mut self.raw[index..index + 2] + self.raw[index] = left; + self.raw[index + 1] = right; } - /// Returns a mutable reference to the "back" volume mix (left and right channel) for the specified auxiliary output device. - pub fn aux_back_mut(&mut self, id: usize) -> &mut [f32] { + /// Sets the values for the "back" volume mix (left and right channel) for the specified auxiliary output device (either 0 or 1). + /// + /// # Notes + /// + /// [Channel] will normalize the mix values to be within 0 and 1. + /// However, an [AudioMix] instance with larger/smaller values is valid. + pub fn set_aux_back(&mut self, left: f32, right: f32, id: usize) { if id > 1 { panic!("invalid auxiliary output device index") } let index = 6 + id * 4; - &mut self.raw[index..index + 2] + self.raw[index] = left; + self.raw[index + 1] = right; } } @@ -398,7 +422,7 @@ impl AudioMix { impl Default for AudioMix { fn default() -> Self { let mut mix = AudioMix::zeroed(); - mix.front_mut().fill(1.); + mix.set_front(1.0, 1.0); mix } From d33c39b57d8fdf63913c7d33fd556dc8679312ba Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Wed, 29 Mar 2023 19:39:26 +0200 Subject: [PATCH 7/7] Percentiles --- ctru-rs/src/services/ndsp/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index 6616bd9..cd45f7b 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -418,7 +418,7 @@ impl AudioMix { } } -/// Returns an [AudioMix] object with "front left" and "front right" volumes set to max, and all other volumes set to 0. +/// Returns an [AudioMix] object with "front left" and "front right" volumes set to 100%, and all other volumes set to 0%. impl Default for AudioMix { fn default() -> Self { let mut mix = AudioMix::zeroed();