unnieversal/crates/utils/src/pitch/mod.rs

52 lines
1.5 KiB
Rust

pub mod pitch_detection;
pub fn generate_vocoder(sample_rate: u32) -> PhaseVocoder {
PhaseVocoder::new(1, sample_rate as f64, 256, 4)
}
// From https://github.com/nwoeanhinnogaehr/pvoc-plugins/blob/master/src/plugins/pitchshifter.rs
use pvoc::{Bin, PhaseVocoder};
pub fn pitch_shift<const LEN: usize>(
pvoc: &mut PhaseVocoder,
input: &[f32],
shift: f32,
) -> [f32; LEN] {
let shift = shift as f64;
let mut output = [0.0; LEN];
pvoc.process(
&[&input],
&mut [&mut output],
|channels: usize, bins: usize, input: &[Vec<Bin>], output: &mut [Vec<Bin>]| {
for i in 0..channels {
for j in 0..bins / 2 {
let index = ((j as f64) * shift) as usize;
if index < bins / 2 {
output[i][index].freq = input[i][j].freq * shift;
output[i][index].amp += input[i][j].amp;
}
}
}
},
);
output
}
/// Returns closest midi note to `pitch`
pub fn pitch_to_midi_note(pitch: f32) -> u8 {
// With the frequency, check the closest note
let note = 69 + (12. * (pitch / 440.).log2()).round() as i16;
note.clamp(0, 127) as u8
}
/// Returns a midi note's pitch
pub fn midi_note_to_pitch(note: u8) -> f32 {
440.0f32 * 2.0f32.powf((note as f32 - 69.) / 12.)
}
/// Returns the closest note frequency
pub fn closest_note_freq(freq: f32) -> f32 {
midi_note_to_pitch(pitch_to_midi_note(freq))
}