Skip to content

Commit

Permalink
Allow signals to be concatenated into one longer signal #415
Browse files Browse the repository at this point in the history
  • Loading branch information
3ll3d00d committed Jan 9, 2021
1 parent 9818c05 commit ff00f33
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 3 deletions.
10 changes: 10 additions & 0 deletions src/main/python/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ def __init__(self, app, prefs, parent=None):
# signal model
self.__cached_selected_signal = None
self.__configure_signal_model(parent)
# signal editor
self.actionMerge_Signals.triggered.connect(self.__open_merge_signal_dialog)
self.actionMerge_Signals.setEnabled(False)
# magnitude
self.showLegend.setChecked(bool(self.preferences.get(DISPLAY_SHOW_LEGEND)))
from model.magnitude import MagnitudeModel
Expand Down Expand Up @@ -433,6 +436,9 @@ def on_signal_change(self, names=None):
self.__hide_waveform_chart()
self.linkSignalButton.setEnabled(len(self.__signal_model) > 1)
self.__magnitude_model.redraw()
signal_count = sum(s.signal is not None for s in self.__signal_model.non_bm_signals)
signal_count += sum([len(bm.channels) for bm in self.__signal_model.bass_managed_signals])
self.actionMerge_Signals.setEnabled(signal_count > 1)

def __get_selected_signal(self):
'''
Expand Down Expand Up @@ -1129,6 +1135,10 @@ def export_beq_filter(self):
with open(file_name, 'w+') as f:
f.write(output_xml)

def __open_merge_signal_dialog(self):
from model.signal import MergeSignalDialog
MergeSignalDialog(self.preferences, self.__signal_model, parent=self).exec()


class SaveChartDialog(QDialog, Ui_saveChartDialog):
'''
Expand Down
43 changes: 42 additions & 1 deletion src/main/python/model/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
BASS_MANAGEMENT_LPF_POSITION, BM_LPF_BEFORE, BM_LPF_AFTER, DISPLAY_SMOOTH_PRECALC, X_RESOLUTION, \
SHOWING_AVERAGE, SHOWING_PEAK, SHOWING_MEDIAN, SHOW_UNFILTERED_ONLY
from model.xy import MagnitudeData, interp
from ui.merge_signals import Ui_MergeSignalDialog
from ui.signal import Ui_addSignalDialog

SIGNAL_END = 'end'
Expand Down Expand Up @@ -593,7 +594,7 @@ def table(self):
return self.__table

@property
def bass_managed_signals(self):
def bass_managed_signals(self) -> typing.Iterable[BassManagedSignalData]:
return self.__bass_managed_signals

@property
Expand Down Expand Up @@ -1983,3 +1984,43 @@ def get_visible_signal_name_filter(show_filtered_signals, show_signals):
else:
filter_match = '(-filtered)?'
return re.compile(f".*_({analysis_match}){filter_match}$")


class MergeSignalDialog(QDialog, Ui_MergeSignalDialog):
'''
Alows user to merge multiple signals.
'''

def __init__(self, preferences, signal_model: SignalModel, parent=None):
super(MergeSignalDialog, self).__init__(parent=parent)
self.setupUi(self)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
self.__prefs = preferences
self.__signal_model = signal_model
single_signals = {s.name: s for s in self.__signal_model.non_bm_signals if s.signal is not None}
bm_signals = {c.name: c for bm in [bm.channels for bm in self.__signal_model.bass_managed_signals] for c in bm}
self.__signals: typing.Dict[str, SingleChannelSignalData] = {**single_signals, **bm_signals}
for s in self.__signals.keys():
self.signals.addItem(s)
self.__validate()

def __validate(self):
self.buttonBox.button(QDialogButtonBox.Save).setEnabled(len(self.signals.selectedItems()) > 0)

