Qt: Move time stretch settings into audio widget

Fewer popup windows.
This commit is contained in:
Stenzek
2026-01-05 16:29:09 +10:00
parent f2adc39709
commit 6c09ba4944
9 changed files with 331 additions and 341 deletions

View File

@@ -20,7 +20,6 @@ set(SRCS
audiosettingswidget.cpp
audiosettingswidget.h
audiosettingswidget.ui
audiostretchsettingsdialog.ui
autoupdaterdialog.cpp
autoupdaterdialog.h
autoupdaterdialog.ui

View File

@@ -6,7 +6,6 @@
#include "qtutils.h"
#include "settingswindow.h"
#include "settingwidgetbinder.h"
#include "ui_audiostretchsettingsdialog.h"
#include "core/core.h"
#include "core/spu.h"
@@ -33,21 +32,35 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* dialog, QWidget* parent
AudioStreamParameters::DEFAULT_STRETCH_MODE, AudioStretchMode::Count);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bufferMS, "Audio", "BufferMS",
AudioStreamParameters::DEFAULT_BUFFER_MS);
QtUtils::BindLabelToSlider(m_ui.bufferMS, m_ui.bufferMSLabel, 1.0f, tr("%1 ms"));
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.outputLatencyMS, "Audio", "OutputLatencyMS",
AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MS);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.outputLatencyMinimal, "Audio", "OutputLatencyMinimal",
AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MINIMAL);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.sequenceLength, "Audio", "StretchSequenceLengthMS",
AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH, 0);
QtUtils::BindLabelToSlider(m_ui.sequenceLength, m_ui.sequenceLengthLabel, 1.0f, tr("%1 ms"));
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.seekWindowSize, "Audio", "StretchSeekWindowMS",
AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW, 0);
QtUtils::BindLabelToSlider(m_ui.seekWindowSize, m_ui.seekWindowSizeLabel, 1.0f, tr("%1 ms"));
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.overlap, "Audio", "StretchOverlapMS",
AudioStreamParameters::DEFAULT_STRETCH_OVERLAP, 0);
QtUtils::BindLabelToSlider(m_ui.overlap, m_ui.overlapLabel, 1.0f, tr("%1 ms"));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useQuickSeek, "Audio", "StretchUseQuickSeek",
AudioStreamParameters::DEFAULT_STRETCH_USE_QUICKSEEK);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useAAFilter, "Audio", "StretchUseAAFilter",
AudioStreamParameters::DEFAULT_STRETCH_USE_AA_FILTER);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.muteCDAudio, "CDROM", "MuteCDAudio", false);
connect(m_ui.audioBackend, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::updateDriverNames);
connect(m_ui.stretchMode, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::onStretchModeChanged);
connect(m_ui.stretchSettings, &QPushButton::clicked, this, &AudioSettingsWidget::onStretchSettingsClicked);
onStretchModeChanged();
updateDriverNames();
connect(m_ui.bufferMS, &QSlider::valueChanged, this, &AudioSettingsWidget::updateLatencyLabel);
connect(m_ui.outputLatencyMS, &QSlider::valueChanged, this, &AudioSettingsWidget::updateLatencyLabel);
connect(m_ui.outputLatencyMinimal, &QCheckBox::checkStateChanged, this,
&AudioSettingsWidget::onMinimalOutputLatencyChecked);
connect(m_ui.bufferMS, &QSlider::valueChanged, this, &AudioSettingsWidget::updateMinimumLatencyLabel);
connect(m_ui.sequenceLength, &QSlider::valueChanged, this, &AudioSettingsWidget::updateMinimumLatencyLabel);
updateLatencyLabel();
// for per-game, just use the normal path, since it needs to re-read/apply
@@ -71,6 +84,11 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* dialog, QWidget* parent
}
connect(m_ui.resetVolume, &QPushButton::clicked, this, [this]() { resetVolume(false); });
connect(m_ui.resetFastForwardVolume, &QPushButton::clicked, this, [this]() { resetVolume(true); });
connect(m_ui.resetBufferSize, &QPushButton::clicked, this, &AudioSettingsWidget::onResetBufferSizeClicked);
connect(m_ui.resetSequenceLength, &QPushButton::clicked, this,
&AudioSettingsWidget::onResetStretchSequenceLengthClicked);
connect(m_ui.resetSeekWindowSize, &QPushButton::clicked, this, &AudioSettingsWidget::onResetStretchSeekWindowClicked);
connect(m_ui.resetOverlap, &QPushButton::clicked, this, &AudioSettingsWidget::onResetStretchOverlapClicked);
dialog->registerWidgetHelp(
m_ui.audioBackend, tr("Audio Backend"), QStringLiteral("Cubeb"),
@@ -102,15 +120,41 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* dialog, QWidget* parent
m_ui.stretchMode, tr("Stretch Mode"), tr("Time Stretching"),
tr("When running outside of 100% speed, adjusts the tempo on audio instead of dropping frames. Produces "
"much nicer fast forward/slowdown audio at a small cost to performance."));
dialog->registerWidgetHelp(m_ui.stretchSettings, tr("Stretch Settings"), tr("N/A"),
tr("These settings fine-tune the behavior of the SoundTouch audio time stretcher when "
"running outside of 100% speed."));
dialog->registerWidgetHelp(m_ui.resetVolume, tr("Reset Volume"), tr("N/A"),
m_dialog->isPerGameSettings() ? tr("Resets volume back to the global/inherited setting.") :
tr("Resets volume back to the default, i.e. full."));
dialog->registerWidgetHelp(m_ui.resetFastForwardVolume, tr("Reset Fast Forward Volume"), tr("N/A"),
m_dialog->isPerGameSettings() ? tr("Resets volume back to the global/inherited setting.") :
tr("Resets volume back to the default, i.e. full."));
dialog->registerWidgetHelp(m_ui.sequenceLength, tr("Stretch Sequence Length"),
tr("%1 ms").arg(AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH),
tr("Determines how long individual sequences are when the time-stretch algorithm chops "
"the audio. Longer sequences can improve quality but increase latency."));
dialog->registerWidgetHelp(
m_ui.seekWindowSize, tr("Stretch Seek Window"), tr("%1 ms").arg(AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW),
tr("Controls how wide a window the algorithm searches for the best overlap position when joining "
"consecutive sequences. Larger windows may yield better joins at the cost of increased CPU work."));
dialog->registerWidgetHelp(m_ui.overlap, tr("Stretch Overlap Length"),
tr("%1 ms").arg(AudioStreamParameters::DEFAULT_STRETCH_OVERLAP),
tr("Specifies how long two consecutive sequences are overlapped when mixed back together. "
"Greater overlap can make transitions smoother but increases latency."));
dialog->registerWidgetHelp(m_ui.useQuickSeek, tr("Enable Quick Seek"),
AudioStreamParameters::DEFAULT_STRETCH_USE_QUICKSEEK ? tr("Checked") : tr("Unchecked"),
tr("Enables the quick seeking algorithm in the time-stretch routine. Reduces CPU usage at "
"a minor cost to audio quality."));
dialog->registerWidgetHelp(m_ui.useAAFilter, tr("Enable Anti-Alias Filter"),
AudioStreamParameters::DEFAULT_STRETCH_USE_AA_FILTER ? tr("Checked") : tr("Unchecked"),
tr("Enables an anti-aliasing filter used by the pitch transposer. Disabling it may reduce "
"quality when pitch shifting but can slightly reduce CPU usage."));
dialog->registerWidgetHelp(m_ui.resetSequenceLength, tr("Reset Sequence Length"), tr("N/A"),
m_dialog->isPerGameSettings() ? tr("Resets value back to the global/inherited setting.") :
tr("Resets value back to the default."));
dialog->registerWidgetHelp(m_ui.resetSeekWindowSize, tr("Reset Seek Window"), tr("N/A"),
m_dialog->isPerGameSettings() ? tr("Resets value back to the global/inherited setting.") :
tr("Resets value back to the default."));
dialog->registerWidgetHelp(m_ui.resetOverlap, tr("Reset Overlap"), tr("N/A"),
m_dialog->isPerGameSettings() ? tr("Resets value back to the global/inherited setting.") :
tr("Resets value back to the default."));
}
AudioSettingsWidget::~AudioSettingsWidget() = default;
@@ -124,7 +168,7 @@ void AudioSettingsWidget::onStretchModeChanged()
CoreAudioStream::GetStretchModeName(AudioStreamParameters::DEFAULT_STRETCH_MODE))
.c_str())
.value_or(AudioStreamParameters::DEFAULT_STRETCH_MODE);
m_ui.stretchSettings->setEnabled(stretch_mode != AudioStretchMode::Off);
m_ui.timeStretchGroup->setEnabled(stretch_mode == AudioStretchMode::TimeStretch);
updateMinimumLatencyLabel();
}
@@ -147,11 +191,22 @@ void AudioSettingsWidget::updateDriverNames()
if (names.empty())
{
m_ui.driver->addItem(tr("Default"));
m_ui.driver->setEnabled(false);
m_ui.driver->setVisible(false);
// I hate this so much but it's the only way to stop Qt leaving a gap on the edge.
// Of course could use a nested layout, but that breaks on MacOS.
m_ui.configurationLayout->removeWidget(m_ui.driver);
m_ui.configurationLayout->removeWidget(m_ui.audioBackend);
m_ui.configurationLayout->addWidget(m_ui.audioBackend, 0, 1, 1, 2);
}
else
{
m_ui.driver->setEnabled(true);
m_ui.driver->setVisible(true);
m_ui.configurationLayout->removeWidget(m_ui.audioBackend);
m_ui.configurationLayout->removeWidget(m_ui.driver);
m_ui.configurationLayout->addWidget(m_ui.audioBackend, 0, 1, 1, 1);
m_ui.configurationLayout->addWidget(m_ui.driver, 0, 2, 1, 1);
for (const auto& [name, display_name] : names)
m_ui.driver->addItem(QString::fromStdString(display_name), QString::fromStdString(name));
@@ -220,15 +275,12 @@ void AudioSettingsWidget::updateLatencyLabel()
{
const bool minimal_output_latency = m_dialog->getEffectiveBoolValue(
"Audio", "OutputLatencyMinimal", AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MINIMAL);
const int config_buffer_ms =
m_dialog->getEffectiveIntValue("Audio", "BufferMS", AudioStreamParameters::DEFAULT_BUFFER_MS);
const int config_output_latency_ms =
minimal_output_latency ?
0 :
m_dialog->getEffectiveIntValue("Audio", "OutputLatencyMS", AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MS);
m_ui.outputLatencyLabel->setText(minimal_output_latency ? tr("N/A") : tr("%1 ms").arg(config_output_latency_ms));
m_ui.bufferMSLabel->setText(tr("%1 ms").arg(config_buffer_ms));
updateMinimumLatencyLabel();
}
@@ -338,62 +390,6 @@ void AudioSettingsWidget::onOutputMutedChanged(int new_state)
g_core_thread->setAudioOutputMuted(muted);
}
void AudioSettingsWidget::onStretchSettingsClicked()
{
QDialog* const dlg = new QDialog(QtUtils::GetRootWidget(this));
dlg->setAttribute(Qt::WA_DeleteOnClose);
Ui::AudioStretchSettingsDialog dlgui;
dlgui.setupUi(dlg);
dlgui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("volume-up-line")).pixmap(32));
dlgui.buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
SettingsInterface* sif = m_dialog->getSettingsInterface();
SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.sequenceLength, "Audio", "StretchSequenceLengthMS",
AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH, 0);
QtUtils::BindLabelToSlider(dlgui.sequenceLength, dlgui.sequenceLengthLabel);
SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.seekWindowSize, "Audio", "StretchSeekWindowMS",
AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW, 0);
QtUtils::BindLabelToSlider(dlgui.seekWindowSize, dlgui.seekWindowSizeLabel);
SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.overlap, "Audio", "StretchOverlapMS",
AudioStreamParameters::DEFAULT_STRETCH_OVERLAP, 0);
QtUtils::BindLabelToSlider(dlgui.overlap, dlgui.overlapLabel);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, dlgui.useQuickSeek, "Audio", "StretchUseQuickSeek",
AudioStreamParameters::DEFAULT_STRETCH_USE_QUICKSEEK);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, dlgui.useAAFilter, "Audio", "StretchUseAAFilter",
AudioStreamParameters::DEFAULT_STRETCH_USE_AA_FILTER);
connect(dlgui.buttonBox, &QDialogButtonBox::rejected, dlg, &QDialog::accept);
connect(dlgui.buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, [this, dlg]() {
m_dialog->setIntSettingValue("Audio", "StretchSequenceLengthMS",
m_dialog->isPerGameSettings() ?
std::nullopt :
std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH));
m_dialog->setIntSettingValue("Audio", "StretchSeekWindowMS",
m_dialog->isPerGameSettings() ?
std::nullopt :
std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW));
m_dialog->setIntSettingValue("Audio", "StretchOverlapMS",
m_dialog->isPerGameSettings() ?
std::nullopt :
std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_OVERLAP));
m_dialog->setBoolSettingValue("Audio", "StretchUseQuickSeek",
m_dialog->isPerGameSettings() ?
std::nullopt :
std::optional<bool>(AudioStreamParameters::DEFAULT_STRETCH_USE_QUICKSEEK));
m_dialog->setBoolSettingValue("Audio", "StretchUseAAFilter",
m_dialog->isPerGameSettings() ?
std::nullopt :
std::optional<bool>(AudioStreamParameters::DEFAULT_STRETCH_USE_AA_FILTER));
dlg->reject();
QMetaObject::invokeMethod(this, &AudioSettingsWidget::onStretchSettingsClicked, Qt::QueuedConnection);
});
connect(dlg, &QDialog::accepted, this, &AudioSettingsWidget::updateMinimumLatencyLabel);
dlg->open();
}
void AudioSettingsWidget::resetVolume(bool fast_forward)
{
const char* key = fast_forward ? "FastForwardVolume" : "OutputVolume";
@@ -419,3 +415,58 @@ void AudioSettingsWidget::resetVolume(bool fast_forward)
slider->setValue(100);
}
}
void AudioSettingsWidget::onResetBufferSizeClicked()
{
m_dialog->setIntSettingValue(
"Audio", "BufferMS",
m_dialog->isPerGameSettings() ? std::nullopt : std::optional<int>(AudioStreamParameters::DEFAULT_BUFFER_MS));
SettingWidgetBinder::DisconnectWidget(m_ui.bufferMS);
SettingWidgetBinder::BindWidgetToIntSetting(m_dialog->getSettingsInterface(), m_ui.bufferMS, "Audio", "BufferMS",
AudioStreamParameters::DEFAULT_BUFFER_MS);
QtUtils::BindLabelToSlider(m_ui.bufferMS, m_ui.bufferMSLabel, 1.0f, tr("%1 ms"));
connect(m_ui.bufferMS, &QSlider::valueChanged, this, &AudioSettingsWidget::updateMinimumLatencyLabel);
updateMinimumLatencyLabel();
}
void AudioSettingsWidget::onResetStretchSequenceLengthClicked()
{
m_dialog->setIntSettingValue("Audio", "StretchSequenceLengthMS",
m_dialog->isPerGameSettings() ?
std::nullopt :
std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH));
SettingWidgetBinder::DisconnectWidget(m_ui.sequenceLength);
SettingWidgetBinder::BindWidgetToIntSetting(m_dialog->getSettingsInterface(), m_ui.sequenceLength, "Audio",
"StretchSequenceLengthMS",
AudioStreamParameters::DEFAULT_STRETCH_SEQUENCE_LENGTH, 0);
QtUtils::BindLabelToSlider(m_ui.sequenceLength, m_ui.sequenceLengthLabel, 1.0f, tr("%1 ms"));
connect(m_ui.sequenceLength, &QSlider::valueChanged, this, &AudioSettingsWidget::updateMinimumLatencyLabel);
updateMinimumLatencyLabel();
}
void AudioSettingsWidget::onResetStretchSeekWindowClicked()
{
m_dialog->setIntSettingValue("Audio", "StretchSeekWindowMS",
m_dialog->isPerGameSettings() ?
std::nullopt :
std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW));
SettingWidgetBinder::DisconnectWidget(m_ui.seekWindowSize);
SettingWidgetBinder::BindWidgetToIntSetting(m_dialog->getSettingsInterface(), m_ui.seekWindowSize, "Audio",
"StretchSeekWindowMS", AudioStreamParameters::DEFAULT_STRETCH_SEEKWINDOW,
0);
QtUtils::BindLabelToSlider(m_ui.seekWindowSize, m_ui.seekWindowSizeLabel, 1.0f, tr("%1 ms"));
}
void AudioSettingsWidget::onResetStretchOverlapClicked()
{
m_dialog->setIntSettingValue(
"Audio", "StretchOverlapMS",
m_dialog->isPerGameSettings() ? std::nullopt : std::optional<int>(AudioStreamParameters::DEFAULT_STRETCH_OVERLAP));
SettingWidgetBinder::DisconnectWidget(m_ui.overlap);
SettingWidgetBinder::BindWidgetToIntSetting(m_dialog->getSettingsInterface(), m_ui.overlap, "Audio",
"StretchOverlapMS", AudioStreamParameters::DEFAULT_STRETCH_OVERLAP, 0);
QtUtils::BindLabelToSlider(m_ui.overlap, m_ui.overlapLabel, 1.0f, tr("%1 ms"));
}

