1 //! A simple source of samples coming from a static buffer.
2 //!
3 //! The `StaticSamplesBuffer` struct can be used to treat a list of values as a `Source`.
4 //!
5 //! # Example
6 //!
7 //! ```
8 //! use rodio::static_buffer::StaticSamplesBuffer;
9 //! let _ = StaticSamplesBuffer::new(1, 44100, &[1i16, 2, 3, 4, 5, 6]);
10 //! ```
11 //!
12 
13 use std::slice::Iter as SliceIter;
14 use std::time::Duration;
15 
16 use crate::{Sample, Source};
17 
18 /// A buffer of samples treated as a source.
19 #[derive(Clone)]
20 pub struct StaticSamplesBuffer<S>
21 where
22     S: 'static,
23 {
24     data: SliceIter<'static, S>,
25     channels: u16,
26     sample_rate: u32,
27     duration: Duration,
28 }
29 
30 impl<S> StaticSamplesBuffer<S>
31 where
32     S: Sample,
33 {
34     /// Builds a new `StaticSamplesBuffer`.
35     ///
36     /// # Panic
37     ///
38     /// - Panics if the number of channels is zero.
39     /// - Panics if the samples rate is zero.
40     /// - Panics if the length of the buffer is larger than approximatively 16 billion elements.
41     ///   This is because the calculation of the duration would overflow.
42     ///
new(channels: u16, sample_rate: u32, data: &'static [S]) -> StaticSamplesBuffer<S>43     pub fn new(channels: u16, sample_rate: u32, data: &'static [S]) -> StaticSamplesBuffer<S> {
44         assert!(channels != 0);
45         assert!(sample_rate != 0);
46 
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         StaticSamplesBuffer {
56             data: data.iter(),
57             channels,
58             sample_rate,
59             duration,
60         }
61     }
62 }
63 
64 impl<S> Source for StaticSamplesBuffer<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 StaticSamplesBuffer<S>
90 where
91     S: Sample + Clone,
92 {
93     type Item = S;
94 
95     #[inline]
next(&mut self) -> Option<S>96     fn next(&mut self) -> Option<S> {
97         self.data.next().cloned()
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::source::Source;
109     use crate::static_buffer::StaticSamplesBuffer;
110 
111     #[test]
basic()112     fn basic() {
113         let _ = StaticSamplesBuffer::new(1, 44100, &[0i16, 0, 0, 0, 0, 0]);
114     }
115 
116     #[test]
117     #[should_panic]
panic_if_zero_channels()118     fn panic_if_zero_channels() {
119         StaticSamplesBuffer::new(0, 44100, &[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         StaticSamplesBuffer::new(1, 0, &[0i16, 0, 0, 0, 0, 0]);
126     }
127 
128     #[test]
duration_basic()129     fn duration_basic() {
130         let buf = StaticSamplesBuffer::new(2, 2, &[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 = StaticSamplesBuffer::new(1, 44100, &[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