use std::f64::consts;
use std::time::Duration;
use crate::Pattern;
use crate::PatternGenerator;
#[derive(Clone, Debug, PartialEq)]
pub struct ScaleTime<P: Pattern> {
pub pattern: P,
pub scalar: f64,
}
impl<P: Pattern> PatternGenerator for ScaleTime<P> {
fn sample(&mut self, time: Duration) -> f64 {
self.pattern.sample(Duration::from_secs_f64(self.scalar * (1.0 / time.as_secs_f64())))
}
fn duration(&self) -> Duration {
self.pattern.duration()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ScaleIntensity<P: Pattern> {
pub pattern: P,
pub scalar: f64,
}
impl<P: Pattern> PatternGenerator for ScaleIntensity<P> {
fn sample(&mut self, time: Duration) -> f64 {
self.scalar * self.pattern.sample(time)
}
fn duration(&self) -> Duration {
self.pattern.duration()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Sum<P: Pattern, Q: Pattern> {
pub a: P,
pub b: Q,
}
impl<P: Pattern, Q: Pattern> PatternGenerator for Sum<P, Q> {
fn sample(&mut self, time: Duration) -> f64 {
self.a.sample(time) + self.b.sample(time)
}
fn duration(&self) -> Duration {
self.a.duration().max(self.b.duration())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Subtract<P: Pattern, Q: Pattern> {
pub a: P,
pub b: Q,
}
impl<P: Pattern, Q: Pattern> PatternGenerator for Subtract<P, Q> {
fn sample(&mut self, time: Duration) -> f64 {
self.a.sample(time) - self.b.sample(time)
}
fn duration(&self) -> Duration {
self.a.duration().max(self.b.duration())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Average<P: Pattern, Q: Pattern> {
pub a: P,
pub b: Q,
}
impl<P: Pattern, Q: Pattern> PatternGenerator for Average<P, Q> {
fn sample(&mut self, time: Duration) -> f64 {
(self.a.sample(time) + self.b.sample(time)) / 2.0
}
fn duration(&self) -> Duration {
self.a.duration().max(self.b.duration())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Clamp<P: Pattern> {
pub pattern: P,
pub ceiling: f64,
pub floor: f64,
}
impl<P: Pattern> PatternGenerator for Clamp<P> {
fn sample(&mut self, time: Duration) -> f64 {
self.pattern.sample(time).max(self.floor).min(self.ceiling)
}
fn duration(&self) -> Duration {
self.pattern.duration()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ValidScale<P: Pattern> {
pub pattern: P
}
impl<P: Pattern> PatternGenerator for ValidScale<P> {
fn sample(&mut self, time: Duration) -> f64 {
1.0 / (1.0 + consts::E.powf(-self.pattern.sample(time)))
}
fn duration(&self) -> Duration {
self.pattern.duration()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Shift<P: Pattern> {
pub pattern: P,
pub time_shift: f64,
}
impl<P: Pattern> PatternGenerator for Shift<P> {
fn sample(&mut self, time: Duration) -> f64 {
self.pattern.sample(time + Duration::from_secs_f64(self.time_shift))
}
fn duration(&self) -> Duration {
self.pattern.duration() - Duration::from_secs_f64(self.time_shift)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Repeat<P: Pattern> {
pub pattern: P,
pub count: f64,
}
impl<P: Pattern> PatternGenerator for Repeat<P> {
fn sample(&mut self, time: Duration) -> f64 {
self.pattern.sample(Duration::from_secs_f64(time.as_secs_f64() % self.duration().as_secs_f64()))
}
fn duration(&self) -> Duration {
Duration::from_secs_f64(self.count * self.pattern.duration().as_secs_f64())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Forever<P: Pattern> {
pub pattern: P,
}
impl<P: Pattern> PatternGenerator for Forever<P> {
fn sample(&mut self, time: Duration) -> f64 {
let time_slice = time.as_secs_f64() % self.pattern.duration().as_secs_f64();
self.pattern.sample(Duration::from_secs_f64(time_slice))
}
fn duration(&self) -> Duration {
Duration::MAX
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Chain<P: Pattern, Q: Pattern> {
pub first: P,
pub then: Q,
}
impl<P: Pattern, Q: Pattern> PatternGenerator for Chain<P, Q> {
fn sample(&mut self, time: Duration) -> f64 {
if time < self.first.duration() {
self.first.sample(time)
} else {
self.then.sample(time)
}
}
fn duration(&self) -> Duration {
self.first.duration() + self.then.duration()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct AmplitudeModulator<P: Pattern, M: Pattern> {
pub pattern: P,
pub modulator: M,
}
impl<P: Pattern, M: Pattern> PatternGenerator for AmplitudeModulator<P, M> {
fn sample(&mut self, time: Duration) -> f64 {
self.pattern.sample(time) * self.modulator.sample(time)
}
fn duration(&self) -> Duration {
self.pattern.duration()
}
}