rodio/source/
mix.rs
1use std::cmp;
2use std::time::Duration;
3
4use crate::source::uniform::UniformSourceIterator;
5use crate::source::SeekError;
6use crate::{Sample, Source};
7use cpal::{FromSample, Sample as CpalSample};
8
9pub fn mix<I1, I2>(input1: I1, input2: I2) -> Mix<I1, I2>
11where
12 I1: Source,
13 I1::Item: FromSample<I2::Item> + Sample,
14 I2: Source,
15 I2::Item: Sample,
16{
17 let channels = input1.channels();
18 let rate = input1.sample_rate();
19
20 Mix {
21 input1: UniformSourceIterator::new(input1, channels, rate),
22 input2: UniformSourceIterator::new(input2, channels, rate),
23 }
24}
25
26#[derive(Clone)]
28pub struct Mix<I1, I2>
29where
30 I1: Source,
31 I1::Item: FromSample<I2::Item> + Sample,
32 I2: Source,
33 I2::Item: Sample,
34{
35 input1: UniformSourceIterator<I1, I1::Item>,
36 input2: UniformSourceIterator<I2, I2::Item>,
37}
38
39impl<I1, I2> Iterator for Mix<I1, I2>
40where
41 I1: Source,
42 I1::Item: FromSample<I2::Item> + Sample,
43 I2: Source,
44 I2::Item: Sample,
45{
46 type Item = I1::Item;
47
48 #[inline]
49 fn next(&mut self) -> Option<I1::Item> {
50 let s1 = self.input1.next();
51 let s2 = self.input2.next();
52
53 match (s1, s2) {
54 (Some(s1), Some(s2)) => Some(s1.saturating_add(CpalSample::from_sample(s2))),
55 (Some(s1), None) => Some(s1),
56 (None, Some(s2)) => Some(CpalSample::from_sample(s2)),
57 (None, None) => None,
58 }
59 }
60
61 #[inline]
62 fn size_hint(&self) -> (usize, Option<usize>) {
63 let s1 = self.input1.size_hint();
64 let s2 = self.input2.size_hint();
65
66 let min = cmp::max(s1.0, s2.0);
67 let max = match (s1.1, s2.1) {
68 (Some(s1), Some(s2)) => Some(cmp::max(s1, s2)),
69 _ => None,
70 };
71
72 (min, max)
73 }
74}
75
76impl<I1, I2> ExactSizeIterator for Mix<I1, I2>
77where
78 I1: Source + ExactSizeIterator,
79 I1::Item: FromSample<I2::Item> + Sample,
80 I2: Source + ExactSizeIterator,
81 I2::Item: Sample,
82{
83}
84
85impl<I1, I2> Source for Mix<I1, I2>
86where
87 I1: Source,
88 I1::Item: FromSample<I2::Item> + Sample,
89 I2: Source,
90 I2::Item: Sample,
91{
92 #[inline]
93 fn current_frame_len(&self) -> Option<usize> {
94 let f1 = self.input1.current_frame_len();
95 let f2 = self.input2.current_frame_len();
96
97 match (f1, f2) {
98 (Some(f1), Some(f2)) => Some(cmp::min(f1, f2)),
99 _ => None,
100 }
101 }
102
103 #[inline]
104 fn channels(&self) -> u16 {
105 self.input1.channels()
106 }
107
108 #[inline]
109 fn sample_rate(&self) -> u32 {
110 self.input1.sample_rate()
111 }
112
113 #[inline]
114 fn total_duration(&self) -> Option<Duration> {
115 let f1 = self.input1.total_duration();
116 let f2 = self.input2.total_duration();
117
118 match (f1, f2) {
119 (Some(f1), Some(f2)) => Some(cmp::max(f1, f2)),
120 _ => None,
121 }
122 }
123
124 #[inline]
126 fn try_seek(&mut self, _: Duration) -> Result<(), SeekError> {
127 Err(SeekError::NotSupported {
128 underlying_source: std::any::type_name::<Self>(),
129 })
130
131 }
144}