[client] usb audio: support up to 192khz 24-bit

We can not support 32-bit because Windows is buggy:

The exact Windows 11 mmsys.cpl from build 26100.8737 populates Speaker
Setup testing against hard-coded speaker masks and for each calls
IKsFormatSupport::IsFormatSupported() using 24 hard-coded PCM formats.

These formats do not include 32-bit in 32-bit, consequently, every one
of the wizard’s format probes fails and it inserts zero channel-list
entries.

It does however test for 24-bit in 32-bit which passes, however this
exposes another breakage due to an inconsistency inside Windows
usbaudio2.sys

For bSubslotSize = 4, bBitResolution = 24, Windows does this:

1. It publishes a KS range whose minimum and maximum bit depths are both
   taken from bBitResolution, so the range says 24-bit.
2. It correctly constructs the actual stream format as:
   wBitsPerSample = 32, wValidBitsPerSample = 24
3. KS range intersection rejects that 24-in-32 format because its
   container is 32 bits while the published range says 24.
4. A packed 24-bit candidate passes range intersection, but the
   subsequent exact stream check rejects it because it uses a three-byte
   container while USB advertises four bytes.

Therefore no format can pass both checks. That exactly explains:

* USB Device Tree Viewer seeing 24-bit device ranges.
* The MMDevice endpoint exposing no usable formats.
* Windows being unable to start playback.

I verified this in the exact Windows 10.0.26100.8737 driver:

* KSPin::AddDataRange stores bBitResolution into both KS bit-depth
  bounds.
* MiniportWave::DataRangeIntersection tests those bounds.
* WaveFormatInfo::IsMatchingStreamFormat separately compares both the
  container width and valid-bit count.
This commit is contained in:
Geoffrey McRae
2026-08-09 22:42:36 +10:00
parent a1da8c14f3
commit ff665c2031
3 changed files with 357 additions and 102 deletions

View File

@@ -24,18 +24,20 @@
#include "usbredir.h"
#include <stddef.h>
#include <stdint.h>
#define LG_USB_AUDIO_SAMPLE_RATE 48000
#define LG_USB_AUDIO_CHANNELS 2
#define LG_USB_AUDIO_DEFAULT_SAMPLE_RATE 48000
typedef struct LG_USBAudio LG_USBAudio;
typedef struct LG_USBAudioEventOps
{
void (*start)(void * opaque);
void (*start)(void * opaque, uint32_t sampleRate, uint32_t channelMask);
void (*stop)(void * opaque);
/* Data is borrowed interleaved stereo 32-bit IEEE float, little endian. */
/* Data is borrowed interleaved packed signed 24-bit PCM, little endian.
* Channels are ordered by ascending set bits in the selected UAC channel
* mask. */
void (*data)(void * opaque, const void * data, size_t frames);
}
LG_USBAudioEventOps;