Skip to content

Commit 33da9d5

Browse files
authored
Fix debug mode for audio filters example (#226)
* Fix debug mode for audio filters example * Avoid using insert * Compact get_buffer impls
1 parent 49a0ae1 commit 33da9d5

File tree

2 files changed

+54
-16
lines changed

2 files changed

+54
-16
lines changed

ctru-rs/examples/audio-filters.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,41 @@
66

77
use std::f32::consts::PI;
88

9-
use ctru::linear::LinearAllocator;
9+
use ctru::linear::{LinearAllocation, LinearAllocator};
1010
use ctru::prelude::*;
1111
use ctru::services::ndsp::{
1212
AudioFormat, AudioMix, InterpolationType, Ndsp, OutputMode,
1313
wave::{Status, Wave},
1414
};
1515

16+
// Buffer holding type (defined separately to implement the AsRef trait)
17+
#[derive(Debug, Clone, PartialEq, Eq)]
18+
struct Buffer(Vec<[i16; 2], LinearAllocator>);
19+
1620
// Configuration for the NDSP process and channels.
1721
const SAMPLE_RATE: usize = 22050;
1822
const SAMPLES_PER_BUF: usize = SAMPLE_RATE / 10; // 2205
19-
const BYTES_PER_SAMPLE: usize = AudioFormat::PCM16Stereo.size();
20-
const AUDIO_WAVE_LENGTH: usize = SAMPLES_PER_BUF * BYTES_PER_SAMPLE;
2123

2224
// Note frequencies.
2325
const NOTEFREQ: [f32; 7] = [220., 440., 880., 1760., 3520., 7040., 14080.];
2426

25-
fn fill_buffer(audio_data: &mut [u8], frequency: f32) {
27+
fn fill_buffer(audio_data: &mut Buffer, frequency: f32) {
2628
// The audio format is Stereo PCM16.
2729
// As such, a sample is made up of 2 "Mono" samples (2 * i16), one for each channel (left and right).
28-
let formatted_data = bytemuck::cast_slice_mut::<_, [i16; 2]>(audio_data);
2930

30-
for (i, chunk) in formatted_data.iter_mut().enumerate() {
31+
for i in 0..SAMPLES_PER_BUF {
3132
// This is a simple sine wave, with a frequency of `frequency` Hz, and an amplitude 30% of maximum.
3233
let sample: f32 = (frequency * (i as f32 / SAMPLE_RATE as f32) * 2. * PI).sin();
3334
let amplitude = 0.3 * i16::MAX as f32;
3435

3536
let result = (sample * amplitude) as i16;
3637

3738
// Stereo samples are interleaved: left and right channels.
38-
*chunk = [result, result];
39+
if audio_data.0.len() <= i {
40+
audio_data.0.push([result, result]);
41+
} else {
42+
audio_data.0[i] = [result, result];
43+
}
3944
}
4045
}
4146

@@ -64,7 +69,7 @@ fn main() {
6469

6570
// We create a buffer on the LINEAR memory that will hold our audio data.
6671
// It's necessary for the buffer to live on the LINEAR memory sector since it needs to be accessed by the DSP processor.
67-
let mut audio_data1: Box<[_], _> = Box::new_in([0u8; AUDIO_WAVE_LENGTH], LinearAllocator);
72+
let mut audio_data1 = Buffer(Vec::with_capacity_in(SAMPLES_PER_BUF, LinearAllocator));
6873

6974
// Fill the buffer with the first set of data. This simply writes a sine wave into the buffer.
7075
fill_buffer(&mut audio_data1, NOTEFREQ[4]);
@@ -97,6 +102,10 @@ fn main() {
97102

98103
println!("\x1b[1;1HPress up/down to change tone frequency");
99104
println!("\x1b[2;1HPress left/right to change filter");
105+
106+
#[cfg(debug_assertions)]
107+
println!("\x1b[3;1HWarning: Running in debug mode may produce gaps.");
108+
100109
println!("\x1b[4;1Hnote = {} Hz ", NOTEFREQ[note]);
101110
println!(
102111
"\x1b[5;1Hfilter = {} ",
@@ -163,7 +172,7 @@ fn main() {
163172
// If the current buffer has finished playing, we can refill it with new data and re-queue it.
164173
let status = current.status();
165174
if let Status::Done = status {
166-
fill_buffer(current.get_buffer_mut().unwrap(), NOTEFREQ[note]);
175+
fill_buffer(current.get_raw_buffer_mut().unwrap(), NOTEFREQ[note]);
167176

168177
channel_zero.queue_wave(current).unwrap();
169178

@@ -173,3 +182,17 @@ fn main() {
173182
gfx.wait_for_vblank();
174183
}
175184
}
185+
186+
impl AsRef<[u8]> for Buffer {
187+
fn as_ref(&self) -> &[u8] {
188+
bytemuck::cast_slice(&self.0)
189+
}
190+
}
191+
192+
impl AsMut<[u8]> for Buffer {
193+
fn as_mut(&mut self) -> &mut [u8] {
194+
bytemuck::cast_slice_mut(&mut self.0)
195+
}
196+
}
197+
198+
unsafe impl LinearAllocation for Buffer {}

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

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,29 @@ where
8787
}
8888
}
8989

90+
/// Returns the original data structure used for the audio data.
91+
pub fn get_raw_buffer(&self) -> &Buffer {
92+
&self.buffer
93+
}
94+
95+
/// Returns a mutable reference to the original data structure used for the audio data.
96+
///
97+
/// # Errors
98+
///
99+
/// This function will return an error if the [`Wave`] is currently busy,
100+
/// with the id to the channel in which it's queued.
101+
pub fn get_raw_buffer_mut(&mut self) -> Result<&mut Buffer, Error> {
102+
match self.status() {
103+
Status::Playing | Status::Queued => {
104+
Err(Error::WaveBusy(self.played_on_channel.unwrap()))
105+
}
106+
_ => Ok(&mut self.buffer),
107+
}
108+
}
109+
90110
/// Returns a slice to the audio data (on the LINEAR memory).
91111
pub fn get_buffer(&self) -> &[u8] {
92-
self.buffer.as_ref()
112+
self.get_raw_buffer().as_ref()
93113
}
94114

95115
/// Returns a mutable slice to the audio data (on the LINEAR memory).
@@ -102,12 +122,7 @@ where
102122
where
103123
Buffer: AsMut<[u8]>,
104124
{
105-
match self.status() {
106-
Status::Playing | Status::Queued => {
107-
Err(Error::WaveBusy(self.played_on_channel.unwrap()))
108-
}
109-
_ => Ok(self.buffer.as_mut()),
110-
}
125+
Ok(self.get_raw_buffer_mut()?.as_mut())
111126
}
112127

113128
/// Returns this wave's playback status.

0 commit comments

Comments
 (0)