pub fn midi_pitch_to_frequency(pitch: f64) -> f64 {
(2.0_f64).powf((pitch - 69.0) / 12.0) * 440.0
}
pub fn frequency_to_midi_pitch(frequency: f64) -> f64 {
(frequency / 440.0).log2() * 12.0 + 69.0
}
pub fn midi_pitch_to_tone_period(pitch: f64, clock_rate: f64) -> u16 {
frequency_to_tone_period(midi_pitch_to_frequency(pitch), clock_rate)
}
pub fn midi_pitch_to_envelope_period(pitch: f64, clock_rate: f64) -> u16 {
frequency_to_envelope_period(midi_pitch_to_frequency(pitch), clock_rate)
}
pub fn tone_period_to_midi_pitch(period: u16, clock_rate: f64) -> f64 {
frequency_to_midi_pitch(tone_period_to_frequency(period, clock_rate))
}
pub fn envelope_period_to_midi_pitch(period: u16, clock_rate: f64) -> f64 {
frequency_to_midi_pitch(envelope_period_to_frequency(period, clock_rate))
}
pub fn frequency_to_tone_period(frequency: f64, clock_rate: f64) -> u16 {
(clock_rate / (16.0 * frequency)).round() as u16
}
pub fn frequency_to_envelope_period(frequency: f64, clock_rate: f64) -> u16 {
(clock_rate / (256.0 * frequency)).round() as u16
}
pub fn tone_period_to_frequency(period: u16, clock_rate: f64) -> f64 {
clock_rate / (period as f64 * 16.0)
}
pub fn envelope_period_to_frequency(period: u16, clock_rate: f64) -> f64 {
clock_rate / (period as f64 * 256.0)
}
#[cfg(test)]
mod tests {
#[test]
fn midi_pitch_to_frequency() {
assert_eq!(super::midi_pitch_to_frequency(81.0), 880.0);
assert_eq!(super::midi_pitch_to_frequency(69.0), 440.0);
assert_eq!(super::midi_pitch_to_frequency(57.0), 220.0);
}
#[test]
fn frequency_to_midi_pitch() {
assert_eq!(super::frequency_to_midi_pitch(880.0), 81.0);
assert_eq!(super::frequency_to_midi_pitch(440.0), 69.0);
assert_eq!(super::frequency_to_midi_pitch(220.0), 57.0);
}
#[test]
fn tone_period_midi_conversion() {
let period = super::midi_pitch_to_tone_period(57.0, 4400000.0);
let pitch = super::tone_period_to_midi_pitch(period, 4400000.0);
assert_eq!(pitch, 57.0);
let frequency = super::tone_period_to_midi_pitch(100, 4400000.0);
let period = super::midi_pitch_to_tone_period(frequency, 4400000.0);
assert_eq!(period, 100);
}
#[test]
fn envelope_period_midi_conversion() {
let period = super::midi_pitch_to_envelope_period(21.0, 4400000.0);
let pitch = super::envelope_period_to_midi_pitch(period, 4400000.0);
assert_eq!(pitch, 21.0);
let frequency = super::envelope_period_to_midi_pitch(100, 4400000.0);
let period = super::midi_pitch_to_envelope_period(frequency, 4400000.0);
assert_eq!(period, 100);
}
#[test]
fn tone_period_conversion() {
let period = super::frequency_to_tone_period(100.0, 1000000.0);
let frequency = super::tone_period_to_frequency(period, 1000000.0);
println!("{} {}", period, frequency);
assert_eq!(frequency, 100.0);
let frequency = super::tone_period_to_frequency(100, 1000000.0);
let period = super::frequency_to_tone_period(frequency, 1000000.0);
assert_eq!(period, 100);
}
#[test]
fn envelop_period_conversion() {
let period = super::frequency_to_envelope_period(1.25, 1000000.0);
let frequency = super::envelope_period_to_frequency(period, 1000000.0);
println!("{} {}", period, frequency);
assert_eq!(frequency, 1.25);
let frequency = super::envelope_period_to_frequency(100, 1000000.0);
let period = super::frequency_to_envelope_period(frequency, 1000000.0);
assert_eq!(period, 100);
}
}