rodio/source/
from_iter.rs1use std::time::Duration;
2
3use crate::{Sample, Source};
4
5use super::SeekError;
6
7pub fn from_iter<I>(iterator: I) -> FromIter<I::IntoIter>
15where
16 I: IntoIterator,
17{
18 let mut iterator = iterator.into_iter();
19 let first_source = iterator.next();
20
21 FromIter {
22 iterator,
23 current_source: first_source,
24 }
25}
26
27#[derive(Clone)]
29pub struct FromIter<I>
30where
31 I: Iterator,
32{
33 iterator: I,
35 current_source: Option<I::Item>,
37}
38
39impl<I> Iterator for FromIter<I>
40where
41 I: Iterator,
42 I::Item: Iterator + Source,
43 <I::Item as Iterator>::Item: Sample,
44{
45 type Item = <I::Item as Iterator>::Item;
46
47 #[inline]
48 fn next(&mut self) -> Option<<I::Item as Iterator>::Item> {
49 loop {
50 if let Some(src) = &mut self.current_source {
51 if let Some(value) = src.next() {
52 return Some(value);
53 }
54 }
55
56 if let Some(src) = self.iterator.next() {
57 self.current_source = Some(src);
58 } else {
59 return None;
60 }
61 }
62 }
63
64 #[inline]
65 fn size_hint(&self) -> (usize, Option<usize>) {
66 if let Some(cur) = &self.current_source {
67 (cur.size_hint().0, None)
68 } else {
69 (0, None)
70 }
71 }
72}
73
74impl<I> Source for FromIter<I>
75where
76 I: Iterator,
77 I::Item: Iterator + Source,
78 <I::Item as Iterator>::Item: Sample,
79{
80 #[inline]
81 fn current_frame_len(&self) -> Option<usize> {
82 const THRESHOLD: usize = 10240;
93
94 if let Some(src) = &self.current_source {
96 if let Some(val) = src.current_frame_len() {
97 if val != 0 {
98 return Some(val);
99 }
100 }
101 }
102
103 if let Some(src) = &self.current_source {
105 if let Some(val) = src.size_hint().1 {
106 if val < THRESHOLD && val != 0 {
107 return Some(val);
108 }
109 }
110 }
111
112 Some(THRESHOLD)
114 }
115
116 #[inline]
117 fn channels(&self) -> u16 {
118 if let Some(src) = &self.current_source {
119 src.channels()
120 } else {
121 2
123 }
124 }
125
126 #[inline]
127 fn sample_rate(&self) -> u32 {
128 if let Some(src) = &self.current_source {
129 src.sample_rate()
130 } else {
131 44100
133 }
134 }
135
136 #[inline]
137 fn total_duration(&self) -> Option<Duration> {
138 None
139 }
140
141 #[inline]
142 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
143 if let Some(source) = self.current_source.as_mut() {
144 source.try_seek(pos)
145 } else {
146 Ok(())
147 }
148 }
149}
150
151#[cfg(test)]
152mod tests {
153 use crate::buffer::SamplesBuffer;
154 use crate::source::{from_iter, Source};
155
156 #[test]
157 fn basic() {
158 let mut rx = from_iter((0..2).map(|n| {
159 if n == 0 {
160 SamplesBuffer::new(1, 48000, vec![10i16, -10, 10, -10])
161 } else if n == 1 {
162 SamplesBuffer::new(2, 96000, vec![5i16, 5, 5, 5])
163 } else {
164 unreachable!()
165 }
166 }));
167
168 assert_eq!(rx.channels(), 1);
169 assert_eq!(rx.sample_rate(), 48000);
170 assert_eq!(rx.next(), Some(10));
171 assert_eq!(rx.next(), Some(-10));
172 assert_eq!(rx.next(), Some(10));
173 assert_eq!(rx.next(), Some(-10));
174 assert_eq!(rx.next(), Some(5));
178 assert_eq!(rx.next(), Some(5));
179 assert_eq!(rx.next(), Some(5));
180 assert_eq!(rx.next(), Some(5));
181 assert_eq!(rx.next(), None);
182 }
183}