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