diff --git a/bot.py b/bot.py index 23df3cd..1164990 100644 --- a/bot.py +++ b/bot.py @@ -514,18 +514,25 @@ class TTSBot(commands.Bot): # Use user's current effects if not overridden user_effects = self.voice_manager.get_user_effects(interaction.user.id) - final_pitch = preview_pitch if preview_pitch is not None else user_effects["pitch"] - final_speed = preview_speed if preview_speed is not None else user_effects["speed"] - + effect_overrides = {} + if preview_pitch is not None: + effect_overrides["pitch"] = preview_pitch + if preview_speed is not None: + effect_overrides["speed"] = preview_speed + + # Use default effects from user settings for preview + preview_effects = user_effects.copy() + preview_effects.update(effect_overrides) + # Queue the preview with voice override and effects - await self.message_queue.put((preview_message, preview_text, voice_name, final_pitch, final_speed)) + await self.message_queue.put((preview_message, preview_text, voice_name, preview_effects)) # Build effect description effect_desc = [] - if final_pitch != 0: - effect_desc.append(f"pitch: {final_pitch:+d}") - if final_speed != 1.0: - effect_desc.append(f"speed: {final_speed:.1f}x") + if preview_effects.get("pitch", 0) != 0: + effect_desc.append(f"pitch: {preview_effects['pitch']:+d}") + if preview_effects.get("speed", 1.0) != 1.0: + effect_desc.append(f"speed: {preview_effects['speed']:.1f}x") effect_str = f" (with {', '.join(effect_desc)})" if effect_desc else "" @@ -622,24 +629,22 @@ class TTSBot(commands.Bot): while True: queue_item = await self.message_queue.get() - # Handle queue items of different lengths: + # Handle queue items: # - (message, text) - regular message - # - (message, text, voice_name) - preview with voice override - # - (message, text, voice_name, pitch, speed) - preview with effects - if len(queue_item) == 5: - message, text, voice_override, pitch, speed = queue_item + # - (message, text, voice_override) - preview with voice override + # - (message, text, voice_override, effects_dict) - preview with effect overrides + if len(queue_item) == 4 and isinstance(queue_item[3], dict): + message, text, voice_override, effect_overrides = queue_item elif len(queue_item) == 3: message, text, voice_override = queue_item - pitch = None - speed = None + effect_overrides = {} else: message, text = queue_item voice_override = None - pitch = None - speed = None + effect_overrides = {} try: - await self.speak_message(message, text, voice_override, pitch, speed) + await self.speak_message(message, text, voice_override, effect_overrides) except Exception as e: print(f"Error processing message: {e}") finally: @@ -650,8 +655,7 @@ class TTSBot(commands.Bot): message: discord.Message, text: str, voice_override: str | None = None, - pitch: int | None = None, - speed: float | None = None, + effect_overrides: dict | None = None, ) -> None: """Generate TTS and play it in the user's voice channel.""" if message.author.voice is None: @@ -685,16 +689,14 @@ class TTSBot(commands.Bot): ) return - # Get user's effects if not overridden - if pitch is None or speed is None: - user_effects = self.voice_manager.get_user_effects(message.author.id) - if pitch is None: - pitch = user_effects["pitch"] - if speed is None: - speed = user_effects["speed"] + # Get user's effects and apply any overrides + user_effects = self.voice_manager.get_user_effects(message.author.id) + effects = user_effects.copy() + if effect_overrides: + effects.update(effect_overrides) wav_bytes = await asyncio.to_thread( - self._generate_wav_bytes, voice_state, text, pitch, speed + self._generate_wav_bytes, voice_state, text, effects ) audio_source = discord.FFmpegPCMAudio( @@ -723,8 +725,7 @@ class TTSBot(commands.Bot): self, voice_state: Any, text: str, - pitch: int = 0, - speed: float = 1.0, + effects: dict, ) -> bytes: """Generate audio and return as WAV file bytes.""" model = self.voice_manager.model @@ -739,12 +740,21 @@ class TTSBot(commands.Bot): audio_np = audio_np.reshape(-1, 1) # Apply audio effects if any are active - if pitch != 0 or speed != 1.0: - print(f"Applying effects - Pitch: {pitch:+d}, Speed: {speed:.1f}x") + pitch = effects.get("pitch", AudioEffects.PITCH_DEFAULT) + speed = effects.get("speed", AudioEffects.SPEED_DEFAULT) + echo = effects.get("echo", AudioEffects.ECHO_DEFAULT) + robot = effects.get("robot", AudioEffects.ROBOT_DEFAULT) + chorus = effects.get("chorus", AudioEffects.CHORUS_DEFAULT) + tremolo_depth = effects.get("tremolo_depth", AudioEffects.TREMOLO_DEPTH_DEFAULT) + tremolo_rate = effects.get("tremolo_rate", AudioEffects.TREMOLO_RATE_DEFAULT) + + if any([pitch != 0, speed != 1.0, echo > 0, robot > 0, chorus > 0, tremolo_depth > 0]): + print(f"Applying {AudioEffects.count_active_effects(**effects)} effect(s)...") # Squeeze to 1D for librosa effects, then reshape back audio_1d = audio_np.squeeze() audio_1d, show_processing = AudioEffects.apply_effects( - audio_1d, model.sample_rate, pitch, speed + audio_1d, model.sample_rate, + pitch, speed, echo, robot, chorus, tremolo_depth, tremolo_rate ) # Reshape back to 2D audio_np = audio_1d.reshape(-1, 1)