aboutsummaryrefslogtreecommitdiff
path: root/lib/tests/test_engines.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-09-07 06:47:47 -0400
committerhistoria <historiavg@proton.me>2026-09-07 06:47:47 -0400
commit84dd2d068317998f6fb59400c534ef5be6b51b53 (patch)
tree025293e9d9229e02960374771ae522d9de2628ce /lib/tests/test_engines.py
parent39b0f2bbed74f6487a41b82501ae3c6799e4b5c4 (diff)
downloadproducer-84dd2d068317998f6fb59400c534ef5be6b51b53.tar.gz
slop rewriteHEADmain
Diffstat (limited to 'lib/tests/test_engines.py')
-rw-r--r--lib/tests/test_engines.py515
1 files changed, 0 insertions, 515 deletions
diff --git a/lib/tests/test_engines.py b/lib/tests/test_engines.py
deleted file mode 100644
index 9881859..0000000
--- a/lib/tests/test_engines.py
+++ /dev/null
@@ -1,515 +0,0 @@
-import os
-import sys
-import types
-import warnings
-
-import numpy as np
-import pytest
-
-AUDIO_META_MSG = (
- "`torchaudio.backend.common.AudioMetaData` has been moved to "
- "`torchaudio.AudioMetaData`. Please update the import path."
-)
-
-
-class _FakeTensor:
- def __init__(self, arr):
- self.arr = np.asarray(arr)
-
- def unsqueeze(self, axis):
- return _FakeTensor(self.arr[None, ...])
-
- def detach(self):
- return self
-
- def cpu(self):
- return self
-
- def numpy(self):
- return self.arr
-
-
-def _install_torch_stub(monkeypatch):
- fake = types.ModuleType("torch")
- fake.Tensor = _FakeTensor
- fake.from_numpy = lambda a: _FakeTensor(a)
- fake.cuda = types.SimpleNamespace(is_available=lambda: False)
- monkeypatch.setitem(sys.modules, "torch", fake)
-
-
-def _install_df_enhance_stub(monkeypatch, transform, calls, records=None):
- pkg = types.ModuleType("df")
-
- class _State:
- def sr(self):
- return 44100
-
- class _Model:
- def to(self, dev):
- return self
-
- def init_df(*_args, **kwargs):
- if records is not None:
- records["init_df"] = kwargs
- return _Model(), _State(), "fake"
-
- def enhance(_model, _state, audio, **kwargs):
- calls.append(audio.arr.shape[-1])
- if records is not None:
- records["enhance"] = kwargs
- return _FakeTensor(transform(audio.arr.copy()))
-
- pkg.enhance = types.ModuleType("df.enhance")
- pkg.enhance.init_df = init_df
- pkg.enhance.enhance = enhance
- for sub in ("df.io", "df.logger", "df.utils"):
- mod = types.ModuleType(sub)
- setattr(pkg, sub.split(".")[1], mod)
- monkeypatch.setitem(sys.modules, sub, mod)
- monkeypatch.setitem(sys.modules, "df", pkg)
- monkeypatch.setitem(sys.modules, "df.enhance", pkg.enhance)
-
-
-def test_dfn3_chunked_engine_stitches_full_length(monkeypatch, sr, noisy_speech):
- from producer.engines import denoise_dfn
-
- monkeypatch.setattr("producer.lazy.ensure", lambda *_a, **_k: None)
- monkeypatch.setattr("producer.lazy.ensure_torch", lambda: None)
- _install_torch_stub(monkeypatch)
- calls: list[int] = []
- _install_df_enhance_stub(monkeypatch, lambda a: a * 0.5 + 0.001, calls)
-
- x = noisy_speech[: sr * 4]
- y, eng, dev = denoise_dfn.denoise(x, sr, 1.0, "cpu", chunk_s=1.0, overlap_s=0.1)
- assert "dfn" in eng
- assert "cpu" in dev
- assert len(calls) > 2
- assert y.shape == x.shape
- np.testing.assert_allclose(y, x * 0.5 + 0.001, atol=1e-6)
-
-
-def test_dfn3_whole_file_mode_single_call(monkeypatch, sr, noisy_speech):
- from producer.engines import denoise_dfn
-
- monkeypatch.setattr("producer.lazy.ensure", lambda *_a, **_k: None)
- monkeypatch.setattr("producer.lazy.ensure_torch", lambda: None)
- _install_torch_stub(monkeypatch)
- calls: list[int] = []
- _install_df_enhance_stub(monkeypatch, lambda a: a * 0.5, calls)
-
- x = noisy_speech[: sr * 2]
- y, _eng, _dev = denoise_dfn.denoise(x, sr, 1.0, "cpu", chunk_s=0.0)
- assert calls == [x.size]
- np.testing.assert_allclose(y, x * 0.5, atol=1e-7)
-
-
-def test_dfn3_post_filter_opt_in_no_atten_lim(monkeypatch, sr, noisy_speech):
- from producer.engines import denoise_dfn
-
- monkeypatch.setattr("producer.lazy.ensure", lambda *_a, **_k: None)
- monkeypatch.setattr("producer.lazy.ensure_torch", lambda: None)
- _install_torch_stub(monkeypatch)
- calls: list[int] = []
- records: dict = {}
- _install_df_enhance_stub(monkeypatch, lambda a: a * 0.5, calls, records)
-
- x = noisy_speech[: sr * 2]
- denoise_dfn.denoise(x, sr, 1.0, "cpu", chunk_s=0.0)
- assert records["init_df"]["post_filter"] is False
- assert records["enhance"] == {} # stock df_enhance call, no atten-lim override
-
- calls.clear()
- records.clear()
- denoise_dfn.denoise(x, sr, 1.0, "cpu", chunk_s=0.0, post_filter=True)
- assert records["init_df"]["post_filter"] is True
-
-
-def test_dfn3_chunked_feeds_context_padding(monkeypatch, sr, noisy_speech):
- from producer.engines import denoise_dfn
-
- monkeypatch.setattr("producer.lazy.ensure", lambda *_a, **_k: None)
- monkeypatch.setattr("producer.lazy.ensure_torch", lambda: None)
- _install_torch_stub(monkeypatch)
- calls: list[int] = []
- _install_df_enhance_stub(monkeypatch, lambda a: a * 0.5, calls)
-
- x = noisy_speech[: sr * 10]
- y, _eng, _dev = denoise_dfn.denoise(x, sr, 1.0, "cpu", chunk_s=3.0, overlap_s=0.5)
- # chunks are widened with context, then trimmed back to the spans
- assert max(calls) > 3.0 * sr
- assert min(calls) >= 3.0 * sr
- np.testing.assert_allclose(y, x * 0.5, atol=1e-7)
-
-
-_Z_MODEL_REPO = "iic/speech_zipenhancer_ans_multiloss_16k_base"
-
-
-def _install_zipenhancer_stub(monkeypatch, calls):
- fake = types.ModuleType("zipenhancer")
- fake.MODEL_ZIPENHANCER = _Z_MODEL_REPO
-
- def denoise(chunk, sample_rate, model=_Z_MODEL_REPO, normalize=True, strength=1.0, **_kw):
- calls.append(
- {"n": chunk.size, "model": model, "normalize": normalize, "strength": strength}
- )
- scale = 0.1 if len(calls) % 2 == 1 else 1.0
- return (chunk * scale, 0.0, chunk.size / sample_rate)
-
- fake.denoise = denoise
- monkeypatch.setitem(sys.modules, "zipenhancer", fake)
-
-
-def test_zipenhancer_chunked_normalizes_once(monkeypatch, sr):
- from producer.engines import denoise_zip
-
- seq: list[str] = []
- monkeypatch.setattr(
- "producer.lazy.ensure",
- lambda pkgs, **_k: seq.append("ensure:" + ",".join(str(p) for p in pkgs)),
- )
- monkeypatch.setattr("producer.lazy.ensure_torch", lambda: seq.append("torch"))
- monkeypatch.setattr(
- "producer.lazy.ensure_import", lambda mod, **_k: seq.append("import:" + mod)
- )
- monkeypatch.setattr("producer.lazy.ensure_call", lambda fn, **_k: (seq.append("call"), fn())[1])
- calls: list[dict] = []
- _install_zipenhancer_stub(monkeypatch, calls)
-
- n = 4 * 44100
- t = np.arange(n) / sr
- x = (0.5 * np.sin(2 * np.pi * 160.0 * t)).astype(np.float32)
- y, eng, _dev = denoise_zip.denoise(x, sr, 1.0, "cpu", chunk_s=1.0, overlap_s=0.0)
- assert "zipenhancer" in eng
- # torch is pinned before package installs; the undeclared modelscope
- # import ships with the engine; import and call probes run after both
- assert seq == [
- "torch",
- "ensure:zipenhancer==0.3.2,modelscope",
- "import:zipenhancer",
- "call",
- "call",
- "call",
- "call",
- ]
- assert len(calls) == 4
- # the library API takes the full modelscope repo id; the short name
- # would be treated as a repo id and fail with modelscope E3021
- assert all(c["model"] == _Z_MODEL_REPO for c in calls)
- assert all(c["normalize"] is False for c in calls)
- assert y.shape == x.shape
- peak = float(np.max(np.abs(y)))
- assert abs(peak - 10 ** (-3.0 / 20.0)) < 0.01
- even_rms = float(np.sqrt(np.mean(y[: n // 4].astype(np.float64) ** 2)))
- odd_rms = float(np.sqrt(np.mean(y[n // 4 : n // 2].astype(np.float64) ** 2)))
- assert 8.0 < odd_rms / even_rms < 12.0
-
-
-def test_zipenhancer_resample_roundtrip_length_realigned(monkeypatch):
- # 120s @ 48k round-tripped through the 16k engine can come back a sample
- # or two long (resample_poly emits ceil(n * up/down) per hop); the blend
- # used to crash on the mismatch instead of realigning
- from producer.engines import denoise_zip
-
- monkeypatch.setattr("producer.lazy.ensure_torch", lambda: None)
- monkeypatch.setattr("producer.lazy.ensure", lambda *_a, **_k: None)
- calls: list[dict] = []
- _install_zipenhancer_stub(monkeypatch, calls)
-
- sr = 48000
- n = 100001 # 48k -> 16k -> 48k drifts +1 for this length
- x = (0.3 * np.sin(2 * np.pi * 220.0 * np.arange(n) / sr)).astype(np.float32)
- y, _eng, _dev = denoise_zip.denoise(x, sr, 0.5, "cpu")
- assert y.shape == x.shape
-
-
-def test_mossformer_clearvoice_probe(monkeypatch, sr, noisy_speech):
- from producer.engines import enhance_mossformer
-
- seq: list[str] = []
- monkeypatch.setattr("producer.lazy.ensure_torch", lambda: seq.append("torch"))
- monkeypatch.setattr(
- "producer.lazy.ensure",
- lambda pkgs, **_k: seq.append("ensure:" + ",".join(str(p) for p in pkgs)),
- )
- monkeypatch.setattr(
- "producer.lazy.ensure_import", lambda mod, **_k: seq.append("import:" + mod)
- )
-
- fake = types.ModuleType("clearvoice")
-
- class _FakeCV:
- def __init__(self, task=None, model_name=None):
- pass
-
- def __call__(self, chunk):
- return (chunk * 0.5, 48000)
-
- fake.ClearVoice = _FakeCV
- monkeypatch.setitem(sys.modules, "clearvoice", fake)
-
- x = noisy_speech[: sr * 4]
- y, eng, _dev = enhance_mossformer.enhance(x, 48000, 1.0, "cpu", chunk_s=2.0)
- assert "mossformer2" in eng
- assert seq == ["torch", "ensure:clearvoice==0.1.2", "import:clearvoice"]
- assert y.shape == x.shape
- np.testing.assert_allclose(y, x * 0.5, atol=1e-6)
-
-
-def _hissy_speech(sr, dur=12.0, noise_db=-42.0, seed=3):
- from conftest import speechish
-
- x = speechish(dur, sr, level_dbfs=-20.0, seed=seed)
- rng = np.random.default_rng(seed)
- noise = rng.standard_normal(x.size)
- noise *= (10 ** (noise_db / 20.0)) / np.sqrt(np.mean(np.square(noise)))
- return (x + noise).astype(np.float32)
-
-
-def test_spectral_reduces_steady_noise(sr):
- from producer import meters
- from producer.engines import denoise_spectral
-
- x = _hissy_speech(sr)
- y, eng, dev = denoise_spectral.denoise(x, sr, 1.0, "cpu")
- assert "spectral" in eng and dev == "cpu"
- assert y.shape == x.shape
- assert np.all(np.isfinite(y))
- assert meters.noise_floor_db(y, sr) < meters.noise_floor_db(x, sr) - 8.0
- assert np.corrcoef(x.astype(np.float64), y.astype(np.float64))[0, 1] > 0.8
-
-
-def test_spectral_speech_level_flat(sr):
- from producer.engines import denoise_spectral
-
- x = _hissy_speech(sr)
- y, _eng, _dev = denoise_spectral.denoise(x, sr, 1.0, "cpu")
- frame = int(0.03 * sr)
- nf = x.size // frame
-
- def frms_db(z):
- rms = np.sqrt(np.mean(z[: nf * frame].reshape(nf, frame).astype(np.float64) ** 2, axis=1))
- return 20.0 * np.log10(rms + 1e-12)
-
- xdb, ydb = frms_db(x), frms_db(y)
- speech = xdb > np.percentile(xdb, 10) + 12.0
- assert speech.sum() > 20
- # the deterministic engine must not pump the speech level (dfn3's failure mode)
- swing = np.abs(ydb[speech] - xdb[speech])
- assert np.percentile(swing, 95) < 2.0
-
-
-def test_spectral_strength_zero_is_identity(sr):
- from producer.engines import denoise_spectral
-
- x = _hissy_speech(sr)
- y, _eng, _dev = denoise_spectral.denoise(x, sr, 0.0, "cpu")
- np.testing.assert_array_equal(y, x)
-
-
-def test_spectral_sample_aligned(sr):
- from producer.engines import denoise_spectral
-
- x = _hissy_speech(sr)
- y, _eng, _dev = denoise_spectral.denoise(x, sr, 1.0, "cpu")
- lo, hi = int(sr * 2.0), int(sr * 9.0)
- corrs = {k: float(np.corrcoef(x[lo:hi], y[lo + k : hi + k])[0, 1]) for k in range(-3, 4)}
- assert max(corrs, key=corrs.get) == 0
- assert corrs[0] > 0.8
-
-
-def test_spectral_suppression_capped(sr):
- from producer import meters
- from producer.engines import denoise_spectral
-
- noise = (0.008 * np.random.default_rng(5).standard_normal(sr * 6)).astype(np.float32)
- y, _eng, _dev = denoise_spectral.denoise(noise, sr, 1.0, "cpu")
- drop = meters.noise_floor_db(noise, sr) - meters.noise_floor_db(y, sr)
- # bounded: deep enough to matter, never gated to digital silence
- assert 20.0 < drop < 40.0
-
-
-def test_spectral_chunked_matches_whole_file(sr):
- from producer.engines import denoise_spectral
-
- x = _hissy_speech(sr, dur=20.0)
- y1, _e, _d = denoise_spectral.denoise(x, sr, 1.0, "cpu", chunk_s=60.0, overlap_s=0.5)
- y2, _e, _d = denoise_spectral.denoise(x, sr, 1.0, "cpu", chunk_s=8.0, overlap_s=0.5)
- assert y1.shape == y2.shape == x.shape
- corr = np.corrcoef(y1.astype(np.float64), y2.astype(np.float64))[0, 1]
- assert corr > 0.99
-
-
-def test_spectral_profile_global_not_per_chunk(sr):
- """Tail hiss must get the same suppression with or without speech up front.
-
- The old per-chunk percentile leaked speech into the noise estimate and
- under-suppressed exactly where it matters (between sentences).
- """
- from conftest import speechish
-
- from producer import meters
- from producer.engines import denoise_spectral
-
- speech = speechish(8.0, sr, level_dbfs=-20.0, seed=11)
- rng = np.random.default_rng(9)
- noise = rng.standard_normal(sr * 16).astype(np.float32)
- noise *= (10 ** (-40.0 / 20.0)) / np.sqrt(np.mean(np.square(noise)))
- tail_lo, tail_hi = sr * 10, sr * 16
- with_speech = np.concatenate([speech + noise[: speech.size], noise[speech.size :]]).astype(
- np.float32
- )
- hiss_only = noise.copy()
- y1, _e, _d = denoise_spectral.denoise(with_speech, sr, 1.0, "cpu")
- y2, _e, _d = denoise_spectral.denoise(hiss_only, sr, 1.0, "cpu")
- drop1 = meters.noise_floor_db(with_speech[tail_lo:tail_hi], sr) - meters.noise_floor_db(
- y1[tail_lo:tail_hi], sr
- )
- drop2 = meters.noise_floor_db(hiss_only[tail_lo:tail_hi], sr) - meters.noise_floor_db(
- y2[tail_lo:tail_hi], sr
- )
- assert drop1 > 14.0
- assert drop1 > drop2 - 4.0
-
-
-def _stub_df_modules(calls: list[str]) -> tuple[types.ModuleType, list[types.ModuleType]]:
- pkg = types.ModuleType("df")
- mods = []
- for full in ("df.utils", "df.logger", "df.io"):
- mod = types.ModuleType(full)
-
- def probe(name: str):
- def fn(*_args):
- calls.append(name)
- return "deadbeef"
-
- return fn
-
- for fn_name in ("get_git_root", "get_commit_hash", "get_branch_name"):
- setattr(mod, fn_name, probe(f"{full}.{fn_name}"))
- setattr(pkg, full.split(".")[1], mod)
- mods.append(mod)
- return pkg, mods
-
-
-def test_dfn_shim_neutralizes_git_probes(monkeypatch):
- from producer.engines import denoise_dfn
-
- calls: list[str] = []
- pkg, mods = _stub_df_modules(calls)
- for name, mod in zip(("df", "df.utils", "df.logger", "df.io"), (pkg, *mods), strict=True):
- monkeypatch.setitem(sys.modules, name, mod)
- assert pkg.logger.get_commit_hash() == "deadbeef"
- calls.clear()
- denoise_dfn._shim_df_git()
- for mod in mods:
- for fn_name in ("get_git_root", "get_commit_hash", "get_branch_name"):
- assert mod.__dict__[fn_name]() is None
- assert calls == []
-
-
-def test_dfn_shim_silences_torchaudio_warning():
- from producer.engines import denoise_dfn
-
- code = "import warnings\nwarnings.warn(MESSAGE, UserWarning)"
- denoise_dfn._shim_torchaudio_backend()
- with warnings.catch_warnings(record=True) as caught:
- exec(compile(code, "df/io.py", "exec"), {"__name__": "df.io", "MESSAGE": AUDIO_META_MSG})
- assert caught == []
- with warnings.catch_warnings(record=True) as caught:
- exec(
- compile(code, "other/mod.py", "exec"),
- {"__name__": "other.mod", "MESSAGE": AUDIO_META_MSG},
- )
- assert len(caught) == 1
-
-
-def _metrics_floor(x, sr):
- from producer import meters
-
- return meters.noise_floor_db(x, sr)
-
-
-@pytest.mark.slow
-def test_dfn3_reduces_noise(sr, noisy_speech):
- pytest.importorskip("torch")
- pytest.importorskip("df")
- from producer.engines import denoise_dfn
-
- x = noisy_speech[: sr * 4]
- y, eng, _dev = denoise_dfn.denoise(x, sr, 1.0, "cpu")
- assert "dfn" in eng
- assert _metrics_floor(y, sr) < _metrics_floor(x, sr) - 5.0
- assert np.corrcoef(x, y.astype(np.float64))[0, 1] > 0.9
-
-
-@pytest.mark.slow
-def test_dfn3_speech_level_flat(sr, noisy_speech):
- """Guard against dfn3's reported failure mode: volume wobble in sentences."""
- pytest.importorskip("torch")
- pytest.importorskip("df")
- from producer.engines import denoise_dfn
-
- x = noisy_speech[: sr * 8]
- y, _eng, _dev = denoise_dfn.denoise(x, sr, 0.9, "cpu")
- frame = int(0.03 * sr)
- nf = x.size // frame
-
- def frms_db(z):
- rms = np.sqrt(np.mean(z[: nf * frame].reshape(nf, frame).astype(np.float64) ** 2, axis=1))
- return 20.0 * np.log10(rms + 1e-12)
-
- xdb, ydb = frms_db(x), frms_db(y)
- speech = xdb > np.percentile(xdb, 10) + 12.0
- swing = np.abs(ydb[speech] - xdb[speech])
- assert np.percentile(swing, 95) < 2.5
-
-
-@pytest.mark.slow
-def test_dfn3_chunked_matches_whole_file(sr, noisy_speech):
- pytest.importorskip("torch")
- pytest.importorskip("df")
- from producer.engines import denoise_dfn
-
- x = noisy_speech[: sr * 60]
- y_full, _, _ = denoise_dfn.denoise(x, sr, 1.0, "cpu", chunk_s=0.0)
- y_chunk, _, _ = denoise_dfn.denoise(x, sr, 1.0, "cpu", chunk_s=15.0, overlap_s=0.5)
- assert y_full.shape == y_chunk.shape == x.shape
- corr = np.corrcoef(y_full.astype(np.float64), y_chunk.astype(np.float64))[0, 1]
- assert corr > 0.99
- assert float(np.max(np.abs(y_full - y_chunk))) < 0.1
-
-
-@pytest.mark.slow
-def test_zipenhancer_reduces_noise(sr, noisy_speech):
- pytest.importorskip("torch")
- pytest.importorskip("zipenhancer")
- from producer.engines import denoise_zip
-
- x = noisy_speech[: sr * 4]
- y, eng, _ = denoise_zip.denoise(x, sr, 1.0, "cpu")
- assert "zipenhancer" in eng
- assert _metrics_floor(y, sr) < _metrics_floor(x, sr) - 5.0
-
-
-@pytest.mark.slow
-def test_mossformer2_enhances(sr, noisy_speech):
- pytest.importorskip("torch")
- pytest.importorskip("clearvoice")
- from producer.engines import enhance_mossformer
-
- x = noisy_speech[: sr * 4]
- y, eng, _ = enhance_mossformer.enhance(x, sr, 1.0, "cpu")
- assert "mossformer2" in eng
- assert np.all(np.isfinite(y))
-
-
-@pytest.mark.slow
-def test_resemble_enhance(sr, noisy_speech):
- if not os.environ.get("PRODUCER_TEST_RESEMBLE"):
- pytest.skip("set PRODUCER_TEST_RESEMBLE=1 to run the isolated-venv generative engine")
- from producer.engines import enhance_resemble
-
- x = noisy_speech[: sr * 4]
- y, eng, _ = enhance_resemble.enhance(x, sr, 1.0, "cpu")
- assert "resemble" in eng
- assert np.all(np.isfinite(y))