[feature] 增加数据库对滤波器数据读写操作
This commit is contained in:
parent
9145e72263
commit
bdc2bd9ba7
BIN
data/database.db
BIN
data/database.db
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -14,13 +14,14 @@ class DatabaseManager:
|
||||
app_dir = Path(os.path.dirname(os.path.abspath(__file__))).parent
|
||||
data_dir = app_dir / 'data'
|
||||
db_path = str(data_dir / 'database.db')
|
||||
|
||||
print(f"db_path: {db_path}")
|
||||
cls._instance.db_path = db_path
|
||||
cls._instance._init_database()
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
self.init_database()
|
||||
# self.init_database()
|
||||
pass
|
||||
|
||||
def _init_database(self):
|
||||
Path(self.db_path).parent.mkdir(parents=True, exist_ok=True)
|
||||
@ -30,22 +31,27 @@ class DatabaseManager:
|
||||
CREATE TABLE IF NOT EXISTS configs (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
channel_id INTEGER NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(name, channel_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS params (
|
||||
id INTEGER PRIMARY KEY,
|
||||
config_id INTEGER,
|
||||
channel_id INTEGER NOT NULL,
|
||||
delay_data1 FLOAT,
|
||||
ENC_volume_data1 FLOAT,
|
||||
ENT_mx_right_data FLOAT,
|
||||
ENT_mix_left_data FLOAT,
|
||||
FOREIGN KEY (config_id) REFERENCES configs(id)
|
||||
FOREIGN KEY (config_id) REFERENCES configs(id),
|
||||
FOREIGN KEY (channel_id) REFERENCES configs(channel_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS filters (
|
||||
id INTEGER PRIMARY KEY,
|
||||
config_id INTEGER,
|
||||
channel_id INTEGER NOT NULL,
|
||||
filter_type TEXT NOT NULL,
|
||||
freq FLOAT,
|
||||
q FLOAT,
|
||||
@ -53,7 +59,8 @@ class DatabaseManager:
|
||||
slope FLOAT,
|
||||
enabled BOOLEAN DEFAULT TRUE,
|
||||
position INTEGER,
|
||||
FOREIGN KEY (config_id) REFERENCES configs(id)
|
||||
FOREIGN KEY (config_id) REFERENCES configs(id),
|
||||
FOREIGN KEY (channel_id) REFERENCES configs(channel_id)
|
||||
);
|
||||
""")
|
||||
|
||||
@ -62,51 +69,84 @@ class DatabaseManager:
|
||||
|
||||
def get_all_configs(self) -> List[ConfigData]:
|
||||
with self.get_connection() as conn:
|
||||
cursor = conn.execute("SELECT id, name, created_at FROM configs")
|
||||
cursor = conn.execute("SELECT id, name, channel_id, created_at FROM configs")
|
||||
return [ConfigData(*row) for row in cursor.fetchall()]
|
||||
|
||||
def load_config(self, config_id: int) -> Tuple[Optional[ParamData], List[FilterData]]:
|
||||
with self.get_connection() as conn:
|
||||
# 1. 首先加载参数数据
|
||||
cursor = conn.execute(
|
||||
"SELECT * FROM params WHERE config_id = ?",
|
||||
"""SELECT config_id, channel_id, delay_data1, ENC_volume_data1,
|
||||
ENT_mx_right_data, ENT_mix_left_data
|
||||
FROM params WHERE config_id = ?""",
|
||||
(config_id,)
|
||||
)
|
||||
param_row = cursor.fetchone()
|
||||
params = ParamData(*param_row[2:]) if param_row else None
|
||||
if param_row is None:
|
||||
return None, []
|
||||
|
||||
# 2. 创建 ParamData 对象
|
||||
params = ParamData(
|
||||
config_id=param_row[0],
|
||||
channel_id=param_row[1],
|
||||
delay_data1=param_row[2],
|
||||
ENC_volume_data1=param_row[3],
|
||||
ENT_mx_right_data=param_row[4],
|
||||
ENT_mix_left_data=param_row[5]
|
||||
)
|
||||
|
||||
# 3. 加载滤波器数据
|
||||
cursor = conn.execute(
|
||||
"SELECT * FROM filters WHERE config_id = ? ORDER BY position",
|
||||
"""SELECT config_id, channel_id, filter_type, freq, q, gain, slope,
|
||||
enabled, position, id
|
||||
FROM filters WHERE config_id = ? ORDER BY position""",
|
||||
(config_id,)
|
||||
)
|
||||
filters = [FilterData(*row[2:]) for row in cursor.fetchall()]
|
||||
|
||||
filters = []
|
||||
for row in cursor.fetchall():
|
||||
filters.append(FilterData(
|
||||
channel_id=row[1],
|
||||
filter_type=row[2],
|
||||
freq=row[3],
|
||||
q=row[4],
|
||||
gain=row[5],
|
||||
slope=row[6],
|
||||
enabled=bool(row[7]),
|
||||
position=row[8],
|
||||
config_id=row[0],
|
||||
id=row[9]
|
||||
))
|
||||
print(f"load_config filters: {filters}")
|
||||
return params, filters
|
||||
|
||||
def save_config(self, name: str, params: ParamData, filters: List[FilterData]) -> int:
|
||||
def save_config(self, name: str, channel_id: int, params: ParamData, filters: List[FilterData]) -> int:
|
||||
with self.get_connection() as conn:
|
||||
cursor = conn.execute(
|
||||
"INSERT INTO configs (name) VALUES (?)",
|
||||
(name,)
|
||||
"INSERT INTO configs (name, channel_id) VALUES (?, ?)",
|
||||
(name, channel_id)
|
||||
)
|
||||
config_id = cursor.lastrowid
|
||||
|
||||
params.config_id = config_id
|
||||
conn.execute(
|
||||
"""INSERT INTO params
|
||||
(config_id, delay_data1, ENC_volume_data1, ENT_mx_right_data, ENT_mix_left_data)
|
||||
VALUES (?, ?, ?, ?, ?)""",
|
||||
(config_id, params.delay_data1, params.ENC_volume_data1,
|
||||
(config_id, channel_id, delay_data1, ENC_volume_data1, ENT_mx_right_data, ENT_mix_left_data)
|
||||
VALUES (?, ?, ?, ?, ?, ?)""",
|
||||
(params.config_id, params.channel_id, params.delay_data1, params.ENC_volume_data1,
|
||||
params.ENT_mx_right_data, params.ENT_mix_left_data)
|
||||
)
|
||||
|
||||
for filter_data in filters:
|
||||
conn.execute(
|
||||
filter_data.config_id = config_id
|
||||
cursor = conn.execute(
|
||||
"""INSERT INTO filters
|
||||
(config_id, filter_type, freq, q, gain, slope, enabled, position)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(config_id, filter_data.filter_type, filter_data.freq,
|
||||
filter_data.q, filter_data.gain, filter_data.slope,
|
||||
(config_id, channel_id, filter_type, freq, q, gain, slope, enabled, position)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(filter_data.config_id, filter_data.channel_id, filter_data.filter_type,
|
||||
filter_data.freq, filter_data.q, filter_data.gain, filter_data.slope,
|
||||
filter_data.enabled, filter_data.position)
|
||||
)
|
||||
filter_data.id = cursor.lastrowid
|
||||
|
||||
conn.commit()
|
||||
return config_id
|
||||
@ -137,29 +177,37 @@ class DatabaseManager:
|
||||
if not configs:
|
||||
# 创建默认配置
|
||||
default_params = ParamData(
|
||||
channel_id=1,
|
||||
delay_data1=0.0,
|
||||
ENC_volume_data1=0.0,
|
||||
ENT_mx_right_data=0.0,
|
||||
ENT_mix_left_data=0.0
|
||||
ENT_mix_left_data=0.0,
|
||||
config_id=None # 将在 save_config 中设置
|
||||
)
|
||||
|
||||
# 创建一些默认滤波器
|
||||
default_filters = [
|
||||
FilterData(
|
||||
channel_id=1,
|
||||
filter_type="PEQ",
|
||||
freq=1000.0,
|
||||
q=1.0,
|
||||
gain=0.0,
|
||||
slope=12.0
|
||||
slope=12.0,
|
||||
position=0,
|
||||
config_id=None # 将在 save_config 中设置
|
||||
),
|
||||
FilterData(
|
||||
channel_id=1,
|
||||
filter_type="HPF",
|
||||
freq=20.0,
|
||||
q=0.707,
|
||||
gain=0.0,
|
||||
slope=12.0
|
||||
slope=12.0,
|
||||
position=1,
|
||||
config_id=None # 将在 save_config 中设置
|
||||
)
|
||||
]
|
||||
|
||||
# 保存默认配置
|
||||
self.save_config("Default Config", default_params, default_filters)
|
||||
self.save_config("Default Config", 1, default_params, default_filters)
|
||||
|
@ -4,17 +4,21 @@ from datetime import datetime
|
||||
|
||||
@dataclass
|
||||
class FilterData:
|
||||
channel_id: int
|
||||
filter_type: str
|
||||
freq: float
|
||||
q: float
|
||||
gain: float
|
||||
slope: float
|
||||
id: int = None
|
||||
enabled: bool = True
|
||||
position: int = 0
|
||||
config_id: Optional[int] = None
|
||||
id: Optional[int] = None
|
||||
|
||||
@dataclass
|
||||
class ParamData:
|
||||
config_id: int
|
||||
channel_id: int
|
||||
delay_data1: float
|
||||
ENC_volume_data1: float
|
||||
ENT_mx_right_data: float
|
||||
@ -24,4 +28,5 @@ class ParamData:
|
||||
class ConfigData:
|
||||
id: int
|
||||
name: str
|
||||
channel_id: int
|
||||
created_at: str
|
||||
|
Binary file not shown.
Binary file not shown.
@ -8,8 +8,11 @@ class AudioFilterModel:
|
||||
def __init__(self, db_manager: DatabaseManager):
|
||||
self.db_manager = db_manager
|
||||
self.current_config_id: Optional[int] = None
|
||||
self.current_channel_id: int = 1 # 添加当前通道ID
|
||||
self.filters: List[FilterData] = []
|
||||
self.params: ParamData = ParamData(
|
||||
config_id=None,
|
||||
channel_id=self.current_channel_id, # 设置通道ID
|
||||
delay_data1=0.0,
|
||||
ENC_volume_data1=0.0,
|
||||
ENT_mx_right_data=0.0,
|
||||
@ -19,15 +22,22 @@ class AudioFilterModel:
|
||||
|
||||
def load_config(self, config_id: int) -> bool:
|
||||
params, filters = self.db_manager.load_config(config_id)
|
||||
print(f"load_config filters: {filters}")
|
||||
if params is not None:
|
||||
self.params = params
|
||||
self.filters = filters
|
||||
self.current_config_id = config_id
|
||||
self.current_channel_id = params.channel_id # 更新当前通道ID
|
||||
return True
|
||||
return False
|
||||
|
||||
def save_config(self, name: str) -> int:
|
||||
return self.db_manager.save_config(name, self.params, self.filters)
|
||||
# 确保所有对象都有正确的channel_id
|
||||
self.params.channel_id = self.current_channel_id
|
||||
for filter_data in self.filters:
|
||||
print(f"save_config filter_data.channel_id: {filter_data.channel_id}")
|
||||
filter_data.channel_id = self.current_channel_id
|
||||
return self.db_manager.save_config(name, self.current_channel_id, self.params, self.filters)
|
||||
|
||||
def update_filter(self, index: int, **kwargs):
|
||||
if 0 <= index < len(self.filters):
|
||||
@ -162,39 +172,38 @@ class AudioFilterController:
|
||||
return next_number
|
||||
|
||||
def add_filter(self):
|
||||
# 检查是否达到最大滤波器数量
|
||||
if len(self.model.filters) >= 20:
|
||||
print("已达到最大滤波器数量限制(20个)")
|
||||
return
|
||||
|
||||
# 显示滤波器类型选择对话框
|
||||
# 1. 用户界面创建
|
||||
dialog = FilterTypeDialog(self.view)
|
||||
if dialog.exec():
|
||||
filter_type = dialog.get_selected_type()
|
||||
|
||||
# 获取下一个可用的序号
|
||||
next_number = self.get_next_available_number(filter_type)
|
||||
|
||||
# 创建新的滤波器名称
|
||||
new_filter_type = f"{filter_type}_{next_number}"
|
||||
|
||||
# 创建新的滤波器,使用默认参数
|
||||
# 2. 内存中创建 FilterData 对象
|
||||
new_filter = FilterData(
|
||||
filter_type=new_filter_type,
|
||||
freq=1000.0,
|
||||
freq=10.0,
|
||||
q=1.0,
|
||||
gain=0.0,
|
||||
slope=12.0,
|
||||
position=len(self.model.filters)
|
||||
gain=1.0,
|
||||
slope=1.0,
|
||||
position=len(self.model.filters),
|
||||
config_id=self.model.current_config_id,
|
||||
channel_id=self.model.current_channel_id,
|
||||
enabled=True,
|
||||
id=None # 初始创建时 id 为 None
|
||||
)
|
||||
|
||||
# 添加到模型中
|
||||
# 3. 添加到模型的过滤器列表
|
||||
self.model.filters.append(new_filter)
|
||||
|
||||
# 如果有当前配置,保存到数据库
|
||||
if self.model.current_config_id:
|
||||
self.model.save_config(f"Config {self.model.current_config_id}")
|
||||
|
||||
# 4. 保存到数据库
|
||||
if not self.model.current_config_id:
|
||||
# 创建新配置,使用默认名称
|
||||
config_name = f"Channel {self.model.current_channel_id} Config"
|
||||
self.model.save_config(config_name)
|
||||
else:
|
||||
# 更新现有配置
|
||||
self.model.save_config(f"Config {self.model.current_config_id}")
|
||||
# 更新视图
|
||||
self.view.update_table()
|
||||
|
||||
@ -231,7 +240,7 @@ class AudioFilterController:
|
||||
pass
|
||||
|
||||
class AudioFilterWidget(QWidget):
|
||||
def __init__(self):
|
||||
def __init__(self, channel_id: int = 1):
|
||||
super().__init__()
|
||||
self.ui = Ui_Widget()
|
||||
self.ui.setupUi(self)
|
||||
@ -242,38 +251,16 @@ class AudioFilterWidget(QWidget):
|
||||
|
||||
self.db_manager = DatabaseManager()
|
||||
self.model = AudioFilterModel(self.db_manager)
|
||||
self.model.current_channel_id = channel_id # 设置当前通道ID
|
||||
|
||||
# 加载配置
|
||||
# 加载该通道的默认配置
|
||||
configs = self.db_manager.get_all_configs()
|
||||
if configs:
|
||||
# 有配置则加载最后一个
|
||||
last_config_id = configs[-1].id
|
||||
self.model.load_config(last_config_id)
|
||||
else:
|
||||
# 没有配置则创建默认配置
|
||||
default_params = ParamData(
|
||||
delay_data1=0.0,
|
||||
ENC_volume_data1=0.0,
|
||||
ENT_mx_right_data=0.0,
|
||||
ENT_mix_left_data=0.0
|
||||
)
|
||||
|
||||
# 创建默认滤波器
|
||||
self.model.filters = [
|
||||
FilterData(
|
||||
filter_type="PEQ",
|
||||
freq=1000.0,
|
||||
q=1.0,
|
||||
gain=0.0,
|
||||
slope=12.0
|
||||
)
|
||||
]
|
||||
self.model.params = default_params
|
||||
|
||||
# 保存到数据库
|
||||
config_id = self.model.save_config("Default Config")
|
||||
self.model.current_config_id = config_id
|
||||
|
||||
# 查找当前通道的配置
|
||||
channel_config = next((config for config in configs if config.channel_id == channel_id), None)
|
||||
if channel_config:
|
||||
self.model.load_config(channel_config.id)
|
||||
|
||||
self.controller = AudioFilterController(self.model, self)
|
||||
self.update_view()
|
||||
|
||||
@ -287,10 +274,12 @@ class AudioFilterWidget(QWidget):
|
||||
|
||||
def update_table_row(self, row: int):
|
||||
filter_data = self.model.filters[row]
|
||||
print(f"filter_data: {filter_data}")
|
||||
# 创建带复选框的滤波器名称项
|
||||
filter_item = QTableWidgetItem(filter_data.filter_type)
|
||||
filter_item = QTableWidgetItem()
|
||||
filter_item.setFlags(filter_item.flags() | Qt.ItemFlag.ItemIsUserCheckable)
|
||||
filter_item.setCheckState(Qt.CheckState.Checked) # 默认选中
|
||||
filter_item.setCheckState(Qt.CheckState.Checked if filter_data.enabled else Qt.CheckState.Unchecked)
|
||||
filter_item.setText(str(filter_data.filter_type)) # 设置文本,这样文本会和复选框一起显示
|
||||
|
||||
# 更新各列的值
|
||||
self.ui.tableWidget.setItem(row, 0, filter_item)
|
||||
|
@ -9,6 +9,8 @@ class ChannelButton(QWidget):
|
||||
def __init__(self, channel_num):
|
||||
super().__init__()
|
||||
|
||||
self.channel_num = channel_num # 保存通道号
|
||||
|
||||
# Create GroupBox for the channel
|
||||
self.group = QGroupBox(f"CH{channel_num}")
|
||||
layout = QVBoxLayout()
|
||||
@ -98,8 +100,8 @@ class ChannelButton(QWidget):
|
||||
|
||||
def show_filter_window(self):
|
||||
if not self.filter_window:
|
||||
self.filter_window = AudioFilterWidget()
|
||||
# Set window title to include channel number
|
||||
# 创建滤波器窗口时传入对应的通道号
|
||||
self.filter_window = AudioFilterWidget(channel_id=self.channel_num)
|
||||
self.filter_window.setWindowTitle(f"Channel {self.group.title()} Filter Settings")
|
||||
|
||||
# Show the window if it's not visible
|
||||
|
Loading…
Reference in New Issue
Block a user