1180 lines
43 KiB
Python
1180 lines
43 KiB
Python
"""
|
|
效果处理器模块
|
|
负责创建和处理各种触觉效果
|
|
"""
|
|
|
|
import time
|
|
import math
|
|
from typing import Dict, Any, List, Optional
|
|
import threading
|
|
import random
|
|
|
|
class EffectType:
|
|
"""效果类型常量"""
|
|
SIMPLE = "simple"
|
|
PERIODIC = "periodic"
|
|
ENVELOPE = "envelope"
|
|
RAMP = "ramp"
|
|
CUSTOM = "custom"
|
|
NOISE = "noise"
|
|
IMPULSE = "impulse"
|
|
EXPLOSION = "explosion"
|
|
TEXTURE = "texture"
|
|
WIND = "wind"
|
|
WATER = "water"
|
|
HEAT = "heat"
|
|
COLD = "cold"
|
|
VIBRATION = "vibration"
|
|
PULSE = "pulse"
|
|
|
|
class EffectProcessor:
|
|
"""
|
|
效果处理器
|
|
负责创建和处理各种触觉效果
|
|
"""
|
|
|
|
def __init__(self, plugin):
|
|
"""
|
|
初始化效果处理器
|
|
|
|
Args:
|
|
plugin: 触觉反馈系统插件实例
|
|
"""
|
|
self.plugin = plugin
|
|
self.enabled = False
|
|
self.initialized = False
|
|
|
|
# 效果模板
|
|
self.effect_templates = {}
|
|
|
|
# 自定义效果
|
|
self.custom_effects = {}
|
|
self.effect_counter = 0
|
|
|
|
# 效果参数
|
|
self.effect_parameters = {
|
|
'simple': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.01, 10.0)
|
|
},
|
|
'periodic': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.01, 10.0),
|
|
'frequency': (1.0, 100.0),
|
|
'amplitude': (0.0, 1.0),
|
|
'offset': (0.0, 1.0),
|
|
'phase': (0.0, 360.0),
|
|
'waveform': ['sine', 'square', 'triangle', 'sawtooth']
|
|
},
|
|
'envelope': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.01, 10.0),
|
|
'attack_time': (0.0, 2.0),
|
|
'attack_level': (0.0, 1.0),
|
|
'fade_time': (0.0, 2.0),
|
|
'fade_level': (0.0, 1.0),
|
|
'sustain_level': (0.0, 1.0)
|
|
},
|
|
'ramp': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.01, 10.0),
|
|
'start_level': (0.0, 1.0),
|
|
'end_level': (0.0, 1.0),
|
|
'curve_type': ['linear', 'exponential', 'logarithmic']
|
|
},
|
|
'noise': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.01, 10.0),
|
|
'frequency': (1.0, 100.0),
|
|
'noise_type': ['white', 'pink', 'brown']
|
|
},
|
|
'impulse': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.001, 1.0),
|
|
'sharpness': (0.0, 1.0),
|
|
'shape': ['gaussian', 'exponential', 'linear']
|
|
},
|
|
'explosion': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.1, 5.0),
|
|
'rise_time': (0.01, 1.0),
|
|
'fall_time': (0.1, 2.0),
|
|
'frequency_start': (20.0, 100.0),
|
|
'frequency_end': (5.0, 50.0)
|
|
},
|
|
'texture': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.1, 10.0),
|
|
'frequency': (5.0, 50.0),
|
|
'roughness': (0.0, 1.0),
|
|
'spacing': (0.01, 1.0)
|
|
},
|
|
'wind': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.5, 30.0),
|
|
'frequency': (0.1, 10.0),
|
|
'turbulence': (0.0, 1.0),
|
|
'direction_variability': (0.0, 1.0)
|
|
},
|
|
'water': {
|
|
'intensity': (0.0, 1.0),
|
|
'duration': (0.5, 30.0),
|
|
'frequency': (0.5, 20.0),
|
|
'wave_height': (0.1, 5.0),
|
|
'viscosity': (0.1, 10.0)
|
|
}
|
|
}
|
|
|
|
# 预定义效果
|
|
self.predefined_effects = {
|
|
'click': {
|
|
'type': EffectType.IMPULSE,
|
|
'intensity': 0.8,
|
|
'duration': 0.05,
|
|
'sharpness': 0.9,
|
|
'shape': 'gaussian'
|
|
},
|
|
'buzz': {
|
|
'type': EffectType.PERIODIC,
|
|
'intensity': 0.6,
|
|
'duration': 0.5,
|
|
'frequency': 50.0,
|
|
'amplitude': 0.5,
|
|
'waveform': 'sine'
|
|
},
|
|
'rumble': {
|
|
'type': EffectType.PERIODIC,
|
|
'intensity': 0.7,
|
|
'duration': 1.0,
|
|
'frequency': 20.0,
|
|
'amplitude': 0.6,
|
|
'waveform': 'sine'
|
|
},
|
|
'pulse': {
|
|
'type': EffectType.PERIODIC,
|
|
'intensity': 0.5,
|
|
'duration': 0.3,
|
|
'frequency': 30.0,
|
|
'amplitude': 0.4,
|
|
'waveform': 'sine'
|
|
},
|
|
'heartbeat': {
|
|
'type': EffectType.ENVELOPE,
|
|
'intensity': 0.6,
|
|
'duration': 1.5,
|
|
'attack_time': 0.1,
|
|
'attack_level': 0.8,
|
|
'fade_time': 0.3,
|
|
'fade_level': 0.2,
|
|
'sustain_level': 0.5
|
|
},
|
|
'explosion': {
|
|
'type': EffectType.EXPLOSION,
|
|
'intensity': 1.0,
|
|
'duration': 2.0,
|
|
'rise_time': 0.05,
|
|
'fall_time': 0.8,
|
|
'frequency_start': 80.0,
|
|
'frequency_end': 10.0
|
|
},
|
|
'impact': {
|
|
'type': EffectType.IMPULSE,
|
|
'intensity': 0.9,
|
|
'duration': 0.1,
|
|
'sharpness': 0.7,
|
|
'shape': 'exponential'
|
|
},
|
|
'texture_rough': {
|
|
'type': EffectType.TEXTURE,
|
|
'intensity': 0.4,
|
|
'duration': 2.0,
|
|
'frequency': 15.0,
|
|
'roughness': 0.8,
|
|
'spacing': 0.05
|
|
},
|
|
'texture_smooth': {
|
|
'type': EffectType.TEXTURE,
|
|
'intensity': 0.3,
|
|
'duration': 2.0,
|
|
'frequency': 8.0,
|
|
'roughness': 0.2,
|
|
'spacing': 0.1
|
|
},
|
|
'wind_light': {
|
|
'type': EffectType.WIND,
|
|
'intensity': 0.2,
|
|
'duration': 5.0,
|
|
'frequency': 0.5,
|
|
'turbulence': 0.3,
|
|
'direction_variability': 0.2
|
|
},
|
|
'wind_strong': {
|
|
'type': EffectType.WIND,
|
|
'intensity': 0.7,
|
|
'duration': 5.0,
|
|
'frequency': 2.0,
|
|
'turbulence': 0.8,
|
|
'direction_variability': 0.5
|
|
},
|
|
'water_shallow': {
|
|
'type': EffectType.WATER,
|
|
'intensity': 0.3,
|
|
'duration': 3.0,
|
|
'frequency': 2.0,
|
|
'wave_height': 0.5,
|
|
'viscosity': 1.0
|
|
},
|
|
'water_deep': {
|
|
'type': EffectType.WATER,
|
|
'intensity': 0.6,
|
|
'duration': 3.0,
|
|
'frequency': 0.8,
|
|
'wave_height': 2.0,
|
|
'viscosity': 3.0
|
|
}
|
|
}
|
|
|
|
# 效果混合
|
|
self.effect_mixing = {
|
|
'max': self._mix_max,
|
|
'add': self._mix_add,
|
|
'multiply': self._mix_multiply,
|
|
'average': self._mix_average,
|
|
'weighted': self._mix_weighted
|
|
}
|
|
|
|
# 波形生成器
|
|
self.waveform_generators = {
|
|
'sine': self._generate_sine_wave,
|
|
'square': self._generate_square_wave,
|
|
'triangle': self._generate_triangle_wave,
|
|
'sawtooth': self._generate_sawtooth_wave
|
|
}
|
|
|
|
# 噪声生成器
|
|
self.noise_generators = {
|
|
'white': self._generate_white_noise,
|
|
'pink': self._generate_pink_noise,
|
|
'brown': self._generate_brown_noise
|
|
}
|
|
|
|
# 脉冲形状生成器
|
|
self.impulse_shapes = {
|
|
'gaussian': self._generate_gaussian_impulse,
|
|
'exponential': self._generate_exponential_impulse,
|
|
'linear': self._generate_linear_impulse
|
|
}
|
|
|
|
# 统计信息
|
|
self.stats = {
|
|
'templates_created': 0,
|
|
'effects_generated': 0,
|
|
'effects_processed': 0,
|
|
'custom_effects': 0,
|
|
'waveforms_generated': 0,
|
|
'noise_samples': 0
|
|
}
|
|
|
|
# 回调函数
|
|
self.effect_callbacks = {
|
|
'effect_created': [],
|
|
'effect_processed': [],
|
|
'template_registered': [],
|
|
'waveform_generated': []
|
|
}
|
|
|
|
# 缓存
|
|
self.waveform_cache = {}
|
|
self.noise_cache = {}
|
|
|
|
# 随机数生成器
|
|
self.random_generator = random.Random()
|
|
|
|
print("✓ 效果处理器已创建")
|
|
|
|
def initialize(self) -> bool:
|
|
"""
|
|
初始化效果处理器
|
|
|
|
Returns:
|
|
是否初始化成功
|
|
"""
|
|
try:
|
|
# 注册预定义效果为模板
|
|
for name, effect_data in self.predefined_effects.items():
|
|
self.register_effect_template(name, effect_data)
|
|
|
|
# 初始化缓存
|
|
self._initialize_cache()
|
|
|
|
self.initialized = True
|
|
print("✓ 效果处理器初始化完成")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果处理器初始化失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def enable(self) -> bool:
|
|
"""
|
|
启用效果处理器
|
|
|
|
Returns:
|
|
是否启用成功
|
|
"""
|
|
try:
|
|
if not self.initialized:
|
|
print("✗ 效果处理器未初始化")
|
|
return False
|
|
|
|
self.enabled = True
|
|
print("✓ 效果处理器已启用")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果处理器启用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def disable(self):
|
|
"""禁用效果处理器"""
|
|
try:
|
|
self.enabled = False
|
|
print("✓ 效果处理器已禁用")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果处理器禁用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def finalize(self):
|
|
"""清理效果处理器资源"""
|
|
try:
|
|
self.disable()
|
|
self.effect_templates.clear()
|
|
self.custom_effects.clear()
|
|
self.effect_callbacks.clear()
|
|
self.waveform_cache.clear()
|
|
self.noise_cache.clear()
|
|
self.initialized = False
|
|
print("✓ 效果处理器资源已清理")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果处理器资源清理失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def update(self, dt: float):
|
|
"""
|
|
更新效果处理器状态
|
|
|
|
Args:
|
|
dt: 时间增量
|
|
"""
|
|
try:
|
|
if not self.enabled:
|
|
return
|
|
|
|
# 清理缓存(定期清理以节省内存)
|
|
self._cleanup_cache()
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果处理器更新失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def _initialize_cache(self):
|
|
"""初始化缓存"""
|
|
try:
|
|
# 预生成常用波形
|
|
common_frequencies = [10, 20, 30, 50, 100]
|
|
common_durations = [0.1, 0.5, 1.0, 2.0]
|
|
|
|
for freq in common_frequencies:
|
|
for duration in common_durations:
|
|
cache_key = f"sine_{freq}_{duration}"
|
|
self.waveform_cache[cache_key] = self._generate_sine_wave(freq, duration, 100)
|
|
|
|
print("✓ 波形缓存初始化完成")
|
|
except Exception as e:
|
|
print(f"✗ 波形缓存初始化失败: {e}")
|
|
|
|
def _cleanup_cache(self):
|
|
"""清理缓存"""
|
|
try:
|
|
# 保持缓存大小在合理范围内
|
|
max_cache_size = 1000
|
|
|
|
if len(self.waveform_cache) > max_cache_size:
|
|
# 移除最旧的一半缓存
|
|
keys_to_remove = list(self.waveform_cache.keys())[:max_cache_size//2]
|
|
for key in keys_to_remove:
|
|
del self.waveform_cache[key]
|
|
|
|
if len(self.noise_cache) > max_cache_size:
|
|
# 移除最旧的一半缓存
|
|
keys_to_remove = list(self.noise_cache.keys())[:max_cache_size//2]
|
|
for key in keys_to_remove:
|
|
del self.noise_cache[key]
|
|
|
|
except Exception as e:
|
|
print(f"✗ 缓存清理失败: {e}")
|
|
|
|
def register_effect_template(self, name: str, template: Dict[str, Any]) -> bool:
|
|
"""
|
|
注册效果模板
|
|
|
|
Args:
|
|
name: 模板名称
|
|
template: 模板数据
|
|
|
|
Returns:
|
|
是否注册成功
|
|
"""
|
|
try:
|
|
self.effect_templates[name] = template.copy()
|
|
self.stats['templates_created'] += 1
|
|
|
|
# 触发模板注册回调
|
|
self._trigger_effect_callback('template_registered', {
|
|
'template_name': name,
|
|
'template_data': template
|
|
})
|
|
|
|
print(f"✓ 效果模板已注册: {name}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果模板注册失败: {e}")
|
|
return False
|
|
|
|
def unregister_effect_template(self, name: str) -> bool:
|
|
"""
|
|
注销效果模板
|
|
|
|
Args:
|
|
name: 模板名称
|
|
|
|
Returns:
|
|
是否注销成功
|
|
"""
|
|
try:
|
|
if name in self.effect_templates:
|
|
del self.effect_templates[name]
|
|
print(f"✓ 效果模板已注销: {name}")
|
|
return True
|
|
else:
|
|
print(f"✗ 效果模板不存在: {name}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果模板注销失败: {e}")
|
|
return False
|
|
|
|
def create_effect_from_template(self, template_name: str,
|
|
overrides: Dict[str, Any] = None) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
从模板创建效果
|
|
|
|
Args:
|
|
template_name: 模板名称
|
|
overrides: 覆盖参数
|
|
|
|
Returns:
|
|
效果数据字典或None
|
|
"""
|
|
try:
|
|
if template_name not in self.effect_templates:
|
|
print(f"✗ 效果模板不存在: {template_name}")
|
|
return None
|
|
|
|
# 获取模板数据
|
|
template = self.effect_templates[template_name].copy()
|
|
|
|
# 应用覆盖参数
|
|
if overrides:
|
|
template.update(overrides)
|
|
|
|
# 添加创建时间戳
|
|
template['created_time'] = time.time()
|
|
|
|
# 触发效果创建回调
|
|
self._trigger_effect_callback('effect_created', {
|
|
'template_name': template_name,
|
|
'effect_data': template
|
|
})
|
|
|
|
self.stats['effects_generated'] += 1
|
|
print(f"✓ 效果已从模板创建: {template_name}")
|
|
return template
|
|
|
|
except Exception as e:
|
|
print(f"✗ 从模板创建效果失败: {e}")
|
|
return None
|
|
|
|
def create_custom_effect(self, effect_type: str, parameters: Dict[str, Any]) -> int:
|
|
"""
|
|
创建自定义效果
|
|
|
|
Args:
|
|
effect_type: 效果类型
|
|
parameters: 效果参数
|
|
|
|
Returns:
|
|
效果ID
|
|
"""
|
|
try:
|
|
effect_id = self.effect_counter
|
|
self.effect_counter += 1
|
|
|
|
custom_effect = {
|
|
'id': effect_id,
|
|
'type': effect_type,
|
|
'parameters': parameters,
|
|
'created_time': time.time()
|
|
}
|
|
|
|
self.custom_effects[effect_id] = custom_effect
|
|
self.stats['custom_effects'] += 1
|
|
|
|
# 触发效果创建回调
|
|
self._trigger_effect_callback('effect_created', {
|
|
'effect_id': effect_id,
|
|
'effect_data': custom_effect
|
|
})
|
|
|
|
print(f"✓ 自定义效果已创建: {effect_type} (ID: {effect_id})")
|
|
return effect_id
|
|
|
|
except Exception as e:
|
|
print(f"✗ 自定义效果创建失败: {e}")
|
|
return -1
|
|
|
|
def remove_custom_effect(self, effect_id: int) -> bool:
|
|
"""
|
|
移除自定义效果
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
|
|
Returns:
|
|
是否移除成功
|
|
"""
|
|
try:
|
|
if effect_id in self.custom_effects:
|
|
del self.custom_effects[effect_id]
|
|
self.stats['custom_effects'] -= 1
|
|
print(f"✓ 自定义效果已移除: ID {effect_id}")
|
|
return True
|
|
else:
|
|
print(f"✗ 自定义效果不存在: ID {effect_id}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ 自定义效果移除失败: {e}")
|
|
return False
|
|
|
|
def get_custom_effect(self, effect_id: int) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
获取自定义效果
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
|
|
Returns:
|
|
效果数据字典或None
|
|
"""
|
|
return self.custom_effects.get(effect_id)
|
|
|
|
def get_all_custom_effects(self) -> Dict[int, Dict[str, Any]]:
|
|
"""
|
|
获取所有自定义效果
|
|
|
|
Returns:
|
|
所有自定义效果字典
|
|
"""
|
|
return self.custom_effects.copy()
|
|
|
|
def process_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""
|
|
处理效果并计算当前强度
|
|
|
|
Args:
|
|
effect_data: 效果数据
|
|
time_progress: 时间进度(0.0-1.0)
|
|
|
|
Returns:
|
|
当前强度值(0.0-1.0)
|
|
"""
|
|
try:
|
|
effect_type = effect_data.get('type', EffectType.SIMPLE)
|
|
intensity = effect_data.get('intensity', 1.0)
|
|
|
|
# 根据效果类型计算强度
|
|
if effect_type == EffectType.SIMPLE:
|
|
current_intensity = self._process_simple_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.PERIODIC:
|
|
current_intensity = self._process_periodic_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.ENVELOPE:
|
|
current_intensity = self._process_envelope_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.RAMP:
|
|
current_intensity = self._process_ramp_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.NOISE:
|
|
current_intensity = self._process_noise_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.IMPULSE:
|
|
current_intensity = self._process_impulse_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.EXPLOSION:
|
|
current_intensity = self._process_explosion_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.TEXTURE:
|
|
current_intensity = self._process_texture_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.WIND:
|
|
current_intensity = self._process_wind_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.WATER:
|
|
current_intensity = self._process_water_effect(effect_data, time_progress)
|
|
elif effect_type == EffectType.CUSTOM:
|
|
current_intensity = self._process_custom_effect(effect_data, time_progress)
|
|
else:
|
|
current_intensity = intensity # 默认返回固定强度
|
|
|
|
# 应用总体强度
|
|
current_intensity *= intensity
|
|
|
|
# 触发效果处理回调
|
|
self._trigger_effect_callback('effect_processed', {
|
|
'effect_data': effect_data,
|
|
'time_progress': time_progress,
|
|
'current_intensity': current_intensity
|
|
})
|
|
|
|
self.stats['effects_processed'] += 1
|
|
return max(0.0, min(1.0, current_intensity))
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_simple_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理简单效果"""
|
|
return 1.0 # 固定强度
|
|
|
|
def _process_periodic_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理周期性效果"""
|
|
try:
|
|
frequency = effect_data.get('frequency', 10.0)
|
|
amplitude = effect_data.get('amplitude', 1.0)
|
|
offset = effect_data.get('offset', 0.0)
|
|
phase = effect_data.get('phase', 0.0)
|
|
waveform = effect_data.get('waveform', 'sine')
|
|
duration = effect_data.get('duration', 1.0)
|
|
|
|
# 生成波形
|
|
generator = self.waveform_generators.get(waveform, self._generate_sine_wave)
|
|
cache_key = f"{waveform}_{frequency}_{duration}"
|
|
|
|
# 检查缓存
|
|
if cache_key in self.waveform_cache:
|
|
waveform_data = self.waveform_cache[cache_key]
|
|
else:
|
|
# 生成波形数据
|
|
sample_count = max(100, int(frequency * duration * 10))
|
|
waveform_data = generator(frequency, duration, sample_count)
|
|
self.waveform_cache[cache_key] = waveform_data
|
|
self.stats['waveforms_generated'] += 1
|
|
|
|
# 计算当前样本索引
|
|
sample_index = int(time_progress * (len(waveform_data) - 1))
|
|
sample_index = max(0, min(len(waveform_data) - 1, sample_index))
|
|
|
|
# 获取波形值
|
|
waveform_value = waveform_data[sample_index]
|
|
|
|
# 应用振幅和偏移
|
|
result = offset + amplitude * waveform_value
|
|
|
|
return max(0.0, min(1.0, result))
|
|
except Exception as e:
|
|
print(f"✗ 周期性效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_envelope_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理包络效果"""
|
|
try:
|
|
attack_time = effect_data.get('attack_time', 0.1)
|
|
attack_level = effect_data.get('attack_level', 1.0)
|
|
fade_time = effect_data.get('fade_time', 0.1)
|
|
fade_level = effect_data.get('fade_level', 0.0)
|
|
sustain_level = effect_data.get('sustain_level', 0.5)
|
|
duration = effect_data.get('duration', 1.0)
|
|
|
|
if time_progress <= attack_time / duration:
|
|
# 攻击阶段
|
|
attack_progress = time_progress / (attack_time / duration)
|
|
return attack_progress * attack_level
|
|
elif time_progress >= 1.0 - (fade_time / duration):
|
|
# 衰减阶段
|
|
fade_progress = (time_progress - (1.0 - (fade_time / duration))) / (fade_time / duration)
|
|
return fade_level + (1.0 - fade_progress) * (sustain_level - fade_level)
|
|
else:
|
|
# 保持阶段
|
|
return sustain_level
|
|
except Exception as e:
|
|
print(f"✗ 包络效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_ramp_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理斜坡效果"""
|
|
try:
|
|
start_level = effect_data.get('start_level', 0.0)
|
|
end_level = effect_data.get('end_level', 1.0)
|
|
curve_type = effect_data.get('curve_type', 'linear')
|
|
|
|
if curve_type == 'exponential':
|
|
# 指数曲线
|
|
return start_level + (end_level - start_level) * (time_progress ** 2)
|
|
elif curve_type == 'logarithmic':
|
|
# 对数曲线
|
|
if time_progress <= 0:
|
|
return start_level
|
|
return start_level + (end_level - start_level) * math.log10(1 + 9 * time_progress)
|
|
else:
|
|
# 线性曲线
|
|
return start_level + (end_level - start_level) * time_progress
|
|
except Exception as e:
|
|
print(f"✗ 斜坡效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_noise_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理噪声效果"""
|
|
try:
|
|
frequency = effect_data.get('frequency', 10.0)
|
|
noise_type = effect_data.get('noise_type', 'white')
|
|
duration = effect_data.get('duration', 1.0)
|
|
|
|
# 生成噪声
|
|
generator = self.noise_generators.get(noise_type, self._generate_white_noise)
|
|
cache_key = f"{noise_type}_{frequency}_{duration}"
|
|
|
|
# 检查缓存
|
|
if cache_key in self.noise_cache:
|
|
noise_data = self.noise_cache[cache_key]
|
|
else:
|
|
# 生成噪声数据
|
|
sample_count = max(100, int(frequency * duration * 10))
|
|
noise_data = generator(sample_count)
|
|
self.noise_cache[cache_key] = noise_data
|
|
self.stats['noise_samples'] += sample_count
|
|
|
|
# 计算当前样本索引
|
|
sample_index = int(time_progress * (len(noise_data) - 1))
|
|
sample_index = max(0, min(len(noise_data) - 1, sample_index))
|
|
|
|
# 获取噪声值
|
|
noise_value = noise_data[sample_index]
|
|
|
|
return max(0.0, min(1.0, noise_value))
|
|
except Exception as e:
|
|
print(f"✗ 噪声效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_impulse_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理脉冲效果"""
|
|
try:
|
|
duration = effect_data.get('duration', 0.1)
|
|
sharpness = effect_data.get('sharpness', 0.5)
|
|
shape = effect_data.get('shape', 'gaussian')
|
|
|
|
# 生成脉冲
|
|
generator = self.impulse_shapes.get(shape, self._generate_gaussian_impulse)
|
|
|
|
# 计算脉冲值
|
|
impulse_value = generator(time_progress, sharpness)
|
|
|
|
return max(0.0, min(1.0, impulse_value))
|
|
except Exception as e:
|
|
print(f"✗ 脉冲效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_explosion_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理爆炸效果"""
|
|
try:
|
|
rise_time = effect_data.get('rise_time', 0.05)
|
|
fall_time = effect_data.get('fall_time', 0.5)
|
|
frequency_start = effect_data.get('frequency_start', 80.0)
|
|
frequency_end = effect_data.get('frequency_end', 10.0)
|
|
duration = effect_data.get('duration', 1.0)
|
|
|
|
# 计算频率变化
|
|
frequency = frequency_start + (frequency_end - frequency_start) * time_progress
|
|
|
|
# 计算振幅包络
|
|
if time_progress <= rise_time / duration:
|
|
# 上升阶段
|
|
envelope = time_progress / (rise_time / duration)
|
|
else:
|
|
# 下降阶段
|
|
fall_progress = (time_progress - (rise_time / duration)) / ((duration - rise_time) / duration)
|
|
envelope = max(0.0, 1.0 - fall_progress)
|
|
|
|
# 生成振动
|
|
vibration = math.sin(2 * math.pi * frequency * time_progress * duration)
|
|
result = envelope * (vibration + 1.0) / 2.0 # 转换到0-1范围
|
|
|
|
return max(0.0, min(1.0, result))
|
|
except Exception as e:
|
|
print(f"✗ 爆炸效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_texture_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理纹理效果"""
|
|
try:
|
|
frequency = effect_data.get('frequency', 10.0)
|
|
roughness = effect_data.get('roughness', 0.5)
|
|
spacing = effect_data.get('spacing', 0.1)
|
|
|
|
# 生成纹理模式
|
|
texture_position = time_progress * frequency
|
|
texture_phase = texture_position - math.floor(texture_position)
|
|
|
|
# 根据粗糙度调整强度
|
|
if texture_phase < spacing:
|
|
# 纹理凸起
|
|
intensity = 1.0 - (texture_phase / spacing) * roughness
|
|
else:
|
|
# 纹理凹陷
|
|
intensity = 0.5 + 0.5 * roughness * math.sin(2 * math.pi * texture_phase)
|
|
|
|
return max(0.0, min(1.0, intensity))
|
|
except Exception as e:
|
|
print(f"✗ 纹理效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_wind_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理风效果"""
|
|
try:
|
|
frequency = effect_data.get('frequency', 1.0)
|
|
turbulence = effect_data.get('turbulence', 0.5)
|
|
direction_variability = effect_data.get('direction_variability', 0.3)
|
|
|
|
# 基础风模式
|
|
base_wind = math.sin(2 * math.pi * frequency * time_progress)
|
|
|
|
# 添加湍流
|
|
turbulence_effect = turbulence * math.sin(2 * math.pi * frequency * 5 * time_progress)
|
|
|
|
# 添加方向变化
|
|
direction_effect = direction_variability * math.sin(2 * math.pi * frequency * 0.2 * time_progress)
|
|
|
|
# 组合效果
|
|
result = (base_wind + turbulence_effect + direction_effect) / 3.0
|
|
result = (result + 1.0) / 2.0 # 转换到0-1范围
|
|
|
|
return max(0.0, min(1.0, result))
|
|
except Exception as e:
|
|
print(f"✗ 风效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_water_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理水效果"""
|
|
try:
|
|
frequency = effect_data.get('frequency', 1.0)
|
|
wave_height = effect_data.get('wave_height', 1.0)
|
|
viscosity = effect_data.get('viscosity', 1.0)
|
|
|
|
# 主波浪
|
|
main_wave = math.sin(2 * math.pi * frequency * time_progress)
|
|
|
|
# 次级波浪
|
|
secondary_wave = 0.5 * math.sin(2 * math.pi * frequency * 2.5 * time_progress + 0.5)
|
|
|
|
# 粘性阻尼
|
|
damping = math.exp(-viscosity * time_progress)
|
|
|
|
# 组合效果
|
|
result = (main_wave + secondary_wave) * damping * wave_height
|
|
result = (result + 1.0) / 2.0 # 转换到0-1范围
|
|
|
|
return max(0.0, min(1.0, result))
|
|
except Exception as e:
|
|
print(f"✗ 水效果处理失败: {e}")
|
|
return 0.0
|
|
|
|
def _process_custom_effect(self, effect_data: Dict[str, Any], time_progress: float) -> float:
|
|
"""处理自定义效果"""
|
|
# 这里可以实现更复杂的自定义效果处理逻辑
|
|
parameters = effect_data.get('parameters', {})
|
|
custom_intensity = parameters.get('intensity_multiplier', 1.0)
|
|
return custom_intensity # 默认返回固定强度
|
|
|
|
def _generate_sine_wave(self, frequency: float, duration: float, samples: int) -> List[float]:
|
|
"""生成正弦波"""
|
|
wave = []
|
|
for i in range(samples):
|
|
t = i / (samples - 1) * duration
|
|
value = math.sin(2 * math.pi * frequency * t)
|
|
wave.append(value)
|
|
return wave
|
|
|
|
def _generate_square_wave(self, frequency: float, duration: float, samples: int) -> List[float]:
|
|
"""生成方波"""
|
|
wave = []
|
|
for i in range(samples):
|
|
t = i / (samples - 1) * duration
|
|
value = 1.0 if math.sin(2 * math.pi * frequency * t) >= 0 else -1.0
|
|
wave.append(value)
|
|
return wave
|
|
|
|
def _generate_triangle_wave(self, frequency: float, duration: float, samples: int) -> List[float]:
|
|
"""生成三角波"""
|
|
wave = []
|
|
for i in range(samples):
|
|
t = i / (samples - 1) * duration
|
|
value = 2 * abs(2 * (frequency * t - math.floor(frequency * t + 0.5))) - 1
|
|
wave.append(value)
|
|
return wave
|
|
|
|
def _generate_sawtooth_wave(self, frequency: float, duration: float, samples: int) -> List[float]:
|
|
"""生成锯齿波"""
|
|
wave = []
|
|
for i in range(samples):
|
|
t = i / (samples - 1) * duration
|
|
value = 2 * (frequency * t - math.floor(frequency * t + 0.5))
|
|
wave.append(value)
|
|
return wave
|
|
|
|
def _generate_white_noise(self, samples: int) -> List[float]:
|
|
"""生成白噪声"""
|
|
noise = []
|
|
for _ in range(samples):
|
|
value = self.random_generator.uniform(-1.0, 1.0)
|
|
noise.append(value)
|
|
return noise
|
|
|
|
def _generate_pink_noise(self, samples: int) -> List[float]:
|
|
"""生成粉红噪声"""
|
|
noise = []
|
|
b = [0.0] * 7
|
|
for _ in range(samples):
|
|
white = self.random_generator.uniform(-1.0, 1.0)
|
|
b[0] = 0.99886 * b[0] + white * 0.0555179
|
|
b[1] = 0.99332 * b[1] + white * 0.0750759
|
|
b[2] = 0.96900 * b[2] + white * 0.1538520
|
|
b[3] = 0.86650 * b[3] + white * 0.3104856
|
|
b[4] = 0.55000 * b[4] + white * 0.5329522
|
|
b[5] = -0.7616 * b[5] - white * 0.0168980
|
|
pink = b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6] + white * 0.5362
|
|
b[6] = white * 0.115926
|
|
noise.append(pink / 5.0) # 归一化
|
|
return noise
|
|
|
|
def _generate_brown_noise(self, samples: int) -> List[float]:
|
|
"""生成布朗噪声"""
|
|
noise = []
|
|
last = 0.0
|
|
for _ in range(samples):
|
|
white = self.random_generator.uniform(-1.0, 1.0)
|
|
brown = (last + (0.02 * white)) / 1.02
|
|
last = brown
|
|
noise.append(brown * 3.5) # 补偿幅度
|
|
return noise
|
|
|
|
def _generate_gaussian_impulse(self, time_progress: float, sharpness: float) -> float:
|
|
"""生成高斯脉冲"""
|
|
try:
|
|
# 高斯函数: exp(-(x^2)/(2*sigma^2))
|
|
sigma = 0.2 * (1.0 - sharpness * 0.8) # 根据锐度调整宽度
|
|
x = (time_progress - 0.5) * 2 # 调整到-1到1范围
|
|
value = math.exp(-(x*x) / (2 * sigma * sigma))
|
|
return value
|
|
except Exception:
|
|
return 0.0
|
|
|
|
def _generate_exponential_impulse(self, time_progress: float, sharpness: float) -> float:
|
|
"""生成指数脉冲"""
|
|
try:
|
|
if time_progress < 0.5:
|
|
# 上升阶段
|
|
rise_factor = 1.0 + 9.0 * sharpness # 1到10
|
|
value = 1.0 - math.exp(-rise_factor * time_progress * 2)
|
|
else:
|
|
# 下降阶段
|
|
fall_factor = 1.0 + 9.0 * (1.0 - sharpness) # 1到10
|
|
value = math.exp(-fall_factor * (time_progress - 0.5) * 2)
|
|
return value
|
|
except Exception:
|
|
return 0.0
|
|
|
|
def _generate_linear_impulse(self, time_progress: float, sharpness: float) -> float:
|
|
"""生成线性脉冲"""
|
|
try:
|
|
peak_position = 0.3 + 0.4 * sharpness # 0.3到0.7
|
|
if time_progress < peak_position:
|
|
# 上升阶段
|
|
value = time_progress / peak_position
|
|
else:
|
|
# 下降阶段
|
|
value = 1.0 - (time_progress - peak_position) / (1.0 - peak_position)
|
|
return max(0.0, value)
|
|
except Exception:
|
|
return 0.0
|
|
|
|
def mix_effects(self, effects: List[Dict[str, Any]], time_progress: float,
|
|
mix_mode: str = 'max', weights: List[float] = None) -> float:
|
|
"""
|
|
混合多个效果
|
|
|
|
Args:
|
|
effects: 效果数据列表
|
|
time_progress: 时间进度(0.0-1.0)
|
|
mix_mode: 混合模式('max', 'add', 'multiply', 'average', 'weighted')
|
|
weights: 权重列表(用于加权混合)
|
|
|
|
Returns:
|
|
混合后的强度值(0.0-1.0)
|
|
"""
|
|
try:
|
|
intensities = []
|
|
for effect_data in effects:
|
|
intensity = self.process_effect(effect_data, time_progress)
|
|
intensities.append(intensity)
|
|
|
|
if not intensities:
|
|
return 0.0
|
|
|
|
# 根据混合模式计算最终强度
|
|
if mix_mode == 'weighted' and weights:
|
|
mix_function = self._mix_weighted
|
|
return mix_function(intensities, weights)
|
|
else:
|
|
mix_function = self.effect_mixing.get(mix_mode, self._mix_max)
|
|
return mix_function(intensities)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 效果混合失败: {e}")
|
|
return 0.0
|
|
|
|
def _mix_max(self, intensities: List[float]) -> float:
|
|
"""最大值混合"""
|
|
return max(intensities)
|
|
|
|
def _mix_add(self, intensities: List[float]) -> float:
|
|
"""加法混合"""
|
|
return min(1.0, sum(intensities))
|
|
|
|
def _mix_multiply(self, intensities: List[float]) -> float:
|
|
"""乘法混合"""
|
|
result = 1.0
|
|
for intensity in intensities:
|
|
result *= max(0.0, intensity) # 避免负值影响
|
|
return result
|
|
|
|
def _mix_average(self, intensities: List[float]) -> float:
|
|
"""平均值混合"""
|
|
return sum(intensities) / len(intensities) if intensities else 0.0
|
|
|
|
def _mix_weighted(self, intensities: List[float], weights: List[float]) -> float:
|
|
"""加权混合"""
|
|
if len(intensities) != len(weights):
|
|
return self._mix_average(intensities)
|
|
|
|
weighted_sum = sum(intensity * weight for intensity, weight in zip(intensities, weights))
|
|
total_weight = sum(weights)
|
|
return weighted_sum / total_weight if total_weight > 0 else 0.0
|
|
|
|
def get_effect_parameters(self, effect_type: str) -> Dict[str, tuple]:
|
|
"""
|
|
获取效果参数信息
|
|
|
|
Args:
|
|
effect_type: 效果类型
|
|
|
|
Returns:
|
|
参数信息字典
|
|
"""
|
|
return self.effect_parameters.get(effect_type, {})
|
|
|
|
def get_predefined_effects(self) -> Dict[str, Dict[str, Any]]:
|
|
"""
|
|
获取预定义效果
|
|
|
|
Returns:
|
|
预定义效果字典
|
|
"""
|
|
return self.predefined_effects.copy()
|
|
|
|
def _trigger_effect_callback(self, callback_type: str, data: Dict[str, Any]):
|
|
"""
|
|
触发效果回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
data: 回调数据
|
|
"""
|
|
try:
|
|
if callback_type in self.effect_callbacks:
|
|
for callback in self.effect_callbacks[callback_type]:
|
|
try:
|
|
callback(data)
|
|
except Exception as e:
|
|
print(f"✗ 效果回调执行失败: {e}")
|
|
except Exception as e:
|
|
print(f"✗ 效果回调触发失败: {e}")
|
|
|
|
def register_effect_callback(self, callback_type: str, callback: callable):
|
|
"""
|
|
注册效果回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
callback: 回调函数
|
|
"""
|
|
try:
|
|
if callback_type in self.effect_callbacks:
|
|
self.effect_callbacks[callback_type].append(callback)
|
|
print(f"✓ 效果回调已注册: {callback_type}")
|
|
else:
|
|
print(f"✗ 无效的回调类型: {callback_type}")
|
|
except Exception as e:
|
|
print(f"✗ 效果回调注册失败: {e}")
|
|
|
|
def unregister_effect_callback(self, callback_type: str, callback: callable):
|
|
"""
|
|
注销效果回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
callback: 回调函数
|
|
"""
|
|
try:
|
|
if callback_type in self.effect_callbacks:
|
|
if callback in self.effect_callbacks[callback_type]:
|
|
self.effect_callbacks[callback_type].remove(callback)
|
|
print(f"✓ 效果回调已注销: {callback_type}")
|
|
except Exception as e:
|
|
print(f"✗ 效果回调注销失败: {e}")
|
|
|
|
def get_stats(self) -> Dict[str, int]:
|
|
"""
|
|
获取统计信息
|
|
|
|
Returns:
|
|
统计信息字典
|
|
"""
|
|
return self.stats.copy()
|
|
|
|
def reset_stats(self):
|
|
"""重置统计信息"""
|
|
try:
|
|
self.stats = {
|
|
'templates_created': 0,
|
|
'effects_generated': 0,
|
|
'effects_processed': 0,
|
|
'custom_effects': 0,
|
|
'waveforms_generated': 0,
|
|
'noise_samples': 0
|
|
}
|
|
print("✓ 效果处理器统计信息已重置")
|
|
except Exception as e:
|
|
print(f"✗ 效果处理器统计信息重置失败: {e}") |