From f0dcf399464f3c434c4773fba8176f03cdbae641 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Thu, 1 Feb 2024 16:55:14 -0600 Subject: [PATCH] Add --mic-channel-index --- wyoming_satellite/__main__.py | 6 ++++++ wyoming_satellite/satellite.py | 30 ++++++++++++++++++++++++++---- wyoming_satellite/settings.py | 3 +++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/wyoming_satellite/__main__.py b/wyoming_satellite/__main__.py index 74f4289..9bcb284 100644 --- a/wyoming_satellite/__main__.py +++ b/wyoming_satellite/__main__.py @@ -85,6 +85,11 @@ async def main() -> None: action="store_true", help="Don't mute the microphone while awake wav is being played", ) + parser.add_argument( + "--mic-channel-index", + type=int, + help="Take microphone input from a specific channel (first channel is 0)", + ) # Sound output parser.add_argument("--snd-uri", help="URI of Wyoming sound service") @@ -321,6 +326,7 @@ async def main() -> None: noise_suppression=args.mic_noise_suppression, seconds_to_mute_after_awake_wav=args.mic_seconds_to_mute_after_awake_wav, mute_during_awake_wav=(not args.mic_no_mute_during_awake_wav), + channel_index=args.mic_channel_index, ), vad=VadSettings( enabled=args.vad, diff --git a/wyoming_satellite/satellite.py b/wyoming_satellite/satellite.py index 492c54b..3f2a19a 100644 --- a/wyoming_satellite/satellite.py +++ b/wyoming_satellite/satellite.py @@ -1,4 +1,5 @@ """Satellite code.""" +import array import asyncio import logging import math @@ -458,15 +459,36 @@ class SatelliteBase: continue # Audio processing - if self.settings.mic.needs_processing and AudioChunk.is_type( - event.type + if ( + self.settings.mic.needs_processing + or (self.settings.mic.channel_index is not None) + and AudioChunk.is_type(event.type) ): chunk = AudioChunk.from_event(event) - audio_bytes = self._process_mic_audio(chunk.audio) + if self.settings.mic.channel_index is not None: + if chunk.width != 2: + raise ValueError( + "Mic channel index selection requires 16-bit samples" + ) + + # Convert to unsigned 16-bit array to make channel extraction easier + audio_array = array.array("H", chunk.audio) + audio_bytes = audio_array[ + self.settings.mic.channel_index :: chunk.channels + ].tobytes() + + if self.settings.mic.needs_processing: + if audio_bytes is None: + audio_bytes = chunk.audio + + audio_bytes = self._process_mic_audio(chunk.audio) + event = AudioChunk( rate=chunk.rate, width=chunk.width, - channels=chunk.channels, + channels=chunk.channels + if (self.settings.mic.channel_index is None) + else 1, audio=audio_bytes, ).event() else: diff --git a/wyoming_satellite/settings.py b/wyoming_satellite/settings.py index 82084d8..903ff27 100644 --- a/wyoming_satellite/settings.py +++ b/wyoming_satellite/settings.py @@ -55,6 +55,9 @@ class MicSettings(ServiceSettings): seconds_to_mute_after_awake_wav: float = 0.5 """Extra second(s) of microphone audio to mute after awake WAV has finished playing.""" + channel_index: Optional[int] = None + """Index of microphone channel to use. When not set, all input channels are used as-is.""" + @property def needs_webrtc(self) -> bool: """True if webrtc audio enhancements are needed."""