Add a SamplesBuffer struct

This commit is contained in:
Pierre Krieger 2017-02-09 13:04:04 +01:00
parent 953681a14d
commit c3d573db9f
2 changed files with 125 additions and 0 deletions

124
src/buffer.rs Normal file
View file

@ -0,0 +1,124 @@
//! A simple source of samples coming from a buffer.
use std::time::Duration;
use std::vec::IntoIter as VecIntoIter;
use source::Source;
use Sample;
/// The input of the mixer.
pub struct SamplesBuffer<S> {
data: VecIntoIter<S>,
channels: u16,
samples_rate: u32,
duration: Duration,
}
impl<S> SamplesBuffer<S> where S: Sample {
/// Builds a new `SamplesBuffer`.
///
/// # Panic
///
/// - Panics if the number of channels is zero.
/// - Panics if the samples rate is zero.
/// - Panics if the length of the buffer is superior to approximatively 16 billion elements.
/// This is because the calculation of the duration would overflow.
///
pub fn new<D>(channels: u16, samples_rate: u32, data: D) -> SamplesBuffer<S>
where D: Into<Vec<S>>
{
assert!(channels != 0);
assert!(samples_rate != 0);
let data = data.into();
let duration_ns = 1_000_000_000u64.checked_mul(data.len() as u64).unwrap() / samples_rate as u64 / channels as u64;
let duration = Duration::new(duration_ns / 1_000_000_000, (duration_ns % 1_000_000_000) as u32);
SamplesBuffer {
data: data.into_iter(),
channels: channels,
samples_rate: samples_rate,
duration: duration,
}
}
}
impl<S> Source for SamplesBuffer<S> where S: Sample {
#[inline]
fn get_current_frame_len(&self) -> Option<usize> {
None
}
#[inline]
fn get_channels(&self) -> u16 {
self.channels
}
#[inline]
fn get_samples_rate(&self) -> u32 {
self.samples_rate
}
#[inline]
fn get_total_duration(&self) -> Option<Duration> {
Some(self.duration)
}
}
impl<S> Iterator for SamplesBuffer<S> where S: Sample {
type Item = S;
#[inline]
fn next(&mut self) -> Option<S> {
self.data.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.data.size_hint()
}
}
#[cfg(test)]
mod tests {
use buffer::SamplesBuffer;
use source::Source;
#[test]
fn basic() {
let _ = SamplesBuffer::new(1, 44100, vec![0i16, 0, 0, 0, 0, 0]);
}
#[test]
#[should_panic]
fn panic_if_zero_channels() {
SamplesBuffer::new(0, 44100, vec![0i16, 0, 0, 0, 0, 0]);
}
#[test]
#[should_panic]
fn panic_if_zero_samples_rate() {
SamplesBuffer::new(1, 0, vec![0i16, 0, 0, 0, 0, 0]);
}
#[test]
fn duration_basic() {
let buf = SamplesBuffer::new(2, 2, vec![0i16, 0, 0, 0, 0, 0]);
let dur = buf.get_total_duration().unwrap();
assert_eq!(dur.as_secs(), 1);
assert_eq!(dur.subsec_nanos(), 500_000_000);
}
#[test]
fn iteration() {
let mut buf = SamplesBuffer::new(1, 44100, vec![1i16, 2, 3, 4, 5, 6]);
assert_eq!(buf.next(), Some(1));
assert_eq!(buf.next(), Some(2));
assert_eq!(buf.next(), Some(3));
assert_eq!(buf.next(), Some(4));
assert_eq!(buf.next(), Some(5));
assert_eq!(buf.next(), Some(6));
assert_eq!(buf.next(), None);
}
}

View file

@ -75,6 +75,7 @@ mod conversions;
mod engine;
mod sink;
pub mod buffer;
pub mod decoder;
pub mod dynamic_mixer;
pub mod queue;