1132 lines
37 KiB
Python
1132 lines
37 KiB
Python
"""
|
||
音频混响和效果插件主文件
|
||
提供专业的音频混响和效果处理功能
|
||
"""
|
||
|
||
import math
|
||
import time
|
||
import uuid
|
||
from typing import Dict, List, Optional, Any, Callable
|
||
from plugins.plugin_manager import BasePlugin
|
||
from panda3d.core import AudioSound, NodePath
|
||
|
||
class Plugin(BasePlugin):
|
||
"""
|
||
音频混响和效果插件
|
||
提供专业的音频混响和效果处理功能
|
||
"""
|
||
|
||
def __init__(self, plugin_manager, name):
|
||
super().__init__(plugin_manager, name)
|
||
self.config = {
|
||
"version": "1.0.0",
|
||
"author": "EG Team",
|
||
"description": "专业的音频混响和效果处理插件,支持多种高级音频效果"
|
||
}
|
||
|
||
# 核心组件
|
||
self.audio_manager = None
|
||
self.listener = None
|
||
|
||
# 效果处理器
|
||
self.reverb_processor = None
|
||
self.eq_processor = None
|
||
self.compressor_processor = None
|
||
self.modulation_processor = None
|
||
self.distortion_processor = None
|
||
self.spatial_processor = None
|
||
|
||
# 效果管理
|
||
self.effects = {} # 所有效果
|
||
self.sound_effects = {} # 音效与效果的关联
|
||
self.presets = {} # 效果预设
|
||
|
||
# GUI元素
|
||
self.gui_elements = []
|
||
|
||
# 事件处理器
|
||
self.event_handlers = {}
|
||
|
||
# 插件状态
|
||
self.is_initialized = False
|
||
self.is_enabled = False
|
||
self.processing_enabled = True
|
||
|
||
# 性能监控
|
||
self.performance_stats = {
|
||
'initialization_time': 0.0,
|
||
'enable_time': 0.0,
|
||
'last_update_time': 0.0,
|
||
'total_updates': 0,
|
||
'total_processing_time': 0.0,
|
||
'effects_processed': 0,
|
||
'memory_usage': 0
|
||
}
|
||
|
||
# 配置参数
|
||
self.master_volume = 1.0
|
||
self.quality_settings = 'high' # low, medium, high
|
||
self.max_effects_per_sound = 8
|
||
self.buffer_size = 4096
|
||
|
||
def initialize(self) -> bool:
|
||
"""
|
||
初始化插件
|
||
"""
|
||
try:
|
||
if self.is_initialized:
|
||
return True
|
||
|
||
init_start_time = time.time()
|
||
print(f"初始化音频混响和效果插件: {self.name}")
|
||
|
||
# 初始化音频管理器
|
||
self.audio_manager = self.plugin_manager.world.audio_manager
|
||
|
||
# 初始化听者
|
||
self.listener = self.plugin_manager.world.camera
|
||
|
||
# 初始化各效果处理器
|
||
from .effects.reverb_processor import ReverbProcessor
|
||
from .effects.eq_processor import EQProcessor
|
||
from .effects.compressor_processor import CompressorProcessor
|
||
from .effects.modulation_processor import ModulationProcessor
|
||
from .effects.distortion_processor import DistortionProcessor
|
||
from .effects.spatial_processor import SpatialProcessor
|
||
|
||
self.reverb_processor = ReverbProcessor(self)
|
||
self.eq_processor = EQProcessor(self)
|
||
self.compressor_processor = CompressorProcessor(self)
|
||
self.modulation_processor = ModulationProcessor(self)
|
||
self.distortion_processor = DistortionProcessor(self)
|
||
self.spatial_processor = SpatialProcessor(self)
|
||
|
||
# 加载预设
|
||
self._load_presets()
|
||
|
||
self.is_initialized = True
|
||
self.performance_stats['initialization_time'] = time.time() - init_start_time
|
||
print("✓ 音频混响和效果插件初始化完成")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 音频混响和效果插件初始化失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def enable(self) -> bool:
|
||
"""
|
||
启用插件
|
||
"""
|
||
if not super().enable():
|
||
return False
|
||
|
||
if self.is_enabled:
|
||
return True
|
||
|
||
try:
|
||
enable_start_time = time.time()
|
||
print(f"启用音频混响和效果插件: {self.name}")
|
||
|
||
# 注册事件处理器
|
||
self._register_event_handlers()
|
||
|
||
# 创建GUI界面
|
||
self._create_gui()
|
||
|
||
self.is_enabled = True
|
||
self.performance_stats['enable_time'] = time.time() - enable_start_time
|
||
print("✓ 音频混响和效果插件启用成功")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 音频混响和效果插件启用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def disable(self) -> bool:
|
||
"""
|
||
禁用插件
|
||
"""
|
||
if not super().disable():
|
||
return False
|
||
|
||
if not self.is_enabled:
|
||
return True
|
||
|
||
try:
|
||
print(f"禁用音频混响和效果插件: {self.name}")
|
||
|
||
# 清理GUI界面
|
||
self._cleanup_gui()
|
||
|
||
# 移除事件处理器
|
||
self._unregister_event_handlers()
|
||
|
||
# 停止所有效果处理
|
||
self._stop_all_processing()
|
||
|
||
self.is_enabled = False
|
||
print("✓ 音频混响和效果插件禁用成功")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 音频混响和效果插件禁用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def finalize(self):
|
||
"""
|
||
清理插件资源
|
||
"""
|
||
print(f"清理音频混响和效果插件资源: {self.name}")
|
||
|
||
# 停止所有处理
|
||
self._stop_all_processing()
|
||
|
||
# 清理所有组件
|
||
processors = [
|
||
self.reverb_processor,
|
||
self.eq_processor,
|
||
self.compressor_processor,
|
||
self.modulation_processor,
|
||
self.distortion_processor,
|
||
self.spatial_processor
|
||
]
|
||
|
||
for processor in processors:
|
||
if processor:
|
||
processor.cleanup()
|
||
|
||
self.reverb_processor = None
|
||
self.eq_processor = None
|
||
self.compressor_processor = None
|
||
self.modulation_processor = None
|
||
self.distortion_processor = None
|
||
self.spatial_processor = None
|
||
|
||
self.audio_manager = None
|
||
self.listener = None
|
||
self.effects.clear()
|
||
self.sound_effects.clear()
|
||
self.presets.clear()
|
||
|
||
self.is_initialized = False
|
||
self.is_enabled = False
|
||
|
||
def _register_event_handlers(self):
|
||
"""
|
||
注册事件处理器
|
||
"""
|
||
world = self.plugin_manager.world
|
||
|
||
# 音频效果控制快捷键
|
||
self.event_handlers['f1'] = self.toggle_debug_mode
|
||
self.event_handlers['f2'] = self.toggle_processing
|
||
self.event_handlers['f3'] = self.apply_test_reverb
|
||
self.event_handlers['f4'] = self.apply_test_eq
|
||
self.event_handlers['f5'] = self.show_stats
|
||
self.event_handlers['f6'] = self.apply_test_compressor
|
||
self.event_handlers['f7'] = self.apply_test_modulation
|
||
self.event_handlers['f8'] = self.apply_test_distortion
|
||
self.event_handlers['f9'] = self.create_test_preset
|
||
self.event_handlers['f10'] = self.toggle_quality
|
||
self.event_handlers['f11'] = self.show_detailed_stats
|
||
self.event_handlers['f12'] = self.reset_all_effects
|
||
|
||
# 注册事件
|
||
for event, handler in self.event_handlers.items():
|
||
world.accept(event, handler)
|
||
world.accept(event.upper(), handler) # 同时注册大写事件
|
||
|
||
def _unregister_event_handlers(self):
|
||
"""
|
||
移除事件处理器
|
||
"""
|
||
world = self.plugin_manager.world
|
||
|
||
for event in self.event_handlers.keys():
|
||
world.ignore(event)
|
||
world.ignore(event.upper())
|
||
|
||
self.event_handlers.clear()
|
||
|
||
def _create_gui(self):
|
||
"""
|
||
创建GUI界面
|
||
"""
|
||
try:
|
||
world = self.plugin_manager.world
|
||
|
||
# 检查是否有GUI管理器
|
||
if not hasattr(world, 'gui_manager') or not world.gui_manager:
|
||
print("⚠ GUI管理器不可用,跳过GUI创建")
|
||
return
|
||
|
||
gui_manager = world.gui_manager
|
||
|
||
# 创建音频效果控制面板
|
||
panel_button = gui_manager.createGUIButton(
|
||
pos=(0.7, 0, 0.35),
|
||
text="音频效果",
|
||
size=0.06
|
||
)
|
||
self.gui_elements.append(panel_button)
|
||
|
||
# 创建功能按钮
|
||
functions = [
|
||
("调试模式 [F1]", self.toggle_debug_mode),
|
||
("切换处理 [F2]", self.toggle_processing),
|
||
("测试混响 [F3]", self.apply_test_reverb),
|
||
("测试EQ [F4]", self.apply_test_eq),
|
||
("效果统计 [F5]", self.show_stats),
|
||
("测试压缩 [F6]", self.apply_test_compressor),
|
||
("测试调制 [F7]", self.apply_test_modulation),
|
||
("测试失真 [F8]", self.apply_test_distortion),
|
||
("测试预设 [F9]", self.create_test_preset),
|
||
("切换质量 [F10]", self.toggle_quality),
|
||
("详细统计 [F11]", self.show_detailed_stats),
|
||
("重置效果 [F12]", self.reset_all_effects)
|
||
]
|
||
|
||
for i, (name, callback) in enumerate(functions):
|
||
button = gui_manager.createGUIButton(
|
||
pos=(0.7, 0, 0.28 - i * 0.055),
|
||
text=name,
|
||
size=0.045
|
||
)
|
||
self.gui_elements.append(button)
|
||
world.accept(f"audio_effect_function_{i}", callback)
|
||
|
||
except Exception as e:
|
||
print(f"⚠ GUI创建失败: {e}")
|
||
|
||
def _cleanup_gui(self):
|
||
"""
|
||
清理GUI界面
|
||
"""
|
||
try:
|
||
world = self.plugin_manager.world
|
||
|
||
if hasattr(world, 'gui_manager') and world.gui_manager:
|
||
gui_manager = world.gui_manager
|
||
|
||
# 删除所有GUI元素
|
||
for element in self.gui_elements:
|
||
gui_manager.deleteGUIElement(element)
|
||
|
||
self.gui_elements.clear()
|
||
|
||
except Exception as e:
|
||
print(f"⚠ GUI清理失败: {e}")
|
||
|
||
# 事件处理方法
|
||
def toggle_debug_mode(self):
|
||
"""切换调试模式"""
|
||
print("✓ 音频效果调试模式切换")
|
||
|
||
def toggle_processing(self):
|
||
"""切换效果处理"""
|
||
self.processing_enabled = not self.processing_enabled
|
||
print(f"✓ 音频效果处理已{'启用' if self.processing_enabled else '禁用'}")
|
||
|
||
def apply_test_reverb(self):
|
||
"""应用测试混响效果"""
|
||
print("✓ 应用测试混响效果")
|
||
try:
|
||
# 创建一个测试混响效果
|
||
reverb_params = {
|
||
'room_size': 0.8,
|
||
'damping': 0.5,
|
||
'wet_level': 0.3,
|
||
'dry_level': 0.7,
|
||
'width': 1.0,
|
||
'freeze_mode': 0.0
|
||
}
|
||
effect_id = self.create_reverb_effect(reverb_params)
|
||
if effect_id:
|
||
print(f"✓ 测试混响效果创建成功: {effect_id}")
|
||
else:
|
||
print("✗ 测试混响效果创建失败")
|
||
except Exception as e:
|
||
print(f"✗ 应用测试混响效果失败: {e}")
|
||
|
||
def apply_test_eq(self):
|
||
"""应用测试均衡器效果"""
|
||
print("✓ 应用测试均衡器效果")
|
||
try:
|
||
# 创建一个测试均衡器效果
|
||
eq_params = {
|
||
'bands': {
|
||
60: 2.0, # 60Hz 提升2dB
|
||
200: -1.0, # 200Hz 降低1dB
|
||
1000: 3.0, # 1kHz 提升3dB
|
||
5000: -2.0, # 5kHz 降低2dB
|
||
10000: 1.0 # 10kHz 提升1dB
|
||
}
|
||
}
|
||
effect_id = self.create_eq_effect(eq_params)
|
||
if effect_id:
|
||
print(f"✓ 测试均衡器效果创建成功: {effect_id}")
|
||
else:
|
||
print("✗ 测试均衡器效果创建失败")
|
||
except Exception as e:
|
||
print(f"✗ 应用测试均衡器效果失败: {e}")
|
||
|
||
def show_stats(self):
|
||
"""显示效果统计信息"""
|
||
stats = self.get_stats()
|
||
print("=== 音频效果统计信息 ===")
|
||
for key, value in stats.items():
|
||
print(f" {key}: {value}")
|
||
|
||
def apply_test_compressor(self):
|
||
"""应用测试压缩器效果"""
|
||
print("✓ 应用测试压缩器效果")
|
||
try:
|
||
# 创建一个测试压缩器效果
|
||
compressor_params = {
|
||
'threshold': -20.0,
|
||
'ratio': 4.0,
|
||
'attack': 0.01,
|
||
'release': 0.1,
|
||
'gain': 2.0,
|
||
'knee': 5.0
|
||
}
|
||
effect_id = self.create_compressor_effect(compressor_params)
|
||
if effect_id:
|
||
print(f"✓ 测试压缩器效果创建成功: {effect_id}")
|
||
else:
|
||
print("✗ 测试压缩器效果创建失败")
|
||
except Exception as e:
|
||
print(f"✗ 应用测试压缩器效果失败: {e}")
|
||
|
||
def apply_test_modulation(self):
|
||
"""应用测试调制效果"""
|
||
print("✓ 应用测试调制效果")
|
||
try:
|
||
# 创建一个测试合唱效果
|
||
modulation_params = {
|
||
'type': 'chorus',
|
||
'rate': 1.0,
|
||
'depth': 0.5,
|
||
'feedback': 0.3,
|
||
'mix': 0.5,
|
||
'delay': 0.01
|
||
}
|
||
effect_id = self.create_modulation_effect(modulation_params)
|
||
if effect_id:
|
||
print(f"✓ 测试调制效果创建成功: {effect_id}")
|
||
else:
|
||
print("✗ 测试调制效果创建失败")
|
||
except Exception as e:
|
||
print(f"✗ 应用测试调制效果失败: {e}")
|
||
|
||
def apply_test_distortion(self):
|
||
"""应用测试失真效果"""
|
||
print("✓ 应用测试失真效果")
|
||
try:
|
||
# 创建一个测试失真效果
|
||
distortion_params = {
|
||
'drive': 0.5,
|
||
'tone': 0.8,
|
||
'level': 0.7,
|
||
'bias': 0.0
|
||
}
|
||
effect_id = self.create_distortion_effect(distortion_params)
|
||
if effect_id:
|
||
print(f"✓ 测试失真效果创建成功: {effect_id}")
|
||
else:
|
||
print("✗ 测试失真效果创建失败")
|
||
except Exception as e:
|
||
print(f"✗ 应用测试失真效果失败: {e}")
|
||
|
||
def create_test_preset(self):
|
||
"""创建测试预设"""
|
||
print("✓ 创建测试预设")
|
||
try:
|
||
preset_name = f"test_preset_{int(time.time())}"
|
||
preset_data = {
|
||
'reverb': {
|
||
'room_size': 0.7,
|
||
'damping': 0.6,
|
||
'wet_level': 0.4,
|
||
'dry_level': 0.6
|
||
},
|
||
'eq': {
|
||
'bands': {
|
||
100: 2.0,
|
||
1000: -1.0,
|
||
8000: 1.5
|
||
}
|
||
},
|
||
'compressor': {
|
||
'threshold': -15.0,
|
||
'ratio': 3.0
|
||
}
|
||
}
|
||
|
||
success = self.create_preset(preset_name, preset_data)
|
||
if success:
|
||
print(f"✓ 测试预设创建成功: {preset_name}")
|
||
else:
|
||
print("✗ 测试预设创建失败")
|
||
except Exception as e:
|
||
print(f"✗ 创建测试预设失败: {e}")
|
||
|
||
def toggle_quality(self):
|
||
"""切换音质设置"""
|
||
quality_levels = ['low', 'medium', 'high']
|
||
current_index = quality_levels.index(self.quality_settings)
|
||
next_index = (current_index + 1) % len(quality_levels)
|
||
self.quality_settings = quality_levels[next_index]
|
||
print(f"✓ 音质设置已切换到: {self.quality_settings}")
|
||
|
||
def show_detailed_stats(self):
|
||
"""显示详细统计信息"""
|
||
print("=== 音频效果详细统计信息 ===")
|
||
|
||
# 显示各处理器统计
|
||
processors = [
|
||
('混响处理器', self.reverb_processor),
|
||
('均衡器处理器', self.eq_processor),
|
||
('压缩器处理器', self.compressor_processor),
|
||
('调制处理器', self.modulation_processor),
|
||
('失真处理器', self.distortion_processor),
|
||
('空间处理器', self.spatial_processor)
|
||
]
|
||
|
||
for name, processor in processors:
|
||
if processor:
|
||
processor_stats = processor.get_stats()
|
||
print(f"{name}统计:")
|
||
for key, value in processor_stats.items():
|
||
print(f" {key}: {value}")
|
||
|
||
# 显示性能统计
|
||
perf_stats = self.performance_stats
|
||
print("性能统计:")
|
||
for key, value in perf_stats.items():
|
||
print(f" {key}: {value}")
|
||
|
||
def reset_all_effects(self):
|
||
"""重置所有效果"""
|
||
print("✓ 重置所有音频效果")
|
||
self.effects.clear()
|
||
self.sound_effects.clear()
|
||
print("✓ 所有音频效果已重置")
|
||
|
||
def _stop_all_processing(self):
|
||
"""停止所有效果处理"""
|
||
print("✓ 停止所有音频效果处理")
|
||
|
||
def _load_presets(self):
|
||
"""加载预设效果"""
|
||
# 默认预设
|
||
self.presets['small_room'] = {
|
||
'reverb': {
|
||
'room_size': 0.3,
|
||
'damping': 0.7,
|
||
'wet_level': 0.2,
|
||
'dry_level': 0.8,
|
||
'width': 0.8
|
||
}
|
||
}
|
||
|
||
self.presets['large_hall'] = {
|
||
'reverb': {
|
||
'room_size': 0.9,
|
||
'damping': 0.4,
|
||
'wet_level': 0.5,
|
||
'dry_level': 0.5,
|
||
'width': 1.0
|
||
}
|
||
}
|
||
|
||
self.presets['cathedral'] = {
|
||
'reverb': {
|
||
'room_size': 1.0,
|
||
'damping': 0.2,
|
||
'wet_level': 0.7,
|
||
'dry_level': 0.3,
|
||
'width': 1.0
|
||
}
|
||
}
|
||
|
||
self.presets['bathroom'] = {
|
||
'reverb': {
|
||
'room_size': 0.2,
|
||
'damping': 0.1,
|
||
'wet_level': 0.8,
|
||
'dry_level': 0.2,
|
||
'width': 0.9
|
||
}
|
||
}
|
||
|
||
print("✓ 预设效果加载完成")
|
||
|
||
def get_stats(self) -> Dict[str, Any]:
|
||
"""
|
||
获取插件统计信息
|
||
|
||
Returns:
|
||
统计信息字典
|
||
"""
|
||
stats = self.performance_stats.copy()
|
||
|
||
# 收集各处理器统计
|
||
processors = [
|
||
self.reverb_processor,
|
||
self.eq_processor,
|
||
self.compressor_processor,
|
||
self.modulation_processor,
|
||
self.distortion_processor,
|
||
self.spatial_processor
|
||
]
|
||
|
||
processor_names = [
|
||
'reverb', 'eq', 'compressor', 'modulation', 'distortion', 'spatial'
|
||
]
|
||
|
||
for i, processor in enumerate(processors):
|
||
if processor:
|
||
processor_stats = processor.get_stats()
|
||
for key, value in processor_stats.items():
|
||
stats[f"{processor_names[i]}_{key}"] = value
|
||
|
||
# 添加效果统计
|
||
stats['total_effects'] = len(self.effects)
|
||
stats['active_effects'] = sum(1 for effect in self.effects.values() if effect.get('active', True))
|
||
stats['effect_assignments'] = sum(len(effect_list) for effect_list in self.sound_effects.values())
|
||
|
||
return stats
|
||
|
||
# 公共接口方法
|
||
def create_reverb_effect(self, parameters: Dict[str, Any]) -> str:
|
||
"""
|
||
创建混响效果
|
||
|
||
Args:
|
||
parameters: 混响参数
|
||
|
||
Returns:
|
||
效果ID
|
||
"""
|
||
if self.reverb_processor:
|
||
return self.reverb_processor.create_effect(parameters)
|
||
return ""
|
||
|
||
def create_eq_effect(self, parameters: Dict[str, Any]) -> str:
|
||
"""
|
||
创建均衡器效果
|
||
|
||
Args:
|
||
parameters: 均衡器参数
|
||
|
||
Returns:
|
||
效果ID
|
||
"""
|
||
if self.eq_processor:
|
||
return self.eq_processor.create_effect(parameters)
|
||
return ""
|
||
|
||
def create_compressor_effect(self, parameters: Dict[str, Any]) -> str:
|
||
"""
|
||
创建压缩器效果
|
||
|
||
Args:
|
||
parameters: 压缩器参数
|
||
|
||
Returns:
|
||
效果ID
|
||
"""
|
||
if self.compressor_processor:
|
||
return self.compressor_processor.create_effect(parameters)
|
||
return ""
|
||
|
||
def create_modulation_effect(self, parameters: Dict[str, Any]) -> str:
|
||
"""
|
||
创建调制效果
|
||
|
||
Args:
|
||
parameters: 调制参数
|
||
|
||
Returns:
|
||
效果ID
|
||
"""
|
||
if self.modulation_processor:
|
||
return self.modulation_processor.create_effect(parameters)
|
||
return ""
|
||
|
||
def create_distortion_effect(self, parameters: Dict[str, Any]) -> str:
|
||
"""
|
||
创建失真效果
|
||
|
||
Args:
|
||
parameters: 失真参数
|
||
|
||
Returns:
|
||
效果ID
|
||
"""
|
||
if self.distortion_processor:
|
||
return self.distortion_processor.create_effect(parameters)
|
||
return ""
|
||
|
||
def create_spatial_effect(self, parameters: Dict[str, Any]) -> str:
|
||
"""
|
||
创建空间效果
|
||
|
||
Args:
|
||
parameters: 空间效果参数
|
||
|
||
Returns:
|
||
效果ID
|
||
"""
|
||
if self.spatial_processor:
|
||
return self.spatial_processor.create_effect(parameters)
|
||
return ""
|
||
|
||
def delete_effect(self, effect_id: str) -> bool:
|
||
"""
|
||
删除效果
|
||
|
||
Args:
|
||
effect_id: 效果ID
|
||
|
||
Returns:
|
||
是否删除成功
|
||
"""
|
||
if effect_id not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_id}")
|
||
return False
|
||
|
||
try:
|
||
# 从所有音效中移除该效果
|
||
for sound_id, effect_list in self.sound_effects.items():
|
||
if effect_id in effect_list:
|
||
effect_list.remove(effect_id)
|
||
|
||
# 删除效果
|
||
del self.effects[effect_id]
|
||
|
||
print(f"✓ 音频效果已删除: {effect_id}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 删除音频效果失败: {e}")
|
||
return False
|
||
|
||
def apply_effect_to_sound(self, sound_id: str, effect_id: str) -> bool:
|
||
"""
|
||
应用效果到音效
|
||
|
||
Args:
|
||
sound_id: 音源ID
|
||
effect_id: 效果ID
|
||
|
||
Returns:
|
||
是否应用成功
|
||
"""
|
||
# 检查音源和效果是否存在
|
||
# 注意:这里需要与主音频系统集成
|
||
if effect_id not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_id}")
|
||
return False
|
||
|
||
try:
|
||
# 初始化音效的效果列表
|
||
if sound_id not in self.sound_effects:
|
||
self.sound_effects[sound_id] = []
|
||
|
||
# 检查是否超过最大效果数
|
||
if len(self.sound_effects[sound_id]) >= self.max_effects_per_sound:
|
||
print(f"✗ 音效已达到最大效果数限制: {self.max_effects_per_sound}")
|
||
return False
|
||
|
||
# 添加效果到音效
|
||
if effect_id not in self.sound_effects[sound_id]:
|
||
self.sound_effects[sound_id].append(effect_id)
|
||
|
||
effect_type = self.effects[effect_id]['type']
|
||
print(f"✓ 效果已应用到音效: {effect_id} ({effect_type}) -> {sound_id}")
|
||
return True
|
||
else:
|
||
print(f"⚠ 效果已应用于该音效: {effect_id} -> {sound_id}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 应用效果到音效失败: {e}")
|
||
return False
|
||
|
||
def remove_effect_from_sound(self, sound_id: str, effect_id: str) -> bool:
|
||
"""
|
||
从音效移除效果
|
||
|
||
Args:
|
||
sound_id: 音源ID
|
||
effect_id: 效果ID
|
||
|
||
Returns:
|
||
是否移除成功
|
||
"""
|
||
# 检查音源和效果是否存在
|
||
if effect_id not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_id}")
|
||
return False
|
||
|
||
try:
|
||
# 检查效果是否已应用于该音效
|
||
if sound_id in self.sound_effects and effect_id in self.sound_effects[sound_id]:
|
||
self.sound_effects[sound_id].remove(effect_id)
|
||
|
||
effect_type = self.effects[effect_id]['type']
|
||
print(f"✓ 效果已从音效移除: {effect_id} ({effect_type}) -> {sound_id}")
|
||
return True
|
||
else:
|
||
print(f"⚠ 效果未应用于该音效: {effect_id} -> {sound_id}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 从音效移除效果失败: {e}")
|
||
return False
|
||
|
||
def set_effect_parameter(self, effect_id: str, parameter: str, value: Any) -> bool:
|
||
"""
|
||
设置效果参数
|
||
|
||
Args:
|
||
effect_id: 效果ID
|
||
parameter: 参数名
|
||
value: 参数值
|
||
|
||
Returns:
|
||
是否设置成功
|
||
"""
|
||
if effect_id not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_id}")
|
||
return False
|
||
|
||
try:
|
||
self.effects[effect_id]['parameters'][parameter] = value
|
||
print(f"✓ 效果参数已设置: {effect_id}.{parameter} = {value}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设置效果参数失败: {e}")
|
||
return False
|
||
|
||
def get_effect_parameters(self, effect_id: str) -> Dict[str, Any]:
|
||
"""
|
||
获取效果参数
|
||
|
||
Args:
|
||
effect_id: 效果ID
|
||
|
||
Returns:
|
||
参数字典
|
||
"""
|
||
if effect_id not in self.effects:
|
||
return {}
|
||
|
||
return self.effects[effect_id]['parameters'].copy()
|
||
|
||
def enable_effect(self, effect_id: str) -> bool:
|
||
"""
|
||
启用效果
|
||
|
||
Args:
|
||
effect_id: 效果ID
|
||
|
||
Returns:
|
||
是否启用成功
|
||
"""
|
||
if effect_id not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_id}")
|
||
return False
|
||
|
||
try:
|
||
self.effects[effect_id]['active'] = True
|
||
print(f"✓ 效果已启用: {effect_id}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 启用效果失败: {e}")
|
||
return False
|
||
|
||
def disable_effect(self, effect_id: str) -> bool:
|
||
"""
|
||
禁用效果
|
||
|
||
Args:
|
||
effect_id: 效果ID
|
||
|
||
Returns:
|
||
是否禁用成功
|
||
"""
|
||
if effect_id not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_id}")
|
||
return False
|
||
|
||
try:
|
||
self.effects[effect_id]['active'] = False
|
||
print(f"✓ 效果已禁用: {effect_id}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 禁用效果失败: {e}")
|
||
return False
|
||
|
||
def get_effect_type(self, effect_id: str) -> str:
|
||
"""
|
||
获取效果类型
|
||
|
||
Args:
|
||
effect_id: 效果ID
|
||
|
||
Returns:
|
||
效果类型
|
||
"""
|
||
if effect_id not in self.effects:
|
||
return ""
|
||
|
||
return self.effects[effect_id]['type']
|
||
|
||
def get_sound_effects(self, sound_id: str) -> List[str]:
|
||
"""
|
||
获取音效应用的效果列表
|
||
|
||
Args:
|
||
sound_id: 音源ID
|
||
|
||
Returns:
|
||
效果ID列表
|
||
"""
|
||
return self.sound_effects.get(sound_id, []).copy()
|
||
|
||
def create_preset(self, preset_name: str, preset_data: Dict[str, Any]) -> bool:
|
||
"""
|
||
创建效果预设
|
||
|
||
Args:
|
||
preset_name: 预设名称
|
||
preset_data: 预设数据
|
||
|
||
Returns:
|
||
是否创建成功
|
||
"""
|
||
try:
|
||
self.presets[preset_name] = preset_data.copy()
|
||
print(f"✓ 效果预设创建成功: {preset_name}")
|
||
return True
|
||
except Exception as e:
|
||
print(f"✗ 创建效果预设失败: {e}")
|
||
return False
|
||
|
||
def apply_preset_to_sound(self, sound_id: str, preset_name: str) -> bool:
|
||
"""
|
||
应用预设到音效
|
||
|
||
Args:
|
||
sound_id: 音源ID
|
||
preset_name: 预设名称
|
||
|
||
Returns:
|
||
是否应用成功
|
||
"""
|
||
if preset_name not in self.presets:
|
||
print(f"✗ 预设不存在: {preset_name}")
|
||
return False
|
||
|
||
try:
|
||
preset_data = self.presets[preset_name]
|
||
created_effects = []
|
||
|
||
# 应用混响预设
|
||
if 'reverb' in preset_data:
|
||
effect_id = self.create_reverb_effect(preset_data['reverb'])
|
||
if effect_id:
|
||
created_effects.append(('reverb', effect_id))
|
||
|
||
# 应用均衡器预设
|
||
if 'eq' in preset_data:
|
||
effect_id = self.create_eq_effect(preset_data['eq'])
|
||
if effect_id:
|
||
created_effects.append(('eq', effect_id))
|
||
|
||
# 应用压缩器预设
|
||
if 'compressor' in preset_data:
|
||
effect_id = self.create_compressor_effect(preset_data['compressor'])
|
||
if effect_id:
|
||
created_effects.append(('compressor', effect_id))
|
||
|
||
# 将所有创建的效果应用到音效
|
||
success_count = 0
|
||
for effect_type, effect_id in created_effects:
|
||
if self.apply_effect_to_sound(sound_id, effect_id):
|
||
success_count += 1
|
||
|
||
print(f"✓ 预设 {preset_name} 已应用到音效 {sound_id} ({success_count}/{len(created_effects)} 效果)")
|
||
return success_count > 0
|
||
|
||
except Exception as e:
|
||
print(f"✗ 应用预设到音效失败: {e}")
|
||
return False
|
||
|
||
def get_preset_names(self) -> List[str]:
|
||
"""
|
||
获取所有预设名称
|
||
|
||
Returns:
|
||
预设名称列表
|
||
"""
|
||
return list(self.presets.keys())
|
||
|
||
def delete_preset(self, preset_name: str) -> bool:
|
||
"""
|
||
删除预设
|
||
|
||
Args:
|
||
preset_name: 预设名称
|
||
|
||
Returns:
|
||
是否删除成功
|
||
"""
|
||
if preset_name not in self.presets:
|
||
print(f"✗ 预设不存在: {preset_name}")
|
||
return False
|
||
|
||
try:
|
||
del self.presets[preset_name]
|
||
print(f"✓ 预设已删除: {preset_name}")
|
||
return True
|
||
except Exception as e:
|
||
print(f"✗ 删除预设失败: {e}")
|
||
return False
|
||
|
||
def set_master_volume(self, volume: float):
|
||
"""
|
||
设置主音量
|
||
|
||
Args:
|
||
volume: 主音量 (0.0-1.0)
|
||
"""
|
||
self.master_volume = max(0.0, min(1.0, volume))
|
||
print(f"✓ 主音量已设置: {self.master_volume}")
|
||
|
||
def get_master_volume(self) -> float:
|
||
"""
|
||
获取主音量
|
||
|
||
Returns:
|
||
主音量 (0.0-1.0)
|
||
"""
|
||
return self.master_volume
|
||
|
||
def set_quality_settings(self, quality: str):
|
||
"""
|
||
设置音质设置
|
||
|
||
Args:
|
||
quality: 音质等级 ('low', 'medium', 'high')
|
||
"""
|
||
if quality in ['low', 'medium', 'high']:
|
||
self.quality_settings = quality
|
||
print(f"✓ 音质设置已更新: {quality}")
|
||
else:
|
||
print(f"✗ 无效的音质设置: {quality}")
|
||
|
||
def get_quality_settings(self) -> str:
|
||
"""
|
||
获取音质设置
|
||
|
||
Returns:
|
||
音质等级
|
||
"""
|
||
return self.quality_settings
|
||
|
||
def update(self, dt: float):
|
||
"""
|
||
更新插件状态
|
||
|
||
Args:
|
||
dt: 时间增量
|
||
"""
|
||
update_start_time = time.time()
|
||
|
||
# 更新各效果处理器
|
||
processors = [
|
||
self.reverb_processor,
|
||
self.eq_processor,
|
||
self.compressor_processor,
|
||
self.modulation_processor,
|
||
self.distortion_processor,
|
||
self.spatial_processor
|
||
]
|
||
|
||
for processor in processors:
|
||
if processor:
|
||
processor.update(dt)
|
||
|
||
# 更新性能统计
|
||
self.performance_stats['total_updates'] += 1
|
||
self.performance_stats['last_update_time'] = time.time()
|
||
self.performance_stats['total_processing_time'] += (time.time() - update_start_time)
|
||
|
||
def process_audio_with_effects(self, sound_id: str, audio_data: Any) -> Any:
|
||
"""
|
||
使用效果处理音频数据
|
||
|
||
Args:
|
||
sound_id: 音源ID
|
||
audio_data: 音频数据
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
if not self.processing_enabled:
|
||
return audio_data
|
||
|
||
# 获取应用到该音效的所有效果
|
||
effect_ids = self.sound_effects.get(sound_id, [])
|
||
|
||
if not effect_ids:
|
||
return audio_data
|
||
|
||
# 按顺序应用效果
|
||
processed_data = audio_data
|
||
effects_processed = 0
|
||
|
||
for effect_id in effect_ids:
|
||
if effect_id in self.effects and self.effects[effect_id].get('active', True):
|
||
effect = self.effects[effect_id]
|
||
effect_type = effect['type']
|
||
|
||
# 根据效果类型调用相应的处理器
|
||
if effect_type == 'reverb' and self.reverb_processor:
|
||
processed_data = self.reverb_processor.process(processed_data, effect['parameters'])
|
||
effects_processed += 1
|
||
elif effect_type == 'eq' and self.eq_processor:
|
||
processed_data = self.eq_processor.process(processed_data, effect['parameters'])
|
||
effects_processed += 1
|
||
elif effect_type == 'compressor' and self.compressor_processor:
|
||
processed_data = self.compressor_processor.process(processed_data, effect['parameters'])
|
||
effects_processed += 1
|
||
elif effect_type == 'modulation' and self.modulation_processor:
|
||
processed_data = self.modulation_processor.process(processed_data, effect['parameters'])
|
||
effects_processed += 1
|
||
elif effect_type == 'distortion' and self.distortion_processor:
|
||
processed_data = self.distortion_processor.process(processed_data, effect['parameters'])
|
||
effects_processed += 1
|
||
elif effect_type == 'spatial' and self.spatial_processor:
|
||
processed_data = self.spatial_processor.process(processed_data, effect['parameters'])
|
||
effects_processed += 1
|
||
|
||
# 更新统计
|
||
self.performance_stats['effects_processed'] += effects_processed
|
||
|
||
return processed_data
|
||
|