[feature] 新增filter model设计,用于补充mvc架构
This commit is contained in:
parent
52d7eddf62
commit
aede544740
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -12,6 +12,7 @@ from Ui_widget import Ui_Widget
|
||||
|
||||
|
||||
from checkbox_header import SCheckBoxHeaderView
|
||||
# from component.widget_filter.checkbox_header import SCheckBoxHeaderView
|
||||
|
||||
from typing import List, Dict, Optional, Any
|
||||
|
||||
@ -676,69 +677,81 @@ class AudioFilterWidget(QWidget):
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from PySide6.QtWidgets import QApplication
|
||||
from audio_filter_model import AudioFilterModel, ChannelParams, FilterParams, FilterType
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# Create and show widget
|
||||
# widget = AudioFilterWidget()
|
||||
# widget.setWindowTitle("Audio Filter Widget")
|
||||
# widget.resize(800, 600)
|
||||
|
||||
# widget.set_channel_id(2)
|
||||
# widget.set_channel("channel_2")
|
||||
|
||||
# test_case_3 = {
|
||||
# 'delay_data2': 100.0, # 最大延迟
|
||||
# 'vol_data2': -80.0, # 最小音量
|
||||
# 'mix_right_data2': 100.0, # 最大混音
|
||||
# 'mix_left_data2': 0.0, # 最小混音
|
||||
# 'filterType2_1': 2, # 低架滤波器
|
||||
# 'fc2_1': 20000.0, # 最大频率
|
||||
# 'q2_1': 10.0, # 最大Q值
|
||||
# 'gain2_1': 12.0, # 最大增益
|
||||
# 'slope2_1': 4.0, # 最大斜率
|
||||
# 'filterType2_2': 3, # 高架滤波器
|
||||
# 'fc2_2': 20.0, # 最小频率
|
||||
# 'q2_2': 0.1, # 最小Q值
|
||||
# 'gain2_2': -12.0, # 最小增益
|
||||
# 'slope2_2': 1.0 # 最小斜率
|
||||
# }
|
||||
|
||||
# widget.set_all_params(test_case_3)
|
||||
|
||||
# # 获取所有参数
|
||||
# params = widget.get_all_params()
|
||||
# print("params:", params)
|
||||
|
||||
# widget.show()
|
||||
|
||||
# 创建模型实例
|
||||
model = AudioFilterModel(channel_id=2, channel_name="channel_2")
|
||||
|
||||
# 设置通道参数
|
||||
model.channel_params = ChannelParams(
|
||||
delay=100.0,
|
||||
volume=-80.0,
|
||||
mix_right=100.0,
|
||||
mix_left=0.0
|
||||
)
|
||||
|
||||
# 添加滤波器
|
||||
model.add_filter(FilterParams(
|
||||
filter_type=FilterType.HIGHPASS,
|
||||
frequency=20000.0,
|
||||
q_value=10.0,
|
||||
gain=12.0,
|
||||
slope=4.0
|
||||
))
|
||||
|
||||
model.add_filter(FilterParams(
|
||||
filter_type=FilterType.ALLPASS,
|
||||
frequency=20.0,
|
||||
q_value=0.1,
|
||||
gain=-12.0,
|
||||
slope=1.0
|
||||
))
|
||||
|
||||
widget_params = model.to_widget_params()
|
||||
print("widget_params:", widget_params)
|
||||
|
||||
widget = AudioFilterWidget()
|
||||
widget.setWindowTitle("Audio Filter Widget")
|
||||
widget.resize(800, 600)
|
||||
|
||||
# 测试数据
|
||||
# widget.set_filters_count(2)
|
||||
# widget.set_filter_data(0, {
|
||||
# 'filter_name': 'peak',
|
||||
# 'filter_type': 'PEAK',
|
||||
# 'freq': 100,
|
||||
# 'q': 1.0,
|
||||
# 'gain': 0.0,
|
||||
# 'slope': 1.0,
|
||||
# 'enabled': True
|
||||
# })
|
||||
# widget.set_filter_data(1, {
|
||||
# 'filter_name': 'lowpass',
|
||||
# 'filter_type': 'LOWPASS',
|
||||
# 'freq': 1000,
|
||||
# 'q': 0.7,
|
||||
# 'gain': 0.0,
|
||||
# 'slope': 2.0,
|
||||
# 'enabled': True
|
||||
# })
|
||||
|
||||
# widget.set_param_data({
|
||||
# 'delay_data1': 30,
|
||||
# 'ENT_volume_data1': 2,
|
||||
# 'ENT_mx_right_data': 3,
|
||||
# 'ENT_mix_left_data': 4
|
||||
# })
|
||||
widget.set_channel_id(model.channel_id)
|
||||
widget.set_channel_name(model.channel_name)
|
||||
widget.set_all_params(widget_params)
|
||||
|
||||
widget.set_channel_id(2)
|
||||
widget.set_channel("channel_2")
|
||||
|
||||
test_case_3 = {
|
||||
'delay_data2': 100.0, # 最大延迟
|
||||
'vol_data2': -80.0, # 最小音量
|
||||
'mix_right_data2': 100.0, # 最大混音
|
||||
'mix_left_data2': 0.0, # 最小混音
|
||||
'filterType2_1': 2, # 低架滤波器
|
||||
'fc2_1': 20000.0, # 最大频率
|
||||
'q2_1': 10.0, # 最大Q值
|
||||
'gain2_1': 12.0, # 最大增益
|
||||
'slope2_1': 4.0, # 最大斜率
|
||||
'filterType2_2': 3, # 高架滤波器
|
||||
'fc2_2': 20.0, # 最小频率
|
||||
'q2_2': 0.1, # 最小Q值
|
||||
'gain2_2': -12.0, # 最小增益
|
||||
'slope2_2': 1.0 # 最小斜率
|
||||
}
|
||||
|
||||
widget.set_all_params(test_case_3)
|
||||
|
||||
# widget.set_all_params(test_params)
|
||||
|
||||
# 获取所有参数
|
||||
params = widget.get_all_params()
|
||||
print("aaaa params:", params)
|
||||
|
||||
print("params:", params)
|
||||
widget.show()
|
||||
|
||||
sys.exit(app.exec())
|
134
component/widget_filter/audio_filter_model.py
Normal file
134
component/widget_filter/audio_filter_model.py
Normal file
@ -0,0 +1,134 @@
|
||||
from dataclasses import dataclass, asdict
|
||||
from typing import List, Dict, Any, Optional
|
||||
from enum import Enum
|
||||
|
||||
class FilterType(Enum):
|
||||
PEAK = 0
|
||||
LOWPASS = 1
|
||||
HIGHPASS = 2
|
||||
ALLPASS = 3
|
||||
|
||||
@dataclass
|
||||
class FilterParams:
|
||||
filter_type: FilterType
|
||||
frequency: float
|
||||
q_value: float
|
||||
gain: float
|
||||
slope: float
|
||||
enabled: bool = True
|
||||
|
||||
def to_dict(self, channel_id: int, filter_num: int) -> Dict[str, Any]:
|
||||
"""转换为与组件兼容的字典格式"""
|
||||
return {
|
||||
f'filterType{channel_id}_{filter_num}': self.filter_type.value,
|
||||
f'fc{channel_id}_{filter_num}': self.frequency,
|
||||
f'q{channel_id}_{filter_num}': self.q_value,
|
||||
f'gain{channel_id}_{filter_num}': self.gain,
|
||||
f'slope{channel_id}_{filter_num}': self.slope
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any], channel_id: int, filter_num: int) -> 'FilterParams':
|
||||
"""从字典创建FilterParams实例"""
|
||||
prefix = f'{channel_id}_{filter_num}'
|
||||
return cls(
|
||||
filter_type=FilterType(data.get(f'filterType{prefix}', 0)),
|
||||
frequency=data.get(f'fc{prefix}', 0.0),
|
||||
q_value=data.get(f'q{prefix}', 0.0),
|
||||
gain=data.get(f'gain{prefix}', 0.0),
|
||||
slope=data.get(f'slope{prefix}', 0.0)
|
||||
)
|
||||
|
||||
@dataclass
|
||||
class ChannelParams:
|
||||
delay: float
|
||||
volume: float
|
||||
mix_right: float
|
||||
mix_left: float
|
||||
|
||||
def to_dict(self, channel_id: int) -> Dict[str, Any]:
|
||||
"""转换为与组件兼容的字典格式"""
|
||||
return {
|
||||
f'delay_data{channel_id}': self.delay,
|
||||
f'vol_data{channel_id}': self.volume,
|
||||
f'mix_right_data{channel_id}': self.mix_right,
|
||||
f'mix_left_data{channel_id}': self.mix_left
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any], channel_id: int) -> 'ChannelParams':
|
||||
"""从字典创建ChannelParams实例"""
|
||||
return cls(
|
||||
delay=data.get(f'delay_data{channel_id}', 0.0),
|
||||
volume=data.get(f'vol_data{channel_id}', 0.0),
|
||||
mix_right=data.get(f'mix_right_data{channel_id}', 0.0),
|
||||
mix_left=data.get(f'mix_left_data{channel_id}', 0.0)
|
||||
)
|
||||
|
||||
class AudioFilterModel:
|
||||
def __init__(self, channel_id: int, channel_name: str):
|
||||
self.channel_id = channel_id
|
||||
self.channel_name = channel_name
|
||||
self.channel_params = ChannelParams(0.0, 0.0, 0.0, 0.0)
|
||||
self.filters: List[FilterParams] = []
|
||||
|
||||
def add_filter(self, filter_params: FilterParams):
|
||||
"""添加新的滤波器"""
|
||||
self.filters.append(filter_params)
|
||||
|
||||
def remove_filter(self, index: int):
|
||||
"""移除指定索引的滤波器"""
|
||||
if 0 <= index < len(self.filters):
|
||||
self.filters.pop(index)
|
||||
|
||||
def update_filter(self, index: int, filter_params: FilterParams):
|
||||
"""更新指定索引的滤波器参数"""
|
||||
if 0 <= index < len(self.filters):
|
||||
self.filters[index] = filter_params
|
||||
|
||||
def to_widget_params(self) -> Dict[str, Any]:
|
||||
"""转换为AudioFilterWidget兼容的参数格式"""
|
||||
params = self.channel_params.to_dict(self.channel_id)
|
||||
|
||||
for i, filter_param in enumerate(self.filters, 1):
|
||||
params.update(filter_param.to_dict(self.channel_id, i))
|
||||
|
||||
return params
|
||||
|
||||
def from_widget_params(self, params: Dict[str, Any]):
|
||||
"""从AudioFilterWidget参数更新模型"""
|
||||
self.channel_params = ChannelParams.from_dict(params, self.channel_id)
|
||||
|
||||
self.filters.clear()
|
||||
filter_count = 1
|
||||
while True:
|
||||
if f'filterType{self.channel_id}_{filter_count}' in params:
|
||||
filter_param = FilterParams.from_dict(params, self.channel_id, filter_count)
|
||||
self.filters.append(filter_param)
|
||||
filter_count += 1
|
||||
else:
|
||||
break
|
||||
|
||||
def save_to_file(self, filepath: str):
|
||||
"""保存配置到文件"""
|
||||
import json
|
||||
data = {
|
||||
'channel_id': self.channel_id,
|
||||
'channel_name': self.channel_name,
|
||||
'channel_params': asdict(self.channel_params),
|
||||
'filters': [asdict(f) for f in self.filters]
|
||||
}
|
||||
with open(filepath, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
@classmethod
|
||||
def load_from_file(cls, filepath: str) -> 'AudioFilterModel':
|
||||
"""从文件加载配置"""
|
||||
import json
|
||||
with open(filepath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
model = cls(data['channel_id'], data['channel_name'])
|
||||
model.channel_params = ChannelParams(**data['channel_params'])
|
||||
model.filters = [FilterParams(**f) for f in data['filters']]
|
||||
return model
|
Loading…
Reference in New Issue
Block a user