1use std::convert::Into;
2use std::convert::TryFrom;
3use std::fmt;
4use std::time::Duration;
5
6pub const DAYS_IN_A_WEEK: u64 = 7;
7pub const HOURS_IN_A_DAY: u64 = 24;
8pub const MINUTES_IN_A_HOUR: u64 = 60;
9pub const SECONDS_IN_A_MINUTE: u64 = 60;
10pub const SECONDS_IN_A_HOUR: u64 = 3600;
11pub const SECONDS_IN_A_DAY: u64 = 86400;
12pub const SECONDS_IN_A_WEEK: u64 = 604800;
13
14pub const SAMPLING_FREQUENCY_8000: u32 = 8000;
16
17pub const SAMPLING_FREQUENCY_11025: u32 = 11025;
19
20pub const SAMPLING_FREQUENCY_16000: u32 = 16000;
22
23pub const SAMPLING_FREQUENCY_22050: u32 = 22050;
25
26pub const SAMPLING_FREQUENCY_32000: u32 = 32000;
28
29pub const SAMPLING_FREQUENCY_44100: u32 = 44100;
31
32pub const SAMPLING_FREQUENCY_48000: u32 = 48000;
34
35pub const SAMPLING_FREQUENCY_88200: u32 = 88200;
37
38pub const SAMPLING_FREQUENCY_96000: u32 = 96000;
40
41pub const SAMPLING_FREQUENCY_176400: u32 = 176400;
43
44pub const SAMPLING_FREQUENCY_192000: u32 = 192000;
46
47pub const SAMPLING_FREQUENCY_352800: u32 = 352800;
49
50pub const SAMPLING_FREQUENCY_384000: u32 = 384000;
52
53pub const SAMPLING_FREQUENCY_705600: u32 = 705600;
55
56pub const SAMPLING_FREQUENCY_768000: u32 = 768000;
58
59pub const SAMPLING_FREQUENCY_2822400: u32 = 2822400;
61
62pub const SAMPLING_FREQUENCY_5644800: u32 = 5644800;
64
65pub const SAMPLING_FREQUENCY_11289600: u32 = 11289600;
67
68pub const SAMPLING_FREQUENCY_22579200: u32 = 22579200;
70
71pub struct AudioDuration {
72 samples: u64,
73 sampling_frequency: u32,
74}
75impl AudioDuration {
76 pub fn new(samples: u64, sampling_frequency: u32) -> AudioDuration {
78 AudioDuration {
79 samples,
80 sampling_frequency,
81 }
82 }
83
84 pub fn samples(&self) -> u64 {
86 self.samples
87 }
88
89 pub fn set_samples(&mut self, samples: u64) {
91 self.samples = samples
92 }
93
94 pub fn sampling_frequency(&self) -> u32 {
96 self.sampling_frequency
97 }
98
99 pub fn as_secs(&self) -> u64 {
101 self.samples / self.sampling_frequency as u64
102 }
103
104 pub fn as_mins(&self) -> u64 {
106 self.as_secs() / SECONDS_IN_A_MINUTE
107 }
108
109 pub fn as_hours(&self) -> u64 {
111 self.as_secs() / SECONDS_IN_A_HOUR
112 }
113
114 pub fn as_days(&self) -> u64 {
116 self.as_secs() / SECONDS_IN_A_DAY
117 }
118
119 pub fn as_weeks(&self) -> u64 {
121 self.as_secs() / SECONDS_IN_A_WEEK
122 }
123
124 pub fn subsec_samples(&self) -> u32 {
128 let remainder = self.samples % self.sampling_frequency as u64;
129
130 u32::try_from(remainder).unwrap()
131 }
132
133 pub fn subsec_nanos(&self) -> u32 {
136 let nanos_as_f64 = self.subsec_secs() * 1000000000.0;
137
138 nanos_as_f64 as u32
139 }
140
141 pub fn subsec_secs(&self) -> f64 {
145 self.subsec_samples() as f64 / self.sampling_frequency as f64
146 }
147
148 pub fn submin_secs(&self) -> u64 {
150 self.as_secs() % SECONDS_IN_A_MINUTE
151 }
152
153 pub fn subhour_mins(&self) -> u64 {
155 self.as_mins() % MINUTES_IN_A_HOUR
156 }
157
158 pub fn subday_hours(&self) -> u64 {
160 self.as_hours() % HOURS_IN_A_DAY
161 }
162
163 pub fn subweek_days(&self) -> u64 {
165 self.as_days() % DAYS_IN_A_WEEK
166 }
167
168 pub fn duration(&self) -> Duration {
170 Duration::new(self.as_secs(), self.subsec_nanos())
171 }
172
173 pub fn fmt_hhmmss_samples(&self) -> String {
175 format!(
176 "{:02}:{:02}:{:02};{}",
177 self.as_hours(),
178 self.subhour_mins(),
179 self.submin_secs(),
180 self.subsec_samples(),
181 )
182 }
183
184 pub fn fmt_hhmmss(&self) -> String {
186 format!(
187 "{:02}:{:02}:{:02}",
188 self.as_hours(),
189 self.subhour_mins(),
190 self.submin_secs(),
191 )
192 }
193
194 pub fn fmt_opt_hh_mmss(&self) -> String {
197 if self.as_hours() == 0 {
198 format!("{:02}:{:02}", self.subhour_mins(), self.submin_secs())
199 } else {
200 self.fmt_hhmmss()
201 }
202 }
203}
204impl fmt::Display for AudioDuration {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 write!(f, "{}", self.fmt_hhmmss_samples())
207 }
208}
209impl Into<Duration> for AudioDuration {
210 fn into(self) -> Duration {
211 self.duration()
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn new_and_getters() {
221 let samples: u64 = 32572394598;
222 let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
223
224 assert_eq!(audio_duration.samples(), samples);
225 assert_eq!(
226 audio_duration.sampling_frequency(),
227 SAMPLING_FREQUENCY_44100
228 );
229 assert_eq!(audio_duration.as_secs(), 738603);
230 assert_eq!(audio_duration.as_mins(), 12310);
231 assert_eq!(audio_duration.as_hours(), 205);
232 assert_eq!(audio_duration.as_days(), 8);
233 assert_eq!(audio_duration.as_weeks(), 1);
234 assert_eq!(audio_duration.subsec_samples(), 2298);
235 assert_eq!(audio_duration.subsec_nanos(), 52108843);
236 assert_eq!(audio_duration.subsec_secs(), 0.05210884353741497);
237 assert_eq!(audio_duration.submin_secs(), 3);
238 assert_eq!(audio_duration.subhour_mins(), 10);
239 assert_eq!(audio_duration.subday_hours(), 13);
240 assert_eq!(audio_duration.subweek_days(), 1);
241
242 assert_eq!(audio_duration.to_string(), "205:10:03;2298");
243 }
244
245 #[test]
246 fn duration() {
247 let samples: u64 = 52394599;
248 let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
249 let duration: Duration = audio_duration.into();
250
251 assert_eq!(duration, Duration::new(1188, 86145124));
252 }
253
254 #[test]
255 fn fmt() {
256 let samples: u64 = 52394599;
257 let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
258 assert_eq!(audio_duration.fmt_hhmmss(), "00:19:48");
259 assert_eq!(audio_duration.fmt_opt_hh_mmss(), "19:48");
260
261 let samples: u64 = 952394599;
262 let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
263 assert_eq!(audio_duration.fmt_hhmmss(), "05:59:56");
264 assert_eq!(audio_duration.fmt_opt_hh_mmss(), "05:59:56");
265 }
266}