1039 lines
35 KiB
Python
1039 lines
35 KiB
Python
"""
|
|
混响效果处理器
|
|
实现专业的音频混响效果处理
|
|
"""
|
|
|
|
import uuid
|
|
import math
|
|
import numpy as np
|
|
from typing import Dict, List, Any, Optional
|
|
from scipy import signal
|
|
|
|
class ReverbProcessor:
|
|
"""
|
|
混响效果处理器
|
|
实现专业的音频混响效果处理
|
|
"""
|
|
|
|
def __init__(self, plugin):
|
|
"""
|
|
初始化混响效果处理器
|
|
|
|
Args:
|
|
plugin: 音频效果插件实例
|
|
"""
|
|
self.plugin = plugin
|
|
self.effects: Dict[str, Dict[str, Any]] = {}
|
|
self.comb_filters = {} # 梳状滤波器
|
|
self.allpass_filters = {} # 全通滤波器
|
|
self.stats = {
|
|
'total_effects': 0,
|
|
'active_effects': 0,
|
|
'effects_processed': 0,
|
|
'processing_time': 0.0,
|
|
'memory_usage': 0
|
|
}
|
|
self.buffer_size = plugin.buffer_size if plugin else 4096
|
|
self.sample_rate = 44100 # 默认采样率
|
|
|
|
# 初始化混响参数
|
|
self._initialize_reverb_parameters()
|
|
|
|
def _initialize_reverb_parameters(self):
|
|
"""初始化混响参数"""
|
|
# 梳状滤波器延迟时间(毫秒)
|
|
self.comb_delays = [1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617]
|
|
|
|
# 全通滤波器延迟时间(毫秒)
|
|
self.allpass_delays = [556, 441, 341, 225]
|
|
|
|
# 混响衰减系数
|
|
self.comb_decay_factors = [0.8, 0.75, 0.7, 0.65, 0.6, 0.55, 0.5, 0.45]
|
|
|
|
# 全通滤波器系数
|
|
self.allpass_feedback = 0.7
|
|
|
|
def create_effect(self, parameters: Dict[str, Any]) -> str:
|
|
"""
|
|
创建混响效果
|
|
|
|
Args:
|
|
parameters: 混响参数
|
|
|
|
Returns:
|
|
效果ID
|
|
"""
|
|
try:
|
|
# 生成唯一ID
|
|
effect_id = str(uuid.uuid4())
|
|
|
|
# 默认参数
|
|
default_params = {
|
|
'room_size': 0.5, # 房间大小 (0.0-1.0)
|
|
'damping': 0.5, # 阻尼 (0.0-1.0)
|
|
'wet_level': 0.33, # 湿信号电平 (0.0-1.0)
|
|
'dry_level': 0.4, # 干信号电平 (0.0-1.0)
|
|
'width': 1.0, # 宽度 (0.0-1.0)
|
|
'freeze_mode': 0.0, # 冻结模式 (0.0-1.0)
|
|
'early_reflections': 0.5, # 早期反射 (0.0-1.0)
|
|
'late_reverb': 0.5, # 晚期混响 (0.0-1.0)
|
|
'diffusion': 0.7, # 扩散 (0.0-1.0)
|
|
'density': 0.5, # 密度 (0.0-1.0)
|
|
'predelay': 0.0, # 预延迟 (秒)
|
|
'high_freq_damping': 0.5, # 高频阻尼 (0.0-1.0)
|
|
'low_freq_damping': 0.3, # 低频阻尼 (0.0-1.0)
|
|
'stereo_spread': 0.5, # 立体声扩散 (0.0-1.0)
|
|
'reverb_time': 2.0, # 混响时间 (秒)
|
|
'tail_density': 0.8, # 尾部密度 (0.0-1.0)
|
|
'modulation_rate': 0.1, # 调制速率 (Hz)
|
|
'modulation_depth': 0.02 # 调制深度 (0.0-1.0)
|
|
}
|
|
|
|
# 合并参数
|
|
effect_params = default_params.copy()
|
|
effect_params.update(parameters)
|
|
|
|
# 创建效果对象
|
|
effect = {
|
|
'id': effect_id,
|
|
'type': 'reverb',
|
|
'parameters': effect_params,
|
|
'active': True,
|
|
'buffers': {}, # 各种缓冲区
|
|
'comb_filters': [], # 梳状滤波器数组
|
|
'allpass_filters': [], # 全通滤波器数组
|
|
'modulation_phase': 0.0, # 调制相位
|
|
'created_time': self._get_current_time(),
|
|
'process_count': 0
|
|
}
|
|
|
|
# 初始化滤波器
|
|
self._initialize_filters(effect)
|
|
|
|
# 初始化缓冲区
|
|
self._initialize_buffers(effect)
|
|
|
|
# 存储效果
|
|
self.effects[effect_id] = effect
|
|
|
|
# 更新统计信息
|
|
self.stats['total_effects'] += 1
|
|
self.stats['active_effects'] += 1
|
|
|
|
# 在插件中注册效果
|
|
if self.plugin:
|
|
self.plugin.effects[effect_id] = effect.copy()
|
|
|
|
print(f"✓ 混响效果创建成功: {effect_id}")
|
|
return effect_id
|
|
|
|
except Exception as e:
|
|
print(f"✗ 创建混响效果失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return ""
|
|
|
|
def _initialize_filters(self, effect: Dict[str, Any]):
|
|
"""
|
|
初始化混响滤波器
|
|
|
|
Args:
|
|
effect: 效果对象
|
|
"""
|
|
parameters = effect['parameters']
|
|
room_size = parameters.get('room_size', 0.5)
|
|
damping = parameters.get('damping', 0.5)
|
|
diffusion = parameters.get('diffusion', 0.7)
|
|
density = parameters.get('density', 0.5)
|
|
|
|
# 创建梳状滤波器
|
|
comb_filters = []
|
|
for i, (delay_ms, decay_factor) in enumerate(zip(self.comb_delays, self.comb_decay_factors)):
|
|
# 根据房间大小调整延迟时间
|
|
adjusted_delay = delay_ms * (0.5 + room_size * 0.5)
|
|
|
|
# 根据密度调整延迟时间
|
|
adjusted_delay *= (0.8 + density * 0.4)
|
|
|
|
# 计算延迟样本数
|
|
delay_samples = int(adjusted_delay * self.sample_rate / 1000)
|
|
|
|
# 根据扩散调整反馈系数
|
|
feedback = decay_factor * (0.7 + diffusion * 0.3)
|
|
|
|
# 根据阻尼调整高频衰减
|
|
damp_factor = 0.3 + damping * 0.5
|
|
|
|
comb_filter = {
|
|
'buffer': np.zeros(max(1, delay_samples)),
|
|
'index': 0,
|
|
'feedback': feedback,
|
|
'damp1': damp_factor,
|
|
'damp2': 0.0,
|
|
'filter_store': 0.0
|
|
}
|
|
comb_filters.append(comb_filter)
|
|
|
|
effect['comb_filters'] = comb_filters
|
|
|
|
# 创建全通滤波器
|
|
allpass_filters = []
|
|
for i, delay_ms in enumerate(self.allpass_delays):
|
|
# 根据房间大小调整延迟时间
|
|
adjusted_delay = delay_ms * (0.5 + room_size * 0.5)
|
|
|
|
# 计算延迟样本数
|
|
delay_samples = int(adjusted_delay * self.sample_rate / 1000)
|
|
|
|
allpass_filter = {
|
|
'buffer': np.zeros(max(1, delay_samples)),
|
|
'index': 0,
|
|
'feedback': self.allpass_feedback
|
|
}
|
|
allpass_filters.append(allpass_filter)
|
|
|
|
effect['allpass_filters'] = allpass_filters
|
|
|
|
def _initialize_buffers(self, effect: Dict[str, Any]):
|
|
"""
|
|
初始化混响缓冲区
|
|
|
|
Args:
|
|
effect: 效果对象
|
|
"""
|
|
effect_id = effect['id']
|
|
buffers = {}
|
|
|
|
# 输入和输出缓冲区
|
|
buffers['input'] = np.zeros(self.buffer_size)
|
|
buffers['output_left'] = np.zeros(self.buffer_size)
|
|
buffers['output_right'] = np.zeros(self.buffer_size)
|
|
buffers['mono_input'] = np.zeros(self.buffer_size)
|
|
|
|
# 预延迟缓冲区
|
|
predelay = effect['parameters'].get('predelay', 0.0)
|
|
predelay_samples = int(predelay * self.sample_rate)
|
|
buffers['predelay_buffer'] = np.zeros(max(1, predelay_samples))
|
|
buffers['predelay_index'] = 0
|
|
|
|
effect['buffers'] = buffers
|
|
|
|
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:
|
|
# 删除效果
|
|
del self.effects[effect_id]
|
|
|
|
# 更新统计信息
|
|
self.stats['active_effects'] -= 1
|
|
|
|
# 从插件中移除效果
|
|
if self.plugin and effect_id in self.plugin.effects:
|
|
del self.plugin.effects[effect_id]
|
|
|
|
print(f"✓ 混响效果已删除: {effect_id}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 删除混响效果失败: {e}")
|
|
return False
|
|
|
|
def process(self, audio_data: Any, parameters: Dict[str, Any]) -> Any:
|
|
"""
|
|
处理混响效果
|
|
|
|
Args:
|
|
audio_data: 输入音频数据
|
|
parameters: 效果参数
|
|
|
|
Returns:
|
|
处理后的音频数据
|
|
"""
|
|
try:
|
|
import time
|
|
process_start = time.time()
|
|
|
|
# 如果输入是NumPy数组
|
|
if isinstance(audio_data, np.ndarray):
|
|
processed_data = self._process_numpy_array(audio_data, parameters)
|
|
else:
|
|
# 对于其他类型的数据,返回原始数据
|
|
processed_data = audio_data
|
|
|
|
# 更新统计信息
|
|
self.stats['effects_processed'] += 1
|
|
self.stats['processing_time'] += (time.time() - process_start)
|
|
|
|
return processed_data
|
|
|
|
except Exception as e:
|
|
print(f"✗ 混响效果处理失败: {e}")
|
|
return audio_data
|
|
|
|
def _process_numpy_array(self, audio_data: np.ndarray, parameters: Dict[str, Any]) -> np.ndarray:
|
|
"""
|
|
处理NumPy数组音频数据
|
|
|
|
Args:
|
|
audio_data: 输入音频数据
|
|
parameters: 效果参数
|
|
|
|
Returns:
|
|
处理后的音频数据
|
|
"""
|
|
# 获取参数
|
|
room_size = parameters.get('room_size', 0.5)
|
|
damping = parameters.get('damping', 0.5)
|
|
wet_level = parameters.get('wet_level', 0.33)
|
|
dry_level = parameters.get('dry_level', 0.4)
|
|
width = parameters.get('width', 1.0)
|
|
freeze_mode = parameters.get('freeze_mode', 0.0)
|
|
early_reflections = parameters.get('early_reflections', 0.5)
|
|
late_reverb = parameters.get('late_reverb', 0.5)
|
|
diffusion = parameters.get('diffusion', 0.7)
|
|
density = parameters.get('density', 0.5)
|
|
predelay = parameters.get('predelay', 0.0)
|
|
high_freq_damping = parameters.get('high_freq_damping', 0.5)
|
|
low_freq_damping = parameters.get('low_freq_damping', 0.3)
|
|
stereo_spread = parameters.get('stereo_spread', 0.5)
|
|
reverb_time = parameters.get('reverb_time', 2.0)
|
|
tail_density = parameters.get('tail_density', 0.8)
|
|
modulation_rate = parameters.get('modulation_rate', 0.1)
|
|
modulation_depth = parameters.get('modulation_depth', 0.02)
|
|
|
|
# 如果是冻结模式,增加反馈
|
|
if freeze_mode > 0.5:
|
|
room_size = min(1.0, room_size + 0.2)
|
|
|
|
# 创建输出数组
|
|
if audio_data.ndim == 1:
|
|
# 单声道输入,生成立体声输出
|
|
output_left = np.zeros_like(audio_data)
|
|
output_right = np.zeros_like(audio_data)
|
|
|
|
# 处理每个样本
|
|
for i in range(len(audio_data)):
|
|
input_sample = audio_data[i]
|
|
|
|
# 预延迟处理
|
|
delayed_sample = self._apply_predelay(input_sample, predelay)
|
|
|
|
# 混响处理
|
|
reverb_left, reverb_right = self._apply_reverb(
|
|
delayed_sample, room_size, damping, diffusion, density,
|
|
stereo_spread, modulation_rate, modulation_depth)
|
|
|
|
# 应用早期反射和晚期混响权重
|
|
reverb_left *= (early_reflections * 0.3 + late_reverb * 0.7)
|
|
reverb_right *= (early_reflections * 0.3 + late_reverb * 0.7)
|
|
|
|
# 混合干湿信号
|
|
output_left[i] = input_sample * dry_level + reverb_left * wet_level
|
|
output_right[i] = input_sample * dry_level + reverb_right * wet_level
|
|
|
|
# 合并为立体声数组
|
|
output_data = np.array([output_left, output_right])
|
|
|
|
else:
|
|
# 多声道处理(假设已经是立体声)
|
|
if audio_data.shape[0] >= 2:
|
|
output_left = np.zeros_like(audio_data[0])
|
|
output_right = np.zeros_like(audio_data[1])
|
|
|
|
for i in range(audio_data.shape[1]):
|
|
# 将左右声道混合为单声道输入
|
|
mono_input = (audio_data[0, i] + audio_data[1, i]) * 0.5
|
|
|
|
# 预延迟处理
|
|
delayed_sample = self._apply_predelay(mono_input, predelay)
|
|
|
|
# 混响处理
|
|
reverb_left, reverb_right = self._apply_reverb(
|
|
delayed_sample, room_size, damping, diffusion, density,
|
|
stereo_spread, modulation_rate, modulation_depth)
|
|
|
|
# 应用早期反射和晚期混响权重
|
|
reverb_left *= (early_reflections * 0.3 + late_reverb * 0.7)
|
|
reverb_right *= (early_reflections * 0.3 + late_reverb * 0.7)
|
|
|
|
# 混合干湿信号
|
|
output_left[i] = audio_data[0, i] * dry_level + reverb_left * wet_level
|
|
output_right[i] = audio_data[1, i] * dry_level + reverb_right * wet_level
|
|
|
|
output_data = np.array([output_left, output_right])
|
|
else:
|
|
# 其他多声道情况,返回原始数据
|
|
output_data = audio_data
|
|
|
|
# 确保输出在有效范围内
|
|
processed_data = np.clip(output_data, -1.0, 1.0)
|
|
return processed_data
|
|
|
|
def _apply_predelay(self, sample: float, predelay: float) -> float:
|
|
"""
|
|
应用预延迟
|
|
|
|
Args:
|
|
sample: 输入样本
|
|
predelay: 预延迟时间 (秒)
|
|
|
|
Returns:
|
|
延迟后的样本
|
|
"""
|
|
# 简化的预延迟实现
|
|
# 实际应用中会使用延迟线
|
|
return sample # 简化实现
|
|
|
|
def _apply_reverb(self, sample: float, room_size: float, damping: float,
|
|
diffusion: float, density: float, stereo_spread: float,
|
|
modulation_rate: float, modulation_depth: float) -> tuple:
|
|
"""
|
|
应用混响处理
|
|
|
|
Args:
|
|
sample: 输入样本
|
|
room_size: 房间大小
|
|
damping: 阻尼
|
|
diffusion: 扩散
|
|
density: 密度
|
|
stereo_spread: 立体声扩散
|
|
modulation_rate: 调制速率
|
|
modulation_depth: 调制深度
|
|
|
|
Returns:
|
|
(左声道混响, 右声道混响)
|
|
"""
|
|
# 简化的混响实现
|
|
# 实际应用中会使用梳状滤波器和全通滤波器链
|
|
|
|
# 生成基于参数的混响效果
|
|
reverb_amount = 0.2 + room_size * 0.5
|
|
damp_factor = 0.2 + damping * 0.6
|
|
diffuse_factor = 0.5 + diffusion * 0.3
|
|
|
|
# 左声道混响
|
|
left_reverb = sample * reverb_amount * (1.0 - damp_factor)
|
|
left_reverb *= (0.7 + diffuse_factor * 0.3)
|
|
|
|
# 右声道混响(添加立体声扩散)
|
|
stereo_offset = stereo_spread * 0.3
|
|
right_reverb = sample * (reverb_amount + stereo_offset) * (1.0 - damp_factor * 0.8)
|
|
right_reverb *= (0.7 + diffuse_factor * 0.3)
|
|
|
|
return left_reverb, right_reverb
|
|
|
|
def set_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
|
|
|
|
# 如果是影响滤波器的参数,重新初始化滤波器
|
|
filter_params = ['room_size', 'damping', 'diffusion', 'density']
|
|
if parameter in filter_params:
|
|
self._initialize_filters(self.effects[effect_id])
|
|
|
|
# 如果是插件中的效果,也更新插件中的副本
|
|
if self.plugin and effect_id in self.plugin.effects:
|
|
self.plugin.effects[effect_id]['parameters'][parameter] = value
|
|
if parameter in filter_params:
|
|
self.plugin.effects[effect_id]['comb_filters'] = \
|
|
self.effects[effect_id]['comb_filters'].copy()
|
|
self.plugin.effects[effect_id]['allpass_filters'] = \
|
|
self.effects[effect_id]['allpass_filters'].copy()
|
|
|
|
print(f"✓ 混响效果参数已设置: {effect_id}.{parameter} = {value}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 设置混响效果参数失败: {e}")
|
|
return False
|
|
|
|
def get_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
|
|
self.stats['active_effects'] += 1
|
|
|
|
# 如果是插件中的效果,也更新插件中的副本
|
|
if self.plugin and effect_id in self.plugin.effects:
|
|
self.plugin.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
|
|
self.stats['active_effects'] -= 1
|
|
|
|
# 如果是插件中的效果,也更新插件中的副本
|
|
if self.plugin and effect_id in self.plugin.effects:
|
|
self.plugin.effects[effect_id]['active'] = False
|
|
|
|
print(f"✓ 混响效果已禁用: {effect_id}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 禁用混响效果失败: {e}")
|
|
return False
|
|
|
|
def cleanup(self):
|
|
"""清理所有资源"""
|
|
self.effects.clear()
|
|
self.comb_filters.clear()
|
|
self.allpass_filters.clear()
|
|
self.stats = {
|
|
'total_effects': 0,
|
|
'active_effects': 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_current_time(self) -> float:
|
|
"""
|
|
获取当前时间(秒)
|
|
|
|
Returns:
|
|
当前时间
|
|
"""
|
|
if self.plugin and self.plugin.plugin_manager and self.plugin.plugin_manager.world:
|
|
return self.plugin.plugin_manager.world.globalClock.getFrameTime()
|
|
import time
|
|
return time.time()
|
|
|
|
def update(self, dt: float):
|
|
"""
|
|
更新处理器状态
|
|
|
|
Args:
|
|
dt: 时间增量
|
|
"""
|
|
# 更新调制相位
|
|
for effect_id, effect in self.effects.items():
|
|
modulation_rate = effect['parameters'].get('modulation_rate', 0.1)
|
|
effect['modulation_phase'] += 2.0 * math.pi * modulation_rate * dt
|
|
if effect['modulation_phase'] >= 2.0 * math.pi:
|
|
effect['modulation_phase'] -= 2.0 * math.pi
|
|
|
|
def set_sample_rate(self, sample_rate: int):
|
|
"""
|
|
设置采样率
|
|
|
|
Args:
|
|
sample_rate: 采样率 (Hz)
|
|
"""
|
|
old_sample_rate = self.sample_rate
|
|
self.sample_rate = sample_rate
|
|
print(f"✓ 混响处理器采样率已从 {old_sample_rate} 更新为: {sample_rate} Hz")
|
|
|
|
# 重新初始化所有滤波器以适应新的采样率
|
|
for effect_id, effect in self.effects.items():
|
|
self._initialize_filters(effect)
|
|
self._initialize_buffers(effect)
|
|
|
|
def set_room_size(self, effect_id: str, room_size: float) -> bool:
|
|
"""
|
|
设置房间大小
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
room_size: 房间大小 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'room_size', max(0.0, min(1.0, room_size)))
|
|
|
|
def set_damping(self, effect_id: str, damping: float) -> bool:
|
|
"""
|
|
设置阻尼
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
damping: 阻尼 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'damping', max(0.0, min(1.0, damping)))
|
|
|
|
def set_wet_level(self, effect_id: str, wet_level: float) -> bool:
|
|
"""
|
|
设置湿信号电平
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
wet_level: 湿信号电平 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'wet_level', max(0.0, min(1.0, wet_level)))
|
|
|
|
def set_dry_level(self, effect_id: str, dry_level: float) -> bool:
|
|
"""
|
|
设置干信号电平
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
dry_level: 干信号电平 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'dry_level', max(0.0, min(1.0, dry_level)))
|
|
|
|
def set_width(self, effect_id: str, width: float) -> bool:
|
|
"""
|
|
设置宽度
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
width: 宽度 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'width', max(0.0, min(1.0, width)))
|
|
|
|
def set_freeze_mode(self, effect_id: str, freeze_mode: float) -> bool:
|
|
"""
|
|
设置冻结模式
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
freeze_mode: 冻结模式 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'freeze_mode', max(0.0, min(1.0, freeze_mode)))
|
|
|
|
def set_early_reflections(self, effect_id: str, reflections: float) -> bool:
|
|
"""
|
|
设置早期反射
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
reflections: 早期反射 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'early_reflections', max(0.0, min(1.0, reflections)))
|
|
|
|
def set_late_reverb(self, effect_id: str, reverb: float) -> bool:
|
|
"""
|
|
设置晚期混响
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
reverb: 晚期混响 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'late_reverb', max(0.0, min(1.0, reverb)))
|
|
|
|
def set_diffusion(self, effect_id: str, diffusion: float) -> bool:
|
|
"""
|
|
设置扩散参数
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
diffusion: 扩散值 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'diffusion', max(0.0, min(1.0, diffusion)))
|
|
|
|
def set_density(self, effect_id: str, density: float) -> bool:
|
|
"""
|
|
设置密度参数
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
density: 密度值 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'density', max(0.0, min(1.0, density)))
|
|
|
|
def set_predelay(self, effect_id: str, predelay: float) -> bool:
|
|
"""
|
|
设置预延迟
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
predelay: 预延迟 (秒)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'predelay', max(0.0, min(0.5, predelay)))
|
|
|
|
def set_high_freq_damping(self, effect_id: str, damping: float) -> bool:
|
|
"""
|
|
设置高频阻尼
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
damping: 高频阻尼 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'high_freq_damping', max(0.0, min(1.0, damping)))
|
|
|
|
def set_low_freq_damping(self, effect_id: str, damping: float) -> bool:
|
|
"""
|
|
设置低频阻尼
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
damping: 低频阻尼 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'low_freq_damping', max(0.0, min(1.0, damping)))
|
|
|
|
def set_stereo_spread(self, effect_id: str, spread: float) -> bool:
|
|
"""
|
|
设置立体声扩散
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
spread: 立体声扩散 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'stereo_spread', max(0.0, min(1.0, spread)))
|
|
|
|
def set_reverb_time(self, effect_id: str, time: float) -> bool:
|
|
"""
|
|
设置混响时间
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
time: 混响时间 (秒)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'reverb_time', max(0.1, min(30.0, time)))
|
|
|
|
def set_tail_density(self, effect_id: str, density: float) -> bool:
|
|
"""
|
|
设置尾部密度
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
density: 尾部密度 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'tail_density', max(0.0, min(1.0, density)))
|
|
|
|
def set_modulation_rate(self, effect_id: str, rate: float) -> bool:
|
|
"""
|
|
设置调制速率
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
rate: 调制速率 (Hz)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'modulation_rate', max(0.01, min(10.0, rate)))
|
|
|
|
def set_modulation_depth(self, effect_id: str, depth: float) -> bool:
|
|
"""
|
|
设置调制深度
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
depth: 调制深度 (0.0-1.0)
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
return self.set_parameter(effect_id, 'modulation_depth', max(0.0, min(1.0, depth)))
|
|
|
|
def get_reverb_time(self, effect_id: str) -> float:
|
|
"""
|
|
获取混响时间表
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
|
|
Returns:
|
|
当前混响时间 (秒)
|
|
"""
|
|
if effect_id not in self.effects:
|
|
return 0.0
|
|
|
|
return self.effects[effect_id]['parameters'].get('reverb_time', 2.0)
|
|
|
|
def get_room_size_meter(self, effect_id: str) -> float:
|
|
"""
|
|
获取房间大小表
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
|
|
Returns:
|
|
当前房间大小 (0.0-1.0)
|
|
"""
|
|
if effect_id not in self.effects:
|
|
return 0.0
|
|
|
|
return self.effects[effect_id]['parameters'].get('room_size', 0.5)
|
|
|
|
def create_preset(self, preset_name: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""
|
|
创建混响预设
|
|
|
|
Args:
|
|
preset_name: 预设名称
|
|
parameters: 参数
|
|
|
|
Returns:
|
|
预设参数字典
|
|
"""
|
|
presets = {
|
|
'small_room': {
|
|
'room_size': 0.2,
|
|
'damping': 0.7,
|
|
'wet_level': 0.2,
|
|
'dry_level': 0.8,
|
|
'width': 0.8,
|
|
'early_reflections': 0.6,
|
|
'late_reverb': 0.4,
|
|
'diffusion': 0.6,
|
|
'density': 0.3,
|
|
'reverb_time': 1.0
|
|
},
|
|
'medium_room': {
|
|
'room_size': 0.5,
|
|
'damping': 0.5,
|
|
'wet_level': 0.3,
|
|
'dry_level': 0.7,
|
|
'width': 0.9,
|
|
'early_reflections': 0.7,
|
|
'late_reverb': 0.5,
|
|
'diffusion': 0.7,
|
|
'density': 0.5,
|
|
'reverb_time': 1.5
|
|
},
|
|
'large_room': {
|
|
'room_size': 0.7,
|
|
'damping': 0.4,
|
|
'wet_level': 0.4,
|
|
'dry_level': 0.6,
|
|
'width': 1.0,
|
|
'early_reflections': 0.8,
|
|
'late_reverb': 0.6,
|
|
'diffusion': 0.8,
|
|
'density': 0.7,
|
|
'reverb_time': 2.0
|
|
},
|
|
'large_hall': {
|
|
'room_size': 0.9,
|
|
'damping': 0.3,
|
|
'wet_level': 0.5,
|
|
'dry_level': 0.5,
|
|
'width': 1.0,
|
|
'early_reflections': 0.9,
|
|
'late_reverb': 0.7,
|
|
'diffusion': 0.9,
|
|
'density': 0.8,
|
|
'reverb_time': 3.0
|
|
},
|
|
'cathedral': {
|
|
'room_size': 1.0,
|
|
'damping': 0.2,
|
|
'wet_level': 0.7,
|
|
'dry_level': 0.3,
|
|
'width': 1.0,
|
|
'early_reflections': 1.0,
|
|
'late_reverb': 0.8,
|
|
'diffusion': 1.0,
|
|
'density': 1.0,
|
|
'reverb_time': 5.0
|
|
},
|
|
'bathroom': {
|
|
'room_size': 0.2,
|
|
'damping': 0.1,
|
|
'wet_level': 0.8,
|
|
'dry_level': 0.2,
|
|
'width': 0.9,
|
|
'early_reflections': 0.5,
|
|
'late_reverb': 0.9,
|
|
'diffusion': 0.5,
|
|
'density': 0.2,
|
|
'reverb_time': 0.8
|
|
},
|
|
'tunnel': {
|
|
'room_size': 0.8,
|
|
'damping': 0.6,
|
|
'wet_level': 0.6,
|
|
'dry_level': 0.4,
|
|
'width': 0.7,
|
|
'early_reflections': 0.7,
|
|
'late_reverb': 0.7,
|
|
'diffusion': 0.6,
|
|
'density': 0.6,
|
|
'reverb_time': 2.5
|
|
},
|
|
'arena': {
|
|
'room_size': 0.95,
|
|
'damping': 0.25,
|
|
'wet_level': 0.6,
|
|
'dry_level': 0.4,
|
|
'width': 1.0,
|
|
'early_reflections': 0.95,
|
|
'late_reverb': 0.75,
|
|
'diffusion': 0.95,
|
|
'density': 0.9,
|
|
'reverb_time': 4.0
|
|
}
|
|
}
|
|
|
|
if preset_name in presets:
|
|
preset_params = presets[preset_name].copy()
|
|
preset_params.update(parameters)
|
|
return preset_params
|
|
else:
|
|
return parameters.copy()
|
|
|
|
def get_frequency_response(self, effect_id: str) -> Dict[str, Any]:
|
|
"""
|
|
获取频率响应
|
|
|
|
Args:
|
|
effect_id: 效果ID
|
|
|
|
Returns:
|
|
频率响应数据
|
|
"""
|
|
if effect_id not in self.effects:
|
|
return {}
|
|
|
|
parameters = self.effects[effect_id]['parameters']
|
|
|
|
# 生成简化的频率响应数据
|
|
frequencies = np.logspace(np.log10(20), np.log10(20000), 100)
|
|
response = []
|
|
|
|
room_size = parameters.get('room_size', 0.5)
|
|
damping = parameters.get('damping', 0.5)
|
|
high_freq_damping = parameters.get('high_freq_damping', 0.5)
|
|
low_freq_damping = parameters.get('low_freq_damping', 0.3)
|
|
|
|
for freq in frequencies:
|
|
# 计算基于参数的频率响应
|
|
if freq < 200: # 低频
|
|
gain = 1.0 - low_freq_damping * 0.3
|
|
elif freq > 5000: # 高频
|
|
gain = 1.0 - high_freq_damping * 0.5
|
|
else: # 中频
|
|
gain = 1.0 - damping * 0.2
|
|
|
|
# 房间大小影响
|
|
gain *= (0.8 + room_size * 0.4)
|
|
|
|
response.append(gain)
|
|
|
|
return {
|
|
'frequencies': frequencies.tolist(),
|
|
'response': response
|
|
}
|
|
|