From 0c87fcc48cbeeb0fcd266ca0b65096fa48838acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6kmen=20G=C3=B6rgen?= Date: Mon, 9 Mar 2026 13:47:50 +0100 Subject: [PATCH] re-add bypass parameter support to `AICFilter` and update related unit tests. --- src/pipecat/audio/filters/aic_filter.py | 18 ++++++++++++++++-- tests/test_aic_filter.py | 22 +++++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/pipecat/audio/filters/aic_filter.py b/src/pipecat/audio/filters/aic_filter.py index 5e8c5bc41..fd4e927c2 100644 --- a/src/pipecat/audio/filters/aic_filter.py +++ b/src/pipecat/audio/filters/aic_filter.py @@ -260,6 +260,7 @@ class AICFilter(BaseAudioFilter): ) self._enhancement_level = enhancement_level self._is_filter_enabled = True + self._bypass = False self._sample_rate = 0 self._aic_ready = False @@ -348,6 +349,13 @@ class AICFilter(BaseAudioFilter): logger.debug(f"AIC EnhancementLevel set_parameter out-of-range: {e}") self._enhancement_level = None + def _apply_bypass(self): + """Apply bypass parameter to the active processor.""" + if self._processor_ctx is None: + return + + self._processor_ctx.set_parameter(ProcessorParameter.Bypass, 1.0 if self._bypass else 0.0) + async def start(self, sample_rate: int): """Initialize the filter with the transport's sample rate. @@ -396,7 +404,8 @@ class AICFilter(BaseAudioFilter): self._processor_ctx = self._processor.get_processor_context() self._vad_ctx = self._processor.get_vad_context() - # Apply initial enhancement settings (if configured) + # Apply initial control parameters + self._apply_bypass() self._apply_enhancement_level() # Log processor information @@ -451,8 +460,13 @@ class AICFilter(BaseAudioFilter): """ if isinstance(frame, FilterEnableFrame): self._is_filter_enabled = frame.enable + self._bypass = not frame.enable if self._processor_ctx is not None: - self._apply_enhancement_level() + try: + self._apply_bypass() + self._apply_enhancement_level() + except Exception as e: # noqa: BLE001 + logger.error(f"AIC set_parameter failed: {e}") async def filter(self, audio: bytes) -> bytes: """Apply AIC enhancement to audio data. diff --git a/tests/test_aic_filter.py b/tests/test_aic_filter.py index 3dc284f32..f47b38233 100644 --- a/tests/test_aic_filter.py +++ b/tests/test_aic_filter.py @@ -178,6 +178,7 @@ class TestAICFilter(unittest.IsolatedAsyncioTestCase): self.assertIsNone(filter_instance._model_path) self.assertIsNone(filter_instance._enhancement_level) self.assertTrue(filter_instance._is_filter_enabled) + self.assertFalse(filter_instance._bypass) async def test_initialization_with_model_path(self): """Test filter initialization with model_path.""" @@ -284,8 +285,8 @@ class TestAICFilter(unittest.IsolatedAsyncioTestCase): self.assertIsNotNone(filter_instance._processor_ctx) self.assertIsNotNone(filter_instance._vad_ctx) - async def test_start_does_not_apply_bypass_parameter(self): - """Test that start does not set SDK Bypass parameter.""" + async def test_start_applies_initial_bypass_parameter(self): + """Test that start applies SDK Bypass parameter.""" filter_instance = self._create_filter_with_mocks() await self._start_filter_with_mocks(filter_instance) @@ -294,7 +295,8 @@ class TestAICFilter(unittest.IsolatedAsyncioTestCase): for p, v in self.mock_processor.processor_ctx.parameters_set if p == aic_sdk.ProcessorParameter.Bypass ] - self.assertEqual(bypass_params, []) + self.assertTrue(len(bypass_params) > 0) + self.assertEqual(bypass_params[-1][1], 0.0) async def test_start_applies_enhancement_level_when_supported(self): """Test that start applies enhancement_level when supported by model.""" @@ -533,8 +535,15 @@ class TestAICFilter(unittest.IsolatedAsyncioTestCase): for p, v in self.mock_processor.processor_ctx.parameters_set if p == aic_sdk.ProcessorParameter.EnhancementLevel ] + bypass_params = [ + (p, v) + for p, v in self.mock_processor.processor_ctx.parameters_set + if p == aic_sdk.ProcessorParameter.Bypass + ] self.assertFalse(filter_instance._is_filter_enabled) + self.assertTrue(filter_instance._bypass) self.assertEqual(enhancement_params[-1][1], 0.0) + self.assertEqual(bypass_params[-1][1], 1.0) async def test_process_frame_enable_restores_configured_enhancement(self): """Test enable frame restores configured enhancement level.""" @@ -549,8 +558,15 @@ class TestAICFilter(unittest.IsolatedAsyncioTestCase): for p, v in self.mock_processor.processor_ctx.parameters_set if p == aic_sdk.ProcessorParameter.EnhancementLevel ] + bypass_params = [ + (p, v) + for p, v in self.mock_processor.processor_ctx.parameters_set + if p == aic_sdk.ProcessorParameter.Bypass + ] self.assertTrue(filter_instance._is_filter_enabled) + self.assertFalse(filter_instance._bypass) self.assertEqual(enhancement_params[-1][1], 0.7) + self.assertEqual(bypass_params[-1][1], 0.0) async def test_filter_when_not_ready(self): """Test that filter returns audio unchanged when not ready."""