Search code examples
c++winapiaudiowasapi

Interpreting WAVEFORMATEXTENSIBLE from IAudioClient::GetMixFormat


I'm learning about Windows Core Audio APIs. Using this Rendering a Stream example, I'm finding that IAudioClient::GetMixFormat returns an ambiguous WAVEFORMATEXTENSIBLE that looks like this:

Format
  wFormatTag          = WAVE_FORMAT_EXTENSIBLE (65534)
  nChannels           = 2
  nSamplesPerSec      = 48000
  nAvgBytesPerSec     = 384000
  nBlockAlign         = 8
  wBitsPerSample      = 32
  cbSize              = 22
Samples  // this is a union
  wValidBitsPerSample = 32
  wSamplesPerBlock    = 32
  wReserved           = 32

Since Format.cbSize is 22, this is the entire structure; there is no SubFormat GUID to provide more information about the samples. That seems weird because the format tag is WAVE_FORMAT_EXTENSIBLE, which--I thought--means that you have to rely on the Subformat GUID to determine the actual format.

I can see that there are two channels of 32-bit samples. How can I determine whether those samples are integers or floating point values?

[The tag is apparently for an Apple API. Is there a different tag for Windows Core Audio?]


Solution

  • 22 is the size of additional data that follows the WAVEFORMATEX data:

    cbSize

    Size, in bytes, of extra format information appended to the end of the WAVEFORMATEX structure. This information can be used by non-PCM formats to store extra attributes for the wFormatTag. If no extra information is required by the wFormatTag, this member must be set to 0. For WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), this member is ignored. When this structure is included in a WAVEFORMATEXTENSIBLE structure, this value must be at least 22.

    If you look at the definition of WAVEFORMATEXTENSIBLE, it begins with a WAVEFORMATEX and then contains extra data after it:

    typedef struct {
      WAVEFORMATEX Format;
      union {
        WORD wValidBitsPerSample;
        WORD wSamplesPerBlock;
        WORD wReserved;
      } Samples;
      DWORD        dwChannelMask;
      GUID         SubFormat;
    } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
    

    That is a minimum of 22 bytes after the WAVEFORMATEX data.

    The SubFormat field contains the format value you are looking for.