75 lines
2.5 KiB
Rust
75 lines
2.5 KiB
Rust
#![feature(iter_collect_into)]
|
|
use std::{sync::mpsc, thread::sleep, time::Duration};
|
|
|
|
use anyhow::{Context, Ok, Result};
|
|
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
|
use pitch_detection::{detector::{mcleod::McLeodDetector, PitchDetector}, utils};
|
|
use rust_music_theory::note::{Note, NoteLetter, Pitch, Tuning};
|
|
|
|
fn main() -> Result<()> {
|
|
// assumes pulseaudio system with f32 samples and 2204 sample packets
|
|
dbg!(cpal::available_hosts());
|
|
let host = cpal::default_host();
|
|
let device = host.devices().unwrap().find(|d|d.name().unwrap() == "pulse").context("no pulse")?;
|
|
|
|
let config = device.default_input_config()?;
|
|
|
|
dbg!(config.sample_format());
|
|
let rate = config.sample_rate();
|
|
|
|
let (sender, notes) = mpsc::channel();
|
|
|
|
const POWER_THRESHOLD: f32 = 5.0;
|
|
const CLARITY_THRESHOLD: f32 = 0.7;
|
|
const PACKET_LEN: usize = 2204;
|
|
|
|
let stream = device.build_input_stream(&config.into(),
|
|
move | data: &[f32], _: &_| {
|
|
assert!(data.len() >= PACKET_LEN);
|
|
let data = &data[..PACKET_LEN];
|
|
|
|
// reinitialized every packet as it is not thread safe
|
|
let mut detctor = McLeodDetector::new(PACKET_LEN, PACKET_LEN/2);
|
|
let vol = utils::buffer::square_sum(data);
|
|
sender.send((detctor.get_pitch(data, rate.0 as usize, POWER_THRESHOLD, CLARITY_THRESHOLD),vol)).unwrap();
|
|
|
|
},
|
|
move |err| {eprintln!("{err}")} ,
|
|
Some(Duration::from_secs(1)))?;
|
|
|
|
stream.play()?;
|
|
|
|
for (note,vol) in notes {
|
|
if let Some(note) = note {
|
|
//dbg!(note.frequency);
|
|
dbg!(note.clarity);
|
|
dbg!(vol);
|
|
let note = Note::from_freq(note.frequency, Tuning::EqualTemperament);
|
|
match note.pitch {
|
|
Pitch { letter: NoteLetter::A, accidental: 0} => {
|
|
println!("forward");
|
|
}
|
|
Pitch { letter: NoteLetter::A, accidental: 1} => {
|
|
println!("backward");
|
|
}
|
|
Pitch { letter: NoteLetter::C, accidental: 0} => {
|
|
println!("right");
|
|
}
|
|
Pitch { letter: NoteLetter::C, accidental: 1} => {
|
|
println!("left");
|
|
}
|
|
Pitch { letter: NoteLetter::G, accidental: 0} => {
|
|
println!("fire");
|
|
}
|
|
pitch => {
|
|
dbg!(pitch);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
drop(stream);
|
|
|
|
Ok(())
|
|
}
|