1use super::engine::EngineHandle;
6use super::preset::PresetKind;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum VibeKind {
10 Default,
11 BladeRunner,
12 Cathedral,
13 DanceFloor,
14}
15
16impl VibeKind {
17 pub fn label(self) -> &'static str {
18 match self {
19 VibeKind::Default => "Default",
20 VibeKind::BladeRunner => "Blade Runner",
21 VibeKind::Cathedral => "Cathedral",
22 VibeKind::DanceFloor => "DanceFloor",
23 }
24 }
25
26 pub fn next(self) -> Self {
27 match self {
28 VibeKind::Default => VibeKind::BladeRunner,
29 VibeKind::BladeRunner => VibeKind::Cathedral,
30 VibeKind::Cathedral => VibeKind::DanceFloor,
31 VibeKind::DanceFloor => VibeKind::Default,
32 }
33 }
34}
35
36pub fn apply(engine: &EngineHandle, vibe: VibeKind) {
40 match vibe {
41 VibeKind::Default => apply_default(engine),
42 VibeKind::BladeRunner => apply_blade_runner(engine),
43 VibeKind::Cathedral => apply_cathedral(engine),
44 VibeKind::DanceFloor => apply_dance_floor(engine),
45 }
46 engine.rebuild_graph();
47}
48
49fn apply_blade_runner(engine: &EngineHandle) {
54 engine.global.bpm.set_value(66.0);
55 engine.global.brightness.set_value(0.45);
56 engine.global.master_gain.set_value(0.65);
57 engine.global.scale_mode.set_value(1.0); let tracks = engine.tracks.lock();
60 let root = 55.0_f32; set_track(&tracks, 0, PresetKind::PadZimmer, root, |p| {
63 p.gain.set_value(0.48);
64 p.cutoff.set_value(2400.0);
65 p.resonance.set_value(0.30);
66 p.detune.set_value(22.0);
67 p.character.set_value(0.70); p.reverb_mix.set_value(0.80);
69 p.supermass.set_value(0.70);
70 p.arp.set_value(0.18);
71 p.lfo_rate.set_value(0.12);
72 p.lfo_depth.set_value(0.45);
73 p.lfo_target.set_value(1.0); });
75 set_track(&tracks, 1, PresetKind::BassPulse, root, |p| {
76 p.gain.set_value(0.55);
77 p.cutoff.set_value(380.0);
78 p.resonance.set_value(0.45);
79 p.character.set_value(0.40);
80 p.reverb_mix.set_value(0.55);
81 p.supermass.set_value(0.30);
82 p.arp.set_value(0.25);
83 });
84 set_track(&tracks, 2, PresetKind::Heartbeat, root, |p| {
85 p.gain.set_value(0.65);
86 p.character.set_value(0.18);
89 p.pattern_hits.set_value(3.0); p.pattern_rotation.set_value(0.0);
91 p.reverb_mix.set_value(0.45); p.supermass.set_value(0.15);
93 });
94 set_track(&tracks, 3, PresetKind::DroneSub, root * 0.5, |p| {
95 p.gain.set_value(0.32);
96 p.cutoff.set_value(180.0);
97 p.reverb_mix.set_value(0.85);
98 p.supermass.set_value(0.60);
99 });
100 set_track(&tracks, 4, PresetKind::Shimmer, root * 2.0, |p| {
101 p.gain.set_value(0.28);
102 p.character.set_value(0.70);
103 p.reverb_mix.set_value(0.90);
104 p.supermass.set_value(0.80);
105 p.arp.set_value(0.22);
106 });
107 set_track(&tracks, 5, PresetKind::Bell, root * 1.5, |p| {
108 p.gain.set_value(0.30);
109 p.resonance.set_value(0.50); p.character.set_value(0.65); p.reverb_mix.set_value(0.85);
112 p.supermass.set_value(0.70);
113 p.arp.set_value(0.30);
114 });
115 set_track(&tracks, 6, PresetKind::SuperSaw, root, |p| {
116 p.gain.set_value(0.32);
117 p.cutoff.set_value(1800.0);
118 p.resonance.set_value(0.35);
119 p.detune.set_value(18.0); p.reverb_mix.set_value(0.70);
121 p.supermass.set_value(0.50);
122 p.arp.set_value(0.20);
123 p.lfo_rate.set_value(0.08);
124 p.lfo_depth.set_value(0.30);
125 p.lfo_target.set_value(1.0); });
127 mute_slot(&tracks, 7); }
129
130fn apply_cathedral(engine: &EngineHandle) {
132 engine.global.bpm.set_value(54.0);
133 engine.global.brightness.set_value(0.55);
134 engine.global.master_gain.set_value(0.60);
135 engine.global.scale_mode.set_value(0.0);
136
137 let tracks = engine.tracks.lock();
138 let root = 55.0_f32;
139
140 set_track(&tracks, 0, PresetKind::PadZimmer, root, |p| {
141 p.gain.set_value(0.45);
142 p.cutoff.set_value(2000.0);
143 p.character.set_value(0.80);
144 p.reverb_mix.set_value(0.95);
145 p.supermass.set_value(1.00);
146 p.arp.set_value(0.10);
147 });
148 set_track(&tracks, 1, PresetKind::Shimmer, root * 2.0, |p| {
149 p.gain.set_value(0.30);
150 p.reverb_mix.set_value(0.95);
151 p.supermass.set_value(1.00);
152 p.arp.set_value(0.15);
153 });
154 set_track(&tracks, 2, PresetKind::Bell, root, |p| {
155 p.gain.set_value(0.28);
156 p.resonance.set_value(0.40);
157 p.character.set_value(0.50);
158 p.reverb_mix.set_value(0.95);
159 p.supermass.set_value(1.00);
160 p.arp.set_value(0.25);
161 });
162 set_track(&tracks, 3, PresetKind::DroneSub, root * 0.5, |p| {
163 p.gain.set_value(0.30);
164 p.cutoff.set_value(160.0);
165 p.reverb_mix.set_value(0.95);
166 p.supermass.set_value(0.90);
167 });
168 mute_slot(&tracks, 4);
169 mute_slot(&tracks, 5);
170 mute_slot(&tracks, 6);
171 mute_slot(&tracks, 7);
172}
173
174fn apply_dance_floor(engine: &EngineHandle) {
176 engine.global.bpm.set_value(128.0);
177 engine.global.brightness.set_value(0.75);
178 engine.global.master_gain.set_value(0.70);
179 engine.global.scale_mode.set_value(0.0);
180
181 let tracks = engine.tracks.lock();
182 let root = 55.0_f32;
183
184 set_track(&tracks, 0, PresetKind::BassPulse, root, |p| {
185 p.gain.set_value(0.62);
186 p.cutoff.set_value(500.0);
187 p.resonance.set_value(0.55);
188 p.reverb_mix.set_value(0.25);
189 p.supermass.set_value(0.0);
190 p.arp.set_value(0.30);
191 });
192 set_track(&tracks, 1, PresetKind::Heartbeat, root, |p| {
193 p.gain.set_value(0.75);
194 p.character.set_value(0.75); p.pattern_hits.set_value(4.0);
196 p.pattern_rotation.set_value(0.0);
197 p.reverb_mix.set_value(0.40);
198 p.supermass.set_value(0.0);
199 });
200 set_track(&tracks, 2, PresetKind::PluckSaw, root * 2.0, |p| {
201 p.gain.set_value(0.45);
202 p.cutoff.set_value(3000.0);
203 p.resonance.set_value(0.45);
204 p.pattern_hits.set_value(11.0);
205 p.reverb_mix.set_value(0.35);
206 p.arp.set_value(0.40);
207 });
208 set_track(&tracks, 3, PresetKind::SuperSaw, root * 1.5, |p| {
209 p.gain.set_value(0.38);
210 p.cutoff.set_value(2400.0);
211 p.detune.set_value(30.0);
212 p.reverb_mix.set_value(0.50);
213 p.supermass.set_value(0.25);
214 p.arp.set_value(0.20);
215 p.lfo_rate.set_value(0.25);
216 p.lfo_depth.set_value(0.35);
217 p.lfo_target.set_value(1.0);
218 });
219 mute_slot(&tracks, 4);
220 mute_slot(&tracks, 5);
221 mute_slot(&tracks, 6);
222 mute_slot(&tracks, 7);
223}
224
225fn apply_default(engine: &EngineHandle) {
227 engine.global.bpm.set_value(72.0);
228 engine.global.brightness.set_value(0.6);
229 engine.global.master_gain.set_value(0.7);
230 engine.global.scale_mode.set_value(0.0);
231
232 let tracks = engine.tracks.lock();
233 let root = 55.0_f32;
234
235 set_track(&tracks, 0, PresetKind::PadZimmer, root, |p| {
236 reset_neutral(p);
237 });
238 set_track(&tracks, 1, PresetKind::BassPulse, root, |p| {
239 reset_neutral(p);
240 });
241 set_track(&tracks, 2, PresetKind::Heartbeat, root, |p| {
242 reset_neutral(p);
243 p.pulse_depth.set_value(0.0);
244 });
245 set_track(&tracks, 3, PresetKind::DroneSub, root * 0.5, |p| {
246 reset_neutral(p);
247 p.gain.set_value(0.32);
248 p.reverb_mix.set_value(0.7);
249 });
250 mute_slot(&tracks, 4);
251 mute_slot(&tracks, 5);
252 mute_slot(&tracks, 6);
253 mute_slot(&tracks, 7);
254}
255
256fn set_track<F>(
259 tracks: &parking_lot::MutexGuard<'_, Vec<super::track::Track>>,
260 idx: usize,
261 kind: PresetKind,
262 freq: f32,
263 config: F,
264) where
265 F: FnOnce(&super::track::TrackParams),
266{
267 let track = &tracks[idx];
272 let track_ptr = track as *const super::track::Track as *mut super::track::Track;
273 unsafe {
274 (*track_ptr).kind = kind;
275 }
276 track.params.freq.set_value(freq);
277 track.params.mute.set_value(0.0);
278 config(&track.params);
279}
280
281fn mute_slot(
282 tracks: &parking_lot::MutexGuard<'_, Vec<super::track::Track>>,
283 idx: usize,
284) {
285 if let Some(t) = tracks.get(idx) {
286 t.params.mute.set_value(1.0);
287 }
288}
289
290fn reset_neutral(p: &super::track::TrackParams) {
292 p.gain.set_value(0.45);
293 p.cutoff.set_value(1600.0);
294 p.resonance.set_value(0.30);
295 p.detune.set_value(7.0);
296 p.sweep_k.set_value(1.2);
297 p.sweep_center.set_value(1.5);
298 p.reverb_mix.set_value(0.6);
299 p.supermass.set_value(0.0);
300 p.pulse_depth.set_value(0.0);
301 p.character.set_value(0.5);
302 p.arp.set_value(0.0);
303 p.lfo_rate.set_value(0.5);
304 p.lfo_depth.set_value(0.0);
305 p.lfo_target.set_value(1.0);
306 p.pattern_hits.set_value(4.0);
307 p.pattern_rotation.set_value(0.0);
308}