diff --git a/README.md b/README.md index 919b6cc..da58369 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,4 @@ what is supported, please visit the `SampleSoundfont` documentation in `core`. ## License -XSynth is licensed under the MIT license. +XSynth is licensed under the GNU Lesser General Public License 3.0. diff --git a/core/src/channel_group/config.rs b/core/src/channel_group/config.rs index fe1397b..4057891 100644 --- a/core/src/channel_group/config.rs +++ b/core/src/channel_group/config.rs @@ -6,7 +6,7 @@ use crate::{channel::ChannelInitOptions, AudioStreamParams}; pub enum SynthFormat { /// Standard MIDI format with 16 channels. Channel 10 will be used for percussion. #[default] - MidiSingle, + Midi, /// Creates a custom number of channels with the default settings. Custom { channels: u32 }, @@ -83,6 +83,8 @@ pub struct ChannelGroupConfig { /// Defines the format that the synthesizer will use. See the `SynthFormat` /// documentation for more information. + /// + /// Default: `SynthFormat::Midi` pub format: SynthFormat, /// Parameters of the output audio. diff --git a/core/src/channel_group/mod.rs b/core/src/channel_group/mod.rs index 5f78a46..3b8ce65 100644 --- a/core/src/channel_group/mod.rs +++ b/core/src/channel_group/mod.rs @@ -60,7 +60,7 @@ impl ChannelGroup { }; let channel_count = match config.format { - SynthFormat::MidiSingle => 16, + SynthFormat::Midi => 16, SynthFormat::Custom { channels } => channels, }; @@ -74,7 +74,7 @@ impl ChannelGroup { sample_cache_vecs.push(Vec::new()); } - if config.format == SynthFormat::MidiSingle { + if config.format == SynthFormat::Midi { channels[9].push_events_iter(std::iter::once(ChannelEvent::Config( ChannelConfigEvent::SetPercussionMode(true), ))); diff --git a/core/src/soundfont/config.rs b/core/src/soundfont/config.rs index 265c004..079ac64 100644 --- a/core/src/soundfont/config.rs +++ b/core/src/soundfont/config.rs @@ -34,7 +34,7 @@ pub struct EnvelopeOptions { /// Controls the type of curve of the attack envelope stage. See the /// documentation of the `EnvelopeCurveType` enum for available options. /// - /// Default: `Convex` + /// Default: `Exponential` pub attack_curve: EnvelopeCurveType, /// Controls the type of curve of the decay envelope stage. See the @@ -76,7 +76,7 @@ pub struct SoundfontInitOptions { /// Default: `None` pub preset: Option, - /// Configures the volume envelope curves in the dB scale. See the + /// Configures the volume envelope curves in dB units. See the /// documentation for `EnvelopeOptions` for more information. pub vol_envelope_options: EnvelopeOptions, diff --git a/realtime/src/config.rs b/realtime/src/config.rs index 4c2da1f..4cbb88a 100644 --- a/realtime/src/config.rs +++ b/realtime/src/config.rs @@ -1,5 +1,8 @@ use std::ops::RangeInclusive; -pub use xsynth_core::{channel::ChannelInitOptions, channel_group::ThreadCount}; +pub use xsynth_core::{ + channel::ChannelInitOptions, + channel_group::{SynthFormat, ThreadCount}, +}; /// Options for initializing a new RealtimeSynth. #[derive(Clone, Debug, PartialEq)] @@ -14,12 +17,11 @@ pub struct XSynthRealtimeConfig { /// Default: `10.0` pub render_window_ms: f64, - /// Amount of VoiceChannel objects to be created (Number of MIDI channels). - /// The MIDI 1 spec uses 16 channels. If the channel count is 16 or - /// greater, then MIDI channel 10 will be set as the percussion channel. + /// Defines the format that the synthesizer will use. See the `SynthFormat` + /// documentation for more information. /// - /// Default: `16` - pub channel_count: u32, + /// Default: `SynthFormat::Midi` + pub format: SynthFormat, /// Controls the multithreading used for rendering per-voice audio for all /// the voices stored in a key for a channel. See the `ThreadCount` documentation @@ -39,7 +41,7 @@ impl Default for XSynthRealtimeConfig { Self { channel_init_options: Default::default(), render_window_ms: 10.0, - channel_count: 16, + format: Default::default(), multithreading: ThreadCount::None, ignore_range: 0..=0, } diff --git a/realtime/src/realtime_synth.rs b/realtime/src/realtime_synth.rs index 5ff012b..06a01f0 100644 --- a/realtime/src/realtime_synth.rs +++ b/realtime/src/realtime_synth.rs @@ -16,6 +16,7 @@ use crossbeam_channel::{bounded, unbounded}; use xsynth_core::{ buffered_renderer::{BufferedRenderer, BufferedRendererStatsReader}, channel::{ChannelConfigEvent, ChannelEvent, VoiceChannel}, + channel_group::SynthFormat, effects::VolumeLimiter, helpers::{prepapre_cache_vec, sum_simd}, AudioPipe, AudioStreamParams, FunctionAudioPipe, @@ -148,11 +149,16 @@ impl RealtimeSynth { )), }; - let (output_sender, output_receiver) = bounded::>(config.channel_count as usize); + let channel_count = match config.format { + SynthFormat::Midi => 16, + SynthFormat::Custom { channels } => channels, + }; + + let (output_sender, output_receiver) = bounded::>(channel_count as usize); let mut thread_handles = vec![]; - for _ in 0u32..(config.channel_count) { + for _ in 0u32..channel_count { let mut channel = VoiceChannel::new(config.channel_init_options, stream_params, pool.clone()); let stats = channel.get_channel_stats(); @@ -183,7 +189,7 @@ impl RealtimeSynth { thread_handles.push(join_handle); } - if config.channel_count >= 16 { + if config.format == SynthFormat::Midi { senders[9] .send(ChannelEvent::Config(ChannelConfigEvent::SetPercussionMode( true, @@ -192,7 +198,7 @@ impl RealtimeSynth { } let mut vec_cache: VecDeque> = VecDeque::new(); - for _ in 0..(config.channel_count) { + for _ in 0..channel_count { vec_cache.push_front(Vec::new()); } @@ -200,7 +206,6 @@ impl RealtimeSynth { let total_voice_count = stats.voice_count.clone(); - let channel_count = config.channel_count; let render = FunctionAudioPipe::new(stream_params, move |out| { for sender in command_senders.iter() { let mut buf = vec_cache.pop_front().unwrap(); diff --git a/render/src/config.rs b/render/src/config.rs index 5a16282..1aa7755 100644 --- a/render/src/config.rs +++ b/render/src/config.rs @@ -133,7 +133,7 @@ impl State { .copied() .unwrap_or(true), }, - format: SynthFormat::MidiSingle, + format: SynthFormat::Midi, audio_params: AudioStreamParams::new( matches.get_one("sample rate").copied().unwrap_or(48000), matches