1use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Default, Serialize, Deserialize)]
10pub struct BeatGrid {
11 pub bpm: f64,
12 pub offset_samples: i64,
13 pub sample_rate: u32,
14 pub beat_interval: f64,
15}
16
17impl BeatGrid {
18 pub fn from_bpm(bpm: f64, offset: i64, sr: u32, _len: u32) -> Self {
19 Self {
20 bpm,
21 offset_samples: offset,
22 sample_rate: sr,
23 beat_interval: 60.0 / bpm * sr as f64,
24 }
25 }
26 pub fn beat_at_sample(&self, sample: i64) -> f64 {
27 let secs = (sample - self.offset_samples) as f64 / self.sample_rate as f64;
28 secs * self.bpm / 60.0
29 }
30 pub fn sample_at_beat(&self, beat: f64) -> i64 {
31 let secs = beat * 60.0 / self.bpm;
32 self.offset_samples + (secs * self.sample_rate as f64) as i64
33 }
34 pub fn snap_to_beat(&self, sample: i64) -> i64 {
35 let beat = self.beat_at_sample(sample).round();
36 self.sample_at_beat(beat)
37 }
38 pub fn phase_at(&self, sample: i64) -> f64 {
39 let beat = self.beat_at_sample(sample);
40 beat - beat.floor()
41 }
42}
43
44#[derive(Clone, Debug, Default)]
47pub struct EffectsPipeline;
48impl EffectsPipeline {
49 pub fn apply(&self, _buf: &mut [f32]) {}
50}
51
52pub trait FxProcessor: Send {
54 fn process(&mut self, buf: &mut [f32]);
55 fn name(&self) -> &str;
56 fn set_intensity(&mut self, _intensity: f32) {}
57 fn init(&mut self, _sample_rate: u32) {}
58}
59
60#[derive(Clone, Debug, Default)]
62pub struct MixBus {
63 pub deck_keys: [Option<u8>; 4],
64 pub deck_bpm: [f64; 4],
65 pub vocal_collision: bool,
66 pub vocal_energy: f32,
67}
68impl MixBus {
69 pub fn new() -> Self { Self::default() }
70 pub fn detect_vocal(&self, _buf: &[f32]) -> f32 { 0.0 }
71 pub fn update_derived(&mut self) {}
72}
73
74pub trait NetworkPresenceHook: Send {
76 fn on_message(&mut self, data: &[u8]);
77}
78
79pub fn is_dsp_module(_name: &str) -> bool { false }
81
82pub fn create_dsp_processor(_name: &str) -> Result<Box<dyn FxProcessor>, String> {
84 Err("Advanced procedural DSP modules require the Commercial B2B License — contact dev@deveraux.dev".into())
85}
86
87pub fn load_preset(_name: &str, _intensity: f32) -> Result<EffectsPipeline, String> {
89 Err("Presets require the Commercial B2B License — contact dev@deveraux.dev".into())
90}
91
92#[derive(Clone, Debug)]
94pub struct AudioCommandTx;
95
96#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
98pub struct DeckId(pub u8);
99impl DeckId {
100 pub const A: Self = Self(0);
101 pub const B: Self = Self(1);
102 pub const C: Self = Self(2);
103 pub const D: Self = Self(3);
104 pub fn as_usize(self) -> usize { self.0 as usize }
105}
106impl From<DeckId> for usize {
107 fn from(d: DeckId) -> usize { d.0 as usize }
108
109}
110
111#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
113pub enum SyncMode {
114 #[default]
115 Free,
116 Leader,
117 Follower,
118 Off,
119 BeatSync,
120 BarSync,
121 PhaseSync,
122}
123
124#[derive(Clone, Debug, Default)]
126pub struct Deck {
127 pub id: DeckId,
128 pub bpm: f64,
129 pub playing: bool,
130 pub position_samples: i64,
131 pub beatgrid: Option<BeatGrid>,
132 pub sync_mode: SyncMode,
133}