Browse Source

Merged WaveBuffer and Waveinfo

pull/83/head
Andrea Ciliberti 2 years ago
parent
commit
ef1bba99b6
  1. 13
      ctru-rs/examples/audio-filters.rs
  2. 93
      ctru-rs/src/services/ndsp/wave.rs

13
ctru-rs/examples/audio-filters.rs

@ -5,7 +5,7 @@ use std::f32::consts::PI; @@ -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() { @@ -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() { @@ -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);

93
ctru-rs/src/services/ndsp/wave.rs

@ -1,21 +1,11 @@ @@ -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<u8>,
@ -30,43 +20,25 @@ pub enum WaveStatus { @@ -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<Self> {
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);
}
Ok(Self {
data,
audio_format,
nsamples,
})
let _r = ctru_sys::DSP_FlushDataCache(buffer.as_ptr().cast(), buffer.len() as u32);
}
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> { @@ -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<u8> for WaveStatus { @@ -110,19 +91,7 @@ impl TryFrom<u8> 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> { @@ -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(),
);
}
}
}

Loading…
Cancel
Save