Skip to content

Commit

Permalink
Use crossbeam for sending events and audio samples in xsynth-render (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
MyBlackMIDIScore authored Aug 25, 2024
1 parent 8e0fa26 commit 7d9aa80
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 42 deletions.
57 changes: 33 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "2"
members = ["core", "clib", "soundfonts", "realtime", "render", "kdmapi"]

[workspace.package]
version = "0.3.0"
version = "0.3.1"
license = "LGPL-3.0"
edition = "2021"
homepage = "https://github.com/BlackMIDIDevs/xsynth"
Expand All @@ -24,6 +24,6 @@ inherits = "release"
debug = true

[workspace.dependencies]
xsynth-core = { version = "0.3.0", path = "core" }
xsynth-realtime = { version = "0.3.0", path = "realtime" }
xsynth-soundfonts = { version = "0.3.0", path = "soundfonts" }
xsynth-core = { version = "0.3.1", path = "core" }
xsynth-realtime = { version = "0.3.1", path = "realtime" }
xsynth-soundfonts = { version = "0.3.1", path = "soundfonts" }
3 changes: 2 additions & 1 deletion render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
clap = { version = "4.5.16", features = ["cargo"] }
crossbeam = "0.8.4"
20 changes: 19 additions & 1 deletion render/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use std::{
Arc,
},
thread,
time::{Duration, Instant},
};

use atomic_float::AtomicF64;
Expand Down Expand Up @@ -74,6 +75,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));

Expand All @@ -94,14 +103,19 @@ fn main() {
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices.load(Ordering::Relaxed));
for _ in 0..10 {
print!(" ");
}
if progress >= 100.0 {
println!();
break;
}
});
}

for batch in merged {
let now = Instant::now();

for batch in rcv {
if batch.delta > 0.0 {
synth.render_batch(batch.delta);
position.fetch_add(batch.delta, Ordering::Relaxed);
Expand Down Expand Up @@ -158,4 +172,8 @@ fn main() {
ChannelAudioEvent::ResetControl,
)));
synth.finalize();

let elapsed = now.elapsed();
thread::sleep(Duration::from_millis(200));
println!("Render time: {:?}", elapsed);
}
1 change: 0 additions & 1 deletion render/src/rendered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
28 changes: 17 additions & 11 deletions render/src/writer.rs
Original file line number Diff line number Diff line change
@@ -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<BufWriter<File>>,
sender: Sender<Vec<f32>>,
}

impl AudioFileWriter {
Expand All @@ -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::<Vec<f32>>();

pub fn write_samples(&mut self, samples: &mut Vec<f32>) {
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<f32>) {
self.sender.send(std::mem::take(samples)).unwrap();
}
}

0 comments on commit 7d9aa80

Please sign in to comment.