diff --git a/ctru-rs/examples/audio_filters.rs b/ctru-rs/examples/audio_filters.rs index c42e1af..437ba77 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}, + wave::{WaveBuffer, WaveInfo, WaveStatus}, AudioFormat, InterpolationType, Ndsp, OutputMode, }; @@ -19,15 +19,20 @@ const NOTEFREQ: [u32; 7] = [220, 440, 880, 1760, 3520, 7040, 14080]; // audioBuffer is stereo PCM16 fn fill_buffer(audioData: &mut [u8], frequency: u32) { - let formatted_data: Vec = audioData.chunks_exact(2).map(|s| i16::from_le_bytes(s.try_into().unwrap())).collect(); + let formatted_data = audioData.chunks_exact_mut(2); - for i in 0..audioData.len() { - // This is a simple sine wave, with a frequency of `frequency` Hz, and an amplitude 30% of maximum. - let sample: i16 = (0.3 * i16::MAX as f32 * (frequency as f32 * (2f32 * PI) * (i / SAMPLE_RATE as usize) as f32).sin()) as i16; + let mut i = 0; + for chunk in formatted_data { + // This is a simple sine wave, with a frequency of `frequency` Hz, and an amplitude 30% of maximum. + let sample: i16 = (0.3 * i16::MAX as f32 * (frequency as f32 * (2f32 * PI) * (i as f32 / SAMPLE_RATE as f32)).sin()) as i16; - // Stereo samples are interleaved: left and right channels. - formatted_data[i] = (sample << 16) | (sample & 0xffff); - } + // This operation is safe, since we are writing to a slice of exactly 16 bits + let chunk_ptr: &mut i16 = unsafe { std::mem::transmute(chunk.as_mut_ptr()) }; + // Stereo samples are interleaved: left and right channels. + *chunk_ptr = (sample << 16) | (sample & 0xffff); + + i += 1; + } } fn main() { @@ -39,19 +44,16 @@ fn main() { println!("libctru filtered streamed audio\n"); - let audioBuffer = Box::new_in( + let mut audioBuffer = Box::new_in( [0u8; AUDIO_WAVE_LENGTH], LinearAllocator, ); - fill_buffer(&mut audioBuffer, NOTEFREQ[4]); - - let audioBuffer1 = - WaveBuffer::new(audioBuffer, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache"); - let audioBuffer2 = audioBuffer1.clone(); + fill_buffer(&mut audioBuffer[..], NOTEFREQ[4]); - let fillBlock = false; + let mut audioBuffer1 = WaveBuffer::new(audioBuffer, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache"); + let mut audioBuffer2 = audioBuffer1.clone(); - let ndsp = Ndsp::init().expect("Couldn't obtain NDSP controller"); + let mut ndsp = Ndsp::init().expect("Couldn't obtain NDSP controller"); // This line isn't needed since the default NDSP configuration already sets the output mode to `Stereo` ndsp.set_output_mode(OutputMode::Stereo); @@ -63,12 +65,12 @@ fn main() { // Output at 100% on the first pair of left and right channels. - let mix = [0f32; 12]; + let mut mix: [f32; 12] = [0f32; 12]; mix[0] = 1.0; mix[1] = 1.0; channel_zero.set_mix(&mix); - let note: usize = 4; + let mut note: usize = 4; // Filters @@ -81,24 +83,23 @@ fn main() { "Peaking", ]; - let filter = 0; + let mut filter = 0; // We set up two wave buffers and alternate between the two, // effectively streaming an infinitely long sine wave. - let mut buf1 = WaveInfo::new(&mut audioBuffer1, false); - let mut buf2 = WaveInfo::new(&mut audioBuffer2, false); + let mut bufs: [WaveInfo; 2] = [ WaveInfo::new(&mut audioBuffer1, false), WaveInfo::new(&mut audioBuffer2, false)]; - unsafe { - channel_zero.queue_wave(&mut buf1); - channel_zero.queue_wave(&mut buf2); - }; + channel_zero.queue_wave(&mut bufs[0]); + channel_zero.queue_wave(&mut bufs[1]); println!("Press up/down to change tone frequency\n"); println!("Press left/right to change filter\n"); println!("\x1b[6;1Hnote = {} Hz ", NOTEFREQ[note]); println!("\x1b[7;1Hfilter = {} ", filter_names[filter]); + let mut fillBlock = false; + while apt.main_loop() { hid.scan_input(); let keys_down = hid.keys_down(); @@ -124,7 +125,7 @@ fn main() { // Check for upper limit note = std::cmp::max(note, NOTEFREQ.len() - 1); - let update_params = false; + let mut update_params = false; if keys_down.contains(KeyPad::KEY_LEFT) { filter = filter.saturating_sub(1); if filter < 0 { @@ -151,15 +152,12 @@ fn main() { } } - if waveBuf[fillBlock].status == NDSP_WBUF_DONE { - if fillBlock { - fill_buffer(buf1.get_mut_wavebuffer().get_mut_data(), NOTEFREQ[note]); - channel_zero.queue_wave(&mut buf1); - } else { - fill_buffer(buf2.get_mut_wavebuffer().get_mut_data(), NOTEFREQ[note]); - channel_zero.queue_wave(&mut buf2); - } - fillBlock = !fillBlock; + let status = bufs[fillBlock as usize].get_status(); + if let WaveStatus::Done = status { + fillBlock = !fillBlock; + + fill_buffer(bufs[fillBlock as usize].get_mut_wavebuffer().get_mut_data(), NOTEFREQ[note]); + channel_zero.queue_wave(&mut bufs[fillBlock as usize]); } // Flush and swap framebuffers