firefly_rust/audio/
freq.rspub const SAMPLE_RATE: u32 = 44_100;
#[derive(Copy, Clone)]
pub enum Pitch {
C,
Cs,
D,
Ds,
E,
F,
Fs,
G,
Gs,
A,
As,
B,
}
impl TryFrom<char> for Pitch {
type Error = ();
fn try_from(value: char) -> Result<Self, Self::Error> {
match value {
'A' => Ok(Self::A),
'B' => Ok(Self::B),
'C' => Ok(Self::C),
'D' => Ok(Self::D),
'E' => Ok(Self::E),
'F' => Ok(Self::F),
'G' => Ok(Self::G),
_ => Err(()),
}
}
}
#[derive(Copy, Clone)]
pub struct Freq(pub(super) f32);
impl Freq {
pub const ZERO: Self = Self(0.);
pub const C0: Self = Self(16.351);
pub const CS0: Self = Self(17.324);
pub const D0: Self = Self(18.354);
pub const DS0: Self = Self(19.445);
pub const E0: Self = Self(20.601);
pub const F0: Self = Self(21.827);
pub const FS0: Self = Self(23.124);
pub const G0: Self = Self(24.499);
pub const GS0: Self = Self(25.956);
pub const A0: Self = Self(27.5);
pub const AS0: Self = Self(29.135);
pub const B0: Self = Self(30.868);
pub const C1: Self = Self(32.703);
pub const CS1: Self = Self(34.648);
pub const D1: Self = Self(36.708);
pub const DS1: Self = Self(38.891);
pub const E1: Self = Self(41.203);
pub const F1: Self = Self(43.654);
pub const FS1: Self = Self(46.249);
pub const G1: Self = Self(48.999);
pub const GS1: Self = Self(51.913);
pub const A1: Self = Self(55.);
pub const AS1: Self = Self(58.27);
pub const B1: Self = Self(61.735);
pub const C2: Self = Self(65.406);
pub const CS2: Self = Self(69.296);
pub const D2: Self = Self(73.416);
pub const DS2: Self = Self(77.782);
pub const E2: Self = Self(82.407);
pub const F2: Self = Self(87.307);
pub const FS2: Self = Self(92.499);
pub const G2: Self = Self(97.999);
pub const GS2: Self = Self(103.826);
pub const A2: Self = Self(110.);
pub const AS2: Self = Self(116.541);
pub const B2: Self = Self(123.471);
pub const C3: Self = Self(130.813);
pub const CS3: Self = Self(138.591);
pub const D3: Self = Self(146.832);
pub const DS3: Self = Self(155.563);
pub const E3: Self = Self(164.814);
pub const F3: Self = Self(174.614);
pub const FS3: Self = Self(184.997);
pub const G3: Self = Self(195.998);
pub const GS3: Self = Self(207.652);
pub const A3: Self = Self(220.);
pub const AS3: Self = Self(233.082);
pub const B3: Self = Self(246.942);
pub const C4: Self = Self(261.626);
pub const CS4: Self = Self(277.183);
pub const D4: Self = Self(293.665);
pub const DS4: Self = Self(311.127);
pub const E4: Self = Self(329.628);
pub const F4: Self = Self(349.228);
pub const FS4: Self = Self(369.994);
pub const G4: Self = Self(391.995);
pub const GS4: Self = Self(415.305);
pub const A4: Self = Self(440.);
pub const AS4: Self = Self(466.164);
pub const B4: Self = Self(493.883);
pub const C5: Self = Self(523.251);
pub const CS5: Self = Self(554.365);
pub const D5: Self = Self(587.33);
pub const DS5: Self = Self(622.254);
pub const E5: Self = Self(659.255);
pub const F5: Self = Self(698.456);
pub const FS5: Self = Self(739.989);
pub const G5: Self = Self(783.991);
pub const GS5: Self = Self(830.609);
pub const A5: Self = Self(880.);
pub const AS5: Self = Self(932.328);
pub const B5: Self = Self(987.767);
pub const C6: Self = Self(1046.502);
pub const CS6: Self = Self(1108.731);
pub const D6: Self = Self(1174.659);
pub const DS6: Self = Self(1244.508);
pub const E6: Self = Self(1318.51);
pub const F6: Self = Self(1396.913);
pub const FS6: Self = Self(1479.978);
pub const G6: Self = Self(1567.982);
pub const GS6: Self = Self(1661.219);
pub const A6: Self = Self(1760.);
pub const AS6: Self = Self(1864.655);
pub const B6: Self = Self(1975.533);
pub const C7: Self = Self(2093.005);
pub const CS7: Self = Self(2217.461);
pub const D7: Self = Self(2349.318);
pub const DS7: Self = Self(2489.016);
pub const E7: Self = Self(2637.021);
pub const F7: Self = Self(2793.826);
pub const FS7: Self = Self(2959.955);
pub const G7: Self = Self(3135.964);
pub const GS7: Self = Self(3322.438);
pub const A7: Self = Self(3520.);
pub const AS7: Self = Self(3729.31);
pub const B7: Self = Self(3951.066);
pub const C8: Self = Self(4186.009);
pub const CS8: Self = Self(4434.922);
pub const D8: Self = Self(4698.636);
pub const DS8: Self = Self(4978.032);
pub const E8: Self = Self(5274.042);
pub const F8: Self = Self(5587.652);
pub const FS8: Self = Self(5919.91);
pub const G8: Self = Self(6271.928);
pub const GS8: Self = Self(6644.876);
pub const A8: Self = Self(7040.);
pub const AS8: Self = Self(7458.62);
pub const B8: Self = Self(7902.132);
pub const C9: Self = Self(8372.018);
pub const CS9: Self = Self(8869.844);
pub const D9: Self = Self(9397.272);
pub const DS9: Self = Self(9956.064);
pub const E9: Self = Self(10548.084);
pub const F9: Self = Self(11175.304);
pub const FS9: Self = Self(11839.82);
pub const G9: Self = Self(12543.856);
pub const GS9: Self = Self(13289.752);
pub const A9: Self = Self(14080.);
pub const AS9: Self = Self(14917.24);
pub const B9: Self = Self(15804.264);
#[must_use]
pub fn hz(hz: f32) -> Self {
Self(hz)
}
#[must_use]
#[expect(clippy::cast_precision_loss)]
pub fn midi(note: u8) -> Self {
let mut f: f32 = match note % 12 {
0 => 8.1758,
1 => 8.66,
2 => 9.18,
3 => 9.72,
4 => 10.30,
5 => 10.91,
6 => 11.56,
7 => 12.25,
8 => 12.98,
9 => 13.75,
10 => 14.57,
_ => 15.43,
};
let oct = note / 12;
f *= (1 << oct) as f32;
Self(f)
}
#[must_use]
#[expect(clippy::cast_precision_loss)]
pub fn note(pitch: Pitch, octave: u8) -> Self {
let mut f: f32 = match pitch {
Pitch::C => 16.351,
Pitch::Cs => 17.324,
Pitch::D => 18.354,
Pitch::Ds => 19.445,
Pitch::E => 20.601,
Pitch::F => 21.827,
Pitch::Fs => 23.124,
Pitch::G => 24.499,
Pitch::Gs => 25.956,
Pitch::A => 27.5,
Pitch::As => 29.135,
Pitch::B => 30.868,
};
f *= (1 << octave) as f32;
Freq(f)
}
}
impl From<f32> for Freq {
fn from(value: f32) -> Self {
Self(value)
}
}