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,
b,
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;
}