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