use std::{collections::HashMap, hash::BuildHasher};
use crate::{
events::NoteID,
synth::{
NumericGlobalExpression, NumericPerNoteExpression, SwitchGlobalExpression, SynthParamStates,
},
};
use super::super::{
IdHash, IdHashMap, InfoRef, InternalValue, States, TypeSpecificInfoRef, hash_id,
};
pub fn override_defaults<'a, S: AsRef<str> + 'a, H: BuildHasher>(
infos: impl IntoIterator<Item = InfoRef<'a, S>> + 'a,
overrides: &HashMap<&'_ str, InternalValue, H>,
) -> HashMap<String, InternalValue> {
infos
.into_iter()
.map(|info| {
let id = info.unique_id;
let value = overrides
.get(id)
.copied()
.unwrap_or(match info.type_specific {
TypeSpecificInfoRef::Enum { default, .. } => InternalValue::Enum(default),
TypeSpecificInfoRef::Numeric { default, .. } => InternalValue::Numeric(default),
TypeSpecificInfoRef::Switch { default, .. } => InternalValue::Switch(default),
});
(id.to_string(), value)
})
.collect()
}
#[derive(Clone, Debug, Default)]
pub struct StatesMap {
map: IdHashMap<InternalValue>,
}
impl<S: AsRef<str>> From<HashMap<S, InternalValue>> for StatesMap {
fn from(map: HashMap<S, InternalValue>) -> Self {
Self {
map: map
.into_iter()
.map(|(k, v)| (hash_id(k.as_ref()), v))
.collect(),
}
}
}
impl StatesMap {
pub fn new_override_defaults<'a, S: AsRef<str> + 'a>(
infos: impl IntoIterator<Item = InfoRef<'a, S>> + 'a,
overrides: &HashMap<&'_ str, InternalValue>,
) -> Self {
Self {
map: override_defaults(infos, overrides)
.into_iter()
.map(|(k, v)| (hash_id(&k), v))
.collect(),
}
}
pub fn new_defaults<'a, S: AsRef<str> + 'a>(
infos: impl IntoIterator<Item = InfoRef<'a, S>> + 'a,
) -> Self {
Self::new_override_defaults(infos, &Default::default())
}
}
impl States for StatesMap {
fn get_by_hash(&self, id_hash: IdHash) -> Option<InternalValue> {
self.map.get(&id_hash).copied()
}
}
#[derive(Clone, Debug, Default)]
pub struct SynthStatesMap {
states: StatesMap,
numeric_expressions: HashMap<NumericGlobalExpression, f32>,
switch_expressions: HashMap<SwitchGlobalExpression, bool>,
per_note_expressions: HashMap<(NumericPerNoteExpression, NoteID), f32>,
}
impl SynthStatesMap {
pub fn new_override_defaults<'a, S: AsRef<str> + 'a>(
infos: impl IntoIterator<Item = InfoRef<'a, S>> + 'a,
overrides: &HashMap<&'_ str, InternalValue>,
numeric_expression_overrides: &HashMap<NumericGlobalExpression, f32>,
switch_expression_overrides: &HashMap<SwitchGlobalExpression, bool>,
) -> Self {
Self {
states: StatesMap::from(override_defaults(infos, overrides)),
numeric_expressions: numeric_expression_overrides.clone(),
switch_expressions: switch_expression_overrides.clone(),
per_note_expressions: Default::default(),
}
}
pub fn new_with_per_note<'a, S: AsRef<str> + 'a>(
infos: impl IntoIterator<Item = InfoRef<'a, S>> + 'a,
overrides: &HashMap<&'_ str, InternalValue>,
numeric_expression_overrides: &HashMap<NumericGlobalExpression, f32>,
switch_expression_overrides: &HashMap<SwitchGlobalExpression, bool>,
per_note_expression_overrides: &HashMap<(NumericPerNoteExpression, NoteID), f32>,
) -> Self {
Self {
states: StatesMap::from(override_defaults(infos, overrides)),
numeric_expressions: numeric_expression_overrides.clone(),
switch_expressions: switch_expression_overrides.clone(),
per_note_expressions: per_note_expression_overrides.clone(),
}
}
pub fn new_defaults<'a, S: AsRef<str> + 'a>(
infos: impl IntoIterator<Item = InfoRef<'a, S>> + 'a,
) -> Self {
Self::new_override_defaults(
infos,
&Default::default(),
&Default::default(),
&Default::default(),
)
}
}
impl States for SynthStatesMap {
fn get_by_hash(&self, id_hash: IdHash) -> Option<InternalValue> {
self.states.get_by_hash(id_hash)
}
}
impl SynthParamStates for SynthStatesMap {
fn get_numeric_global_expression(&self, expression: NumericGlobalExpression) -> f32 {
self.numeric_expressions
.get(&expression)
.copied()
.unwrap_or_default()
}
fn get_switch_global_expression(&self, expression: SwitchGlobalExpression) -> bool {
self.switch_expressions
.get(&expression)
.copied()
.unwrap_or_default()
}
fn get_numeric_expression_for_note(
&self,
expression: NumericPerNoteExpression,
note_id: NoteID,
) -> f32 {
self.per_note_expressions
.get(&(expression, note_id))
.copied()
.unwrap_or_default()
}
}