diff --git a/knyst/src/gen/noise.rs b/knyst/src/gen/noise.rs index bacab38..2d94fa6 100644 --- a/knyst/src/gen/noise.rs +++ b/knyst/src/gen/noise.rs @@ -6,7 +6,7 @@ use super::GenState; use crate as knyst; use crate::Sample; -/// Whate noise (fastrand RNG based on wyrand) +/// White noise (fastrand RNG based on wyrand) pub struct WhiteNoise { rng: fastrand::Rng, } @@ -98,3 +98,39 @@ impl PinkNoise { GenState::Continue } } + +/// Brown noise (also known as red noise) +/// +/// Brown noise is generated by integrating white noise. +/// This implementation uses a simple integration of white noise samples with a small step size, +/// and clamps the output to prevent it from exceeding the [-1.0, 1.0] range. +pub struct BrownNoise { + rng: fastrand::Rng, + last_output: Sample, +} + +#[impl_gen(range = normal)] +impl BrownNoise { + #[allow(missing_docs)] + pub fn new() -> Self { + let mut rng = fastrand::Rng::new(); + rng.seed(next_randomness_seed()); + Self { + rng, + last_output: 0.0, + } + } + + #[allow(missing_docs)] + pub fn process(&mut self, output: &mut [Sample]) -> GenState { + for out in output.iter_mut() { + let white = self.rng.f32() as Sample * 2.0 - 1.0; + // Adjust the coefficient to control the step size + self.last_output += white * 0.1; + // Clamp to [-1.0, 1.0] to prevent output from exceeding the range + self.last_output = self.last_output.clamp(-1.0, 1.0); + *out = self.last_output; + } + GenState::Continue + } +}