rill_core_dsp/generators/
noise.rs1use super::Generator;
4use crate::filters::{FilterParams, FilterType, OnePole};
5use crate::vector::prelude::*;
6use rill_core::math::vector::scalar::ScalarVector4;
7use rill_core::math::vector::traits::Vector as VecTrait;
8use rill_core::traits::algorithm::{Algorithm, AlgorithmCategory, AlgorithmMetadata};
9use rill_core::traits::ProcessResult;
10use rill_core::Transcendental;
11
12#[derive(Debug, Clone, Copy, PartialEq)]
14pub enum NoiseType {
15 White,
17 Pink,
19 Brown,
21 Blue,
23 Violet,
25}
26
27impl NoiseType {
28 pub fn name(&self) -> &'static str {
30 match self {
31 NoiseType::White => "White Noise",
32 NoiseType::Pink => "Pink Noise",
33 NoiseType::Brown => "Brown Noise",
34 NoiseType::Blue => "Blue Noise",
35 NoiseType::Violet => "Violet Noise",
36 }
37 }
38
39 pub fn description(&self) -> &'static str {
41 match self {
42 NoiseType::White => "Equal energy per Hz",
43 NoiseType::Pink => "Equal energy per octave (1/f)",
44 NoiseType::Brown => "Brownian motion (1/f²)",
45 NoiseType::Blue => "Increasing with frequency (+3dB/oct)",
46 NoiseType::Violet => "Strongly increasing (+6dB/oct)",
47 }
48 }
49}
50
51pub struct NoiseGenerator<T: Transcendental> {
56 noise_type: NoiseType,
57 amplitude: ScalarVector1<T>,
58 state: u32,
59 pink_filters: [OnePole<T>; 6],
60 brown_state: ScalarVector1<T>,
61 sample_rate: f32,
62 last_white: ScalarVector1<T>,
63 last_white1: ScalarVector1<T>,
64 last_white2: ScalarVector1<T>,
65}
66
67impl<T: Transcendental> NoiseGenerator<T> {
68 pub fn new(noise_type: NoiseType, amplitude: T) -> Self {
70 let filter_params = FilterParams {
72 filter_type: FilterType::LowPass,
73 cutoff: 1.0,
74 q: 0.707,
75 gain_db: 0.0,
76 };
77
78 Self {
79 noise_type,
80 amplitude: ScalarVector1::splat(amplitude),
81 state: 123456789,
82 pink_filters: [
83 OnePole::new(filter_params.clone()),
84 OnePole::new(filter_params.clone()),
85 OnePole::new(filter_params.clone()),
86 OnePole::new(filter_params.clone()),
87 OnePole::new(filter_params.clone()),
88 OnePole::new(filter_params),
89 ],
90 brown_state: ScalarVector1::splat(T::ZERO),
91 sample_rate: 44100.0,
92 last_white: ScalarVector1::splat(T::ZERO),
93 last_white1: ScalarVector1::splat(T::ZERO),
94 last_white2: ScalarVector1::splat(T::ZERO),
95 }
96 }
97
98 #[inline(always)]
100 fn xorshift(&mut self) -> T {
101 let mut x = self.state;
102
103 x ^= x << 13;
104 x ^= x >> 17;
105 x ^= x << 5;
106
107 self.state = x;
108
109 let float_val = (x as f32 / 2147483648.0) - 1.0; T::from_f32(float_val)
113 }
114
115 fn generate_white_block(&mut self, out: &mut [T]) {
117 let chunks = out.len() / 4;
118 let amp = ScalarVector4::splat(self.amplitude.extract(0));
119
120 for chunk in 0..chunks {
121 let offset = chunk * 4;
122 let w0 = self.xorshift();
124 let w1 = self.xorshift();
125 let w2 = self.xorshift();
126 let w3 = self.xorshift();
127
128 let v = ScalarVector4::load(&[w0, w1, w2, w3]);
129 v.mul(&).store(&mut out[offset..offset + 4]);
130 }
131
132 for out in out[chunks * 4..].iter_mut() {
134 *out = self.generate_white().extract(0);
135 }
136 }
137
138 #[inline(always)]
140 fn generate_white(&mut self) -> ScalarVector1<T> {
141 ScalarVector1::splat(self.xorshift()) * self.amplitude
142 }
143
144 fn generate_pink_scalar(&mut self) -> ScalarVector1<T> {
146 let white = self.xorshift();
147
148 let mut output = T::ZERO;
150 for filter in &mut self.pink_filters {
151 output = output.add(filter.process_sample(white));
152 }
153
154 ScalarVector1::splat(output) * self.amplitude / ScalarVector1::splat(T::from_f32(3.0))
155 }
157
158 fn generate_brown_block(&mut self, out: &mut [T]) {
160 let chunks = out.len() / 4;
161 let amp = self.amplitude.extract(0);
162 let factor = T::from_f32(0.1);
163 let one = T::ONE;
164 let neg_one = -T::ONE;
165 let mut state = self.brown_state.extract(0);
166
167 for chunk in 0..chunks {
168 let offset = chunk * 4;
169 let w0 = self.xorshift();
170 let w1 = self.xorshift();
171 let w2 = self.xorshift();
172 let w3 = self.xorshift();
173
174 state = (state + w0 * factor).clamp(neg_one, one);
176 out[offset] = state * amp;
177
178 state = (state + w1 * factor).clamp(neg_one, one);
179 out[offset + 1] = state * amp;
180
181 state = (state + w2 * factor).clamp(neg_one, one);
182 out[offset + 2] = state * amp;
183
184 state = (state + w3 * factor).clamp(neg_one, one);
185 out[offset + 3] = state * amp;
186 }
187
188 self.brown_state = ScalarVector1::splat(state);
189
190 for out in out[chunks * 4..].iter_mut() {
191 *out = self.generate_brown_scalar().extract(0);
192 }
193 }
194
195 fn generate_brown_scalar(&mut self) -> ScalarVector1<T> {
197 let white = self.xorshift();
198 self.brown_state =
200 self.brown_state + ScalarVector1::splat(white) * ScalarVector1::splat(T::from_f32(0.1));
201 let one_vec = ScalarVector1::splat(T::ONE);
202 let neg_one_vec = ScalarVector1::splat(-T::ONE);
203 self.brown_state = self.brown_state.clamp(&neg_one_vec, &one_vec);
204 self.brown_state * self.amplitude
205 }
206
207 fn generate_blue_block(&mut self, out: &mut [T]) {
209 let chunks = out.len() / 4;
210 let amp = self.amplitude.extract(0);
211 let mut last = self.last_white.extract(0);
212
213 for chunk in 0..chunks {
214 let offset = chunk * 4;
215 let w0 = self.xorshift();
216 let w1 = self.xorshift();
217 let w2 = self.xorshift();
218 let w3 = self.xorshift();
219
220 let white_v = ScalarVector4::load(&[w0, w1, w2, w3]);
221 let shifted_v = ScalarVector4::load(&[last, w0, w1, w2]);
222 let diff = white_v.sub(&shifted_v);
223 diff.mul(&ScalarVector4::splat(amp))
224 .store(&mut out[offset..offset + 4]);
225 last = w3;
226 }
227
228 self.last_white = ScalarVector1::splat(last);
229
230 for out in out[chunks * 4..].iter_mut() {
232 *out = self.generate_blue_scalar().extract(0);
233 }
234 }
235
236 fn generate_violet_block(&mut self, out: &mut [T]) {
238 let chunks = out.len() / 4;
239 let amp = self.amplitude.extract(0);
240 let mut l1 = self.last_white1.extract(0);
241 let mut l2 = self.last_white2.extract(0);
242
243 for chunk in 0..chunks {
244 let offset = chunk * 4;
245 let w0 = self.xorshift();
246 let w1 = self.xorshift();
247 let w2 = self.xorshift();
248 let w3 = self.xorshift();
249
250 let white_v = ScalarVector4::load(&[w0, w1, w2, w3]);
252 let s1_v = ScalarVector4::load(&[l1, w0, w1, w2]);
253 let diff1 = white_v.sub(&s1_v);
254
255 let s2_v =
257 ScalarVector4::load(&[l2, diff1.extract(0), diff1.extract(1), diff1.extract(2)]);
258 let diff2 = diff1.sub(&s2_v);
259
260 diff2
261 .mul(&ScalarVector4::splat(amp))
262 .store(&mut out[offset..offset + 4]);
263 l1 = w3;
264 l2 = diff1.extract(3);
265 }
266
267 self.last_white1 = ScalarVector1::splat(l1);
268 self.last_white2 = ScalarVector1::splat(l2);
269
270 for out in out[chunks * 4..].iter_mut() {
271 *out = self.generate_violet_scalar().extract(0);
272 }
273 }
274
275 fn generate_blue_scalar(&mut self) -> ScalarVector1<T> {
277 let white = self.xorshift();
278 let white_vec = ScalarVector1::splat(white);
279 let diff = white_vec - self.last_white;
280 self.last_white = white_vec;
281 diff * self.amplitude
282 }
283
284 fn generate_violet_scalar(&mut self) -> ScalarVector1<T> {
286 let white = self.xorshift();
287 let white_vec = ScalarVector1::splat(white);
288 let diff1 = white_vec - self.last_white1;
289 let diff2 = diff1 - self.last_white2;
290 self.last_white2 = diff1;
291 self.last_white1 = white_vec;
292 diff2 * self.amplitude
293 }
294}
295
296impl<T: Transcendental> Algorithm<T> for NoiseGenerator<T> {
297 fn init(&mut self, sample_rate: f32) {
298 self.sample_rate = sample_rate;
299
300 let freqs = [5.0, 15.0, 45.0, 135.0, 405.0, 1215.0];
302 for (i, &freq) in freqs.iter().enumerate() {
303 use crate::filters::Filter;
306 self.pink_filters[i].set_cutoff(freq);
307 }
308
309 self.reset();
310 }
311
312 fn reset(&mut self) {
313 self.state = 123456789;
314 self.brown_state = ScalarVector1::splat(T::ZERO);
315 self.last_white = ScalarVector1::splat(T::ZERO);
316 self.last_white1 = ScalarVector1::splat(T::ZERO);
317 self.last_white2 = ScalarVector1::splat(T::ZERO);
318 for filter in &mut self.pink_filters {
319 filter.reset();
320 }
321 }
322
323 fn process(&mut self, _input: Option<&[T]>, output: &mut [T]) -> ProcessResult<()> {
324 match self.noise_type {
325 NoiseType::White => self.generate_white_block(output),
326 NoiseType::Brown => self.generate_brown_block(output),
327 NoiseType::Blue => self.generate_blue_block(output),
328 NoiseType::Violet => self.generate_violet_block(output),
329 _ => {
330 for out in output.iter_mut() {
331 *out = match self.noise_type {
332 NoiseType::Pink => self.generate_pink_scalar().extract(0),
333 _ => unreachable!(),
334 };
335 }
336 }
337 }
338 Ok(())
339 }
340
341 fn metadata(&self) -> AlgorithmMetadata {
342 AlgorithmMetadata {
343 name: self.noise_type.name(),
344 category: AlgorithmCategory::Generator,
345 description: self.noise_type.description(),
346 author: "Rill",
347 version: env!("CARGO_PKG_VERSION"),
348 }
349 }
350}
351
352impl<T: Transcendental> Generator<T> for NoiseGenerator<T> {
353 fn phase(&self) -> T {
354 T::ZERO
355 } fn set_phase(&mut self, _phase: T) {}
358
359 fn frequency(&self) -> f32 {
360 0.0
361 }
362
363 fn set_frequency(&mut self, _freq: f32) {}
364
365 fn amplitude(&self) -> T {
366 self.amplitude.extract(0)
367 }
368
369 fn set_amplitude(&mut self, amp: T) {
370 let one = T::from_f32(1.0);
371 let clamped = if amp > one {
372 one
373 } else if amp < T::ZERO {
374 T::ZERO
375 } else {
376 amp
377 };
378 self.amplitude = ScalarVector1::splat(clamped);
379 }
380}