1use std::cell::OnceCell;
2use std::sync::{Arc, OnceLock};
3use lazy_static::lazy_static;
4use crate::Note;
5
6#[derive(Copy, Clone)]
8pub struct Tuning {
9 notes: [f32; 128]
10}
11
12impl Tuning {
13 pub fn equal_temperament(a4: f32) -> Self {
15 let mut notes = [0.0; 128];
16 for note in 0..128 {
17 notes[note] = 440.0 * 2.0f32.powf((note as f32 - 69.0) / 12.0);
18 }
19 Self { notes }
20 }
21
22 pub fn concert_pitch() -> Arc<Self> {
24 static TUNING: OnceLock<Arc<Tuning>> = OnceLock::new();
25 TUNING.get_or_init(|| Arc::new(Self::equal_temperament(440.0))).clone()
26 }
27
28 pub fn pitch(&self, note: Note) -> f32 {
30 *self.notes.get(note as usize)
31 .expect("MIDI note must be between 0 and 127.")
32 }
33}