View File

@@ -36,8 +36,10 @@ private:
void onOutputVolumeChanged(int new_value);
void onFastForwardVolumeChanged(int new_value);
void onOutputMutedChanged(int new_state);
void onStretchSettingsClicked();
void onResetBufferSizeClicked();
void onResetStretchSequenceLengthClicked();
void onResetStretchSeekWindowClicked();
void onResetStretchOverlapClicked();
Ui::AudioSettingsWidget m_ui;
SettingsWindow* m_dialog;

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>523</width>
<height>480</height>
<height>533</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -28,7 +28,7 @@
<property name="title">
<string>Controls</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<layout class="QGridLayout" name="gridLayout_3" columnminimumwidth="120,0,0,0">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
@@ -159,7 +159,7 @@
<property name="title">
<string>Configuration</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<layout class="QGridLayout" name="configurationLayout" columnstretch="0,1,1" columnminimumwidth="120,0,0">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
@@ -167,7 +167,7 @@
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<item row="0" column="1">
<widget class="QComboBox" name="audioBackend">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -177,14 +177,7 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Driver:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<item row="0" column="2">
<widget class="QComboBox" name="driver">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -194,14 +187,14 @@
</property>
</widget>
</item>
<item row="2" column="0">
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Output Device:</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="outputDevice">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -211,14 +204,14 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Stretch Mode:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1" colspan="2">
<widget class="QComboBox" name="stretchMode">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -228,24 +221,14 @@
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="stretchSettings">
<property name="toolTip">
<string>Stretch Settings</string>
</property>
<property name="icon">
<iconset theme="settings-3-line"/>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Buffer Size:</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<item row="3" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSlider" name="bufferMS">
@@ -276,16 +259,26 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="resetBufferSize">
<property name="toolTip">
<string>Reset Buffer Size</string>
</property>
<property name="icon">
<iconset theme="restart-line"/>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Output Latency:</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<item row="4" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QSlider" name="outputLatencyMS">
@@ -322,7 +315,7 @@
</item>
</layout>
</item>
<item row="6" column="0" colspan="3">
<item row="5" column="0" colspan="3">
<widget class="QLabel" name="bufferingLabel">
<property name="text">
<string>Maximum latency: 0 frames (0.00ms)</string>
@@ -335,6 +328,171 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="timeStretchGroup">
<property name="title">
<string>Time Stretching</string>
</property>
<layout class="QGridLayout" name="gridLayout_4" columnminimumwidth="120,0,0,0">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Sequence Length:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="sequenceLength">
<property name="minimum">
<number>20</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>30</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TickPosition::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="sequenceLengthLabel">
<property name="text">
<string>0 ms</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="resetSequenceLength">
<property name="toolTip">
<string>Reset Sequence Length</string>
</property>
<property name="icon">
<iconset theme="restart-line"/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Seek Window:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="seekWindowSize">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>30</number>
</property>
<property name="value">
<number>20</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TickPosition::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>2</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="seekWindowSizeLabel">
<property name="text">
<string>0 ms</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="resetSeekWindowSize">
<property name="toolTip">
<string>Reset Seek Window</string>
</property>
<property name="icon">
<iconset theme="restart-line"/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Overlap:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="overlap">
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>15</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TickPosition::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="overlapLabel">
<property name="text">
<string>0 ms</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="resetOverlap">
<property name="toolTip">
<string>Reset Overlap</string>
</property>
<property name="icon">
<iconset theme="restart-line"/>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QCheckBox" name="useQuickSeek">
<property name="text">
<string>Use Quick Seek</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="useAAFilter">
<property name="text">
<string>Use Anti-Aliasing Filter</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View File

