"""noise_reduction_config 领域模型单测.""" from __future__ import annotations import pytest from packages.domain.noise_reduction_config import ( DEFAULT_LEVEL, DEFAULT_NOISE_FLOOR, MAX_NOISE_FLOOR, MIN_NOISE_FLOOR, NoiseReductionConfig, NoiseReductionLevel, apply_noise_reduction_if_needed, build_afftdn_filter, build_arnndn_filter, get_level_names, ) # ── NoiseReductionLevel 枚举测试 ─────────────────────────────────────────── class TestNoiseReductionLevel: def test_four_levels(self): assert len(NoiseReductionLevel) == 4 def test_level_values(self): assert NoiseReductionLevel.LOW.value == "low" assert NoiseReductionLevel.MEDIUM.value == "medium" assert NoiseReductionLevel.HIGH.value == "high" assert NoiseReductionLevel.CUSTOM.value == "custom" def test_from_string(self): assert NoiseReductionLevel("low") == NoiseReductionLevel.LOW assert NoiseReductionLevel("medium") == NoiseReductionLevel.MEDIUM assert NoiseReductionLevel("high") == NoiseReductionLevel.HIGH assert NoiseReductionLevel("custom") == NoiseReductionLevel.CUSTOM # ── NoiseReductionConfig.from_dict 测试 ─────────────────────────────────── class TestNoiseReductionConfigFromDict: def test_none_returns_disabled(self): cfg = NoiseReductionConfig.from_dict(None) assert cfg.enabled is False def test_empty_dict_returns_disabled(self): cfg = NoiseReductionConfig.from_dict({}) assert cfg.enabled is False def test_disabled_returns_disabled(self): cfg = NoiseReductionConfig.from_dict({"enabled": False}) assert cfg.enabled is False def test_enabled_default_params(self): cfg = NoiseReductionConfig.from_dict({"enabled": True}) assert cfg.enabled is True assert cfg.level == NoiseReductionLevel.MEDIUM assert cfg.noise_floor == DEFAULT_NOISE_FLOOR assert cfg.voice_enhance is False def test_custom_level(self): cfg = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": -30.0}) assert cfg.level == NoiseReductionLevel.CUSTOM assert cfg.noise_floor == -30.0 def test_invalid_level_defaults_medium(self): cfg = NoiseReductionConfig.from_dict({"enabled": True, "level": "invalid"}) assert cfg.level == NoiseReductionLevel.MEDIUM def test_noise_floor_clamped_low(self): cfg = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": -100.0}) assert cfg.noise_floor == MIN_NOISE_FLOOR def test_noise_floor_clamped_high(self): cfg = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": 0.0}) assert cfg.noise_floor == MAX_NOISE_FLOOR def test_invalid_noise_floor_type_uses_default(self): cfg = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": "not_a_number"}) assert cfg.noise_floor == DEFAULT_NOISE_FLOOR def test_voice_enhance_true(self): cfg = NoiseReductionConfig.from_dict({"enabled": True, "voice_enhance": True}) assert cfg.voice_enhance is True def test_case_insensitive_level(self): cfg = NoiseReductionConfig.from_dict({"enabled": True, "level": "HIGH"}) assert cfg.level == NoiseReductionLevel.HIGH # ── has_effect / get_effective_noise_floor 测试 ─────────────────────────── class TestConfigProperties: def test_disabled_no_effect(self): cfg = NoiseReductionConfig(enabled=False) assert cfg.has_effect() is False def test_enabled_has_effect(self): cfg = NoiseReductionConfig(enabled=True) assert cfg.has_effect() is True def test_effective_noise_floor_low(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.LOW) assert cfg.get_effective_noise_floor() == -35.0 def test_effective_noise_floor_medium(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.MEDIUM) assert cfg.get_effective_noise_floor() == -25.0 def test_effective_noise_floor_high(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.HIGH) assert cfg.get_effective_noise_floor() == -15.0 def test_effective_noise_floor_custom(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.CUSTOM, noise_floor=-40.0) assert cfg.get_effective_noise_floor() == -40.0 def test_get_level_params_medium(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.MEDIUM) params = cfg.get_level_params() assert params["nf"] == -25.0 assert params["tn"] == -10.0 assert params["tr"] == 50.0 def test_get_level_params_custom(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.CUSTOM, noise_floor=-30.0) params = cfg.get_level_params() assert params["nf"] == -30.0 assert "tn" in params assert "tr" in params # ── validate 测试 ───────────────────────────────────────────────────────── class TestValidate: def test_disabled_valid(self): cfg = NoiseReductionConfig(enabled=False) ok, msg = cfg.validate() assert ok is True assert msg == "" def test_enabled_valid(self): cfg = NoiseReductionConfig(enabled=True, noise_floor=-25.0) ok, msg = cfg.validate() assert ok is True def test_noise_floor_out_of_range(self): cfg = NoiseReductionConfig(enabled=True, noise_floor=-100.0) ok, msg = cfg.validate() assert ok is False assert "noise_floor" in msg # ── build_afftdn_filter 测试 ─────────────────────────────────────────────── class TestBuildAfftdnFilter: def test_disabled_returns_anull(self): cfg = NoiseReductionConfig(enabled=False) result = build_afftdn_filter(cfg, "[in]", "[out]") assert "anull" in result assert "[in]" in result assert "[out]" in result def test_medium_level(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.MEDIUM) result = build_afftdn_filter(cfg, "[a]", "[nr]") assert "afftdn=" in result assert "nf=-25.0" in result or "nf=-25" in result assert "[a]" in result assert "[nr]" in result def test_high_level(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.HIGH) result = build_afftdn_filter(cfg, "[in]", "[out]") assert "afftdn=" in result assert "nf=-15.0" in result or "nf=-15" in result def test_low_level(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.LOW) result = build_afftdn_filter(cfg, "[in]", "[out]") assert "afftdn=" in result assert "nf=-35.0" in result or "nf=-35" in result def test_custom_level(self): cfg = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.CUSTOM, noise_floor=-40.0) result = build_afftdn_filter(cfg, "[in]", "[out]") assert "afftdn=" in result assert "nf=-40.0" in result or "nf=-40" in result def test_voice_enhance_adds_filters(self): cfg = NoiseReductionConfig(enabled=True, voice_enhance=True) result = build_afftdn_filter(cfg, "[in]", "[out]") assert "highpass" in result assert "acompressor" in result assert "loudnorm" in result def test_no_voice_enhance_no_extra_filters(self): cfg = NoiseReductionConfig(enabled=True, voice_enhance=False) result = build_afftdn_filter(cfg, "[in]", "[out]") assert "highpass" not in result assert "acompressor" not in result # ── build_arnndn_filter 测试 ─────────────────────────────────────────────── class TestBuildArnndnFilter: def test_disabled_returns_anull(self): cfg = NoiseReductionConfig(enabled=False) result = build_arnndn_filter(cfg, "[in]", "[out]", "model.rnnn") assert "anull" in result def test_enabled_returns_arnndn(self): cfg = NoiseReductionConfig(enabled=True) result = build_arnndn_filter(cfg, "[a]", "[nr]", "/path/to/model.rnnn") assert "arnndn=" in result assert "m=/path/to/model.rnnn" in result assert "[a]" in result assert "[nr]" in result # ── apply_noise_reduction_if_needed 测试 ───────────────────────────────── class TestApplyNoiseReductionIfNeeded: def test_none_config_returns_none(self): assert apply_noise_reduction_if_needed(None, "[in]", "[out]") is None def test_disabled_returns_none(self): assert apply_noise_reduction_if_needed({"enabled": False}, "[in]", "[out]") is None def test_enabled_returns_filter(self): result = apply_noise_reduction_if_needed({"enabled": True, "level": "medium"}, "[in]", "[out]") assert result is not None assert "afftdn" in result def test_invalid_config_handles_exception(self): # 异常情况应该返回 None 而不是抛出 result = apply_noise_reduction_if_needed("invalid", "[in]", "[out]") assert result is None # ── 工具函数测试 ─────────────────────────────────────────────────────────── class TestUtils: def test_get_level_names_returns_four(self): names = get_level_names() assert len(names) == 4 assert "low" in names assert "medium" in names assert "high" in names assert "custom" in names