xsynth_core/channel_group/config.rs
1use crate::{channel::ChannelInitOptions, AudioStreamParams};
2
3/// Controls the channel format that will be used in the synthesizer.
4#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
5#[cfg_attr(
6 feature = "serde",
7 derive(serde::Deserialize, serde::Serialize),
8 serde(rename_all = "snake_case")
9)]
10pub enum SynthFormat {
11 /// Standard MIDI format with 16 channels. Channel 10 will be used for percussion.
12 #[default]
13 Midi,
14
15 /// Creates a custom number of channels with the default settings.
16 Custom { channels: u32 },
17}
18
19/// Defines the multithreading options for each task that supports it.
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
21#[cfg_attr(
22 feature = "serde",
23 derive(serde::Deserialize, serde::Serialize),
24 serde(rename_all = "snake_case")
25)]
26pub enum ThreadCount {
27 /// No multithreading. Run everything on the same thread.
28 None,
29
30 /// Run with multithreading, with an automatically determined thread count.
31 /// Please read
32 /// [this](https://docs.rs/rayon-core/1.5.0/rayon_core/struct.ThreadPoolBuilder.html#method.num_threads)
33 /// for more information about the thread count selection.
34 Auto,
35
36 /// Run with multithreading, with the specified thread count.
37 Manual(usize),
38}
39
40/// Options regarding which parts of the ChannelGroup should be multithreaded.
41///
42/// Responsibilities of a channel: processing input events for the channel,
43/// dispatching per-key rendering of audio, applying filters to the final channel's audio
44///
45/// Responsibilities of a key: Rendering per-voice audio for all the voices stored in a
46/// key for a channel. This is generally the most compute intensive part of the synth.
47///
48/// Best practices:
49/// - As there are often 16 channels in MIDI, per-key multithreading can balance out the
50/// load more evenly between CPU cores.
51/// - However, per-key multithreading adds some overhead, so if the synth is invoked to
52/// render very small sample counts each time (e.g. sub 1 millisecond), not using per-key
53/// multithreading becomes more efficient.
54#[derive(Clone, Copy, Debug, PartialEq)]
55#[cfg_attr(
56 feature = "serde",
57 derive(serde::Deserialize, serde::Serialize),
58 serde(default)
59)]
60pub struct ParallelismOptions {
61 /// Render the MIDI channels parallel in a threadpool with the specified
62 /// thread count.
63 pub channel: ThreadCount,
64
65 /// Render the individisual keys of each channel parallel in a threadpool
66 /// with the specified thread count.
67 pub key: ThreadCount,
68}
69
70impl ParallelismOptions {
71 pub const AUTO_PER_KEY: Self = ParallelismOptions {
72 channel: ThreadCount::Auto,
73 key: ThreadCount::Auto,
74 };
75
76 pub const AUTO_PER_CHANNEL: Self = ParallelismOptions {
77 channel: ThreadCount::Auto,
78 key: ThreadCount::None,
79 };
80}
81
82impl Default for ParallelismOptions {
83 fn default() -> Self {
84 Self::AUTO_PER_KEY
85 }
86}
87
88/// Options for initializing a new ChannelGroup.
89#[derive(Clone, Debug, PartialEq)]
90#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
91pub struct ChannelGroupConfig {
92 /// Channel initialization options (same for all channels).
93 /// See the `ChannelInitOptions` documentation for more information.
94 pub channel_init_options: ChannelInitOptions,
95
96 /// Defines the format that the synthesizer will use. See the `SynthFormat`
97 /// documentation for more information.
98 ///
99 /// Default: `SynthFormat::Midi`
100 pub format: SynthFormat,
101
102 /// Parameters of the output audio.
103 /// See the `AudioStreamParams` documentation for more information.
104 pub audio_params: AudioStreamParams,
105
106 /// Options about the `ChannelGroup` instance's parallelism. See the `ParallelismOptions`
107 /// documentation for more information.
108 pub parallelism: ParallelismOptions,
109}