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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
pub struct TwiddleFactors {
pub a :Vec<f32>,
pub b :Vec<f32>,
pub c :Vec<f32>,
}
pub struct CachedBlocksizeDerived {
pub twiddle_factors : TwiddleFactors,
pub window_slope : Vec<f32>,
pub bitrev : Vec<u32>,
}
impl CachedBlocksizeDerived {
pub fn from_blocksize(bs :u8) -> Self {
CachedBlocksizeDerived {
window_slope : generate_window((1 << (bs as u16)) >> 1),
twiddle_factors : compute_twiddle_factors(bs),
bitrev : compute_bitreverse(bs),
}
}
}
fn win_slope(x :u16, n :u16) -> f32 {
let v = (0.5 * ::std::f32::consts::PI * (x as f32 + 0.5) / n as f32).sin();
return (0.5 * ::std::f32::consts::PI * v * v ).sin();
}
fn generate_window(n :u16) -> Vec<f32> {
let mut window = Vec::with_capacity(n as usize);
for i in 0 .. n {
window.push(win_slope(i, n));
}
return window;
}
fn compute_twiddle_factors(blocksize :u8) -> TwiddleFactors {
let n = 1 << (blocksize as u16);
let n2 = n >> 1;
let n4 = n >> 2;
let n8 = n >> 3;
let mut a = Vec::with_capacity(n2);
let mut b = Vec::with_capacity(n2);
let mut c = Vec::with_capacity(n4);
let mut k2 = 0;
let pi_4_n = 4.0 * ::std::f32::consts::PI / (n as f32);
let pi_05_n = 0.5 * ::std::f32::consts::PI / (n as f32);
let pi_2_n = 2.0 * ::std::f32::consts::PI / (n as f32);
for k in 0..n4 {
a.push( f32::cos((k as f32) * pi_4_n));
a.push(-f32::sin((k as f32) * pi_4_n));
b.push( f32::cos(((k2+1) as f32) * pi_05_n) * 0.5);
b.push( f32::sin(((k2+1) as f32) * pi_05_n) * 0.5);
k2 += 2;
}
k2 = 0;
for _ in 0..n8 {
c.push( f32::cos(((k2 + 1) as f32) * pi_2_n));
c.push(-f32::sin(((k2 + 1) as f32) * pi_2_n));
k2 += 2;
}
return TwiddleFactors {
a : a,
b : b,
c : c,
};
}
fn compute_bitreverse(blocksize :u8) -> Vec<u32> {
let ld = blocksize as u16;
let n = 1 << blocksize;
let n8 = n >> 3;
let mut rev = Vec::with_capacity(n8);
for i in 0 .. n8 {
rev.push((::bit_reverse(i as u32) as u32 >> (32 - ld + 3)) << 2);
}
return rev;
}
#[test]
fn test_compute_bitreverse() {
let br = compute_bitreverse(8);
let cmp_arr = &[
0, 64, 32, 96,
16, 80, 48, 112,
8, 72, 40, 104,
24, 88, 56, 120,
4, 68, 36, 100,
20, 84, 52, 116,
12, 76, 44, 108,
28, 92, 60, 124];
assert_eq!(br, cmp_arr);
}
#[inline]
fn bark(x :f32) -> f32 {
13.1 * (0.00074 * x).atan() + 2.24 * (0.0000000185*x*x).atan() + 0.0001 * x
}
pub fn compute_bark_map_cos_omega(n :u16, floor0_rate :u16,
floor0_bark_map_size :u16) -> Vec<f32> {
let mut res = Vec::with_capacity(n as usize);
let hfl = floor0_rate as f32 / 2.0;
let hfl_dn = hfl / n as f32;
let foobar_const_part = floor0_bark_map_size as f32 / bark(hfl);
let bms_m1 = floor0_bark_map_size as f32 - 1.0;
let omega_factor = ::std::f32::consts::PI / floor0_bark_map_size as f32;
for i in 0 .. n {
let foobar = (bark(i as f32 * hfl_dn) * foobar_const_part).floor();
let map_elem = foobar.min(bms_m1);
let cos_omega = (map_elem * omega_factor).cos();
res.push(cos_omega);
}
return res;
}