Skip to main content

sva_samples/measure/
mod.rs

1// Concern: groups the readings taken off samples, and declares the three things one can consume | Non-concern: which reading consumes which (sva-engine's query.rs) | IO: none
2
3pub mod alias;
4pub mod bands;
5pub mod crest;
6pub mod envelope;
7pub mod formants;
8pub mod harmony;
9pub mod ledger;
10pub mod loudness;
11pub mod loudness_pattern;
12pub mod modulation;
13pub mod panel;
14pub mod partials;
15pub mod peaks;
16pub mod periodicity;
17pub mod pitch;
18pub mod score;
19pub mod self_similarity;
20pub mod sliding;
21pub mod spectrum;
22pub mod stereo;
23pub(crate) mod stiff;
24
25pub(crate) fn scaled_pow2(samples_48k: f64, sr: f64) -> usize {
26    let n = (samples_48k * sr / 48_000.0).max(2.0);
27    let below = (n as usize).next_power_of_two() / 2;
28    match below >= 2 && n - below as f64 <= (2 * below) as f64 - n {
29        true => below,
30        false => (2 * below).max(2),
31    }
32}
33
34pub(crate) fn held(planes: &[&[f64]]) -> usize {
35    let len = planes
36        .first()
37        .expect("a reading reads at least one channel")
38        .len();
39    assert!(
40        planes.iter().all(|p| p.len() == len),
41        "a reading's channels are one length"
42    );
43    len
44}
45
46/// Every channel in power, as `envelope` reads it: summed, then divided by the count.
47pub(crate) fn averaged(per_channel: Vec<Vec<f64>>) -> Vec<f64> {
48    let count = per_channel.len() as f64;
49    let mut each = per_channel.into_iter();
50    let mut out = each.next().unwrap_or_default();
51    for more in each {
52        for (sum, x) in out.iter_mut().zip(more) {
53            *sum += x;
54        }
55    }
56    out.iter_mut().for_each(|sum| *sum /= count);
57    out
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq)]
61pub enum Consumes {
62    ClosedForm,
63    Buffer,
64    Frames,
65}