rodio/source/
crossfade.rs

1use std::time::Duration;
2
3use cpal::FromSample;
4
5use crate::source::{FadeIn, Mix, TakeDuration};
6use crate::{Sample, Source};
7
8/// Mixes one sound fading out with another sound fading in for the given
9/// duration.
10///
11/// Only the crossfaded portion (beginning of fadeout, beginning of fadein) is
12/// returned.
13pub 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
30/// Mixes one sound fading out with another sound fading in for the given
31/// duration.
32///
33/// Only the crossfaded portion (beginning of fadeout, beginning of fadein) is
34/// covered.
35pub 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}