Browse Source

Feels like hell in here

pull/83/head
Andrea Ciliberti 2 years ago
parent
commit
44e904b0c9
  1. 60
      ctru-rs/examples/audio_filters.rs

60
ctru-rs/examples/audio_filters.rs

@ -5,7 +5,7 @@ use std::f32::consts::PI;
use ctru::linear::LinearAllocator; use ctru::linear::LinearAllocator;
use ctru::prelude::*; use ctru::prelude::*;
use ctru::services::ndsp::{ use ctru::services::ndsp::{
wave::{WaveBuffer, WaveInfo}, wave::{WaveBuffer, WaveInfo, WaveStatus},
AudioFormat, InterpolationType, Ndsp, OutputMode, AudioFormat, InterpolationType, Ndsp, OutputMode,
}; };
@ -19,14 +19,19 @@ const NOTEFREQ: [u32; 7] = [220, 440, 880, 1760, 3520, 7040, 14080];
// audioBuffer is stereo PCM16 // audioBuffer is stereo PCM16
fn fill_buffer(audioData: &mut [u8], frequency: u32) { fn fill_buffer(audioData: &mut [u8], frequency: u32) {
let formatted_data: Vec<i16> = 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() { 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. // 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 sample: i16 = (0.3 * i16::MAX as f32 * (frequency as f32 * (2f32 * PI) * (i as f32 / SAMPLE_RATE as f32)).sin()) as i16;
// 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. // Stereo samples are interleaved: left and right channels.
formatted_data[i] = (sample << 16) | (sample & 0xffff); *chunk_ptr = (sample << 16) | (sample & 0xffff);
i += 1;
} }
} }
@ -39,19 +44,16 @@ fn main() {
println!("libctru filtered streamed audio\n"); println!("libctru filtered streamed audio\n");
let audioBuffer = Box::new_in( let mut audioBuffer = Box::new_in(
[0u8; AUDIO_WAVE_LENGTH], [0u8; AUDIO_WAVE_LENGTH],
LinearAllocator, LinearAllocator,
); );
fill_buffer(&mut audioBuffer, NOTEFREQ[4]); fill_buffer(&mut audioBuffer[..], NOTEFREQ[4]);
let audioBuffer1 =
WaveBuffer::new(audioBuffer, AudioFormat::PCM16Stereo).expect("Couldn't sync DSP cache");
let audioBuffer2 = audioBuffer1.clone();
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` // This line isn't needed since the default NDSP configuration already sets the output mode to `Stereo`
ndsp.set_output_mode(OutputMode::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. // 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[0] = 1.0;
mix[1] = 1.0; mix[1] = 1.0;
channel_zero.set_mix(&mix); channel_zero.set_mix(&mix);
let note: usize = 4; let mut note: usize = 4;
// Filters // Filters
@ -81,24 +83,23 @@ fn main() {
"Peaking", "Peaking",
]; ];
let filter = 0; let mut filter = 0;
// 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 buf1 = WaveInfo::new(&mut audioBuffer1, false); let mut bufs: [WaveInfo; 2] = [ WaveInfo::new(&mut audioBuffer1, false), WaveInfo::new(&mut audioBuffer2, false)];
let mut buf2 = WaveInfo::new(&mut audioBuffer2, false);
unsafe { channel_zero.queue_wave(&mut bufs[0]);
channel_zero.queue_wave(&mut buf1); channel_zero.queue_wave(&mut bufs[1]);
channel_zero.queue_wave(&mut buf2);
};
println!("Press up/down to change tone frequency\n"); println!("Press up/down to change tone frequency\n");
println!("Press left/right to change filter\n"); println!("Press left/right to change filter\n");
println!("\x1b[6;1Hnote = {} Hz ", NOTEFREQ[note]); println!("\x1b[6;1Hnote = {} Hz ", NOTEFREQ[note]);
println!("\x1b[7;1Hfilter = {} ", filter_names[filter]); println!("\x1b[7;1Hfilter = {} ", filter_names[filter]);
let mut fillBlock = false;
while apt.main_loop() { while apt.main_loop() {
hid.scan_input(); hid.scan_input();
let keys_down = hid.keys_down(); let keys_down = hid.keys_down();
@ -124,7 +125,7 @@ fn main() {
// Check for upper limit // Check for upper limit
note = std::cmp::max(note, NOTEFREQ.len() - 1); note = std::cmp::max(note, NOTEFREQ.len() - 1);
let update_params = false; let mut update_params = false;
if keys_down.contains(KeyPad::KEY_LEFT) { if keys_down.contains(KeyPad::KEY_LEFT) {
filter = filter.saturating_sub(1); filter = filter.saturating_sub(1);
if filter < 0 { if filter < 0 {
@ -151,15 +152,12 @@ fn main() {
} }
} }
if waveBuf[fillBlock].status == NDSP_WBUF_DONE { let status = bufs[fillBlock as usize].get_status();
if fillBlock { if let WaveStatus::Done = status {
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; 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 // Flush and swap framebuffers

Loading…
Cancel
Save