use crate::inference::native_model::fbank::{
FFT_SIZE, MelTable, SPECTRUM_BINS, hamming_window, mel_filters,
};
pub(super) use crate::inference::native_model::fbank::{
ENERGY_FLOOR, FBANK_FRAME_LENGTH, FBANK_FRAME_SHIFT, PREEMPHASIS, WAVEFORM_SCALE,
};
pub use crate::inference::native_model::fbank::{
FBANK_FRAMES, FBANK_MEL_BINS, FBANK_WINDOW_SAMPLES,
};
#[cfg(any(feature = "migraphx", feature = "coreml"))]
const _: () = assert!(FBANK_FRAMES == crate::inference::embedding::FBANK_FRAMES);
const _: () = assert!(FBANK_MEL_BINS == crate::inference::embedding::FBANK_FEATURES);
pub(super) const SPECTRUM_COLUMNS: usize = SPECTRUM_BINS + (SPECTRUM_BINS - 2);
pub(super) const MEL_GEMM_BINS: usize = SPECTRUM_BINS - 1;
#[derive(Debug, Clone)]
pub struct FbankConstants {
window: Vec<f32>,
dft_basis: Vec<f32>,
mel: Vec<f32>,
mel_table: MelTable,
}
impl FbankConstants {
pub fn new() -> Self {
let mel = mel_filters();
let mel_table = MelTable::new(&mel);
Self {
window: hamming_window(),
dft_basis: dft_basis(),
mel,
mel_table,
}
}
pub fn window(&self) -> &[f32] {
&self.window
}
pub fn dft_basis(&self) -> &[f32] {
&self.dft_basis
}
pub fn mel(&self) -> &[f32] {
&self.mel
}
pub(in crate::inference::cuda) fn mel_table(&self) -> &MelTable {
&self.mel_table
}
}
impl Default for FbankConstants {
fn default() -> Self {
Self::new()
}
}
fn dft_basis() -> Vec<f32> {
let angle = |bin: usize, sample: usize| {
std::f64::consts::TAU * ((bin * sample) % FFT_SIZE) as f64 / FFT_SIZE as f64
};
let mut basis = Vec::with_capacity(FBANK_FRAME_LENGTH * SPECTRUM_COLUMNS);
for sample in 0..FBANK_FRAME_LENGTH {
basis.extend((0..SPECTRUM_BINS).map(|bin| angle(bin, sample).cos() as f32));
basis.extend((1..SPECTRUM_BINS - 1).map(|bin| angle(bin, sample).sin() as f32));
}
basis
}