redo noisegate to fix voice presense

This commit is contained in:
Logan Cusano
2025-07-14 21:34:08 -04:00
parent f893209f36
commit 9040462171
2 changed files with 123 additions and 154 deletions

View File

@@ -4,7 +4,7 @@ import os
from discord import VoiceClient, VoiceChannel, opus, Activity, ActivityType, Intents
from discord.ext import commands
from typing import Optional, Dict
from internal.NoiseGatev2 import NoiseGate
from internal.NoiseGatev2 import AudioTransmitter
from internal.logger import create_logger
LOGGER = create_logger(__name__)
@@ -18,7 +18,6 @@ class DiscordBotManager:
def __init__(self):
self.bot: Optional[commands.Bot] = None
self.bot_task: Optional[asyncio.Task] = None
# This dictionary will hold both the client and its audio stream handler
self.voice_connections: Dict[int, Dict] = {}
self.token: Optional[str] = None
self.loop = asyncio.get_event_loop()
@@ -83,7 +82,6 @@ class DiscordBotManager:
async def stop_bot(self):
async with self.lock:
if self.bot:
# Disconnect from all voice channels cleanly
for guild_id in list(self.voice_connections.keys()):
await self.leave_voice_channel(guild_id)
await self.bot.close()
@@ -112,20 +110,23 @@ class DiscordBotManager:
await asyncio.wait_for(self._voice_ready_event.wait(), timeout=15.0)
LOGGER.info("Bot voice connection is ready.")
stream_handler = NoiseGate(
_voice_connection=voice_client,
_noise_gate_threshold=ng_threshold,
# **THE FIX**: Pass the event loop to the stream handler.
# Create and start the new AudioTransmitter
transmitter = AudioTransmitter(
voice_client=voice_client,
noise_gate_threshold=ng_threshold,
loop=self.loop,
_input_device_index=device_id
input_device_index=device_id
)
stream_handler.run()
# Start the transmitter's main loop as a background task
transmitter_task = self.loop.create_task(transmitter.start())
self.voice_connections[guild_id] = {
"client": voice_client,
"stream": stream_handler
"transmitter": transmitter,
"task": transmitter_task
}
LOGGER.info(f"Joined guild {guild_id} and audio stream is now running.")
LOGGER.info(f"Joined guild {guild_id} and audio transmitter is running.")
except asyncio.TimeoutError:
LOGGER.error(f"Timeout waiting for bot to join voice channel {channel_id}.")
@@ -140,12 +141,16 @@ class DiscordBotManager:
connection_info = self.voice_connections.get(guild_id)
if not connection_info: raise RuntimeError("Not connected to the specified guild's voice channel.")
stream_handler = connection_info.get('stream')
if stream_handler:
LOGGER.info(f"Stopping audio stream for guild {guild_id}.")
await stream_handler.close()
# Stop the transmitter task and clean up its resources
transmitter = connection_info.get("transmitter")
task = connection_info.get("task")
if transmitter:
LOGGER.info(f"Stopping audio transmitter for guild {guild_id}.")
await transmitter.stop()
if task and not task.done():
task.cancel()
voice_client = connection_info.get('client')
voice_client = connection_info.get("client")
if voice_client and voice_client.is_connected():
await voice_client.disconnect()
@@ -153,15 +158,16 @@ class DiscordBotManager:
LOGGER.info(f"Left guild {guild_id} voice channel.")
async def load_opus(self):
# ... this method is unchanged ...
processor = platform.machine()
script_dir = os.path.dirname(os.path.abspath(__file__))
LOGGER.debug(f"Processor: {processor}, OS: {os.name}")
try:
if os.name == 'nt': # Windows
if os.name == 'nt':
if processor == "AMD64":
opus.load_opus(os.path.join(script_dir, './opus/libopus_amd64.dll'))
LOGGER.info("Loaded OPUS library for AMD64")
else: # Linux / other
else:
if processor == "aarch64":
opus.load_opus(os.path.join(script_dir, './opus/libopus_aarcch64.so'))
LOGGER.info("Loaded OPUS library for aarch64")
@@ -169,7 +175,6 @@ class DiscordBotManager:
opus.load_opus(os.path.join(script_dir, './opus/libopus_armv7l.so'))
LOGGER.info("Loaded OPUS library for armv7l")
else:
# Fallback for other Linux archs like x86_64
opus.load_opus('libopus.so.0')
LOGGER.info(f"Loaded system OPUS library for {processor}")
except Exception as e:
@@ -177,6 +182,7 @@ class DiscordBotManager:
raise RuntimeError("Could not load a valid Opus library. Voice functionality will fail.")
async def set_presence(self, system_name: str):
# ... this method is unchanged ...
if not self.bot or not self.bot.is_ready():
LOGGER.warning("Bot is not ready, cannot set presence.")
return