rill_core_dsp/generators/
noise.rs1use super::Generator;
4use crate::algorithm::{Algorithm, AlgorithmCategory, AlgorithmMetadata};
5use crate::filters::{FilterParams, FilterType, OnePole};
6use crate::vector::prelude::*;
7use rill_core::traits::{ActionContext, ProcessResult};
8use rill_core::Transcendental;
9
10#[derive(Debug, Clone, Copy, PartialEq)]
12pub enum NoiseType {
13 White, Pink, Brown, Blue, Violet, }
19
20impl NoiseType {
21 pub fn name(&self) -> &'static str {
22 match self {
23 NoiseType::White => "White Noise",
24 NoiseType::Pink => "Pink Noise",
25 NoiseType::Brown => "Brown Noise",
26 NoiseType::Blue => "Blue Noise",
27 NoiseType::Violet => "Violet Noise",
28 }
29 }
30
31 pub fn description(&self) -> &'static str {
32 match self {
33 NoiseType::White => "Equal energy per Hz",
34 NoiseType::Pink => "Equal energy per octave (1/f)",
35 NoiseType::Brown => "Brownian motion (1/f²)",
36 NoiseType::Blue => "Increasing with frequency (+3dB/oct)",
37 NoiseType::Violet => "Strongly increasing (+6dB/oct)",
38 }
39 }
40}
41
42pub struct NoiseGenerator<T: Transcendental> {
44 noise_type: NoiseType,
46 amplitude: ScalarVector1<T>,
48 state: u32,
50 pink_filters: [OnePole<T>; 6],
52 brown_state: ScalarVector1<T>,
53 sample_rate: f32,
55 last_white: ScalarVector1<T>,
57 last_white1: ScalarVector1<T>,
59 last_white2: ScalarVector1<T>,
60}
61
62impl<T: Transcendental> NoiseGenerator<T> {
63 pub fn new(noise_type: NoiseType, amplitude: T) -> Self {
65 let filter_params = FilterParams {
67 filter_type: FilterType::LowPass,
68 cutoff: 1.0,
69 q: 0.707,
70 gain_db: 0.0,
71 };
72
73 Self {
74 noise_type,
75 amplitude: ScalarVector1::splat(amplitude),
76 state: 123456789,
77 pink_filters: [
78 OnePole::new(filter_params.clone()),
79 OnePole::new(filter_params.clone()),
80 OnePole::new(filter_params.clone()),
81 OnePole::new(filter_params.clone()),
82 OnePole::new(filter_params.clone()),
83 OnePole::new(filter_params),
84 ],
85 brown_state: ScalarVector1::splat(T::ZERO),
86 sample_rate: 44100.0,
87 last_white: ScalarVector1::splat(T::ZERO),
88 last_white1: ScalarVector1::splat(T::ZERO),
89 last_white2: ScalarVector1::splat(T::ZERO),
90 }
91 }
92
93 #[inline(always)]
95 fn xorshift(&mut self) -> T {
96 let mut x = self.state;
97
98 x ^= x << 13;
99 x ^= x >> 17;
100 x ^= x << 5;
101
102 self.state = x;
103
104 let float_val = (x as f32 / 2147483648.0) - 1.0; T::from_f32(float_val)
108 }
109
110 #[inline(always)]
112 fn generate_white(&mut self) -> ScalarVector1<T> {
113 ScalarVector1::splat(self.xorshift()) * self.amplitude
114 }
115
116 fn generate_pink(&mut self) -> ScalarVector1<T> {
119 let white = self.xorshift();
120
121 let mut output = T::ZERO;
123 for filter in &mut self.pink_filters {
124 output = output.add(filter.process_sample(white));
125 }
126
127 ScalarVector1::splat(output) * self.amplitude / ScalarVector1::splat(T::from_f32(3.0))
128 }
130
131 fn generate_brown(&mut self) -> ScalarVector1<T> {
133 let white = self.xorshift();
134
135 self.brown_state =
137 self.brown_state + ScalarVector1::splat(white) * ScalarVector1::splat(T::from_f32(0.1));
138 let one_vec = ScalarVector1::splat(T::from_f32(1.0));
140 let neg_one_vec = ScalarVector1::splat(T::from_f32(-1.0));
141 self.brown_state = self.brown_state.clamp(&neg_one_vec, &one_vec);
142
143 self.brown_state * self.amplitude
144 }
145
146 fn generate_blue(&mut self) -> ScalarVector1<T> {
148 let white = self.xorshift();
149 let white_vec = ScalarVector1::splat(white);
150
151 let diff = white_vec - self.last_white;
153 self.last_white = white_vec;
154
155 diff * self.amplitude
156 }
157
158 fn generate_violet(&mut self) -> ScalarVector1<T> {
160 let white = self.xorshift();
161 let white_vec = ScalarVector1::splat(white);
162
163 let diff1 = white_vec - self.last_white1;
165 let diff2 = diff1 - self.last_white2;
166 self.last_white2 = diff1;
167 self.last_white1 = white_vec;
168
169 diff2 * self.amplitude
170 }
171}
172
173impl<T: Transcendental> Algorithm<T> for NoiseGenerator<T> {
174 fn init(&mut self, sample_rate: f32) {
175 self.sample_rate = sample_rate;
176
177 let freqs = [5.0, 15.0, 45.0, 135.0, 405.0, 1215.0];
179 for (i, &freq) in freqs.iter().enumerate() {
180 use crate::filters::Filter;
183 self.pink_filters[i].set_cutoff(freq);
184 }
185
186 self.reset();
187 }
188
189 fn reset(&mut self) {
190 self.state = 123456789;
191 self.brown_state = ScalarVector1::splat(T::ZERO);
192 self.last_white = ScalarVector1::splat(T::ZERO);
193 self.last_white1 = ScalarVector1::splat(T::ZERO);
194 self.last_white2 = ScalarVector1::splat(T::ZERO);
195 for filter in &mut self.pink_filters {
196 filter.reset();
197 }
198 }
199
200 fn process(
201 &mut self,
202 input: Option<&[T]>,
203 output: &mut [T],
204 _ctx: &ActionContext,
205 ) -> ProcessResult<()> {
206 let input = input.unwrap_or(&[]);
207 for out in output.iter_mut() {
208 *out = match self.noise_type {
209 NoiseType::White => self.generate_white().extract(0),
210 NoiseType::Pink => self.generate_pink().extract(0),
211 NoiseType::Brown => self.generate_brown().extract(0),
212 NoiseType::Blue => self.generate_blue().extract(0),
213 NoiseType::Violet => self.generate_violet().extract(0),
214 };
215 }
216 Ok(())
217 }
218
219 fn metadata(&self) -> AlgorithmMetadata {
220 AlgorithmMetadata {
221 name: self.noise_type.name(),
222 category: AlgorithmCategory::Generator,
223 description: self.noise_type.description(),
224 author: "Rill",
225 version: env!("CARGO_PKG_VERSION"),
226 }
227 }
228}
229
230impl<T: Transcendental> Generator<T> for NoiseGenerator<T> {
231 fn phase(&self) -> T {
232 T::ZERO
233 } fn set_phase(&mut self, _phase: T) {}
236
237 fn frequency(&self) -> f32 {
238 0.0
239 }
240
241 fn set_frequency(&mut self, _freq: f32) {}
242
243 fn amplitude(&self) -> T {
244 self.amplitude.extract(0)
245 }
246
247 fn set_amplitude(&mut self, amp: T) {
248 let one = T::from_f32(1.0);
249 let clamped = if amp > one {
250 one
251 } else if amp < T::ZERO {
252 T::ZERO
253 } else {
254 amp
255 };
256 self.amplitude = ScalarVector1::splat(clamped);
257 }
258}