proteus_lib/playback/engine/
mod.rs1use dasp_ring_buffer::Bounded;
4use rodio::buffer::SamplesBuffer;
5use std::collections::HashMap;
6use std::sync::atomic::AtomicBool;
7use std::sync::atomic::AtomicU64;
8use std::sync::{mpsc::Receiver, Arc, Condvar, Mutex};
9
10use crate::audio::buffer::{init_buffer_map, TrackBuffer};
11use crate::container::prot::Prot;
12
13mod mix;
14mod reverb;
15mod state;
16
17pub use state::{PlaybackBufferSettings, ReverbMetrics, ReverbSettings};
18
19use mix::{spawn_mix_thread, MixThreadArgs};
20
21#[derive(Debug, Clone)]
23pub struct PlayerEngine {
24 pub finished_tracks: Arc<Mutex<Vec<u16>>>,
25 start_time: f64,
26 abort: Arc<AtomicBool>,
27 buffer_map: Arc<Mutex<HashMap<u16, TrackBuffer>>>,
28 buffer_notify: Arc<Condvar>,
29 effects_buffer: Arc<Mutex<Bounded<Vec<f32>>>>,
30 track_weights: Arc<Mutex<HashMap<u16, f32>>>,
31 reverb_reset: Arc<AtomicU64>,
32 prot: Arc<Mutex<Prot>>,
33 buffer_settings: Arc<Mutex<PlaybackBufferSettings>>,
34 reverb_settings: Arc<Mutex<ReverbSettings>>,
35 reverb_metrics: Arc<Mutex<ReverbMetrics>>,
36}
37
38impl PlayerEngine {
39 pub fn new(
41 prot: Arc<Mutex<Prot>>,
42 abort_option: Option<Arc<AtomicBool>>,
43 start_time: f64,
44 buffer_settings: Arc<Mutex<PlaybackBufferSettings>>,
45 reverb_settings: Arc<Mutex<ReverbSettings>>,
46 reverb_metrics: Arc<Mutex<ReverbMetrics>>,
47 reverb_reset: Arc<AtomicU64>,
48 ) -> Self {
49 let buffer_map = init_buffer_map();
50 let buffer_notify = Arc::new(Condvar::new());
51 let track_weights = Arc::new(Mutex::new(HashMap::new()));
52 let finished_tracks: Arc<Mutex<Vec<u16>>> = Arc::new(Mutex::new(Vec::new()));
53 let abort = if abort_option.is_some() {
54 abort_option.unwrap()
55 } else {
56 Arc::new(AtomicBool::new(false))
57 };
58
59 let prot_unlocked = prot.lock().unwrap();
60 let start_buffer_ms = buffer_settings.lock().unwrap().start_buffer_ms;
61 let channels = prot_unlocked.info.channels as usize;
62 let start_samples = ((prot_unlocked.info.sample_rate as f32 * start_buffer_ms) / 1000.0)
63 as usize
64 * channels;
65 let buffer_size = (prot_unlocked.info.sample_rate as usize * 10).max(start_samples * 2);
66 let effects_buffer = Arc::new(Mutex::new(dasp_ring_buffer::Bounded::from(vec![
67 0.0;
68 buffer_size
69 ])));
70 drop(prot_unlocked);
71
72 Self {
73 finished_tracks,
74 start_time,
75 buffer_map,
76 buffer_notify,
77 effects_buffer,
78 track_weights,
79 reverb_reset,
80 abort,
81 prot,
82 buffer_settings,
83 reverb_settings,
84 reverb_metrics,
85 }
86 }
87
88 pub fn reception_loop(&mut self, f: &dyn Fn((SamplesBuffer, f64))) {
90 let prot = self.prot.lock().unwrap();
91 let keys = prot.get_keys();
92 drop(prot);
93 self.ready_buffer_map(&keys);
94 let receiver = self.get_receiver();
95
96 for (mixer, length_in_seconds) in receiver {
97 f((mixer, length_in_seconds));
98 }
99 }
100
101 pub fn start_receiver(&mut self) -> Receiver<(SamplesBuffer, f64)> {
103 let prot = self.prot.lock().unwrap();
104 let keys = prot.get_keys();
105 drop(prot);
106 self.ready_buffer_map(&keys);
107 self.get_receiver()
108 }
109
110 fn get_receiver(&self) -> Receiver<(SamplesBuffer, f64)> {
111 let prot = self.prot.lock().unwrap();
112 let audio_info = prot.info.clone();
113 drop(prot);
114
115 spawn_mix_thread(MixThreadArgs {
116 audio_info,
117 buffer_map: self.buffer_map.clone(),
118 buffer_notify: self.buffer_notify.clone(),
119 effects_buffer: self.effects_buffer.clone(),
120 track_weights: self.track_weights.clone(),
121 reverb_reset: self.reverb_reset.clone(),
122 finished_tracks: self.finished_tracks.clone(),
123 prot: self.prot.clone(),
124 abort: self.abort.clone(),
125 start_time: self.start_time,
126 buffer_settings: self.buffer_settings.clone(),
127 reverb_settings: self.reverb_settings.clone(),
128 reverb_metrics: self.reverb_metrics.clone(),
129 })
130 }
131
132 pub fn get_duration(&self) -> f64 {
134 let prot = self.prot.lock().unwrap();
135 *prot.get_duration()
136 }
137
138 fn ready_buffer_map(&mut self, keys: &Vec<u32>) {
139 self.buffer_map = init_buffer_map();
140 self.track_weights.lock().unwrap().clear();
141
142 let prot = self.prot.lock().unwrap();
143 let sample_rate = prot.info.sample_rate;
144 let channels = prot.info.channels as usize;
145 let start_buffer_ms = self.buffer_settings.lock().unwrap().start_buffer_ms;
146 drop(prot);
147 let start_samples = ((sample_rate as f32 * start_buffer_ms) / 1000.0) as usize * channels;
148 let buffer_size = (sample_rate as usize * 10).max(start_samples * 2);
149
150 for key in keys {
151 let ring_buffer =
152 Arc::new(Mutex::new(dasp_ring_buffer::Bounded::from(vec![
153 0.0;
154 buffer_size
155 ])));
156 self.buffer_map
157 .lock()
158 .unwrap()
159 .insert(*key as u16, ring_buffer);
160 self.track_weights.lock().unwrap().insert(*key as u16, 1.0);
161 }
162 }
163
164 pub fn finished_buffering(&self) -> bool {
166 let finished_tracks = self.finished_tracks.lock().unwrap();
167 let prot = self.prot.lock().unwrap();
168 let keys = prot.get_keys();
169 drop(prot);
170
171 for key in keys {
172 if !finished_tracks.contains(&(key as u16)) {
173 return false;
174 }
175 }
176
177 true
178 }
179}