1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
extern crate time;
use std::thread;
use std::ops::{Div, Range};
extern crate num;
use num::{One};
#[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 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
}
#[inline]
pub fn current_time_ns() -> u64 {
time::precise_time_ns()
}
pub fn sleep_for_constant_rate(fps: usize, ns_before: u64) {
let ns_per_frame = fps_to_ns_per_frame(fps);
let ns_after: u64 = time::precise_time_ns();
let ns_elapsed = ns_after - ns_before;
if ns_elapsed < ns_per_frame {
let ns_left_to_sleep = ns_per_frame - ns_elapsed;
thread::sleep_ms(ns_to_ms(ns_left_to_sleep) as u32);
}
}
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.),
(43.06640625)..22050.);
assert_eq!(
hertz_range(44100., 512.),
(86.1328125)..22050.);
}
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.);
}
fn rayleigh<T>(sample_rate: T, window_size: T) -> T
where T: Div<T, Output=T> + From<u16>
{
T::from(1 as u16) / seconds_per_window(sample_rate, window_size)
}
#[test]
fn test_rayleigh() {
assert_eq!(rayleigh(44100., 1024.), 43.06640625);
}
fn seconds_per_window<T>(samples_per_second: T, samples_per_window: T) -> T
where T: Div<T, Output=T>
{
samples_per_window / samples_per_second
}