From 39b0f2bbed74f6487a41b82501ae3c6799e4b5c4 Mon Sep 17 00:00:00 2001 From: historia Date: Sun, 6 Sep 2026 20:55:27 -0400 Subject: feat: chunking, zipenhancer denoising --- lib/tests/test_cli.py | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) (limited to 'lib/tests/test_cli.py') diff --git a/lib/tests/test_cli.py b/lib/tests/test_cli.py index 1a157f7..76952ba 100644 --- a/lib/tests/test_cli.py +++ b/lib/tests/test_cli.py @@ -2,6 +2,7 @@ import sys from types import SimpleNamespace import numpy as np +import pytest import soundfile as sf from conftest import speechish @@ -165,6 +166,74 @@ def test_default_output_suffix_processed(tmp_path): assert _resolve_output(inp, opts, single=False) == odir / "song_processed.wav" +def test_engine_chunk_flags(): + args = build_parser().parse_args(["in.wav", "--engine-chunk", "15", "--engine-overlap", "1.0"]) + opts = Options() + _apply_args(opts, args) + assert opts.engine_chunk_s == 15.0 + assert opts.engine_overlap_s == 1.0 + + +def test_default_options_whole_file_and_soft_denoise(): + opts = Options() + assert opts.engine_chunk_s == 0.0 + assert opts.denoise_strength == 0.9 + + +def test_engine_chunk_validation(): + with pytest.raises(SystemExit): + args = build_parser().parse_args(["in.wav", "--engine-chunk", "5", "--engine-overlap", "5"]) + _apply_args(Options(), args) + with pytest.raises(SystemExit): + args = build_parser().parse_args(["in.wav", "--engine-chunk", "-1"]) + _apply_args(Options(), args) + + +def test_engine_chunk_config_override(tmp_path): + from producer import config as cfgmod + + cfg = tmp_path / "config.toml" + cfg.write_text("engine_chunk = 10.0\nengine_overlap = 1.0\n") + opts = Options() + cfgmod.apply_config(opts, cfgmod.load_config(cfg)) + assert opts.engine_chunk_s == 10.0 + assert opts.engine_overlap_s == 1.0 + + +def test_denoise_pf_flag_and_config_plumbing(tmp_path): + from producer import config as cfgmod + + opts = Options() + _apply_args(opts, build_parser().parse_args(["in.wav"])) + assert opts.denoise_pf is False + + opts = Options() + _apply_args(opts, build_parser().parse_args(["in.wav", "--denoise-pf"])) + assert opts.denoise_pf is True + + cfg = tmp_path / "config.toml" + cfg.write_text('[denoise]\nengine = "dfn3"\nstrength = 0.8\npf = true\n') + opts = Options() + cfgmod.apply_config(opts, cfgmod.load_config(cfg)) + assert opts.denoise_strength == 0.8 + assert opts.denoise_pf is True + + +def test_spectral_denoise_choice(tmp_path): + from producer import config as cfgmod + + opts = Options() + _apply_args(opts, build_parser().parse_args(["in.wav", "--denoise", "spectral"])) + assert opts.denoise == "spectral" + + cfg = tmp_path / "config.toml" + cfg.write_text('[denoise]\nengine = "spectral"\nstrength = 0.8\n') + opts = Options() + cfgmod.apply_config(opts, cfgmod.load_config(cfg)) + assert opts.denoise == "spectral" + assert opts.denoise_strength == 0.8 + + def test_conflict_auto_renames_when_not_a_tty(tmp_path): inp = _mk_wav(tmp_path, "in.wav") first = process_one(inp, _opts(), single=True) @@ -228,3 +297,61 @@ def test_conflict_prompt_eof_cancels(tmp_path, monkeypatch): monkeypatch.setattr("builtins.input", _eof) assert process_one(inp, _opts(), single=True) is None + + +def test_process_one_reports_stage_status(tmp_path, capsys): + inp = _mk_wav(tmp_path, "status.wav") + out_path = process_one(inp, _opts(), single=True) + assert out_path is not None + out = capsys.readouterr().out + assert f"[producer] {inp} (" in out + assert "dsp done in" in out + assert "levelling done in" in out + assert f"[producer] wrote {out_path}" in out + + +def test_multi_file_run_gets_position_prefixes(tmp_path, capsys): + from producer.cli import main + + a = _mk_wav(tmp_path, "a.wav") + b = _mk_wav(tmp_path, "b.wav") + rc = main([str(a), str(b), "--denoise", "off"]) + assert rc == 0 + out = capsys.readouterr().out + assert "[1/2]" in out and "[2/2]" in out + assert (tmp_path / "a_processed.wav").exists() + assert (tmp_path / "b_processed.wav").exists() + + +def test_output_file_rejected_for_multiple_inputs(tmp_path): + from producer.cli import main + + a = _mk_wav(tmp_path, "a.wav") + b = _mk_wav(tmp_path, "b.wav") + with pytest.raises(SystemExit): + main([str(a), str(b), "-o", str(tmp_path / "out.wav"), "--denoise", "off"]) + + +def test_output_dir_accepted_for_multiple_inputs(tmp_path): + from producer.cli import main + + a = _mk_wav(tmp_path, "a.wav") + b = _mk_wav(tmp_path, "b.wav") + outdir = tmp_path / "masters" + rc = main([str(a), str(b), "-o", str(outdir), "--denoise", "off"]) + assert rc == 0 + assert (outdir / "a_processed.wav").exists() + assert (outdir / "b_processed.wav").exists() + + +def test_batch_failure_continues_to_next_file(tmp_path, capsys): + from producer.cli import main + + good = _mk_wav(tmp_path, "good.wav") + missing = tmp_path / "missing.wav" + rc = main([str(missing), str(good), "--denoise", "off"]) + assert rc == 1 + captured = capsys.readouterr() + assert "[2/2]" in captured.out + assert "[producer] ERROR" in captured.err + assert (tmp_path / "good_processed.wav").exists() -- cgit v1.2.3