From 12b3272d9e6b2810985516ebad0ce545e5601d59 Mon Sep 17 00:00:00 2001 From: Oleg Dubinskiy Date: Thu, 11 Apr 2024 11:59:14 +0200 Subject: [PATCH] [AUDIO] Implement support for WAVE_FORMAT_EXTENSIBLE audio format (#6686) [MMIXER] Implement hadling WAVE_FORMAT_EXTENSIBLE audio format Fix opening audio device error when trying to open it with WAVE_FORMAT_EXTENSIBLE format tag set in wFormatTag member of WAVEFORMATEX: - Pass additional data size from WAVEFORMATEX.cbSize to pin data format. - Append it to the whole size of pin data format (KSDATAFORMAT.FormatSize). - Set additional fields in WAVEFORMATEXTENSIBLE structure (data format, BPS and channel mask) when WAVE_FORMAT_EXTENSIBLE is used. They are used by our inbuilt Intel AC97 miniport driver at least. It simply fails when these members are not set. - Fix pin connect allocation size by appending an additional data size from WAVEFORMATEX.cbSize to KSPIN_CONNECT + KSDATAFORMAT + WAVEFORMATEX. This allows to proerly initialize additional extensible data and avoids kernel memory leakage when using extensible audio format. - Remove format tag check which allowed WAVE_FORMAT_PCM to be opened correctly. So now all possible audio formats can be opened properly at least (although it does not mean they may work correctly). This fixes the audio playback for all apps those are supporting extensible audio data and use it by default (e. g. AIMP 5.30, QMMP 0.12.17, all Chrome/Chromium-based browsers, GameDev Tycoon Demo game etc.). CORE-10907, CORE-14783 * [KS] Allow passing additional extensible audio data when extensible audio format is used - Append additional data size from WAVEFORMATEX.cbSize to pin connect size passed to KsCreatePin. If the tag is WAVE_FORMAT_PCM, then this member should always be zero. So in that case, no any additional data is passed to creation request, and the passed data size is correct for PCM too (KSDATAFORMAT + WAVEFORMATEX). This fixes audio playback in several apps those are supporting extensibble audio and use it by default (e. g. AIMP 5.30, QMMP 0.12.17, all Chrome/Chromium based browsers, GameDev Tycoon Demo game etc.). CORE-10907, CORE-14783. * [WDMAUD.DRV] Pass the correct additional data size to I/O control request Store a correct size of additional data in WAVEFORMATEX.cbSize when performing open of audio device, when WAVE_FORMAT_EXTENSIBLE audio format is used. It allows to properly open audio device with Legacy APIs enabled too. This fixes audio playback in several apps those are using extensible audio data (e. g. AIMP 5.30, QMMP 0.12.17, all Chrome/Chromium based browsers, GameDevTycoon Demo game etc.). CORE-10907, CORE-14783 --- dll/win32/wdmaud.drv/legacy.c | 4 ++-- drivers/ksfilter/ks/connectivity.c | 2 +- sdk/lib/drivers/sound/mmixer/wave.c | 34 +++++++++++++++++++---------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/dll/win32/wdmaud.drv/legacy.c b/dll/win32/wdmaud.drv/legacy.c index 00c9507341d8e..f1ada7cdd3b95 100644 --- a/dll/win32/wdmaud.drv/legacy.c +++ b/dll/win32/wdmaud.drv/legacy.c @@ -506,7 +506,7 @@ WdmAudSetWaveDeviceFormatByLegacy( ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); DeviceInfo.DeviceType = DeviceType; DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); //WaveFormat->cbSize; + DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize; DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag; #ifdef USERMODE_MIXER DeviceInfo.u.WaveFormatEx.nChannels = 2; @@ -546,7 +546,7 @@ WdmAudSetWaveDeviceFormatByLegacy( } /* store details */ - Instance->WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); + Instance->WaveFormatEx.cbSize = WaveFormat->cbSize; Instance->WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels); /* Store sound device handle instance handle */ diff --git a/drivers/ksfilter/ks/connectivity.c b/drivers/ksfilter/ks/connectivity.c index ba7db56d8b5c2..395d5b53d633f 100644 --- a/drivers/ksfilter/ks/connectivity.c +++ b/drivers/ksfilter/ks/connectivity.c @@ -43,7 +43,7 @@ KsCreatePin( PKSDATAFORMAT_WAVEFORMATEX Format = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1); if (Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) || - Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX)) + Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + Format->WaveFormatEx.cbSize) { ConnectSize += Format->DataFormat.FormatSize; } diff --git a/sdk/lib/drivers/sound/mmixer/wave.c b/sdk/lib/drivers/sound/mmixer/wave.c index e049ca485bd86..7c48f0bc82789 100644 --- a/sdk/lib/drivers/sound/mmixer/wave.c +++ b/sdk/lib/drivers/sound/mmixer/wave.c @@ -116,22 +116,40 @@ MMixerInitializeDataFormat( IN PKSDATAFORMAT_WAVEFORMATEX DataFormat, LPWAVEFORMATEX WaveFormatEx) { - DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag; DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels; DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec; DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign; DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec; DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample; - DataFormat->WaveFormatEx.cbSize = 0; - DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); + DataFormat->WaveFormatEx.cbSize = WaveFormatEx->cbSize; + DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + WaveFormatEx->cbSize; DataFormat->DataFormat.Flags = 0; DataFormat->DataFormat.Reserved = 0; DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; - DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; DataFormat->DataFormat.SampleSize = 4; + + /* Write additional fields for Extensible audio format */ + if (WaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + PWAVEFORMATEXTENSIBLE WaveFormatExt = (PWAVEFORMATEXTENSIBLE)&DataFormat->WaveFormatEx; + WaveFormatExt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + WaveFormatExt->Samples.wValidBitsPerSample = WaveFormatEx->wBitsPerSample; + if (WaveFormatEx->nChannels == 0) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; + else if (WaveFormatEx->nChannels == 1) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_MONO; + else if (WaveFormatEx->nChannels == 2) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_STEREO; + else if (WaveFormatEx->nChannels == 4) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_QUAD; + else if (WaveFormatEx->nChannels == 5) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; + else if (WaveFormatEx->nChannels == 7) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; + } } MIXER_STATUS @@ -232,7 +250,7 @@ MMixerOpenWavePin( return MM_STATUS_INVALID_PARAMETER; /* allocate pin connect */ - PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT_WAVEFORMATEX)); + PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT_WAVEFORMATEX) + WaveFormatEx->cbSize); if (!PinConnect) { /* no memory */ @@ -453,12 +471,6 @@ MMixerOpenWave( /* grab mixer list */ MixerList = (PMIXER_LIST)MixerContext->MixerContext; - if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM) - { - /* not implemented */ - return MM_STATUS_NOT_IMPLEMENTED; - } - /* find destination wave */ Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, bWaveIn, &WaveInfo); if (Status != MM_STATUS_SUCCESS)