When IsFormatSupported returns S_FALSE with a closestMatch format,
evaluate it and use it if it's acceptable (stereo float). This can
improve compatibility with devices that don't support our exact
requested format but have a similar one.
Previously we just discarded closestMatch and forced manual conversion,
which was wasteful when the device provided a perfectly usable
alternative format.
CRITICAL BUG FIX: The previous code assumed incorrect channel ordering
for multichannel audio, breaking 5.1 (6-channel) configurations.
Problem:
- Code assumed channel order: FL, FR, RL, RR, C, LFE
o systems- Actual 5.1 standard order: FL, FR, C, LFE, RL, RR
- This caused center/LFE to receive rear audio and vice versa
- Users had to force stereo mode to get working audio
Solution:
- Parse dwChannelMask from WAVEFORMATEXTENSIBLE to determine actual
channel positions
- Map stereo input to correct output channels based on the mask
- Properly handles 5.1, 7.1, and other multichannel configurations
- Safely handles non-standard channel layouts
The channel mapping now works correctly for all standard speaker
configurations by querying the device's actual channel layout instead
of assuming a fixed order.
Define constants for channel upmixing attenuation factors to improve
code readability and maintainability:
- SURROUND_ATTENUATION (0.7f) for rear/side channels
- CENTER_MIX_ATTENUATION (0.7f) for center channel
- LFE_MIX_ATTENUATION (0.5f) for LFE channel
Store format_->nChannels in atomic curChannels_ member to avoid
unsynchronized access to format_ pointer from the audio thread.
The format_ pointer can be freed/reallocated during Stop() while
the audio thread might still be reading it.