From 198cb06a733244ce38b27b86cd0303edb606b0bc Mon Sep 17 00:00:00 2001 From: MyBlackMIDIScore Date: Sun, 25 Aug 2024 14:21:52 +0300 Subject: [PATCH] Use crossbeam for sending events and audio samples in xsynth-render --- Cargo.lock | 45 +++++++++++++++++++++++++----------------- render/Cargo.toml | 3 ++- render/src/main.rs | 13 +++++++++++- render/src/rendered.rs | 1 - render/src/writer.rs | 28 +++++++++++++++----------- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bec817..b62ebcc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,6 +432,19 @@ dependencies = [ "itertools", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + [[package]] name = "crossbeam-channel" version = "0.5.13" @@ -443,26 +456,30 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] @@ -905,15 +922,6 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - [[package]] name = "midi-toolkit-rs" version = "0.1.0" @@ -2329,6 +2337,7 @@ version = "0.3.0" dependencies = [ "atomic_float", "clap 4.5.16", + "crossbeam", "crossbeam-channel", "hound", "midi-toolkit-rs", diff --git a/render/Cargo.toml b/render/Cargo.toml index 665d399..9cee066 100644 --- a/render/Cargo.toml +++ b/render/Cargo.toml @@ -21,4 +21,5 @@ midi-toolkit-rs = "0.1.0" spin_sleep = "1.2.1" atomic_float = "1.0.0" thiserror = "1.0.63" -clap = { version = "4.5.16", features = ["cargo"] } \ No newline at end of file +clap = { version = "4.5.16", features = ["cargo"] } +crossbeam = "0.8.4" diff --git a/render/src/main.rs b/render/src/main.rs index 5af3588..095ee81 100644 --- a/render/src/main.rs +++ b/render/src/main.rs @@ -74,6 +74,14 @@ fn main() { |>unwrap_items() ); + let (snd, rcv) = crossbeam_channel::bounded(100); + + thread::spawn(move || { + for batch in merged { + snd.send(batch).unwrap(); + } + }); + let position = Arc::new(AtomicF64::new(0.0)); let voices = Arc::new(AtomicU64::new(0)); @@ -94,6 +102,9 @@ fn main() { } print!("] {progress:.3}% | "); print!("Voice Count: {}", voices.load(Ordering::Relaxed)); + for _ in 0..10 { + print!(" "); + } if progress >= 100.0 { println!(); break; @@ -101,7 +112,7 @@ fn main() { }); } - for batch in merged { + for batch in rcv { if batch.delta > 0.0 { synth.render_batch(batch.delta); position.fetch_add(batch.delta, Ordering::Relaxed); diff --git a/render/src/rendered.rs b/render/src/rendered.rs index 5368dbd..1f156ed 100644 --- a/render/src/rendered.rs +++ b/render/src/rendered.rs @@ -124,7 +124,6 @@ impl XSynthRender { self.audio_writer .write_samples(&mut self.render_elements.output_vec); } - self.audio_writer.finalize(); } /// Returns the active voice count of the MIDI synthesizer. diff --git a/render/src/writer.rs b/render/src/writer.rs index 0b397fd..9ac4115 100644 --- a/render/src/writer.rs +++ b/render/src/writer.rs @@ -1,11 +1,12 @@ use crate::config::XSynthRenderConfig; -use std::{fs::File, io::BufWriter, path::PathBuf}; +use std::{path::PathBuf, thread}; +use crossbeam_channel::Sender; use hound::{WavSpec, WavWriter}; pub struct AudioFileWriter { - writer: WavWriter>, + sender: Sender>, } impl AudioFileWriter { @@ -16,18 +17,23 @@ impl AudioFileWriter { bits_per_sample: 32, sample_format: hound::SampleFormat::Float, }; - let writer = WavWriter::create(path, spec).unwrap(); + let mut writer = WavWriter::create(path, spec).unwrap(); - Self { writer } - } + let (snd, rcv) = crossbeam_channel::unbounded::>(); - pub fn write_samples(&mut self, samples: &mut Vec) { - for s in samples.drain(0..) { - self.writer.write_sample(s).unwrap(); - } + thread::spawn(move || { + for batch in rcv { + for s in batch { + writer.write_sample(s).unwrap(); + } + } + writer.finalize().unwrap(); + }); + + Self { sender: snd } } - pub fn finalize(self) { - self.writer.finalize().unwrap(); + pub fn write_samples(&mut self, samples: &mut Vec) { + self.sender.send(std::mem::take(samples)).unwrap(); } }