mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-13 15:27:21 +00:00
[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:
@@ -420,6 +420,20 @@ static bool validFormat(const KVMFRAudioFormat * wire,
|
|||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KVMFR_AUDIO_SAMPLE_S32_LE:
|
||||||
|
format = LG_AUDIO_FMT_S32_LE;
|
||||||
|
bytesPerSample = 4;
|
||||||
|
if (wire->validBits != 32 || wire->containerBits != 32)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KVMFR_AUDIO_SAMPLE_F32_LE:
|
||||||
|
format = LG_AUDIO_FMT_F32_LE;
|
||||||
|
bytesPerSample = 4;
|
||||||
|
if (wire->validBits != 32 || wire->containerBits != 32)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ enum
|
|||||||
#define KVMFR_AUDIO_MAX_CHANNELS 18U
|
#define KVMFR_AUDIO_MAX_CHANNELS 18U
|
||||||
#define KVMFR_AUDIO_MAX_SAMPLE_RATE 192000U
|
#define KVMFR_AUDIO_MAX_SAMPLE_RATE 192000U
|
||||||
#define KVMFR_AUDIO_MAX_FRAMES_PER_PACKET 2048U
|
#define KVMFR_AUDIO_MAX_FRAMES_PER_PACKET 2048U
|
||||||
#define KVMFR_AUDIO_MAX_BYTES_PER_SAMPLE 3U
|
#define KVMFR_AUDIO_MAX_BYTES_PER_SAMPLE 4U
|
||||||
#define KVMFR_AUDIO_STREAM_MAX_CHANNELS 8U
|
#define KVMFR_AUDIO_STREAM_MAX_CHANNELS 8U
|
||||||
#define KVMFR_AUDIO_STREAM_SLOT_COUNT 16U
|
#define KVMFR_AUDIO_STREAM_SLOT_COUNT 16U
|
||||||
#define KVMFR_AUDIO_OWNER_LEASE_MS 1000U
|
#define KVMFR_AUDIO_OWNER_LEASE_MS 1000U
|
||||||
@@ -75,6 +75,9 @@ enum
|
|||||||
KVMFR_AUDIO_SAMPLE_S16_LE = 1,
|
KVMFR_AUDIO_SAMPLE_S16_LE = 1,
|
||||||
/* Signed little-endian samples packed into exactly three bytes. */
|
/* Signed little-endian samples packed into exactly three bytes. */
|
||||||
KVMFR_AUDIO_SAMPLE_S24_LE = 2,
|
KVMFR_AUDIO_SAMPLE_S24_LE = 2,
|
||||||
|
KVMFR_AUDIO_SAMPLE_S32_LE = 3,
|
||||||
|
/* IEEE 754 little-endian floating-point samples. */
|
||||||
|
KVMFR_AUDIO_SAMPLE_F32_LE = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t KVMFRAudioSampleFormat;
|
typedef uint32_t KVMFRAudioSampleFormat;
|
||||||
@@ -83,6 +86,8 @@ enum
|
|||||||
{
|
{
|
||||||
KVMFR_AUDIO_SAMPLE_MASK_S16_LE = 1U << 0,
|
KVMFR_AUDIO_SAMPLE_MASK_S16_LE = 1U << 0,
|
||||||
KVMFR_AUDIO_SAMPLE_MASK_S24_LE = 1U << 1,
|
KVMFR_AUDIO_SAMPLE_MASK_S24_LE = 1U << 1,
|
||||||
|
KVMFR_AUDIO_SAMPLE_MASK_S32_LE = 1U << 2,
|
||||||
|
KVMFR_AUDIO_SAMPLE_MASK_F32_LE = 1U << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t KVMFRAudioSampleFormatFlags;
|
typedef uint32_t KVMFRAudioSampleFormatFlags;
|
||||||
|
|||||||
@@ -778,11 +778,39 @@ namespace
|
|||||||
_In_ const LGAudioBrokerFormat &format,
|
_In_ const LGAudioBrokerFormat &format,
|
||||||
_Out_opt_ FormatFingerprint *fingerprint)
|
_Out_opt_ FormatFingerprint *fingerprint)
|
||||||
{
|
{
|
||||||
|
if (format.reserved)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SampleFormat sampleFormat = SampleFormat::Unknown;
|
||||||
|
switch (format.sampleFormat)
|
||||||
|
{
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_S16_LE:
|
||||||
|
if (format.containerBits != 16 || format.validBits != 16)
|
||||||
|
return false;
|
||||||
|
sampleFormat = SampleFormat::S16LE;
|
||||||
|
break;
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_S24_LE:
|
||||||
|
if (format.containerBits != 24 || format.validBits != 24)
|
||||||
|
return false;
|
||||||
|
sampleFormat = SampleFormat::S24LE;
|
||||||
|
break;
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_S32_LE:
|
||||||
|
if (format.containerBits != 32 || format.validBits != 32)
|
||||||
|
return false;
|
||||||
|
sampleFormat = SampleFormat::S32LE;
|
||||||
|
break;
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_F32_LE:
|
||||||
|
if (format.containerBits != 32 || format.validBits != 32)
|
||||||
|
return false;
|
||||||
|
sampleFormat = SampleFormat::F32LE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!format.sampleRate ||
|
if (!format.sampleRate ||
|
||||||
format.sampleRate > kMaximumSampleRate ||
|
format.sampleRate > kMaximumSampleRate ||
|
||||||
!format.channels || format.channels > 8 ||
|
!format.channels || format.channels > 8 ||
|
||||||
(format.containerBits != 16 && format.containerBits != 24) ||
|
|
||||||
format.validBits != format.containerBits ||
|
|
||||||
format.blockAlign !=
|
format.blockAlign !=
|
||||||
format.channels * (format.containerBits / 8))
|
format.channels * (format.containerBits / 8))
|
||||||
{
|
{
|
||||||
@@ -791,6 +819,7 @@ namespace
|
|||||||
|
|
||||||
if (fingerprint)
|
if (fingerprint)
|
||||||
{
|
{
|
||||||
|
fingerprint->sampleFormat = sampleFormat;
|
||||||
fingerprint->sampleRate = format.sampleRate;
|
fingerprint->sampleRate = format.sampleRate;
|
||||||
fingerprint->channelMask = format.channelMask;
|
fingerprint->channelMask = format.channelMask;
|
||||||
fingerprint->channels = format.channels;
|
fingerprint->channels = format.channels;
|
||||||
@@ -805,12 +834,31 @@ namespace
|
|||||||
_In_ const FormatFingerprint &source,
|
_In_ const FormatFingerprint &source,
|
||||||
_Out_ LGAudioBrokerFormat *destination)
|
_Out_ LGAudioBrokerFormat *destination)
|
||||||
{
|
{
|
||||||
|
switch (source.sampleFormat)
|
||||||
|
{
|
||||||
|
case SampleFormat::S16LE:
|
||||||
|
destination->sampleFormat = LGAUDIO_BROKER_SAMPLE_S16_LE;
|
||||||
|
break;
|
||||||
|
case SampleFormat::S24LE:
|
||||||
|
destination->sampleFormat = LGAUDIO_BROKER_SAMPLE_S24_LE;
|
||||||
|
break;
|
||||||
|
case SampleFormat::S32LE:
|
||||||
|
destination->sampleFormat = LGAUDIO_BROKER_SAMPLE_S32_LE;
|
||||||
|
break;
|
||||||
|
case SampleFormat::F32LE:
|
||||||
|
destination->sampleFormat = LGAUDIO_BROKER_SAMPLE_F32_LE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
destination->sampleFormat = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
destination->sampleRate = source.sampleRate;
|
destination->sampleRate = source.sampleRate;
|
||||||
destination->channelMask = source.channelMask;
|
destination->channelMask = source.channelMask;
|
||||||
destination->channels = source.channels;
|
destination->channels = source.channels;
|
||||||
destination->containerBits = source.containerBits;
|
destination->containerBits = source.containerBits;
|
||||||
destination->validBits = source.validBits;
|
destination->validBits = source.validBits;
|
||||||
destination->blockAlign = source.blockAlign;
|
destination->blockAlign = source.blockAlign;
|
||||||
|
destination->reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 GetBrokerStreamState(_In_ KSSTATE state)
|
UINT32 GetBrokerStreamState(_In_ KSSTATE state)
|
||||||
|
|||||||
@@ -27,13 +27,19 @@ namespace LGAudio
|
|||||||
constexpr USHORT kExtensibleExtraSize = static_cast<USHORT>(
|
constexpr USHORT kExtensibleExtraSize = static_cast<USHORT>(
|
||||||
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX));
|
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
|
return
|
||||||
IsEqualGUIDAligned(format->MajorFormat,
|
IsEqualGUIDAligned(format->MajorFormat,
|
||||||
KSDATAFORMAT_TYPE_AUDIO) &&
|
KSDATAFORMAT_TYPE_AUDIO) &&
|
||||||
IsEqualGUIDAligned(format->SubFormat,
|
IsSupportedSubFormat(format->SubFormat) &&
|
||||||
KSDATAFORMAT_SUBTYPE_PCM) &&
|
|
||||||
IsEqualGUIDAligned(format->Specifier,
|
IsEqualGUIDAligned(format->Specifier,
|
||||||
KSDATAFORMAT_SPECIFIER_WAVEFORMATEX);
|
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(
|
bool AudioRangeContainsFormat(
|
||||||
_In_ const KSDATARANGE_AUDIO & range,
|
_In_ const KSDATARANGE_AUDIO & range,
|
||||||
_In_ const KSDATAFORMAT_WAVEFORMATEXTENSIBLE & format)
|
_In_ const KSDATAFORMAT_WAVEFORMATEXTENSIBLE & format)
|
||||||
@@ -104,6 +93,8 @@ namespace LGAudio
|
|||||||
const WAVEFORMATEX & wave = format.WaveFormatExt.Format;
|
const WAVEFORMATEX & wave = format.WaveFormatExt.Format;
|
||||||
|
|
||||||
return
|
return
|
||||||
|
IsEqualGUIDAligned(range.DataRange.SubFormat,
|
||||||
|
format.DataFormat.SubFormat) &&
|
||||||
range.MaximumChannels == wave.nChannels &&
|
range.MaximumChannels == wave.nChannels &&
|
||||||
range.MinimumBitsPerSample <= wave.wBitsPerSample &&
|
range.MinimumBitsPerSample <= wave.wBitsPerSample &&
|
||||||
range.MaximumBitsPerSample >= wave.wBitsPerSample &&
|
range.MaximumBitsPerSample >= wave.wBitsPerSample &&
|
||||||
@@ -118,16 +109,48 @@ namespace LGAudio
|
|||||||
const WAVEFORMATEX & wave = format.WaveFormatExt.Format;
|
const WAVEFORMATEX & wave = format.WaveFormatExt.Format;
|
||||||
|
|
||||||
return
|
return
|
||||||
|
IsEqualGUIDAligned(range.DataRange.SubFormat,
|
||||||
|
format.DataFormat.SubFormat) &&
|
||||||
range.MaximumChannels == wave.nChannels &&
|
range.MaximumChannels == wave.nChannels &&
|
||||||
range.MinimumBitsPerSample == wave.wBitsPerSample &&
|
range.MinimumBitsPerSample == wave.wBitsPerSample &&
|
||||||
range.MaximumBitsPerSample == wave.wBitsPerSample &&
|
range.MaximumBitsPerSample == wave.wBitsPerSample &&
|
||||||
range.MinimumSampleFrequency == wave.nSamplesPerSec &&
|
range.MinimumSampleFrequency == wave.nSamplesPerSec &&
|
||||||
range.MaximumSampleFrequency == 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( \
|
#define LG_AUDIO_FORMAT( \
|
||||||
sampleRate_, channels_, containerBits_, validBits_, mask_) \
|
sampleRate_, channels_, bits_, mask_, subType_) \
|
||||||
{ \
|
{ \
|
||||||
{ \
|
{ \
|
||||||
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), \
|
sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), \
|
||||||
@@ -135,7 +158,7 @@ namespace LGAudio
|
|||||||
0, \
|
0, \
|
||||||
0, \
|
0, \
|
||||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), \
|
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), \
|
||||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), \
|
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_##subType_), \
|
||||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) \
|
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) \
|
||||||
}, \
|
}, \
|
||||||
{ \
|
{ \
|
||||||
@@ -143,28 +166,56 @@ namespace LGAudio
|
|||||||
WAVE_FORMAT_EXTENSIBLE, \
|
WAVE_FORMAT_EXTENSIBLE, \
|
||||||
channels_, \
|
channels_, \
|
||||||
sampleRate_, \
|
sampleRate_, \
|
||||||
sampleRate_ * channels_ * (containerBits_ / 8), \
|
sampleRate_ * channels_ * (bits_ / 8), \
|
||||||
channels_ * (containerBits_ / 8), \
|
channels_ * (bits_ / 8), \
|
||||||
containerBits_, \
|
bits_, \
|
||||||
kExtensibleExtraSize \
|
kExtensibleExtraSize \
|
||||||
}, \
|
}, \
|
||||||
validBits_, \
|
bits_, \
|
||||||
mask_, \
|
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_) \
|
#define LG_RENDER_FORMATS(sampleRate_) \
|
||||||
LG_AUDIO_FORMAT(sampleRate_, 2, 16, 16, KSAUDIO_SPEAKER_STEREO), \
|
LG_RENDER_LAYOUTS(sampleRate_, 16, PCM), \
|
||||||
LG_AUDIO_FORMAT(sampleRate_, 2, 24, 24, KSAUDIO_SPEAKER_STEREO), \
|
LG_RENDER_LAYOUTS(sampleRate_, 24, PCM), \
|
||||||
LG_AUDIO_FORMAT(sampleRate_, 6, 24, 24, \
|
LG_RENDER_LAYOUTS(sampleRate_, 32, PCM), \
|
||||||
KSAUDIO_SPEAKER_5POINT1_SURROUND), \
|
LG_RENDER_LAYOUTS(sampleRate_, 32, IEEE_FLOAT)
|
||||||
LG_AUDIO_FORMAT(sampleRate_, 8, 24, 24, \
|
|
||||||
KSAUDIO_SPEAKER_7POINT1_SURROUND)
|
|
||||||
|
|
||||||
#define LG_CAPTURE_FORMATS(sampleRate_) \
|
#define LG_CAPTURE_FORMATS(sampleRate_) \
|
||||||
LG_AUDIO_FORMAT(sampleRate_, 1, 16, 16, KSAUDIO_SPEAKER_MONO), \
|
LG_CAPTURE_LAYOUTS(sampleRate_, 16, PCM), \
|
||||||
LG_RENDER_FORMATS(sampleRate_)
|
LG_CAPTURE_LAYOUTS(sampleRate_, 24, PCM), \
|
||||||
|
LG_CAPTURE_LAYOUTS(sampleRate_, 32, PCM), \
|
||||||
|
LG_CAPTURE_LAYOUTS(sampleRate_, 32, IEEE_FLOAT)
|
||||||
|
|
||||||
KSDATAFORMAT_WAVEFORMATEXTENSIBLE
|
KSDATAFORMAT_WAVEFORMATEXTENSIBLE
|
||||||
g_renderFormats[kRenderFormatCount] =
|
g_renderFormats[kRenderFormatCount] =
|
||||||
@@ -190,9 +241,11 @@ namespace LGAudio
|
|||||||
|
|
||||||
#undef LG_CAPTURE_FORMATS
|
#undef LG_CAPTURE_FORMATS
|
||||||
#undef LG_RENDER_FORMATS
|
#undef LG_RENDER_FORMATS
|
||||||
|
#undef LG_CAPTURE_LAYOUTS
|
||||||
|
#undef LG_RENDER_LAYOUTS
|
||||||
#undef LG_AUDIO_FORMAT
|
#undef LG_AUDIO_FORMAT
|
||||||
|
|
||||||
#define LG_AUDIO_RANGE(sampleRate_, channels_, containerBits_) \
|
#define LG_AUDIO_RANGE(sampleRate_, channels_, bits_, subType_) \
|
||||||
{ \
|
{ \
|
||||||
{ \
|
{ \
|
||||||
sizeof(KSDATARANGE_AUDIO), \
|
sizeof(KSDATARANGE_AUDIO), \
|
||||||
@@ -200,27 +253,43 @@ namespace LGAudio
|
|||||||
0, \
|
0, \
|
||||||
0, \
|
0, \
|
||||||
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), \
|
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), \
|
||||||
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), \
|
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_##subType_), \
|
||||||
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) \
|
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) \
|
||||||
}, \
|
}, \
|
||||||
channels_, \
|
channels_, \
|
||||||
containerBits_, \
|
bits_, \
|
||||||
containerBits_, \
|
bits_, \
|
||||||
sampleRate_, \
|
sampleRate_, \
|
||||||
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_) \
|
#define LG_RENDER_RANGES(sampleRate_) \
|
||||||
LG_AUDIO_RANGE(sampleRate_, 2, 16), \
|
LG_RENDER_LAYOUT_RANGES(sampleRate_, 16, PCM), \
|
||||||
LG_AUDIO_RANGE(sampleRate_, 2, 24), \
|
LG_RENDER_LAYOUT_RANGES(sampleRate_, 24, PCM), \
|
||||||
LG_AUDIO_RANGE(sampleRate_, 6, 24), \
|
LG_RENDER_LAYOUT_RANGES(sampleRate_, 32, PCM), \
|
||||||
LG_AUDIO_RANGE(sampleRate_, 8, 24)
|
LG_RENDER_LAYOUT_RANGES(sampleRate_, 32, IEEE_FLOAT)
|
||||||
|
|
||||||
#define LG_CAPTURE_RANGES(sampleRate_) \
|
#define LG_CAPTURE_RANGES(sampleRate_) \
|
||||||
LG_AUDIO_RANGE(sampleRate_, 1, 16), \
|
LG_CAPTURE_LAYOUT_RANGES(sampleRate_, 16, PCM), \
|
||||||
LG_RENDER_RANGES(sampleRate_)
|
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(48000),
|
||||||
LG_RENDER_RANGES(44100),
|
LG_RENDER_RANGES(44100),
|
||||||
@@ -230,7 +299,7 @@ namespace LGAudio
|
|||||||
LG_RENDER_RANGES(192000)
|
LG_RENDER_RANGES(192000)
|
||||||
};
|
};
|
||||||
|
|
||||||
KSDATARANGE_AUDIO g_captureDataRanges[kCaptureFormatCount] =
|
KSDATARANGE_AUDIO g_captureDataRanges[kCaptureDataRangeCount] =
|
||||||
{
|
{
|
||||||
LG_CAPTURE_RANGES(48000),
|
LG_CAPTURE_RANGES(48000),
|
||||||
LG_CAPTURE_RANGES(44100),
|
LG_CAPTURE_RANGES(44100),
|
||||||
@@ -242,43 +311,45 @@ namespace LGAudio
|
|||||||
|
|
||||||
#undef LG_CAPTURE_RANGES
|
#undef LG_CAPTURE_RANGES
|
||||||
#undef LG_RENDER_RANGES
|
#undef LG_RENDER_RANGES
|
||||||
|
#undef LG_CAPTURE_LAYOUT_RANGES
|
||||||
|
#undef LG_RENDER_LAYOUT_RANGES
|
||||||
#undef LG_AUDIO_RANGE
|
#undef LG_AUDIO_RANGE
|
||||||
|
|
||||||
#define LG_RENDER_RANGE_POINTERS(base_) \
|
#define LG_RANGE_POINTERS_5(ranges_, base_) \
|
||||||
(PKSDATARANGE)&g_renderDataRanges[(base_)], \
|
(PKSDATARANGE)&ranges_[(base_)], \
|
||||||
(PKSDATARANGE)&g_renderDataRanges[(base_) + 1], \
|
(PKSDATARANGE)&ranges_[(base_) + 1], \
|
||||||
(PKSDATARANGE)&g_renderDataRanges[(base_) + 2], \
|
(PKSDATARANGE)&ranges_[(base_) + 2], \
|
||||||
(PKSDATARANGE)&g_renderDataRanges[(base_) + 3]
|
(PKSDATARANGE)&ranges_[(base_) + 3], \
|
||||||
|
(PKSDATARANGE)&ranges_[(base_) + 4]
|
||||||
|
|
||||||
#define LG_CAPTURE_RANGE_POINTERS(base_) \
|
#define LG_RANGE_POINTERS(ranges_, base_) \
|
||||||
(PKSDATARANGE)&g_captureDataRanges[(base_)], \
|
LG_RANGE_POINTERS_5(ranges_, base_), \
|
||||||
(PKSDATARANGE)&g_captureDataRanges[(base_) + 1], \
|
LG_RANGE_POINTERS_5(ranges_, (base_) + 5), \
|
||||||
(PKSDATARANGE)&g_captureDataRanges[(base_) + 2], \
|
LG_RANGE_POINTERS_5(ranges_, (base_) + 10), \
|
||||||
(PKSDATARANGE)&g_captureDataRanges[(base_) + 3], \
|
LG_RANGE_POINTERS_5(ranges_, (base_) + 15)
|
||||||
(PKSDATARANGE)&g_captureDataRanges[(base_) + 4]
|
|
||||||
|
|
||||||
PKSDATARANGE g_renderDataRangePointers[kRenderFormatCount] =
|
PKSDATARANGE g_renderDataRangePointers[kRenderDataRangeCount] =
|
||||||
{
|
{
|
||||||
LG_RENDER_RANGE_POINTERS(0),
|
LG_RANGE_POINTERS(g_renderDataRanges, 0),
|
||||||
LG_RENDER_RANGE_POINTERS(4),
|
LG_RANGE_POINTERS(g_renderDataRanges, 20),
|
||||||
LG_RENDER_RANGE_POINTERS(8),
|
LG_RANGE_POINTERS(g_renderDataRanges, 40),
|
||||||
LG_RENDER_RANGE_POINTERS(12),
|
LG_RANGE_POINTERS(g_renderDataRanges, 60),
|
||||||
LG_RENDER_RANGE_POINTERS(16),
|
LG_RANGE_POINTERS(g_renderDataRanges, 80),
|
||||||
LG_RENDER_RANGE_POINTERS(20)
|
LG_RANGE_POINTERS(g_renderDataRanges, 100)
|
||||||
};
|
};
|
||||||
|
|
||||||
PKSDATARANGE g_captureDataRangePointers[kCaptureFormatCount] =
|
PKSDATARANGE g_captureDataRangePointers[kCaptureDataRangeCount] =
|
||||||
{
|
{
|
||||||
LG_CAPTURE_RANGE_POINTERS(0),
|
LG_RANGE_POINTERS(g_captureDataRanges, 0),
|
||||||
LG_CAPTURE_RANGE_POINTERS(5),
|
LG_RANGE_POINTERS(g_captureDataRanges, 20),
|
||||||
LG_CAPTURE_RANGE_POINTERS(10),
|
LG_RANGE_POINTERS(g_captureDataRanges, 40),
|
||||||
LG_CAPTURE_RANGE_POINTERS(15),
|
LG_RANGE_POINTERS(g_captureDataRanges, 60),
|
||||||
LG_CAPTURE_RANGE_POINTERS(20),
|
LG_RANGE_POINTERS(g_captureDataRanges, 80),
|
||||||
LG_CAPTURE_RANGE_POINTERS(25)
|
LG_RANGE_POINTERS(g_captureDataRanges, 100)
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef LG_CAPTURE_RANGE_POINTERS
|
#undef LG_RANGE_POINTERS
|
||||||
#undef LG_RENDER_RANGE_POINTERS
|
#undef LG_RANGE_POINTERS_5
|
||||||
|
|
||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
NTSTATUS ValidateFormat(
|
NTSTATUS ValidateFormat(
|
||||||
@@ -292,7 +363,7 @@ namespace LGAudio
|
|||||||
|
|
||||||
if (!dataFormat ||
|
if (!dataFormat ||
|
||||||
dataFormat->FormatSize < sizeof(KSDATAFORMAT_WAVEFORMATEX) ||
|
dataFormat->FormatSize < sizeof(KSDATAFORMAT_WAVEFORMATEX) ||
|
||||||
!IsAudioPcmWaveFormat(dataFormat))
|
!IsAudioWaveFormat(dataFormat))
|
||||||
return STATUS_NO_MATCH;
|
return STATUS_NO_MATCH;
|
||||||
|
|
||||||
const WAVEFORMATEX * requested =
|
const WAVEFORMATEX * requested =
|
||||||
@@ -307,18 +378,29 @@ namespace LGAudio
|
|||||||
const KSDATAFORMAT_WAVEFORMATEXTENSIBLE & candidate = formats[i];
|
const KSDATAFORMAT_WAVEFORMATEXTENSIBLE & candidate = formats[i];
|
||||||
const WAVEFORMATEXTENSIBLE & candidateWave = candidate.WaveFormatExt;
|
const WAVEFORMATEXTENSIBLE & candidateWave = candidate.WaveFormatExt;
|
||||||
|
|
||||||
if (!WaveFormatCoreMatches(candidateWave.Format, *requested))
|
if (!IsEqualGUIDAligned(candidate.DataFormat.SubFormat,
|
||||||
|
dataFormat->SubFormat) ||
|
||||||
|
!WaveFormatCoreMatches(candidateWave.Format, *requested))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (requested->wFormatTag == WAVE_FORMAT_PCM)
|
if (requested->wFormatTag == WAVE_FORMAT_PCM)
|
||||||
{
|
{
|
||||||
// A stand-alone WAVEFORMATEX is unambiguous only for these legacy
|
if (!IsEqualGUIDAligned(candidateWave.SubFormat,
|
||||||
// mono/stereo, 16-bit formats.
|
KSDATAFORMAT_SUBTYPE_PCM) ||
|
||||||
if (candidateWave.Format.wBitsPerSample != 16 ||
|
candidateWave.Format.wBitsPerSample != 16 ||
|
||||||
candidateWave.Samples.wValidBitsPerSample != 16 ||
|
candidateWave.Samples.wValidBitsPerSample != 16 ||
|
||||||
candidateWave.Format.nChannels > 2)
|
candidateWave.Format.nChannels > 2)
|
||||||
continue;
|
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)
|
else if (requested->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
|
||||||
{
|
{
|
||||||
if (dataFormat->FormatSize <
|
if (dataFormat->FormatSize <
|
||||||
@@ -328,7 +410,9 @@ namespace LGAudio
|
|||||||
|
|
||||||
const WAVEFORMATEXTENSIBLE * requestedExtensible =
|
const WAVEFORMATEXTENSIBLE * requestedExtensible =
|
||||||
reinterpret_cast<const WAVEFORMATEXTENSIBLE *>(requested);
|
reinterpret_cast<const WAVEFORMATEXTENSIBLE *>(requested);
|
||||||
if (!ExtensibleFormatMatches(candidateWave, *requestedExtensible))
|
if (!IsEqualGUIDAligned(dataFormat->SubFormat,
|
||||||
|
requestedExtensible->SubFormat) ||
|
||||||
|
!ExtensibleFormatMatches(candidateWave, *requestedExtensible))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -359,8 +443,8 @@ namespace LGAudio
|
|||||||
|
|
||||||
if (clientDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO) ||
|
if (clientDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO) ||
|
||||||
driverDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO) ||
|
driverDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO) ||
|
||||||
!IsAudioPcmWaveFormat(clientDataRange) ||
|
!IsAudioWaveFormat(clientDataRange) ||
|
||||||
!IsAudioPcmWaveFormat(driverDataRange))
|
!IsAudioWaveFormat(driverDataRange))
|
||||||
return STATUS_NO_MATCH;
|
return STATUS_NO_MATCH;
|
||||||
|
|
||||||
const KSDATARANGE_AUDIO & client =
|
const KSDATARANGE_AUDIO & client =
|
||||||
@@ -369,20 +453,13 @@ namespace LGAudio
|
|||||||
*reinterpret_cast<const KSDATARANGE_AUDIO *>(driverDataRange);
|
*reinterpret_cast<const KSDATARANGE_AUDIO *>(driverDataRange);
|
||||||
|
|
||||||
KSDATAFORMAT_WAVEFORMATEXTENSIBLE * formats;
|
KSDATAFORMAT_WAVEFORMATEXTENSIBLE * formats;
|
||||||
KSDATARANGE_AUDIO * ranges;
|
|
||||||
ULONG formatCount;
|
ULONG formatCount;
|
||||||
ULONG rangeCount;
|
|
||||||
GetFormatList(endpoint, &formats, &formatCount);
|
GetFormatList(endpoint, &formats, &formatCount);
|
||||||
GetDataRangeList(endpoint, &ranges, &rangeCount);
|
|
||||||
|
|
||||||
if (formatCount != rangeCount)
|
|
||||||
return STATUS_INTERNAL_ERROR;
|
|
||||||
|
|
||||||
const KSDATAFORMAT_WAVEFORMATEXTENSIBLE * selected = nullptr;
|
const KSDATAFORMAT_WAVEFORMATEXTENSIBLE * selected = nullptr;
|
||||||
for (ULONG i = 0; i < formatCount; ++i)
|
for (ULONG i = 0; i < formatCount; ++i)
|
||||||
{
|
{
|
||||||
if (!DataRangeIdentifiesFormat(driver, formats[i]) ||
|
if (!DataRangeIdentifiesFormat(driver, formats[i]) ||
|
||||||
!DataRangeIdentifiesFormat(ranges[i], formats[i]) ||
|
|
||||||
!AudioRangeContainsFormat(client, formats[i]))
|
!AudioRangeContainsFormat(client, formats[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -417,6 +494,7 @@ namespace LGAudio
|
|||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
const WAVEFORMATEXTENSIBLE & wave = dataFormat->WaveFormatExt;
|
const WAVEFORMATEXTENSIBLE & wave = dataFormat->WaveFormatExt;
|
||||||
|
const SampleFormat sampleFormat = GetSampleFormat(wave);
|
||||||
if (wave.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE ||
|
if (wave.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE ||
|
||||||
wave.Format.cbSize < kExtensibleExtraSize ||
|
wave.Format.cbSize < kExtensibleExtraSize ||
|
||||||
wave.Format.nChannels == 0 ||
|
wave.Format.nChannels == 0 ||
|
||||||
@@ -425,11 +503,13 @@ namespace LGAudio
|
|||||||
wave.Samples.wValidBitsPerSample == 0 ||
|
wave.Samples.wValidBitsPerSample == 0 ||
|
||||||
wave.Samples.wValidBitsPerSample >
|
wave.Samples.wValidBitsPerSample >
|
||||||
wave.Format.wBitsPerSample ||
|
wave.Format.wBitsPerSample ||
|
||||||
!IsAudioPcmWaveFormat(&dataFormat->DataFormat) ||
|
!IsAudioWaveFormat(&dataFormat->DataFormat) ||
|
||||||
!IsEqualGUIDAligned(wave.SubFormat,
|
!IsEqualGUIDAligned(dataFormat->DataFormat.SubFormat,
|
||||||
KSDATAFORMAT_SUBTYPE_PCM))
|
wave.SubFormat) ||
|
||||||
|
sampleFormat == SampleFormat::Unknown)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
fingerprint->sampleFormat = sampleFormat;
|
||||||
fingerprint->sampleRate = wave.Format.nSamplesPerSec;
|
fingerprint->sampleRate = wave.Format.nSamplesPerSec;
|
||||||
fingerprint->channelMask = wave.dwChannelMask;
|
fingerprint->channelMask = wave.dwChannelMask;
|
||||||
fingerprint->channels = wave.Format.nChannels;
|
fingerprint->channels = wave.Format.nChannels;
|
||||||
@@ -445,6 +525,7 @@ namespace LGAudio
|
|||||||
_In_ const FormatFingerprint & right)
|
_In_ const FormatFingerprint & right)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
left.sampleFormat == right.sampleFormat &&
|
||||||
left.sampleRate == right.sampleRate &&
|
left.sampleRate == right.sampleRate &&
|
||||||
left.channelMask == right.channelMask &&
|
left.channelMask == right.channelMask &&
|
||||||
left.channels == right.channels &&
|
left.channels == right.channels &&
|
||||||
|
|||||||
@@ -26,6 +26,15 @@
|
|||||||
|
|
||||||
namespace LGAudio
|
namespace LGAudio
|
||||||
{
|
{
|
||||||
|
enum class SampleFormat : ULONG
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
S16LE = 1,
|
||||||
|
S24LE = 2,
|
||||||
|
S32LE = 3,
|
||||||
|
F32LE = 4
|
||||||
|
};
|
||||||
|
|
||||||
enum class EndpointKind : UCHAR
|
enum class EndpointKind : UCHAR
|
||||||
{
|
{
|
||||||
Render,
|
Render,
|
||||||
@@ -34,6 +43,7 @@ namespace LGAudio
|
|||||||
|
|
||||||
struct FormatFingerprint
|
struct FormatFingerprint
|
||||||
{
|
{
|
||||||
|
SampleFormat sampleFormat;
|
||||||
ULONG sampleRate;
|
ULONG sampleRate;
|
||||||
ULONG channelMask;
|
ULONG channelMask;
|
||||||
USHORT channels;
|
USHORT channels;
|
||||||
@@ -44,15 +54,21 @@ namespace LGAudio
|
|||||||
|
|
||||||
constexpr ULONG kSampleRate = 48000;
|
constexpr ULONG kSampleRate = 48000;
|
||||||
constexpr ULONG kSampleRateCount = 6;
|
constexpr ULONG kSampleRateCount = 6;
|
||||||
constexpr ULONG kRenderFormatsPerRate = 4;
|
constexpr ULONG kRenderFormatsPerRate = 24;
|
||||||
constexpr ULONG kCaptureFormatsPerRate = 5;
|
constexpr ULONG kCaptureFormatsPerRate = 24;
|
||||||
|
constexpr ULONG kRenderDataRangesPerRate = 20;
|
||||||
|
constexpr ULONG kCaptureDataRangesPerRate = 20;
|
||||||
constexpr ULONG kRenderFormatCount =
|
constexpr ULONG kRenderFormatCount =
|
||||||
kSampleRateCount * kRenderFormatsPerRate;
|
kSampleRateCount * kRenderFormatsPerRate;
|
||||||
constexpr ULONG kCaptureFormatCount =
|
constexpr ULONG kCaptureFormatCount =
|
||||||
kSampleRateCount * kCaptureFormatsPerRate;
|
kSampleRateCount * kCaptureFormatsPerRate;
|
||||||
|
constexpr ULONG kRenderDataRangeCount =
|
||||||
|
kSampleRateCount * kRenderDataRangesPerRate;
|
||||||
|
constexpr ULONG kCaptureDataRangeCount =
|
||||||
|
kSampleRateCount * kCaptureDataRangesPerRate;
|
||||||
constexpr ULONG kMaximumSampleRate = 192000;
|
constexpr ULONG kMaximumSampleRate = 192000;
|
||||||
constexpr ULONG kMaximumBlockAlign =
|
constexpr ULONG kMaximumBlockAlign =
|
||||||
8 * 3;
|
8 * 4;
|
||||||
constexpr ULONG kMaximumBytesPerSecond =
|
constexpr ULONG kMaximumBytesPerSecond =
|
||||||
kMaximumSampleRate * kMaximumBlockAlign;
|
kMaximumSampleRate * kMaximumBlockAlign;
|
||||||
|
|
||||||
@@ -61,11 +77,11 @@ namespace LGAudio
|
|||||||
extern KSDATAFORMAT_WAVEFORMATEXTENSIBLE
|
extern KSDATAFORMAT_WAVEFORMATEXTENSIBLE
|
||||||
g_captureFormats[kCaptureFormatCount];
|
g_captureFormats[kCaptureFormatCount];
|
||||||
|
|
||||||
extern KSDATARANGE_AUDIO g_renderDataRanges[kRenderFormatCount];
|
extern KSDATARANGE_AUDIO g_renderDataRanges[kRenderDataRangeCount];
|
||||||
extern KSDATARANGE_AUDIO g_captureDataRanges[kCaptureFormatCount];
|
extern KSDATARANGE_AUDIO g_captureDataRanges[kCaptureDataRangeCount];
|
||||||
|
|
||||||
extern PKSDATARANGE g_renderDataRangePointers[kRenderFormatCount];
|
extern PKSDATARANGE g_renderDataRangePointers[kRenderDataRangeCount];
|
||||||
extern PKSDATARANGE g_captureDataRangePointers[kCaptureFormatCount];
|
extern PKSDATARANGE g_captureDataRangePointers[kCaptureDataRangeCount];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate an instantiated WaveRT format against the endpoint's exact
|
* Validate an instantiated WaveRT format against the endpoint's exact
|
||||||
@@ -106,6 +122,7 @@ namespace LGAudio
|
|||||||
// The rest of the driver uses these as its shared, unqualified audio types.
|
// The rest of the driver uses these as its shared, unqualified audio types.
|
||||||
using LGAudio::EndpointKind;
|
using LGAudio::EndpointKind;
|
||||||
using LGAudio::FormatFingerprint;
|
using LGAudio::FormatFingerprint;
|
||||||
|
using LGAudio::SampleFormat;
|
||||||
using LGAudio::EqualFormatFingerprint;
|
using LGAudio::EqualFormatFingerprint;
|
||||||
using LGAudio::GetFormatFingerprint;
|
using LGAudio::GetFormatFingerprint;
|
||||||
using LGAudio::SelectFormatIntersection;
|
using LGAudio::SelectFormatIntersection;
|
||||||
@@ -117,9 +134,11 @@ using LGAudio::g_renderDataRangePointers;
|
|||||||
using LGAudio::g_renderDataRanges;
|
using LGAudio::g_renderDataRanges;
|
||||||
using LGAudio::g_renderFormats;
|
using LGAudio::g_renderFormats;
|
||||||
using LGAudio::kCaptureFormatCount;
|
using LGAudio::kCaptureFormatCount;
|
||||||
|
using LGAudio::kCaptureDataRangeCount;
|
||||||
using LGAudio::kMaximumBlockAlign;
|
using LGAudio::kMaximumBlockAlign;
|
||||||
using LGAudio::kMaximumBytesPerSecond;
|
using LGAudio::kMaximumBytesPerSecond;
|
||||||
using LGAudio::kMaximumSampleRate;
|
using LGAudio::kMaximumSampleRate;
|
||||||
using LGAudio::kRenderFormatCount;
|
using LGAudio::kRenderFormatCount;
|
||||||
|
using LGAudio::kRenderDataRangeCount;
|
||||||
using LGAudio::kSampleRate;
|
using LGAudio::kSampleRate;
|
||||||
using LGAudio::kSampleRateCount;
|
using LGAudio::kSampleRateCount;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ PCPIN_DESCRIPTOR g_RenderWavePins[] =
|
|||||||
{
|
{
|
||||||
0, nullptr,
|
0, nullptr,
|
||||||
0, nullptr,
|
0, nullptr,
|
||||||
kRenderFormatCount, g_renderDataRangePointers,
|
kRenderDataRangeCount, g_renderDataRangePointers,
|
||||||
KSPIN_DATAFLOW_IN,
|
KSPIN_DATAFLOW_IN,
|
||||||
KSPIN_COMMUNICATION_SINK,
|
KSPIN_COMMUNICATION_SINK,
|
||||||
&KSCATEGORY_AUDIO,
|
&KSCATEGORY_AUDIO,
|
||||||
@@ -115,7 +115,7 @@ PCPIN_DESCRIPTOR g_CaptureWavePins[] =
|
|||||||
{
|
{
|
||||||
0, nullptr,
|
0, nullptr,
|
||||||
0, nullptr,
|
0, nullptr,
|
||||||
kCaptureFormatCount, g_captureDataRangePointers,
|
kCaptureDataRangeCount, g_captureDataRangePointers,
|
||||||
KSPIN_DATAFLOW_OUT,
|
KSPIN_DATAFLOW_OUT,
|
||||||
KSPIN_COMMUNICATION_SINK,
|
KSPIN_COMMUNICATION_SINK,
|
||||||
&KSCATEGORY_AUDIO,
|
&KSCATEGORY_AUDIO,
|
||||||
@@ -284,8 +284,8 @@ NTSTATUS CMiniportWaveRT::NewStream(
|
|||||||
if (InterlockedCompareExchange(&m_streamOpen, 1, 0) != 0)
|
if (InterlockedCompareExchange(&m_streamOpen, 1, 0) != 0)
|
||||||
return STATUS_DEVICE_BUSY;
|
return STATUS_DEVICE_BUSY;
|
||||||
|
|
||||||
CMiniportWaveRTStream *newStream =
|
CWS *newStream =
|
||||||
new(NonPagedPoolNx, LGAUDIO_POOL_TAG) CMiniportWaveRTStream(
|
new(NonPagedPoolNx, LGAUDIO_POOL_TAG) CWS(
|
||||||
this, m_adapter, portStream, m_kind);
|
this, m_adapter, portStream, m_kind);
|
||||||
if (!newStream)
|
if (!newStream)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ ULONGLONG FramesToQpcTicks(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CMiniportWaveRTStream::CMiniportWaveRTStream(
|
CWS::CWS(
|
||||||
_In_ CMiniportWaveRT *miniport,
|
_In_ CMiniportWaveRT *miniport,
|
||||||
_In_ CAudioAdapter *adapter,
|
_In_ CAudioAdapter *adapter,
|
||||||
_In_ PPORTWAVERTSTREAM portStream,
|
_In_ PPORTWAVERTSTREAM portStream,
|
||||||
@@ -177,7 +177,7 @@ CMiniportWaveRTStream::CMiniportWaveRTStream(
|
|||||||
KeInitializeSpinLock(&m_positionLock);
|
KeInitializeSpinLock(&m_positionLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMiniportWaveRTStream::~CMiniportWaveRTStream()
|
CWS::~CWS()
|
||||||
{
|
{
|
||||||
SetState(KSSTATE_STOP);
|
SetState(KSSTATE_STOP);
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ CMiniportWaveRTStream::~CMiniportWaveRTStream()
|
|||||||
m_miniport->Release();
|
m_miniport->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::Initialize(
|
NTSTATUS CWS::Initialize(
|
||||||
_In_ const KSDATAFORMAT_WAVEFORMATEXTENSIBLE *format)
|
_In_ const KSDATAFORMAT_WAVEFORMATEXTENSIBLE *format)
|
||||||
{
|
{
|
||||||
if (!format)
|
if (!format)
|
||||||
@@ -221,7 +221,7 @@ NTSTATUS CMiniportWaveRTStream::Initialize(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::QueryInterface(
|
NTSTATUS CWS::QueryInterface(
|
||||||
_In_ REFIID interfaceId,
|
_In_ REFIID interfaceId,
|
||||||
_COM_Outptr_ void **object)
|
_COM_Outptr_ void **object)
|
||||||
{
|
{
|
||||||
@@ -254,12 +254,12 @@ NTSTATUS CMiniportWaveRTStream::QueryInterface(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG CMiniportWaveRTStream::AddRef()
|
ULONG CWS::AddRef()
|
||||||
{
|
{
|
||||||
return static_cast<ULONG>(InterlockedIncrement(&m_refCount));
|
return static_cast<ULONG>(InterlockedIncrement(&m_refCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG CMiniportWaveRTStream::Release()
|
ULONG CWS::Release()
|
||||||
{
|
{
|
||||||
const LONG count = InterlockedDecrement(&m_refCount);
|
const LONG count = InterlockedDecrement(&m_refCount);
|
||||||
if (!count)
|
if (!count)
|
||||||
@@ -267,7 +267,7 @@ ULONG CMiniportWaveRTStream::Release()
|
|||||||
return static_cast<ULONG>(count);
|
return static_cast<ULONG>(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::SetFormat(
|
NTSTATUS CWS::SetFormat(
|
||||||
_In_ PKSDATAFORMAT dataFormat)
|
_In_ PKSDATAFORMAT dataFormat)
|
||||||
{
|
{
|
||||||
if (!dataFormat)
|
if (!dataFormat)
|
||||||
@@ -301,7 +301,7 @@ NTSTATUS CMiniportWaveRTStream::SetFormat(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::SetState(_In_ KSSTATE state)
|
NTSTATUS CWS::SetState(_In_ KSSTATE state)
|
||||||
{
|
{
|
||||||
if (state < KSSTATE_STOP || state > KSSTATE_RUN)
|
if (state < KSSTATE_STOP || state > KSSTATE_RUN)
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
@@ -394,7 +394,7 @@ NTSTATUS CMiniportWaveRTStream::SetState(_In_ KSSTATE state)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::GetPosition(
|
NTSTATUS CWS::GetPosition(
|
||||||
_Out_ PKSAUDIO_POSITION position)
|
_Out_ PKSAUDIO_POSITION position)
|
||||||
{
|
{
|
||||||
if (!position)
|
if (!position)
|
||||||
@@ -418,7 +418,7 @@ NTSTATUS CMiniportWaveRTStream::GetPosition(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::AllocateAudioBuffer(
|
NTSTATUS CWS::AllocateAudioBuffer(
|
||||||
_In_ ULONG requestedSize,
|
_In_ ULONG requestedSize,
|
||||||
_Out_ PMDL *audioBufferMdl,
|
_Out_ PMDL *audioBufferMdl,
|
||||||
_Out_ ULONG *actualSize,
|
_Out_ ULONG *actualSize,
|
||||||
@@ -429,7 +429,7 @@ NTSTATUS CMiniportWaveRTStream::AllocateAudioBuffer(
|
|||||||
offsetFromFirstPage, cacheType);
|
offsetFromFirstPage, cacheType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::FreeAudioBuffer(
|
void CWS::FreeAudioBuffer(
|
||||||
_In_opt_ PMDL audioBufferMdl,
|
_In_opt_ PMDL audioBufferMdl,
|
||||||
_In_ ULONG bufferSize)
|
_In_ ULONG bufferSize)
|
||||||
{
|
{
|
||||||
@@ -437,14 +437,14 @@ void CMiniportWaveRTStream::FreeAudioBuffer(
|
|||||||
FreeBuffer(audioBufferMdl);
|
FreeBuffer(audioBufferMdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::GetHWLatency(
|
void CWS::GetHWLatency(
|
||||||
_Out_ PKSRTAUDIO_HWLATENCY latency)
|
_Out_ PKSRTAUDIO_HWLATENCY latency)
|
||||||
{
|
{
|
||||||
if (latency)
|
if (latency)
|
||||||
RtlZeroMemory(latency, sizeof(*latency));
|
RtlZeroMemory(latency, sizeof(*latency));
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::GetPositionRegister(
|
NTSTATUS CWS::GetPositionRegister(
|
||||||
_Out_ PKSRTAUDIO_HWREGISTER positionRegister)
|
_Out_ PKSRTAUDIO_HWREGISTER positionRegister)
|
||||||
{
|
{
|
||||||
if (positionRegister)
|
if (positionRegister)
|
||||||
@@ -452,7 +452,7 @@ NTSTATUS CMiniportWaveRTStream::GetPositionRegister(
|
|||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::GetClockRegister(
|
NTSTATUS CWS::GetClockRegister(
|
||||||
_Out_ PKSRTAUDIO_HWREGISTER clockRegister)
|
_Out_ PKSRTAUDIO_HWREGISTER clockRegister)
|
||||||
{
|
{
|
||||||
if (clockRegister)
|
if (clockRegister)
|
||||||
@@ -460,7 +460,7 @@ NTSTATUS CMiniportWaveRTStream::GetClockRegister(
|
|||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::AllocateBufferWithNotification(
|
NTSTATUS CWS::AllocateBufferWithNotification(
|
||||||
_In_ ULONG notificationCount,
|
_In_ ULONG notificationCount,
|
||||||
_In_ ULONG requestedSize,
|
_In_ ULONG requestedSize,
|
||||||
_Out_ PMDL *audioBufferMdl,
|
_Out_ PMDL *audioBufferMdl,
|
||||||
@@ -475,7 +475,7 @@ NTSTATUS CMiniportWaveRTStream::AllocateBufferWithNotification(
|
|||||||
actualSize, offsetFromFirstPage, cacheType);
|
actualSize, offsetFromFirstPage, cacheType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::FreeBufferWithNotification(
|
void CWS::FreeBufferWithNotification(
|
||||||
_In_ PMDL audioBufferMdl,
|
_In_ PMDL audioBufferMdl,
|
||||||
_In_ ULONG bufferSize)
|
_In_ ULONG bufferSize)
|
||||||
{
|
{
|
||||||
@@ -483,7 +483,7 @@ void CMiniportWaveRTStream::FreeBufferWithNotification(
|
|||||||
FreeBuffer(audioBufferMdl);
|
FreeBuffer(audioBufferMdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::RegisterNotificationEvent(
|
NTSTATUS CWS::RegisterNotificationEvent(
|
||||||
_In_ PKEVENT notificationEvent)
|
_In_ PKEVENT notificationEvent)
|
||||||
{
|
{
|
||||||
if (!notificationEvent)
|
if (!notificationEvent)
|
||||||
@@ -511,7 +511,7 @@ NTSTATUS CMiniportWaveRTStream::RegisterNotificationEvent(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::UnregisterNotificationEvent(
|
NTSTATUS CWS::UnregisterNotificationEvent(
|
||||||
_In_ PKEVENT notificationEvent)
|
_In_ PKEVENT notificationEvent)
|
||||||
{
|
{
|
||||||
if (!notificationEvent)
|
if (!notificationEvent)
|
||||||
@@ -535,7 +535,7 @@ NTSTATUS CMiniportWaveRTStream::UnregisterNotificationEvent(
|
|||||||
return STATUS_NOT_FOUND;
|
return STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::GetReadPacket(
|
NTSTATUS CWS::GetReadPacket(
|
||||||
_Out_ ULONG *packetNumber,
|
_Out_ ULONG *packetNumber,
|
||||||
_Out_ DWORD *flags,
|
_Out_ DWORD *flags,
|
||||||
_Out_ ULONG64 *performanceCounterValue,
|
_Out_ ULONG64 *performanceCounterValue,
|
||||||
@@ -597,7 +597,7 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::SetWritePacket(
|
NTSTATUS CWS::SetWritePacket(
|
||||||
_In_ ULONG packetNumber,
|
_In_ ULONG packetNumber,
|
||||||
_In_ DWORD flags,
|
_In_ DWORD flags,
|
||||||
_In_ ULONG eosPacketLength)
|
_In_ ULONG eosPacketLength)
|
||||||
@@ -669,7 +669,7 @@ NTSTATUS CMiniportWaveRTStream::SetWritePacket(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition(
|
NTSTATUS CWS::GetOutputStreamPresentationPosition(
|
||||||
_Out_ KSAUDIO_PRESENTATION_POSITION *position)
|
_Out_ KSAUDIO_PRESENTATION_POSITION *position)
|
||||||
{
|
{
|
||||||
if (m_kind != EndpointKind::Render || !position)
|
if (m_kind != EndpointKind::Render || !position)
|
||||||
@@ -710,7 +710,7 @@ NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::GetPacketCount(
|
NTSTATUS CWS::GetPacketCount(
|
||||||
_Out_ ULONG *packetCount)
|
_Out_ ULONG *packetCount)
|
||||||
{
|
{
|
||||||
if (m_kind != EndpointKind::Render || !packetCount)
|
if (m_kind != EndpointKind::Render || !packetCount)
|
||||||
@@ -732,7 +732,7 @@ NTSTATUS CMiniportWaveRTStream::GetPacketCount(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS CMiniportWaveRTStream::AllocateBuffer(
|
NTSTATUS CWS::AllocateBuffer(
|
||||||
_In_ ULONG notificationCount,
|
_In_ ULONG notificationCount,
|
||||||
_In_ ULONG requestedSize,
|
_In_ ULONG requestedSize,
|
||||||
_Out_ PMDL *audioBufferMdl,
|
_Out_ PMDL *audioBufferMdl,
|
||||||
@@ -824,7 +824,7 @@ NTSTATUS CMiniportWaveRTStream::AllocateBuffer(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::FreeBuffer(_In_opt_ PMDL audioBufferMdl)
|
void CWS::FreeBuffer(_In_opt_ PMDL audioBufferMdl)
|
||||||
{
|
{
|
||||||
if (!audioBufferMdl)
|
if (!audioBufferMdl)
|
||||||
return;
|
return;
|
||||||
@@ -856,13 +856,13 @@ void CMiniportWaveRTStream::FreeBuffer(_In_opt_ PMDL audioBufferMdl)
|
|||||||
m_portStream->FreePagesFromMdl(mdl);
|
m_portStream->FreePagesFromMdl(mdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::StopTimer()
|
void CWS::StopTimer()
|
||||||
{
|
{
|
||||||
if (m_timer)
|
if (m_timer)
|
||||||
ExCancelTimer(m_timer, nullptr);
|
ExCancelTimer(m_timer, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::ArmTimerLocked()
|
void CWS::ArmTimerLocked()
|
||||||
{
|
{
|
||||||
if (!m_timer || m_state != KSSTATE_RUN || !m_notificationCount ||
|
if (!m_timer || m_state != KSSTATE_RUN || !m_notificationCount ||
|
||||||
!m_packetSize || !m_clockFrequency || !m_qpcFrequency ||
|
!m_packetSize || !m_clockFrequency || !m_qpcFrequency ||
|
||||||
@@ -927,7 +927,7 @@ void CMiniportWaveRTStream::ArmTimerLocked()
|
|||||||
ExSetTimer(m_timer, -static_cast<LONGLONG>(dueTime), 0, nullptr);
|
ExSetTimer(m_timer, -static_cast<LONGLONG>(dueTime), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::AdvanceLocked(
|
void CWS::AdvanceLocked(
|
||||||
_In_ const AudioClockSnapshot &clock)
|
_In_ const AudioClockSnapshot &clock)
|
||||||
{
|
{
|
||||||
if (m_state != KSSTATE_RUN || !m_buffer || !m_bufferSize ||
|
if (m_state != KSSTATE_RUN || !m_buffer || !m_bufferSize ||
|
||||||
@@ -986,7 +986,7 @@ void CMiniportWaveRTStream::AdvanceLocked(
|
|||||||
AdvanceEventPacketsLocked(clock);
|
AdvanceEventPacketsLocked(clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::AdvanceEventPacketsLocked(
|
void CWS::AdvanceEventPacketsLocked(
|
||||||
_In_ const AudioClockSnapshot &clock)
|
_In_ const AudioClockSnapshot &clock)
|
||||||
{
|
{
|
||||||
if (!m_packetSize)
|
if (!m_packetSize)
|
||||||
@@ -1080,7 +1080,7 @@ void CMiniportWaveRTStream::AdvanceEventPacketsLocked(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMiniportWaveRTStream::RenderPacketCommittedLocked(
|
bool CWS::RenderPacketCommittedLocked(
|
||||||
_In_ ULONGLONG position) const
|
_In_ ULONGLONG position) const
|
||||||
{
|
{
|
||||||
if (m_kind != EndpointKind::Render || !m_notificationCount ||
|
if (m_kind != EndpointKind::Render || !m_notificationCount ||
|
||||||
@@ -1091,7 +1091,7 @@ bool CMiniportWaveRTStream::RenderPacketCommittedLocked(
|
|||||||
return static_cast<LONG>(m_lastWritePacket - packet) >= 0;
|
return static_cast<LONG>(m_lastWritePacket - packet) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::PublishRenderFramesLocked()
|
void CWS::PublishRenderFramesLocked()
|
||||||
{
|
{
|
||||||
if (m_kind != EndpointKind::Render || !m_notificationCount ||
|
if (m_kind != EndpointKind::Render || !m_notificationCount ||
|
||||||
!m_packetSize || !m_renderPublicationSliceBytes || !m_bufferSize)
|
!m_packetSize || !m_renderPublicationSliceBytes || !m_bufferSize)
|
||||||
@@ -1133,7 +1133,7 @@ void CMiniportWaveRTStream::PublishRenderFramesLocked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::UpdatePresentationQpcLocked(
|
void CWS::UpdatePresentationQpcLocked(
|
||||||
_In_ const AudioClockSnapshot &clock)
|
_In_ const AudioClockSnapshot &clock)
|
||||||
{
|
{
|
||||||
const ULONG blockAlign =
|
const ULONG blockAlign =
|
||||||
@@ -1161,7 +1161,7 @@ void CMiniportWaveRTStream::UpdatePresentationQpcLocked(
|
|||||||
clock.QpcPosition - ticksSinceBoundary : 0;
|
clock.QpcPosition - ticksSinceBoundary : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::TransferFramesLocked(
|
void CWS::TransferFramesLocked(
|
||||||
_In_ ULONGLONG bytes,
|
_In_ ULONGLONG bytes,
|
||||||
_In_ bool transferRender)
|
_In_ bool transferRender)
|
||||||
{
|
{
|
||||||
@@ -1233,19 +1233,19 @@ void CMiniportWaveRTStream::TransferFramesLocked(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::SignalNotificationsLocked()
|
void CWS::SignalNotificationsLocked()
|
||||||
{
|
{
|
||||||
for (ULONG i = 0; i < m_notificationEventCount; ++i)
|
for (ULONG i = 0; i < m_notificationEventCount; ++i)
|
||||||
KeSetEvent(m_notificationEvents[i], IO_NO_INCREMENT, FALSE);
|
KeSetEvent(m_notificationEvents[i], IO_NO_INCREMENT, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniportWaveRTStream::TimerCallback(
|
void CWS::TimerCallback(
|
||||||
_In_ PEX_TIMER timer,
|
_In_ PEX_TIMER timer,
|
||||||
_In_opt_ void *context)
|
_In_opt_ void *context)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(timer);
|
UNREFERENCED_PARAMETER(timer);
|
||||||
|
|
||||||
auto *stream = static_cast<CMiniportWaveRTStream *>(context);
|
auto *stream = static_cast<CWS *>(context);
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -26,18 +26,18 @@
|
|||||||
|
|
||||||
class CMiniportWaveRT;
|
class CMiniportWaveRT;
|
||||||
|
|
||||||
class CMiniportWaveRTStream final :
|
class CWS final :
|
||||||
public IMiniportWaveRTStreamNotification,
|
public IMiniportWaveRTStreamNotification,
|
||||||
public IMiniportWaveRTInputStream,
|
public IMiniportWaveRTInputStream,
|
||||||
public IMiniportWaveRTOutputStream
|
public IMiniportWaveRTOutputStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CMiniportWaveRTStream(
|
CWS(
|
||||||
_In_ CMiniportWaveRT *miniport,
|
_In_ CMiniportWaveRT *miniport,
|
||||||
_In_ CAudioAdapter *adapter,
|
_In_ CAudioAdapter *adapter,
|
||||||
_In_ PPORTWAVERTSTREAM portStream,
|
_In_ PPORTWAVERTSTREAM portStream,
|
||||||
_In_ EndpointKind kind);
|
_In_ EndpointKind kind);
|
||||||
~CMiniportWaveRTStream();
|
~CWS();
|
||||||
|
|
||||||
NTSTATUS Initialize(
|
NTSTATUS Initialize(
|
||||||
_In_ const KSDATAFORMAT_WAVEFORMATEXTENSIBLE *format);
|
_In_ const KSDATAFORMAT_WAVEFORMATEXTENSIBLE *format);
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ namespace LGAudio
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr ULONG kRingPoolTag = 'rAGL';
|
constexpr ULONG kRingPoolTag = 'rAGL';
|
||||||
|
// LCM of every supported channel-count and sample-width block alignment.
|
||||||
|
constexpr ULONG kRingBufferAlignment = 288;
|
||||||
|
|
||||||
ULONG MinUlong(_In_ ULONG left, _In_ ULONG right)
|
ULONG MinUlong(_In_ ULONG left, _In_ ULONG right)
|
||||||
{
|
{
|
||||||
@@ -56,8 +58,8 @@ namespace LGAudio
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
constexpr ULONG capacity =
|
constexpr ULONG capacity =
|
||||||
(kMaximumBytesPerSecond + kMaximumBlockAlign - 1) /
|
(kMaximumBytesPerSecond + kRingBufferAlignment - 1) /
|
||||||
kMaximumBlockAlign * kMaximumBlockAlign;
|
kRingBufferAlignment * kRingBufferAlignment;
|
||||||
|
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4996) // Required for pre-2004 Windows 10 releases.
|
#pragma warning(disable:4996) // Required for pre-2004 Windows 10 releases.
|
||||||
@@ -110,7 +112,8 @@ namespace LGAudio
|
|||||||
NTSTATUS CAudioRingBuffer::Configure(
|
NTSTATUS CAudioRingBuffer::Configure(
|
||||||
_In_ const FormatFingerprint & format)
|
_In_ const FormatFingerprint & format)
|
||||||
{
|
{
|
||||||
if (format.sampleRate == 0 ||
|
if (format.sampleFormat == SampleFormat::Unknown ||
|
||||||
|
format.sampleRate == 0 ||
|
||||||
format.channels == 0 ||
|
format.channels == 0 ||
|
||||||
format.containerBits == 0 ||
|
format.containerBits == 0 ||
|
||||||
(format.containerBits % 8) != 0 ||
|
(format.containerBits % 8) != 0 ||
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ static const GUID LGAUDIO_BROKER_DEVICE_CLASS_GUID =
|
|||||||
{ 0x98f877f1, 0x73d6, 0x4429,
|
{ 0x98f877f1, 0x73d6, 0x4429,
|
||||||
{ 0xb4, 0x90, 0x28, 0xc5, 0x30, 0xd2, 0x38, 0xcd } };
|
{ 0xb4, 0x90, 0x28, 0xc5, 0x30, 0xd2, 0x38, 0xcd } };
|
||||||
|
|
||||||
static constexpr UINT32 LGAUDIO_BROKER_ABI_VERSION = 1U;
|
static constexpr UINT32 LGAUDIO_BROKER_ABI_VERSION = 2U;
|
||||||
// The transfer limits in LGAudioBrokerCaps exclude the packet header.
|
// The transfer limits in LGAudioBrokerCaps exclude the packet header.
|
||||||
static constexpr UINT32 LGAUDIO_BROKER_MAX_PAYLOAD_BYTES = 64U * 1024U;
|
static constexpr UINT32 LGAUDIO_BROKER_MAX_PAYLOAD_BYTES = 64U * 1024U;
|
||||||
|
|
||||||
@@ -87,6 +87,14 @@ enum LGAudioBrokerPacketFlag : UINT32
|
|||||||
LGAUDIO_BROKER_PACKET_DISCONTINUITY = 1U << 0
|
LGAUDIO_BROKER_PACKET_DISCONTINUITY = 1U << 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LGAudioBrokerSampleFormat : UINT32
|
||||||
|
{
|
||||||
|
LGAUDIO_BROKER_SAMPLE_S16_LE = 1,
|
||||||
|
LGAUDIO_BROKER_SAMPLE_S24_LE = 2,
|
||||||
|
LGAUDIO_BROKER_SAMPLE_S32_LE = 3,
|
||||||
|
LGAUDIO_BROKER_SAMPLE_F32_LE = 4
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_QUERY_CAPS =
|
static constexpr UINT32 IOCTL_LGAUDIO_BROKER_QUERY_CAPS =
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED,
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED,
|
||||||
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
|
FILE_READ_ACCESS | FILE_WRITE_ACCESS);
|
||||||
@@ -116,12 +124,14 @@ struct LGAudioBrokerHeader
|
|||||||
|
|
||||||
struct LGAudioBrokerFormat
|
struct LGAudioBrokerFormat
|
||||||
{
|
{
|
||||||
|
UINT32 sampleFormat;
|
||||||
UINT32 sampleRate;
|
UINT32 sampleRate;
|
||||||
UINT32 channelMask;
|
UINT32 channelMask;
|
||||||
UINT16 channels;
|
UINT16 channels;
|
||||||
UINT16 containerBits;
|
UINT16 containerBits;
|
||||||
UINT16 validBits;
|
UINT16 validBits;
|
||||||
UINT16 blockAlign;
|
UINT16 blockAlign;
|
||||||
|
UINT32 reserved;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LGAudioBrokerStreamState
|
struct LGAudioBrokerStreamState
|
||||||
@@ -230,15 +240,15 @@ struct LGAudioBrokerClockControl
|
|||||||
|
|
||||||
static_assert(sizeof(LGAudioBrokerHeader) == 8,
|
static_assert(sizeof(LGAudioBrokerHeader) == 8,
|
||||||
"LGAudio broker header layout changed");
|
"LGAudio broker header layout changed");
|
||||||
static_assert(sizeof(LGAudioBrokerFormat) == 16,
|
static_assert(sizeof(LGAudioBrokerFormat) == 24,
|
||||||
"LGAudio broker format layout changed");
|
"LGAudio broker format layout changed");
|
||||||
static_assert(sizeof(LGAudioBrokerStreamState) == 32,
|
static_assert(sizeof(LGAudioBrokerStreamState) == 40,
|
||||||
"LGAudio broker stream-state layout changed");
|
"LGAudio broker stream-state layout changed");
|
||||||
static_assert(sizeof(LGAudioBrokerPacketHeader) == 80,
|
static_assert(sizeof(LGAudioBrokerPacketHeader) == 88,
|
||||||
"LGAudio broker packet layout changed");
|
"LGAudio broker packet layout changed");
|
||||||
static_assert(sizeof(LGAudioBrokerCaps) == 64,
|
static_assert(sizeof(LGAudioBrokerCaps) == 64,
|
||||||
"LGAudio broker capabilities layout changed");
|
"LGAudio broker capabilities layout changed");
|
||||||
static_assert(sizeof(LGAudioBrokerState) == 104,
|
static_assert(sizeof(LGAudioBrokerState) == 120,
|
||||||
"LGAudio broker state layout changed");
|
"LGAudio broker state layout changed");
|
||||||
static_assert(sizeof(LGAudioBrokerBind) == 48,
|
static_assert(sizeof(LGAudioBrokerBind) == 48,
|
||||||
"LGAudio broker binding layout changed");
|
"LGAudio broker binding layout changed");
|
||||||
@@ -247,5 +257,5 @@ static_assert(sizeof(LGAudioBrokerStats) == 160,
|
|||||||
static_assert(sizeof(LGAudioBrokerClockControl) == 64,
|
static_assert(sizeof(LGAudioBrokerClockControl) == 64,
|
||||||
"LGAudio broker clock-control layout changed");
|
"LGAudio broker clock-control layout changed");
|
||||||
static_assert(LGAUDIO_BROKER_MAX_PAYLOAD_BYTES >=
|
static_assert(LGAUDIO_BROKER_MAX_PAYLOAD_BYTES >=
|
||||||
(192000U / 100U) * 8U * 3U,
|
(192000U / 100U) * 8U * 4U,
|
||||||
"LGAudio broker payload cannot hold 10 ms at the maximum format");
|
"LGAudio broker payload cannot hold 10 ms at the maximum format");
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ namespace
|
|||||||
|
|
||||||
bool SameFormat(const AudioFormat& left, const AudioFormat& right)
|
bool SameFormat(const AudioFormat& left, const AudioFormat& right)
|
||||||
{
|
{
|
||||||
return left.sampleRate == right.sampleRate &&
|
return left.sampleFormat == right.sampleFormat &&
|
||||||
|
left.sampleRate == right.sampleRate &&
|
||||||
left.channelMask == right.channelMask &&
|
left.channelMask == right.channelMask &&
|
||||||
left.channels == right.channels &&
|
left.channels == right.channels &&
|
||||||
left.containerBits == right.containerBits &&
|
left.containerBits == right.containerBits &&
|
||||||
@@ -78,6 +79,22 @@ namespace
|
|||||||
left.blockAlign == right.blockAlign;
|
left.blockAlign == right.blockAlign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ValidSampleFormat(const AudioFormat& format)
|
||||||
|
{
|
||||||
|
switch (format.sampleFormat)
|
||||||
|
{
|
||||||
|
case AudioSampleFormat::S16_LE:
|
||||||
|
return format.containerBits == 16 && format.validBits == 16;
|
||||||
|
case AudioSampleFormat::S24_LE:
|
||||||
|
return format.containerBits == 24 && format.validBits == 24;
|
||||||
|
case AudioSampleFormat::S32_LE:
|
||||||
|
case AudioSampleFormat::F32_LE:
|
||||||
|
return format.containerBits == 32 && format.validBits == 32;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ValidFormat(const AudioFormat& format)
|
bool ValidFormat(const AudioFormat& format)
|
||||||
{
|
{
|
||||||
return format.sampleRate && format.sampleRate <= 192000 &&
|
return format.sampleRate && format.sampleRate <= 192000 &&
|
||||||
@@ -85,15 +102,52 @@ namespace
|
|||||||
format.channelMask &&
|
format.channelMask &&
|
||||||
!(format.channelMask & ~AUDIO_CHANNEL_POSITION_MASK) &&
|
!(format.channelMask & ~AUDIO_CHANNEL_POSITION_MASK) &&
|
||||||
PopCount(format.channelMask) == format.channels &&
|
PopCount(format.channelMask) == format.channels &&
|
||||||
(format.containerBits == 16 || format.containerBits == 24) &&
|
ValidSampleFormat(format) &&
|
||||||
format.validBits == format.containerBits &&
|
|
||||||
format.blockAlign ==
|
format.blockAlign ==
|
||||||
format.channels * (format.containerBits / 8);
|
format.channels * (format.containerBits / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioSampleFormat BrokerSampleFormat(uint32_t source)
|
||||||
|
{
|
||||||
|
switch (source)
|
||||||
|
{
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_S16_LE:
|
||||||
|
return AudioSampleFormat::S16_LE;
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_S24_LE:
|
||||||
|
return AudioSampleFormat::S24_LE;
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_S32_LE:
|
||||||
|
return AudioSampleFormat::S32_LE;
|
||||||
|
case LGAUDIO_BROKER_SAMPLE_F32_LE:
|
||||||
|
return AudioSampleFormat::F32_LE;
|
||||||
|
default:
|
||||||
|
return AudioSampleFormat::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DeviceSampleFormat(AudioSampleFormat source)
|
||||||
|
{
|
||||||
|
switch (source)
|
||||||
|
{
|
||||||
|
case AudioSampleFormat::S16_LE:
|
||||||
|
return LGAUDIO_BROKER_SAMPLE_S16_LE;
|
||||||
|
case AudioSampleFormat::S24_LE:
|
||||||
|
return LGAUDIO_BROKER_SAMPLE_S24_LE;
|
||||||
|
case AudioSampleFormat::S32_LE:
|
||||||
|
return LGAUDIO_BROKER_SAMPLE_S32_LE;
|
||||||
|
case AudioSampleFormat::F32_LE:
|
||||||
|
return LGAUDIO_BROKER_SAMPLE_F32_LE;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AudioFormat BrokerFormat(const LGAudioBrokerFormat& source)
|
AudioFormat BrokerFormat(const LGAudioBrokerFormat& source)
|
||||||
{
|
{
|
||||||
AudioFormat result;
|
AudioFormat result;
|
||||||
|
if (source.reserved)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result.sampleFormat = BrokerSampleFormat(source.sampleFormat);
|
||||||
result.sampleRate = source.sampleRate;
|
result.sampleRate = source.sampleRate;
|
||||||
result.channelMask = source.channelMask;
|
result.channelMask = source.channelMask;
|
||||||
result.channels = source.channels;
|
result.channels = source.channels;
|
||||||
@@ -106,6 +160,7 @@ namespace
|
|||||||
LGAudioBrokerFormat DeviceFormat(const AudioFormat& source)
|
LGAudioBrokerFormat DeviceFormat(const AudioFormat& source)
|
||||||
{
|
{
|
||||||
LGAudioBrokerFormat result = {};
|
LGAudioBrokerFormat result = {};
|
||||||
|
result.sampleFormat = DeviceSampleFormat(source.sampleFormat);
|
||||||
result.sampleRate = source.sampleRate;
|
result.sampleRate = source.sampleRate;
|
||||||
result.channelMask = source.channelMask;
|
result.channelMask = source.channelMask;
|
||||||
result.channels = source.channels;
|
result.channels = source.channels;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
static constexpr uint32_t AUDIO_MAX_CHANNELS = 18;
|
static constexpr uint32_t AUDIO_MAX_CHANNELS = 18;
|
||||||
static constexpr uint32_t AUDIO_STREAM_MAX_CHANNELS = 8;
|
static constexpr uint32_t AUDIO_STREAM_MAX_CHANNELS = 8;
|
||||||
static constexpr uint32_t AUDIO_MAX_FRAMES_PER_PACKET = 2048;
|
static constexpr uint32_t AUDIO_MAX_FRAMES_PER_PACKET = 2048;
|
||||||
static constexpr uint32_t AUDIO_MAX_BYTES_PER_SAMPLE = 3;
|
static constexpr uint32_t AUDIO_MAX_BYTES_PER_SAMPLE = 4;
|
||||||
static constexpr uint32_t AUDIO_MAX_PCM_BYTES =
|
static constexpr uint32_t AUDIO_MAX_PCM_BYTES =
|
||||||
AUDIO_MAX_FRAMES_PER_PACKET * AUDIO_STREAM_MAX_CHANNELS *
|
AUDIO_MAX_FRAMES_PER_PACKET * AUDIO_STREAM_MAX_CHANNELS *
|
||||||
AUDIO_MAX_BYTES_PER_SAMPLE;
|
AUDIO_MAX_BYTES_PER_SAMPLE;
|
||||||
@@ -54,6 +54,15 @@ enum AudioClockFlag : uint32_t
|
|||||||
AUDIO_CLOCK_DISCONTINUITY = 1U << 2,
|
AUDIO_CLOCK_DISCONTINUITY = 1U << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class AudioSampleFormat : uint32_t
|
||||||
|
{
|
||||||
|
UNKNOWN = 0,
|
||||||
|
S16_LE = 1,
|
||||||
|
S24_LE = 2,
|
||||||
|
S32_LE = 3,
|
||||||
|
F32_LE = 4,
|
||||||
|
};
|
||||||
|
|
||||||
enum class AudioStreamState : uint32_t
|
enum class AudioStreamState : uint32_t
|
||||||
{
|
{
|
||||||
UNAVAILABLE,
|
UNAVAILABLE,
|
||||||
@@ -75,12 +84,13 @@ enum class AudioResult
|
|||||||
|
|
||||||
struct AudioFormat
|
struct AudioFormat
|
||||||
{
|
{
|
||||||
uint32_t sampleRate = 0;
|
AudioSampleFormat sampleFormat = AudioSampleFormat::UNKNOWN;
|
||||||
uint32_t channelMask = 0;
|
uint32_t sampleRate = 0;
|
||||||
uint16_t channels = 0;
|
uint32_t channelMask = 0;
|
||||||
uint16_t containerBits = 0;
|
uint16_t channels = 0;
|
||||||
uint16_t validBits = 0;
|
uint16_t containerBits = 0;
|
||||||
uint16_t blockAlign = 0;
|
uint16_t validBits = 0;
|
||||||
|
uint16_t blockAlign = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AudioStreamStatus
|
struct AudioStreamStatus
|
||||||
|
|||||||
@@ -50,6 +50,16 @@ namespace
|
|||||||
"audio packet limits differ");
|
"audio packet limits differ");
|
||||||
static_assert(AUDIO_MAX_PCM_BYTES == KVMFR_AUDIO_PCM_BYTES,
|
static_assert(AUDIO_MAX_PCM_BYTES == KVMFR_AUDIO_PCM_BYTES,
|
||||||
"audio PCM limits differ");
|
"audio PCM limits differ");
|
||||||
|
static_assert(
|
||||||
|
static_cast<uint32_t>(AudioSampleFormat::S16_LE) ==
|
||||||
|
KVMFR_AUDIO_SAMPLE_S16_LE &&
|
||||||
|
static_cast<uint32_t>(AudioSampleFormat::S24_LE) ==
|
||||||
|
KVMFR_AUDIO_SAMPLE_S24_LE &&
|
||||||
|
static_cast<uint32_t>(AudioSampleFormat::S32_LE) ==
|
||||||
|
KVMFR_AUDIO_SAMPLE_S32_LE &&
|
||||||
|
static_cast<uint32_t>(AudioSampleFormat::F32_LE) ==
|
||||||
|
KVMFR_AUDIO_SAMPLE_F32_LE,
|
||||||
|
"audio sample formats differ");
|
||||||
static_assert(static_cast<uint32_t>(AUDIO_CAP_PLAYBACK) ==
|
static_assert(static_cast<uint32_t>(AUDIO_CAP_PLAYBACK) ==
|
||||||
static_cast<uint32_t>(KVMFR_AUDIO_CAP_PLAYBACK) &&
|
static_cast<uint32_t>(KVMFR_AUDIO_CAP_PLAYBACK) &&
|
||||||
static_cast<uint32_t>(AUDIO_CAP_CAPTURE) ==
|
static_cast<uint32_t>(AUDIO_CAP_CAPTURE) ==
|
||||||
@@ -75,7 +85,7 @@ namespace
|
|||||||
KVMFR_AUDIO_MESSAGE_CLOCK_VALID |
|
KVMFR_AUDIO_MESSAGE_CLOCK_VALID |
|
||||||
KVMFR_AUDIO_MESSAGE_CLOCK_STABLE;
|
KVMFR_AUDIO_MESSAGE_CLOCK_STABLE;
|
||||||
constexpr size_t AUDIO_SHARED_MEMORY_PREFLIGHT =
|
constexpr size_t AUDIO_SHARED_MEMORY_PREFLIGHT =
|
||||||
2U * 1024U * 1024U;
|
3U * 1024U * 1024U;
|
||||||
|
|
||||||
bool ArmAudioPollTimer(HANDLE timer, uint32_t waitUs)
|
bool ArmAudioPollTimer(HANDLE timer, uint32_t waitUs)
|
||||||
{
|
{
|
||||||
@@ -122,7 +132,8 @@ CLGMPAudioTransport::~CLGMPAudioTransport()
|
|||||||
bool CLGMPAudioTransport::SameFormat(
|
bool CLGMPAudioTransport::SameFormat(
|
||||||
const AudioFormat& left, const AudioFormat& right)
|
const AudioFormat& left, const AudioFormat& right)
|
||||||
{
|
{
|
||||||
return left.sampleRate == right.sampleRate &&
|
return left.sampleFormat == right.sampleFormat &&
|
||||||
|
left.sampleRate == right.sampleRate &&
|
||||||
left.channelMask == right.channelMask &&
|
left.channelMask == right.channelMask &&
|
||||||
left.channels == right.channels &&
|
left.channels == right.channels &&
|
||||||
left.containerBits == right.containerBits &&
|
left.containerBits == right.containerBits &&
|
||||||
@@ -152,11 +163,29 @@ bool CLGMPAudioTransport::ValidFormat(const AudioFormat& format)
|
|||||||
ChannelCount(format.channelMask) != format.channels)
|
ChannelCount(format.channelMask) != format.channels)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const bool s16 = format.containerBits == 16 && format.validBits == 16;
|
bool validSampleFormat = false;
|
||||||
const bool s24 = format.containerBits == 24 && format.validBits == 24;
|
switch (format.sampleFormat)
|
||||||
|
{
|
||||||
|
case AudioSampleFormat::S16_LE:
|
||||||
|
validSampleFormat =
|
||||||
|
format.containerBits == 16 && format.validBits == 16;
|
||||||
|
break;
|
||||||
|
case AudioSampleFormat::S24_LE:
|
||||||
|
validSampleFormat =
|
||||||
|
format.containerBits == 24 && format.validBits == 24;
|
||||||
|
break;
|
||||||
|
case AudioSampleFormat::S32_LE:
|
||||||
|
case AudioSampleFormat::F32_LE:
|
||||||
|
validSampleFormat =
|
||||||
|
format.containerBits == 32 && format.validBits == 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const uint16_t bytes = static_cast<uint16_t>(
|
const uint16_t bytes = static_cast<uint16_t>(
|
||||||
format.channels * (format.containerBits / 8U));
|
format.channels * (format.containerBits / 8U));
|
||||||
return (s16 || s24) && format.blockAlign == bytes;
|
return validSampleFormat && format.blockAlign == bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
KVMFRAudioFormat CLGMPAudioTransport::WireFormat(
|
KVMFRAudioFormat CLGMPAudioTransport::WireFormat(
|
||||||
@@ -165,8 +194,8 @@ KVMFRAudioFormat CLGMPAudioTransport::WireFormat(
|
|||||||
KVMFRAudioFormat result = {};
|
KVMFRAudioFormat result = {};
|
||||||
result.version = KVMFR_AUDIO_FORMAT_VERSION;
|
result.version = KVMFR_AUDIO_FORMAT_VERSION;
|
||||||
result.size = sizeof(result);
|
result.size = sizeof(result);
|
||||||
result.sampleFormat = format.containerBits == 16 ?
|
result.sampleFormat =
|
||||||
KVMFR_AUDIO_SAMPLE_S16_LE : KVMFR_AUDIO_SAMPLE_S24_LE;
|
static_cast<uint32_t>(format.sampleFormat);
|
||||||
result.sampleRate = format.sampleRate;
|
result.sampleRate = format.sampleRate;
|
||||||
result.channelMask = format.channelMask;
|
result.channelMask = format.channelMask;
|
||||||
result.channelCount = format.channels;
|
result.channelCount = format.channels;
|
||||||
|
|||||||
Reference in New Issue
Block a user