|
|
@ -11,29 +11,34 @@ use ctru::services::ndsp::{ |
|
|
|
|
|
|
|
|
|
|
|
const SAMPLE_RATE: usize = 22050; |
|
|
|
const SAMPLE_RATE: usize = 22050; |
|
|
|
const SAMPLES_PER_BUF: usize = SAMPLE_RATE / 30; // 735
|
|
|
|
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; |
|
|
|
const AUDIO_WAVE_LENGTH: usize = SAMPLES_PER_BUF * BYTES_PER_SAMPLE; |
|
|
|
|
|
|
|
|
|
|
|
// Note Frequencies
|
|
|
|
// Note Frequencies
|
|
|
|
const NOTEFREQ: [f32; 7] = [220., 440., 880., 1760., 3520., 7040., 14080.]; |
|
|
|
const NOTEFREQ: [f32; 7] = [220., 440., 880., 1760., 3520., 7040., 14080.]; |
|
|
|
|
|
|
|
|
|
|
|
// audioBuffer is stereo PCM16
|
|
|
|
// audioBuffer is Stereo PCM16
|
|
|
|
fn fill_buffer(audio_data: &mut [u8], frequency: f32) { |
|
|
|
// As such, a sample is made up of 2 "Mono" samples (2 * i16 = u32), one for each channel (left and right)
|
|
|
|
let formatted_data = audio_data.chunks_exact_mut(2); |
|
|
|
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 { |
|
|
|
for chunk in formatted_data { |
|
|
|
// This is a simple sine wave, with a frequency of `frequency` Hz, and an amplitude 30% of maximum.
|
|
|
|
// 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; |
|
|
|
let amplitude = 0.3 * i16::MAX as f32; |
|
|
|
|
|
|
|
|
|
|
|
// This operation is safe, since we are writing to a slice of exactly 16 bits
|
|
|
|
// This operation is safe, since we are writing to a slice of exactly 32 bits
|
|
|
|
let chunk_ptr: &mut i16 = unsafe { std::mem::transmute(chunk.as_mut_ptr()) }; |
|
|
|
let chunk_ptr: &mut [i16; 2] = unsafe { std::mem::transmute(chunk.as_mut_ptr()) }; |
|
|
|
// Stereo samples are interleaved: left and right channels.
|
|
|
|
// 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() { |
|
|
|
fn main() { |
|
|
@ -77,9 +82,13 @@ fn main() { |
|
|
|
|
|
|
|
|
|
|
|
// We set up two wave buffers and alternate between the two,
|
|
|
|
// We set up two wave buffers and alternate between the two,
|
|
|
|
// effectively streaming an infinitely long sine wave.
|
|
|
|
// effectively streaming an infinitely long sine wave.
|
|
|
|
|
|
|
|
let mut offset: usize = 0; |
|
|
|
|
|
|
|
|
|
|
|
let mut audio_data1 = Box::new_in([0u8; AUDIO_WAVE_LENGTH], LinearAllocator); |
|
|
|
let mut audio_data1 = Box::new_in([0u8; AUDIO_WAVE_LENGTH], LinearAllocator); |
|
|
|
fill_buffer(&mut audio_data1[..], NOTEFREQ[4]); |
|
|
|
fill_buffer(&mut audio_data1[..], NOTEFREQ[4], &mut offset); |
|
|
|
let mut audio_data2 = audio_data1.clone(); |
|
|
|
|
|
|
|
|
|
|
|
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 = |
|
|
|
let mut audio_buffer1 = |
|
|
|
WaveBuffer::new(audio_data1, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache"); |
|
|
|
WaveBuffer::new(audio_data1, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache"); |
|
|
@ -158,7 +167,11 @@ fn main() { |
|
|
|
|
|
|
|
|
|
|
|
let status = current.get_status(); |
|
|
|
let status = current.get_status(); |
|
|
|
if let WaveStatus::Done = 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); |
|
|
|
channel_zero.queue_wave(current); |
|
|
|
|
|
|
|
|
|
|
|
altern = !altern; |
|
|
|
altern = !altern; |
|
|
|