Skip to main content

sva_engine/
query.rs

1// Concern: names every observation, what each consumes, and the envelope an answer carries | Non-concern: taking one reading (answer.rs, sva-samples) | IO: (name) -> Representation, Consumes
2
3use sva_formula::{Line, SpectralSum};
4use sva_samples::{
5    Alias, Bands, Buffer, Consumes, Crest, EnvelopeFrame, FormantFrame, LedgerEntry, Loudness,
6    PitchFrame, Source, Spectrum, StereoImage,
7};
8
9use crate::bindings::Binding;
10
11/// The default window a framed reading uses when the observation names none.
12pub const DEFAULT_FRAME_SECS: f64 = 0.05;
13
14#[derive(Clone, Copy, Debug, PartialEq)]
15pub enum Representation {
16    Lines,
17    Atoms,
18    Spectrum {
19        max_peaks: usize,
20        frame_secs: Option<f64>,
21    },
22    Envelope {
23        frame_secs: Option<f64>,
24    },
25    Derivative,
26    Samples,
27    Ledger {
28        depth: usize,
29    },
30    Pitch {
31        max_notes: usize,
32        frame_secs: f64,
33    },
34    Formants {
35        max_formants: usize,
36        frame_secs: f64,
37    },
38    Stereo {
39        frame_secs: f64,
40    },
41    Bands,
42    Crest,
43    Loudness,
44    Alias {
45        oversample: u32,
46    },
47    Bindings,
48    Flops,
49}
50
51/// What a caller asked of one node.
52#[derive(Clone, Debug, PartialEq)]
53pub struct Ask {
54    pub node: String,
55    pub representation: Representation,
56}
57
58#[derive(Clone, Debug, PartialEq)]
59pub enum Output {
60    Lines(Vec<Line>),
61    Atoms(Vec<String>),
62    Symbolic(Box<SpectralSum>),
63    Samples(Box<Buffer>),
64    Spectrum(Box<Spectrum>),
65    Envelope(Vec<EnvelopeFrame>),
66    Pitch(Vec<PitchFrame>),
67    Formants(Vec<FormantFrame>),
68    Stereo(Box<StereoImage>),
69    Bands(Box<Bands>),
70    Crest(Box<Crest>),
71    Loudness(Box<Loudness>),
72    Alias(Box<Alias>),
73    Ledger(Vec<LedgerEntry>),
74    Bindings(Vec<Binding>),
75    Flops(Box<crate::flops::Tree>),
76}
77
78/// Every answer says which reading ran and under which profile, so a caller never has to
79/// infer either from the shape of the value.
80#[derive(Clone, Debug, PartialEq)]
81pub struct Answer {
82    pub value: Output,
83    pub source: Source,
84    pub profile: &'static str,
85    pub rate: Option<u32>,
86    /// FORMAT 14.1: a series answers the terms above the floor, the tail beside them.
87    pub dropped: Vec<sva_formula::Line>,
88    pub tail_db: Option<f64>,
89}
90
91impl Answer {
92    pub fn whole(
93        value: Output,
94        source: Source,
95        profile: &'static str,
96        rate: Option<u32>,
97    ) -> Answer {
98        Answer {
99            value,
100            source,
101            profile,
102            rate,
103            dropped: Vec::new(),
104            tail_db: None,
105        }
106    }
107}
108
109impl Representation {
110    pub fn name(self) -> &'static str {
111        match self {
112            Representation::Lines => "lines",
113            Representation::Atoms => "atoms",
114            Representation::Spectrum { .. } => "spectrum",
115            Representation::Envelope { .. } => "envelope",
116            Representation::Derivative => "derivative",
117            Representation::Samples => "samples",
118            Representation::Ledger { .. } => "ledger",
119            Representation::Pitch { .. } => "pitch",
120            Representation::Formants { .. } => "formants",
121            Representation::Stereo { .. } => "stereo",
122            Representation::Bands => "bands",
123            Representation::Crest => "crest",
124            Representation::Loudness => "loudness",
125            Representation::Alias { .. } => "alias",
126            Representation::Bindings => "bindings",
127            Representation::Flops => "flops",
128        }
129    }
130
131    /// `lines` and `atoms` read a closed form and nothing else. `spectrum`, `envelope`,
132    /// `derivative` and `pitch` read whichever the node holds, so its own `Ty` decides.
133    pub fn consumes(self, closed: bool) -> Consumes {
134        match self {
135            Representation::Lines | Representation::Atoms => Consumes::ClosedForm,
136            Representation::Spectrum { .. }
137            | Representation::Envelope { .. }
138            | Representation::Derivative
139            | Representation::Pitch { .. }
140                if closed =>
141            {
142                Consumes::ClosedForm
143            }
144            // Neither reads a buffer: one is resolved first, the other counts the schedule.
145            Representation::Bindings | Representation::Flops => Consumes::ClosedForm,
146            _ => Consumes::Buffer,
147        }
148    }
149
150    pub fn from_name(name: &str) -> Option<Representation> {
151        Some(match name {
152            "lines" => Representation::Lines,
153            "atoms" => Representation::Atoms,
154            "spectrum" => Representation::Spectrum {
155                max_peaks: 16,
156                frame_secs: None,
157            },
158            "envelope" => Representation::Envelope { frame_secs: None },
159            "derivative" => Representation::Derivative,
160            "samples" => Representation::Samples,
161            "ledger" => Representation::Ledger { depth: 3 },
162            "pitch" => Representation::Pitch {
163                max_notes: 6,
164                frame_secs: DEFAULT_FRAME_SECS,
165            },
166            "formants" => Representation::Formants {
167                max_formants: 5,
168                frame_secs: DEFAULT_FRAME_SECS,
169            },
170            "stereo" => Representation::Stereo {
171                frame_secs: DEFAULT_FRAME_SECS,
172            },
173            "bands" => Representation::Bands,
174            "crest" => Representation::Crest,
175            "loudness" => Representation::Loudness,
176            "alias" => Representation::Alias { oversample: 4 },
177            "bindings" => Representation::Bindings,
178            "flops" => Representation::Flops,
179            _ => return None,
180        })
181    }
182}