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