xsynth_core/channel/
mod.rs1use std::sync::{atomic::AtomicU64, Arc};
2
3use crate::{
4 effects::MultiChannelBiQuad,
5 helpers::{prepapre_cache_vec, sum_simd},
6 voice::VoiceControlData,
7 AudioStreamParams, ChannelCount,
8};
9
10use xsynth_soundfonts::FilterType;
11
12use self::{control::ControlEventData, key::KeyData, params::VoiceChannelParams};
13
14use super::AudioPipe;
15
16use rayon::prelude::*;
17
18mod channel_sf;
19mod control;
20mod key;
21mod params;
22mod voice_buffer;
23mod voice_spawner;
24
25mod event;
26pub use event::*;
27
28pub(crate) use control::ValueLerp;
29pub use params::VoiceChannelStatsReader;
30
31struct Key {
32 data: KeyData,
33 audio_cache: Vec<f32>,
34 event_cache: Vec<KeyNoteEvent>,
35}
36
37impl Key {
38 pub fn new(key: u8, shared_voice_counter: Arc<AtomicU64>, options: ChannelInitOptions) -> Self {
39 Key {
40 data: KeyData::new(key, shared_voice_counter, options),
41 audio_cache: Vec::new(),
42 event_cache: Vec::new(),
43 }
44 }
45}
46
47#[derive(Clone, Copy, Debug, PartialEq)]
49#[cfg_attr(
50 feature = "serde",
51 derive(serde::Deserialize, serde::Serialize),
52 serde(default)
53)]
54pub struct ChannelInitOptions {
55 pub fade_out_killing: bool,
61}
62
63#[allow(clippy::derivable_impls)]
64impl Default for ChannelInitOptions {
65 fn default() -> Self {
66 Self {
67 fade_out_killing: false,
68 }
69 }
70}
71
72pub struct VoiceChannel {
92 key_voices: Vec<Key>,
93
94 params: VoiceChannelParams,
95 threadpool: Option<Arc<rayon::ThreadPool>>,
96
97 stream_params: AudioStreamParams,
98
99 control_event_data: ControlEventData,
101
102 voice_control_data: VoiceControlData,
104
105 cutoff: MultiChannelBiQuad,
107}
108
109impl VoiceChannel {
110 pub fn new(
118 options: ChannelInitOptions,
119 stream_params: AudioStreamParams,
120 threadpool: Option<Arc<rayon::ThreadPool>>,
121 ) -> VoiceChannel {
122 fn fill_key_array<T, F: Fn(u8) -> T>(func: F) -> Vec<T> {
123 let mut vec = Vec::with_capacity(128);
124 for i in 0..128 {
125 vec.push(func(i));
126 }
127 vec
128 }
129
130 let params = VoiceChannelParams::new(stream_params);
131 let shared_voice_counter = params.stats.voice_counter.clone();
132
133 VoiceChannel {
134 params,
135 key_voices: fill_key_array(|i| Key::new(i, shared_voice_counter.clone(), options)),
136
137 threadpool,
138
139 stream_params,
140
141 control_event_data: ControlEventData::new_defaults(stream_params.sample_rate),
142 voice_control_data: VoiceControlData::new_defaults(),
143
144 cutoff: MultiChannelBiQuad::new(
145 stream_params.channels.count() as usize,
146 FilterType::LowPass,
147 stream_params.sample_rate as f32 / 2.0,
148 stream_params.sample_rate as f32,
149 None,
150 ),
151 }
152 }
153
154 fn apply_channel_effects(&mut self, out: &mut [f32]) {
155 let control = &mut self.control_event_data;
156
157 match self.stream_params.channels {
158 ChannelCount::Mono => {
159 for sample in out.iter_mut() {
161 let vol = control.volume.get_next() * control.expression.get_next();
162 let vol = vol.powi(2);
163 *sample *= vol;
164 }
165 }
166 ChannelCount::Stereo => {
167 for sample in out.chunks_mut(2) {
169 let vol = control.volume.get_next() * control.expression.get_next();
170 let vol = vol.powi(2);
171 sample[0] *= vol;
172 sample[1] *= vol;
173 }
174
175 for sample in out.chunks_mut(2) {
177 let pan = control.pan.get_next();
178 sample[0] *= ((pan * std::f32::consts::PI / 2.0).cos()).min(1.0);
179 sample[1] *= ((pan * std::f32::consts::PI / 2.0).sin()).min(1.0);
180 }
181 }
182 }
183
184 if let Some(cutoff) = control.cutoff {
186 self.cutoff
187 .set_filter_type(FilterType::LowPass, cutoff, control.resonance);
188 self.cutoff.process(out);
189 }
190 }
191
192 fn push_key_events_and_render(&mut self, out: &mut [f32]) {
193 self.params.load_program();
194
195 out.fill(0.0);
196 match self.threadpool.as_ref() {
197 Some(pool) => {
198 let len = out.len();
199 let key_voices = &mut self.key_voices;
200 let params = &self.params;
201 let control_data = &self.voice_control_data;
202 pool.install(|| {
203 key_voices.par_iter_mut().for_each(move |key| {
204 for e in key.event_cache.drain(..) {
205 key.data
206 .send_event(e, control_data, ¶ms.channel_sf, params.layers);
207 }
208
209 prepapre_cache_vec(&mut key.audio_cache, len, 0.0);
210 key.data.render_to(&mut key.audio_cache);
211 });
212 });
213
214 for key in self.key_voices.iter() {
215 sum_simd(&key.audio_cache, out);
216 }
217 }
218 None => {
219 for key in self.key_voices.iter_mut() {
220 for e in key.event_cache.drain(..) {
221 key.data.send_event(
222 e,
223 &self.voice_control_data,
224 &self.params.channel_sf,
225 self.params.layers,
226 );
227 }
228
229 key.data.render_to(out);
230 }
231 }
232 }
233
234 self.apply_channel_effects(out);
235 }
236
237 fn propagate_voice_controls(&mut self) {
238 for key in self.key_voices.iter_mut() {
239 key.data.process_controls(&self.voice_control_data);
240 }
241 }
242
243 fn kill_voices_in_exclusive_class(&mut self, class: u8) {
244 for key in self.key_voices.iter_mut() {
245 key.data.kill_by_exclusive_class(class);
246 }
247 }
248
249 pub fn process_event(&mut self, event: ChannelEvent) {
252 self.push_events_iter(std::iter::once(event));
253 }
254
255 pub fn push_events_iter<T: Iterator<Item = ChannelEvent>>(&mut self, iter: T) {
257 for e in iter {
258 match e {
259 ChannelEvent::Audio(audio) => match audio {
260 ChannelAudioEvent::NoteOn { key, vel } => {
261 let classes: Vec<_> = self
262 .params
263 .channel_sf
264 .exclusive_classes_attack(key, vel)
265 .collect();
266 for class in classes {
267 self.kill_voices_in_exclusive_class(class);
268 }
269 if let Some(key) = self.key_voices.get_mut(key as usize) {
270 let ev = KeyNoteEvent::On(vel);
271 key.event_cache.push(ev);
272 }
273 }
274 ChannelAudioEvent::NoteOff { key } => {
275 if let Some(key) = self.key_voices.get_mut(key as usize) {
276 let ev = KeyNoteEvent::Off;
277 key.event_cache.push(ev);
278 }
279 }
280 ChannelAudioEvent::AllNotesOff => {
281 for key in self.key_voices.iter_mut() {
282 let ev = KeyNoteEvent::AllOff;
283 key.event_cache.push(ev);
284 }
285 }
286 ChannelAudioEvent::AllNotesKilled => {
287 for key in self.key_voices.iter_mut() {
288 let ev = KeyNoteEvent::AllKilled;
289 key.event_cache.push(ev);
290 }
291 }
292 ChannelAudioEvent::ResetControl => {
293 self.reset_control();
294 }
295 ChannelAudioEvent::Control(control) => {
296 self.process_control_event(control);
297 }
298 ChannelAudioEvent::ProgramChange(preset) => {
299 self.params.set_preset(preset);
300 }
301 ChannelAudioEvent::SystemReset => {
302 for key in self.key_voices.iter_mut() {
303 key.event_cache.clear();
304 key.event_cache.push(KeyNoteEvent::AllKilled);
305 }
306 self.reset_control();
307 self.reset_program();
308 }
309 },
310 ChannelEvent::Config(config) => self.params.process_config_event(config),
311 }
312 }
313 }
314
315 pub fn get_channel_stats(&self) -> VoiceChannelStatsReader {
318 let stats = self.params.stats.clone();
319 VoiceChannelStatsReader::new(stats)
320 }
321}
322
323impl AudioPipe for VoiceChannel {
324 fn stream_params(&self) -> &AudioStreamParams {
325 &self.params.constant.stream_params
326 }
327
328 fn read_samples_unchecked(&mut self, out: &mut [f32]) {
329 self.push_key_events_and_render(out);
330 }
331}