mini_sdl/audio.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
use sdl2::audio::AudioCallback;
use std::collections::VecDeque;
/// A single audio sample, with left and right channels.
#[derive(Debug, Default, Clone, Copy)]
pub struct StereoFrame {
pub left: i16,
pub right: i16,
}
/// Used internally to push audio samples to the audio device. Although you can access it directly,
/// it requires locking the audio device so it's easier to use 'App::audio_push_samples' instead.
pub struct AudioInput {
buffer: VecDeque<StereoFrame>,
last_frame: StereoFrame,
head: usize,
device_sample_count:u16
}
impl AudioInput {
// pub fn new(mix_rate:u32) -> Self {
pub fn new(device_sample_count:u16) -> Self {
Self {
buffer: VecDeque::default(),
last_frame: StereoFrame::default(),
head: 0,
device_sample_count,
}
}
/// Estimates how many stereo frames to fill the buffer now for minimum lag without audio cut-offs.
pub fn frames_available(&self) -> usize {
let desired_frames = self.device_sample_count as usize * 2;
let len = self.buffer.len();
if len < desired_frames {
// println!( "desired: {}, filled: {}, result:{}", desired_frames, len, desired_frames - len);
desired_frames - len
} else {
32
}
}
/// For debugging purposes, returns lengh of internal buffer
pub fn buffer_len(&self) -> usize {
self.buffer.len()
}
/// Push a single StereoFrame to the buffer.
#[inline(always)]
pub fn push_sample(&mut self, frame: StereoFrame) {
self.buffer.push_back(frame);
}
/// Push a slice of StereoFrames. Ideally you should call this only once per frame,
/// with all the samples that you need for that frame.
#[inline(always)]
pub fn push_samples(&mut self, frames: &[StereoFrame]) {
for sample in frames.iter(){
self.buffer.push_back(*sample);
}
}
}
impl<'a> AudioCallback for AudioInput {
type Channel = i16;
fn callback(&mut self, out: &mut [i16]) {
for x in out.iter_mut() {
if self.head % 2 == 0 {
self.head = 0;
self.last_frame = self.buffer.pop_front().unwrap_or_default();
*x = self.last_frame.left;
} else {
*x = self.last_frame.right;
}
self.head += 1;
}
}
}