#![allow(dead_code)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Stage {
Hpf,
SilenceDetect,
Ingest,
PitchSearch,
PitchTrack,
SignalSpectrum,
RefinePitch,
Vuv,
Amplitude,
MatchedDecoder,
Tail,
DibitUnpack,
DecodeFrame,
Dequantize,
Enhance,
Smoothing,
SynthUnvoiced,
SynthVoiced,
SynthMix,
}
impl Stage {
pub const ALL: &'static [Stage] = &[
Stage::Hpf,
Stage::SilenceDetect,
Stage::Ingest,
Stage::PitchSearch,
Stage::PitchTrack,
Stage::SignalSpectrum,
Stage::RefinePitch,
Stage::Vuv,
Stage::Amplitude,
Stage::MatchedDecoder,
Stage::Tail,
Stage::DibitUnpack,
Stage::DecodeFrame,
Stage::Dequantize,
Stage::Enhance,
Stage::Smoothing,
Stage::SynthUnvoiced,
Stage::SynthVoiced,
Stage::SynthMix,
];
pub const fn label(self) -> &'static str {
match self {
Stage::Hpf => "hpf",
Stage::SilenceDetect => "silence_detect",
Stage::Ingest => "ingest",
Stage::PitchSearch => "pitch_search",
Stage::PitchTrack => "pitch_track",
Stage::SignalSpectrum => "signal_spectrum",
Stage::RefinePitch => "refine_pitch",
Stage::Vuv => "vuv",
Stage::Amplitude => "amplitude",
Stage::MatchedDecoder => "matched_decoder",
Stage::Tail => "tail",
Stage::DibitUnpack => "dibit_unpack",
Stage::DecodeFrame => "decode_frame",
Stage::Dequantize => "dequantize",
Stage::Enhance => "enhance",
Stage::Smoothing => "smoothing",
Stage::SynthUnvoiced => "synth_unvoiced",
Stage::SynthVoiced => "synth_voiced",
Stage::SynthMix => "synth_mix",
}
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Timings {
pub total_ns: [u64; 19],
pub frames: u64,
pub decode_frames: u64,
}
impl Timings {
pub fn entries(&self) -> impl Iterator<Item = (Stage, u64)> + '_ {
Stage::ALL.iter().enumerate().map(|(i, &s)| (s, self.total_ns[i]))
}
pub fn total_ns_sum(&self) -> u64 {
self.total_ns.iter().copied().sum()
}
}
#[cfg(feature = "profile")]
mod inner {
use super::Stage;
use std::cell::RefCell;
use std::time::Instant;
thread_local! {
static T: RefCell<super::Timings> = RefCell::new(super::Timings::default());
}
pub fn time<R>(stage: Stage, f: impl FnOnce() -> R) -> R {
let t0 = Instant::now();
let r = f();
let dt = t0.elapsed().as_nanos() as u64;
T.with(|t| {
let mut t = t.borrow_mut();
t.total_ns[stage as usize] = t.total_ns[stage as usize].saturating_add(dt);
if matches!(stage, Stage::Hpf) {
t.frames = t.frames.saturating_add(1);
} else if matches!(stage, Stage::DibitUnpack) {
t.decode_frames = t.decode_frames.saturating_add(1);
}
});
r
}
pub fn snapshot() -> super::Timings {
T.with(|t| *t.borrow())
}
pub fn reset() {
T.with(|t| *t.borrow_mut() = super::Timings::default());
}
}
#[cfg(not(feature = "profile"))]
mod inner {
use super::Stage;
#[inline(always)]
pub fn time<R>(_stage: Stage, f: impl FnOnce() -> R) -> R {
f()
}
pub fn snapshot() -> super::Timings {
super::Timings::default()
}
pub fn reset() {}
}
#[inline(always)]
pub fn time<R>(stage: Stage, f: impl FnOnce() -> R) -> R {
inner::time(stage, f)
}
pub fn snapshot() -> Timings {
inner::snapshot()
}
pub fn reset() {
inner::reset()
}