Skip to main content

kithara_decode/
pcm_time.rs

1use std::time::Duration;
2
3const NANOS_PER_SECOND: u128 = 1_000_000_000;
4
5/// Convert PCM frame count at a given sample rate into a saturating `Duration`.
6#[must_use]
7pub fn duration_for_frames(sample_rate: u32, frames: u64) -> Duration {
8    if sample_rate == 0 {
9        return Duration::ZERO;
10    }
11
12    let nanos = u128::from(frames)
13        .saturating_mul(NANOS_PER_SECOND)
14        .saturating_div(u128::from(sample_rate));
15    Duration::from_nanos(u64::try_from(nanos).unwrap_or(u64::MAX))
16}
17
18/// Convert `Duration` back into PCM frame count at a given sample rate.
19#[must_use]
20pub fn frames_for_duration(sample_rate: u32, duration: Duration) -> usize {
21    if sample_rate == 0 {
22        return 0;
23    }
24
25    let frames = duration
26        .as_nanos()
27        .saturating_mul(u128::from(sample_rate))
28        .saturating_div(NANOS_PER_SECOND);
29    usize::try_from(frames).unwrap_or(usize::MAX)
30}
31
32#[cfg(test)]
33mod tests {
34    use std::time::Duration;
35
36    use kithara_test_utils::kithara;
37
38    use super::*;
39
40    #[kithara::test]
41    fn duration_for_frames_maps_pcm_frames_to_duration() {
42        assert_eq!(duration_for_frames(48_000, 576), Duration::from_millis(12));
43    }
44
45    #[kithara::test]
46    fn frames_for_duration_maps_duration_to_pcm_frames() {
47        assert_eq!(frames_for_duration(48_000, Duration::from_millis(12)), 576);
48    }
49
50    #[kithara::test]
51    fn zero_sample_rate_is_safe() {
52        assert_eq!(duration_for_frames(0, 576), Duration::ZERO);
53        assert_eq!(frames_for_duration(0, Duration::from_millis(12)), 0);
54    }
55}