use thiserror::Error;
#[derive(Debug, Clone, Copy)]
pub struct PitchFrame {
pub frame_index: u64,
pub time_s: f32,
pub pitch_hz: f32,
pub confidence: f32,
pub is_preliminary: bool,
}
#[derive(Debug, Error)]
pub enum EstimatorError {
#[error("ONNX runtime error: {0}")]
Ort(String),
#[error("TorchScript error: {0}")]
TorchScript(String),
#[error("resample error: {0}")]
Resample(String),
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("not implemented: {0}")]
NotImplemented(String),
#[error("io: {0}")]
Io(#[from] std::io::Error),
}
pub type Result<T> = std::result::Result<T, EstimatorError>;
pub trait PitchEstimator: Send {
fn name(&self) -> &str;
fn target_sample_rate(&self) -> u32;
fn process(&mut self, audio_target_sr: &[f32]) -> Result<Vec<PitchFrame>>;
fn reset(&mut self) {}
}
#[inline]
pub fn calibrate_confidence(t: Option<f32>, raw: f32) -> f32 {
#[cfg(feature = "confidence-calibration")]
if let Some(t_val) = t {
let p = raw.clamp(1e-7, 1.0 - 1e-7);
let logit = (p / (1.0 - p)).ln();
return 1.0 / (1.0 + (-logit / t_val).exp());
}
let _ = t;
raw
}