use std::convert::Into;
use std::convert::TryFrom;
use std::fmt;
use std::time::Duration;
pub const DAYS_IN_A_WEEK: u64 = 7;
pub const HOURS_IN_A_DAY: u64 = 24;
pub const MINUTES_IN_A_HOUR: u64 = 60;
pub const SECONDS_IN_A_MINUTE: u64 = 60;
pub const SECONDS_IN_A_HOUR: u64 = 3600;
pub const SECONDS_IN_A_DAY: u64 = 86400;
pub const SECONDS_IN_A_WEEK: u64 = 604800;
pub const SAMPLING_FREQUENCY_8000: u32 = 8000;
pub const SAMPLING_FREQUENCY_11025: u32 = 11025;
pub const SAMPLING_FREQUENCY_16000: u32 = 16000;
pub const SAMPLING_FREQUENCY_22050: u32 = 22050;
pub const SAMPLING_FREQUENCY_32000: u32 = 32000;
pub const SAMPLING_FREQUENCY_44100: u32 = 44100;
pub const SAMPLING_FREQUENCY_48000: u32 = 48000;
pub const SAMPLING_FREQUENCY_88200: u32 = 88200;
pub const SAMPLING_FREQUENCY_96000: u32 = 96000;
pub const SAMPLING_FREQUENCY_176400: u32 = 176400;
pub const SAMPLING_FREQUENCY_192000: u32 = 192000;
pub const SAMPLING_FREQUENCY_352800: u32 = 352800;
pub const SAMPLING_FREQUENCY_384000: u32 = 384000;
pub const SAMPLING_FREQUENCY_705600: u32 = 705600;
pub const SAMPLING_FREQUENCY_768000: u32 = 768000;
pub const SAMPLING_FREQUENCY_2822400: u32 = 2822400;
pub const SAMPLING_FREQUENCY_5644800: u32 = 5644800;
pub const SAMPLING_FREQUENCY_11289600: u32 = 11289600;
pub const SAMPLING_FREQUENCY_22579200: u32 = 22579200;
pub struct AudioDuration {
samples: u64,
sampling_frequency: u32,
}
impl AudioDuration {
pub fn new(samples: u64, sampling_frequency: u32) -> AudioDuration {
AudioDuration {
samples,
sampling_frequency,
}
}
pub fn samples(&self) -> u64 {
self.samples
}
pub fn set_samples(&mut self, samples: u64) {
self.samples = samples
}
pub fn sampling_frequency(&self) -> u32 {
self.sampling_frequency
}
pub fn as_secs(&self) -> u64 {
self.samples / self.sampling_frequency as u64
}
pub fn as_mins(&self) -> u64 {
self.as_secs() / SECONDS_IN_A_MINUTE
}
pub fn as_hours(&self) -> u64 {
self.as_secs() / SECONDS_IN_A_HOUR
}
pub fn as_days(&self) -> u64 {
self.as_secs() / SECONDS_IN_A_DAY
}
pub fn as_weeks(&self) -> u64 {
self.as_secs() / SECONDS_IN_A_WEEK
}
pub fn subsec_samples(&self) -> u32 {
let remainder = self.samples % self.sampling_frequency as u64;
u32::try_from(remainder).unwrap()
}
pub fn subsec_nanos(&self) -> u32 {
let nanos_as_f64 = self.subsec_secs() * 1000000000.0;
nanos_as_f64 as u32
}
pub fn subsec_secs(&self) -> f64 {
self.subsec_samples() as f64 / self.sampling_frequency as f64
}
pub fn submin_secs(&self) -> u64 {
self.as_secs() % SECONDS_IN_A_MINUTE
}
pub fn subhour_mins(&self) -> u64 {
self.as_mins() % MINUTES_IN_A_HOUR
}
pub fn subday_hours(&self) -> u64 {
self.as_hours() % HOURS_IN_A_DAY
}
pub fn subweek_days(&self) -> u64 {
self.as_days() % DAYS_IN_A_WEEK
}
pub fn duration(&self) -> Duration {
Duration::new(self.as_secs(), self.subsec_nanos())
}
pub fn fmt_hhmmss_samples(&self) -> String {
format!(
"{:02}:{:02}:{:02};{}",
self.as_hours(),
self.subhour_mins(),
self.submin_secs(),
self.subsec_samples(),
)
}
pub fn fmt_hhmmss(&self) -> String {
format!(
"{:02}:{:02}:{:02}",
self.as_hours(),
self.subhour_mins(),
self.submin_secs(),
)
}
pub fn fmt_opt_hh_mmss(&self) -> String {
if self.as_hours() == 0 {
format!("{:02}:{:02}", self.subhour_mins(), self.submin_secs())
} else {
self.fmt_hhmmss()
}
}
}
impl fmt::Display for AudioDuration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.fmt_hhmmss_samples())
}
}
impl Into<Duration> for AudioDuration {
fn into(self) -> Duration {
self.duration()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_and_getters() {
let samples: u64 = 32572394598;
let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
assert_eq!(audio_duration.samples(), samples);
assert_eq!(
audio_duration.sampling_frequency(),
SAMPLING_FREQUENCY_44100
);
assert_eq!(audio_duration.as_secs(), 738603);
assert_eq!(audio_duration.as_mins(), 12310);
assert_eq!(audio_duration.as_hours(), 205);
assert_eq!(audio_duration.as_days(), 8);
assert_eq!(audio_duration.as_weeks(), 1);
assert_eq!(audio_duration.subsec_samples(), 2298);
assert_eq!(audio_duration.subsec_nanos(), 52108843);
assert_eq!(audio_duration.subsec_secs(), 0.05210884353741497);
assert_eq!(audio_duration.submin_secs(), 3);
assert_eq!(audio_duration.subhour_mins(), 10);
assert_eq!(audio_duration.subday_hours(), 13);
assert_eq!(audio_duration.subweek_days(), 1);
assert_eq!(audio_duration.to_string(), "205:10:03;2298");
}
#[test]
fn duration() {
let samples: u64 = 52394599;
let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
let duration: Duration = audio_duration.into();
assert_eq!(duration, Duration::new(1188, 86145124));
}
#[test]
fn fmt() {
let samples: u64 = 52394599;
let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
assert_eq!(audio_duration.fmt_hhmmss(), "00:19:48");
assert_eq!(audio_duration.fmt_opt_hh_mmss(), "19:48");
let samples: u64 = 952394599;
let audio_duration = AudioDuration::new(samples, SAMPLING_FREQUENCY_44100);
assert_eq!(audio_duration.fmt_hhmmss(), "05:59:56");
assert_eq!(audio_duration.fmt_opt_hh_mmss(), "05:59:56");
}
}