use std::convert::TryFrom;
pub struct SynthDescriptor {
pub reverb_active: bool,
pub chorus_active: bool,
pub drums_channel_active: bool,
pub polyphony: u16,
pub midi_channels: u8,
pub gain: f32,
pub audio_channels: u8,
pub audio_groups: u8,
pub sample_rate: f32,
pub min_note_length: u16,
}
impl Default for SynthDescriptor {
fn default() -> Self {
Self {
reverb_active: true,
chorus_active: true,
drums_channel_active: true,
polyphony: 256,
midi_channels: 16,
gain: 0.2,
audio_channels: 1,
audio_groups: 1,
sample_rate: 44100.0,
min_note_length: 10,
}
}
}
pub struct Settings {
pub(crate) drums_channel_active: bool,
pub(crate) polyphony: u16,
pub(crate) midi_channels: u8,
pub(crate) gain: f32,
pub(crate) audio_channels: u8,
pub(crate) audio_groups: u8,
pub(crate) sample_rate: f32,
pub(crate) min_note_length: u16,
}
impl Settings {
pub fn audio_channels_len(&self) -> u8 {
self.audio_channels
}
pub fn audio_groups_len(&self) -> u8 {
self.audio_groups
}
}
struct Range<T> {
min: T,
max: T,
}
#[derive(Debug)]
pub enum RangeError<T> {
ToBig { got: T, max: T },
ToSmall { got: T, min: T },
}
impl<T: PartialOrd + Copy> Range<T> {
fn check(&self, v: T) -> Result<T, RangeError<T>> {
if v < self.min {
Err(RangeError::ToSmall {
got: v,
min: self.min,
})
} else if v > self.max {
Err(RangeError::ToBig {
got: v,
max: self.max,
})
} else {
Ok(v)
}
}
}
static POLYPHONY_RANGE: Range<u16> = Range { min: 1, max: 65535 };
static GAIN_RANGE: Range<f32> = Range {
min: 0.0,
max: 10.0,
};
static AUDIO_CHANNELS_RANGE: Range<u8> = Range { min: 1, max: 128 };
static AUDIO_GROUPS_RANGE: Range<u8> = Range { min: 1, max: 128 };
static SAMPLE_RATE_RANGE: Range<f32> = Range {
min: 8000.0,
max: 96000.0,
};
#[derive(Debug)]
pub enum SettingsError {
PolyphonyRange(RangeError<u16>),
GainRange(RangeError<f32>),
AudioChannelRange(RangeError<u8>),
AudioGroupsRange(RangeError<u8>),
SammpleRateRange(RangeError<f32>),
MidiChannelsIsNotMultipleOf16,
}
impl TryFrom<SynthDescriptor> for Settings {
type Error = SettingsError;
fn try_from(desc: SynthDescriptor) -> Result<Self, Self::Error> {
let midi_channels = if desc.midi_channels % 16 != 0 {
log::warn!("Requested number of MIDI channels is not a multiple of 16. Increase the number of channels to the next multiple.");
return Err(SettingsError::MidiChannelsIsNotMultipleOf16);
} else {
desc.midi_channels
};
let polyphony = POLYPHONY_RANGE
.check(desc.polyphony)
.map_err(|e| SettingsError::PolyphonyRange(e))?;
let gain = GAIN_RANGE
.check(desc.gain)
.map_err(|e| SettingsError::GainRange(e))?;
let audio_channels = AUDIO_CHANNELS_RANGE
.check(desc.audio_channels)
.map_err(|e| SettingsError::AudioChannelRange(e))?;
let audio_groups = AUDIO_GROUPS_RANGE
.check(desc.audio_groups)
.map_err(|e| SettingsError::AudioGroupsRange(e))?;
let sample_rate = SAMPLE_RATE_RANGE
.check(desc.sample_rate)
.map_err(|e| SettingsError::SammpleRateRange(e))?;
let min_note_length = desc.min_note_length;
Ok(Self {
drums_channel_active: desc.drums_channel_active,
polyphony,
midi_channels,
gain,
audio_channels,
audio_groups,
sample_rate,
min_note_length,
})
}
}