52 lines
1.5 KiB
Rust
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::{FreqBin, 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<FreqBin>], output: &mut [Vec<FreqBin>]| {
|
|
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))
|
|
}
|