Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WASAPI gets the channel count wrong for some devices #286

Closed
PortAudio-admin opened this issue Nov 19, 2018 · 7 comments
Closed

WASAPI gets the channel count wrong for some devices #286

PortAudio-admin opened this issue Nov 19, 2018 · 7 comments
Labels
P3 Priority: Normal src-wasapi MS WASAPI Host API /src/hostapi/wasapi windows Affects MS Windows

Comments

@PortAudio-admin
Copy link
Collaborator

Issue created by @dechamps

This was originally a FlexASIO bug, which I am now reporting upstream.

For some audio devices, the WASAPI PortAudio code reports a channel count (both in PaDeviceInfo and from PaWasapi_GetDeviceDefaultFormat()) that is completely wrong.

Specifically, I have a user for whom PortAudio returns the following:

Device index: 20
Device name: Microphone (Realtek High Definition Audio)
Default sample rate: 48000
Input: max channel count 8, default latency 0.003s (low) 0.01s (high)
Output: max channel count 0, default latency 0s (low) 0s (high)
Host API name: Windows WASAPI
Host API type: 13 [WASAPI]
DEFAULT INPUT DEVICE for this host API
WASAPI device default format: WAVEFORMAT with format tag 65534 [EXTENSIBLE],
  8 channels, 48000 samples/second, 768000 average bytes/second, block alignment 16 bytes,
  16 bits per sample, 16 valid bits per sample,
  channel mask 1599 [Front Left, Front Right, Front Center, Low Frequency, Back Left, Back Right, Side Left, Side Right],
  format {00000001-0000-0010-8000-00AA00389B71} [PCM]

This is for the built-in microphone input of a MSI GS63VR 7RG Stealth Pro running Windows 10.0.17134.

It goes without saying that the microphone input of a laptop is definitely not an 8-channel 7.1 audio input device. Trying to open it with 8 channels (in shared and exclusive mode), unsurprisingly, fails.

All other host APIs (MME, DirectSound, and WDM-KS) correctly report 2 channels for this device.

Relevant portion of the PortAudio debug log:

WASAPI:4| name[Microphone (Realtek High Definition Audio)]
WASAPI:4| form-factor[4]
WASAPI:4| def.SR[48000] max.CH[8] latency{hi[0.010000] lo[0.003000]}
WASAPI: device idx: 05

Both pa_stable_v190600_20161030 and latest PortAudio master (0cdb346) exhibit this problem.

Sadly, I am unable to reproduce this using any of my own hardware. I only know of a single end user who is experiencing this bug.

@PortAudio-admin
Copy link
Collaborator Author

Comment by @dechamps

The code is getting the default device format using this code:

IMMDevice_OpenPropertyStore(paWasapi->devInfo[i].device, STGM_READ, &pProperty);
IPropertyStore_GetValue(pProperty, &PKEY_AudioEngine_DeviceFormat, &value);

This is then fed into PaDeviceInfo.

MSDN seems to be somewhat conflicted about the use of PKEY_AudioEngine_DeviceFormat. On one hand, it states:

"This format might not be the best default format for an exclusive-mode application to use."

But on the other hand:

"An application can query an audio endpoint device's PKEY_AudioEngine_DeviceFormat property to obtain the shared-mode format that the user has selected for the device. For information about querying the properties of a device, see Device Properties. Some applications might find the format specified by a device's PKEY_AudioEngine_DeviceFormat property to be a suitable format for opening an exclusive-mode stream on the device."

Here this is clearly not true, since the user surely never selected 8 channels for a built-in microphone input. This looks like a Windows bug.

In any case, it seems like it would make more sense to use the IAudioClient::GetMixFormat() method anyway:

"When creating a shared-mode stream for an audio endpoint device, the Initialize method always accepts the stream format obtained from a GetMixFormat call on the same device."

I believe this makes most sense for the channel count returned by PortAudio, because shared mode is the default in PortAudio. If we want PortAudio users to be able to simply enumerate devices and be able to open them without having to care about host API specifics (which seems like what PortAudio is designed to do), then we should optimize for shared mode.

That said, regarding exclusive mode, the same page goes on to say:

"This format is not necessarily a format that the audio endpoint device supports. Thus, the caller might not succeed in creating an exclusive-mode stream with a format obtained by calling GetMixFormat."

Therefore, it seems like the best way to fix this is to do the following:

  • Use GetMixFormat() to populate PaDeviceInfo, such that PortAudio users can always expect the default channel count to work in the default mode.
  • Use GetMixFormat() in PaWasapi_GetDeviceDefaultFormat(), for consistency with PaDeviceInfo. Existing code might rely on such consistency.

It's actually highly likely that this format will work for exclusive mode too, because it looks like the difference would be only on the sample type, and PortAudio can already automatically handle such differences through implicit sample type conversion (which already works). Therefore I am not convinced that we actually need to use PKEY_AudioEngine_DeviceFormat at all. Worst case scenario we could expose a separate WASAPI-specific function for it.

@PortAudio-admin
Copy link
Collaborator Author

Comment by @dechamps

Here's what I'm getting from IAudioClient::GetMixFormat() for one of my devices:

WAVEFORMAT with format tag 65534 [EXTENSIBLE],
6 channels, 48000 samples/second, 1152000 average bytes/second,
block alignment 24 bytes, 32 bits per sample, 32 valid bits per sample,
channel mask 63 [Front Left, Front Right, Front Center, Low Frequency, Back Left, Back Right],
subformat {00000003-0000-0010-8000-00AA00389B71} [IEEE Float]

This is what I'd expect. Now I'll get my user with the offending hardware to try this and see what happens.

@PortAudio-admin
Copy link
Collaborator Author

Comment by @dechamps

Use GetMixFormat() instead of PKEY_AudioEngine_DeviceFormat.

See #286 for rationale.

Committed to: portaudio:wasapiformat
Commit: d0f3413f8ebaf8a716feb5944665823dbda884bc

@PortAudio-admin
Copy link
Collaborator Author

Comment by @dechamps

Use GetMixFormat() instead of PKEY_AudioEngine_DeviceFormat.

See #286 for rationale.

Committed to: portaudio:wasapiformat
Commit: 1f5429e

@PortAudio-admin
Copy link
Collaborator Author

Comment by @dechamps

Use GetMixFormat() instead of PKEY_AudioEngine_DeviceFormat.

See #286 for rationale.

Committed to: portaudio:wasapiformat2
Commit: 29ad0712036a4a4dd5499fe30c022f7bff9057ae

@PortAudio-admin
Copy link
Collaborator Author

Comment by @dechamps

Fixed in d74ea7b in master.

@PortAudio-admin
Copy link
Collaborator Author

Issue closed by @dechamps

@PortAudio-admin PortAudio-admin added src-wasapi MS WASAPI Host API /src/hostapi/wasapi P3 Priority: Normal windows Affects MS Windows labels Sep 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 Priority: Normal src-wasapi MS WASAPI Host API /src/hostapi/wasapi windows Affects MS Windows
Projects
None yet
Development

No branches or pull requests

1 participant