|
30 | 30 | #[cfg(any(feature = "claxon", feature = "hound"))] |
31 | 31 | use std::time::Duration; |
32 | 32 |
|
| 33 | +#[cfg(any(feature = "claxon", feature = "hound"))] |
| 34 | +use crate::SampleRate; |
| 35 | + |
33 | 36 | #[cfg(any( |
34 | 37 | feature = "claxon", |
35 | 38 | feature = "hound", |
@@ -62,33 +65,11 @@ use std::io::{Read, Seek, SeekFrom}; |
62 | 65 | /// |
63 | 66 | /// # Edge Cases |
64 | 67 | /// |
65 | | -/// - **Zero sample rate**: Returns `Duration::ZERO` to prevent division by zero |
66 | 68 | /// - **Zero samples**: Returns `Duration::ZERO` (mathematically correct) |
67 | | -/// - **Large values**: Handles overflow gracefully within Duration limits |
68 | | -/// |
69 | | -/// # Examples |
70 | | -/// |
71 | | -/// ```ignore |
72 | | -/// use std::time::Duration; |
73 | | -/// # use rodio::decoder::utils::samples_to_duration; |
74 | | -/// |
75 | | -/// // 1 second at 44.1kHz |
76 | | -/// assert_eq!(samples_to_duration(44100, 44100), Duration::from_secs(1)); |
77 | | -/// |
78 | | -/// // 0.5 seconds at 44.1kHz |
79 | | -/// assert_eq!(samples_to_duration(22050, 44100), Duration::from_millis(500)); |
80 | | -/// ``` |
81 | | -/// |
82 | | -/// # Performance |
83 | | -/// |
84 | | -/// This function is optimized for common audio sample rates and performs |
85 | | -/// integer arithmetic only, making it suitable for real-time applications. |
| 69 | +/// - **Large values**: Handles overflow gracefully within `Duration` limits |
86 | 70 | #[cfg(any(feature = "claxon", feature = "hound",))] |
87 | | -pub(super) fn samples_to_duration(samples: u64, sample_rate: u64) -> Duration { |
88 | | - if sample_rate == 0 { |
89 | | - return Duration::ZERO; |
90 | | - } |
91 | | - |
| 71 | +pub(super) fn samples_to_duration(samples: u64, sample_rate: SampleRate) -> Duration { |
| 72 | + let sample_rate = sample_rate.get() as u64; |
92 | 73 | let secs = samples / sample_rate; |
93 | 74 | let nanos = ((samples % sample_rate) * 1_000_000_000) / sample_rate; |
94 | 75 | Duration::new(secs, nanos as u32) |
@@ -182,34 +163,31 @@ mod tests { |
182 | 163 | #[test] |
183 | 164 | fn test_samples_to_duration() { |
184 | 165 | // Standard CD quality: 1 second at 44.1kHz |
185 | | - assert_eq!(samples_to_duration(44100, 44100), Duration::from_secs(1)); |
| 166 | + let rate_44_1k = SampleRate::new(44100).unwrap(); |
| 167 | + assert_eq!( |
| 168 | + samples_to_duration(rate_44_1k.get() as u64, rate_44_1k), |
| 169 | + Duration::from_secs(1) |
| 170 | + ); |
186 | 171 |
|
187 | 172 | // Half second at CD quality |
188 | 173 | assert_eq!( |
189 | | - samples_to_duration(22050, 44100), |
| 174 | + samples_to_duration(rate_44_1k.get() as u64 / 2, rate_44_1k), |
190 | 175 | Duration::from_millis(500) |
191 | 176 | ); |
192 | 177 |
|
193 | | - // Professional audio: 1 second at 48kHz |
194 | | - assert_eq!(samples_to_duration(48000, 48000), Duration::from_secs(1)); |
195 | | - |
196 | | - // High resolution: 1 second at 96kHz |
197 | | - assert_eq!(samples_to_duration(96000, 96000), Duration::from_secs(1)); |
198 | | - |
199 | 178 | // Edge case: Zero samples should return zero duration |
200 | | - assert_eq!(samples_to_duration(0, 44100), Duration::ZERO); |
201 | | - |
202 | | - // Edge case: Zero sample rate should not panic and return zero |
203 | | - assert_eq!(samples_to_duration(44100, 0), Duration::ZERO); |
| 179 | + assert_eq!(samples_to_duration(0, rate_44_1k), Duration::ZERO); |
204 | 180 |
|
205 | 181 | // Precision test: Fractional milliseconds |
206 | 182 | // 441 samples at 44.1kHz = 10ms exactly |
207 | | - assert_eq!(samples_to_duration(441, 44100), Duration::from_millis(10)); |
| 183 | + assert_eq!( |
| 184 | + samples_to_duration(rate_44_1k.get() as u64 / 100, rate_44_1k), |
| 185 | + Duration::from_millis(10) |
| 186 | + ); |
208 | 187 |
|
209 | 188 | // Very small durations should have nanosecond precision |
210 | | - // 1 sample at 44.1kHz ≈ 22.676 microseconds |
211 | | - let one_sample_duration = samples_to_duration(1, 44100); |
212 | | - assert!(one_sample_duration.as_nanos() > 22000); |
213 | | - assert!(one_sample_duration.as_nanos() < 23000); |
| 189 | + // 1 sample at 44.1kHz ≈ 22.675 microseconds |
| 190 | + let one_sample_duration = samples_to_duration(1, rate_44_1k); |
| 191 | + assert_eq!(one_sample_duration.as_nanos(), 22675); |
214 | 192 | } |
215 | 193 | } |
0 commit comments