Skip to content

Commit

Permalink
allow user to set fractional octave preference #108 fix resample #173
Browse files Browse the repository at this point in the history
  • Loading branch information
3ll3d00d committed Dec 28, 2018
1 parent 82f0c86 commit 12de318
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 55 deletions.
5 changes: 5 additions & 0 deletions src/main/python/model/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
DISPLAY_GAIN_STEP = 'display/gain_step'
DISPLAY_LINE_STYLE = 'display/line_style'
DISPLAY_SMOOTH_FULL_RANGE = 'display/smooth_full'
DISPLAY_SMOOTH_FRACTION = 'display/fraction'

GRAPH_X_AXIS_SCALE = 'graph/x_axis'
GRAPH_X_MIN = 'graph/x_min'
Expand Down Expand Up @@ -161,6 +162,7 @@
DISPLAY_GAIN_STEP: '0.1',
DISPLAY_LINE_STYLE: True,
DISPLAY_SMOOTH_FULL_RANGE: True,
DISPLAY_SMOOTH_FRACTION: 3,
EXTRACTION_OUTPUT_DIR: os.path.expanduser('~'),
EXTRACTION_MIX_MONO: False,
EXTRACTION_COMPRESS: False,
Expand Down Expand Up @@ -212,6 +214,7 @@
DISPLAY_SHOW_LEGEND: bool,
DISPLAY_LINE_STYLE: bool,
DISPLAY_SMOOTH_FULL_RANGE: bool,
DISPLAY_SMOOTH_FRACTION: int,
EXTRACTION_MIX_MONO: bool,
EXTRACTION_COMPRESS: bool,
EXTRACTION_DECIMATE: bool,
Expand Down Expand Up @@ -408,6 +411,7 @@ def __init__(self, preferences, style_root, main_chart_limits, parent=None):
self.bmlpfFreq.setValue(self.__preferences.get(BASS_MANAGEMENT_LPF_FS))

self.smoothFullRange.setChecked(self.__preferences.get(DISPLAY_SMOOTH_FULL_RANGE))
self.fractionalOctave.setValue(self.__preferences.get(DISPLAY_SMOOTH_FRACTION))

self.__count_beq_files()

Expand Down Expand Up @@ -503,6 +507,7 @@ def accept(self):
self.__preferences.set(BEQ_DOWNLOAD_DIR, self.beqFiltersDir.text())
self.__preferences.set(BASS_MANAGEMENT_LPF_FS, self.bmlpfFreq.value())
self.__preferences.set(DISPLAY_SMOOTH_FULL_RANGE, self.smoothFullRange.isChecked())
self.__preferences.set(DISPLAY_SMOOTH_FRACTION, self.fractionalOctave.value())

QDialog.accept(self)

Expand Down
43 changes: 33 additions & 10 deletions src/main/python/model/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,8 @@ def raw(self):
"""
return self.samples

def spectrum(self, ref=SPECLAB_REFERENCE, resolution_shift=0, window=None, smooth_full=True, **kwargs):
def spectrum(self, ref=SPECLAB_REFERENCE, resolution_shift=0, window=None, smooth_full=True, smooth_fraction=3,
**kwargs):
"""
analyses the source to generate the linear spectrum.
:param ref: the reference value for dB purposes.
Expand All @@ -817,7 +818,7 @@ def spectrum(self, ref=SPECLAB_REFERENCE, resolution_shift=0, window=None, smoot
f = results[0][0]
if self.fs > 24000 and smooth_full:
from acoustics.smooth import fractional_octaves
fob, Pxx_spec = fractional_octaves(f, Pxx_spec)
fob, Pxx_spec = fractional_octaves(f, Pxx_spec, fraction=smooth_fraction)
f = fob.center
# a 3dB adjustment is required to account for the change in nperseg
Pxx_spec = amplitude_to_db(np.sqrt(Pxx_spec), ref * SPECLAB_REFERENCE)
Expand All @@ -829,7 +830,7 @@ def __segment_spectrum(self, segment, resolution_shift=0, window=None, **kwargs)
window=window if window else 'hann', **kwargs)
return f, Pxx_spec