def calc_duration(self):
duration = 0
if len(self.signals.selectedItems()) > 0:
duration = sum([self.__signals[s.text()].duration_seconds for s in self.signals.selectedItems()])
self.duration.setTime(QtCore.QTime(0, 0, 0).addMSecs(int(duration * 1000)))
self.__validate()

def accept(self):
selected_signals: typing.List[Signal] = [self.__signals[s.text()].signal for s in self.signals.selectedItems()]
logger.debug(f"Merging {','.join([s.name for s in selected_signals])}")
samples = np.concatenate([s.samples for s in selected_signals])
suffix = f"{len([s.name for s in self.__signal_model.non_bm_signals if s.name.startswith('merged')]) + 1}"
output_signal = Signal(f"merged{suffix}", samples, self.__prefs, selected_signals[0].fs)
self.__signal_model.add(SingleChannelSignalData(f"merged{suffix}", signal=output_signal,
filter=CompleteFilter(fs=output_signal.fs)))
super().accept()
7 changes: 6 additions & 1 deletion src/main/python/ui/beq.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,8 @@ def setupUi(self, MainWindow):
self.actionManage_JRiver_MC.setObjectName("actionManage_JRiver_MC")
self.actionShow_Filter_Widget = QtWidgets.QAction(MainWindow)
self.actionShow_Filter_Widget.setObjectName("actionShow_Filter_Widget")
self.actionMerge_Signals = QtWidgets.QAction(MainWindow)
self.actionMerge_Signals.setObjectName("actionMerge_Signals")
self.menuHelp.addAction(self.actionUser_Guide)
self.menuHelp.addAction(self.actionShow_Logs)
self.menuHelp.addSeparator()
Expand Down Expand Up @@ -667,6 +669,7 @@ def setupUi(self, MainWindow):
self.menu_Tools.addAction(self.actionExtract_Audio)
self.menu_Tools.addAction(self.action_Batch_Extract)
self.menu_Tools.addAction(self.action_Remux_Audio)
self.menu_Tools.addAction(self.actionMerge_Signals)
self.menu_Tools.addSeparator()
self.menu_Tools.addAction(self.actionAnalyse_Audio)
self.menu_Tools.addSeparator()
Expand Down Expand Up @@ -825,7 +828,7 @@ def retranslateUi(self, MainWindow):
self.actionClear_Preset_3.setText(_translate("MainWindow", "Clear Preset 3"))
self.actionSave_Chart.setText(_translate("MainWindow", "Save &Chart"))
self.actionSave_Chart.setShortcut(_translate("MainWindow", "Ctrl+Shift+C"))
self.actionExport_Biquad.setText(_translate("MainWindow", "Export &Biquad"))
self.actionExport_Biquad.setText(_translate("MainWindow", "Export Bi&quad"))
self.actionExport_Biquad.setShortcut(_translate("MainWindow", "Ctrl+B"))
self.actionSave_Filter.setText(_translate("MainWindow", "Save &Filter"))
self.actionSave_Filter.setShortcut(_translate("MainWindow", "Ctrl+Alt+S"))
Expand Down Expand Up @@ -898,5 +901,7 @@ def retranslateUi(self, MainWindow):
self.actionManage_JRiver_MC.setShortcut(_translate("MainWindow", "Ctrl+J"))
self.actionShow_Filter_Widget.setText(_translate("MainWindow", "Show Filter Widget"))
self.actionShow_Filter_Widget.setShortcut(_translate("MainWindow", "Ctrl+Alt+="))
self.actionMerge_Signals.setText(_translate("MainWindow", "Merge &Signals"))
self.actionMerge_Signals.setShortcut(_translate("MainWindow", "Ctrl+Alt+S"))
from app import PlotWidgetWithDateAxis
from mpl import MplWidget
11 changes: 10 additions & 1 deletion src/main/python/ui/beq.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,7 @@
<addaction name="actionExtract_Audio"/>
<addaction name="action_Batch_Extract"/>
<addaction name="action_Remux_Audio"/>
<addaction name="actionMerge_Signals"/>
<addaction name="separator"/>
<addaction name="actionAnalyse_Audio"/>
<addaction name="separator"/>
Expand Down Expand Up @@ -1234,7 +1235,7 @@
</action>
<action name="actionExport_Biquad">
<property name="text">
<string>Export &amp;Biquad</string>
<string>Export Bi&amp;quad</string>
</property>
<property name="shortcut">
<string>Ctrl+B</string>
Expand Down Expand Up @@ -1544,6 +1545,14 @@
<string>Ctrl+Alt+=</string>
</property>
</action>
<action name="actionMerge_Signals">
<property name="text">
<string>Merge &amp;Signals</string>
</property>
<property name="shortcut">
<string>Ctrl+Alt+S</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
Expand Down
50 changes: 50 additions & 0 deletions src/main/python/ui/merge_signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'merge_signals.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MergeSignalDialog(object):
def setupUi(self, MergeSignalDialog):
MergeSignalDialog.setObjectName("MergeSignalDialog")
MergeSignalDialog.resize(400, 308)
self.gridLayout = QtWidgets.QGridLayout(MergeSignalDialog)
self.gridLayout.setObjectName("gridLayout")
self.signals = QtWidgets.QListWidget(MergeSignalDialog)
self.signals.setDragEnabled(True)
self.signals.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.signals.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
self.signals.setObjectName("signals")
self.gridLayout.addWidget(self.signals, 0, 1, 1, 1)
self.signalsLabel = QtWidgets.QLabel(MergeSignalDialog)
self.signalsLabel.setObjectName("signalsLabel")
self.gridLayout.addWidget(self.signalsLabel, 0, 0, 1, 1)
self.durationLabel = QtWidgets.QLabel(MergeSignalDialog)
self.durationLabel.setObjectName("durationLabel")
self.gridLayout.addWidget(self.durationLabel, 1, 0, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox(MergeSignalDialog)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Save)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 2, 1, 1, 1)
self.duration = QtWidgets.QTimeEdit(MergeSignalDialog)
self.duration.setReadOnly(True)
self.duration.setObjectName("duration")
self.gridLayout.addWidget(self.duration, 1, 1, 1, 1)

