use crate::prelude::*;
use std::{collections::HashMap, hash::Hash};
#[derive(Clone, Debug)]
pub struct Polyphony<K: Eq + Hash + Clone, S: Done> {
signals: HashMap<K, S>,
}
impl<K: Eq + Hash + Clone, S: Done> Default for Polyphony<K, S> {
fn default() -> Self {
Self {
signals: HashMap::new(),
}
}
}
impl<K: Eq + Hash + Clone, S: Done> Polyphony<K, S> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn signals(&self) -> impl Iterator<Item = (&K, &S)> {
self.signals.iter()
}
pub fn signals_mut(&mut self) -> impl Iterator<Item = (&K, &mut S)> {
self.signals.iter_mut()
}
pub fn add(&mut self, key: K, sgn: S) {
self.signals.insert(key, sgn);
}
#[must_use]
pub fn get(&self, key: &K) -> Option<&S> {
self.signals.get(key)
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut S> {
self.signals.get_mut(key)
}
pub fn modify<F: Fn(&mut S)>(&mut self, key: &K, f: F) -> bool {
if let Some(sgn) = self.get_mut(key) {
f(sgn);
true
} else {
false
}
}
pub fn stop(&mut self, key: &K) -> bool
where
S: Stop,
{
self.modify(key, S::stop)
}
pub fn stop_all(&mut self)
where
S: Stop,
{
for (_, signal) in self.signals_mut() {
signal.stop();
}
}
}
impl<K: Eq + Hash + Clone, S: Done> Signal for Polyphony<K, S> {
type Sample = S::Sample;
fn get(&self) -> S::Sample {
self.signals.values().map(Signal::get).sum()
}
}
impl<K: Eq + Hash + Clone, S: SignalMut + Done> SignalMut for Polyphony<K, S> {
fn advance(&mut self) {
let mut clear = Vec::new();
for (index, sgn) in &mut self.signals {
sgn.advance();
if sgn.is_done() {
clear.push(index.clone());
}
}
for index in clear {
self.signals.remove(&index);
}
}
fn retrigger(&mut self) {
self.signals.clear();
}
}
impl<K: Eq + Hash + Clone, S: SignalMut + Done> Base for Polyphony<K, S> {
impl_base!();
}
impl<K: Eq + Hash + Clone, S: SignalMut + Done> Panic for Polyphony<K, S> {
fn panic(&mut self) {
self.retrigger();
}
}