941 lines
32 KiB
Python
941 lines
32 KiB
Python
"""
|
||
效果处理器
|
||
负责为动态音乐添加各种音频效果
|
||
"""
|
||
|
||
import uuid
|
||
import math
|
||
import time
|
||
import numpy as np
|
||
from typing import Dict, List, Any, Optional
|
||
|
||
class EffectProcessor:
|
||
"""
|
||
效果处理器
|
||
负责为动态音乐添加各种音频效果
|
||
"""
|
||
|
||
def __init__(self, plugin):
|
||
"""
|
||
初始化效果处理器
|
||
|
||
Args:
|
||
plugin: 动态音乐系统插件实例
|
||
"""
|
||
self.plugin = plugin
|
||
self.effects: Dict[str, Dict[str, Any]] = {}
|
||
self.active_effects: Dict[str, Dict[str, Any]] = {}
|
||
self.effect_chains: Dict[str, List[str]] = {}
|
||
|
||
self.stats = {
|
||
'effects_created': 0,
|
||
'effects_active': 0,
|
||
'effects_processed': 0,
|
||
'processing_time': 0.0,
|
||
'memory_usage': 0
|
||
}
|
||
|
||
self.sample_rate = 44100
|
||
self.buffer_size = plugin.buffer_size if plugin else 4096
|
||
|
||
# 效果参数范围
|
||
self.effect_ranges = {
|
||
'reverb': {'room_size': (0.0, 1.0), 'damping': (0.0, 1.0), 'wet_level': (0.0, 1.0)},
|
||
'chorus': {'rate': (0.1, 5.0), 'depth': (0.0, 1.0), 'mix': (0.0, 1.0)},
|
||
'delay': {'time': (0.01, 2.0), 'feedback': (0.0, 1.0), 'mix': (0.0, 1.0)},
|
||
'filter': {'frequency': (20.0, 20000.0), 'q': (0.1, 10.0), 'gain': (-24.0, 24.0)},
|
||
'distortion': {'drive': (0.0, 1.0), 'tone': (0.0, 1.0), 'mix': (0.0, 1.0)},
|
||
'phaser': {'rate': (0.1, 10.0), 'depth': (0.0, 1.0), 'feedback': (-0.9, 0.9)},
|
||
'flanger': {'rate': (0.1, 10.0), 'depth': (0.0, 0.005), 'feedback': (-0.9, 0.9)},
|
||
'compressor': {'threshold': (-60.0, 0.0), 'ratio': (1.0, 20.0), 'attack': (0.001, 0.1)},
|
||
'eq': {'frequency': (20.0, 20000.0), 'gain': (-24.0, 24.0), 'q': (0.1, 10.0)}
|
||
}
|
||
|
||
# 初始化效果处理器
|
||
self._initialize_effect_processor()
|
||
|
||
def _initialize_effect_processor(self):
|
||
"""初始化效果处理器"""
|
||
print("✓ 效果处理器初始化完成")
|
||
|
||
def create_effect(self, effect_name: str, effect_type: str, effect_params: Dict[str, Any]) -> bool:
|
||
"""
|
||
创建音频效果
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
effect_type: 效果类型
|
||
effect_params: 效果参数
|
||
|
||
Returns:
|
||
是否创建成功
|
||
"""
|
||
try:
|
||
# 验证效果类型
|
||
valid_effects = [
|
||
'reverb', 'chorus', 'delay', 'filter', 'distortion',
|
||
'phaser', 'flanger', 'compressor', 'eq', 'limiter',
|
||
'tremolo', 'vibrato', 'pitch_shift', 'stereo_widen'
|
||
]
|
||
|
||
if effect_type not in valid_effects:
|
||
print(f"✗ 无效的效果类型: {effect_type}")
|
||
return False
|
||
|
||
# 设置默认参数
|
||
default_params = self._get_default_effect_params(effect_type)
|
||
|
||
# 合并参数
|
||
params = default_params.copy()
|
||
params.update(effect_params)
|
||
|
||
# 验证参数范围
|
||
if not self._validate_effect_params(effect_type, params):
|
||
print(f"✗ 效果参数超出有效范围: {effect_type}")
|
||
return False
|
||
|
||
# 创建效果
|
||
effect = {
|
||
'name': effect_name,
|
||
'type': effect_type,
|
||
'params': params,
|
||
'state': 'created',
|
||
'bypass': False,
|
||
'wet_dry_mix': params.get('mix', 1.0),
|
||
'created_time': time.time()
|
||
}
|
||
|
||
self.effects[effect_name] = effect
|
||
self.stats['effects_created'] += 1
|
||
|
||
print(f"✓ 音频效果创建成功: {effect_name} ({effect_type})")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 创建音频效果失败: {e}")
|
||
return False
|
||
|
||
def _get_default_effect_params(self, effect_type: str) -> Dict[str, Any]:
|
||
"""
|
||
获取默认效果参数
|
||
|
||
Args:
|
||
effect_type: 效果类型
|
||
|
||
Returns:
|
||
默认参数字典
|
||
"""
|
||
defaults = {
|
||
'reverb': {
|
||
'room_size': 0.5,
|
||
'damping': 0.5,
|
||
'wet_level': 0.3,
|
||
'dry_level': 0.7,
|
||
'width': 1.0,
|
||
'freeze_mode': 0.0
|
||
},
|
||
'chorus': {
|
||
'rate': 1.0,
|
||
'depth': 0.5,
|
||
'feedback': 0.3,
|
||
'mix': 0.5,
|
||
'delay': 0.01
|
||
},
|
||
'delay': {
|
||
'time': 0.3,
|
||
'feedback': 0.4,
|
||
'mix': 0.5,
|
||
'sync': False,
|
||
'sync_note': '1/4'
|
||
},
|
||
'filter': {
|
||
'type': 'lowpass',
|
||
'frequency': 1000.0,
|
||
'q': 1.0,
|
||
'gain': 0.0
|
||
},
|
||
'distortion': {
|
||
'drive': 0.5,
|
||
'tone': 0.5,
|
||
'mix': 0.5
|
||
},
|
||
'phaser': {
|
||
'rate': 1.0,
|
||
'depth': 0.5,
|
||
'feedback': 0.3,
|
||
'mix': 0.5
|
||
},
|
||
'flanger': {
|
||
'rate': 1.0,
|
||
'depth': 0.002,
|
||
'feedback': 0.3,
|
||
'mix': 0.5
|
||
},
|
||
'compressor': {
|
||
'threshold': -20.0,
|
||
'ratio': 4.0,
|
||
'attack': 0.01,
|
||
'release': 0.1,
|
||
'gain': 0.0,
|
||
'knee': 5.0
|
||
},
|
||
'eq': {
|
||
'type': 'peaking',
|
||
'frequency': 1000.0,
|
||
'gain': 0.0,
|
||
'q': 1.0
|
||
},
|
||
'limiter': {
|
||
'threshold': -0.1,
|
||
'release': 0.05,
|
||
'mix': 1.0
|
||
},
|
||
'tremolo': {
|
||
'rate': 5.0,
|
||
'depth': 0.5,
|
||
'mix': 1.0,
|
||
'waveform': 'sine'
|
||
},
|
||
'vibrato': {
|
||
'rate': 5.0,
|
||
'depth': 0.5,
|
||
'mix': 1.0,
|
||
'delay': 0.01
|
||
},
|
||
'pitch_shift': {
|
||
'semitones': 0.0,
|
||
'mix': 1.0,
|
||
'formant_preserve': True
|
||
},
|
||
'stereo_widen': {
|
||
'width': 1.0,
|
||
'mix': 1.0
|
||
}
|
||
}
|
||
|
||
return defaults.get(effect_type, {})
|
||
|
||
def _validate_effect_params(self, effect_type: str, params: Dict[str, Any]) -> bool:
|
||
"""
|
||
验证效果参数范围
|
||
|
||
Args:
|
||
effect_type: 效果类型
|
||
params: 参数字典
|
||
|
||
Returns:
|
||
是否验证通过
|
||
"""
|
||
if effect_type not in self.effect_ranges:
|
||
return True # 没有定义范围的效果默认通过验证
|
||
|
||
ranges = self.effect_ranges[effect_type]
|
||
for param_name, (min_val, max_val) in ranges.items():
|
||
if param_name in params:
|
||
param_value = params[param_name]
|
||
if not (min_val <= param_value <= max_val):
|
||
print(f"✗ 参数 {param_name} 超出范围 [{min_val}, {max_val}]: {param_value}")
|
||
return False
|
||
|
||
return True
|
||
|
||
def activate_effect(self, effect_name: str) -> bool:
|
||
"""
|
||
激活音频效果
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
|
||
Returns:
|
||
是否激活成功
|
||
"""
|
||
try:
|
||
if effect_name not in self.effects:
|
||
print(f"✗ 音频效果不存在: {effect_name}")
|
||
return False
|
||
|
||
self.active_effects[effect_name] = self.effects[effect_name]
|
||
self.stats['effects_active'] = len(self.active_effects)
|
||
|
||
print(f"✓ 音频效果已激活: {effect_name}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 激活音频效果失败: {e}")
|
||
return False
|
||
|
||
def deactivate_effect(self, effect_name: str) -> bool:
|
||
"""
|
||
停用音频效果
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
|
||
Returns:
|
||
是否停用成功
|
||
"""
|
||
try:
|
||
if effect_name not in self.active_effects:
|
||
print(f"⚠ 音频效果未激活: {effect_name}")
|
||
return True
|
||
|
||
del self.active_effects[effect_name]
|
||
self.stats['effects_active'] = len(self.active_effects)
|
||
|
||
print(f"✓ 音频效果已停用: {effect_name}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 停用音频效果失败: {e}")
|
||
return False
|
||
|
||
def apply_effects(self, audio_data: Any, chain_name: str = 'default') -> Any:
|
||
"""
|
||
应用效果链到音频数据
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
chain_name: 效果链名称
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
try:
|
||
process_start_time = time.time()
|
||
|
||
# 获取效果链
|
||
effect_chain = self.effect_chains.get(chain_name, [])
|
||
if not effect_chain:
|
||
# 如果没有指定效果链,使用所有激活的效果
|
||
effect_chain = list(self.active_effects.keys())
|
||
|
||
# 依次应用效果
|
||
processed_data = audio_data
|
||
effects_applied = 0
|
||
|
||
for effect_name in effect_chain:
|
||
if effect_name in self.active_effects:
|
||
effect = self.active_effects[effect_name]
|
||
if not effect.get('bypass', False):
|
||
processed_data = self._apply_single_effect(processed_data, effect)
|
||
effects_applied += 1
|
||
|
||
# 更新统计信息
|
||
self.stats['effects_processed'] += effects_applied
|
||
self.stats['processing_time'] += (time.time() - process_start_time)
|
||
|
||
return processed_data
|
||
|
||
except Exception as e:
|
||
print(f"✗ 应用效果链失败: {e}")
|
||
return audio_data
|
||
|
||
def _apply_single_effect(self, audio_data: Any, effect: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用单个效果到音频数据
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
effect: 效果数据
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
try:
|
||
effect_type = effect['type']
|
||
params = effect['params']
|
||
wet_dry_mix = effect.get('wet_dry_mix', 1.0)
|
||
|
||
# 根据效果类型应用处理
|
||
if effect_type == 'reverb':
|
||
processed_data = self._apply_reverb(audio_data, params)
|
||
elif effect_type == 'chorus':
|
||
processed_data = self._apply_chorus(audio_data, params)
|
||
elif effect_type == 'delay':
|
||
processed_data = self._apply_delay(audio_data, params)
|
||
elif effect_type == 'filter':
|
||
processed_data = self._apply_filter(audio_data, params)
|
||
elif effect_type == 'distortion':
|
||
processed_data = self._apply_distortion(audio_data, params)
|
||
elif effect_type == 'phaser':
|
||
processed_data = self._apply_phaser(audio_data, params)
|
||
elif effect_type == 'flanger':
|
||
processed_data = self._apply_flanger(audio_data, params)
|
||
elif effect_type == 'compressor':
|
||
processed_data = self._apply_compressor(audio_data, params)
|
||
elif effect_type == 'eq':
|
||
processed_data = self._apply_eq(audio_data, params)
|
||
else:
|
||
# 未知效果类型,不处理
|
||
processed_data = audio_data
|
||
|
||
# 应用湿/干混合
|
||
if wet_dry_mix < 1.0:
|
||
processed_data = audio_data * (1.0 - wet_dry_mix) + processed_data * wet_dry_mix
|
||
|
||
return processed_data
|
||
|
||
except Exception as e:
|
||
print(f"✗ 应用单个效果失败: {e}")
|
||
return audio_data
|
||
|
||
def _apply_reverb(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用混响效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
# 简化的混响实现
|
||
# 实际应用中会使用更复杂的算法
|
||
|
||
room_size = params.get('room_size', 0.5)
|
||
damping = params.get('damping', 0.5)
|
||
wet_level = params.get('wet_level', 0.3)
|
||
|
||
# 模拟混响效果
|
||
reverb_amount = wet_level * room_size
|
||
damp_factor = 1.0 - damping * 0.5
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
# 对NumPy数组应用简化效果
|
||
processed = audio_data.copy()
|
||
# 添加延迟和衰减效果
|
||
for i in range(1, min(100, len(processed))):
|
||
processed[i:] += processed[:-i] * reverb_amount * damp_factor * (0.95 ** i)
|
||
return np.clip(processed, -1.0, 1.0)
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_chorus(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用合唱效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
# 简化的合唱实现
|
||
rate = params.get('rate', 1.0)
|
||
depth = params.get('depth', 0.5)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
# 添加基于正弦波的调制
|
||
t = np.arange(len(processed)) / self.sample_rate
|
||
modulation = np.sin(2 * np.pi * rate * t) * depth
|
||
# 简化的延迟效果
|
||
delay_samples = (modulation * self.sample_rate * 0.01).astype(int)
|
||
for i in range(len(processed)):
|
||
delay_idx = max(0, i - abs(delay_samples[i]))
|
||
processed[i] += processed[delay_idx] * 0.3
|
||
return np.clip(processed, -1.0, 1.0)
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_delay(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用延迟效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
delay_time = params.get('time', 0.3)
|
||
feedback = params.get('feedback', 0.4)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
delay_samples = int(delay_time * self.sample_rate)
|
||
if delay_samples > 0:
|
||
for i in range(delay_samples, len(processed)):
|
||
processed[i] += processed[i - delay_samples] * feedback
|
||
return np.clip(processed, -1.0, 1.0)
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_filter(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用滤波器效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
filter_type = params.get('type', 'lowpass')
|
||
frequency = params.get('frequency', 1000.0)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
# 简化的滤波器实现
|
||
if filter_type == 'lowpass':
|
||
# 简单的低通滤波
|
||
rc = 1.0 / (2 * np.pi * frequency)
|
||
dt = 1.0 / self.sample_rate
|
||
alpha = dt / (rc + dt)
|
||
for i in range(1, len(processed)):
|
||
processed[i] = alpha * processed[i] + (1 - alpha) * processed[i-1]
|
||
elif filter_type == 'highpass':
|
||
# 简单的高通滤波
|
||
rc = 1.0 / (2 * np.pi * frequency)
|
||
dt = 1.0 / self.sample_rate
|
||
alpha = rc / (rc + dt)
|
||
for i in range(1, len(processed)):
|
||
processed[i] = alpha * (processed[i-1] + processed[i] - processed[i-1])
|
||
return processed
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_distortion(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用失真效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
drive = params.get('drive', 0.5)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
# 应用饱和失真
|
||
drive_factor = 1.0 + drive * 10.0
|
||
processed = np.tanh(processed * drive_factor)
|
||
return processed
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_phaser(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用移相器效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
rate = params.get('rate', 1.0)
|
||
depth = params.get('depth', 0.5)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
# 简化的移相器实现
|
||
t = np.arange(len(processed)) / self.sample_rate
|
||
lfo = np.sin(2 * np.pi * rate * t) * depth
|
||
# 应用相位调制
|
||
processed += processed * lfo * 0.5
|
||
return np.clip(processed, -1.0, 1.0)
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_flanger(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用镶边效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
rate = params.get('rate', 1.0)
|
||
depth = params.get('depth', 0.002)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
# 简化的镶边实现
|
||
t = np.arange(len(processed)) / self.sample_rate
|
||
delay = np.sin(2 * np.pi * rate * t) * depth
|
||
delay_samples = (delay * self.sample_rate).astype(int)
|
||
for i in range(len(processed)):
|
||
delay_idx = max(0, i - abs(delay_samples[i]))
|
||
processed[i] += processed[delay_idx] * 0.7
|
||
return np.clip(processed, -1.0, 1.0)
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_compressor(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用压缩器效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
threshold = params.get('threshold', -20.0)
|
||
ratio = params.get('ratio', 4.0)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
# 简化的压缩器实现
|
||
threshold_linear = 10 ** (threshold / 20.0)
|
||
# 对超过阈值的信号进行压缩
|
||
abs_signal = np.abs(processed)
|
||
compressed = np.where(
|
||
abs_signal > threshold_linear,
|
||
np.sign(processed) * (threshold_linear + (abs_signal - threshold_linear) / ratio),
|
||
processed
|
||
)
|
||
return compressed
|
||
else:
|
||
return audio_data
|
||
|
||
def _apply_eq(self, audio_data: Any, params: Dict[str, Any]) -> Any:
|
||
"""
|
||
应用均衡器效果
|
||
|
||
Args:
|
||
audio_data: 输入音频数据
|
||
params: 效果参数
|
||
|
||
Returns:
|
||
处理后的音频数据
|
||
"""
|
||
frequency = params.get('frequency', 1000.0)
|
||
gain = params.get('gain', 0.0)
|
||
|
||
if isinstance(audio_data, np.ndarray):
|
||
processed = audio_data.copy()
|
||
# 简化的均衡器实现
|
||
if gain != 0.0:
|
||
gain_factor = 10 ** (gain / 20.0)
|
||
# 根据频率调整增益(简化实现)
|
||
if frequency < 500:
|
||
# 低频增强/衰减
|
||
processed *= 0.8 + 0.2 * gain_factor
|
||
elif frequency < 2000:
|
||
# 中频增强/衰减
|
||
processed *= gain_factor
|
||
else:
|
||
# 高频增强/衰减
|
||
processed *= 1.0 + 0.1 * (gain_factor - 1.0)
|
||
return processed
|
||
else:
|
||
return audio_data
|
||
|
||
def create_effect_chain(self, chain_name: str, effect_names: List[str]) -> bool:
|
||
"""
|
||
创建效果链
|
||
|
||
Args:
|
||
chain_name: 效果链名称
|
||
effect_names: 效果名称列表
|
||
|
||
Returns:
|
||
是否创建成功
|
||
"""
|
||
try:
|
||
# 验证效果是否存在
|
||
for effect_name in effect_names:
|
||
if effect_name not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_name}")
|
||
return False
|
||
|
||
# 创建效果链
|
||
self.effect_chains[chain_name] = effect_names.copy()
|
||
print(f"✓ 效果链创建成功: {chain_name}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 创建效果链失败: {e}")
|
||
return False
|
||
|
||
def update(self, dt: float):
|
||
"""
|
||
更新效果处理器状态
|
||
|
||
Args:
|
||
dt: 时间增量
|
||
"""
|
||
# 这里可以更新任何需要定期更新的状态
|
||
# 例如:LFO相位更新、动态参数调整等
|
||
pass
|
||
|
||
def cleanup(self):
|
||
"""清理所有资源"""
|
||
self.effects.clear()
|
||
self.active_effects.clear()
|
||
self.effect_chains.clear()
|
||
|
||
self.stats = {
|
||
'effects_created': 0,
|
||
'effects_active': 0,
|
||
'effects_processed': 0,
|
||
'processing_time': 0.0,
|
||
'memory_usage': 0
|
||
}
|
||
|
||
print("✓ 效果处理器资源已清理")
|
||
|
||
def get_stats(self) -> Dict[str, int]:
|
||
"""
|
||
获取统计信息
|
||
|
||
Returns:
|
||
统计信息字典
|
||
"""
|
||
return self.stats.copy()
|
||
|
||
def get_active_effects(self) -> List[str]:
|
||
"""
|
||
获取激活的效果列表
|
||
|
||
Returns:
|
||
激活的效果名称列表
|
||
"""
|
||
return list(self.active_effects.keys())
|
||
|
||
def get_effect_status(self, effect_name: str) -> Dict[str, Any]:
|
||
"""
|
||
获取效果状态
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
|
||
Returns:
|
||
效果状态字典
|
||
"""
|
||
if effect_name in self.active_effects:
|
||
effect = self.active_effects[effect_name]
|
||
return {
|
||
'name': effect_name,
|
||
'type': effect['type'],
|
||
'state': 'active',
|
||
'bypass': effect.get('bypass', False),
|
||
'wet_dry_mix': effect.get('wet_dry_mix', 1.0)
|
||
}
|
||
elif effect_name in self.effects:
|
||
effect = self.effects[effect_name]
|
||
return {
|
||
'name': effect_name,
|
||
'type': effect['type'],
|
||
'state': 'inactive',
|
||
'bypass': effect.get('bypass', False),
|
||
'wet_dry_mix': effect.get('wet_dry_mix', 1.0)
|
||
}
|
||
else:
|
||
return {
|
||
'name': effect_name,
|
||
'state': 'unknown'
|
||
}
|
||
|
||
def bypass_effect(self, effect_name: str, bypass: bool = True) -> bool:
|
||
"""
|
||
旁路/启用效果
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
bypass: 是否旁路
|
||
|
||
Returns:
|
||
是否设置成功
|
||
"""
|
||
try:
|
||
if effect_name not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_name}")
|
||
return False
|
||
|
||
self.effects[effect_name]['bypass'] = bypass
|
||
if effect_name in self.active_effects:
|
||
self.active_effects[effect_name]['bypass'] = bypass
|
||
|
||
state = "旁路" if bypass else "启用"
|
||
print(f"✓ 效果已{state}: {effect_name}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设置效果旁路状态失败: {e}")
|
||
return False
|
||
|
||
def set_effect_parameter(self, effect_name: str, parameter: str, value: Any) -> bool:
|
||
"""
|
||
设置效果参数
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
parameter: 参数名称
|
||
value: 参数值
|
||
|
||
Returns:
|
||
是否设置成功
|
||
"""
|
||
try:
|
||
if effect_name not in self.effects:
|
||
print(f"✗ 效果不存在: {effect_name}")
|
||
return False
|
||
|
||
# 验证参数范围
|
||
effect = self.effects[effect_name]
|
||
effect_type = effect['type']
|
||
|
||
if effect_type in self.effect_ranges and parameter in self.effect_ranges[effect_type]:
|
||
min_val, max_val = self.effect_ranges[effect_type][parameter]
|
||
if not (min_val <= value <= max_val):
|
||
print(f"✗ 参数 {parameter} 超出范围 [{min_val}, {max_val}]: {value}")
|
||
return False
|
||
|
||
# 设置参数
|
||
self.effects[effect_name]['params'][parameter] = value
|
||
if effect_name in self.active_effects:
|
||
self.active_effects[effect_name]['params'][parameter] = value
|
||
|
||
print(f"✓ 效果参数已设置: {effect_name}.{parameter} = {value}")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设置效果参数失败: {e}")
|
||
return False
|
||
|
||
def get_effect_parameters(self, effect_name: str) -> Dict[str, Any]:
|
||
"""
|
||
获取效果参数
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
|
||
Returns:
|
||
参数字典
|
||
"""
|
||
if effect_name in self.effects:
|
||
return self.effects[effect_name]['params'].copy()
|
||
return {}
|
||
|
||
def set_wet_dry_mix(self, effect_name: str, mix: float) -> bool:
|
||
"""
|
||
设置湿/干混合比例
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
mix: 混合比例 (0.0-1.0)
|
||
|
||
Returns:
|
||
是否设置成功
|
||
"""
|
||
mix = max(0.0, min(1.0, mix))
|
||
return self.set_effect_parameter(effect_name, 'mix', mix)
|
||
|
||
def set_sample_rate(self, sample_rate: int):
|
||
"""
|
||
设置采样率
|
||
|
||
Args:
|
||
sample_rate: 采样率 (Hz)
|
||
"""
|
||
self.sample_rate = sample_rate
|
||
print(f"✓ 效果处理器采样率设置为: {self.sample_rate} Hz")
|
||
|
||
def create_modulation_effect(self, effect_name: str, effect_type: str,
|
||
mod_rate: float, mod_depth: float) -> bool:
|
||
"""
|
||
创建调制效果
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
effect_type: 效果类型 (chorus, flanger, phaser, tremolo, vibrato)
|
||
mod_rate: 调制速率 (Hz)
|
||
mod_depth: 调制深度 (0.0-1.0)
|
||
|
||
Returns:
|
||
是否创建成功
|
||
"""
|
||
try:
|
||
# 验证调制效果类型
|
||
modulation_effects = ['chorus', 'flanger', 'phaser', 'tremolo', 'vibrato']
|
||
if effect_type not in modulation_effects:
|
||
print(f"✗ 无效的调制效果类型: {effect_type}")
|
||
return False
|
||
|
||
# 创建效果参数
|
||
effect_params = {
|
||
'rate': mod_rate,
|
||
'depth': mod_depth,
|
||
'mix': 0.5
|
||
}
|
||
|
||
return self.create_effect(effect_name, effect_type, effect_params)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 创建调制效果失败: {e}")
|
||
return False
|
||
|
||
def create_dynamic_effect(self, effect_name: str, effect_type: str,
|
||
intensity_callback: callable) -> bool:
|
||
"""
|
||
创建动态效果(参数随游戏状态变化)
|
||
|
||
Args:
|
||
effect_name: 效果名称
|
||
effect_type: 效果类型
|
||
intensity_callback: 强度回调函数
|
||
|
||
Returns:
|
||
是否创建成功
|
||
"""
|
||
try:
|
||
# 创建效果
|
||
if self.create_effect(effect_name, effect_type, {}):
|
||
# 添加动态参数支持
|
||
self.effects[effect_name]['dynamic'] = True
|
||
self.effects[effect_name]['intensity_callback'] = intensity_callback
|
||
return True
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"✗ 创建动态效果失败: {e}")
|
||
return False
|
||
|
||
def update_dynamic_effects(self):
|
||
"""
|
||
更新动态效果参数
|
||
"""
|
||
try:
|
||
for effect_name, effect in self.active_effects.items():
|
||
if effect.get('dynamic', False) and 'intensity_callback' in effect:
|
||
try:
|
||
# 获取当前强度
|
||
intensity = effect['intensity_callback']()
|
||
|
||
# 根据强度调整效果参数
|
||
effect_type = effect['type']
|
||
params = effect['params']
|
||
|
||
if effect_type == 'reverb':
|
||
params['room_size'] = intensity
|
||
params['wet_level'] = intensity * 0.5
|
||
elif effect_type == 'chorus':
|
||
params['rate'] = 0.5 + intensity * 4.5
|
||
params['depth'] = intensity
|
||
elif effect_type == 'delay':
|
||
params['time'] = 0.1 + intensity * 0.9
|
||
params['feedback'] = intensity * 0.8
|
||
|
||
# 更新效果参数
|
||
self.active_effects[effect_name]['params'] = params
|
||
|
||
except Exception as e:
|
||
print(f"✗ 更新动态效果参数失败: {effect_name} - {e}")
|
||
|
||
except Exception as e:
|
||
print(f"✗ 更新动态效果失败: {e}") |