diff --git a/ctru-rs/examples/audio_filters.rs b/ctru-rs/examples/audio_filters.rs index 5625d8f..7ef4967 100644 --- a/ctru-rs/examples/audio_filters.rs +++ b/ctru-rs/examples/audio_filters.rs @@ -11,29 +11,34 @@ use ctru::services::ndsp::{ const SAMPLE_RATE: usize = 22050; const SAMPLES_PER_BUF: usize = SAMPLE_RATE / 30; // 735 -const BYTES_PER_SAMPLE: usize = 2; +const BYTES_PER_SAMPLE: usize = 4; const AUDIO_WAVE_LENGTH: usize = SAMPLES_PER_BUF * BYTES_PER_SAMPLE; // Note Frequencies const NOTEFREQ: [f32; 7] = [220., 440., 880., 1760., 3520., 7040., 14080.]; -// audioBuffer is stereo PCM16 -fn fill_buffer(audio_data: &mut [u8], frequency: f32) { - let formatted_data = audio_data.chunks_exact_mut(2); +// audioBuffer is Stereo PCM16 +// As such, a sample is made up of 2 "Mono" samples (2 * i16 = u32), one for each channel (left and right) +fn fill_buffer(audio_data: &mut [u8], frequency: f32, offset: &mut usize) { + let formatted_data = audio_data.chunks_exact_mut(4); - let mut i = 0.; + let mut i: usize = 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: f32 = (frequency / 30. * (i / SAMPLES_PER_BUF as f32) * 2. * PI).sin(); + let sample: f32 = (frequency * ((i + *offset) as f32 / SAMPLE_RATE as f32) * 2. * PI).sin(); let amplitude = 0.3 * i16::MAX as f32; - // 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()) }; + // This operation is safe, since we are writing to a slice of exactly 32 bits + let chunk_ptr: &mut [i16; 2] = unsafe { std::mem::transmute(chunk.as_mut_ptr()) }; // Stereo samples are interleaved: left and right channels. - *chunk_ptr = (sample * amplitude) as i16; + chunk_ptr[0] = (sample * amplitude) as i16; + chunk_ptr[1] = (sample * amplitude) as i16; - i += 1.; + i += 1; } + + // Adds the SAMPLES_PER_BUF length back to the offset + *offset += i; } fn main() { @@ -77,9 +82,13 @@ fn main() { // We set up two wave buffers and alternate between the two, // effectively streaming an infinitely long sine wave. + let mut offset: usize = 0; + let mut audio_data1 = Box::new_in([0u8; AUDIO_WAVE_LENGTH], LinearAllocator); - fill_buffer(&mut audio_data1[..], NOTEFREQ[4]); - let mut audio_data2 = audio_data1.clone(); + fill_buffer(&mut audio_data1[..], NOTEFREQ[4], &mut offset); + + let mut audio_data2 = Box::new_in([0u8; AUDIO_WAVE_LENGTH], LinearAllocator); + fill_buffer(&mut audio_data2[..], NOTEFREQ[4], &mut offset); let mut audio_buffer1 = WaveBuffer::new(audio_data1, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache"); @@ -158,7 +167,11 @@ 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_wavebuffer().get_mut_data(), + NOTEFREQ[note], + &mut offset, + ); channel_zero.queue_wave(current); altern = !altern; diff --git a/ctru-rs/src/services/ndsp/mod.rs b/ctru-rs/src/services/ndsp/mod.rs index eb2ff80..4c63f47 100644 --- a/ctru-rs/src/services/ndsp/mod.rs +++ b/ctru-rs/src/services/ndsp/mod.rs @@ -220,11 +220,16 @@ impl AudioFormat { /// 16 bit formats return 2 (bytes) pub fn sample_size(self) -> u8 { match self { - AudioFormat::PCM16Mono | AudioFormat::PCM16Stereo => 2, + AudioFormat::PCM8Mono | AudioFormat::ADPCMMono => 1, + AudioFormat::PCM16Mono | AudioFormat::PCM8Stereo => 2, + AudioFormat::PCM16Stereo => 4, AudioFormat::SurroundPreprocessed => { - panic!("Can't find size for Sourround Preprocessed audio: format is under research") + panic!("Can't find sample size for Sourround Preprocessed audio: format is under research") + } + // TODO: Understand what this is. + AudioFormat::FrontBypass => { + panic!("Can't find sample size for FrontBypass audio") } - _ => 1, } } }