1use crate::sample;
2use crate::sample::{Sample, XfadeDirection};
3use crossbeam_channel::{bounded, Receiver, Sender, TrySendError};
4use crossbeam_queue::ArrayQueue;
5use std::path::{Path, PathBuf};
6use std::sync::Arc;
7use std::thread;
8
9use crate::error::SaveLoadError;
10use loopers_common::api::{
11 FrameTime, LooperCommand, LooperMode, LooperSpeed, Part, PartSet, SavedLooper,
12};
13use loopers_common::gui_channel::GuiCommand::{AddNewSample, AddOverdubSample};
14use loopers_common::gui_channel::{
15 GuiCommand, GuiSender, LooperState, Waveform, WAVEFORM_DOWNSAMPLE,
16};
17use loopers_common::music::PanLaw;
18use std::collections::VecDeque;
19use std::fmt::{Debug, Formatter};
20use std::mem::swap;
21
22use atomic::Atomic;
23use std::sync::atomic::Ordering;
24
25
26#[cfg(test)]
27mod tests {
28 use super::*;
29 use std::f32::consts::PI;
30 use tempfile::tempdir;
31
32 fn install_test_logger() {
33 let _ = fern::Dispatch::new()
34 .level(log::LevelFilter::Debug)
35 .chain(fern::Output::call(|record| println!("{}", record.args())))
36 .apply();
37 }
38
39 fn process_until_done(looper: &mut Looper) {
40 loop {
41 let msg = looper.backend.as_mut().unwrap().channel.try_recv();
42 match msg {
43 Ok(msg) => looper.backend.as_mut().unwrap().handle_msg(msg),
44 Err(_) => break,
45 };
46 }
47 }
48
49 fn verify_mode(looper: &Looper, expected: LooperMode) {
50 assert_eq!(
51 looper.backend.as_ref().unwrap().mode(),
52 expected,
53 "backend in unexpected state"
54 );
55 assert_eq!(looper.mode(), expected, "looper in unexpected state");
56 }
57
58 fn verify_length(looper: &Looper, expected: u64) {
59 assert_eq!(
60 looper.backend.as_ref().unwrap().length_in_samples(false),
61 expected,
62 "backend has unexpected length"
63 );
64 assert_eq!(
65 looper.length(), expected,
66 "looper has unexpected length"
67 );
68 }
69
70 fn looper_for_test() -> Looper {
71 let mut l = Looper::new(1, PartSet::new(), GuiSender::disconnected());
72 l.pan_law = PanLaw::Transparent;
73 l.backend.as_mut().unwrap().enable_crossfading = false;
74 l
75 }
76
77 #[test]
78 fn test_transfer_buf() {
79 let mut t = TransferBuf {
80 id: 0,
81 time: FrameTime(12),
82 size: 6,
83 data: [[0i32; TRANSFER_BUF_SIZE]; 2],
84 };
85
86 for i in 0usize..6 {
87 t.data[0][i] = i as i32 + 1;
88 t.data[1][i] = -(i as i32 + 1);
89 }
90
91 assert!(!t.contains_t(FrameTime(0)));
92 assert!(!t.contains_t(FrameTime(11)));
93
94 assert!(t.contains_t(FrameTime(12)));
95 assert!(t.contains_t(FrameTime(17)));
96
97 assert!(!t.contains_t(FrameTime(18)));
98
99 assert_eq!(Some((1, -1)), t.get_t(FrameTime(12)));
100 assert_eq!(Some((6, -6)), t.get_t(FrameTime(17)));
101 }
102
103 #[test]
104 fn test_new() {
105 install_test_logger();
106
107 let looper = looper_for_test();
108 verify_mode(&looper, LooperMode::Playing);
109 assert_eq!(1, looper.id);
110 assert_eq!(0, looper.length());
111 }
112
113 #[test]
114 fn test_transitions() {
115 install_test_logger();
116
117 let mut looper = looper_for_test();
118
119 verify_mode(&looper, LooperMode::Playing);
120
121 looper.transition_to(LooperMode::Recording);
122 process_until_done(&mut looper);
123 verify_mode(&looper, LooperMode::Recording);
124 assert_eq!(1, looper.backend.as_ref().unwrap().samples.len());
125
126 let data = [vec![1.0f32, 1.0], vec![-1.0, -1.0]];
127 looper.process_input(0, &[&data[0], &data[1]], Part::A);
128 process_until_done(&mut looper);
129 looper.transition_to(LooperMode::Overdubbing);
130 process_until_done(&mut looper);
131
132 assert_eq!(2, looper.backend.as_ref().unwrap().samples.len());
133 for s in &looper.backend.as_ref().unwrap().samples {
134 assert_eq!(2, s.length());
135 }
136
137 looper.transition_to(LooperMode::Playing);
138 process_until_done(&mut looper);
139 verify_mode(&looper, LooperMode::Playing);
140
141 looper.transition_to(LooperMode::Recording);
142 process_until_done(&mut looper);
143 assert_eq!(1, looper.backend.as_ref().unwrap().samples.len());
144 verify_length(&looper, 0);
145 }
146
147 #[test]
148 fn test_io() {
149 install_test_logger();
150
151 let mut l = looper_for_test();
152 l.backend.as_mut().unwrap().enable_crossfading = false;
153
154 l.transition_to(LooperMode::Recording);
155 process_until_done(&mut l);
156
157 let mut input_left = vec![0f32; TRANSFER_BUF_SIZE];
158 let mut input_right = vec![0f32; TRANSFER_BUF_SIZE];
159 for i in 0..TRANSFER_BUF_SIZE {
160 input_left[i] = i as f32;
161 input_right[i] = -(i as f32);
162 }
163
164 l.process_input(0, &[&input_left, &input_right], Part::A);
165 process_until_done(&mut l);
166
167 let mut o_l = vec![1f64; TRANSFER_BUF_SIZE];
168 let mut o_r = vec![-1f64; TRANSFER_BUF_SIZE];
169
170 l.transition_to(LooperMode::Playing);
171 process_until_done(&mut l);
172 l.process_input(
173 input_left.len() as u64,
174 &[&input_left, &input_right],
175 Part::A,
176 );
177 process_until_done(&mut l);
178
179 l.process_output(
180 FrameTime(input_left.len() as i64),
181 &mut [&mut o_l, &mut o_r],
182 Part::A,
183 false,
184 );
185 process_until_done(&mut l);
186
187 for i in 0..TRANSFER_BUF_SIZE {
188 assert_eq!(o_l[i], (i + 1) as f64);
189 assert_eq!(o_r[i], -((i + 1) as f64));
190 }
191 }
192
193 #[test]
194 fn test_overdub() {
195 install_test_logger();
196
197 let mut l = looper_for_test();
198 l.backend.as_mut().unwrap().enable_crossfading = false;
199
200 l.transition_to(LooperMode::Recording);
201 process_until_done(&mut l);
202
203 let mut input_left = vec![0f32; TRANSFER_BUF_SIZE];
204 let mut input_right = vec![0f32; TRANSFER_BUF_SIZE];
205 for i in 0..TRANSFER_BUF_SIZE {
206 input_left[i] = i as f32 + 1.0;
207 input_right[i] = -(i as f32 + 1.0);
208 }
209
210 let mut t = 0 as i64;
211
212 l.process_input(t as u64, &[&input_left, &input_right], Part::A);
213 process_until_done(&mut l);
214
215 let mut o_l = vec![0f64; TRANSFER_BUF_SIZE];
216 let mut o_r = vec![0f64; TRANSFER_BUF_SIZE];
217 l.process_output(FrameTime(t), &mut [&mut o_l, &mut o_r], Part::A, false);
218 process_until_done(&mut l);
219
220 t += TRANSFER_BUF_SIZE as i64;
221
222 for (l, r) in o_l.iter().zip(&o_r) {
223 assert_eq!(*l, 0.0);
224 assert_eq!(*r, 0.0);
225 }
226
227 l.transition_to(LooperMode::Overdubbing);
228 process_until_done(&mut l);
229
230 let mut o_l = vec![0f64; TRANSFER_BUF_SIZE];
232 let mut o_r = vec![0f64; TRANSFER_BUF_SIZE];
233 l.process_output(FrameTime(t), &mut [&mut o_l, &mut o_r], Part::A, false);
234 process_until_done(&mut l);
235
236 l.process_input(t as u64, &[&input_left, &input_right], Part::A);
237 process_until_done(&mut l);
238
239 t += TRANSFER_BUF_SIZE as i64;
240
241 for (i, (l, r)) in o_l.iter().zip(&o_r).enumerate() {
242 assert_eq!(*l, (i + 1) as f64);
243 assert_eq!(*r, -((i + 1) as f64));
244 }
245
246 let mut o_l = vec![0f64; TRANSFER_BUF_SIZE];
248 let mut o_r = vec![0f64; TRANSFER_BUF_SIZE];
249 l.process_output(FrameTime(t), &mut [&mut o_l, &mut o_r], Part::A, false);
250 process_until_done(&mut l);
251
252 l.process_input(t as u64, &[&input_left, &input_right], Part::A);
253 process_until_done(&mut l);
254
255 for (i, (l, r)) in o_l.iter().zip(&o_r).enumerate() {
256 let v = ((i + 1) * 2) as f64;
257 assert_eq!(*l, v);
258 assert_eq!(*r, -v);
259 }
260 }
261
262 #[test]
263 fn test_solo() {
264 install_test_logger();
265
266 let mut l = looper_for_test();
267 l.transition_to(LooperMode::Recording);
268
269 let input_left = vec![1f32; 128];
270 let input_right = vec![-1f32; 128];
271
272 l.process_input(0, &[&input_left, &input_right], Part::A);
273 process_until_done(&mut l);
274
275 let mut o_l = vec![0f64; 128];
276 let mut o_r = vec![0f64; 128];
277
278 l.set_time(FrameTime(0));
280 l.transition_to(LooperMode::Playing);
281 process_until_done(&mut l);
282
283 l.process_output(
284 FrameTime(0),
285 &mut [&mut o_l, &mut o_r],
286 Part::A,
287 true,
288 );
289
290 for i in 0..128 {
291 assert_eq!(0.0, o_l[i]);
292 assert_eq!(0.0, o_r[i]);
293 }
294
295 l.set_time(FrameTime(0));
297 l.transition_to(LooperMode::Soloed);
298 process_until_done(&mut l);
299
300 l.process_output(
301 FrameTime(0),
302 &mut [&mut o_l, &mut o_r],
303 Part::A,
304 true,
305 );
306
307 for i in 0..128 {
308 assert_eq!(1.0, o_l[i]);
309 assert_eq!(-1.0, o_r[i]);
310 }
311
312 o_l = vec![0f64; 128];
314 o_r = vec![0f64; 128];
315
316 l.set_time(FrameTime(0));
317 process_until_done(&mut l);
318
319 l.process_output(
320 FrameTime(0),
321 &mut [&mut o_l, &mut o_r],
322 Part::B,
323 true,
324 );
325
326 for i in 0..128 {
327 assert_eq!(0.0, o_l[i]);
328 assert_eq!(0.0, o_r[i]);
329 }
330 }
331
332 #[test]
333 fn test_non_harmonious_lengths() {
334 install_test_logger();
335
336 let buf_size = 128;
340
341 let mut l = looper_for_test();
342 l.transition_to(LooperMode::Recording);
343
344 let mut input_left = vec![1f32; buf_size];
345 let mut input_right = vec![-1f32; buf_size];
346
347 let mut time = 0i64;
348
349 let mut o_l = vec![0f64; buf_size];
350 let mut o_r = vec![0f64; buf_size];
351 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
352 process_until_done(&mut l);
353
354 l.process_input(0, &[&input_left, &input_right], Part::A);
355 process_until_done(&mut l);
356
357 time += buf_size as i64;
358
359 l.process_output(
361 FrameTime(time),
362 &mut [&mut o_l[0..100], &mut o_r[0..100]],
363 Part::A,
364 false,
365 );
366 process_until_done(&mut l);
367
368 input_left = vec![2f32; buf_size];
369 input_right = vec![-2f32; buf_size];
370 l.process_input(
371 time as u64,
372 &[&input_left[0..100], &input_right[0..100]],
373 Part::A,
374 );
375 process_until_done(&mut l);
376
377 time += 100;
378
379 l.transition_to(LooperMode::Overdubbing);
381 process_until_done(&mut l);
382
383 let len = buf_size + 100;
384 verify_length(&l, len as u64);
385
386 l.process_output(
387 FrameTime(time),
388 &mut [&mut o_l[100..buf_size], &mut o_r[100..buf_size]],
389 Part::A,
390 false,
391 );
392 process_until_done(&mut l);
393
394 l.process_input(
395 time as u64,
396 &[&input_left[100..buf_size], &input_right[100..buf_size]],
397 Part::A,
398 );
399 process_until_done(&mut l);
400
401 time += buf_size as i64 - 100;
402
403 for i in 0..buf_size {
404 if i < 100 {
405 assert_eq!(o_l[i], 0f64);
406 assert_eq!(o_r[i], 0f64);
407 } else {
408 assert_eq!(o_l[i], 1f64);
409 assert_eq!(o_r[i], -1f64);
410 }
411 }
412
413 o_l = vec![0f64; buf_size];
414 o_r = vec![0f64; buf_size];
415 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
416 process_until_done(&mut l);
417
418 for i in 0..buf_size {
419 let t = time as usize + i;
420 if t % len < buf_size {
421 assert_eq!(o_l[i], 1f64);
422 assert_eq!(o_r[i], -1f64);
423 } else {
424 assert_eq!(o_l[i], 2f64);
425 assert_eq!(o_r[i], -2f64);
426 }
427 }
428
429 l.set_time(FrameTime(0));
431 process_until_done(&mut l);
432 l.transition_to(LooperMode::Playing);
433 process_until_done(&mut l);
434
435 o_l = vec![0f64; buf_size];
436 o_r = vec![0f64; buf_size];
437 l.process_output(FrameTime(0), &mut [&mut o_l, &mut o_r], Part::A, false);
438 process_until_done(&mut l);
439
440 for i in 0..buf_size {
441 if i < buf_size - 100 {
442 assert_eq!(o_l[i], 3f64);
443 assert_eq!(o_r[i], -3f64);
444 } else {
445 assert_eq!(o_l[i], 1.0f64);
446 assert_eq!(o_r[i], -1.0f64);
447 }
448 }
449 }
450
451 #[test]
452 fn test_offset() {
453 install_test_logger();
454
455 let offset = 4u64;
456
457 let mut l = looper_for_test();
458 l.backend.as_mut().unwrap().enable_crossfading = false;
459
460 l.set_time(FrameTime(offset as i64));
461
462 l.transition_to(LooperMode::Recording);
463 process_until_done(&mut l);
464
465 let mut input_left = vec![0f32; TRANSFER_BUF_SIZE];
466 let mut input_right = vec![0f32; TRANSFER_BUF_SIZE];
467 for i in 0..TRANSFER_BUF_SIZE {
468 input_left[i] = i as f32;
469 input_right[i] = -(i as f32);
470 }
471
472 l.process_input(offset, &[&input_left, &input_right], Part::A);
473 process_until_done(&mut l);
474
475 let mut o_l = vec![1f64; TRANSFER_BUF_SIZE];
476 let mut o_r = vec![-1f64; TRANSFER_BUF_SIZE];
477
478 l.transition_to(LooperMode::Playing);
479 process_until_done(&mut l);
480 l.process_input(
481 offset + input_left.len() as u64,
482 &[&input_left, &input_right],
483 Part::A,
484 );
485 process_until_done(&mut l);
486
487 l.process_output(
488 FrameTime(offset as i64 + input_left.len() as i64),
489 &mut [&mut o_l, &mut o_r],
490 Part::A,
491 false,
492 );
493 process_until_done(&mut l);
494
495 for i in 0..TRANSFER_BUF_SIZE {
496 assert_eq!(o_l[i], (i + 1) as f64);
497 assert_eq!(o_r[i], -((i + 1) as f64));
498 }
499 }
500
501 #[test]
502 fn test_post_xfade() {
503 install_test_logger();
504
505 let mut l = looper_for_test();
506 l.backend.as_mut().unwrap().enable_crossfading = true;
507 l.transition_to(LooperMode::Recording);
508 process_until_done(&mut l);
509
510 let mut time = 0i64;
511
512 let mut input_left = vec![1f32; CROSS_FADE_SAMPLES * 2];
513 let mut input_right = vec![-1f32; CROSS_FADE_SAMPLES * 2];
514 let mut o_l = vec![0f64; CROSS_FADE_SAMPLES * 2];
515 let mut o_r = vec![0f64; CROSS_FADE_SAMPLES * 2];
516
517 l.process_input(time as u64, &[&input_left, &input_right], Part::A);
518 process_until_done(&mut l);
519 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
520 process_until_done(&mut l);
521 time += input_left.len() as i64;
522
523 for i in 0..CROSS_FADE_SAMPLES {
524 let q = i as f32 / CROSS_FADE_SAMPLES as f32;
525 input_left[i] = -q / (1f32 - q);
526 input_right[i] = q / (1f32 - q);
527 }
528
529 l.transition_to(LooperMode::Playing);
530 process_until_done(&mut l);
531
532 for i in (0..CROSS_FADE_SAMPLES * 2).step_by(32) {
533 l.process_input(
534 time as u64,
535 &[&input_left[i..i + 32], &input_right[i..i + 32]],
536 Part::A,
537 );
538 process_until_done(&mut l);
539
540 let mut o_l = vec![0f64; 32];
541 let mut o_r = vec![0f64; 32];
542 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
543 process_until_done(&mut l);
544
545 time += 32;
546 }
547
548 let mut o_l = vec![0f64; CROSS_FADE_SAMPLES * 2];
549 let mut o_r = vec![0f64; CROSS_FADE_SAMPLES * 2];
550
551 l.process_input(time as u64, &[&input_left, &input_right], Part::A);
552 process_until_done(&mut l);
553
554 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
555
556 verify_length(&l, CROSS_FADE_SAMPLES as u64 * 2);
557
558 for i in 0..o_l.len() {
559 if i < CROSS_FADE_SAMPLES {
560 assert!(
561 (0f64 - o_l[i]).abs() < 0.000001,
562 "left is {} at idx {}, expected 0",
563 o_l[i],
564 time + i as i64
565 );
566 assert!(
567 (0f64 - o_r[i]).abs() < 0.000001,
568 "right is {} at idx {}, expected 0",
569 o_r[i],
570 time + i as i64
571 );
572 } else {
573 assert_eq!(1f64, o_l[i], "mismatch at {}", time + i as i64);
574 assert_eq!(-1f64, o_r[i], "mismatch at {}", time + i as i64);
575 }
576 }
577 }
578
579 #[test]
580 fn test_pre_xfade() {
581 install_test_logger();
582
583 let mut l = looper_for_test();
584
585 let mut input_left = vec![17f32; CROSS_FADE_SAMPLES];
586 let mut input_right = vec![-17f32; CROSS_FADE_SAMPLES];
587
588 let mut time = 0i64;
589 for i in (0..CROSS_FADE_SAMPLES).step_by(32) {
591 l.process_input(
592 time as u64,
593 &[&input_left[i..i + 32], &input_right[i..i + 32]],
594 Part::A,
595 );
596 process_until_done(&mut l);
597
598 let mut o_l = vec![0f64; 32];
599 let mut o_r = vec![0f64; 32];
600 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
601 process_until_done(&mut l);
602
603 time += 32;
604 }
605
606 for i in 0..CROSS_FADE_SAMPLES {
608 let q = 1.0 - i as f32 / CROSS_FADE_SAMPLES as f32;
614
615 if i != 0 {
616 input_left[i] = -q / (1f32 - q);
617 input_right[i] = q / (1f32 - q);
618 }
619 }
620
621 for i in (0..CROSS_FADE_SAMPLES).step_by(32) {
623 l.process_input(
624 time as u64,
625 &[&input_left[i..i + 32], &input_right[i..i + 32]],
626 Part::A,
627 );
628 process_until_done(&mut l);
629
630 let mut o_l = vec![0f64; 32];
631 let mut o_r = vec![0f64; 32];
632 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
633 process_until_done(&mut l);
634
635 time += 32;
636 }
637
638 l.transition_to(LooperMode::Recording);
639 process_until_done(&mut l);
640
641 input_left = vec![1f32; CROSS_FADE_SAMPLES * 2];
642 input_right = vec![-1f32; CROSS_FADE_SAMPLES * 2];
643
644 let mut o_l = vec![0f64; CROSS_FADE_SAMPLES * 2];
645 let mut o_r = vec![0f64; CROSS_FADE_SAMPLES * 2];
646
647 l.process_input(time as u64, &[&input_left, &input_right], Part::A);
648 process_until_done(&mut l);
649 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
650 process_until_done(&mut l);
651 time += input_left.len() as i64;
652
653 l.transition_to(LooperMode::Playing);
654 process_until_done(&mut l);
655
656 l.process_input(time as u64, &[&input_left, &input_right], Part::A);
658 process_until_done(&mut l);
659 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
660 process_until_done(&mut l);
661 time += input_left.len() as i64;
662
663 let mut o_l = vec![0f64; CROSS_FADE_SAMPLES * 2];
664 let mut o_r = vec![0f64; CROSS_FADE_SAMPLES * 2];
665 l.process_output(FrameTime(time), &mut [&mut o_l, &mut o_r], Part::A, false);
666 process_until_done(&mut l);
667
668 for i in 0..o_l.len() {
669 if i > CROSS_FADE_SAMPLES {
670 assert!(
671 (0f64 - o_l[i]).abs() < 0.000001,
672 "left is {} at idx {}, expected 0",
673 o_l[i],
674 i
675 );
676 assert!(
677 (0f64 - o_r[i]).abs() < 0.000001,
678 "right is {} at idx {}, expected 0",
679 o_r[i],
680 i
681 );
682 }
683 }
684 }
685
686 #[test]
687 fn test_serialization() {
688 install_test_logger();
689
690 let dir = tempdir().unwrap();
691 let mut input_left = vec![];
692 let mut input_right = vec![];
693
694 let mut input_left2 = vec![];
695 let mut input_right2 = vec![];
696
697 for t in (0..16).map(|x| x as f32 / 44100.0) {
698 let sample = (t * 440.0 * 2.0 * PI).sin();
699 input_left.push(sample / 2.0);
700 input_right.push(sample / 2.0);
701
702 let sample = (t * 540.0 * 2.0 * PI).sin();
703 input_left2.push(sample / 2.0);
704 input_right2.push(sample / 2.0);
705 }
706
707 let mut l = Looper::new(5, PartSet::new(), GuiSender::disconnected());
708
709 l.transition_to(LooperMode::Recording);
710 process_until_done(&mut l);
711 l.process_input(0, &[&input_left, &input_right], Part::A);
712 process_until_done(&mut l);
713
714 l.transition_to(LooperMode::Overdubbing);
715 process_until_done(&mut l);
716 l.process_input(0, &[&input_left2, &input_right2], Part::A);
717 process_until_done(&mut l);
718
719 let (tx, rx) = bounded(1);
720 l.channel()
721 .send(ControlMessage::Serialize(dir.path().to_path_buf(), tx))
722 .unwrap();
723 process_until_done(&mut l);
724
725 let state = rx.recv().unwrap().unwrap();
726
727 let deserialized =
728 Looper::from_serialized(&state, dir.path(), GuiSender::disconnected()).unwrap();
729
730 assert_eq!(l.id, deserialized.id);
731
732 let b1 = l.backend.as_ref().unwrap();
733 let b2 = deserialized.backend.as_ref().unwrap();
734
735 assert_eq!(2, b2.samples.len());
736
737 for i in 0..input_left.len() {
738 assert!((b1.samples[0].buffer[0][i] - b2.samples[0].buffer[0][i]).abs() < 0.00001);
739 assert!((b1.samples[0].buffer[1][i] - b2.samples[0].buffer[1][i]).abs() < 0.00001);
740
741 assert!((b1.samples[1].buffer[0][i] - b2.samples[1].buffer[0][i]).abs() < 0.00001);
742 assert!((b1.samples[1].buffer[0][i] - b2.samples[1].buffer[1][i]).abs() < 0.00001);
743 }
744 }
745}
746
747const CROSS_FADE_SAMPLES: usize = 8192;
748
749struct StateMachine {
750 transitions: Vec<(
751 Vec<LooperMode>,
752 Vec<LooperMode>,
753 for<'r> fn(&'r mut LooperBackend, LooperMode),
754 )>,
755}
756
757impl StateMachine {
758 fn new() -> StateMachine {
759 use LooperMode::*;
760 StateMachine {
761 transitions: vec![
762 (vec![Recording], vec![], LooperBackend::finish_recording),
763 (
764 vec![Recording, Overdubbing],
765 vec![],
766 LooperBackend::handle_crossfades,
767 ),
768 (
769 vec![],
770 vec![Overdubbing],
771 LooperBackend::prepare_for_overdubbing,
772 ),
773 (
774 vec![],
775 vec![Recording],
776 LooperBackend::prepare_for_recording,
777 ),
778 ],
780 }
781 }
782
783 fn handle_transition(&self, looper: &mut LooperBackend, next_state: LooperMode) {
784 let cur = looper.mode();
785 for transition in &self.transitions {
786 if (transition.0.is_empty() || transition.0.contains(&cur))
787 && (transition.1.is_empty() || transition.1.contains(&next_state))
788 {
789 transition.2(looper, next_state);
790 }
791 }
792 looper.mode.store(next_state, Ordering::Relaxed);
793 }
794}
795
796lazy_static! {
797 static ref STATE_MACHINE: StateMachine = StateMachine::new();
798}
799
800#[derive(Debug)]
801pub enum ControlMessage {
802 InputDataReady { id: u64, size: usize },
803 TransitionTo(LooperMode),
804 SetTime(FrameTime),
805 ReadOutput(FrameTime),
806 Shutdown,
807 Serialize(PathBuf, Sender<Result<SavedLooper, SaveLoadError>>),
808 Deleted,
809 Clear,
810 SetSpeed(LooperSpeed),
811 SetPan(f32),
812 SetLevel(f32),
813 SetParts(PartSet),
814 Undo,
815 Redo,
816 StopOutput,
817}
818
819const TRANSFER_BUF_SIZE: usize = 16;
820
821#[derive(Clone, Copy)]
822struct TransferBuf<DATA: Copy> {
823 id: u64,
824 time: FrameTime,
825 size: usize,
826 data: [[DATA; TRANSFER_BUF_SIZE]; 2],
827}
828
829impl<DATA: Copy> TransferBuf<DATA> {
830 pub fn contains_t(&self, time: FrameTime) -> bool {
831 return time.0 >= self.time.0 && time.0 < self.time.0 + self.size as i64;
832 }
833
834 pub fn get_t(&self, time: FrameTime) -> Option<(DATA, DATA)> {
835 if self.contains_t(time) {
836 let idx = (time.0 - self.time.0) as usize;
837 Some((self.data[0][idx], self.data[1][idx]))
838 } else {
839 None
840 }
841 }
842}
843
844fn compute_waveform(samples: &[Sample], downsample: usize) -> Waveform {
845 let len = samples[0].length() as usize;
846 let size = len / downsample + 1;
847 let mut out = [Vec::with_capacity(size), Vec::with_capacity(size)];
848
849 for c in 0..2 {
850 for t in (0..len).step_by(downsample) {
851 let mut p = 0f64;
852 let end = downsample.min(len - t);
853 for s in samples {
854 for j in 0..end {
855 let i = t as usize + j;
856 p += s.buffer[c][i].abs() as f64;
857 }
858 }
859
860 out[c].push((p as f64 / (samples.len() as f64 * end as f64)) as f32);
861 }
862 }
863
864 out
865}
866
867struct WaveformGenerator {
868 id: u32,
869 start_time: FrameTime,
870 acc: [f64; 2],
871 size: usize,
872}
873
874impl WaveformGenerator {
875 fn new(id: u32) -> Self {
876 WaveformGenerator {
877 id,
878 start_time: FrameTime(0),
879 acc: [0.0, 0.0],
880 size: 0,
881 }
882 }
883
884 fn add_buf(
885 &mut self,
886 mode: LooperMode,
887 time: FrameTime,
888 samples: &[&[f64]],
889 looper_length: u64,
890 sender: &mut GuiSender,
891 ) {
892 if !(self.start_time.0..self.start_time.0 + WAVEFORM_DOWNSAMPLE as i64).contains(&time.0) {
893 debug!(
896 "sending partial buffer to GUI because we got a newer one \
897 (cur time = {}, buf time = {})",
898 self.start_time.0, time.0
899 );
900 self.flush(mode, looper_length, sender);
901 self.start_time = time;
902 }
903
904 for i in 0..samples[0].len() {
905 if self.size < WAVEFORM_DOWNSAMPLE {
906 for c in 0..2 {
907 self.acc[c] += samples[c][i].abs();
908 }
909 self.size += 1;
910 } else {
911 self.flush(mode, looper_length, sender);
912 self.start_time = FrameTime(time.0 + i as i64);
913 }
914 }
915 }
916
917 fn flush(&mut self, mode: LooperMode, looper_length: u64, sender: &mut GuiSender) {
918 let s = [
919 (self.acc[0] / self.size as f64).min(1.0) as f32,
920 (self.acc[1] / self.size as f64).min(1.0) as f32,
921 ];
922 match mode {
923 LooperMode::Recording => {
924 sender.send_update(AddNewSample(self.id, self.start_time, s, looper_length));
925 }
926 LooperMode::Overdubbing => {
927 sender.send_update(AddOverdubSample(self.id, self.start_time, s));
928 }
929 _ => {}
930 }
931
932 self.acc = [0.0, 0.0];
933 self.size = 0;
934 }
935}
936
937enum LooperChange {
938 PushSample,
939 PopSample(Sample),
940 Clear {
941 samples: Vec<Sample>,
942 in_time: FrameTime,
943 out_time: FrameTime,
944 offset: FrameTime,
945 },
946 UnClear,
947}
948
949impl Debug for LooperChange {
950 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
951 match self {
952 LooperChange::PushSample => write!(f, "PushSample"),
953 LooperChange::PopSample(sample) => write!(f, "PopSample<{}>", sample.length()),
954 LooperChange::Clear { samples, .. } => write!(f, "Clear<{}>", samples.len()),
955 LooperChange::UnClear => write!(f, "UnClear"),
956 }
957 }
958}
959
960pub struct LooperBackend {
961 pub id: u32,
962 pub samples: Vec<Sample>,
963 pub mode: Arc<Atomic<LooperMode>>,
964 pub length: Arc<Atomic<u64>>,
965 pub speed: LooperSpeed,
966 pub pan: f32,
967 pub level: f32,
968 pub parts: PartSet,
969 pub deleted: bool,
970
971 offset: FrameTime,
972
973 enable_crossfading: bool,
974
975 out_time: FrameTime,
976 in_time: FrameTime,
977
978 input_buffer: Sample,
979 input_buffer_idx: usize,
980 xfade_samples_left: usize,
981 xfade_sample_idx: usize,
982
983 in_queue: Arc<ArrayQueue<TransferBuf<f32>>>,
984 out_queue: Arc<ArrayQueue<TransferBuf<f64>>>,
985
986 gui_sender: GuiSender,
987
988 pub channel: Receiver<ControlMessage>,
990
991 waveform_generator: WaveformGenerator,
992
993 undo_queue: VecDeque<LooperChange>,
994 redo_queue: VecDeque<LooperChange>,
995
996 should_output: bool,
997 gui_needs_reset: bool,
998}
999
1000impl LooperBackend {
1001 fn start(mut self) {
1002 thread::spawn(move || loop {
1003 match self.channel.recv() {
1004 Ok(msg) => {
1005 if !self.handle_msg(msg) {
1006 break;
1007 }
1008 }
1009 Err(_) => {
1010 info!("Channel closed, stopping");
1011 break;
1012 }
1013 }
1014 });
1015 }
1016
1017 pub fn process_until_done(&mut self) {
1018 loop {
1019 let msg = self.channel.try_recv();
1020 match msg {
1021 Ok(msg) => self.handle_msg(msg),
1022 Err(_) => break,
1023 };
1024 }
1025 }
1026
1027 fn current_state(&self) -> LooperState {
1028 LooperState {
1029 mode: self.mode(),
1030 speed: self.speed,
1031 pan: self.pan,
1032 level: self.level,
1033 parts: self.parts,
1034 offset: self.offset,
1035 has_undos: !self.undo_queue.is_empty(),
1036 has_redos: !self.redo_queue.is_empty(),
1037 }
1038 }
1039
1040 pub fn mode(&self) -> LooperMode {
1041 return self.mode.load(Ordering::Relaxed);
1042 }
1043
1044 fn handle_msg(&mut self, msg: ControlMessage) -> bool {
1045 debug!("[{}] got control message: {:?}", self.id, msg);
1046 match msg {
1047 ControlMessage::InputDataReady { id, size } => {
1048 let mut read = 0;
1049 let mut processing = false;
1050 while read < size {
1051 let buf = self
1052 .in_queue
1053 .pop()
1054 .expect("missing expected data from queue");
1055 if buf.id == id {
1056 processing = true;
1057 } else if processing {
1058 assert_eq!(read, size, "did not find enough values in input data!");
1059 break;
1060 } else {
1061 warn!(
1062 "Skipping unexpected input data in looper {}: \
1063 got {}, but waiting for {}",
1064 self.id, buf.id, id
1065 );
1066 }
1067
1068 if processing {
1069 let to_read = (size - read).min(buf.size);
1070 read += to_read;
1071 self.handle_input(
1072 buf.time.0 as u64,
1073 &[&buf.data[0][0..to_read], &buf.data[1][0..to_read]],
1074 );
1075 }
1076 }
1077 }
1078 ControlMessage::TransitionTo(mode) => {
1079 self.transition_to(mode);
1080 }
1081 ControlMessage::Clear => {
1082 self.transition_to(LooperMode::Playing);
1083
1084 let mut samples = vec![];
1085 swap(&mut samples, &mut self.samples);
1086
1087 let change = LooperChange::Clear {
1088 samples,
1089 in_time: self.in_time,
1090 out_time: self.out_time,
1091 offset: self.offset,
1092 };
1093
1094 self.in_time = FrameTime(0);
1095 self.out_time = FrameTime(0);
1096 self.offset = FrameTime(0);
1097 self.xfade_samples_left = 0;
1098 self.length.store(0, Ordering::Relaxed);
1099 self.gui_sender
1100 .send_update(GuiCommand::ClearLooper(self.id));
1101
1102 self.add_change(change);
1103 }
1104 ControlMessage::SetTime(time) => {
1105 self.out_time = FrameTime(time.0.max(0));
1106 self.in_time = time;
1107 self.should_output = true;
1108 }
1109 ControlMessage::ReadOutput(time) => {
1110 self.out_time = FrameTime(self.out_time.0.max(time.0));
1111 }
1112 ControlMessage::Shutdown => {
1113 info!("Got shutdown message, stopping");
1114 return false;
1115 }
1116 ControlMessage::Deleted => {
1117 info!("Looper was deleted");
1118 self.gui_sender
1119 .send_update(GuiCommand::RemoveLooper(self.id));
1120 return false;
1121 }
1122 ControlMessage::Serialize(path, channel) => {
1123 let result = self.serialize(&path);
1124 if let Err(e) = channel.try_send(result) {
1125 warn!("failed to respond to serialize request: {:?}", e);
1126 }
1127 }
1128 ControlMessage::SetSpeed(speed) => {
1129 self.speed = speed;
1130 self.gui_needs_reset = true;
1131 }
1132 ControlMessage::SetPan(pan) => {
1133 self.pan = pan;
1134 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1135 self.id,
1136 self.current_state(),
1137 ));
1138 }
1139 ControlMessage::SetLevel(level) => {
1140 self.level = level;
1141 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1142 self.id, self.current_state()
1143 ));
1144 }
1145 ControlMessage::SetParts(parts) => {
1146 self.parts = parts;
1147 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1148 self.id, self.current_state()
1149 ));
1150 },
1151 ControlMessage::Undo => {
1152 info!("Performing Undo on queue: {:?}", self.undo_queue);
1153
1154 if let Some(change) = self.undo_queue.pop_back() {
1155 if let Some(change) = self.undo_change(change) {
1156 self.redo_queue.push_back(change);
1157 }
1158 }
1159 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1160 self.id, self.current_state()
1161 ));
1162 }
1163 ControlMessage::Redo => {
1164 info!("Performing Redo on queue: {:?}", self.redo_queue);
1165 if let Some(change) = self.redo_queue.pop_back() {
1166 if let Some(change) = self.undo_change(change) {
1167 self.undo_queue.push_back(change);
1168 }
1169 }
1170 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1171 self.id, self.current_state()
1172 ));
1173 }
1174 ControlMessage::StopOutput => {
1175 self.should_output = false;
1176 }
1177 }
1178
1179 if self.should_output {
1180 self.fill_output();
1181 if self.gui_needs_reset {
1182 self.reset_gui();
1183 self.gui_needs_reset = false;
1184 }
1185 }
1186 true
1187 }
1188
1189 #[inline]
1190 fn time_loop_idx(&self, t: FrameTime, adjust_for_speed: bool) -> usize {
1191 let t = (t - self.offset).0;
1192
1193 if adjust_for_speed {
1194 match self.speed {
1195 LooperSpeed::Half => t / 2,
1196 LooperSpeed::One => t,
1197 LooperSpeed::Double => t * 2,
1198 }
1199 } else {
1200 t
1201 }.rem_euclid(self.length.load(Ordering::Relaxed) as i64) as usize
1202 }
1203
1204 fn fill_output(&mut self) {
1205 let sample_len = self.length_in_samples(true) as usize;
1206 if sample_len > 0 && self.mode() != LooperMode::Recording && self.out_time.0 >= 0 {
1209 let mut count = 0;
1211 let end = self.in_time.0 + sample_len as i64;
1212 while self.out_time.0 + 1 < end as i64
1213 && count < 32
1214 && self.out_queue.len() < self.out_queue.capacity() / 2
1215 {
1216 let mut buf = TransferBuf {
1217 id: 0,
1218 time: self.out_time,
1219 size: ((end - self.out_time.0) as usize).min(TRANSFER_BUF_SIZE),
1220 data: [[0f64; TRANSFER_BUF_SIZE]; 2],
1221 };
1222
1223 for sample in &self.samples {
1224 let b = &sample.buffer;
1225 if b[0].is_empty() {
1226 continue;
1227 }
1228
1229 for i in 0..2 {
1230 for t in 0..buf.size {
1231 buf.data[i][t] +=
1232 b[i][self.time_loop_idx(self.out_time + FrameTime(t as i64), true)] as f64;
1233 }
1234 }
1235 }
1236
1237 if self.out_queue.push(buf).is_err() {
1238 break;
1239 }
1240
1241 debug!(
1242 "[OUTPUT {}] t = {} [{}; {}] (in time = {})",
1243 self.id, self.out_time.0, buf.data[0][0], buf.size, self.in_time.0
1244 );
1245
1246 self.out_time.0 += buf.size as i64;
1247 count += 1;
1248 }
1249 }
1250 }
1251
1252 fn finish_recording(&mut self, _: LooperMode) {
1253 self.out_time = self.in_time;
1256
1257 self.add_change(LooperChange::UnClear);
1258
1259 self.gui_sender
1261 .send_update(GuiCommand::SetLoopLengthAndOffset(
1262 self.id,
1263 self.length_in_samples(false),
1264 self.offset,
1265 ));
1266 }
1267
1268 fn handle_crossfades(&mut self, _next_state: LooperMode) {
1270 debug!("handling crossfade");
1271 self.xfade_samples_left = CROSS_FADE_SAMPLES;
1272 self.xfade_sample_idx = self.samples.len() - 1;
1273
1274 if let Some(s) = self.samples.last_mut() {
1277 let size = self.input_buffer_idx.min(CROSS_FADE_SAMPLES);
1278 if let Some(write_start) = s.length().checked_sub(size as u64) {
1279 let mut left = vec![0f32; size];
1281 let mut right = vec![0f32; size];
1282
1283 let len = self.input_buffer.length();
1284 let read_start =
1285 (self.input_buffer_idx as i64 - size as i64).rem_euclid(len as i64) as usize;
1286
1287 for i in 0..size {
1288 left[i] = self.input_buffer.buffer[0][(i + read_start) % len as usize];
1289 right[i] = self.input_buffer.buffer[1][(i + read_start) % len as usize];
1290 }
1291
1292 if self.enable_crossfading {
1293 s.xfade(
1294 CROSS_FADE_SAMPLES,
1295 0,
1296 write_start,
1297 &[&left, &right],
1298 XfadeDirection::IN,
1299 sample::norm,
1300 );
1301 }
1302 } else {
1303 warn!("Couldn't post crossfade because start was wrong");
1304 }
1305 }
1306
1307 self.input_buffer.clear();
1308 self.input_buffer_idx = 0;
1309 }
1310
1311 fn prepare_for_recording(&mut self, _: LooperMode) {
1312 self.samples.clear();
1313 self.samples.push(Sample::new());
1314 self.length.store(0, Ordering::Relaxed);
1315 }
1316
1317 fn prepare_for_overdubbing(&mut self, _next_state: LooperMode) {
1318 let overdub_sample = Sample::with_size(self.length_in_samples(false) as usize);
1319
1320 self.add_change(LooperChange::PushSample);
1339 self.samples.push(overdub_sample);
1340 }
1341
1342 pub fn transition_to(&mut self, mode: LooperMode) {
1343 debug!("Transition {:?} to {:?}", self.mode, mode);
1344
1345 if self.mode() == mode {
1346 return;
1348 }
1349
1350 STATE_MACHINE.handle_transition(self, mode);
1351
1352 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1353 self.id,
1354 LooperState {
1355 mode,
1356 speed: self.speed,
1357 pan: self.pan,
1358 level: self.level,
1359 parts: self.parts,
1360 offset: self.offset,
1361 has_undos: !self.undo_queue.is_empty(),
1362 has_redos: !self.redo_queue.is_empty(),
1363 },
1364 ));
1365 }
1366
1367 fn handle_input(&mut self, time_in_samples: u64, inputs: &[&[f32]]) {
1368 if self.mode() == LooperMode::Overdubbing {
1369 let time_in_loop = self.time_loop_idx(FrameTime(time_in_samples as i64), false);
1371
1372 let s = self
1373 .samples
1374 .last_mut()
1375 .expect("No samples for looper in overdub mode");
1376
1377 s.overdub(time_in_loop as u64, inputs, self.speed);
1378
1379 let mut wv = [vec![0f64; inputs[0].len()], vec![0f64; inputs[0].len()]];
1382 for c in 0..2 {
1383 for i in 0..inputs[0].len() {
1384 for s in &self.samples {
1385 wv[c][i] += s.buffer[c]
1386 [self.time_loop_idx(FrameTime(time_in_samples as i64 + i as i64), true)]
1387 as f64;
1388 }
1389 }
1390 }
1391 self.waveform_generator.add_buf(
1392 self.mode(),
1393 FrameTime(time_in_samples as i64),
1394 &[&wv[0], &wv[1]],
1395 self.length_in_samples(true),
1396 &mut self.gui_sender,
1397 );
1398 } else if self.mode() == LooperMode::Recording {
1399 if self.length_in_samples(false) == 0 {
1403 self.offset = FrameTime(time_in_samples as i64);
1404 }
1405
1406 let s = self
1407 .samples
1408 .last_mut()
1409 .expect("No samples for looper in record mode");
1410 s.record(inputs);
1411
1412 self.length.store(s.length(), Ordering::Relaxed);
1413
1414 let mut wv = [vec![0f64; inputs[0].len()], vec![0f64; inputs[0].len()]];
1416 for (c, vs) in inputs.iter().enumerate() {
1417 for (i, v) in vs.iter().enumerate() {
1418 wv[c][i] = *v as f64;
1419 }
1420 }
1421 self.waveform_generator.add_buf(
1422 self.mode(),
1423 FrameTime(time_in_samples as i64),
1424 &[&wv[0], &wv[1]],
1425 self.length_in_samples(true),
1426 &mut self.gui_sender,
1427 );
1428 } else {
1429 self.input_buffer
1431 .replace(self.input_buffer_idx as u64, inputs);
1432 self.input_buffer_idx += inputs[0].len();
1433 }
1434
1435 if self.xfade_samples_left > 0 {
1438 debug!("crossfading beginning at time {}", time_in_samples);
1439 if let Some(s) = self.samples.get_mut(self.xfade_sample_idx) {
1440 if self.enable_crossfading {
1442 s.xfade(
1443 CROSS_FADE_SAMPLES,
1444 CROSS_FADE_SAMPLES as u64 - self.xfade_samples_left as u64,
1445 (CROSS_FADE_SAMPLES - self.xfade_samples_left) as u64,
1446 inputs,
1447 XfadeDirection::OUT,
1448 sample::norm,
1449 );
1450 }
1451 self.xfade_samples_left =
1452 (self.xfade_samples_left as i64 - inputs[0].len() as i64).max(0) as usize;
1453 } else {
1454 debug!("tried to cross fade but no samples... something is likely wrong");
1455 }
1456 }
1457
1458 self.in_time = FrameTime(time_in_samples as i64 + inputs[0].len() as i64);
1459 }
1460
1461 fn add_change(&mut self, change: LooperChange) {
1462 self.undo_queue.push_back(change);
1463 self.redo_queue.clear();
1464 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1465 self.id, self.current_state()
1466 ));
1467 }
1468
1469 fn reset_gui(&mut self) {
1470 if self.length_in_samples(false) > 0 {
1471 self.gui_sender.send_update(GuiCommand::UpdateLooperWithSamples(
1472 self.id,
1473 self.length_in_samples(true),
1474 Box::new(compute_waveform(&self.samples, WAVEFORM_DOWNSAMPLE)),
1475 self.current_state(),
1476 ));
1477 } else {
1478 self.gui_sender.send_update(GuiCommand::LooperStateChange(
1479 self.id, self.current_state()))
1480 }
1481 }
1482
1483 fn undo_change(&mut self, change: LooperChange) -> Option<LooperChange> {
1484 match change {
1485 LooperChange::PushSample => {
1486 let sample = self.samples.pop()
1487 .map(|s| LooperChange::PopSample(s));
1488 self.gui_needs_reset = true;
1489 sample
1490 }
1491 LooperChange::PopSample(buffer) => {
1492 self.samples.push(buffer);
1493 self.gui_needs_reset = true;
1494 Some(LooperChange::PushSample)
1495 }
1496 LooperChange::Clear { samples, in_time, out_time, offset } => {
1497 self.samples = samples;
1498 self.in_time = in_time;
1499 self.out_time = out_time;
1500 self.offset = offset;
1501
1502 if !self.samples.is_empty() {
1503 self.length.store(self.samples[0].length(), Ordering::Relaxed);
1504 }
1505
1506 self.gui_needs_reset = true;
1507
1508 Some(LooperChange::UnClear)
1509 }
1510 LooperChange::UnClear => {
1511 let mut samples = vec![];
1512 swap(&mut samples, &mut self.samples);
1513 let change = Some(LooperChange::Clear {
1514 samples,
1515 in_time: self.in_time,
1516 out_time: self.out_time,
1517 offset: self.offset,
1518 });
1519 self.in_time = FrameTime(0);
1520 self.out_time = FrameTime(0);
1521 self.offset = FrameTime(0);
1522 self.gui_sender
1523 .send_update(GuiCommand::ClearLooper(self.id));
1524
1525 change
1526 }
1527 }
1528 }
1529
1530 pub fn length_in_samples(&self, adjust_for_speed: bool) -> u64 {
1531 let len = self.length.load(Ordering::Relaxed);
1532 if adjust_for_speed {
1533 match self.speed {
1534 LooperSpeed::Half => len * 2,
1535 LooperSpeed::One => len,
1536 LooperSpeed::Double => len / 2,
1537 }
1538 } else {
1539 len
1540 }
1541 }
1542
1543 pub fn serialize(&self, path: &Path) -> Result<SavedLooper, SaveLoadError> {
1544 let spec = hound::WavSpec {
1545 channels: 2,
1546 sample_rate: 44100,
1547 bits_per_sample: 32,
1548 sample_format: hound::SampleFormat::Float,
1549 };
1550
1551 let mut saved = SavedLooper {
1552 id: self.id,
1553 mode: self.mode(),
1554 parts: self.parts,
1555 speed: self.speed,
1556 pan: self.pan,
1557 level: self.level,
1558 samples: Vec::with_capacity(self.samples.len()),
1559 offset_samples: self.offset.0,
1560 };
1561
1562 for (i, s) in self.samples.iter().enumerate() {
1563 let name = format!("loop_{}_{}.wav", self.id, i);
1564 let p = path.join(&name);
1565 let mut writer = hound::WavWriter::create(&p, spec.clone())?;
1566
1567 for j in 0..s.length() as usize {
1568 writer.write_sample(s.buffer[0][j])?;
1569 writer.write_sample(s.buffer[1][j])?;
1570 }
1571 writer.finalize()?;
1572 saved.samples.push(PathBuf::from(name));
1574 }
1575
1576 Ok(saved)
1577 }
1578}
1579
1580pub struct Looper {
1584 pub id: u32,
1585 pub deleted: bool,
1586 pub parts: PartSet,
1587 pub pan: f32,
1588 pub level: f32,
1589
1590 pub pan_law: PanLaw,
1591
1592
1593 local_mode: Option<LooperMode>,
1596 mode: Arc<Atomic<LooperMode>>,
1597 length: Arc<Atomic<u64>>,
1598 pub backend: Option<LooperBackend>,
1599 msg_counter: u64,
1600 out_queue: Arc<ArrayQueue<TransferBuf<f32>>>,
1601 in_queue: Arc<ArrayQueue<TransferBuf<f64>>>,
1602 channel: Sender<ControlMessage>,
1603
1604 in_progress_output: Option<TransferBuf<f64>>,
1605
1606 last_time: FrameTime,
1607}
1608
1609impl Looper {
1610 pub fn new(id: u32, parts: PartSet, gui_output: GuiSender) -> Looper {
1611 Self::new_with_samples(
1612 id,
1613 parts,
1614 LooperSpeed::One,
1615 0.0,
1616 1.0,
1617 FrameTime(0),
1618 vec![],
1619 gui_output,
1620 )
1621 }
1622
1623 fn new_with_samples(
1624 id: u32,
1625 parts: PartSet,
1626 speed: LooperSpeed,
1627 pan: f32,
1628 level: f32,
1629 offset: FrameTime,
1630 samples: Vec<Sample>,
1631 mut gui_sender: GuiSender,
1632 ) -> Looper {
1633 debug!("Creating new looper with samples {}", id);
1634 let record_queue = Arc::new(ArrayQueue::new(512 * 1024 / TRANSFER_BUF_SIZE));
1635 let play_queue = Arc::new(ArrayQueue::new(512 * 1024 / TRANSFER_BUF_SIZE));
1636
1637 let (s, r) = bounded(1000);
1638
1639 let length = samples.get(0).map(|s| s.length()).unwrap_or(0);
1640
1641 let state = LooperState {
1642 mode: LooperMode::Playing,
1643 speed,
1644 pan,
1645 level,
1646 parts,
1647 offset,
1648 has_undos: false,
1649 has_redos: false,
1650 };
1651
1652 if samples.is_empty() {
1653 gui_sender.send_update(GuiCommand::AddLooper(id, state));
1654 } else {
1655 gui_sender.send_update(GuiCommand::AddLooperWithSamples(
1656 id,
1657 length,
1658 Box::new(compute_waveform(&samples, WAVEFORM_DOWNSAMPLE)),
1659 state,
1660 ));
1661 }
1662
1663 let mode = Arc::new(Atomic::new(LooperMode::Playing));
1664 let length = Arc::new(Atomic::new(samples.get(0)
1665 .map(|s| s.length())
1666 .unwrap_or(0)));
1667
1668 let backend = LooperBackend {
1669 id,
1670 samples,
1671 mode: mode.clone(),
1672 length: length.clone(),
1673 speed,
1674 pan,
1675 level,
1676 parts,
1677 deleted: false,
1678 offset,
1679 enable_crossfading: true,
1680 out_time: FrameTime(0),
1681 in_time: FrameTime(0),
1682 input_buffer: Sample::with_size(CROSS_FADE_SAMPLES),
1685 input_buffer_idx: 0,
1686 xfade_samples_left: 0,
1689 xfade_sample_idx: 0,
1690 in_queue: record_queue.clone(),
1691 out_queue: play_queue.clone(),
1692 gui_sender,
1693 channel: r,
1694 waveform_generator: WaveformGenerator::new(id),
1695 undo_queue: VecDeque::new(),
1696 redo_queue: VecDeque::new(),
1697 should_output: true,
1698 gui_needs_reset: false,
1699 };
1700
1701 Looper {
1702 id,
1703 backend: Some(backend),
1704 parts,
1705 pan,
1706 level,
1707 pan_law: PanLaw::Neg4_5,
1708 deleted: false,
1709 msg_counter: 0,
1710 in_queue: play_queue.clone(),
1711 out_queue: record_queue.clone(),
1712 channel: s,
1713 mode,
1714 length,
1715
1716 in_progress_output: None,
1717
1718 last_time: FrameTime(0),
1719 local_mode: None
1720 }
1721 }
1722
1723 pub fn from_serialized(
1724 state: &SavedLooper,
1725 path: &Path,
1726 gui_output: GuiSender,
1727 ) -> Result<Looper, SaveLoadError> {
1728 let mut samples = vec![];
1729 for sample_path in &state.samples {
1730 let mut reader = hound::WavReader::open(&path.join(sample_path))?;
1731
1732 let mut sample = Sample::new();
1733 let mut left = Vec::with_capacity(reader.len() as usize / 2);
1734 let mut right = Vec::with_capacity(reader.len() as usize / 2);
1735
1736 for (i, s) in reader.samples().enumerate() {
1737 if i % 2 == 0 {
1738 left.push(s?);
1739 } else {
1740 right.push(s?);
1741 }
1742 }
1743
1744 sample.record(&[&left, &right]);
1745 samples.push(sample);
1746 }
1747
1748 Ok(Self::new_with_samples(
1749 state.id,
1750 state.parts,
1751 state.speed,
1752 state.pan,
1753 state.level,
1754 FrameTime(state.offset_samples),
1755 samples,
1756 gui_output,
1757 ))
1758 }
1759
1760 pub fn channel(&self) -> Sender<ControlMessage> {
1761 self.channel.clone()
1762 }
1763
1764 pub fn start(mut self) -> Self {
1765 let mut backend: Option<LooperBackend> = None;
1766 std::mem::swap(&mut backend, &mut self.backend);
1767
1768 match backend {
1769 Some(backend) => backend.start(),
1770 _ => warn!("looper already started!"),
1771 }
1772
1773 self
1774 }
1775
1776 fn send_to_backend(&mut self, message: ControlMessage) -> bool {
1777 match self.channel.try_send(message) {
1778 Ok(_) => true,
1779 Err(TrySendError::Full(msg)) => {
1780 error!(
1781 "Failed to process message {:?} in looper {}: channel is full",
1782 msg, self.id
1783 );
1784 false
1785 }
1786 Err(TrySendError::Disconnected(_)) => {
1787 error!("Backend channel disconnected in looper {}", self.id);
1788 false
1789 }
1790 }
1791 }
1792
1793 pub fn local_mode(&self) -> LooperMode {
1794 return self.local_mode.unwrap_or(self.mode());
1795 }
1796
1797 pub fn mode(&self) -> LooperMode {
1798 self.mode.load(Ordering::Relaxed)
1799 }
1800
1801 pub fn length(&self) -> u64 {
1802 self.length.load(Ordering::Relaxed)
1803 }
1804
1805 pub fn set_time(&mut self, time: FrameTime) {
1806 loop {
1807 if self.in_queue.pop().is_none() {
1808 break;
1809 }
1810 }
1811 self.in_progress_output = None;
1812
1813 if self.mode() == LooperMode::Recording && time < FrameTime(0) {
1814 self.send_to_backend(ControlMessage::Clear);
1816 }
1817
1818 self.send_to_backend(ControlMessage::SetTime(time));
1819 }
1820
1821 fn clear_queue(&mut self) {
1822 self.set_time(self.last_time)
1823 }
1824
1825 pub fn handle_command(&mut self, command: LooperCommand) {
1826 use LooperCommand::*;
1827 match command {
1828 Record => self.transition_to(LooperMode::Recording),
1829 Overdub => self.transition_to(LooperMode::Overdubbing),
1830 Play => self.transition_to(LooperMode::Playing),
1831 Mute => self.transition_to(LooperMode::Muted),
1832 Solo => self.transition_to(LooperMode::Soloed),
1833 Clear => {
1834 self.send_to_backend(ControlMessage::Clear);
1835 self.clear_queue();
1836 }
1837
1838 SetSpeed(speed) => {
1839 self.send_to_backend(ControlMessage::StopOutput);
1840 self.send_to_backend(ControlMessage::SetSpeed(speed));
1841 self.clear_queue();
1842 }
1843
1844 SetPan(pan) => {
1845 self.pan = pan;
1846 self.send_to_backend(ControlMessage::SetPan(pan));
1847 }
1848
1849 SetLevel(level) => {
1850 self.level = level;
1851 self.send_to_backend(ControlMessage::SetLevel(level));
1852 }
1853
1854 AddToPart(part) => {
1855 self.parts[part] = true;
1856 self.send_to_backend(ControlMessage::SetParts(self.parts));
1857 }
1858 RemoveFromPart(part) => {
1859 self.parts[part] = false;
1860 if self.parts.is_empty() {
1861 self.parts[part] = true;
1863 } else {
1864 self.send_to_backend(ControlMessage::SetParts(self.parts));
1865 }
1866 }
1867 Delete => {
1868 self.deleted = true;
1869 self.send_to_backend(ControlMessage::Deleted);
1870 }
1871 RecordOverdubPlay => {
1872 if self.length() == 0 {
1874 self.transition_to(LooperMode::Recording);
1875 } else if self.mode() == LooperMode::Recording || self.mode() == LooperMode::Playing {
1876 self.transition_to(LooperMode::Overdubbing);
1877 } else {
1878 self.transition_to(LooperMode::Playing);
1879 }
1880 }
1881 Undo => {
1882 self.send_to_backend(ControlMessage::StopOutput);
1883 self.send_to_backend(ControlMessage::Undo);
1884 self.clear_queue();
1885 }
1886 Redo => {
1887 self.send_to_backend(ControlMessage::StopOutput);
1888 self.send_to_backend(ControlMessage::Redo);
1889 self.clear_queue();
1890 }
1891 }
1892 }
1893
1894 fn output_for_t(&mut self, t: FrameTime) -> Option<(f64, f64)> {
1895 let mut cur = self
1896 .in_progress_output
1897 .or_else(|| self.in_queue.pop())?;
1898 self.in_progress_output = Some(cur);
1899
1900 loop {
1901 if cur.time.0 > t.0 {
1902 error!(
1903 "data is in future for looper id {} (time is {}, needed {})",
1904 self.id, cur.time.0, t.0
1905 );
1906 self.clear_queue();
1907 return None;
1908 }
1909
1910 if let Some(o) = cur.get_t(t) {
1911 return Some(o);
1912 }
1913
1914 if let Some(buf) = self.in_queue.pop() {
1915 cur = buf;
1916 self.in_progress_output = Some(buf);
1917 } else {
1918 self.in_progress_output = None;
1919 return None;
1920 }
1921 }
1922 }
1923
1924 fn should_output(&self, part: Part, solo: bool) -> bool {
1925 if !self.parts[part] {
1926 return false
1927 }
1928
1929 if solo && self.mode() != LooperMode::Soloed {
1930 return false
1931 }
1932
1933 return self.mode() == LooperMode::Playing ||
1934 self.mode() == LooperMode::Overdubbing ||
1935 self.mode() == LooperMode::Soloed
1936 }
1937
1938 pub fn process_output(
1943 &mut self,
1944 time: FrameTime,
1945 outputs: &mut [&mut [f64]],
1946 part: Part,
1947 solo: bool,
1948 ) {
1949 if time.0 < 0 || self.length() == 0 {
1950 return;
1951 }
1952
1953 debug!("reading time {}", time.0);
1954
1955 let mut time = time;
1956 let mut out_idx = 0;
1957
1958 let mut missing = 0;
1959 let mut waiting = 1_000;
1960 let backoff = crossbeam_utils::Backoff::new();
1961
1962 let pan_l = self.pan_law.left(self.pan);
1965 let pan_r = self.pan_law.right(self.pan);
1966
1967 while out_idx < outputs[0].len() {
1968 if let Some((l, r)) = self.output_for_t(time) {
1969 if self.should_output(part, solo) {
1970 outputs[0][out_idx] += l * pan_l as f64 * self.level as f64;
1971 outputs[1][out_idx] += r * pan_r as f64 * self.level as f64;
1972 }
1973 } else if waiting > 0 && self.mode() != LooperMode::Recording {
1974 backoff.spin();
1975 waiting -= 1;
1976 continue;
1977 } else {
1978 missing += 1;
1979 }
1980 out_idx += 1;
1981 time.0 += 1;
1982 }
1983
1984 self.last_time = time;
1985
1986 if self.mode() != LooperMode::Recording && missing > 0 {
1987 error!(
1988 "needed output but queue was empty in looper {} at {} (missed {} samples)",
1989 self.id, time.0, missing
1990 );
1991 }
1992
1993 match self.channel.try_send(ControlMessage::ReadOutput(time)) {
1994 Err(TrySendError::Disconnected(_)) => panic!("channel closed"),
1995 Err(TrySendError::Full(_)) => warn!("channel full while requesting more output"),
1996 _ => {}
1997 }
1998
1999 self.local_mode = None;
2000 }
2001
2002 pub fn process_input(&mut self, time_in_samples: u64, inputs: &[&[f32]], part: Part) {
2006 assert_eq!(2, inputs.len());
2007
2008 debug!("inputting time {}", time_in_samples);
2009
2010 let msg_id = self.msg_counter;
2011 self.msg_counter += 1;
2012
2013 let mut buf = TransferBuf {
2014 id: msg_id,
2015 time: FrameTime(0 as i64),
2016 size: 0,
2017 data: [[0f32; TRANSFER_BUF_SIZE]; 2],
2018 };
2019
2020 let mut time = time_in_samples;
2021 for (l, r) in inputs[0]
2022 .chunks(TRANSFER_BUF_SIZE)
2023 .zip(inputs[1].chunks(TRANSFER_BUF_SIZE))
2024 {
2025 buf.time = FrameTime(time as i64);
2026 buf.size = l.len();
2027
2028 if self.parts[part] {
2029 for i in 0..l.len() {
2031 buf.data[0][i] = l[i];
2032 buf.data[1][i] = r[i];
2033 }
2034 }
2035
2036 if let Err(_) = self.out_queue.push(buf) {
2037 error!("queue is full on looper {}", self.id);
2039 }
2040
2041 time += l.len() as u64;
2042 }
2043
2044 self.send_to_backend(ControlMessage::InputDataReady {
2045 id: msg_id,
2046 size: inputs[0].len(),
2047 });
2048 }
2049
2050 pub fn transition_to(&mut self, mode: LooperMode) {
2051 let mut mode = mode;
2052 if self.length() == 0 && mode == LooperMode::Overdubbing {
2053 warn!("trying to move to overdub with 0-length looper");
2054 mode = LooperMode::Recording;
2055 }
2056
2057 self.send_to_backend(ControlMessage::TransitionTo(mode));
2058 self.local_mode = Some(mode);
2059 }
2060}
2061
2062impl Drop for Looper {
2063 fn drop(&mut self) {
2064 if let Err(_) = self.channel.send(ControlMessage::Shutdown) {
2065 warn!("failed to shutdown backend because queue was full");
2066 }
2067 }
2068}