Struct xsynth_render::AudioStreamParams

source ·
pub struct AudioStreamParams {
    pub sample_rate: u32,
    pub channels: ChannelCount,
}
Expand description

Parameters of the output audio.

Fields§

§sample_rate: u32§channels: ChannelCount

Implementations§

source§

impl AudioStreamParams

source

pub fn new(sample_rate: u32, channels: ChannelCount) -> AudioStreamParams

Examples found in repository?
examples/render.rs (line 74)
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
90
91
92
93
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 {
        group_options: ChannelGroupConfig {
            channel_init_options: Default::default(),
            channel_count: 16,
            drums_channels: vec![9],
            audio_params: AudioStreamParams::new(48000, 2.into()),
            parallelism: Default::default(),
        },
        use_limiter: true,
        audio_format: XSynthRenderAudioFormat::Wav,
    };

    let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
        SampleSoundfont::new(sfz, config.group_options.audio_params, Default::default()).unwrap(),
    )];

    xsynth_renderer(config, &midi, out)
        .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 88)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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 {
        group_options: ChannelGroupConfig {
            channel_init_options: Default::default(),
            channel_count: 16,
            drums_channels: vec![9],
            audio_params: AudioStreamParams::new(sample_rate, 2.into()),
            parallelism: if use_threadpool {
                Default::default()
            } else {
                ParallelismOptions {
                    channel: ThreadCount::None,
                    key: ThreadCount::None,
                }
            },
        },
        use_limiter: true,
        audio_format: XSynthRenderAudioFormat::Wav,
    };

    let soundfonts: Vec<Arc<dyn SoundfontBase>> = vec![Arc::new(
        SampleSoundfont::new(
            sf_path,
            config.group_options.audio_params,
            Default::default(),
        )
        .unwrap(),
    )];

    xsynth_renderer(config, &midi_path, &out_path)
        .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();
}

Trait Implementations§

source§

impl Clone for AudioStreamParams

source§

fn clone(&self) -> AudioStreamParams

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for AudioStreamParams

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Copy for AudioStreamParams

Auto Trait Implementations§

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> CloneToUninit for T
where T: Clone,

source§

default unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> CloneToUninit for T
where T: Copy,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. 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> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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.