rodio/source/
crossfade.rs
1use std::time::Duration;
2
3use cpal::FromSample;
4
5use crate::source::{FadeIn, Mix, TakeDuration};
6use crate::{Sample, Source};
7
8pub fn crossfade<I1, I2>(
14 input_fadeout: I1,
15 input_fadein: I2,
16 duration: Duration,
17) -> Crossfade<I1, I2>
18where
19 I1: Source,
20 I2: Source,
21 I1::Item: FromSample<I2::Item> + Sample,
22 I2::Item: Sample,
23{
24 let mut input_fadeout = input_fadeout.take_duration(duration);
25 input_fadeout.set_filter_fadeout();
26 let input_fadein = input_fadein.take_duration(duration).fade_in(duration);
27 input_fadeout.mix(input_fadein)
28}
29
30pub type Crossfade<I1, I2> = Mix<TakeDuration<I1>, FadeIn<TakeDuration<I2>>>;
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use crate::buffer::SamplesBuffer;
41 fn dummysource(length: u8) -> SamplesBuffer<f32> {
42 let data: Vec<f32> = (1..=length).map(f32::from).collect();
43 SamplesBuffer::new(1, 1, data)
44 }
45
46 #[test]
47 fn test_crossfade_with_self() {
48 let source1 = dummysource(10);
49 let source2 = dummysource(10);
50 let mut mixed = crossfade(
51 source1,
52 source2,
53 Duration::from_secs(5) + Duration::from_nanos(1),
54 );
55 assert_eq!(mixed.next(), Some(1.0));
56 assert_eq!(mixed.next(), Some(2.0));
57 assert_eq!(mixed.next(), Some(3.0));
58 assert_eq!(mixed.next(), Some(4.0));
59 assert_eq!(mixed.next(), Some(5.0));
60 assert_eq!(mixed.next(), None);
61 }
62
63 #[test]
64 fn test_crossfade() {
65 let source1 = dummysource(10);
66 let source2 = dummysource(10).amplify(0.0);
67 let mut mixed = crossfade(
68 source1,
69 source2,
70 Duration::from_secs(5) + Duration::from_nanos(1),
71 );
72 assert_eq!(mixed.next(), Some(1.0 * 1.0));
73 assert_eq!(mixed.next(), Some(2.0 * 0.8));
74 assert_eq!(mixed.next(), Some(3.0 * 0.6));
75 assert_eq!(mixed.next(), Some(4.0 * 0.4));
76 assert_eq!(mixed.next(), Some(5.0 * 0.2));
77 assert_eq!(mixed.next(), None);
78 }
79}