Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions src/platform/windows/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,26 @@

using virtual_sink_waveformats_t = std::vector<WAVEFORMATEXTENSIBLE>;

/**
* @brief List of supported waveformats for an N-channel virtual audio device
* @tparam channel_count Number of virtual audio channels
* @returns std::vector<WAVEFORMATEXTENSIBLE>
* @note The list of virtual formats returned are sorted in preference order and the first valid
* format will be used. All bits-per-sample options are listed because we try to match
* this to the default audio device. See also: set_format() below.
*/
template<WORD channel_count>
virtual_sink_waveformats_t create_virtual_sink_waveformats() {
if constexpr (channel_count == 2) {
auto channel_mask = waveformat_mask_stereo;
// only choose 24 or 16-bit formats to avoid clobbering existing Dolby/DTS spatial audio settings
// The 32-bit formats are a lower priority for stereo because using one will disable Dolby/DTS
// spatial audio mode if the user enabled it on the Steam speaker.
return {
create_waveformat(sample_format_e::s24in32, channel_count, channel_mask),
create_waveformat(sample_format_e::s24, channel_count, channel_mask),
create_waveformat(sample_format_e::s16, channel_count, channel_mask),
create_waveformat(sample_format_e::f32, channel_count, channel_mask),
create_waveformat(sample_format_e::s32, channel_count, channel_mask),
};
} else if (channel_count == 6) {
auto channel_mask1 = waveformat_mask_surround51_with_backspeakers;
Expand Down Expand Up @@ -298,6 +309,10 @@
auto waveformatext_pointer = reinterpret_cast<const WAVEFORMATEXTENSIBLE *>(mixer_waveformat.get());
capture_waveformat.dwChannelMask = waveformatext_pointer->dwChannelMask;
}

BOOST_LOG(info) << "Audio mixer format is "sv << mixer_waveformat->wBitsPerSample << "-bit, "sv
<< mixer_waveformat->nSamplesPerSec << " Hz, "sv
<< ((mixer_waveformat->nSamplesPerSec != 48000) ? "will be resampled to 48000 by Windows"sv : "no resampling needed"sv);
}

status = audio_client->Initialize(
Expand All @@ -315,7 +330,7 @@
return nullptr;
}

BOOST_LOG(info) << "Audio capture format is " << logging::bracket(waveformat_to_pretty_string(capture_waveformat));
BOOST_LOG(info) << "Audio capture format is "sv << logging::bracket(waveformat_to_pretty_string(capture_waveformat));

return audio_client;
}
Expand Down Expand Up @@ -793,6 +808,22 @@
}
}

// When switching to a Steam virtual speaker device, try to retain the bit depth of the
// default audio device. Switching from a 16-bit device to a 24-bit one has been known to
// cause glitches for some users.
int wanted_bits_per_sample = 32;

Check warning on line 814 in src/platform/windows/audio.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/audio.cpp#L814

Added line #L814 was not covered by tests
auto current_default_dev = default_device(device_enum);
if (current_default_dev) {
audio::prop_t prop;

Check warning on line 817 in src/platform/windows/audio.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/audio.cpp#L817

Added line #L817 was not covered by tests
prop_var_t current_device_format;

if (SUCCEEDED(current_default_dev->OpenPropertyStore(STGM_READ, &prop)) && SUCCEEDED(prop->GetValue(PKEY_AudioEngine_DeviceFormat, &current_device_format.prop))) {
auto *format = (WAVEFORMATEXTENSIBLE *) current_device_format.prop.blob.pBlobData;
wanted_bits_per_sample = format->Samples.wValidBitsPerSample;

Check warning on line 822 in src/platform/windows/audio.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/audio.cpp#L821-L822

Added lines #L821 - L822 were not covered by tests
BOOST_LOG(info) << "Virtual audio device will use "sv << wanted_bits_per_sample << "-bit to match default device"sv;
}
}

auto &device_id = virtual_sink_info->first;
auto &waveformats = virtual_sink_info->second.get().virtual_sink_waveformats;
for (const auto &waveformat : waveformats) {
Expand All @@ -802,6 +833,10 @@
auto waveformat_copy = waveformat;
auto waveformat_copy_pointer = reinterpret_cast<WAVEFORMATEX *>(&waveformat_copy);

if (wanted_bits_per_sample != waveformat.Samples.wValidBitsPerSample) {
continue;

Check warning on line 837 in src/platform/windows/audio.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/windows/audio.cpp#L837

Added line #L837 was not covered by tests
}

WAVEFORMATEXTENSIBLE p {};
if (SUCCEEDED(policy->SetDeviceFormat(device_id_copy.c_str(), waveformat_copy_pointer, (WAVEFORMATEX *) &p))) {
BOOST_LOG(info) << "Changed virtual audio sink format to " << logging::bracket(waveformat_to_pretty_string(waveformat));
Expand Down
Loading