mirror of
https://github.com/stenzek/duckstation.git
synced 2026-02-14 02:14:35 +00:00
CoreAudioStream: Handle parameter changes without restarting
This commit is contained in:
@@ -4507,7 +4507,10 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||
if (g_settings.audio_backend != old_settings.audio_backend ||
|
||||
g_settings.audio_driver != old_settings.audio_driver ||
|
||||
g_settings.audio_output_device != old_settings.audio_output_device ||
|
||||
g_settings.audio_stream_parameters != old_settings.audio_stream_parameters)
|
||||
g_settings.audio_stream_parameters.output_latency_ms !=
|
||||
old_settings.audio_stream_parameters.output_latency_ms ||
|
||||
g_settings.audio_stream_parameters.output_latency_minimal !=
|
||||
old_settings.audio_stream_parameters.output_latency_minimal)
|
||||
{
|
||||
if (g_settings.audio_backend != old_settings.audio_backend)
|
||||
{
|
||||
@@ -4524,6 +4527,10 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||
if (sound_effects_active)
|
||||
SoundEffectManager::EnsureInitialized();
|
||||
}
|
||||
else if (g_settings.audio_stream_parameters != old_settings.audio_stream_parameters)
|
||||
{
|
||||
SPU::GetOutputStream().UpdateParameters(g_settings.audio_stream_parameters);
|
||||
}
|
||||
|
||||
if (g_settings.emulation_speed != old_settings.emulation_speed)
|
||||
UpdateThrottlePeriod();
|
||||
|
||||
@@ -134,6 +134,64 @@ bool CoreAudioStream::Initialize(AudioBackend backend, u32 sample_rate, const Au
|
||||
return true;
|
||||
}
|
||||
|
||||
void CoreAudioStream::UpdateParameters(const AudioStreamParameters& params)
|
||||
{
|
||||
constexpr auto copy_stretch_params = [](AudioStreamParameters& dest, const AudioStreamParameters& src) {
|
||||
dest.stretch_sequence_length_ms = src.stretch_sequence_length_ms;
|
||||
dest.stretch_seekwindow_ms = src.stretch_seekwindow_ms;
|
||||
dest.stretch_overlap_ms = src.stretch_overlap_ms;
|
||||
dest.stretch_use_quickseek = src.stretch_use_quickseek;
|
||||
dest.stretch_use_aa_filter = src.stretch_use_aa_filter;
|
||||
};
|
||||
|
||||
if (params.buffer_ms != m_parameters.buffer_ms)
|
||||
{
|
||||
Error error;
|
||||
|
||||
// have to pause the stream to change buffer size
|
||||
if (m_stream && !m_paused)
|
||||
{
|
||||
if (!m_stream->Stop(&error))
|
||||
{
|
||||
ERROR_LOG("Failed to stop audio stream for buffer size change: {}", error.GetDescription());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StretchDestroy();
|
||||
DestroyBuffer();
|
||||
|
||||
m_parameters.buffer_ms = params.buffer_ms;
|
||||
copy_stretch_params(m_parameters, params);
|
||||
|
||||
AllocateBuffer();
|
||||
StretchAllocate();
|
||||
|
||||
if (m_stream && !m_paused)
|
||||
{
|
||||
if (!m_stream->Start(&error))
|
||||
{
|
||||
ERROR_LOG("Failed to start audio stream after buffer size change: {}", error.GetDescription());
|
||||
m_paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (params.stretch_mode != m_parameters.stretch_mode)
|
||||
{
|
||||
StretchDestroy();
|
||||
copy_stretch_params(m_parameters, params);
|
||||
StretchAllocate();
|
||||
}
|
||||
else
|
||||
{
|
||||
// easier case: just changing stretch settings
|
||||
StretchUpdateParameters(params);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreAudioStream::Destroy()
|
||||
{
|
||||
m_stream.reset();
|
||||
@@ -583,6 +641,42 @@ void CoreAudioStream::StretchAllocate()
|
||||
m_staging_buffer_pos = 0;
|
||||
}
|
||||
|
||||
void CoreAudioStream::StretchUpdateParameters(const AudioStreamParameters& params)
|
||||
{
|
||||
if (m_parameters.stretch_mode == AudioStretchMode::Off)
|
||||
return;
|
||||
|
||||
if (params.stretch_use_quickseek != m_parameters.stretch_use_quickseek)
|
||||
{
|
||||
m_parameters.stretch_use_quickseek = params.stretch_use_quickseek;
|
||||
soundtouch_setSetting(m_soundtouch, SETTING_USE_QUICKSEEK, m_parameters.stretch_use_quickseek);
|
||||
}
|
||||
|
||||
if (params.stretch_use_aa_filter != m_parameters.stretch_use_aa_filter)
|
||||
{
|
||||
m_parameters.stretch_use_aa_filter = params.stretch_use_aa_filter;
|
||||
soundtouch_setSetting(m_soundtouch, SETTING_USE_AA_FILTER, m_parameters.stretch_use_aa_filter);
|
||||
}
|
||||
|
||||
if (params.stretch_sequence_length_ms != m_parameters.stretch_sequence_length_ms)
|
||||
{
|
||||
m_parameters.stretch_sequence_length_ms = params.stretch_sequence_length_ms;
|
||||
soundtouch_setSetting(m_soundtouch, SETTING_SEQUENCE_MS, m_parameters.stretch_sequence_length_ms);
|
||||
}
|
||||
|
||||
if (params.stretch_seekwindow_ms != m_parameters.stretch_seekwindow_ms)
|
||||
{
|
||||
m_parameters.stretch_seekwindow_ms = params.stretch_seekwindow_ms;
|
||||
soundtouch_setSetting(m_soundtouch, SETTING_SEEKWINDOW_MS, m_parameters.stretch_seekwindow_ms);
|
||||
}
|
||||
|
||||
if (params.stretch_overlap_ms != m_parameters.stretch_overlap_ms)
|
||||
{
|
||||
m_parameters.stretch_overlap_ms = params.stretch_overlap_ms;
|
||||
soundtouch_setSetting(m_soundtouch, SETTING_OVERLAP_MS, m_parameters.stretch_overlap_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreAudioStream::StretchDestroy()
|
||||
{
|
||||
if (m_soundtouch)
|
||||
|
||||
@@ -94,6 +94,10 @@ public:
|
||||
std::string_view driver_name, std::string_view device_name, Error* error);
|
||||
void Destroy();
|
||||
|
||||
/// Updates stream parameters without recreating the stream.
|
||||
/// NOTE: Cannot handle changes in output latency.
|
||||
void UpdateParameters(const AudioStreamParameters& params);
|
||||
|
||||
/// Temporarily pauses the stream, preventing it from requesting data.
|
||||
void SetPaused(bool paused);
|
||||
|
||||
@@ -125,6 +129,7 @@ private:
|
||||
void InternalWriteFrames(SampleType* samples, u32 num_frames);
|
||||
|
||||
void StretchAllocate();
|
||||
void StretchUpdateParameters(const AudioStreamParameters& params);
|
||||
void StretchDestroy();
|
||||
void StretchWriteBlock(const float* block);
|
||||
void StretchUnderrun();
|
||||
|
||||
Reference in New Issue
Block a user