def peakSpectrum(self, ref=SPECLAB_REFERENCE, resolution_shift=0, window=None, smooth_full=True):
def peakSpectrum(self, ref=SPECLAB_REFERENCE, resolution_shift=0, window=None, smooth_full=True, smooth_fraction=3):
"""
analyses the source to generate the max values per bin per segment
:param resolution_shift: allows resolution to go down (if positive) or up (if negative).
Expand All @@ -850,7 +851,7 @@ def peakSpectrum(self, ref=SPECLAB_REFERENCE, resolution_shift=0, window=None, s
f = results[0][0]
if self.fs > 24000 and smooth_full:
from acoustics.smooth import fractional_octaves
fob, Pxy_max = fractional_octaves(f, Pxy_max)
fob, Pxy_max = fractional_octaves(f, Pxy_max, fraction=smooth_fraction)
f = fob.center
# a 3dB adjustment is required to account for the change in nperseg
Pxy_max = amplitude_to_db(Pxy_max, ref=ref * SPECLAB_REFERENCE)
Expand Down Expand Up @@ -976,15 +977,19 @@ def calculate_peak_average(self, preferences):
'''
caches the peak and avg spectrum.
'''
from model.preferences import ANALYSIS_RESOLUTION, ANALYSIS_PEAK_WINDOW, ANALYSIS_AVG_WINDOW, DISPLAY_SMOOTH_FULL_RANGE
from model.preferences import ANALYSIS_RESOLUTION, ANALYSIS_PEAK_WINDOW, ANALYSIS_AVG_WINDOW, \
DISPLAY_SMOOTH_FULL_RANGE, DISPLAY_SMOOTH_FRACTION
resolution_shift = math.log(preferences.get(ANALYSIS_RESOLUTION), 2)
peak_wnd = self.__get_window(preferences, ANALYSIS_PEAK_WINDOW)
avg_wnd = self.__get_window(preferences, ANALYSIS_AVG_WINDOW)
smooth_full = preferences.get(DISPLAY_SMOOTH_FULL_RANGE)
smooth_fraction = preferences.get(DISPLAY_SMOOTH_FRACTION)
logger.debug(
f"Analysing {self.name} at {resolution_shift}x resolution using {peak_wnd}/{avg_wnd} peak/avg windows")
self.__avg = self.spectrum(resolution_shift=resolution_shift, window=avg_wnd, smooth_full=smooth_full)
self.__peak = self.peakSpectrum(resolution_shift=resolution_shift, window=peak_wnd, smooth_full=smooth_full)
self.__avg = self.spectrum(resolution_shift=resolution_shift, window=avg_wnd, smooth_full=smooth_full,
smooth_fraction=smooth_fraction)
self.__peak = self.peakSpectrum(resolution_shift=resolution_shift, window=peak_wnd, smooth_full=smooth_full,
smooth_fraction=smooth_fraction)
self.__cached = [XYData(self.name, 'avg', self.__avg[0], self.__avg[1]),
XYData(self.name, 'peak', self.__peak[0], self.__peak[1])]

Expand Down Expand Up @@ -1142,9 +1147,12 @@ def auto_load(self, name_provider, decimate, offset=0.0):
start = time.time()
try:
for x in range(0, self.info.channels):
self.prepare(channel=x + 1, name=name_provider(x, self.info.channels), channel_count=self.info.channels, decimate=decimate)
self.prepare(channel=x + 1, name=name_provider(x, self.info.channels),
channel_count=self.info.channels,
decimate=decimate)
if self.info.channels > 1:
signals = [self.get_signal(x, name_provider(x-1, self.info.channels), offset=offset) for x in self.__cache.keys()]
signals = [self.get_signal(x, name_provider(x-1, self.info.channels), offset=offset)
for x in self.__cache.keys()]
lpf_fs = self.__preferences.get(BASS_MANAGEMENT_LPF_FS)
lpf_position = self.__preferences.get(BASS_MANAGEMENT_LPF_POSITION)
return BassManagedSignalData(signals, lpf_fs, lpf_position)
Expand Down Expand Up @@ -1229,6 +1237,9 @@ def has_signal(self):
'''
return len(self.__cache) > 0

def toggle_decimate(self):
pass


class DialogWavLoaderBridge:
'''
Expand All @@ -1242,6 +1253,10 @@ def __init__(self, dialog, preferences, allow_multichannel=True):
self.__duration = 0
self.__allow_multichannel = allow_multichannel

def toggle_decimate(self, channel_idx):
self.__auto_loader.clear_cache()
self.prepare_signal(channel_idx)

def select_wav_file(self):
file = select_file(self.__dialog, ['wav', 'flac'])
if file is not None:
Expand Down Expand Up @@ -1297,7 +1312,8 @@ def prepare_signal(self, channel_idx):
'''
Reads the actual file and calculates the relevant peak/avg spectrum.
'''
self.__auto_loader.prepare(name=self.__dialog.wavSignalName.text(), channel=channel_idx,
self.__auto_loader.prepare(name=self.__dialog.wavSignalName.text(),
channel=channel_idx,
decimate=self.__dialog.decimate.isChecked())
self.__dialog.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
self.__dialog.gainOffset.setEnabled(True)
Expand Down Expand Up @@ -1615,6 +1631,13 @@ def __apply_default_filter(self, signal):
for s in signal:
s.filter = self.__signal_model.default_signal.filter.resample(s.fs)

def toggleDecimate(self, state):
''' toggles whether to decimate '''
from app import wait_cursor
with (wait_cursor()):
self.__loaders[self.__loader_idx].toggle_decimate(int(self.wavChannelSelector.currentText()))
self.__magnitudeModel.redraw()


def read_wav_data(input_file, start=None, end=None):
'''
Expand Down
38 changes: 25 additions & 13 deletions src/main/python/ui/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ def setupUi(self, preferencesDialog):
self.xmin.setProperty("value", 2)
self.xmin.setObjectName("xmin")
self.graphPane.addWidget(self.xmin, 2, 1, 1, 1)
self.xminmaxLabel = QtWidgets.QLabel(preferencesDialog)
self.xminmaxLabel.setObjectName("xminmaxLabel")
self.graphPane.addWidget(self.xminmaxLabel, 2, 0, 1, 1)
self.xmax = QtWidgets.QSpinBox(preferencesDialog)
self.xmax.setMinimum(2)
self.xmax.setMaximum(24000)
self.xmax.setProperty("value", 160)
self.xmax.setObjectName("xmax")
self.graphPane.addWidget(self.xmax, 2, 2, 1, 1)
self.freqIsLogScale = QtWidgets.QCheckBox(preferencesDialog)
self.freqIsLogScale.setChecked(True)
self.freqIsLogScale.setObjectName("freqIsLogScale")
Expand All @@ -194,19 +203,22 @@ def setupUi(self, preferencesDialog):
self.graphLabel.setAlignment(QtCore.Qt.AlignCenter)
self.graphLabel.setObjectName("graphLabel")
self.graphPane.addWidget(self.graphLabel, 0, 0, 1, 3)
self.xminmaxLabel = QtWidgets.QLabel(preferencesDialog)
self.xminmaxLabel.setObjectName("xminmaxLabel")
self.graphPane.addWidget(self.xminmaxLabel, 2, 0, 1, 1)
self.xmax = QtWidgets.QSpinBox(preferencesDialog)
self.xmax.setMinimum(2)
self.xmax.setMaximum(24000)
self.xmax.setProperty("value", 160)
self.xmax.setObjectName("xmax")
self.graphPane.addWidget(self.xmax, 2, 2, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.fractionalOctaveLabel = QtWidgets.QLabel(preferencesDialog)
self.fractionalOctaveLabel.setObjectName("fractionalOctaveLabel")
self.horizontalLayout.addWidget(self.fractionalOctaveLabel)
self.fractionalOctave = QtWidgets.QSpinBox(preferencesDialog)
self.fractionalOctave.setMinimum(1)
self.fractionalOctave.setMaximum(24)
self.fractionalOctave.setProperty("value", 3)
self.fractionalOctave.setObjectName("fractionalOctave")
self.horizontalLayout.addWidget(self.fractionalOctave)
self.smoothFullRange = QtWidgets.QCheckBox(preferencesDialog)
self.smoothFullRange.setChecked(True)
self.smoothFullRange.setObjectName("smoothFullRange")
self.graphPane.addWidget(self.smoothFullRange, 1, 1, 1, 1)
self.horizontalLayout.addWidget(self.smoothFullRange)
self.graphPane.addLayout(self.horizontalLayout, 1, 1, 1, 2)
self.panes.addLayout(self.graphPane)
self.filterPane = QtWidgets.QGridLayout()
self.filterPane.setObjectName("filterPane")
Expand Down Expand Up @@ -325,8 +337,7 @@ def setupUi(self, preferencesDialog):
preferencesDialog.setTabOrder(self.extractCompleteAudioFilePicker, self.themePicker)
preferencesDialog.setTabOrder(self.themePicker, self.freqIsLogScale)
preferencesDialog.setTabOrder(self.freqIsLogScale, self.xmin)
preferencesDialog.setTabOrder(self.xmin, self.xmax)
preferencesDialog.setTabOrder(self.xmax, self.ffmpegDirectory)
preferencesDialog.setTabOrder(self.xmin, self.ffmpegDirectory)
preferencesDialog.setTabOrder(self.ffmpegDirectory, self.defaultOutputDirectory)
preferencesDialog.setTabOrder(self.defaultOutputDirectory, self.extractCompleteAudioFile)
preferencesDialog.setTabOrder(self.extractCompleteAudioFile, self.ffprobeDirectory)
Expand Down Expand Up @@ -370,9 +381,10 @@ def retranslateUi(self, preferencesDialog):
self.themePicker.setItemText(0, _translate("preferencesDialog", "default"))
self.styleLabel.setText(_translate("preferencesDialog", "Style"))
self.speclabLineStyle.setText(_translate("preferencesDialog", "Speclab Line Colours?"))
self.xminmaxLabel.setText(_translate("preferencesDialog", "x min/max"))
self.freqIsLogScale.setText(_translate("preferencesDialog", "Frequency Axis Log Scale?"))
self.graphLabel.setText(_translate("preferencesDialog", "Graph"))
self.xminmaxLabel.setText(_translate("preferencesDialog", "x min/max"))
self.fractionalOctaveLabel.setText(_translate("preferencesDialog", "Fractional Octave:"))
self.smoothFullRange.setText(_translate("preferencesDialog", "Smooth Full Range?"))
self.filterQLabel.setText(_translate("preferencesDialog", "Default Q"))
self.filterFreqLabel.setText(_translate("preferencesDialog", "Default Freq"))
Expand Down
85 changes: 54 additions & 31 deletions src/main/python/ui/preferences.ui
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@
</layout>
</item>
<item>
<layout class="QGridLayout" name="graphPane" columnstretch="0,0,0">
<layout class="QGridLayout" name="graphPane" columnstretch="0,0,0,0">
<item row="2" column="1">
<widget class="QSpinBox" name="xmin">
<property name="minimum">
Expand All @@ -381,6 +381,26 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="xminmaxLabel">
<property name="text">
<string>x min/max</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="xmax">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>24000</number>
</property>
<property name="value">
<number>160</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="freqIsLogScale">
<property name="text">
Expand Down Expand Up @@ -413,35 +433,39 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="xminmaxLabel">
<property name="text">
<string>x min/max</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="xmax">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>24000</number>
</property>
<property name="value">
<number>160</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="smoothFullRange">
<property name="text">
<string>Smooth Full Range?</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<item row="1" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="fractionalOctaveLabel">
<property name="text">
<string>Fractional Octave:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="fractionalOctave">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>24</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="smoothFullRange">
<property name="text">
<string>Smooth Full Range?</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
Expand Down Expand Up @@ -664,7 +688,6 @@
<tabstop>themePicker</tabstop>
<tabstop>freqIsLogScale</tabstop>
<tabstop>xmin</tabstop>
<tabstop>xmax</tabstop>
<tabstop>ffmpegDirectory</tabstop>
<tabstop>defaultOutputDirectory</tabstop>
<tabstop>extractCompleteAudioFile</tabstop>
Expand Down
1 change: 1 addition & 0 deletions src/main/python/ui/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def setupUi(self, addSignalDialog):
self.applyTimeRangeButton.clicked.connect(addSignalDialog.limitTimeRange)
self.wavStartTime.timeChanged['QTime'].connect(addSignalDialog.enableLimitTimeRangeButton)
self.wavEndTime.timeChanged['QTime'].connect(addSignalDialog.enableLimitTimeRangeButton)
self.decimate.stateChanged['int'].connect(addSignalDialog.toggleDecimate)
QtCore.QMetaObject.connectSlotsByName(addSignalDialog)
addSignalDialog.setTabOrder(self.signalTypeTabs, self.wavFilePicker)
addSignalDialog.setTabOrder(self.wavFilePicker, self.wavChannelSelector)
Expand Down
19 changes: 18 additions & 1 deletion src/main/python/ui/signal.ui
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@
<slot>enableOk()</slot>
<hints>
<hint type="sourcelabel">
<x>159</x>
<x>161</x>
<y>193</y>
</hint>
<hint type="destinationlabel">
Expand Down Expand Up @@ -615,6 +615,22 @@
</hint>
</hints>
</connection>
<connection>
<sender>decimate</sender>
<signal>stateChanged(int)</signal>
<receiver>addSignalDialog</receiver>
<slot>toggleDecimate()</slot>
<hints>
<hint type="sourcelabel">
<x>118</x>
<y>351</y>
</hint>
<hint type="destinationlabel">
<x>50</x>
<y>588</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>selectFile()</slot>
Expand All @@ -630,5 +646,6 @@
<slot>limitTimeRange()</slot>
<slot>enableLimitTimeRangeButton()</slot>
<slot>offsetGain()</slot>
<slot>toggleDecimate()</slot>
</slots>
</ui>

0 comments on commit 12de318

Please sign in to comment.