Skip to main content

sva_samples/
profile.rs

1// Concern: the named tolerance set every label cites, and the ceiling and floor it puts on a rate | Non-concern: what a collapse does with either (collapse/), choosing the rate | IO: none -> Profile
2
3use sva_formula::{ContentHasher, HashDomain};
4
5#[derive(Clone, Copy, Debug, PartialEq)]
6pub struct Profile {
7    pub name: &'static str,
8    pub floor_db: f64,
9    pub floor_db_above_5k: f64,
10    pub ceiling_hz: f64,
11    pub precision_bits: i32,
12    pub silence_threshold_dbfs: f64,
13}
14
15pub const PSYCHOACOUSTIC_V1: Profile = Profile {
16    name: "psychoacoustic-v1",
17    floor_db: -20.0,
18    floor_db_above_5k: -25.0,
19    ceiling_hz: 20_000.0,
20    precision_bits: 24,
21    silence_threshold_dbfs: -120.0,
22};
23
24impl Profile {
25    pub fn ceiling(&self, rate: u32) -> f64 {
26        self.ceiling_hz.min(f64::from(rate) / 2.0)
27    }
28
29    pub fn half_lsb(&self) -> f64 {
30        2f64.powi(-self.precision_bits)
31    }
32
33    pub fn silence_threshold_amplitude(&self) -> f64 {
34        10f64.powf(self.silence_threshold_dbfs / 20.0)
35    }
36
37    /// Every setting a value or its label depends on.
38    pub fn deciding(&self) -> [u64; 6] {
39        let Profile {
40            name,
41            floor_db,
42            floor_db_above_5k,
43            ceiling_hz,
44            precision_bits,
45            silence_threshold_dbfs: _,
46        } = *self;
47        let mut named = ContentHasher::new(HashDomain::ProfileName);
48        named.text(name);
49        let named = named.finish();
50        [
51            named.0,
52            named.1,
53            floor_db.to_bits(),
54            floor_db_above_5k.to_bits(),
55            ceiling_hz.to_bits(),
56            precision_bits as u64,
57        ]
58    }
59
60    pub fn floor(&self, hz: f64) -> f64 {
61        if hz > 5_000.0 {
62            self.floor_db_above_5k
63        } else {
64            self.floor_db
65        }
66    }
67}