[idd] audio: support 32-bit and common channel layouts

Advertise signed and floating-point 32-bit formats across mono,
stereo, quad, surround, 5.1, and 7.1 at every supported rate.

Carry sample encoding through the broker and LGMP protocol so integer
and floating-point streams remain distinct.

Expand packet, shared-memory, and ring capacity for eight-channel
32-bit audio.
This commit is contained in:
Geoffrey McRae
2026-09-05 07:39:32 +10:00
parent 5681dcdbe7
commit efc9952e74
13 changed files with 444 additions and 170 deletions

View File

@@ -27,13 +27,19 @@ namespace LGAudio
constexpr USHORT kExtensibleExtraSize = static_cast<USHORT>(
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX));
bool IsAudioPcmWaveFormat(_In_ const KSDATAFORMAT * format)
bool IsSupportedSubFormat(_In_ const GUID & subFormat)
{
return
IsEqualGUIDAligned(subFormat, KSDATAFORMAT_SUBTYPE_PCM) ||
IsEqualGUIDAligned(subFormat, KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
}
bool IsAudioWaveFormat(_In_ const KSDATAFORMAT * format)
{
return
IsEqualGUIDAligned(format->MajorFormat,
KSDATAFORMAT_TYPE_AUDIO) &&
IsEqualGUIDAligned(format->SubFormat,
KSDATAFORMAT_SUBTYPE_PCM) &&
IsSupportedSubFormat(format->SubFormat) &&
IsEqualGUIDAligned(format->Specifier,
KSDATAFORMAT_SPECIFIER_WAVEFORMATEX);
}
@@ -80,23 +86,6 @@ namespace LGAudio
}
}
void GetDataRangeList(
_In_ EndpointKind endpoint,
_Outptr_result_buffer_(*count) KSDATARANGE_AUDIO ** ranges,
_Out_ PULONG count)
{
if (endpoint == EndpointKind::Render)
{
*ranges = g_renderDataRanges;
*count = kRenderFormatCount;
}
else
{
*ranges = g_captureDataRanges;
*count = kCaptureFormatCount;
}
}
bool AudioRangeContainsFormat(
_In_ const KSDATARANGE_AUDIO & range,
_In_ const KSDATAFORMAT_WAVEFORMATEXTENSIBLE & format)
@@ -104,6 +93,8 @@ namespace LGAudio
const WAVEFORMATEX & wave = format.WaveFormatExt.Format;
return
IsEqualGUIDAligned(range.DataRange.SubFormat,
format.DataFormat.SubFormat) &&
range.MaximumChannels == wave.nChannels &&
range.MinimumBitsPerSample <= wave.wBitsPerSample &&
range.MaximumBitsPerSample >= wave.wBitsPerSample &&
@@ -118,16 +109,48 @@ namespace LGAudio
const WAVEFORMATEX & wave = format.WaveFormatExt.Format;
return
IsEqualGUIDAligned(range.DataRange.SubFormat,
format.DataFormat.SubFormat) &&
range.MaximumChannels == wave.nChannels &&
range.MinimumBitsPerSample == wave.wBitsPerSample &&
range.MaximumBitsPerSample == wave.wBitsPerSample &&
range.MinimumSampleFrequency == wave.nSamplesPerSec &&
range.MaximumSampleFrequency == wave.nSamplesPerSec;
}
SampleFormat GetSampleFormat(
_In_ const WAVEFORMATEXTENSIBLE & wave)
{
if (IsEqualGUIDAligned(wave.SubFormat,
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
{
return wave.Format.wBitsPerSample == 32 &&
wave.Samples.wValidBitsPerSample == 32 ?
SampleFormat::F32LE : SampleFormat::Unknown;
}
if (!IsEqualGUIDAligned(wave.SubFormat,
KSDATAFORMAT_SUBTYPE_PCM) ||
wave.Format.wBitsPerSample !=
wave.Samples.wValidBitsPerSample)
return SampleFormat::Unknown;
switch (wave.Format.wBitsPerSample)
{
case 16:
return SampleFormat::S16LE;
case 24:
return SampleFormat::S24LE;
case 32:
return SampleFormat::S32LE;
default:
return SampleFormat::Unknown;
}
}
}
#define LG_AUDIO_FORMAT( \
sampleRate_, channels_, containerBits_, validBits_, mask_) \
sampleRate_, channels_, bits_, mask_, subType_) \
{ \
{ \
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), \
@@ -135,7 +158,7 @@ namespace LGAudio
0, \
0, \
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), \
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), \
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_##subType_), \
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) \
}, \
{ \
@@ -143,28 +166,56 @@ namespace LGAudio
WAVE_FORMAT_EXTENSIBLE, \
channels_, \
sampleRate_, \
sampleRate_ * channels_ * (containerBits_ / 8), \
channels_ * (containerBits_ / 8), \
containerBits_, \
sampleRate_ * channels_ * (bits_ / 8), \
channels_ * (bits_ / 8), \
bits_, \
kExtensibleExtraSize \
}, \
validBits_, \
bits_, \
mask_, \
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) \
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_##subType_) \
} \
}
#define LG_RENDER_LAYOUTS(sampleRate_, bits_, subType_) \
LG_AUDIO_FORMAT(sampleRate_, 2, bits_, KSAUDIO_SPEAKER_STEREO, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 1, bits_, KSAUDIO_SPEAKER_MONO, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 4, bits_, KSAUDIO_SPEAKER_QUAD, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 4, bits_, KSAUDIO_SPEAKER_SURROUND, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 6, bits_, \
KSAUDIO_SPEAKER_5POINT1_SURROUND, subType_), \
LG_AUDIO_FORMAT(sampleRate_, 8, bits_, \
KSAUDIO_SPEAKER_7POINT1_SURROUND, subType_)
#define LG_CAPTURE_LAYOUTS(sampleRate_, bits_, subType_) \
LG_AUDIO_FORMAT(sampleRate_, 1, bits_, KSAUDIO_SPEAKER_MONO, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 2, bits_, KSAUDIO_SPEAKER_STEREO, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 4, bits_, KSAUDIO_SPEAKER_QUAD, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 4, bits_, KSAUDIO_SPEAKER_SURROUND, \
subType_), \
LG_AUDIO_FORMAT(sampleRate_, 6, bits_, \
KSAUDIO_SPEAKER_5POINT1_SURROUND, subType_), \
LG_AUDIO_FORMAT(sampleRate_, 8, bits_, \
KSAUDIO_SPEAKER_7POINT1_SURROUND, subType_)
#define LG_RENDER_FORMATS(sampleRate_) \
LG_AUDIO_FORMAT(sampleRate_, 2, 16, 16, KSAUDIO_SPEAKER_STEREO), \
LG_AUDIO_FORMAT(sampleRate_, 2, 24, 24, KSAUDIO_SPEAKER_STEREO), \
LG_AUDIO_FORMAT(sampleRate_, 6, 24, 24, \
KSAUDIO_SPEAKER_5POINT1_SURROUND), \
LG_AUDIO_FORMAT(sampleRate_, 8, 24, 24, \
KSAUDIO_SPEAKER_7POINT1_SURROUND)
LG_RENDER_LAYOUTS(sampleRate_, 16, PCM), \
LG_RENDER_LAYOUTS(sampleRate_, 24, PCM), \
LG_RENDER_LAYOUTS(sampleRate_, 32, PCM), \
LG_RENDER_LAYOUTS(sampleRate_, 32, IEEE_FLOAT)
#define LG_CAPTURE_FORMATS(sampleRate_) \
LG_AUDIO_FORMAT(sampleRate_, 1, 16, 16, KSAUDIO_SPEAKER_MONO), \
LG_RENDER_FORMATS(sampleRate_)
LG_CAPTURE_LAYOUTS(sampleRate_, 16, PCM), \
LG_CAPTURE_LAYOUTS(sampleRate_, 24, PCM), \
LG_CAPTURE_LAYOUTS(sampleRate_, 32, PCM), \
LG_CAPTURE_LAYOUTS(sampleRate_, 32, IEEE_FLOAT)
KSDATAFORMAT_WAVEFORMATEXTENSIBLE
g_renderFormats[kRenderFormatCount] =
@@ -190,9 +241,11 @@ namespace LGAudio
#undef LG_CAPTURE_FORMATS
#undef LG_RENDER_FORMATS
#undef LG_CAPTURE_LAYOUTS
#undef LG_RENDER_LAYOUTS
#undef LG_AUDIO_FORMAT
#define LG_AUDIO_RANGE(sampleRate_, channels_, containerBits_) \
#define LG_AUDIO_RANGE(sampleRate_, channels_, bits_, subType_) \
{ \
{ \
sizeof(KSDATARANGE_AUDIO), \
@@ -200,27 +253,43 @@ namespace LGAudio
0, \
0, \
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), \
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), \
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_##subType_), \
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) \
}, \
channels_, \
containerBits_, \
containerBits_, \
bits_, \
bits_, \
sampleRate_, \
sampleRate_ \
}
#define LG_RENDER_LAYOUT_RANGES(sampleRate_, bits_, subType_) \
LG_AUDIO_RANGE(sampleRate_, 2, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 1, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 4, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 6, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 8, bits_, subType_)
#define LG_CAPTURE_LAYOUT_RANGES(sampleRate_, bits_, subType_) \
LG_AUDIO_RANGE(sampleRate_, 1, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 2, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 4, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 6, bits_, subType_), \
LG_AUDIO_RANGE(sampleRate_, 8, bits_, subType_)
#define LG_RENDER_RANGES(sampleRate_) \
LG_AUDIO_RANGE(sampleRate_, 2, 16), \
LG_AUDIO_RANGE(sampleRate_, 2, 24), \
LG_AUDIO_RANGE(sampleRate_, 6, 24), \
LG_AUDIO_RANGE(sampleRate_, 8, 24)
LG_RENDER_LAYOUT_RANGES(sampleRate_, 16, PCM), \
LG_RENDER_LAYOUT_RANGES(sampleRate_, 24, PCM), \
LG_RENDER_LAYOUT_RANGES(sampleRate_, 32, PCM), \
LG_RENDER_LAYOUT_RANGES(sampleRate_, 32, IEEE_FLOAT)
#define LG_CAPTURE_RANGES(sampleRate_) \
LG_AUDIO_RANGE(sampleRate_, 1, 16), \
LG_RENDER_RANGES(sampleRate_)
LG_CAPTURE_LAYOUT_RANGES(sampleRate_, 16, PCM), \
LG_CAPTURE_LAYOUT_RANGES(sampleRate_, 24, PCM), \
LG_CAPTURE_LAYOUT_RANGES(sampleRate_, 32, PCM), \
LG_CAPTURE_LAYOUT_RANGES(sampleRate_, 32, IEEE_FLOAT)
KSDATARANGE_AUDIO g_renderDataRanges[kRenderFormatCount] =
KSDATARANGE_AUDIO g_renderDataRanges[kRenderDataRangeCount] =
{
LG_RENDER_RANGES(48000),
LG_RENDER_RANGES(44100),
@@ -230,7 +299,7 @@ namespace LGAudio
LG_RENDER_RANGES(192000)
};
KSDATARANGE_AUDIO g_captureDataRanges[kCaptureFormatCount] =
KSDATARANGE_AUDIO g_captureDataRanges[kCaptureDataRangeCount] =
{
LG_CAPTURE_RANGES(48000),
LG_CAPTURE_RANGES(44100),
@@ -242,43 +311,45 @@ namespace LGAudio
#undef LG_CAPTURE_RANGES
#undef LG_RENDER_RANGES
#undef LG_CAPTURE_LAYOUT_RANGES
#undef LG_RENDER_LAYOUT_RANGES
#undef LG_AUDIO_RANGE
#define LG_RENDER_RANGE_POINTERS(base_) \
(PKSDATARANGE)&g_renderDataRanges[(base_)], \
(PKSDATARANGE)&g_renderDataRanges[(base_) + 1], \
(PKSDATARANGE)&g_renderDataRanges[(base_) + 2], \
(PKSDATARANGE)&g_renderDataRanges[(base_) + 3]
#define LG_RANGE_POINTERS_5(ranges_, base_) \
(PKSDATARANGE)&ranges_[(base_)], \
(PKSDATARANGE)&ranges_[(base_) + 1], \
(PKSDATARANGE)&ranges_[(base_) + 2], \
(PKSDATARANGE)&ranges_[(base_) + 3], \
(PKSDATARANGE)&ranges_[(base_) + 4]
#define LG_CAPTURE_RANGE_POINTERS(base_) \
(PKSDATARANGE)&g_captureDataRanges[(base_)], \
(PKSDATARANGE)&g_captureDataRanges[(base_) + 1], \
(PKSDATARANGE)&g_captureDataRanges[(base_) + 2], \
(PKSDATARANGE)&g_captureDataRanges[(base_) + 3], \
(PKSDATARANGE)&g_captureDataRanges[(base_) + 4]
#define LG_RANGE_POINTERS(ranges_, base_) \
LG_RANGE_POINTERS_5(ranges_, base_), \
LG_RANGE_POINTERS_5(ranges_, (base_) + 5), \
LG_RANGE_POINTERS_5(ranges_, (base_) + 10), \
LG_RANGE_POINTERS_5(ranges_, (base_) + 15)
PKSDATARANGE g_renderDataRangePointers[kRenderFormatCount] =
PKSDATARANGE g_renderDataRangePointers[kRenderDataRangeCount] =
{
LG_RENDER_RANGE_POINTERS(0),
LG_RENDER_RANGE_POINTERS(4),
LG_RENDER_RANGE_POINTERS(8),
LG_RENDER_RANGE_POINTERS(12),
LG_RENDER_RANGE_POINTERS(16),
LG_RENDER_RANGE_POINTERS(20)
LG_RANGE_POINTERS(g_renderDataRanges, 0),
LG_RANGE_POINTERS(g_renderDataRanges, 20),
LG_RANGE_POINTERS(g_renderDataRanges, 40),
LG_RANGE_POINTERS(g_renderDataRanges, 60),
LG_RANGE_POINTERS(g_renderDataRanges, 80),
LG_RANGE_POINTERS(g_renderDataRanges, 100)
};
PKSDATARANGE g_captureDataRangePointers[kCaptureFormatCount] =
PKSDATARANGE g_captureDataRangePointers[kCaptureDataRangeCount] =
{
LG_CAPTURE_RANGE_POINTERS(0),
LG_CAPTURE_RANGE_POINTERS(5),
LG_CAPTURE_RANGE_POINTERS(10),
LG_CAPTURE_RANGE_POINTERS(15),
LG_CAPTURE_RANGE_POINTERS(20),
LG_CAPTURE_RANGE_POINTERS(25)
LG_RANGE_POINTERS(g_captureDataRanges, 0),
LG_RANGE_POINTERS(g_captureDataRanges, 20),
LG_RANGE_POINTERS(g_captureDataRanges, 40),
LG_RANGE_POINTERS(g_captureDataRanges, 60),
LG_RANGE_POINTERS(g_captureDataRanges, 80),
LG_RANGE_POINTERS(g_captureDataRanges, 100)
};
#undef LG_CAPTURE_RANGE_POINTERS
#undef LG_RENDER_RANGE_POINTERS
#undef LG_RANGE_POINTERS
#undef LG_RANGE_POINTERS_5
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS ValidateFormat(
@@ -292,7 +363,7 @@ namespace LGAudio
if (!dataFormat ||
dataFormat->FormatSize < sizeof(KSDATAFORMAT_WAVEFORMATEX) ||
!IsAudioPcmWaveFormat(dataFormat))
!IsAudioWaveFormat(dataFormat))
return STATUS_NO_MATCH;
const WAVEFORMATEX * requested =
@@ -307,18 +378,29 @@ namespace LGAudio
const KSDATAFORMAT_WAVEFORMATEXTENSIBLE & candidate = formats[i];
const WAVEFORMATEXTENSIBLE & candidateWave = candidate.WaveFormatExt;
if (!WaveFormatCoreMatches(candidateWave.Format, *requested))
if (!IsEqualGUIDAligned(candidate.DataFormat.SubFormat,
dataFormat->SubFormat) ||
!WaveFormatCoreMatches(candidateWave.Format, *requested))
continue;
if (requested->wFormatTag == WAVE_FORMAT_PCM)
{
// A stand-alone WAVEFORMATEX is unambiguous only for these legacy
// mono/stereo, 16-bit formats.
if (candidateWave.Format.wBitsPerSample != 16 ||
if (!IsEqualGUIDAligned(candidateWave.SubFormat,
KSDATAFORMAT_SUBTYPE_PCM) ||
candidateWave.Format.wBitsPerSample != 16 ||
candidateWave.Samples.wValidBitsPerSample != 16 ||
candidateWave.Format.nChannels > 2)
continue;
}
else if (requested->wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
{
if (!IsEqualGUIDAligned(candidateWave.SubFormat,
KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) ||
candidateWave.Format.wBitsPerSample != 32 ||
candidateWave.Samples.wValidBitsPerSample != 32 ||
candidateWave.Format.nChannels > 2)
continue;
}
else if (requested->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
{
if (dataFormat->FormatSize <
@@ -328,7 +410,9 @@ namespace LGAudio
const WAVEFORMATEXTENSIBLE * requestedExtensible =
reinterpret_cast<const WAVEFORMATEXTENSIBLE *>(requested);
if (!ExtensibleFormatMatches(candidateWave, *requestedExtensible))
if (!IsEqualGUIDAligned(dataFormat->SubFormat,
requestedExtensible->SubFormat) ||
!ExtensibleFormatMatches(candidateWave, *requestedExtensible))
continue;
}
else
@@ -359,8 +443,8 @@ namespace LGAudio
if (clientDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO) ||
driverDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO) ||
!IsAudioPcmWaveFormat(clientDataRange) ||
!IsAudioPcmWaveFormat(driverDataRange))
!IsAudioWaveFormat(clientDataRange) ||
!IsAudioWaveFormat(driverDataRange))
return STATUS_NO_MATCH;
const KSDATARANGE_AUDIO & client =
@@ -369,20 +453,13 @@ namespace LGAudio
*reinterpret_cast<const KSDATARANGE_AUDIO *>(driverDataRange);
KSDATAFORMAT_WAVEFORMATEXTENSIBLE * formats;
KSDATARANGE_AUDIO * ranges;
ULONG formatCount;
ULONG rangeCount;
GetFormatList(endpoint, &formats, &formatCount);
GetDataRangeList(endpoint, &ranges, &rangeCount);
if (formatCount != rangeCount)
return STATUS_INTERNAL_ERROR;
const KSDATAFORMAT_WAVEFORMATEXTENSIBLE * selected = nullptr;
for (ULONG i = 0; i < formatCount; ++i)
{
if (!DataRangeIdentifiesFormat(driver, formats[i]) ||
!DataRangeIdentifiesFormat(ranges[i], formats[i]) ||
!AudioRangeContainsFormat(client, formats[i]))
continue;
@@ -417,6 +494,7 @@ namespace LGAudio
return STATUS_INVALID_PARAMETER;
const WAVEFORMATEXTENSIBLE & wave = dataFormat->WaveFormatExt;
const SampleFormat sampleFormat = GetSampleFormat(wave);
if (wave.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE ||
wave.Format.cbSize < kExtensibleExtraSize ||
wave.Format.nChannels == 0 ||
@@ -425,11 +503,13 @@ namespace LGAudio
wave.Samples.wValidBitsPerSample == 0 ||
wave.Samples.wValidBitsPerSample >
wave.Format.wBitsPerSample ||
!IsAudioPcmWaveFormat(&dataFormat->DataFormat) ||
!IsEqualGUIDAligned(wave.SubFormat,
KSDATAFORMAT_SUBTYPE_PCM))
!IsAudioWaveFormat(&dataFormat->DataFormat) ||
!IsEqualGUIDAligned(dataFormat->DataFormat.SubFormat,
wave.SubFormat) ||
sampleFormat == SampleFormat::Unknown)
return STATUS_INVALID_PARAMETER;
fingerprint->sampleFormat = sampleFormat;
fingerprint->sampleRate = wave.Format.nSamplesPerSec;
fingerprint->channelMask = wave.dwChannelMask;
fingerprint->channels = wave.Format.nChannels;
@@ -445,6 +525,7 @@ namespace LGAudio
_In_ const FormatFingerprint & right)
{
return
left.sampleFormat == right.sampleFormat &&
left.sampleRate == right.sampleRate &&
left.channelMask == right.channelMask &&
left.channels == right.channels &&