Struct xsynth_render::XSynthRenderBuilder
source · pub struct XSynthRenderBuilder<'a, StatsCallback: FnMut(XSynthRenderStats)> { /* private fields */ }
Expand description
Helper struct to create an XSynthRender object and render a MIDI file.
Initialize using the xsynth_renderer
function.
Implementations§
source§impl<'a, ProgressCallback: FnMut(XSynthRenderStats)> XSynthRenderBuilder<'a, ProgressCallback>
impl<'a, ProgressCallback: FnMut(XSynthRenderStats)> XSynthRenderBuilder<'a, ProgressCallback>
sourcepub fn with_config(self, config: XSynthRenderConfig) -> Self
pub fn with_config(self, config: XSynthRenderConfig) -> Self
Examples found in repository?
examples/render.rs (line 81)
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
fn main() {
let args = std::env::args().collect::<Vec<String>>();
let (Some(midi), Some(sfz)) = (
args.get(1)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_MIDI").ok()),
args.get(2)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_SF").ok()),
) else {
println!(
"Usage: {} [midi] [sfz/sf2]",
std::env::current_exe()
.unwrap_or("example".into())
.display()
);
return;
};
let out = "out.wav";
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
thread::spawn(move || loop {
thread::sleep(Duration::from_millis(100));
let pos = position_thread.load(Ordering::Relaxed);
let time = Duration::from_secs_f64(pos);
println!(
"Progress: {:?}, Voice Count: {}",
time,
voices_thread.load(Ordering::Relaxed)
);
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sfz,
AudioStreamParams::new(
config.sample_rate,
ChannelCount::from(config.audio_channels),
),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi, out)
.with_config(config)
.add_soundfonts(soundfonts)
.with_layer_count(Some(128))
.with_progress_callback(callback)
.run()
.unwrap();
println!("Render time: {} seconds", render_time.elapsed().as_secs());
}
pub fn with_channel_count(self, channels: u32) -> Self
sourcepub fn use_threadpool(self, use_threadpool: bool) -> Self
pub fn use_threadpool(self, use_threadpool: bool) -> Self
Examples found in repository?
examples/render_dialog.rs (line 92)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
fn main() {
println!("--- FILE PATHS ---");
let midi_path = read_input("Enter MIDI path");
let sf_path = read_input("Enter SFZ/SF2 path");
let out_path = read_input("Enter output path");
println!("\n--- RENDER OPTIONS ---");
let sample_rate: u32 = read_input("Enter sample rate (in Hz)").parse().unwrap();
let use_threadpool = read_input_bool("Use threadpool? (y/n)");
let use_limiter = read_input_bool("Use audio limiter? (y/n)");
let layers = match read_input("Enter layer count").parse::<usize>().unwrap() {
0 => None,
voices => Some(voices),
};
io::stdout().lock().flush().unwrap();
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
let length = get_midi_length(&midi_path);
thread::spawn(move || loop {
let pos = position_thread.load(Ordering::Relaxed);
let progress = (pos / length) * 100.0 + 0.0004;
print!("\rProgress: [");
let bars = progress as u8 / 5;
for _ in 0..bars {
print!("=");
}
for _ in 0..(20 - bars) {
print!(" ");
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices_thread.load(Ordering::Relaxed));
if progress >= 100.0 {
break;
}
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sf_path,
AudioStreamParams::new(sample_rate, ChannelCount::from(2)),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi_path, &out_path)
.with_sample_rate(sample_rate)
.use_threadpool(use_threadpool)
.use_limiter(use_limiter)
.add_soundfonts(soundfonts)
.with_layer_count(layers)
.with_progress_callback(callback)
.run()
.unwrap();
println!(
"\n\n--- RENDER FINISHED ---\nRender time: {} seconds | Max Voice Count: {} voices",
render_time.elapsed().as_secs(),
max_voices.load(Ordering::Relaxed)
);
pause();
}
sourcepub fn use_limiter(self, use_limiter: bool) -> Self
pub fn use_limiter(self, use_limiter: bool) -> Self
Examples found in repository?
examples/render_dialog.rs (line 93)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
fn main() {
println!("--- FILE PATHS ---");
let midi_path = read_input("Enter MIDI path");
let sf_path = read_input("Enter SFZ/SF2 path");
let out_path = read_input("Enter output path");
println!("\n--- RENDER OPTIONS ---");
let sample_rate: u32 = read_input("Enter sample rate (in Hz)").parse().unwrap();
let use_threadpool = read_input_bool("Use threadpool? (y/n)");
let use_limiter = read_input_bool("Use audio limiter? (y/n)");
let layers = match read_input("Enter layer count").parse::<usize>().unwrap() {
0 => None,
voices => Some(voices),
};
io::stdout().lock().flush().unwrap();
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
let length = get_midi_length(&midi_path);
thread::spawn(move || loop {
let pos = position_thread.load(Ordering::Relaxed);
let progress = (pos / length) * 100.0 + 0.0004;
print!("\rProgress: [");
let bars = progress as u8 / 5;
for _ in 0..bars {
print!("=");
}
for _ in 0..(20 - bars) {
print!(" ");
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices_thread.load(Ordering::Relaxed));
if progress >= 100.0 {
break;
}
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sf_path,
AudioStreamParams::new(sample_rate, ChannelCount::from(2)),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi_path, &out_path)
.with_sample_rate(sample_rate)
.use_threadpool(use_threadpool)
.use_limiter(use_limiter)
.add_soundfonts(soundfonts)
.with_layer_count(layers)
.with_progress_callback(callback)
.run()
.unwrap();
println!(
"\n\n--- RENDER FINISHED ---\nRender time: {} seconds | Max Voice Count: {} voices",
render_time.elapsed().as_secs(),
max_voices.load(Ordering::Relaxed)
);
pause();
}
sourcepub fn with_sample_rate(self, sample_rate: u32) -> Self
pub fn with_sample_rate(self, sample_rate: u32) -> Self
Examples found in repository?
examples/render_dialog.rs (line 91)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
fn main() {
println!("--- FILE PATHS ---");
let midi_path = read_input("Enter MIDI path");
let sf_path = read_input("Enter SFZ/SF2 path");
let out_path = read_input("Enter output path");
println!("\n--- RENDER OPTIONS ---");
let sample_rate: u32 = read_input("Enter sample rate (in Hz)").parse().unwrap();
let use_threadpool = read_input_bool("Use threadpool? (y/n)");
let use_limiter = read_input_bool("Use audio limiter? (y/n)");
let layers = match read_input("Enter layer count").parse::<usize>().unwrap() {
0 => None,
voices => Some(voices),
};
io::stdout().lock().flush().unwrap();
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
let length = get_midi_length(&midi_path);
thread::spawn(move || loop {
let pos = position_thread.load(Ordering::Relaxed);
let progress = (pos / length) * 100.0 + 0.0004;
print!("\rProgress: [");
let bars = progress as u8 / 5;
for _ in 0..bars {
print!("=");
}
for _ in 0..(20 - bars) {
print!(" ");
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices_thread.load(Ordering::Relaxed));
if progress >= 100.0 {
break;
}
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sf_path,
AudioStreamParams::new(sample_rate, ChannelCount::from(2)),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi_path, &out_path)
.with_sample_rate(sample_rate)
.use_threadpool(use_threadpool)
.use_limiter(use_limiter)
.add_soundfonts(soundfonts)
.with_layer_count(layers)
.with_progress_callback(callback)
.run()
.unwrap();
println!(
"\n\n--- RENDER FINISHED ---\nRender time: {} seconds | Max Voice Count: {} voices",
render_time.elapsed().as_secs(),
max_voices.load(Ordering::Relaxed)
);
pause();
}
pub fn with_audio_channels(self, audio_channels: u16) -> Self
sourcepub fn _with_audio_format(self, audio_format: XSynthRenderAudioFormat) -> Self
pub fn _with_audio_format(self, audio_format: XSynthRenderAudioFormat) -> Self
Unused because only WAV is supported
sourcepub fn with_layer_count(self, layers: Option<usize>) -> Self
pub fn with_layer_count(self, layers: Option<usize>) -> Self
Examples found in repository?
examples/render.rs (line 83)
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
fn main() {
let args = std::env::args().collect::<Vec<String>>();
let (Some(midi), Some(sfz)) = (
args.get(1)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_MIDI").ok()),
args.get(2)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_SF").ok()),
) else {
println!(
"Usage: {} [midi] [sfz/sf2]",
std::env::current_exe()
.unwrap_or("example".into())
.display()
);
return;
};
let out = "out.wav";
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
thread::spawn(move || loop {
thread::sleep(Duration::from_millis(100));
let pos = position_thread.load(Ordering::Relaxed);
let time = Duration::from_secs_f64(pos);
println!(
"Progress: {:?}, Voice Count: {}",
time,
voices_thread.load(Ordering::Relaxed)
);
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sfz,
AudioStreamParams::new(
config.sample_rate,
ChannelCount::from(config.audio_channels),
),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi, out)
.with_config(config)
.add_soundfonts(soundfonts)
.with_layer_count(Some(128))
.with_progress_callback(callback)
.run()
.unwrap();
println!("Render time: {} seconds", render_time.elapsed().as_secs());
}
More examples
examples/render_dialog.rs (line 95)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
fn main() {
println!("--- FILE PATHS ---");
let midi_path = read_input("Enter MIDI path");
let sf_path = read_input("Enter SFZ/SF2 path");
let out_path = read_input("Enter output path");
println!("\n--- RENDER OPTIONS ---");
let sample_rate: u32 = read_input("Enter sample rate (in Hz)").parse().unwrap();
let use_threadpool = read_input_bool("Use threadpool? (y/n)");
let use_limiter = read_input_bool("Use audio limiter? (y/n)");
let layers = match read_input("Enter layer count").parse::<usize>().unwrap() {
0 => None,
voices => Some(voices),
};
io::stdout().lock().flush().unwrap();
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
let length = get_midi_length(&midi_path);
thread::spawn(move || loop {
let pos = position_thread.load(Ordering::Relaxed);
let progress = (pos / length) * 100.0 + 0.0004;
print!("\rProgress: [");
let bars = progress as u8 / 5;
for _ in 0..bars {
print!("=");
}
for _ in 0..(20 - bars) {
print!(" ");
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices_thread.load(Ordering::Relaxed));
if progress >= 100.0 {
break;
}
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sf_path,
AudioStreamParams::new(sample_rate, ChannelCount::from(2)),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi_path, &out_path)
.with_sample_rate(sample_rate)
.use_threadpool(use_threadpool)
.use_limiter(use_limiter)
.add_soundfonts(soundfonts)
.with_layer_count(layers)
.with_progress_callback(callback)
.run()
.unwrap();
println!(
"\n\n--- RENDER FINISHED ---\nRender time: {} seconds | Max Voice Count: {} voices",
render_time.elapsed().as_secs(),
max_voices.load(Ordering::Relaxed)
);
pause();
}
sourcepub fn add_soundfonts(self, soundfonts: Vec<Arc<dyn SoundfontBase>>) -> Self
pub fn add_soundfonts(self, soundfonts: Vec<Arc<dyn SoundfontBase>>) -> Self
Examples found in repository?
examples/render.rs (line 82)
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
fn main() {
let args = std::env::args().collect::<Vec<String>>();
let (Some(midi), Some(sfz)) = (
args.get(1)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_MIDI").ok()),
args.get(2)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_SF").ok()),
) else {
println!(
"Usage: {} [midi] [sfz/sf2]",
std::env::current_exe()
.unwrap_or("example".into())
.display()
);
return;
};
let out = "out.wav";
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
thread::spawn(move || loop {
thread::sleep(Duration::from_millis(100));
let pos = position_thread.load(Ordering::Relaxed);
let time = Duration::from_secs_f64(pos);
println!(
"Progress: {:?}, Voice Count: {}",
time,
voices_thread.load(Ordering::Relaxed)
);
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sfz,
AudioStreamParams::new(
config.sample_rate,
ChannelCount::from(config.audio_channels),
),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi, out)
.with_config(config)
.add_soundfonts(soundfonts)
.with_layer_count(Some(128))
.with_progress_callback(callback)
.run()
.unwrap();
println!("Render time: {} seconds", render_time.elapsed().as_secs());
}
More examples
examples/render_dialog.rs (line 94)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
fn main() {
println!("--- FILE PATHS ---");
let midi_path = read_input("Enter MIDI path");
let sf_path = read_input("Enter SFZ/SF2 path");
let out_path = read_input("Enter output path");
println!("\n--- RENDER OPTIONS ---");
let sample_rate: u32 = read_input("Enter sample rate (in Hz)").parse().unwrap();
let use_threadpool = read_input_bool("Use threadpool? (y/n)");
let use_limiter = read_input_bool("Use audio limiter? (y/n)");
let layers = match read_input("Enter layer count").parse::<usize>().unwrap() {
0 => None,
voices => Some(voices),
};
io::stdout().lock().flush().unwrap();
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
let length = get_midi_length(&midi_path);
thread::spawn(move || loop {
let pos = position_thread.load(Ordering::Relaxed);
let progress = (pos / length) * 100.0 + 0.0004;
print!("\rProgress: [");
let bars = progress as u8 / 5;
for _ in 0..bars {
print!("=");
}
for _ in 0..(20 - bars) {
print!(" ");
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices_thread.load(Ordering::Relaxed));
if progress >= 100.0 {
break;
}
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sf_path,
AudioStreamParams::new(sample_rate, ChannelCount::from(2)),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi_path, &out_path)
.with_sample_rate(sample_rate)
.use_threadpool(use_threadpool)
.use_limiter(use_limiter)
.add_soundfonts(soundfonts)
.with_layer_count(layers)
.with_progress_callback(callback)
.run()
.unwrap();
println!(
"\n\n--- RENDER FINISHED ---\nRender time: {} seconds | Max Voice Count: {} voices",
render_time.elapsed().as_secs(),
max_voices.load(Ordering::Relaxed)
);
pause();
}
sourcepub fn with_progress_callback<F: FnMut(XSynthRenderStats)>(
self,
stats_callback: F,
) -> XSynthRenderBuilder<'a, F>
pub fn with_progress_callback<F: FnMut(XSynthRenderStats)>( self, stats_callback: F, ) -> XSynthRenderBuilder<'a, F>
Sets a callback function to be used to update the render statistics.
Examples found in repository?
examples/render.rs (line 84)
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
fn main() {
let args = std::env::args().collect::<Vec<String>>();
let (Some(midi), Some(sfz)) = (
args.get(1)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_MIDI").ok()),
args.get(2)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_SF").ok()),
) else {
println!(
"Usage: {} [midi] [sfz/sf2]",
std::env::current_exe()
.unwrap_or("example".into())
.display()
);
return;
};
let out = "out.wav";
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
thread::spawn(move || loop {
thread::sleep(Duration::from_millis(100));
let pos = position_thread.load(Ordering::Relaxed);
let time = Duration::from_secs_f64(pos);
println!(
"Progress: {:?}, Voice Count: {}",
time,
voices_thread.load(Ordering::Relaxed)
);
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sfz,
AudioStreamParams::new(
config.sample_rate,
ChannelCount::from(config.audio_channels),
),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi, out)
.with_config(config)
.add_soundfonts(soundfonts)
.with_layer_count(Some(128))
.with_progress_callback(callback)
.run()
.unwrap();
println!("Render time: {} seconds", render_time.elapsed().as_secs());
}
More examples
examples/render_dialog.rs (line 96)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
fn main() {
println!("--- FILE PATHS ---");
let midi_path = read_input("Enter MIDI path");
let sf_path = read_input("Enter SFZ/SF2 path");
let out_path = read_input("Enter output path");
println!("\n--- RENDER OPTIONS ---");
let sample_rate: u32 = read_input("Enter sample rate (in Hz)").parse().unwrap();
let use_threadpool = read_input_bool("Use threadpool? (y/n)");
let use_limiter = read_input_bool("Use audio limiter? (y/n)");
let layers = match read_input("Enter layer count").parse::<usize>().unwrap() {
0 => None,
voices => Some(voices),
};
io::stdout().lock().flush().unwrap();
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
let length = get_midi_length(&midi_path);
thread::spawn(move || loop {
let pos = position_thread.load(Ordering::Relaxed);
let progress = (pos / length) * 100.0 + 0.0004;
print!("\rProgress: [");
let bars = progress as u8 / 5;
for _ in 0..bars {
print!("=");
}
for _ in 0..(20 - bars) {
print!(" ");
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices_thread.load(Ordering::Relaxed));
if progress >= 100.0 {
break;
}
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sf_path,
AudioStreamParams::new(sample_rate, ChannelCount::from(2)),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi_path, &out_path)
.with_sample_rate(sample_rate)
.use_threadpool(use_threadpool)
.use_limiter(use_limiter)
.add_soundfonts(soundfonts)
.with_layer_count(layers)
.with_progress_callback(callback)
.run()
.unwrap();
println!(
"\n\n--- RENDER FINISHED ---\nRender time: {} seconds | Max Voice Count: {} voices",
render_time.elapsed().as_secs(),
max_voices.load(Ordering::Relaxed)
);
pause();
}
sourcepub fn run(self) -> Result<(), XSynthRenderError>
pub fn run(self) -> Result<(), XSynthRenderError>
Examples found in repository?
examples/render.rs (line 85)
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
fn main() {
let args = std::env::args().collect::<Vec<String>>();
let (Some(midi), Some(sfz)) = (
args.get(1)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_MIDI").ok()),
args.get(2)
.cloned()
.or_else(|| std::env::var("XSYNTH_EXAMPLE_SF").ok()),
) else {
println!(
"Usage: {} [midi] [sfz/sf2]",
std::env::current_exe()
.unwrap_or("example".into())
.display()
);
return;
};
let out = "out.wav";
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
thread::spawn(move || loop {
thread::sleep(Duration::from_millis(100));
let pos = position_thread.load(Ordering::Relaxed);
let time = Duration::from_secs_f64(pos);
println!(
"Progress: {:?}, Voice Count: {}",
time,
voices_thread.load(Ordering::Relaxed)
);
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sfz,
AudioStreamParams::new(
config.sample_rate,
ChannelCount::from(config.audio_channels),
),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi, out)
.with_config(config)
.add_soundfonts(soundfonts)
.with_layer_count(Some(128))
.with_progress_callback(callback)
.run()
.unwrap();
println!("Render time: {} seconds", render_time.elapsed().as_secs());
}
More examples
examples/render_dialog.rs (line 97)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
fn main() {
println!("--- FILE PATHS ---");
let midi_path = read_input("Enter MIDI path");
let sf_path = read_input("Enter SFZ/SF2 path");
let out_path = read_input("Enter output path");
println!("\n--- RENDER OPTIONS ---");
let sample_rate: u32 = read_input("Enter sample rate (in Hz)").parse().unwrap();
let use_threadpool = read_input_bool("Use threadpool? (y/n)");
let use_limiter = read_input_bool("Use audio limiter? (y/n)");
let layers = match read_input("Enter layer count").parse::<usize>().unwrap() {
0 => None,
voices => Some(voices),
};
io::stdout().lock().flush().unwrap();
println!("\n--- STARTING RENDER ---");
let render_time = Instant::now();
let position = Arc::new(AtomicF64::new(0.0));
let voices = Arc::new(AtomicU64::new(0));
let max_voices = Arc::new(AtomicU64::new(0));
let callback = |stats: XSynthRenderStats| {
position.store(stats.progress, Ordering::Relaxed);
voices.store(stats.voice_count, Ordering::Relaxed);
if stats.voice_count > max_voices.load(Ordering::Relaxed) {
max_voices.store(stats.voice_count, Ordering::Relaxed);
}
};
let position_thread = position.clone();
let voices_thread = voices.clone();
let length = get_midi_length(&midi_path);
thread::spawn(move || loop {
let pos = position_thread.load(Ordering::Relaxed);
let progress = (pos / length) * 100.0 + 0.0004;
print!("\rProgress: [");
let bars = progress as u8 / 5;
for _ in 0..bars {
print!("=");
}
for _ in 0..(20 - bars) {
print!(" ");
}
print!("] {progress:.3}% | ");
print!("Voice Count: {}", voices_thread.load(Ordering::Relaxed));
if progress >= 100.0 {
break;
}
});
let config: XSynthRenderConfig = Default::default();
let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
SampleSoundfont::new(
sf_path,
AudioStreamParams::new(sample_rate, ChannelCount::from(2)),
config.sf_init_options,
)
.unwrap(),
)];
xsynth_renderer(&midi_path, &out_path)
.with_sample_rate(sample_rate)
.use_threadpool(use_threadpool)
.use_limiter(use_limiter)
.add_soundfonts(soundfonts)
.with_layer_count(layers)
.with_progress_callback(callback)
.run()
.unwrap();
println!(
"\n\n--- RENDER FINISHED ---\nRender time: {} seconds | Max Voice Count: {} voices",
render_time.elapsed().as_secs(),
max_voices.load(Ordering::Relaxed)
);
pause();
}
Auto Trait Implementations§
impl<'a, StatsCallback> Freeze for XSynthRenderBuilder<'a, StatsCallback>where
StatsCallback: Freeze,
impl<'a, StatsCallback> !RefUnwindSafe for XSynthRenderBuilder<'a, StatsCallback>
impl<'a, StatsCallback> Send for XSynthRenderBuilder<'a, StatsCallback>where
StatsCallback: Send,
impl<'a, StatsCallback> Sync for XSynthRenderBuilder<'a, StatsCallback>where
StatsCallback: Sync,
impl<'a, StatsCallback> Unpin for XSynthRenderBuilder<'a, StatsCallback>where
StatsCallback: Unpin,
impl<'a, StatsCallback> !UnwindSafe for XSynthRenderBuilder<'a, StatsCallback>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more