self.retranslateUi(MergeSignalDialog)
self.signals.itemSelectionChanged.connect(MergeSignalDialog.calc_duration)
QtCore.QMetaObject.connectSlotsByName(MergeSignalDialog)

def retranslateUi(self, MergeSignalDialog):
_translate = QtCore.QCoreApplication.translate
MergeSignalDialog.setWindowTitle(_translate("MergeSignalDialog", "Merge Signals"))
self.signalsLabel.setText(_translate("MergeSignalDialog", "Signals"))
self.durationLabel.setText(_translate("MergeSignalDialog", "Duration"))
self.duration.setDisplayFormat(_translate("MergeSignalDialog", "HH:mm:ss.zzz"))
85 changes: 85 additions & 0 deletions src/main/python/ui/merge_signals.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MergeSignalDialog</class>
<widget class="QDialog" name="MergeSignalDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>308</height>
</rect>
</property>
<property name="windowTitle">
<string>Merge Signals</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QListWidget" name="signals">
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="signalsLabel">
<property name="text">
<string>Signals</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="durationLabel">
<property name="text">
<string>Duration</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QTimeEdit" name="duration">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="displayFormat">
<string>HH:mm:ss.zzz</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>signals</sender>
<signal>itemSelectionChanged()</signal>
<receiver>MergeSignalDialog</receiver>
<slot>calc_duration()</slot>
<hints>
<hint type="sourcelabel">
<x>204</x>
<y>106</y>
</hint>
<hint type="destinationlabel">
<x>374</x>
<y>120</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>calc_duration()</slot>
</slots>
</ui>

0 comments on commit ff00f33

Please sign in to comment.