1mod stats;
4mod store;
5
6pub use stats::{CacheStats, Lookup, Outcome};
7pub(crate) use stats::{Lens, Recording};
8pub use store::{Cache, CachePolicy, DEFAULT_CACHE_BYTES, PrunePolicy};
9pub use sva_formula::Hash;
10
11use sva_formula::SpectralSum;
12use sva_samples::{Buffer, Frames, Label};
13
14#[derive(Clone, Debug, PartialEq)]
16pub enum Payload {
17 Samples(Box<Buffer>),
18 Frames(Box<Frames>),
19 Symbolic(Box<SpectralSum>),
20}
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum PayloadKind {
24 Samples,
25 Frames,
26 Symbolic,
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq)]
31pub enum Expected {
32 Samples {
33 rate: u32,
34 width: usize,
35 samples: usize,
36 },
37 Frames,
38 Symbolic,
39}
40
41#[derive(Clone, Debug, PartialEq)]
42pub struct Entry {
43 pub payload: Payload,
44 pub label: Option<Label>,
46}
47
48impl Expected {
49 pub fn kind(self) -> PayloadKind {
50 match self {
51 Expected::Samples { .. } => PayloadKind::Samples,
52 Expected::Frames => PayloadKind::Frames,
53 Expected::Symbolic => PayloadKind::Symbolic,
54 }
55 }
56}
57
58impl Payload {
59 pub fn kind(&self) -> PayloadKind {
60 match self {
61 Payload::Samples(_) => PayloadKind::Samples,
62 Payload::Frames(_) => PayloadKind::Frames,
63 Payload::Symbolic(_) => PayloadKind::Symbolic,
64 }
65 }
66
67 pub fn samples(&self) -> Option<&Buffer> {
68 match self {
69 Payload::Samples(buffer) => Some(buffer),
70 _ => None,
71 }
72 }
73
74 pub fn symbolic(&self) -> Option<&SpectralSum> {
75 match self {
76 Payload::Symbolic(sum) => Some(sum),
77 _ => None,
78 }
79 }
80
81 pub fn bytes(&self) -> usize {
82 match self {
83 Payload::Samples(b) => b.len() * b.width * size_of::<f64>(),
84 Payload::Frames(f) => f.width * f.frames * f.bins * 2 * size_of::<f64>(),
85 Payload::Symbolic(n) => {
86 size_of::<SpectralSum>()
87 + n.lanes
88 .iter()
89 .map(|lane| {
90 lane.atoms.len() * size_of::<sva_formula::SpectralAtom>()
91 + (lane.series.len() + lane.modal.len()) * size_of::<SpectralSum>()
92 })
93 .sum::<usize>()
94 }
95 }
96 }
97
98 pub fn answers(&self, expected: Expected) -> bool {
99 match (self, expected) {
100 (
101 Payload::Samples(b),
102 Expected::Samples {
103 rate,
104 width,
105 samples,
106 },
107 ) => b.rate == rate && b.width == width && b.len() == samples,
108 (Payload::Frames(_), Expected::Frames) => true,
109 (Payload::Symbolic(_), Expected::Symbolic) => true,
110 _ => false,
111 }
112 }
113}
114
115pub fn symbolic_key(src: Hash) -> Hash {
117 mixed(src, &[0x73_79_6d_62_6f_6c_69_63])
118}
119
120pub fn frames_key(buffer: Hash, window: usize, hop: usize) -> Hash {
122 mixed(
123 buffer,
124 &[window as u64, hop as u64, 0x66_72_61_6d_65_73_00_01],
125 )
126}
127
128pub fn buffer_key(
131 symbolic: Hash,
132 rate: u32,
133 origin_secs: f64,
134 samples: usize,
135 width: usize,
136 score: sva_samples::AliasScore,
137) -> Hash {
138 mixed(
139 symbolic,
140 &[
141 u64::from(rate),
142 origin_secs.to_bits(),
143 samples as u64,
144 width as u64,
145 u64::from(score == sva_samples::AliasScore::Asked),
146 0x62_75_66_66_65_72_00_01,
147 ],
148 )
149}
150
151const ADDRESS_ROTATE: u32 = 17;
152
153pub(crate) fn mixed(seed: Hash, parts: &[u64]) -> Hash {
154 let mut lanes = sva_formula::Lanes::<ADDRESS_ROTATE>::from(seed);
155 for part in parts {
156 lanes.word(*part);
157 }
158 lanes.finish()
159}