1use crate::oscillator::Gain;
2use crate::settings::NUM_WAVEFORM_STEPS;
3
4pub type Amp4 = u8;
5pub type Waveform = [Amp4; NUM_WAVEFORM_STEPS as usize];
6
7#[derive(PartialEq, Copy, Clone)]
8pub enum Noise {
9 Off,
10 ShortPeriod,
11 LongPeriod,
12}
13
14impl Noise {
15 pub fn from_index(index: u32) -> Self {
16 match index {
17 1 => Self::ShortPeriod,
18 2 => Self::LongPeriod,
19 _ => Self::Off,
20 }
21 }
22
23 pub fn to_index(&self) -> u32 {
24 match self {
25 Self::Off => 0,
26 Self::ShortPeriod => 1,
27 Self::LongPeriod => 2,
28 }
29 }
30}
31
32pub struct Tone {
33 pub gain: Gain,
34 pub noise: Noise,
35 pub waveform: Waveform,
36}
37
38pub type SharedTone = shared_type!(Tone);
39
40impl Tone {
41 pub fn new() -> SharedTone {
42 new_shared_type!(Self {
43 gain: 1.0,
44 noise: Noise::Off,
45 waveform: [0; NUM_WAVEFORM_STEPS as usize],
46 })
47 }
48
49 pub fn amplitude(&self, phase: u32, noise_reg: &mut u16) -> f64 {
50 (match self.noise {
51 Noise::Off => self.waveform[phase as usize] as f64 / 7.5 - 1.0,
52 Noise::ShortPeriod | Noise::LongPeriod => {
53 if phase % 8 == 0 {
54 let bit = if self.noise == Noise::LongPeriod {
55 1
56 } else {
57 6
58 };
59
60 let feedback = (*noise_reg ^ (*noise_reg >> bit)) & 1;
61 *noise_reg >>= 1;
62 *noise_reg |= feedback << 14;
63 }
64
65 (*noise_reg & 1) as f64 * 2.0 - 1.0
66 }
67 }) * self.gain
68 }
69}