use pyo3::prelude::*;
use crate::{Mfcc, MfccParams};
use super::params::PyMfccParams;
use super::spectrogram::{PyArrayData, PyScalar, real_dlpack};
#[pyclass(name = "Mfcc", skip_from_py_object)]
pub struct PyMfcc {
data: PyArrayData,
params: MfccParams,
n_bins: usize,
n_frames: usize,
}
impl PyMfcc {
pub(crate) fn from_mfcc<T: PyScalar>(py: Python<'_>, mfcc: Mfcc<T>) -> Self {
let n_bins = mfcc.data.nrows();
let n_frames = mfcc.data.ncols();
let params = *mfcc.params();
let data = T::into_array_data(py, mfcc.data);
Self {
data,
params,
n_bins,
n_frames,
}
}
}
#[pymethods]
impl PyMfcc {
#[getter]
fn data<'py>(&self, py: Python<'py>) -> Bound<'py, PyAny> {
self.data.bind(py)
}
#[getter]
const fn dtype(&self) -> &'static str {
self.data.dtype()
}
#[getter]
const fn n_frames(&self) -> usize {
self.n_frames
}
#[getter]
const fn n_bins(&self) -> usize {
self.n_bins
}
#[getter]
const fn shape(&self) -> (usize, usize) {
(self.n_bins, self.n_frames)
}
#[getter]
fn params(&self) -> PyMfccParams {
PyMfccParams::from(self.params)
}
#[pyo3(signature = (dtype=None))]
fn __array__<'py>(
&self,
py: Python<'py>,
dtype: Option<&Bound<'py, PyAny>>,
) -> PyResult<Bound<'py, PyAny>> {
let arr = self.data.bind(py);
if let Some(dt) = dtype {
arr.call_method1("astype", (dt,))
} else {
Ok(arr)
}
}
#[staticmethod]
const fn __dlpack_device__() -> (i32, i32) {
(1, 0) }
#[pyo3(signature = (*, stream=None, max_version=None, dl_device=None, copy=None))]
fn __dlpack__<'py>(
&self,
py: Python<'py>,
stream: Option<&Bound<'py, PyAny>>,
max_version: Option<(u32, u32)>,
dl_device: Option<(i32, i32)>,
copy: Option<bool>,
) -> PyResult<Bound<'py, pyo3::types::PyCapsule>> {
real_dlpack(py, &self.data, stream, max_version, dl_device, copy)
}
fn __repr__(&self) -> String {
format!(
"Mfcc(shape=({}, {}), dtype={})",
self.n_bins,
self.n_frames,
self.dtype()
)
}
}