mirror of
https://github.com/RustAudio/rodio
synced 2024-12-14 06:02:31 +00:00
Add a SamplesBuffer struct
This commit is contained in:
parent
953681a14d
commit
c3d573db9f
2 changed files with 125 additions and 0 deletions
124
src/buffer.rs
Normal file
124
src/buffer.rs
Normal 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);
|
||||
}
|
||||
}
|
|
@ -75,6 +75,7 @@ mod conversions;
|
|||
mod engine;
|
||||
mod sink;
|
||||
|
||||
pub mod buffer;
|
||||
pub mod decoder;
|
||||
pub mod dynamic_mixer;
|
||||
pub mod queue;
|
||||
|
|
Loading…
Reference in a new issue