feat: wire up all effects to audio processing pipeline
- Updated queue system to pass effects as dict instead of individual params - Updated process_queue to handle effects_dict for previews - Updated speak_message to extract all 7 effects from user settings - Updated _generate_wav_bytes to accept effects dict and pass all params - Updated _handle_voice_preview to use new effects dict system - Effects now actually process the audio: - pitch, speed, echo, robot, chorus, tremolo_depth, tremolo_rate - Fixed preview effect description to use preview_effects dict
This commit is contained in:
76
bot.py
76
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)
|
||||
|
||||
Reference in New Issue
Block a user