Skip to content

Commit

Permalink
Better envelope curve control (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
MyBlackMIDIScore committed Aug 25, 2024
1 parent 1d85c6a commit 898a1c4
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 66 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ what is supported, please visit the `SampleSoundfont` documentation in `core`.

## License

XSynth is licensed under the GNU Lesser General Public License 3.0.
XSynth is licensed under the MIT license.
11 changes: 9 additions & 2 deletions core/examples/core_samples_per_second.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::{sync::Arc, time::Instant};

use xsynth_core::{
channel::{ChannelAudioEvent, ChannelConfigEvent, ChannelEvent, VoiceChannel},
soundfont::{Interpolator, SampleSoundfont, SoundfontBase, SoundfontInitOptions},
soundfont::{
EnvelopeCurveType, EnvelopeOptions, Interpolator, SampleSoundfont, SoundfontBase,
SoundfontInitOptions,
},
AudioPipe, AudioStreamParams, ChannelCount,
};

Expand Down Expand Up @@ -33,8 +36,12 @@ pub fn main() {
SoundfontInitOptions {
bank: None,
preset: None,
vol_envelope_options: EnvelopeOptions {
attack_curve: EnvelopeCurveType::Exponential,
decay_curve: EnvelopeCurveType::Exponential,
release_curve: EnvelopeCurveType::Exponential,
},
interpolator: Interpolator::Nearest,
linear_release: false,
use_effects: false,
},
)
Expand Down
57 changes: 51 additions & 6 deletions core/src/soundfont/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,53 @@ pub enum Interpolator {
Linear,
}

/// Type of curve to be used in certain envelope stages.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum EnvelopeCurveType {
/// Apply a linear curve to the envelope stage.
/// This option is supported by the attack, decay and release stages.
Linear,

/// Apply an exponential curve to the envelope stage.
/// The decay and release stages will use a concave curve, while the
/// attack stage will use a convex curve.
Exponential,
}

/// Options for the curves of a specific envelope.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
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`
pub attack_curve: EnvelopeCurveType,

/// Controls the type of curve of the decay envelope stage. See the
/// documentation of the `EnvelopeCurveType` enum for available options.
///
/// Default: `Linear`
pub decay_curve: EnvelopeCurveType,

/// Controls the type of curve of the release envelope stage. See the
/// documentation of the `EnvelopeCurveType` enum for available options.
///
/// Default: `Linear`
pub release_curve: EnvelopeCurveType,
}

impl Default for EnvelopeOptions {
fn default() -> Self {
Self {
attack_curve: EnvelopeCurveType::Exponential,
decay_curve: EnvelopeCurveType::Linear,
release_curve: EnvelopeCurveType::Linear,
}
}
}

/// Options for initializing/loading a new sample soundfont.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
Expand All @@ -29,11 +76,9 @@ pub struct SoundfontInitOptions {
/// Default: `None`
pub preset: Option<u8>,

/// If set to true, the voices generated using this soundfont will
/// release using a linear function instead of convex.
///
/// Default: `false`
pub linear_release: bool,
/// Configures the volume envelope curves in the dB scale. See the
/// documentation for `EnvelopeOptions` for more information.
pub vol_envelope_options: EnvelopeOptions,

/// If set to true, the voices generated using this soundfont will
/// be able to use signal processing effects. Currently this option
Expand All @@ -54,7 +99,7 @@ impl Default for SoundfontInitOptions {
Self {
bank: None,
preset: None,
linear_release: false,
vol_envelope_options: Default::default(),
use_effects: true,
interpolator: Interpolator::Nearest,
}
Expand Down
14 changes: 9 additions & 5 deletions core/src/soundfont/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ mod voice_spawners;
use utils::*;
use voice_spawners::*;

pub use config::{Interpolator, SoundfontInitOptions};
pub use config::*;

pub trait VoiceSpawner: Sync + Send {
fn spawn_voice(&self, control: &VoiceControlData) -> Box<dyn Voice>;
Expand Down Expand Up @@ -244,9 +244,10 @@ impl SampleSoundfont {
if !exists {
unique_envelope_params.push((
envelope_descriptor,
Arc::new(
envelope_descriptor.to_envelope_params(stream_params.sample_rate, options),
),
Arc::new(envelope_descriptor.to_envelope_params(
stream_params.sample_rate,
options.vol_envelope_options,
)),
));
}
}
Expand Down Expand Up @@ -397,7 +398,10 @@ impl SampleSoundfont {
for region in preset.regions {
let envelope_params = Arc::new(
envelope_descriptor_from_region_params(&region.ampeg_envelope)
.to_envelope_params(stream_params.sample_rate, options),
.to_envelope_params(
stream_params.sample_rate,
options.vol_envelope_options,
),
);

for key in region.keyrange.clone() {
Expand Down
Loading

0 comments on commit 898a1c4

Please sign in to comment.