@@ -1,227 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AudioStretchSettingsDialog</class>
<widget class="QDialog" name="AudioStretchSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>267</height>
</rect>
</property>
<property name="windowTitle">
<string>Audio Stretch Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="QLabel" name="seekWindowSizeLabel">
<property name="text">
<string>20</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Overlap:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="sequenceLength">
<property name="minimum">
<number>20</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>30</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TickPosition::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="seekWindowSize">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>30</number>
</property>
<property name="value">
<number>20</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TickPosition::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>2</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Seekwindow Size:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="sequenceLengthLabel">
<property name="text">
<string>30</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Sequence Length:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="overlap">
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>15</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TickPosition::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Close|QDialogButtonBox::StandardButton::RestoreDefaults</set>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QCheckBox" name="useQuickSeek">
<property name="text">
<string>Use Quickseek</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="overlapLabel">
<property name="text">
<string>10</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="useAAFilter">
<property name="text">
<string>Use Anti-Aliasing Filter</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="icon">
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Audio Stretch Settings</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>These settings fine-tune the behavior of the SoundTouch audio time stretcher when running outside of 100% speed.</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -283,9 +283,6 @@
<QtUi Include="controllerbindingwidget_negconrumble.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="audiostretchsettingsdialog.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="controllerbindingwidget_justifier.ui">
<FileType>Document</FileType>
</QtUi>

