1 //! A simple source of samples coming from a buffer.
2 //!
3 //! The `SamplesBuffer` struct can be used to treat a list of values as a `Source`.
4 //!
5 //! # Example
6 //!
7 //! ```
8 //! use rodio::buffer::SamplesBuffer;
9 //! let _ = SamplesBuffer::new(1, 44100, vec![1i16, 2, 3, 4, 5, 6]);
10 //! ```
11 //!
12 
13 use std::time::Duration;
14 use std::vec::IntoIter as VecIntoIter;
15 
16 use crate::{Sample, Source};
17 
18 /// A buffer of samples treated as a source.
19 pub struct SamplesBuffer<S> {
20     data: VecIntoIter<S>,
21     channels: u16,
22     sample_rate: u32,
23     duration: Duration,
24 }
25 
26 impl<S> SamplesBuffer<S>
27 where
28     S: Sample,
29 {
30     /// Builds a new `SamplesBuffer`.
31     ///
32     /// # Panic
33     ///
34     /// - Panics if the number of channels is zero.
35     /// - Panics if the samples rate is zero.
36     /// - Panics if the length of the buffer is larger than approximately 16 billion elements.
37     ///   This is because the calculation of the duration would overflow.
38     ///
new<D>(channels: u16, sample_rate: u32, data: D) -> SamplesBuffer<S> where D: Into<Vec<S>>,39     pub fn new<D>(channels: u16, sample_rate: u32, data: D) -> SamplesBuffer<S>
40     where
41         D: Into<Vec<S>>,
42     {
43         assert!(channels != 0);
44         assert!(sample_rate != 0);
45 
46         let data = data.into();
47         let duration_ns = 1_000_000_000u64.checked_mul(data.len() as u64).unwrap()
48             / sample_rate as u64
49             / channels as u64;
50         let duration = Duration::new(
51             duration_ns / 1_000_000_000,
52             (duration_ns % 1_000_000_000) as u32,
53         );
54 
55         SamplesBuffer {
56             data: data.into_iter(),
57             channels,
58             sample_rate,
59             duration,
60         }
61     }
62 }
63 
64 impl<S> Source for SamplesBuffer<S>
65 where
66     S: Sample,
67 {
68     #[inline]
current_frame_len(&self) -> Option<usize>69     fn current_frame_len(&self) -> Option<usize> {
70         None
71     }
72 
73     #[inline]
channels(&self) -> u1674     fn channels(&self) -> u16 {
75         self.channels
76     }
77 
78     #[inline]
sample_rate(&self) -> u3279     fn sample_rate(&self) -> u32 {
80         self.sample_rate
81     }
82 
83     #[inline]
total_duration(&self) -> Option<Duration>84     fn total_duration(&self) -> Option<Duration> {
85         Some(self.duration)
86     }
87 }
88 
89 impl<S> Iterator for SamplesBuffer<S>
90 where
91     S: Sample,
92 {
93     type Item = S;
94 
95     #[inline]
next(&mut self) -> Option<S>96     fn next(&mut self) -> Option<S> {
97         self.data.next()
98     }
99 
100     #[inline]
size_hint(&self) -> (usize, Option<usize>)101     fn size_hint(&self) -> (usize, Option<usize>) {
102         self.data.size_hint()
103     }
104 }
105 
106 #[cfg(test)]
107 mod tests {
108     use crate::buffer::SamplesBuffer;
109     use crate::source::Source;
110 
111     #[test]
basic()112     fn basic() {
113         let _ = SamplesBuffer::new(1, 44100, vec![0i16, 0, 0, 0, 0, 0]);
114     }
115 
116     #[test]
117     #[should_panic]
panic_if_zero_channels()118     fn panic_if_zero_channels() {
119         SamplesBuffer::new(0, 44100, vec![0i16, 0, 0, 0, 0, 0]);
120     }
121 
122     #[test]
123     #[should_panic]
panic_if_zero_sample_rate()124     fn panic_if_zero_sample_rate() {
125         SamplesBuffer::new(1, 0, vec![0i16, 0, 0, 0, 0, 0]);
126     }
127 
128     #[test]
duration_basic()129     fn duration_basic() {
130         let buf = SamplesBuffer::new(2, 2, vec![0i16, 0, 0, 0, 0, 0]);
131         let dur = buf.total_duration().unwrap();
132         assert_eq!(dur.as_secs(), 1);
133         assert_eq!(dur.subsec_nanos(), 500_000_000);
134     }
135 
136     #[test]
iteration()137     fn iteration() {
138         let mut buf = SamplesBuffer::new(1, 44100, vec![1i16, 2, 3, 4, 5, 6]);
139         assert_eq!(buf.next(), Some(1));
140         assert_eq!(buf.next(), Some(2));
141         assert_eq!(buf.next(), Some(3));
142         assert_eq!(buf.next(), Some(4));
143         assert_eq!(buf.next(), Some(5));
144         assert_eq!(buf.next(), Some(6));
145         assert_eq!(buf.next(), None);
146     }
147 }
148