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