use crate::euclid::Modulus;
use std::f64::consts;
pub fn log_spaced(length: usize, start_exp: f64, stop_exp: f64) -> Vec<f64> {
match length {
0 => Vec::new(),
1 => vec![10f64.powf(stop_exp)],
_ => {
let step = (stop_exp - start_exp) / (length - 1) as f64;
let mut vec = (0..length)
.map(|x| 10f64.powf(start_exp + (x as f64) * step))
.collect::<Vec<f64>>();
vec[length - 1] = 10f64.powf(stop_exp);
vec
}
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct InfinitePeriodic {
amplitude: f64,
step: f64,
phase: f64,
k: f64,
}
impl InfinitePeriodic {
pub fn new(
sampling_rate: f64,
frequency: f64,
amplitude: f64,
phase: f64,
delay: i64,
) -> InfinitePeriodic {
let step = frequency / sampling_rate * amplitude;
InfinitePeriodic {
amplitude,
step,
phase: (phase - delay as f64 * step).modulus(amplitude),
k: 0.0,
}
}
pub fn default(sampling_rate: f64, frequency: f64) -> InfinitePeriodic {
Self::new(sampling_rate, frequency, 1.0, 0.0, 0)
}
}
impl std::fmt::Display for InfinitePeriodic {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:#?}")
}
}
impl Iterator for InfinitePeriodic {
type Item = f64;
fn next(&mut self) -> Option<f64> {
let mut x = self.phase + self.k * self.step;
if x >= self.amplitude {
x %= self.amplitude;
self.phase = x;
self.k = 0.0;
}
self.k += 1.0;
Some(x)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InfiniteSinusoidal {
amplitude: f64,
mean: f64,
step: f64,
phase: f64,
i: usize,
}
impl InfiniteSinusoidal {
pub fn new(
sampling_rate: f64,
frequency: f64,
amplitude: f64,
mean: f64,
phase: f64,
delay: i64,
) -> InfiniteSinusoidal {
let pi2 = consts::PI * 2.0;
let step = frequency / sampling_rate * pi2;
InfiniteSinusoidal {
amplitude,
mean,
step,
phase: (phase - delay as f64 * step) % pi2,
i: 0,
}
}
pub fn default(sampling_rate: f64, frequency: f64, amplitude: f64) -> InfiniteSinusoidal {
Self::new(sampling_rate, frequency, amplitude, 0.0, 0.0, 0)
}
}
impl std::fmt::Display for InfiniteSinusoidal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#?}", &self)
}
}
impl Iterator for InfiniteSinusoidal {
type Item = f64;
fn next(&mut self) -> Option<f64> {
let x = self.mean + self.amplitude * (self.phase + self.i as f64 * self.step).sin();
self.i += 1;
if self.i == 1000 {
self.i = 0;
self.phase = (self.phase + 1000.0 * self.step) % (consts::PI * 2.0);
}
Some(x)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InfiniteSquare {
periodic: InfinitePeriodic,
high_duration: f64,
high_value: f64,
low_value: f64,
}
impl InfiniteSquare {
pub fn new(
high_duration: i64,
low_duration: i64,
high_value: f64,
low_value: f64,
delay: i64,
) -> InfiniteSquare {
let duration = (high_duration + low_duration) as f64;
InfiniteSquare {
periodic: InfinitePeriodic::new(1.0, 1.0 / duration, duration, 0.0, delay),
high_duration: high_duration as f64,
high_value,
low_value,
}
}
}
impl std::fmt::Display for InfiniteSquare {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#?}", &self)
}
}
impl Iterator for InfiniteSquare {
type Item = f64;
fn next(&mut self) -> Option<f64> {
self.periodic.next().map(|x| {
if x < self.high_duration {
self.high_value
} else {
self.low_value
}
})
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InfiniteTriangle {
periodic: InfinitePeriodic,
raise_duration: f64,
raise: f64,
fall: f64,
high_value: f64,
low_value: f64,
}
impl InfiniteTriangle {
pub fn new(
raise_duration: i64,
fall_duration: i64,
high_value: f64,
low_value: f64,
delay: i64,
) -> InfiniteTriangle {
let duration = (raise_duration + fall_duration) as f64;
let height = high_value - low_value;
InfiniteTriangle {
periodic: InfinitePeriodic::new(1.0, 1.0 / duration, duration, 0.0, delay),
raise_duration: raise_duration as f64,
raise: height / raise_duration as f64,
fall: height / fall_duration as f64,
high_value,
low_value,
}
}
}
impl std::fmt::Display for InfiniteTriangle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#?}", &self)
}
}
impl Iterator for InfiniteTriangle {
type Item = f64;
fn next(&mut self) -> Option<f64> {
self.periodic.next().map(|x| {
if x < self.raise_duration {
self.low_value + x * self.raise
} else {
self.high_value - (x - self.raise_duration) * self.fall
}
})
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InfiniteSawtooth {
periodic: InfinitePeriodic,
low_value: f64,
}
impl InfiniteSawtooth {
pub fn new(period: i64, high_value: f64, low_value: f64, delay: i64) -> InfiniteSawtooth {
let height = high_value - low_value;
let period = period as f64;
InfiniteSawtooth {
periodic: InfinitePeriodic::new(
1.0,
1.0 / period,
height * period / (period - 1.0),
0.0,
delay,
),
low_value,
}
}
}
impl std::fmt::Display for InfiniteSawtooth {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#?}", &self)
}
}
impl Iterator for InfiniteSawtooth {
type Item = f64;
fn next(&mut self) -> Option<f64> {
self.periodic.next().map(|x| x + self.low_value)
}
}