[PATCH 0/1] MR9663: Draft: winecoreaudio: Set the AudioChannelLayout on output units.
Some users have reported the center/LFE channels being swapped when playing games that support surround sound. After investigating, it appears that winecoreaudio never sets AudioChannelLayout on the audio unit, and assumes that it matches the Windows layout (which is the order of `dwChannelMask`). This is often true, but not always. Using some test code [1] in `ca_setup_audiounit()` to get the AudioChannelLayout (Dell U2711 over HDMI), for some reason the audio unit defaults to having the center (3) and LFE (4) positions swapped from where Windows lays them out: ``` 1389548.056:0020:0124:err:coreaudio:ca_setup_audiounit Got channel layout: {tag: 0x0, bitmap: 0x0, num_descs: 6} 1389548.056:0020:0124:err:coreaudio:ca_setup_audiounit desc 0: label 1 flags 0 1389548.056:0020:0124:err:coreaudio:ca_setup_audiounit desc 1: label 2 flags 0 1389548.056:0020:0124:err:coreaudio:ca_setup_audiounit desc 2: label 4 flags 0 1389548.056:0020:0124:err:coreaudio:ca_setup_audiounit desc 3: label 3 flags 0 1389548.056:0020:0124:err:coreaudio:ca_setup_audiounit desc 4: label 5 flags 0 1389548.056:0020:0124:err:coreaudio:ca_setup_audiounit desc 5: label 6 flags 0 ``` To fix this, set the AudioChannelLayout in `ca_setup_audiounit()`. Happily the Core Audio `AudioChannelBitmap` and Windows `dwChannelMask` perfectly match each other in speaker/bit positions, so this is easy. Marked as draft pending some extra testing. [1]: ``` { UInt32 size; Boolean writable; sc = AudioUnitGetPropertyInfo(unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &size, &writable); ERR("AudioChannelLayout sc %d\n", sc); if (sc == noErr) { AudioChannelLayout *layout = malloc(size); sc = AudioUnitGetProperty(unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, layout, &size); ERR("AudioChannelLayout 2 sc %d\n", sc); ERR("Got channel layout: {tag: 0x%x, bitmap: 0x%x, num_descs: %u}\n", (unsigned int)layout->mChannelLayoutTag, (unsigned int)layout->mChannelBitmap, (unsigned int)layout->mNumberChannelDescriptions); for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; i++) { ERR("desc %d: label %d flags %x\n", i, layout->mChannelDescriptions[i].mChannelLabel, layout->mChannelDescriptions[i].mChannelFlags); } free(layout); } } } ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9663
From: Brendan Shanks <bshanks(a)codeweavers.com> Fixes center/LFE channels being swapped for some users. --- dlls/winecoreaudio.drv/coreaudio.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index 9d85cde34d4..da2ae2dd67b 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -662,6 +662,8 @@ static HRESULT ca_setup_audiounit(EDataFlow dataflow, AudioComponentInstance uni return osstatus_to_hresult(sc); } }else{ + AudioChannelLayout layout; + hr = ca_get_audiodesc(dev_desc, fmt); if(FAILED(hr)) return hr; @@ -673,6 +675,16 @@ static HRESULT ca_setup_audiounit(EDataFlow dataflow, AudioComponentInstance uni WARN("Couldn't set format: %x\n", (int)sc); return osstatus_to_hresult(sc); } + + /* Set channel layout: AudioChannelBitmap and dwChannelMask conveniently have identical positions */ + layout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelBitmap; + layout.mChannelBitmap = (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) ? ((WAVEFORMATEXTENSIBLE *)fmt)->dwChannelMask : 0x3; + layout.mNumberChannelDescriptions = 0; + + sc = AudioUnitSetProperty(unit, kAudioUnitProperty_AudioChannelLayout, + kAudioUnitScope_Input, 0, &layout, sizeof(layout)); + if (sc != noErr) + WARN("Couldn't set channel layout: %d\n", (int)sc); } return S_OK; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9663
This merge request was approved by Huw Davies. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9663
participants (3)
-
Brendan Shanks -
Brendan Shanks (@bshanks) -
Huw Davies (@huw)