1use bytemuck::{Pod, Zeroable};
7use ringkernel_core::prelude::*;
8use rkyv::{Archive, Deserialize, Serialize};
9
10pub mod message_types {
12 pub const AUDIO_FRAME: u64 = 0x4155_4449_4F00_0001; pub const FREQUENCY_BIN: u64 = 0x4155_4449_4F00_0002;
16 pub const NEIGHBOR_DATA: u64 = 0x4155_4449_4F00_0003;
18 pub const SEPARATED_BIN: u64 = 0x4155_4449_4F00_0004;
20 pub const FRAME_COMPLETE: u64 = 0x4155_4449_4F00_0005;
22 pub const BIN_CONTROL: u64 = 0x4155_4449_4F00_0006;
24}
25
26#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
28pub struct AudioFrame {
29 pub frame_id: u64,
31 pub sample_rate: u32,
33 pub channels: u8,
35 pub samples: Vec<f32>,
37 pub timestamp_samples: u64,
39}
40
41impl AudioFrame {
42 pub fn new(
44 frame_id: u64,
45 sample_rate: u32,
46 channels: u8,
47 samples: Vec<f32>,
48 timestamp_samples: u64,
49 ) -> Self {
50 Self {
51 frame_id,
52 sample_rate,
53 channels,
54 samples,
55 timestamp_samples,
56 }
57 }
58
59 pub fn duration_secs(&self) -> f64 {
61 let sample_count = self.samples.len() / self.channels as usize;
62 sample_count as f64 / self.sample_rate as f64
63 }
64
65 pub fn channel_samples(&self, channel: usize) -> Vec<f32> {
67 if channel >= self.channels as usize {
68 return Vec::new();
69 }
70 self.samples
71 .iter()
72 .skip(channel)
73 .step_by(self.channels as usize)
74 .copied()
75 .collect()
76 }
77}
78
79impl RingMessage for AudioFrame {
80 fn message_type() -> u64 {
81 message_types::AUDIO_FRAME
82 }
83
84 fn message_id(&self) -> MessageId {
85 MessageId::new(self.frame_id)
86 }
87
88 fn serialize(&self) -> Vec<u8> {
89 rkyv::to_bytes::<_, 256>(self)
90 .map(|v| v.to_vec())
91 .unwrap_or_default()
92 }
93
94 fn deserialize(bytes: &[u8]) -> ringkernel_core::error::Result<Self> {
95 let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
97 Ok(archived
98 .deserialize(&mut rkyv::Infallible)
99 .expect("rkyv::Infallible deserialization cannot fail"))
100 }
101}
102
103#[derive(Debug, Clone, Copy, Default, Pod, Zeroable, Archive, Serialize, Deserialize)]
105#[repr(C)]
106pub struct Complex {
107 pub re: f32,
109 pub im: f32,
111}
112
113impl Complex {
114 pub const fn new(re: f32, im: f32) -> Self {
116 Self { re, im }
117 }
118
119 pub fn from_polar(magnitude: f32, phase: f32) -> Self {
121 Self {
122 re: magnitude * phase.cos(),
123 im: magnitude * phase.sin(),
124 }
125 }
126
127 pub fn magnitude(&self) -> f32 {
129 (self.re * self.re + self.im * self.im).sqrt()
130 }
131
132 pub fn phase(&self) -> f32 {
134 self.im.atan2(self.re)
135 }
136
137 pub fn magnitude_squared(&self) -> f32 {
139 self.re * self.re + self.im * self.im
140 }
141
142 pub fn mul(&self, other: &Self) -> Self {
144 Self {
145 re: self.re * other.re - self.im * other.im,
146 im: self.re * other.im + self.im * other.re,
147 }
148 }
149
150 pub fn conj(&self) -> Self {
152 Self {
153 re: self.re,
154 im: -self.im,
155 }
156 }
157
158 pub fn add(&self, other: &Self) -> Self {
160 Self {
161 re: self.re + other.re,
162 im: self.im + other.im,
163 }
164 }
165
166 pub fn scale(&self, s: f32) -> Self {
168 Self {
169 re: self.re * s,
170 im: self.im * s,
171 }
172 }
173}
174
175#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
177pub struct FrequencyBin {
178 pub frame_id: u64,
180 pub bin_index: u32,
182 pub total_bins: u32,
184 pub value: Complex,
186 pub frequency_hz: f32,
188 pub prev_value: Option<Complex>,
190}
191
192impl FrequencyBin {
193 pub fn new(
195 frame_id: u64,
196 bin_index: u32,
197 total_bins: u32,
198 value: Complex,
199 frequency_hz: f32,
200 ) -> Self {
201 Self {
202 frame_id,
203 bin_index,
204 total_bins,
205 value,
206 frequency_hz,
207 prev_value: None,
208 }
209 }
210
211 pub fn with_prev_value(mut self, prev: Complex) -> Self {
213 self.prev_value = Some(prev);
214 self
215 }
216
217 pub fn magnitude_db(&self) -> f32 {
219 let mag = self.value.magnitude();
220 if mag > 1e-10 {
221 20.0 * mag.log10()
222 } else {
223 -200.0 }
225 }
226}
227
228impl RingMessage for FrequencyBin {
229 fn message_type() -> u64 {
230 message_types::FREQUENCY_BIN
231 }
232
233 fn message_id(&self) -> MessageId {
234 MessageId::new(self.frame_id * 10000 + self.bin_index as u64)
235 }
236
237 fn serialize(&self) -> Vec<u8> {
238 rkyv::to_bytes::<_, 128>(self)
239 .map(|v| v.to_vec())
240 .unwrap_or_default()
241 }
242
243 fn deserialize(bytes: &[u8]) -> ringkernel_core::error::Result<Self> {
244 let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
246 Ok(archived
247 .deserialize(&mut rkyv::Infallible)
248 .expect("rkyv::Infallible deserialization cannot fail"))
249 }
250}
251
252#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
254pub struct NeighborData {
255 pub source_bin: u32,
257 pub frame_id: u64,
259 pub value: Complex,
261 pub magnitude: f32,
263 pub phase: f32,
265 pub phase_derivative: f32,
267 pub spectral_flux: f32,
269}
270
271impl NeighborData {
272 pub fn from_bin(bin: &FrequencyBin, phase_derivative: f32, spectral_flux: f32) -> Self {
274 Self {
275 source_bin: bin.bin_index,
276 frame_id: bin.frame_id,
277 value: bin.value,
278 magnitude: bin.value.magnitude(),
279 phase: bin.value.phase(),
280 phase_derivative,
281 spectral_flux,
282 }
283 }
284}
285
286impl RingMessage for NeighborData {
287 fn message_type() -> u64 {
288 message_types::NEIGHBOR_DATA
289 }
290
291 fn message_id(&self) -> MessageId {
292 MessageId::new(self.frame_id * 10000 + self.source_bin as u64)
293 }
294
295 fn serialize(&self) -> Vec<u8> {
296 rkyv::to_bytes::<_, 64>(self)
297 .map(|v| v.to_vec())
298 .unwrap_or_default()
299 }
300
301 fn deserialize(bytes: &[u8]) -> ringkernel_core::error::Result<Self> {
302 let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
304 Ok(archived
305 .deserialize(&mut rkyv::Infallible)
306 .expect("rkyv::Infallible deserialization cannot fail"))
307 }
308}
309
310#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
312pub struct SeparatedBin {
313 pub frame_id: u64,
315 pub bin_index: u32,
317 pub direct: Complex,
319 pub ambience: Complex,
321 pub coherence: f32,
323 pub transient: f32,
325}
326
327impl SeparatedBin {
328 pub fn new(
330 frame_id: u64,
331 bin_index: u32,
332 direct: Complex,
333 ambience: Complex,
334 coherence: f32,
335 transient: f32,
336 ) -> Self {
337 Self {
338 frame_id,
339 bin_index,
340 direct,
341 ambience,
342 coherence,
343 transient,
344 }
345 }
346
347 pub fn combined(&self) -> Complex {
349 self.direct.add(&self.ambience)
350 }
351
352 pub fn direct_ratio(&self) -> f32 {
354 let total = self.direct.magnitude() + self.ambience.magnitude();
355 if total > 1e-10 {
356 self.direct.magnitude() / total
357 } else {
358 0.5
359 }
360 }
361}
362
363impl RingMessage for SeparatedBin {
364 fn message_type() -> u64 {
365 message_types::SEPARATED_BIN
366 }
367
368 fn message_id(&self) -> MessageId {
369 MessageId::new(self.frame_id * 10000 + self.bin_index as u64)
370 }
371
372 fn serialize(&self) -> Vec<u8> {
373 rkyv::to_bytes::<_, 128>(self)
374 .map(|v| v.to_vec())
375 .unwrap_or_default()
376 }
377
378 fn deserialize(bytes: &[u8]) -> ringkernel_core::error::Result<Self> {
379 let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
381 Ok(archived
382 .deserialize(&mut rkyv::Infallible)
383 .expect("rkyv::Infallible deserialization cannot fail"))
384 }
385}
386
387#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
389pub enum BinControl {
390 Reset,
392 UpdateParams {
394 coherence_threshold: f32,
396 transient_sensitivity: f32,
398 temporal_smoothing: f32,
400 },
401 GetState,
403 Shutdown,
405}
406
407impl RingMessage for BinControl {
408 fn message_type() -> u64 {
409 message_types::BIN_CONTROL
410 }
411
412 fn message_id(&self) -> MessageId {
413 MessageId::generate()
414 }
415
416 fn serialize(&self) -> Vec<u8> {
417 rkyv::to_bytes::<_, 64>(self)
418 .map(|v| v.to_vec())
419 .unwrap_or_default()
420 }
421
422 fn deserialize(bytes: &[u8]) -> ringkernel_core::error::Result<Self> {
423 let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
425 Ok(archived
426 .deserialize(&mut rkyv::Infallible)
427 .expect("rkyv::Infallible deserialization cannot fail"))
428 }
429}
430
431#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
433pub struct FrameComplete {
434 pub frame_id: u64,
436 pub processing_time_us: u64,
438 pub bins_processed: u32,
440}
441
442impl RingMessage for FrameComplete {
443 fn message_type() -> u64 {
444 message_types::FRAME_COMPLETE
445 }
446
447 fn message_id(&self) -> MessageId {
448 MessageId::new(self.frame_id)
449 }
450
451 fn serialize(&self) -> Vec<u8> {
452 rkyv::to_bytes::<_, 32>(self)
453 .map(|v| v.to_vec())
454 .unwrap_or_default()
455 }
456
457 fn deserialize(bytes: &[u8]) -> ringkernel_core::error::Result<Self> {
458 let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
460 Ok(archived
461 .deserialize(&mut rkyv::Infallible)
462 .expect("rkyv::Infallible deserialization cannot fail"))
463 }
464}
465
466#[cfg(test)]
467mod tests {
468 use super::*;
469
470 #[test]
471 fn test_complex_operations() {
472 let c1 = Complex::new(3.0, 4.0);
473 assert!((c1.magnitude() - 5.0).abs() < 1e-6);
474
475 let c2 = Complex::from_polar(5.0, 0.927295); assert!((c2.re - 3.0).abs() < 0.01);
477 assert!((c2.im - 4.0).abs() < 0.01);
478 }
479
480 #[test]
481 fn test_audio_frame_serialization() {
482 use ringkernel_core::RingMessage;
483 let frame = AudioFrame::new(1, 44100, 2, vec![0.0, 0.1, 0.2, 0.3], 0);
484 let bytes = RingMessage::serialize(&frame);
485 let restored = <AudioFrame as RingMessage>::deserialize(&bytes).unwrap();
486 assert_eq!(restored.frame_id, 1);
487 assert_eq!(restored.sample_rate, 44100);
488 assert_eq!(restored.samples.len(), 4);
489 }
490
491 #[test]
492 fn test_frequency_bin_db() {
493 let bin = FrequencyBin::new(0, 10, 1024, Complex::new(1.0, 0.0), 440.0);
494 assert!((bin.magnitude_db() - 0.0).abs() < 0.1); let quiet_bin = FrequencyBin::new(0, 10, 1024, Complex::new(0.1, 0.0), 440.0);
497 assert!((quiet_bin.magnitude_db() - (-20.0)).abs() < 0.1); }
499}