use crate::config::validate_output_gain;
use crate::effects::alien::AlienConfig;
use crate::effects::punch::PunchConfig;
use crate::effects::reverb::ReverbConfig;
use crate::effects::warm::WarmConfig;
use crate::midi::MidiEvent;
use crate::{Error, EventProblem, ProcessorConfig, ResynthesisConfig};
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(
all(feature = "wasm", target_arch = "wasm32"),
derive(serde::Serialize, serde::Deserialize, tsify::Tsify),
serde(rename_all = "camelCase", tag = "type", content = "value")
)]
pub enum ControlEvent {
Configure(ProcessorConfig),
Resynthesis(ResynthesisConfig),
Punch(PunchConfig),
Warm(WarmConfig),
Alien(AlienConfig),
Reverb(ReverbConfig),
OutputGain(f32),
Midi(MidiEvent),
CorrectionMidi(MidiEvent),
Reset,
}
impl ControlEvent {
pub fn validate(self) -> Result<(), Error> {
match self {
Self::Configure(config) => config.validate(),
Self::Resynthesis(config) => config.validate(),
Self::Punch(config) => config.validate(),
Self::Warm(config) => config.validate(),
Self::Alien(config) => config.validate(),
Self::Reverb(config) => config.validate(),
Self::OutputGain(gain) => validate_output_gain(gain),
Self::Midi(event) | Self::CorrectionMidi(event) => event.validate(),
Self::Reset => Ok(()),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(
all(feature = "wasm", target_arch = "wasm32"),
derive(serde::Serialize, serde::Deserialize, tsify::Tsify),
serde(rename_all = "camelCase")
)]
pub struct TimedEvent {
pub offset: usize,
pub event: ControlEvent,
}
pub(crate) struct ValidatedEvents<'a> {
remaining: &'a [TimedEvent],
}
pub(crate) struct ValidatedEvent(ControlEvent);
impl ValidatedEvent {
pub(crate) fn into_inner(self) -> ControlEvent {
self.0
}
}
impl<'a> ValidatedEvents<'a> {
pub(crate) fn new(events: &'a [TimedEvent], frames: usize) -> Result<Self, Error> {
let mut previous = 0;
for (index, event) in events.iter().enumerate() {
let problem = if event.offset >= frames {
Some(EventProblem::OffsetOutsideBlock)
} else if event.offset < previous {
Some(EventProblem::OffsetDecreasing)
} else {
match event.event.validate() {
Ok(()) => None,
Err(Error::InvalidConfig { field, problem }) => {
Some(EventProblem::Config { field, problem })
}
Err(_) => Some(EventProblem::Midi),
}
};
if let Some(problem) = problem {
return Err(Error::InvalidEvent { index, problem });
}
previous = event.offset;
}
Ok(Self { remaining: events })
}
pub(crate) fn next_at(&mut self, frame: usize) -> Option<ValidatedEvent> {
let (event, remaining) = self.remaining.split_first()?;
if event.offset != frame {
return None;
}
self.remaining = remaining;
Some(ValidatedEvent(event.event))
}
}