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>

source

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());
}
source

pub fn with_channel_count(self, channels: u32) -> Self

source

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();
}
source

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();
}
source

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();
}
source

pub fn with_audio_channels(self, audio_channels: u16) -> Self

source

pub fn _with_audio_format(self, audio_format: XSynthRenderAudioFormat) -> Self

Unused because only WAV is supported

source

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
Hide additional 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();
}
source

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
Hide additional 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();
}
source

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
Hide additional 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();
}
source

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
Hide additional 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> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

source§

fn into_sample(self) -> T

source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.