1use std::time::Duration;
2
3use super::SeekError;
4use crate::common::{ChannelCount, SampleRate};
5use crate::Source;
6
7fn remaining_samples(
8 until_playback: Duration,
9 sample_rate: SampleRate,
10 channels: ChannelCount,
11) -> usize {
12 let ns = until_playback.as_secs() * 1_000_000_000 + until_playback.subsec_nanos() as u64;
13 let samples = ns * channels as u64 * sample_rate as u64 / 1_000_000_000;
14 samples as usize
15}
16
17pub fn delay<I>(input: I, duration: Duration) -> Delay<I>
19where
20 I: Source,
21{
22 Delay {
23 remaining_samples: remaining_samples(duration, input.sample_rate(), input.channels()),
24 requested_duration: duration,
25 input,
26 }
27}
28
29#[derive(Clone, Debug)]
31pub struct Delay<I> {
32 input: I,
33 remaining_samples: usize,
34 requested_duration: Duration,
35}
36
37impl<I> Delay<I>
38where
39 I: Source,
40{
41 #[inline]
43 pub fn inner(&self) -> &I {
44 &self.input
45 }
46
47 #[inline]
49 pub fn inner_mut(&mut self) -> &mut I {
50 &mut self.input
51 }
52
53 #[inline]
55 pub fn into_inner(self) -> I {
56 self.input
57 }
58}
59
60impl<I> Iterator for Delay<I>
61where
62 I: Source,
63{
64 type Item = <I as Iterator>::Item;
65
66 #[inline]
67 fn next(&mut self) -> Option<<I as Iterator>::Item> {
68 if self.remaining_samples >= 1 {
69 self.remaining_samples -= 1;
70 Some(0.0)
71 } else {
72 self.input.next()
73 }
74 }
75
76 #[inline]
77 fn size_hint(&self) -> (usize, Option<usize>) {
78 let (min, max) = self.input.size_hint();
79 (
80 min + self.remaining_samples,
81 max.map(|v| v + self.remaining_samples),
82 )
83 }
84}
85
86impl<I> Source for Delay<I>
87where
88 I: Iterator + Source,
89{
90 #[inline]
91 fn current_span_len(&self) -> Option<usize> {
92 self.input
93 .current_span_len()
94 .map(|val| val + self.remaining_samples)
95 }
96
97 #[inline]
98 fn channels(&self) -> ChannelCount {
99 self.input.channels()
100 }
101
102 #[inline]
103 fn sample_rate(&self) -> SampleRate {
104 self.input.sample_rate()
105 }
106
107 #[inline]
108 fn total_duration(&self) -> Option<Duration> {
109 self.input
110 .total_duration()
111 .map(|val| val + self.requested_duration)
112 }
113
114 #[inline]
128 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
129 if pos < self.requested_duration {
130 self.input.try_seek(Duration::ZERO)?;
131 let until_playback = self.requested_duration - pos;
132 self.remaining_samples =
133 remaining_samples(until_playback, self.sample_rate(), self.channels());
134 }
135 let compensated_for_delay = pos.saturating_sub(self.requested_duration);
136 self.input.try_seek(compensated_for_delay)
137 }
138}