Download deepfilternet3_ax/session.py from HY-2012/DeepFilterNet3.AXERA: direct link, hf CLI and curl.
- Browser
- Download file 4.84 kB
-
https://huggingface.co/HY-2012/DeepFilterNet3.AXERA/resolve/main/deepfilternet3_ax/session.py
- Command line
-
hf download hf://HY-2012/DeepFilterNet3.AXERA/deepfilternet3_ax/session.py
-
curl -L -o session.py https://huggingface.co/HY-2012/DeepFilterNet3.AXERA/resolve/main/deepfilternet3_ax/session.py
4.84 kB
| """3 个 axmodel 的 axengine 会话封装 (enc/erb_dec/df_dec 流水线)。""" | |
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from pathlib import Path | |
| from typing import Any | |
| import numpy as np | |
| T = 99 # 静态时间帧 (1s @ 48kHz 流式 STFT) | |
| class TensorInfo: | |
| name: str | |
| shape: tuple[int, ...] | |
| dtype: np.dtype | |
| def _numpy_dtype(value: Any) -> np.dtype: | |
| text = str(value).lower() | |
| mapping = ( | |
| (("tensor(float)", "float32", "fp32", "f32"), np.float32), | |
| (("tensor(float16)", "float16", "fp16", "f16"), np.float16), | |
| (("tensor(int64)", "int64", "s64"), np.int64), | |
| (("tensor(int32)", "int32", "s32"), np.int32), | |
| (("tensor(uint16)", "uint16", "u16"), np.uint16), | |
| (("tensor(uint8)", "uint8", "u8"), np.uint8), | |
| ) | |
| for aliases, dtype in mapping: | |
| if any(alias in text for alias in aliases): | |
| return np.dtype(dtype) | |
| raise ValueError(f"unsupported runtime tensor dtype: {value}") | |
| def _tensor_info(value: Any) -> TensorInfo: | |
| shape = getattr(value, "shape", None) | |
| if shape is None: | |
| shape = getattr(value, "dims", None) | |
| if shape is None or any(dim is None for dim in shape): | |
| raise ValueError(f"dynamic or missing tensor shape for {value.name}: {shape}") | |
| dtype = getattr(value, "dtype", None) | |
| if dtype is None: | |
| dtype = getattr(value, "type", None) | |
| return TensorInfo( | |
| name=value.name, | |
| shape=tuple(int(dim) for dim in shape), | |
| dtype=_numpy_dtype(dtype), | |
| ) | |
| class _AxSession: | |
| """单个 axmodel 的 axengine 会话 (参考 AXERA 官方推理工程封装)。""" | |
| def __init__(self, model_path: str | Path): | |
| import axengine | |
| self.path = Path(model_path) | |
| if not self.path.is_file(): | |
| raise FileNotFoundError(self.path) | |
| self._session = axengine.InferenceSession(str(self.path)) | |
| self.inputs = [_tensor_info(v) for v in self._session.get_inputs()] | |
| self.outputs = [_tensor_info(v) for v in self._session.get_outputs()] | |
| self.input_by_name = {v.name: v for v in self.inputs} | |
| def run(self, feed: dict[str, np.ndarray]) -> dict[str, np.ndarray]: | |
| missing = [v.name for v in self.inputs if v.name not in feed] | |
| if missing: | |
| raise KeyError(f"missing inputs for {self.path.name}: {missing}") | |
| prepared = { | |
| name: np.ascontiguousarray(np.asarray(feed[name], dtype=meta.dtype)) | |
| for name, meta in self.input_by_name.items() | |
| } | |
| values = self._session.run(None, prepared) | |
| if isinstance(values, dict): | |
| return {name: np.asarray(v) for name, v in values.items()} | |
| if not isinstance(values, (list, tuple)): | |
| values = [values] | |
| if len(values) != len(self.outputs): | |
| raise RuntimeError( | |
| f"unexpected output count from {self.path.name}: " | |
| f"{len(values)} != {len(self.outputs)}") | |
| return {meta.name: np.asarray(v) for meta, v in zip(self.outputs, values)} | |
| class DfNet3Ax: | |
| """DeepFilterNet3 三子图 NPU 流水线 (与 dsp.pipeline 配合)。 | |
| enc: feat_erb(1,1,T,32)+feat_spec(1,2,T,96) -> e0..e3, emb, c0, lsnr | |
| erb_dec: emb,e3,e2,e1,e0 -> m(1,1,T,32) | |
| df_dec: emb,c0 -> coefs(1,T,96,10) | |
| """ | |
| def __init__(self, model_dir: str | Path): | |
| model_dir = Path(model_dir) | |
| self.enc = _AxSession(model_dir / "enc.axmodel") | |
| self.erb_dec = _AxSession(model_dir / "erb_dec.axmodel") | |
| self.df_dec = _AxSession(model_dir / "df_dec.axmodel") | |
| # 状态携带模式检测: axmodel 是否有 h0 输入 | |
| self.stateful = all("h0" in s.input_by_name for s in (self.enc, self.df_dec)) | |
| def run_enc(self, feat_erb: np.ndarray, feat_spec: np.ndarray, | |
| h: np.ndarray | None = None) -> tuple[dict[str, np.ndarray], np.ndarray | None]: | |
| feed = {"feat_erb": feat_erb, "feat_spec": feat_spec} | |
| if self.stateful: | |
| if h is None: | |
| h = np.zeros((1, 1, 256), np.float32) | |
| feed["h0"] = h | |
| out = self.enc.run(feed) | |
| return out, np.asarray(out["h_out"]) | |
| return self.enc.run(feed), None | |
| def run_erb_dec(self, emb, e3, e2, e1, e0) -> np.ndarray: | |
| return self.erb_dec.run({"emb": emb, "e3": e3, "e2": e2, "e1": e1, "e0": e0})["m"] | |
| def run_df_dec(self, emb, c0, h: np.ndarray | None = None) -> tuple[np.ndarray, np.ndarray | None]: | |
| feed = {"emb": emb, "c0": c0} | |
| if self.stateful: | |
| if h is None: | |
| h = np.zeros((2, 1, 256), np.float32) | |
| feed["h0"] = h | |
| out = self.df_dec.run(feed) | |
| return np.asarray(out["coefs"]), np.asarray(out["h_out"]) | |
| return self.df_dec.run(feed)["coefs"], None | |