View File

@@ -155,7 +155,6 @@
<QtUi Include="graphicssettingswidget.ui" />
<QtUi Include="memoryscannerwindow.ui" />
<QtUi Include="controllerbindingwidget_negconrumble.ui" />
<QtUi Include="audiostretchsettingsdialog.ui" />
<QtUi Include="controllerbindingwidget_justifier.ui" />
<QtUi Include="selectdiscdialog.ui" />
<QtUi Include="texturereplacementsettingsdialog.ui" />

View File

@@ -201,13 +201,25 @@ void QtUtils::SetWidgetFontForInheritedSetting(QWidget* widget, bool inherited)
}
}
void QtUtils::BindLabelToSlider(QSlider* slider, QLabel* label, float range /*= 1.0f*/)
void QtUtils::BindLabelToSlider(QSlider* slider, QLabel* label, float range /*= 1.0f*/,
const QString& format /*= QStringLiteral()*/)
{
auto update_label = [label, range](int new_value) {
label->setText(QString::number(static_cast<int>(new_value) / range));
};
update_label(slider->value());
QObject::connect(slider, &QSlider::valueChanged, label, std::move(update_label));
if (format.isEmpty())
{
auto update_label = [label, range](int new_value) {
label->setText(QString::number(static_cast<int>(new_value) / range));
};
update_label(slider->value());
QObject::connect(slider, &QSlider::valueChanged, label, std::move(update_label));
}
else
{
auto update_label = [label, range, format](int new_value) {
label->setText(format.arg(static_cast<int>(new_value) / range));
};
update_label(slider->value());
QObject::connect(slider, &QSlider::valueChanged, label, std::move(update_label));
}
}
void QtUtils::SetWindowResizeable(QWidget* widget, bool resizeable)

View File

@@ -32,7 +32,6 @@ class QVariant;
class QWidget;
class QUrl;
enum class ConsoleRegion : u8;
enum class DiscRegion : u8;
namespace GameDatabase {
@@ -109,7 +108,7 @@ QString NormalizeLineEndings(QString str);
void SetWidgetFontForInheritedSetting(QWidget* widget, bool inherited);
/// Binds a label to a slider's value.
void BindLabelToSlider(QSlider* slider, QLabel* label, float range = 1.0f);
void BindLabelToSlider(QSlider* slider, QLabel* label, float range = 1.0f, const QString& format = QString());
/// Changes whether a window is resizable.
void SetWindowResizeable(QWidget* widget, bool resizeable);