1use std::{num::ParseIntError, str::FromStr};
2
3#[rustfmt::skip]
4#[derive(Debug, PartialEq, Clone)]
5pub enum Tone {
6 C, Db, D, Eb, E, F, Gb, G, Ab, A, Bb, B,
7}
8
9#[derive(Debug, thiserror::Error, derive_more::Display)]
10pub struct ToneError();
11
12#[derive(Debug, PartialEq, Clone)]
13pub struct Note {
14 tone: Tone,
15 octave: u32,
16}
17
18#[derive(Debug, thiserror::Error, derive_more::From, derive_more::Display)]
19pub enum NoteError {
20 InvalidOctave(ParseIntError),
21 InalidNote(ToneError),
22}
23
24impl FromStr for Note {
25 type Err = NoteError;
26
27 fn from_str(txt: &str) -> Result<Self, Self::Err> {
28 let trimmed = txt.trim();
29 let mut split = 0;
30 for c in trimmed.chars() {
31 if !c.is_ascii_digit() {
32 split += 1;
33 } else {
34 break;
35 }
36 }
37 Ok(Note {
38 tone: trimmed[..split].parse::<Tone>()?,
39 octave: trimmed[split..].parse::<u32>().unwrap_or(0),
40 })
41 }
42}
43
44impl FromStr for Tone {
45 type Err = ToneError;
46
47 fn from_str(txt: &str) -> Result<Self, Self::Err> {
48 match txt {
49 "C" => Ok(Tone::C),
50 "C#" | "Db" => Ok(Tone::Db),
51 "D" => Ok(Tone::D),
52 "D#" | "Eb" => Ok(Tone::Eb),
53 "E" => Ok(Tone::E),
54 "F" => Ok(Tone::F),
55 "F#" | "Gb" => Ok(Tone::Gb),
56 "G" => Ok(Tone::G),
57 "G#" | "Ab" => Ok(Tone::Ab),
58 "A" => Ok(Tone::A),
59 "A#" | "Bb" => Ok(Tone::Bb),
60 "B" => Ok(Tone::B),
61 _ => Err(ToneError()),
62 }
63 }
64}
65
66impl Note {
67 pub fn tune_buffer_size(&self, sample_rate: u32) -> u32 {
68 let t = 1.0 / self.tone.freq(self.octave); let buf = (sample_rate as f32) * t;
70 buf.round() as u32
71 }
72}
73
74impl Tone {
75 pub fn freq(&self, octave: u32) -> f32 {
76 match octave {
77 0 => match self {
78 Tone::C => 16.35,
79 Tone::Db => 17.32,
80 Tone::D => 18.35,
81 Tone::Eb => 19.45,
82 Tone::E => 20.60,
83 Tone::F => 21.83,
84 Tone::Gb => 23.12,
85 Tone::G => 24.50,
86 Tone::Ab => 25.96,
87 Tone::A => 27.50,
88 Tone::Bb => 29.14,
89 Tone::B => 30.87,
90 },
91 _ => {
92 let mut freq = self.freq(0);
93 for _ in 0..octave {
94 freq *= 2.0;
95 }
96 freq
97 }
98 }
99 }
100}