1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use wasm4_sys::tone;

use super::{adsr::Adsr, frequency_slide::FrequencySlide, tone_flags::ToneFlags, volume::Volume};

/// Tone.
#[derive(Clone, Default)]
#[cfg_attr(not(target_family = "wasm"), derive(PartialEq, Eq, Debug))]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
pub struct Tone {
    /// Frequency.
    pub frequency: FrequencySlide,
    /// Duration.
    pub duration: Adsr,
    /// Volume.
    pub volume: Volume,
    /// Flags.
    pub flags: ToneFlags,
}

impl Tone {
    /// Create a new tone builder.
    pub const fn builder() -> ToneBuilder {
        ToneBuilder::new()
    }

    /// Build a new default tone.
    pub const fn new() -> Self {
        Self {
            frequency: FrequencySlide::new(220),
            duration: Adsr::new(0, 0, 1, 0),
            volume: Volume::new(100),
            flags: ToneFlags::new(),
        }
    }

    /// Copy the tone with another frequency.
    pub fn with_frequency(&self, freq: FrequencySlide) -> Tone {
        let mut new_tone = self.clone();
        new_tone.frequency = freq;
        new_tone
    }

    /// Convert tone to binary.
    pub fn to_binary(&self) -> (u32, u32, u16, u16) {
        (
            u32::from(self.frequency),
            u32::from(self.duration),
            u16::from(self.volume),
            u16::from(self.flags),
        )
    }

    /// Play the tone.
    pub fn play(&self) {
        tone(
            self.frequency.into(),
            self.duration.into(),
            u16::from(self.volume) as u32,
            u16::from(self.flags) as u32,
        );
    }
}

/// Tone builder.
pub struct ToneBuilder {
    tone: Tone,
}

impl ToneBuilder {
    /// Create a new tone builder.
    pub const fn new() -> Self {
        Self { tone: Tone::new() }
    }

    /// Set the tone frequency.
    pub const fn with_frequency(mut self, frequency: FrequencySlide) -> Self {
        self.tone.frequency = frequency;
        self
    }

    /// Set the tone duration.
    pub const fn with_duration(mut self, duration: Adsr) -> Self {
        self.tone.duration = duration;
        self
    }

    /// Set the tone volume.
    pub const fn with_volume(mut self, volume: Volume) -> Self {
        self.tone.volume = volume;
        self
    }

    /// Set the tone flags.
    pub const fn with_flags(mut self, flags: ToneFlags) -> Self {
        self.tone.flags = flags;
        self
    }

    /// Build the tone.
    pub const fn build(self) -> Tone {
        self.tone
    }

    /// Play the tone.
    pub fn play(&self) {
        self.tone.play()
    }
}

impl Default for ToneBuilder {
    fn default() -> Self {
        Self::new()
    }
}