use std::sync::atomic::AtomicU64;
use knyst_macro::impl_gen;
use crate::Sample;
#[allow(unused)]
use crate::{self as knyst, gen::Gen, SampleRate};
use super::GenState;
pub struct RandomLin {
rng: fastrand::Rng,
current_value: Sample,
current_change_width: Sample,
phase: Sample,
freq_to_phase_inc: Sample,
}
static NEXT_SEED: AtomicU64 = AtomicU64::new(0);
pub fn next_randomness_seed() -> u64 {
NEXT_SEED.fetch_add(1, std::sync::atomic::Ordering::SeqCst)
}
#[impl_gen]
impl RandomLin {
pub fn new() -> Self {
let mut rng = fastrand::Rng::with_seed(next_randomness_seed() * 94 + 53);
Self {
current_value: rng.f32() as Sample,
phase: 0.0,
rng,
freq_to_phase_inc: 0.0,
current_change_width: 0.0,
}
}
pub fn init(&mut self, sample_rate: SampleRate) {
self.freq_to_phase_inc = 1.0 / *sample_rate;
self.new_value();
}
#[inline]
fn new_value(&mut self) {
let old_target = self.current_value + self.current_change_width;
let new = self.rng.f32() as Sample;
self.current_value = old_target;
self.current_change_width = new - old_target;
self.phase = 0.0;
}
pub fn process(&mut self, freq: &[Sample], output: &mut [Sample]) -> GenState {
let phase_step = freq[0] * self.freq_to_phase_inc;
for out in output {
*out = self.current_value + self.phase * self.current_change_width;
self.phase += phase_step;
if self.phase >= 1.0 {
self.new_value();
}
}
GenState::Continue
}
}