qualia_core_db/audio/
dsp_kernel.rs1use crate::audio::audio_spectral_sheet::SPECTRAL_PREVIEW_BINS;
6
7#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct ParametricVoiceState {
10 pub phase: f32,
11 pub frequency_hz: f32,
12 pub gain: f32,
13 pub fm_index: f32,
14}
15
16impl Default for ParametricVoiceState {
17 fn default() -> Self {
18 Self {
19 phase: 0.0,
20 frequency_hz: 440.0,
21 gain: 0.0,
22 fm_index: 0.0,
23 }
24 }
25}
26
27#[inline]
29pub fn epistemic_temperature_from_q(q: f32) -> f32 {
30 (q * q).clamp(0.0, 4.0)
31}
32
33#[inline]
35pub fn epistemic_fm_index(q: f32, mu: f32) -> f32 {
36 let tau = epistemic_temperature_from_q(q);
37 (tau * 0.25 + mu.abs() * 0.5).clamp(0.0, 8.0)
38}
39
40#[inline]
42pub fn sigma_dominant_frequency(bins: &[f32; SPECTRAL_PREVIEW_BINS], base_hz: f32) -> f32 {
43 let mut peak = 0usize;
44 let mut max_e = 0.0_f32;
45 for (i, &e) in bins.iter().enumerate() {
46 let a = e.abs();
47 if a > max_e {
48 max_e = a;
49 peak = i;
50 }
51 }
52 let ratio = (peak as f32 + 1.0) / SPECTRAL_PREVIEW_BINS as f32;
53 (base_hz * (0.5 + ratio * 3.0)).clamp(55.0, 8_000.0)
54}
55
56#[inline]
58pub fn parametric_sample(state: &mut ParametricVoiceState, sample_rate: f32) -> f32 {
59 let dt = 1.0 / sample_rate.max(1.0);
60 let mod_phase = state.phase * (1.0 + state.fm_index * 0.01);
61 let sample = (mod_phase * std::f32::consts::TAU).sin() * state.gain;
62 state.phase += state.frequency_hz * dt;
63 if state.phase > 1.0 {
64 state.phase -= state.phase.floor();
65 }
66 sample
67}
68
69#[inline]
71pub fn configure_voice_from_tensor(
72 state: &mut ParametricVoiceState,
73 q: f32,
74 mu: f32,
75 alpha: f32,
76 bins: &[f32; SPECTRAL_PREVIEW_BINS],
77) {
78 state.frequency_hz = sigma_dominant_frequency(bins, 220.0);
79 state.gain = alpha.clamp(0.0, 1.0) * 0.35;
80 state.fm_index = epistemic_fm_index(q, mu);
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn epistemic_temperature_monotonic() {
89 assert!(epistemic_temperature_from_q(1.0) > epistemic_temperature_from_q(0.5));
90 }
91
92 #[test]
93 fn parametric_sample_bounded() {
94 let mut v = ParametricVoiceState {
95 gain: 1.0,
96 frequency_hz: 440.0,
97 ..Default::default()
98 };
99 for _ in 0..512 {
100 let s = parametric_sample(&mut v, 48_000.0);
101 assert!(s >= -1.0 && s <= 1.0);
102 }
103 }
104
105 #[test]
106 fn sigma_frequency_in_audible_range() {
107 let bins = [0.0_f32; SPECTRAL_PREVIEW_BINS];
108 let mut hot = bins;
109 hot[32] = 1.0;
110 let hz = sigma_dominant_frequency(&hot, 220.0);
111 assert!(hz >= 55.0 && hz <= 8_000.0);
112 }
113}