Skip to main content

signal_utils/
generator.rs

1//! Signal generators
2// TODO: use signal generators from dasp crate?
3
4use rand;
5use rand_xorshift::XorShiftRng;
6use derive_more::{From, TryInto};
7
8#[derive(Clone, Debug)]
9pub struct Generator {
10  pub freq : f64,
11  pub kind : Kind,
12  pub rng  : XorShiftRng
13}
14
15pub trait Generate {
16  fn generate (&mut self, rng : &mut XorShiftRng, samples : &mut [i16], freq : f64);
17}
18
19#[derive(Clone, Debug, Eq, PartialEq, From, TryInto)]
20pub enum Kind {
21  Wave  (Wave),
22  Noise (Noise)
23}
24
25#[derive(Clone, Debug, Eq, PartialEq)]
26pub enum Wave {
27  Sin,
28  Tri,
29  Saw,
30  Square { width : u32 }
31}
32
33#[derive(Clone, Debug, Eq, PartialEq)]
34pub enum Noise {
35  White,
36  Brown { intensity : i16 },
37  Pink
38}
39
40impl Generator {
41  #[inline]
42  pub fn new (kind : Kind, freq : f64) -> Self {
43    use rand::SeedableRng;
44    // TODO: seed rng
45    let rng = XorShiftRng::seed_from_u64 (0);
46    Generator { kind, freq, rng }
47  }
48  #[inline]
49  pub fn generate (&mut self, samples : &mut [i16]) {
50    self.kind.generate (&mut self.rng, samples, self.freq)
51  }
52}
53
54impl Generate for Kind {
55  fn generate (&mut self, rng : &mut XorShiftRng, samples : &mut [i16], freq : f64) {
56    match self {
57      Kind::Wave  (wave)  => wave.generate  (rng, samples, freq),
58      Kind::Noise (noise) => noise.generate (rng, samples, freq)
59    }
60  }
61}
62
63impl Generate for Wave {
64  fn generate (&mut self, _rng : &mut XorShiftRng, _samples : &mut [i16], _freq : f64) {
65    unimplemented!("TODO")
66  }
67}
68
69impl Generate for Noise {
70  fn generate (&mut self, rng : &mut XorShiftRng, samples : &mut [i16], _freq : f64) {
71    use rand::RngExt;
72    match self {
73      Noise::White => for sample in samples.iter_mut() {
74        *sample = rng.random()
75      }
76      Noise::Brown { intensity } => {
77        let mut level = 0i16;
78        for sample in samples.iter_mut() {
79          *sample = level;
80          let delta = rng.random_range(-(intensity.abs())..intensity.abs());
81          level = level.saturating_add (delta);
82        }
83        // TODO: amplitude
84        //pcm::normalize (samples, std::i16::MAX - 1000);
85      }
86      Noise::Pink => unimplemented!("TODO")
87    }
88  }
89}