Browse Source

Readded offset and fixed misunderstanding about sample size

pull/83/head
Andrea Ciliberti 2 years ago
parent
commit
31e3542dd5
  1. 39
      ctru-rs/examples/audio_filters.rs
  2. 11
      ctru-rs/src/services/ndsp/mod.rs

39
ctru-rs/examples/audio_filters.rs

@ -11,29 +11,34 @@ use ctru::services::ndsp::{ @@ -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() { @@ -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() { @@ -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;

11
ctru-rs/src/services/ndsp/mod.rs

@ -220,11 +220,16 @@ impl AudioFormat { @@ -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,
}
}
}

Loading…
Cancel
Save