use std::ops::RangeInclusive;
use crate::{
Processor,
audio::BufferMut,
events::{self, Event, Events},
parameters::{
self, NumericBufferState, PiecewiseLinearCurvePoint, SwitchBufferState, TimedValue,
},
};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum NumericGlobalExpression {
PitchBend,
ModWheel,
ExpressionPedal,
Aftertouch,
Timbre,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum NumericPerNoteExpression {
PitchBend,
Timbre,
Aftertouch,
}
#[must_use]
pub fn valid_range_for_per_note_expression(
expression: NumericPerNoteExpression,
) -> RangeInclusive<f32> {
match expression {
NumericPerNoteExpression::PitchBend => -128.0..=128.0,
NumericPerNoteExpression::Timbre | NumericPerNoteExpression::Aftertouch => 0.0..=1.0,
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum SwitchGlobalExpression {
SustainPedal,
}
pub trait SynthParamStates: parameters::States {
fn get_numeric_global_expression(&self, expression: NumericGlobalExpression) -> f32;
fn get_switch_global_expression(&self, expression: SwitchGlobalExpression) -> bool;
fn get_numeric_expression_for_note(
&self,
expression: NumericPerNoteExpression,
note_id: events::NoteID,
) -> f32;
}
pub trait HandleEventsContext {
fn events(&self) -> impl Iterator<Item = events::Data> + Clone;
fn parameters(&self) -> &impl SynthParamStates;
}
pub trait SynthParamBufferStates: parameters::BufferStates {
fn get_numeric_global_expression(
&self,
expression: NumericGlobalExpression,
) -> NumericBufferState<impl Iterator<Item = PiecewiseLinearCurvePoint> + Clone>;
fn get_switch_global_expression(
&self,
expression: SwitchGlobalExpression,
) -> SwitchBufferState<impl Iterator<Item = TimedValue<bool>> + Clone>;
fn get_numeric_expression_for_note(
&self,
expression: NumericPerNoteExpression,
note_id: events::NoteID,
) -> NumericBufferState<impl Iterator<Item = PiecewiseLinearCurvePoint> + Clone>;
}
pub trait ProcessContext {
fn events(&self) -> Events<impl Iterator<Item = Event> + Clone>;
fn parameters(&self) -> &impl SynthParamBufferStates;
}
pub trait Synth: Processor {
fn handle_events(&mut self, context: &impl HandleEventsContext);
fn process(&mut self, context: &impl ProcessContext, output: &mut impl BufferMut);
}