use std::time;
use std::ops::{Mul, Div, Range};
#[inline]
pub fn ns_to_s(ns: u64) -> f64 {
(ns as f64) / 1_000_000_000.
}
#[inline]
pub fn s_to_ns(s: f64) -> f64 {
s * 1_000_000_000.
}
#[inline]
pub fn ns_to_ms(ns: u64) -> f64 {
(ns as f64) / 1_000_000.
}
#[inline]
pub fn s_to_ms<T>(s: T) -> T
where T: Mul<T, Output=T> + From<u16>
{
s * T::from(1000 as u16)
}
#[test]
fn test_s_to_ms() {
assert_eq!(s_to_ms(1), 1000);
assert_eq!(s_to_ms(1.), 1000.);
}
#[inline]
pub fn ms_to_s<T>(ms: T) -> T
where T: Div<T, Output=T> + From<u16>
{
ms / T::from(1000 as u16)
}
#[test]
fn test_ms_to_s() {
assert_eq!(ms_to_s(1000), 1);
assert_eq!(ms_to_s(1000.), 1.);
}
#[inline]
pub fn ms_to_ns(ns: f64) -> f64 {
ns * 1_000_000.
}
#[inline]
pub fn fps_to_ns_per_frame(fps: usize) -> u64 {
(s_to_ns(1.0) / (fps as f64)).round() as u64
}
pub fn sleep_for_constant_rate(fps: usize, instant_at_last_frame_start: time::Instant) {
let ns_per_frame = fps_to_ns_per_frame(fps);
let frame_duration = time::Duration::new(ns_per_frame * 1000000000, (ns_per_frame % 1000000000) as u32);
let elapsed = instant_at_last_frame_start.elapsed();
if elapsed < frame_duration {
std::thread::sleep(frame_duration - elapsed);
}
}
pub fn hertz_range<T>(sample_rate: T, window_size: T) -> Range<T>
where T: Div<T, Output=T> + From<u16> + Clone
{
rayleigh(sample_rate.clone(), window_size)..nyquist(sample_rate)
}
#[test]
fn test_hertz_range() {
assert_eq!(
hertz_range(44100., 1024. * 8.),
(5.38330078125)..22050.);
assert_eq!(
hertz_range(44100., 1024. * 4.),
(10.7666015625)..22050.);
assert_eq!(
hertz_range(44100., 1024.),
(43.06640625)..22050.);
assert_eq!(
hertz_range(44100., 512.),
(86.1328125)..22050.);
}
pub fn nyquist<T>(sample_rate: T) -> T
where T: Div<T, Output=T> + From<u16>
{
sample_rate / T::from(2 as u16)
}
#[test]
fn test_nyquist() {
assert_eq!(nyquist(44100.), 22050.);
}
pub fn rayleigh<T>(sample_rate: T, window_size: T) -> T
where T: Div<T, Output=T> + From<u16>
{
T::from(1 as u16) / cycles_per_second_to_seconds_per_cycle(sample_rate, window_size)
}
#[test]
fn test_rayleigh() {
assert_eq!(rayleigh(44100., 1024.), 43.06640625);
}
pub fn cycles_per_second_to_seconds_per_cycle<T>(cycles_per_second: T, cycles: T) -> T
where T: Div<T, Output=T>
{
cycles / cycles_per_second
}
#[test]
fn test_seconds_per_window() {
assert_eq!(cycles_per_second_to_seconds_per_cycle(44100., 512.), 0.011609977324263039);
assert_eq!(cycles_per_second_to_seconds_per_cycle(44100., 1024.), 0.023219954648526078);
}