From ef1bba99b628ca687a839e6026d431db014a2d1c Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Sat, 14 Jan 2023 18:15:05 +0100 Subject: [PATCH] Merged WaveBuffer and Waveinfo --- ctru-rs/examples/audio-filters.rs | 13 ++--- ctru-rs/src/services/ndsp/wave.rs | 93 ++++++++++++------------------- 2 files changed, 39 insertions(+), 67 deletions(-) diff --git a/ctru-rs/examples/audio-filters.rs b/ctru-rs/examples/audio-filters.rs index c5f25d8..8381bfa 100644 --- a/ctru-rs/examples/audio-filters.rs +++ b/ctru-rs/examples/audio-filters.rs @@ -5,7 +5,7 @@ use std::f32::consts::PI; use ctru::linear::LinearAllocator; use ctru::prelude::*; use ctru::services::ndsp::{ - wave::{WaveBuffer, WaveInfo, WaveStatus}, + wave::{WaveInfo, WaveStatus}, AudioFormat, InterpolationType, Ndsp, OutputMode, }; @@ -82,13 +82,8 @@ fn main() { let mut audio_data2 = Box::new_in([0u8; AUDIO_WAVE_LENGTH], LinearAllocator); fill_buffer(&mut audio_data2[..], NOTEFREQ[4]); - let mut audio_buffer1 = - WaveBuffer::new(audio_data1, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache"); - let mut audio_buffer2 = - WaveBuffer::new(audio_data2, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache"); - - let mut wave_info1 = WaveInfo::new(&mut audio_buffer1, false); - let mut wave_info2 = WaveInfo::new(&mut audio_buffer2, false); + let mut wave_info1 = WaveInfo::new(audio_data1, AudioFormat::PCM16Stereo, false); + let mut wave_info2 = WaveInfo::new(audio_data2, AudioFormat::PCM16Stereo, false); channel_zero.queue_wave(&mut wave_info1); channel_zero.queue_wave(&mut wave_info2); @@ -157,7 +152,7 @@ fn main() { let status = current.get_status(); if let WaveStatus::Done = status { - fill_buffer(current.get_mut_wavebuffer().get_mut_data(), NOTEFREQ[note]); + fill_buffer(current.get_mut_buffer(), NOTEFREQ[note]); channel_zero.queue_wave(current); diff --git a/ctru-rs/src/services/ndsp/wave.rs b/ctru-rs/src/services/ndsp/wave.rs index cf12e57..ebb30dd 100644 --- a/ctru-rs/src/services/ndsp/wave.rs +++ b/ctru-rs/src/services/ndsp/wave.rs @@ -1,21 +1,11 @@ -use ctru_sys::ndspChnWaveBufClear; - use super::AudioFormat; use crate::linear::LinearAllocator; -/// Base struct to represent audio wave data. This requires audio format information. -pub struct WaveBuffer { - /// Buffer data. This data must be allocated on the LINEAR memory. - data: Box<[u8], LinearAllocator>, +/// Informational struct holding the raw audio data and playback info. This corresponds to [ctru_sys::ndspWaveBuf] +pub struct WaveInfo { + /// Data block of the audio wave (and its format information). + buffer: Box<[u8], LinearAllocator>, audio_format: AudioFormat, - nsamples: usize, // We don't use the slice's length here because depending on the format it may vary - // adpcm_data: AdpcmData, TODO: Requires research on how this format is handled. -} - -/// Informational struct holding the raw audio data and playaback info. This corresponds to [ctru_sys::ndspWaveBuf] -pub struct WaveInfo<'b> { - /// Data block of the audio wave (plus its format information). - buffer: &'b mut WaveBuffer, // Holding the data with the raw format is necessary since `libctru` will access it. pub(crate) raw_data: ctru_sys::ndspWaveBuf, played_on_channel: Option, @@ -30,43 +20,25 @@ pub enum WaveStatus { Done = ctru_sys::NDSP_WBUF_DONE as u8, } -impl WaveBuffer { - pub fn new(data: Box<[u8], LinearAllocator>, audio_format: AudioFormat) -> crate::Result { - let nsamples: usize = data.len() / (audio_format.sample_size() as usize); +impl WaveInfo { + pub fn new( + buffer: Box<[u8], LinearAllocator>, + audio_format: AudioFormat, + looping: bool, + ) -> Self { + let nsamples: usize = buffer.len() / (audio_format.sample_size() as usize); unsafe { - let _r = ctru_sys::DSP_FlushDataCache(data.as_ptr().cast(), data.len() as u32); + let _r = ctru_sys::DSP_FlushDataCache(buffer.as_ptr().cast(), buffer.len() as u32); } - Ok(Self { - data, - audio_format, - nsamples, - }) - } - - pub fn get_mut_data(&mut self) -> &mut [u8] { - &mut self.data - } - - pub fn get_format(&self) -> AudioFormat { - self.audio_format - } - - pub fn get_sample_amount(&self) -> usize { - self.nsamples - } -} - -impl<'b> WaveInfo<'b> { - pub fn new(buffer: &'b mut WaveBuffer, looping: bool) -> Self { let address = ctru_sys::tag_ndspWaveBuf__bindgen_ty_1 { - data_vaddr: buffer.data.as_ptr().cast(), + data_vaddr: buffer.as_ptr().cast(), }; let raw_data = ctru_sys::ndspWaveBuf { __bindgen_anon_1: address, // Buffer data virtual address - nsamples: buffer.get_sample_amount() as u32, + nsamples: nsamples as u32, adpcm_data: std::ptr::null_mut(), offset: 0, looping, @@ -78,19 +50,28 @@ impl<'b> WaveInfo<'b> { Self { buffer, + audio_format, raw_data, played_on_channel: None, } } - pub fn get_mut_wavebuffer(&mut self) -> &mut WaveBuffer { - self.buffer + pub fn get_mut_buffer(&mut self) -> &mut [u8] { + &mut self.buffer } pub fn get_status(&self) -> WaveStatus { self.raw_data.status.try_into().unwrap() } + pub fn get_sample_amount(&self) -> u32 { + self.raw_data.nsamples + } + + pub fn get_format(&self) -> AudioFormat { + self.audio_format + } + pub(crate) fn set_channel(&mut self, id: i32) { self.played_on_channel = Some(id as u8) } @@ -110,19 +91,7 @@ impl TryFrom for WaveStatus { } } -impl Drop for WaveBuffer { - fn drop(&mut self) { - unsafe { - // Result can't be used in any way, let's just shrug it off - let _r = ctru_sys::DSP_InvalidateDataCache( - self.data.as_ptr().cast(), - self.data.len().try_into().unwrap(), - ); - } - } -} - -impl<'b> Drop for WaveInfo<'b> { +impl Drop for WaveInfo { fn drop(&mut self) { // This was the only way I found I could check for improper drops of `WaveInfos`. // A panic was considered, but it would cause issues with drop order against `Ndsp`. @@ -131,8 +100,16 @@ impl<'b> Drop for WaveInfo<'b> { // If the status flag is "unfinished" _ => { // The unwrap is safe, since it must have a value in the case the status is "unfinished". - unsafe { ndspChnWaveBufClear(self.played_on_channel.unwrap().into()) }; + unsafe { ctru_sys::ndspChnWaveBufClear(self.played_on_channel.unwrap().into()) }; } } + + unsafe { + // Result can't be used in any way, let's just shrug it off + let _r = ctru_sys::DSP_InvalidateDataCache( + self.buffer.as_ptr().cast(), + self.buffer.len().try_into().unwrap(), + ); + } } }