diff options
| author | Daniel Rugerio <[email protected]> | 2019-06-28 16:08:54 -0700 |
|---|---|---|
| committer | Adonais Romero González <[email protected]> | 2019-06-28 16:08:54 -0700 |
| commit | 8ffcdad009e4d410f92fabc4e322a76a0be3a69d (patch) | |
| tree | 378b2d98a4210c61e2bc34f5b8959e87e4be5c6c | |
| parent | 75b2290f2a4ece68739d07135d352cdfec3a9e89 (diff) | |
Update audio samples (#387)
* Update SysVAD public sample.
* Add WaveTest public sample.
82 files changed, 8150 insertions, 1066 deletions
diff --git a/audio/sysvad/APO/DelayAPO/DelayAPO.h b/audio/sysvad/APO/DelayAPO/DelayAPO.h index e59fccf7..65ee98e5 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPO.h +++ b/audio/sysvad/APO/DelayAPO/DelayAPO.h @@ -136,6 +136,11 @@ public: STDMETHODIMP GetFormat(UINT nFormat, IAudioMediaType** ppFormat); STDMETHODIMP GetFormatRepresentation(UINT nFormat, _Outptr_ LPWSTR* ppwstrFormatRep); + // IAudioProcessingObject + STDMETHODIMP IsOutputFormatSupported(IAudioMediaType *pOppositeFormat, IAudioMediaType *pRequestedOutputFormat, IAudioMediaType **ppSupportedOutputFormat); + + STDMETHODIMP CheckCustomFormats(IAudioMediaType *pRequestedFormat); + public: LONG m_fEnableDelayMFX; GUID m_AudioProcessingMode; diff --git a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj index 5fc4b06a..ecdaf321 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj +++ b/audio/sysvad/APO/DelayAPO/DelayAPO.vcxproj @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> @@ -13,10 +9,6 @@ <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> @@ -89,15 +81,6 @@ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> @@ -107,15 +90,6 @@ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <OutDir>$(IntDir)</OutDir> @@ -135,15 +109,9 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>DelayAPO</TargetName> @@ -160,15 +128,9 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <TargetName>DelayAPO</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <TargetName>DelayAPO</TargetName> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetName>DelayAPO</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <TargetName>DelayAPO</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> @@ -199,24 +161,12 @@ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Link> <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <UseOfAtl>Dynamic</UseOfAtl> </PropertyGroup> @@ -232,15 +182,9 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <UseOfAtl>Dynamic</UseOfAtl> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <UseOfAtl>Dynamic</UseOfAtl> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <UseOfAtl>Dynamic</UseOfAtl> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> @@ -363,31 +307,6 @@ <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary> - </RuntimeLibrary> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> @@ -412,31 +331,6 @@ <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <ClCompile> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <RuntimeLibrary> - </RuntimeLibrary> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> - <ModuleDefinitionFile>DelayAPODll.def</ModuleDefinitionFile> - <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> - </Link> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="Delay.cpp" /> <ClCompile Include="DelayAPODll.cpp" /> diff --git a/audio/sysvad/APO/DelayAPO/DelayAPODll.cpp b/audio/sysvad/APO/DelayAPO/DelayAPODll.cpp index fe49a000..9b24637a 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPODll.cpp +++ b/audio/sysvad/APO/DelayAPO/DelayAPODll.cpp @@ -67,4 +67,4 @@ STDAPI DllCanUnloadNow(void) STDAPI DllGetClassObject(_In_ REFCLSID rclsid,_In_ REFIID riid, _Outptr_ LPVOID* ppv) { return _AtlModule.DllGetClassObject(rclsid, riid, ppv); -} +}
\ No newline at end of file diff --git a/audio/sysvad/APO/DelayAPO/DelayAPODll.def b/audio/sysvad/APO/DelayAPO/DelayAPODll.def index f4b6fcd9..3f3b0c5a 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPODll.def +++ b/audio/sysvad/APO/DelayAPO/DelayAPODll.def @@ -1,4 +1,4 @@ EXPORTS DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE + DllGetClassObject PRIVATE
\ No newline at end of file diff --git a/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp b/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp index 5f5ad2c6..8b53b42c 100644 --- a/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp +++ b/audio/sysvad/APO/DelayAPO/DelayAPOMFX.cpp @@ -905,8 +905,9 @@ DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_A CUSTOM_FORMAT_ITEM _rgCustomFormats[] = { {{ WAVE_FORMAT_EXTENSIBLE, 2, 44100, 176400, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #1 (really 44.1 KHz, 16-bit, stereo)"}, - {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #2 (really 48 KHz, 16-bit, stereo)"}, - {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_AC3}, L"Custom #3 (really 48 KHz AC-3)"} + {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #2 (really 48 KHz, 16-bit, stereo)"} + // The compressed AC3 format has been temporarily removed since the APO is not set up for compressed formats or EFXs yet. + // {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_AC3}, L"Custom #3 (really 48 KHz AC-3)"} }; #define _cCustomFormats (ARRAYSIZE(_rgCustomFormats)) @@ -1029,3 +1030,139 @@ STDMETHODIMP CDelayAPOMFX::GetFormatRepresentation Exit: return hr; } + +//------------------------------------------------------------------------- +// Description: +// +// Implementation of IAudioProcessingObject::IsOutputFormatSupported +// +// Parameters: +// +// pInputFormat - [in] A pointer to an IAudioMediaType interface. This parameter indicates the output format. This parameter must be set to NULL to indicate that the output format can be any type +// pRequestedOutputFormat - [in] A pointer to an IAudioMediaType interface. This parameter indicates the output format that is to be verified +// ppSupportedOutputFormat - [in] This parameter indicates the supported output format that is closest to the format to be verified +// +// Return values: +// +// S_OK Success +// S_FALSE The format of Input/output format pair is not supported. The ppSupportedOutPutFormat parameter returns a suggested new format +// APOERR_FORMAT_NOT_SUPPORTED The format is not supported. The value of ppSupportedOutputFormat does not change. +// E_POINTER Null pointer passed +// +// Remarks: +// +STDMETHODIMP CDelayAPOMFX::IsOutputFormatSupported +( + IAudioMediaType *pInputFormat, + IAudioMediaType *pRequestedOutputFormat, + IAudioMediaType **ppSupportedOutputFormat +) +{ + ASSERT_NONREALTIME(); + bool formatChanged = false; + HRESULT hResult; + UNCOMPRESSEDAUDIOFORMAT uncompOutputFormat; + IAudioMediaType *recommendedFormat = NULL; + + IF_TRUE_ACTION_JUMP((NULL == pRequestedOutputFormat) || (NULL == ppSupportedOutputFormat), hResult = E_POINTER, Exit); + *ppSupportedOutputFormat = NULL; + + // Initial comparison to make sure the requested format is valid and consistent with the input + // format. Because of the APO flags specified during creation, the samples per frame value will + // not be validated. + hResult = IsFormatTypeSupported(pInputFormat, pRequestedOutputFormat, &recommendedFormat, true); + IF_FAILED_JUMP(hResult, Exit); + + // Check to see if a custom format from the APO was used. + if (S_FALSE == hResult) + { + hResult = CheckCustomFormats(pRequestedOutputFormat); + + // If the output format is changed, make sure we track it for our return code. + if (S_FALSE == hResult) + { + formatChanged = true; + } + } + + // now retrieve the format that IsFormatTypeSupported decided on, building upon that by adding + // our channel count constraint. + hResult = recommendedFormat->GetUncompressedAudioFormat(&uncompOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + + // If the requested format exactly matched our requirements, + // just return it. + if (!formatChanged) + { + *ppSupportedOutputFormat = pRequestedOutputFormat; + (*ppSupportedOutputFormat)->AddRef(); + hResult = S_OK; + } + else // we're proposing something different, copy it and return S_FALSE + { + hResult = CreateAudioMediaTypeFromUncompressedAudioFormat(&uncompOutputFormat, ppSupportedOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + hResult = S_FALSE; + } + +Exit: + if (recommendedFormat) + { + recommendedFormat->Release(); + } + + return hResult; +} + +HRESULT CDelayAPOMFX::CheckCustomFormats(IAudioMediaType *pRequestedFormat) +{ + HRESULT hResult = S_OK; + + for (int i = 0; i < _cCustomFormats; i++) + { + hResult = S_OK; + const WAVEFORMATEX* waveFormat = pRequestedFormat->GetAudioFormat(); + + if (waveFormat->wFormatTag != _rgCustomFormats[i].wfxFmt.Format.wFormatTag) + { + hResult = S_FALSE; + } + + if (waveFormat->nChannels != _rgCustomFormats[i].wfxFmt.Format.nChannels) + { + hResult = S_FALSE; + } + + if (waveFormat->nSamplesPerSec != _rgCustomFormats[i].wfxFmt.Format.nSamplesPerSec) + { + hResult = S_FALSE; + } + + if (waveFormat->nAvgBytesPerSec != _rgCustomFormats[i].wfxFmt.Format.nAvgBytesPerSec) + { + hResult = S_FALSE; + } + + if (waveFormat->nBlockAlign != _rgCustomFormats[i].wfxFmt.Format.nBlockAlign) + { + hResult = S_FALSE; + } + + if (waveFormat->wBitsPerSample != _rgCustomFormats[i].wfxFmt.Format.wBitsPerSample) + { + hResult = S_FALSE; + } + + if (waveFormat->cbSize != _rgCustomFormats[i].wfxFmt.Format.cbSize) + { + hResult = S_FALSE; + } + + if (hResult == S_OK) + { + break; + } + } + + return hResult; +}
\ No newline at end of file diff --git a/audio/sysvad/APO/DelayAPO/makefile b/audio/sysvad/APO/DelayAPO/makefile deleted file mode 100644 index 593ab379..00000000 --- a/audio/sysvad/APO/DelayAPO/makefile +++ /dev/null @@ -1,34 +0,0 @@ -############################################################################# -# -# Copyright (c) Microsoft Corporation. -# All Rights Reserved. -# -############################################################################# - -## NT BUILD ENVIROMENT - -# -# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source -# file to this component. This file merely indirects to the real make file -# that is shared by all the components of NT. -# -!if defined(IA64) -!message This sample is not to be built for IA64 targets -!else - -!IF DEFINED(_NT_TARGET_VERSION) -#! IF $(_NT_TARGET_VERSION)>=0x501 -! IF $(_NT_TARGET_VERSION)>=0x600 -! INCLUDE $(NTMAKEENV)\makefile.def -! ELSE -# Only warn once per directory -! INCLUDE $(NTMAKEENV)\makefile.plt -! IF "$(BUILD_PASS)"=="PASS1" -! message BUILDMSG: Warning : Building the sample "$(MAKEDIR)" for downlevel build environments is temporarily disabled in WDK for Beta2. -! ENDIF -! ENDIF -!ELSE -! INCLUDE $(NTMAKEENV)\makefile.def -!ENDIF - -!endif diff --git a/audio/sysvad/APO/DelayAPO/sources b/audio/sysvad/APO/DelayAPO/sources deleted file mode 100644 index 355dc80f..00000000 --- a/audio/sysvad/APO/DelayAPO/sources +++ /dev/null @@ -1,12 +0,0 @@ -!include ..\sources.inc - -TARGETNAME=DelayAPO -DLLDEF=DelayAPODll.def - -SOURCES=DelayAPOInterface.idl \ - DelayAPOMFX.cpp \ - DelayAPOSFX.cpp \ - Delay.cpp \ - DelayAPODll.idl \ - DelayAPODll.rc \ - DelayAPODll.cpp \ diff --git a/audio/sysvad/APO/KWSApo/KWSApo.cpp b/audio/sysvad/APO/KWSApo/KWSApo.cpp new file mode 100644 index 00000000..d67eaca0 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApo.cpp @@ -0,0 +1,62 @@ +// +// KWSApo.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Implementation of ProcessBuffer +// +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include <audioenginebaseapo.h> +#include <baseaudioprocessingobject.h> +#include <resource.h> + +#include <float.h> + +#include "KWSApo.h" + +#pragma AVRT_CODE_BEGIN +void WriteSilence( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32Frames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ) +{ + ZeroMemory(pf32Frames, sizeof(FLOAT32) * u32FrameCount * u32SamplesPerFrame); +} +#pragma AVRT_CODE_END + +#pragma AVRT_CODE_BEGIN +void ProcessBuffer( + FLOAT32 *pf32OutputFrames, + const FLOAT32 *pf32InputFrames, + UINT32 u32ValidFrameCount, + INTERLEAVED_AUDIO_FORMAT_INFORMATION *formatInfo) +{ + UINT32 totalChannelCount = (formatInfo->PrimaryChannelCount + formatInfo->InterleavedChannelCount); + + ASSERT_REALTIME(); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); + ATLASSERT( IS_VALID_TYPED_WRITE_POINTER(pf32OutputFrames) ); + + // loop through samples + while (u32ValidFrameCount--) + { + // copy over the Primary channel data + for (UINT32 i = formatInfo->PrimaryChannelStartPosition; i < (formatInfo->PrimaryChannelStartPosition + formatInfo->PrimaryChannelCount); i++) + { + *pf32OutputFrames = *(pf32InputFrames + i); + pf32OutputFrames++; + } + + // step forward to the next frame, ignoring interleaved data + pf32InputFrames += (totalChannelCount); + } +} + +#pragma AVRT_CODE_END + diff --git a/audio/sysvad/APO/KWSApo/KWSApo.h b/audio/sysvad/APO/KWSApo/KWSApo.h new file mode 100644 index 00000000..38c3434e --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApo.h @@ -0,0 +1,134 @@ +// +// KWSApo.h -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Declaration of the CKWSApoEFX class. +// + +#pragma once + +#include <audioenginebaseapo.h> +#include <BaseAudioProcessingObject.h> +#include <KWSApoInterface.h> +#include <KWSApoDll.h> + +#include <commonmacros.h> +#include <devicetopology.h> + +_Analysis_mode_(_Analysis_code_type_user_driver_) + +#pragma AVRT_VTABLES_BEGIN +// KWS APO class - EFX +class CKWSApoEFX : + public CComObjectRootEx<CComMultiThreadModel>, + public CComCoClass<CKWSApoEFX, &CLSID_KWSApoEFX>, + public CBaseAudioProcessingObject, + public IMMNotificationClient, + public IAudioSystemEffects2, + public IKWSApoEFX +{ +public: + // constructor + CKWSApoEFX() + : CBaseAudioProcessingObject(sm_RegProperties) + { + } + + virtual ~CKWSApoEFX(); // destructor + +DECLARE_REGISTRY_RESOURCEID(IDR_KWSAPOEFX) + +BEGIN_COM_MAP(CKWSApoEFX) + COM_INTERFACE_ENTRY(IKWSApoEFX) + COM_INTERFACE_ENTRY(IAudioSystemEffects) + COM_INTERFACE_ENTRY(IAudioSystemEffects2) + COM_INTERFACE_ENTRY(IMMNotificationClient) + COM_INTERFACE_ENTRY(IAudioProcessingObjectRT) + COM_INTERFACE_ENTRY(IAudioProcessingObject) + COM_INTERFACE_ENTRY(IAudioProcessingObjectConfiguration) +END_COM_MAP() + +DECLARE_PROTECT_FINAL_CONSTRUCT() + +public: + STDMETHOD_(void, APOProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections); + + STDMETHOD(GetLatency)(HNSTIME* pTime); + + STDMETHOD(LockForProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections); + + STDMETHOD(Initialize)(UINT32 cbDataSize, BYTE* pbyData); + + // IAudioSystemEffects2 + STDMETHOD(GetEffectsList)(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event); + + // IAudioProcessingObject + STDMETHOD(IsInputFormatSupported)(IAudioMediaType *pOutputFormat, IAudioMediaType *pRequestedInputFormat, IAudioMediaType **ppSupportedInputFormat); + STDMETHOD(IsOutputFormatSupported)(IAudioMediaType *pInputFormat, IAudioMediaType *pRequestedOutputFormat, IAudioMediaType **ppSupportedOutputFormat); + STDMETHOD(GetInputChannelCount)(UINT32 *pu32ChannelCount); + + // IMMNotificationClient + STDMETHODIMP OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + UNREFERENCED_PARAMETER(dwNewState); + return S_OK; + } + STDMETHODIMP OnDeviceAdded(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDeviceRemoved(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) + { + UNREFERENCED_PARAMETER(flow); + UNREFERENCED_PARAMETER(role); + UNREFERENCED_PARAMETER(pwstrDefaultDeviceId); + return S_OK; + } + STDMETHODIMP OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + UNREFERENCED_PARAMETER(key); + return S_OK; + } + +public: + CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties; + CComPtr<IMMDeviceEnumerator> m_spEnumerator; + static const CRegAPOProperties<1> sm_RegProperties; // registration properties + INTERLEAVED_AUDIO_FORMAT_INFORMATION m_FormatInfo; +}; +#pragma AVRT_VTABLES_END + +OBJECT_ENTRY_AUTO(__uuidof(KWSApoEFX), CKWSApoEFX) + +// +// Declaration of the ProcessBuffer routine. +// +void ProcessBuffer( + FLOAT32 *pf32OutputFrames, + const FLOAT32 *pf32InputFrames, + UINT32 u32ValidFrameCount, + INTERLEAVED_AUDIO_FORMAT_INFORMATION *formatInfo); + +// +// Convenience methods +// + +void WriteSilence( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32Frames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ); + diff --git a/audio/sysvad/APO/KWSApo/KWSApo.png b/audio/sysvad/APO/KWSApo/KWSApo.png Binary files differnew file mode 100644 index 00000000..3a6e102a --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApo.png diff --git a/audio/sysvad/APO/KWSApo/KWSApo.vcxproj b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj new file mode 100644 index 00000000..2000bcf4 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj @@ -0,0 +1,355 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|ARM64"> + <Configuration>Debug</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM64"> + <Configuration>Release</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{47358AD6-A48A-465B-965F-0A66F8BDFE23}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <SupportsPackaging>false</SupportsPackaging> + <RequiresPackageProject>true</RequiresPackageProject> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{D5CCDCB1-348E-414E-BB0F-33C773760034}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>KWSApo</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <TargetName>KWSApo</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>KWSApo</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <TargetName>KWSApo</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>KWSApo</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>KWSApo</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary> + </RuntimeLibrary> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary> + </RuntimeLibrary> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="KWSApo.cpp" /> + <ClCompile Include="KWSApoDll.cpp" /> + <ClCompile Include="KWSApoEFX.cpp" /> + <Midl Include="KWSApoDll.idl" /> + <Midl Include="KWSApoInterface.idl" /> + <ResourceCompile Include="KWSApoDll.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project> diff --git a/audio/sysvad/APO/KWSApo/KWSApo.vcxproj.Filters b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj.Filters new file mode 100644 index 00000000..7ff54ea8 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApo.vcxproj.Filters @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{5f4ff11d-7a0b-4f75-9d79-744ae028cc53}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{bd103b81-05b2-440e-84e7-0723d7fe4109}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{a57b6b78-38ae-4348-ade3-0200e81a3dd7}</UniqueIdentifier> + </Filter> + <Filter Include="IDL Files"> + <Extensions>idl</Extensions> + <UniqueIdentifier>{c6318700-1bce-4812-92f1-160881e4c976}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <Midl Include="KWSApoDll.idl"> + <Filter>IDL Files</Filter> + </Midl> + <Midl Include="KWSApoInterface.idl"> + <Filter>IDL Files</Filter> + </Midl> + </ItemGroup> + <ItemGroup> + <ClInclude Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <None Include="*.rc;*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2"> + <Filter>Resource Files</Filter> + </None> + <None Include="*.cpp;*.def;*.bat;*.hpj;*.asmx"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/audio/sysvad/APO/KWSApo/KWSApoDll.cpp b/audio/sysvad/APO/KWSApo/KWSApoDll.cpp new file mode 100644 index 00000000..f8cbc95f --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoDll.cpp @@ -0,0 +1,71 @@ +// +// KWSApoDll.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Author: +// +// Description: +// +// KWSApoDll.cpp : Implementation of DLL Exports. + +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include "resource.h" +#include "KWSApoDll.h" +#include <KWSApo.h> + +#include <KWSApoDll_i.c> + + +//------------------------------------------------------------------------- +// Array of APO_REG_PROPERTIES structures implemented in this module. +// Each new APO implementation will be added to this array. +// +APO_REG_PROPERTIES const *gCoreAPOs[] = +{ + &CKWSApoEFX::sm_RegProperties.m_Properties +}; + +// {secret} +class CKWSApoDllModule : public CAtlDllModuleT< CKWSApoDllModule > +{ +public : + DECLARE_LIBID(LIBID_KWSApoDlllib) + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_KWSAPODLL, "{0A21D954-674A-4C09-806E-DB4FBE8F199C}") + +}; + +// {secret} +CKWSApoDllModule _AtlModule; + + +// {secret} +extern "C" BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID lpReserved) +{ + if (DLL_PROCESS_ATTACH == dwReason) + { + } + // do necessary cleanup only if the DLL is being unloaded dynamically + else if ((DLL_PROCESS_DETACH == dwReason) && (NULL == lpReserved)) + { + } + + return _AtlModule.DllMain(dwReason, lpReserved); +} + + +// {secret} +STDAPI DllCanUnloadNow(void) +{ + return _AtlModule.DllCanUnloadNow(); +} + + +// {secret} +STDAPI DllGetClassObject(_In_ REFCLSID rclsid,_In_ REFIID riid, _Outptr_ LPVOID* ppv) +{ + return _AtlModule.DllGetClassObject(rclsid, riid, ppv); +} diff --git a/audio/sysvad/APO/KWSApo/KWSApoDll.def b/audio/sysvad/APO/KWSApo/KWSApoDll.def new file mode 100644 index 00000000..3f3b0c5a --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoDll.def @@ -0,0 +1,4 @@ + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE
\ No newline at end of file diff --git a/audio/sysvad/APO/KWSApo/KWSApoDll.idl b/audio/sysvad/APO/KWSApo/KWSApoDll.idl new file mode 100644 index 00000000..086643d7 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoDll.idl @@ -0,0 +1,40 @@ +// +// KWSAPODll.idl -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Author: +// +// Description: +// +// KWSAPODll.idl : Definition of COM interfaces and coclasses for the DLL. + +import "oaidl.idl"; +import "ocidl.idl"; +import "KWSApoInterface.idl"; + +//------------------------------------------------------------------------- +// KWSApoDlllib +// +[ + uuid(E928E566-CBA7-4181-9B8B-8822E2BD28AB), + version(1.0) +] +library KWSApoDlllib +{ + importlib("stdole2.tlb"); + + // for KWS APO - EFX + [ + uuid(9D89F614-F9D6-40DD-9F21-5E69FA3981ED) + ] + coclass KWSApoEFX + { + interface IAudioProcessingObject; + interface IAudioProcessingObjectRT; + interface IAudioProcessingObjectConfiguration; + interface IMMNotificationClient; + interface IAudioSystemEffects; + [default] interface IKWSApoEFX; + }; + + +} diff --git a/audio/sysvad/APO/KWSApo/KWSApoDll.rc b/audio/sysvad/APO/KWSApo/KWSApoDll.rc new file mode 100644 index 00000000..9add8452 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoDll.rc @@ -0,0 +1,20 @@ +#if 0 +Copyright (c) Microsoft Corporation. All Rights Reserved +#endif + +#include "resource.h" +#include "winres.h" +#include <ntverp.h> +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "KWS APO" +#define VER_INTERNALNAME_STR "KWSApo" +#define VER_ORIGINALFILENAME_STR "KWSApo.Dll" +#include <Common.ver> + +IDR_KWSAPODLL REGISTRY "KWSApoDll.rgs" +IDR_KWSAPOEFX REGISTRY "KWSApoEFX.rgs" + +// ICON +IDI_EFFECT_ICON RCDATA "KWSApo.png" + diff --git a/audio/sysvad/APO/KWSApo/KWSApoDll.rgs b/audio/sysvad/APO/KWSApo/KWSApoDll.rgs new file mode 100644 index 00000000..b89d2a41 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoDll.rgs @@ -0,0 +1,11 @@ +HKCR +{ + NoRemove AppID + { + '%APPID%' = s 'KWSApoDll' + 'KWSApoDll.DLL' + { + val AppID = s '%APPID%' + } + } +} diff --git a/audio/sysvad/APO/KWSApo/KWSApoEfx.cpp b/audio/sysvad/APO/KWSApo/KWSApoEfx.cpp new file mode 100644 index 00000000..5924cd36 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoEfx.cpp @@ -0,0 +1,599 @@ +// +// KWSApoEFX.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Implementation of CKWSApoEFX +// + +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include <initguid.h> +#include <audioenginebaseapo.h> +#include <baseaudioprocessingobject.h> +#include <resource.h> + +#include <float.h> + +#include "KWSApo.h" +#include <devicetopology.h> +#include <CustomPropKeys.h> + +// Static declaration of the APO_REG_PROPERTIES structure +// associated with this APO. The number in <> brackets is the +// number of IIDs supported by this APO. If more than one, then additional +// IIDs are added at the end +#pragma warning (disable : 4815) +const AVRT_DATA CRegAPOProperties<1> CKWSApoEFX::sm_RegProperties( + __uuidof(KWSApoEFX), // clsid of this APO + L"CKWSApoEFX", // friendly name of this APO + L"Copyright (c) Microsoft Corporation", // copyright info + 1, // major version # + 0, // minor version # + __uuidof(IKWSApoEFX), // iid of primary interface + (APO_FLAG) (APO_FLAG_BITSPERSAMPLE_MUST_MATCH | APO_FLAG_FRAMESPERSECOND_MUST_MATCH), + DEFAULT_APOREG_MININPUTCONNECTIONS, + DEFAULT_APOREG_MAXINPUTCONNECTIONS, + DEFAULT_APOREG_MINOUTPUTCONNECTIONS, + DEFAULT_APOREG_MAXOUTPUTCONNECTIONS, + DEFAULT_APOREG_MAXINSTANCES + ); + + +#pragma AVRT_CODE_BEGIN +//------------------------------------------------------------------------- +// Description: +// +// Do the actual processing of data. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections +// ppInputConnections - [in] pointer to list of input APO_CONNECTION_PROPERTY pointers +// u32NumOutputConnections - [in] number of output connections +// ppOutputConnections - [in] pointer to list of output APO_CONNECTION_PROPERTY pointers +// +// Return values: +// +// void +// +// Remarks: +// +// This function processes data in a manner dependent on the implementing +// object. This routine can not fail and can not block, or call any other +// routine that blocks, or touch pagable memory. +// +STDMETHODIMP_(void) CKWSApoEFX::APOProcess( + UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, + UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections) +{ + UNREFERENCED_PARAMETER(u32NumInputConnections); + UNREFERENCED_PARAMETER(u32NumOutputConnections); + + FLOAT32 *pf32InputFrames, *pf32OutputFrames; + + ATLASSERT(m_bIsLocked); + + // assert that the number of input and output connectins fits our registration properties + ATLASSERT(m_pRegProperties->u32MinInputConnections <= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MaxInputConnections >= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MinOutputConnections <= u32NumOutputConnections); + ATLASSERT(m_pRegProperties->u32MaxOutputConnections >= u32NumOutputConnections); + + // check APO_BUFFER_FLAGS. + switch( ppInputConnections[0]->u32BufferFlags ) + { + case BUFFER_INVALID: + { + ATLASSERT(false); // invalid flag - should never occur. don't do anything. + break; + } + case BUFFER_VALID: + case BUFFER_SILENT: + { + // get input pointer to connection buffer + pf32InputFrames = reinterpret_cast<FLOAT32*>(ppInputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); + + // get output pointer to connection buffer + pf32OutputFrames = reinterpret_cast<FLOAT32*>(ppOutputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_WRITE_POINTER(pf32OutputFrames) ); + + if (BUFFER_SILENT == ppInputConnections[0]->u32BufferFlags) + { + WriteSilence( pf32OutputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); + } + else + { + ProcessBuffer(pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + &m_FormatInfo); + + // we don't try to remember silence + ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID; + } + + // Set the valid frame count. + ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; + + break; + } + default: + { + ATLASSERT(false); // invalid flag - should never occur + break; + } + } // switch + +} // APOProcess +#pragma AVRT_CODE_END + +//------------------------------------------------------------------------- +// Description: +// +// Parameters: +// +// pTime - [out] hundreds-of-nanoseconds +// +// Return values: +// +// S_OK on success, a failure code on failure +STDMETHODIMP CKWSApoEFX::GetLatency(HNSTIME* pTime) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit); + + *pTime = 0; + +Exit: + return hr; +} + + +//------------------------------------------------------------------------- +// Description: +// +// Verifies that the APO is ready to process and locks its state if so. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections attached to this APO +// ppInputConnections - [in] connection descriptor of each input connection attached to this APO +// u32NumOutputConnections - [in] number of output connections attached to this APO +// ppOutputConnections - [in] connection descriptor of each output connection attached to this APO +// +// Return values: +// +// S_OK Object is locked and ready to process. +// E_POINTER Invalid pointer passed to function. +// APOERR_INVALID_CONNECTION_FORMAT Invalid connection format. +// APOERR_NUM_CONNECTIONS_INVALID Number of input or output connections is not valid on +// this APO. +STDMETHODIMP CKWSApoEFX::LockForProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + UNCOMPRESSEDAUDIOFORMAT uncompAudioFormat; + + // fill in the samples per frame for the output (since APO_FLAG_SAMPLESPERFRAME_MUST_MATCH is not selected) + // There are two potentially different samples per frame values here. The input, which will be interleaved + primary. + // And the output, which is just the primary. Because this is used for clearing the zeroing the output buffer, we're going + // to fill it in with the output samples per frame. ProcessBuffer has both. + hr = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&uncompAudioFormat); + IF_FAILED_JUMP(hr, Exit); + + m_u32SamplesPerFrame = uncompAudioFormat.dwSamplesPerFrame; + + hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections, + ppInputConnections, u32NumOutputConnections, ppOutputConnections); + IF_FAILED_JUMP(hr, Exit); + +Exit: + return hr; +} + +// The method that this long comment refers to is "Initialize()" +//------------------------------------------------------------------------- +// Description: +// +// Generic initialization routine for APOs. +// +// Parameters: +// +// cbDataSize - [in] the size in bytes of the initialization data. +// pbyData - [in] initialization data specific to this APO +// +// Return values: +// +// S_OK Successful completion. +// E_POINTER Invalid pointer passed to this function. +// E_INVALIDARG Invalid argument +// AEERR_ALREADY_INITIALIZED APO is already initialized +// +// Remarks: +// +// This method initializes the APO. The data is variable length and +// should have the form of: +// +// struct MyAPOInitializationData +// { +// APOInitBaseStruct APOInit; +// ... // add additional fields here +// }; +// +// If the APO needs no initialization or needs no data to initialize +// itself, it is valid to pass NULL as the pbyData parameter and 0 as +// the cbDataSize parameter. +// +// As part of designing an APO, decide which parameters should be +// immutable (set once during initialization) and which mutable (changeable +// during the lifetime of the APO instance). Immutable parameters must +// only be specifiable in the Initialize call; mutable parameters must be +// settable via methods on whichever parameter control interface(s) your +// APO provides. Mutable values should either be set in the initialize +// method (if they are required for proper operation of the APO prior to +// LockForProcess) or default to reasonable values upon initialize and not +// be required to be set before LockForProcess. +// +// Within the mutable parameters, you must also decide which can be changed +// while the APO is locked for processing and which cannot. +// +// All parameters should be considered immutable as a first choice, unless +// there is a specific scenario which requires them to be mutable; similarly, +// no mutable parameters should be changeable while the APO is locked, unless +// a specific scenario requires them to be. Following this guideline will +// simplify the APO's state diagram and implementation and prevent certain +// types of bug. +// +// If a parameter changes the APOs latency or MaxXXXFrames values, it must be +// immutable. +// +// The default version of this function uses no initialization data, but does verify +// the passed parameters and set the m_bIsInitialized member to true. +// +// Note: This method may not be called from a real-time processing thread. +// + +HRESULT CKWSApoEFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) +{ + HRESULT hr = S_OK; + CComPtr<IMMDevice> spMyDevice; + CComPtr<IDeviceTopology> spMyDeviceTopology; + CComPtr<IConnector> spMyConnector; + CComPtr<IPart> spPart; + UINT myPartId; + CComPtr<IKsControl> spKsControl; + ULONG cbReturned = 0; + + IF_TRUE_ACTION_JUMP( ((NULL == pbyData) && (0 != cbDataSize)), hr = E_INVALIDARG, Exit); + IF_TRUE_ACTION_JUMP( ((NULL != pbyData) && (0 == cbDataSize)), hr = E_INVALIDARG, Exit); + + if (cbDataSize == sizeof(APOInitSystemEffects2)) + { + // + // Initialize for mode-specific signal processing + // + APOInitSystemEffects2* papoSysFxInit2 = (APOInitSystemEffects2*)pbyData; + KSP_PIN ksPinProperty; + + // Save reference to the effects property store. This saves effects settings + // and is the communication medium between this APO and any associated UI. + m_spAPOSystemEffectsProperties = papoSysFxInit2->pAPOSystemEffectsProperties; + + // Windows should pass a valid collection. + ATLASSERT(papoSysFxInit2->pDeviceCollection != nullptr); + IF_TRUE_ACTION_JUMP(papoSysFxInit2->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + + // Get the IDeviceTopology and IConnector interfaces to communicate with this + // APO's counterpart audio driver. This can be used for any proprietary + // communication. + hr = papoSysFxInit2->pDeviceCollection->Item(papoSysFxInit2->nSoftwareIoDeviceInCollection, &spMyDevice); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDevice->Activate(__uuidof(IKsControl), CLSCTX_ALL, NULL, (void**)&spKsControl); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDeviceTopology->GetConnector(papoSysFxInit2->nSoftwareIoConnectorIndex, &spMyConnector); + IF_FAILED_JUMP(hr, Exit); + + spPart = spMyConnector; + + hr = spPart->GetLocalId(&myPartId); + IF_FAILED_JUMP(hr, Exit); + + ::ZeroMemory(&ksPinProperty, sizeof(ksPinProperty)); + ksPinProperty.Property.Set = KSPROPSETID_InterleavedAudio; + ksPinProperty.Property.Id = KSPROPERTY_INTERLEAVEDAUDIO_FORMATINFORMATION; + ksPinProperty.Property.Flags = KSPROPERTY_TYPE_GET; + ksPinProperty.PinId = myPartId & 0x0000ffff; + + ::ZeroMemory(&m_FormatInfo, sizeof(m_FormatInfo)); + + hr = spKsControl->KsProperty(&(ksPinProperty.Property), sizeof(ksPinProperty), &m_FormatInfo, sizeof(m_FormatInfo), &cbReturned); + IF_FAILED_JUMP(hr, Exit); + + IF_TRUE_ACTION_JUMP( m_FormatInfo.Size != sizeof(m_FormatInfo), hr = E_INVALIDARG, Exit); + } + else + { + // Invalid initialization size + hr = E_INVALIDARG; + goto Exit; + } + + // + // Register for notification of registry updates + // + hr = m_spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)); + IF_FAILED_JUMP(hr, Exit); + + hr = m_spEnumerator->RegisterEndpointNotificationCallback(this); + IF_FAILED_JUMP(hr, Exit); + + m_bIsInitialized = true; + + +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event) +{ + UNREFERENCED_PARAMETER(Event); + + *ppEffectsIds = NULL; + *pcEffects = 0; + + return S_OK; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::IsInputFormatSupported(IAudioMediaType *pOutputFormat, IAudioMediaType *pRequestedInputFormat, IAudioMediaType **ppSupportedInputFormat) +{ + ASSERT_NONREALTIME(); + bool formatChanged = false; + HRESULT hResult; + UNCOMPRESSEDAUDIOFORMAT uncompInputFormat; + IAudioMediaType *recommendedFormat = NULL; + UINT totalChannelCount = (m_FormatInfo.PrimaryChannelCount + m_FormatInfo.InterleavedChannelCount); + + IF_TRUE_ACTION_JUMP((NULL == pRequestedInputFormat) || (NULL == ppSupportedInputFormat), hResult = E_POINTER, Exit); + *ppSupportedInputFormat = NULL; + + // Initial comparison to make sure the requested format is valid and consistent with the output + // format. Because of the APO flags specified during creation, the samples per frame value will + // not be validated. + hResult = IsFormatTypeSupported( pOutputFormat, pRequestedInputFormat, &recommendedFormat, true ); + IF_FAILED_JUMP(hResult, Exit); + + // If the input format is changed, make sure we track it for our return code. + if (S_FALSE == hResult) + { + formatChanged = true; + } + + // now retrieve the format that IsFormatTypeSupported decided on, building upon that by adding + // our channel count constraint. + hResult = recommendedFormat->GetUncompressedAudioFormat(&uncompInputFormat); + IF_FAILED_JUMP(hResult, Exit); + + // the expected input channel count, for interleaved audio, is the total number of channels + // reported in the interleaved format information. Fail any request for a format that doesn't + // meet that requirement. + if (uncompInputFormat.dwSamplesPerFrame != totalChannelCount) + { + hResult = APOERR_FORMAT_NOT_SUPPORTED; + goto Exit; + } + + // If the requested format exactly matched our requirements, + // just return it. + if(!formatChanged) + { + *ppSupportedInputFormat = pRequestedInputFormat; + (*ppSupportedInputFormat)->AddRef(); + hResult = S_OK; + } + else // we're proposing something different than the input, copy it and return S_FALSE; + { + hResult = CreateAudioMediaTypeFromUncompressedAudioFormat(&uncompInputFormat, ppSupportedInputFormat); + IF_FAILED_JUMP(hResult, Exit); + + hResult = S_FALSE; + } + +Exit: + + if (recommendedFormat) + { + recommendedFormat->Release(); + } + + return hResult; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::IsOutputFormatSupported(IAudioMediaType *pInputFormat, IAudioMediaType *pRequestedOutputFormat, IAudioMediaType **ppSupportedOutputFormat) +{ + ASSERT_NONREALTIME(); + bool formatChanged = false; + HRESULT hResult; + UNCOMPRESSEDAUDIOFORMAT uncompOutputFormat; + IAudioMediaType *recommendedFormat = NULL; + + IF_TRUE_ACTION_JUMP((NULL == pRequestedOutputFormat) || (NULL == ppSupportedOutputFormat), hResult = E_POINTER, Exit); + *ppSupportedOutputFormat = NULL; + + // Initial comparison to make sure the requested format is valid and consistent with the input + // format. Because of the APO flags specified during creation, the samples per frame value will + // not be validated. + hResult = IsFormatTypeSupported( pInputFormat, pRequestedOutputFormat, &recommendedFormat, true ); + IF_FAILED_JUMP(hResult, Exit); + + // If the output format is changed, make sure we track it for our return code. + if (S_FALSE == hResult) + { + formatChanged = true; + } + + // now retrieve the format that IsFormatTypeSupported decided on, building upon that by adding + // our channel count constraint. + hResult = recommendedFormat->GetUncompressedAudioFormat(&uncompOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + + // The expected output channel count is the number of primary channels in the interleaved data. + // We're removing the interleaved data. + if (uncompOutputFormat.dwSamplesPerFrame != m_FormatInfo.PrimaryChannelCount) + { + uncompOutputFormat.dwSamplesPerFrame = m_FormatInfo.PrimaryChannelCount; + uncompOutputFormat.dwChannelMask = m_FormatInfo.PrimaryChannelMask; + formatChanged = true; + } + + // If the requested format exactly matched our requirements, + // just return it. + if(!formatChanged) + { + *ppSupportedOutputFormat = pRequestedOutputFormat; + (*ppSupportedOutputFormat)->AddRef(); + hResult = S_OK; + } + else // we're proposing something different, copy it and return S_FALSE; + { + hResult = CreateAudioMediaTypeFromUncompressedAudioFormat(&uncompOutputFormat, ppSupportedOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + hResult = S_FALSE; + } + +Exit: + + if (recommendedFormat) + { + recommendedFormat->Release(); + } + + return hResult; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::GetInputChannelCount(UINT32 *pu32ChannelCount) +{ + ASSERT_NONREALTIME(); + HRESULT hResult = S_OK; + + IF_TRUE_ACTION_JUMP(!m_bIsInitialized, hResult = APOERR_NOT_INITIALIZED, Exit); + IF_TRUE_ACTION_JUMP(NULL == pu32ChannelCount, hResult = E_POINTER, Exit); + + // the input channel count is always the sum of the primary and interleaved + *pu32ChannelCount = (m_FormatInfo.PrimaryChannelCount + m_FormatInfo.InterleavedChannelCount); + +Exit: + return hResult; +} // GetChannelCount + +//------------------------------------------------------------------------- +// Description: +// +// Destructor. +// +// Parameters: +// +// void +// +// Return values: +// +// void +// +// Remarks: +// +// This method deletes whatever was allocated. +// +// This method may not be called from a real-time processing thread. +// +CKWSApoEFX::~CKWSApoEFX(void) +{ + // + // unregister for callbacks + // + if (m_bIsInitialized) + { + m_spEnumerator->UnregisterEndpointNotificationCallback(this); + } +} // ~CKWSApoEFX diff --git a/audio/sysvad/APO/KWSApo/KWSApoEfx.rgs b/audio/sysvad/APO/KWSApo/KWSApoEfx.rgs new file mode 100644 index 00000000..dc5bd41a --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoEfx.rgs @@ -0,0 +1,13 @@ +HKCR +{ + NoRemove CLSID + { + ForceRemove {9D89F614-F9D6-40DD-9F21-5E69FA3981ED} = s 'KWSApoEFX Class' + { + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Both' + } + } + } +} diff --git a/audio/sysvad/APO/KWSApo/KWSApoInterface.idl b/audio/sysvad/APO/KWSApo/KWSApoInterface.idl new file mode 100644 index 00000000..6c0c98ad --- /dev/null +++ b/audio/sysvad/APO/KWSApo/KWSApoInterface.idl @@ -0,0 +1,21 @@ +// +// KWSApoInterface.idl -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// The interface and type definitions for KWS APO functionality. +// +import "oaidl.idl"; +import "ocidl.idl"; +import "audioenginebaseapo.idl"; + + +[ + object, + uuid(CF5C2AA7-68A8-4FD1-B86F-EBC008AD1B6F), + pointer_default(unique) +] +interface IKWSApoEFX : IUnknown +{ +}; + diff --git a/audio/sysvad/APO/KWSApo/Resource.h b/audio/sysvad/APO/KWSApo/Resource.h new file mode 100644 index 00000000..df1260e1 --- /dev/null +++ b/audio/sysvad/APO/KWSApo/Resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by KWSApoDll.rc +// +#define IDS_PROJNAME 100 +#define IDR_KWSAPODLL 101 +#define IDR_KWSAPOEFX 110 +#define IDI_EFFECT_ICON 200 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 201 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 132 +#endif +#endif diff --git a/audio/sysvad/APO/SwapAPO/SwapAPO.h b/audio/sysvad/APO/SwapAPO/SwapAPO.h index fc279460..83702e6f 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPO.h +++ b/audio/sysvad/APO/SwapAPO/SwapAPO.h @@ -129,6 +129,11 @@ public: STDMETHODIMP GetFormat(UINT nFormat, IAudioMediaType** ppFormat); STDMETHODIMP GetFormatRepresentation(UINT nFormat, _Outptr_ LPWSTR* ppwstrFormatRep); + // IAudioProcessingObject + STDMETHODIMP IsOutputFormatSupported(IAudioMediaType *pOppositeFormat, IAudioMediaType *pRequestedOutputFormat, IAudioMediaType **ppSupportedOutputFormat); + + STDMETHODIMP CheckCustomFormats(IAudioMediaType *pRequestedFormat); + public: LONG m_fEnableSwapMFX; GUID m_AudioProcessingMode; diff --git a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj index 4ab6f2e4..4e680972 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj +++ b/audio/sysvad/APO/SwapAPO/SwapAPO.vcxproj @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> @@ -13,10 +9,6 @@ <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> @@ -89,15 +81,6 @@ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> @@ -107,15 +90,6 @@ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <EmbedManifest>false</EmbedManifest> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <OutDir>$(IntDir)</OutDir> @@ -135,15 +109,9 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>SwapAPO</TargetName> diff --git a/audio/sysvad/APO/SwapAPO/SwapAPODll.cpp b/audio/sysvad/APO/SwapAPO/SwapAPODll.cpp index 22e810bf..ff7a1cd6 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPODll.cpp +++ b/audio/sysvad/APO/SwapAPO/SwapAPODll.cpp @@ -69,4 +69,4 @@ _Check_return_ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) { return _AtlModule.DllGetClassObject(rclsid, riid, ppv); -} +}
\ No newline at end of file diff --git a/audio/sysvad/APO/SwapAPO/SwapAPODll.def b/audio/sysvad/APO/SwapAPO/SwapAPODll.def index f4b6fcd9..3f3b0c5a 100644 --- a/audio/sysvad/APO/SwapAPO/SwapAPODll.def +++ b/audio/sysvad/APO/SwapAPO/SwapAPODll.def @@ -1,4 +1,4 @@ EXPORTS DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE + DllGetClassObject PRIVATE
\ No newline at end of file diff --git a/audio/sysvad/APO/SwapAPO/makefile b/audio/sysvad/APO/SwapAPO/makefile deleted file mode 100644 index c7837f4f..00000000 --- a/audio/sysvad/APO/SwapAPO/makefile +++ /dev/null @@ -1,36 +0,0 @@ -############################################################################# -# -# Copyright (c) Microsoft Corporation. -# All Rights Reserved. -# -# Makefile for wdm\audio\sysfx\apo -# -############################################################################# - -## NT BUILD ENVIROMENT - -# -# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source -# file to this component. This file merely indirects to the real make file -# that is shared by all the components of NT. -# -!if defined(IA64) -!message This sample is not to be built for IA64 targets -!else - -!IF DEFINED(_NT_TARGET_VERSION) -#! IF $(_NT_TARGET_VERSION)>=0x501 -! IF $(_NT_TARGET_VERSION)>=0x600 -! INCLUDE $(NTMAKEENV)\makefile.def -! ELSE -# Only warn once per directory -! INCLUDE $(NTMAKEENV)\makefile.plt -! IF "$(BUILD_PASS)"=="PASS1" -! message BUILDMSG: Warning : Building the sample "$(MAKEDIR)" for downlevel build environments is temporarily disabled in WDK for Beta2. -! ENDIF -! ENDIF -!ELSE -! INCLUDE $(NTMAKEENV)\makefile.def -!ENDIF - -!endif
\ No newline at end of file diff --git a/audio/sysvad/APO/SwapAPO/sources b/audio/sysvad/APO/SwapAPO/sources deleted file mode 100644 index 7baf3745..00000000 --- a/audio/sysvad/APO/SwapAPO/sources +++ /dev/null @@ -1,13 +0,0 @@ -!include ..\sources.inc - -TARGETNAME=SwapAPO -DLLDEF=SwapAPODll.def - -SOURCES=SwapAPOInterface.idl \ - SwapAPOMFX.cpp \ - SwapAPOSFX.cpp \ - Swap.cpp \ - SwapAPODll.idl \ - SwapAPODll.rc \ - SwapAPODll.cpp \ - diff --git a/audio/sysvad/APO/SwapAPO/swapapomfx.cpp b/audio/sysvad/APO/SwapAPO/swapapomfx.cpp index b4e6e95a..a6c0d111 100644 --- a/audio/sysvad/APO/SwapAPO/swapapomfx.cpp +++ b/audio/sysvad/APO/SwapAPO/swapapomfx.cpp @@ -870,8 +870,9 @@ DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_A CUSTOM_FORMAT_ITEM _rgCustomFormats[] = { {{ WAVE_FORMAT_EXTENSIBLE, 2, 44100, 176400, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #1 (really 44.1 KHz, 16-bit, stereo)"}, - {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #2 (really 48 KHz, 16-bit, stereo)"}, - {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_AC3}, L"Custom #3 (really 48 KHz AC-3)"} + {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_PCM}, L"Custom #2 (really 48 KHz, 16-bit, stereo)"} + // The compressed AC3 format has been temporarily removed since the APO is not set up for compressed formats or EFXs yet. + // {{ WAVE_FORMAT_EXTENSIBLE, 2, 48000, 192000, 4, 16, sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX), 16, KSAUDIO_SPEAKER_STEREO, KSDATAFORMAT_SUBTYPE_AC3}, L"Custom #3 (really 48 KHz AC-3)"} }; #define _cCustomFormats (ARRAYSIZE(_rgCustomFormats)) @@ -994,3 +995,139 @@ STDMETHODIMP CSwapAPOMFX::GetFormatRepresentation Exit: return hr; } + +//------------------------------------------------------------------------- +// Description: +// +// Implementation of IAudioProcessingObject::IsOutputFormatSupported +// +// Parameters: +// +// pInputFormat - [in] A pointer to an IAudioMediaType interface. This parameter indicates the output format. This parameter must be set to NULL to indicate that the output format can be any type +// pRequestedOutputFormat - [in] A pointer to an IAudioMediaType interface. This parameter indicates the output format that is to be verified +// ppSupportedOutputFormat - [in] This parameter indicates the supported output format that is closest to the format to be verified +// +// Return values: +// +// S_OK Success +// S_FALSE The format of Input/output format pair is not supported. The ppSupportedOutPutFormat parameter returns a suggested new format +// APOERR_FORMAT_NOT_SUPPORTED The format is not supported. The value of ppSupportedOutputFormat does not change. +// E_POINTER Null pointer passed +// +// Remarks: +// +STDMETHODIMP CSwapAPOMFX::IsOutputFormatSupported +( + IAudioMediaType *pInputFormat, + IAudioMediaType *pRequestedOutputFormat, + IAudioMediaType **ppSupportedOutputFormat +) +{ + ASSERT_NONREALTIME(); + bool formatChanged = false; + HRESULT hResult; + UNCOMPRESSEDAUDIOFORMAT uncompOutputFormat; + IAudioMediaType *recommendedFormat = NULL; + + IF_TRUE_ACTION_JUMP((NULL == pRequestedOutputFormat) || (NULL == ppSupportedOutputFormat), hResult = E_POINTER, Exit); + *ppSupportedOutputFormat = NULL; + + // Initial comparison to make sure the requested format is valid and consistent with the input + // format. Because of the APO flags specified during creation, the samples per frame value will + // not be validated. + hResult = IsFormatTypeSupported(pInputFormat, pRequestedOutputFormat, &recommendedFormat, true); + IF_FAILED_JUMP(hResult, Exit); + + // Check to see if a custom format from the APO was used. + if (S_FALSE == hResult) + { + hResult = CheckCustomFormats(pRequestedOutputFormat); + + // If the output format is changed, make sure we track it for our return code. + if (S_FALSE == hResult) + { + formatChanged = true; + } + } + + // now retrieve the format that IsFormatTypeSupported decided on, building upon that by adding + // our channel count constraint. + hResult = recommendedFormat->GetUncompressedAudioFormat(&uncompOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + + // If the requested format exactly matched our requirements, + // just return it. + if (!formatChanged) + { + *ppSupportedOutputFormat = pRequestedOutputFormat; + (*ppSupportedOutputFormat)->AddRef(); + hResult = S_OK; + } + else // we're proposing something different, copy it and return S_FALSE + { + hResult = CreateAudioMediaTypeFromUncompressedAudioFormat(&uncompOutputFormat, ppSupportedOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + hResult = S_FALSE; + } + +Exit: + if (recommendedFormat) + { + recommendedFormat->Release(); + } + + return hResult; +} + +HRESULT CSwapAPOMFX::CheckCustomFormats(IAudioMediaType *pRequestedFormat) +{ + HRESULT hResult = S_OK; + + for (int i = 0; i < _cCustomFormats; i++) + { + hResult = S_OK; + const WAVEFORMATEX* waveFormat = pRequestedFormat->GetAudioFormat(); + + if (waveFormat->wFormatTag != _rgCustomFormats[i].wfxFmt.Format.wFormatTag) + { + hResult = S_FALSE; + } + + if (waveFormat->nChannels != _rgCustomFormats[i].wfxFmt.Format.nChannels) + { + hResult = S_FALSE; + } + + if (waveFormat->nSamplesPerSec != _rgCustomFormats[i].wfxFmt.Format.nSamplesPerSec) + { + hResult = S_FALSE; + } + + if (waveFormat->nAvgBytesPerSec != _rgCustomFormats[i].wfxFmt.Format.nAvgBytesPerSec) + { + hResult = S_FALSE; + } + + if (waveFormat->nBlockAlign != _rgCustomFormats[i].wfxFmt.Format.nBlockAlign) + { + hResult = S_FALSE; + } + + if (waveFormat->wBitsPerSample != _rgCustomFormats[i].wfxFmt.Format.wBitsPerSample) + { + hResult = S_FALSE; + } + + if (waveFormat->cbSize != _rgCustomFormats[i].wfxFmt.Format.cbSize) + { + hResult = S_FALSE; + } + + if (hResult == S_OK) + { + break; + } + } + + return hResult; +}
\ No newline at end of file diff --git a/audio/sysvad/ContosoKeywordDetector.h b/audio/sysvad/ContosoKeywordDetector.h index e23daf15..6f12f4de 100644 --- a/audio/sysvad/ContosoKeywordDetector.h +++ b/audio/sysvad/ContosoKeywordDetector.h @@ -14,7 +14,15 @@ // // {6F7DBCC1-202E-498D-99C5-61C36C4EB2DC} DEFINE_GUID(CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER, 0x6f7dbcc1, 0x202e, 0x498d, 0x99, 0xc5, 0x61, 0xc3, 0x6c, 0x4e, 0xb2, 0xdc); - + +// {207F3D0C-5C79-496F-A94C-D3D2934DBFA9} +DEFINE_GUID(CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2, 0x207f3d0c, 0x5c79, 0x496f, 0xa9, 0x4c, 0xd3, 0xd2, 0x93, 0x4d, 0xbf, 0xa9); + +// {A537F559-2D67-463B-B10E-BEB750A21F31} +DEFINE_GUID(CONTOSO_KEYWORD1, 0xa537f559, 0x2d67, 0x463b, 0xb1, 0xe, 0xbe, 0xb7, 0x50, 0xa2, 0x1f, 0x31); +// {655E417A-80A5-4A77-B3F1-512EAF67ABCF} +DEFINE_GUID(CONTOSO_KEYWORD2, 0x655e417a, 0x80a5, 0x4a77, 0xb3, 0xf1, 0x51, 0x2e, 0xaf, 0x67, 0xab, 0xcf); + // // The format of the Contoso keyword pattern matching data. // @@ -33,4 +41,5 @@ typedef struct LONGLONG ContosoDetectorResultData; ULONGLONG KeywordStartTimestamp; ULONGLONG KeywordStopTimestamp; + GUID EventId; } CONTOSO_KEYWORDDETECTIONRESULT; diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj index 7fda3a23..b4d1c802 100644 --- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj +++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> @@ -13,10 +9,6 @@ <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> @@ -83,14 +75,6 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> @@ -99,14 +83,6 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>StaticLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>StaticLibrary</ConfigurationType> - </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <OutDir>$(IntDir)</OutDir> @@ -126,15 +102,9 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>EndpointsCommon</TargetName> @@ -151,15 +121,9 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <TargetName>EndpointsCommon</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <TargetName>EndpointsCommon</TargetName> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetName>EndpointsCommon</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <TargetName>EndpointsCommon</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> @@ -245,23 +209,6 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ResourceCompile> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> @@ -279,23 +226,6 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..;.</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="AudioModuleHelper.cpp" /> <ClCompile Include="bthhfpmictopo.cpp" /> diff --git a/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp index c3a77d1f..5f45d15a 100644 --- a/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp +++ b/audio/sysvad/EndpointsCommon/MiniportAudioEngineNode.cpp @@ -851,10 +851,10 @@ NTSTATUS CMiniportWaveRT::GetVolumeSteppings(_Out_writes_bytes_(_ui32DataSize) P //============================================================================= // The volume control should be implemented as follows: // -// #1 If the Sideband device supports volume control, then the audio driver should +// #1 If the USB headset supports volume control, then the audio driver should // pipe the volume change requests through the Sideband Interface // -// #2 If the Sideband device does not implement a hardware volume, and the codec +// #2 If the USB headset does not implement a hardware volume, and the codec // (or DSP) has a hardware volume, the audio driver should handle the volume // control on the codec (or DSP). // diff --git a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp index 1b0f13f1..49f4cec8 100644 --- a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp +++ b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp @@ -860,12 +860,11 @@ NTSTATUS CMiniportWaveRTStream::SetCurrentWritePositionInternal(_In_ ULONG _ulC //linear and presentation positions #pragma code_seg() -NTSTATUS CMiniportWaveRTStream::GetPositions -( +NTSTATUS CMiniportWaveRTStream::GetPositions( _Out_opt_ ULONGLONG * _pullLinearBufferPosition, _Out_opt_ ULONGLONG * _pullPresentationPosition, _Out_opt_ LARGE_INTEGER * _pliQPCTime -) + ) { DPF_ENTER(("[CMiniportWaveRTStream::GetPositions]")); diff --git a/audio/sysvad/EndpointsCommon/NewDelete.h b/audio/sysvad/EndpointsCommon/NewDelete.h index 288634d4..1b5d5e61 100644 --- a/audio/sysvad/EndpointsCommon/NewDelete.h +++ b/audio/sysvad/EndpointsCommon/NewDelete.h @@ -10,10 +10,6 @@ Abstract: Declaration of placement new and delete operators. -//@@BEGIN_DDKSPLIT -Revision History: - -//@@END_DDKSPLIT --*/ #pragma once @@ -114,3 +110,4 @@ void __cdecl operator delete[] ); #endif//_NEW_DELETE_OPERATORS_ + diff --git a/audio/sysvad/EndpointsCommon/bthhfpmictopo.cpp b/audio/sysvad/EndpointsCommon/bthhfpmictopo.cpp index 01eb156b..bcaaca94 100644 --- a/audio/sysvad/EndpointsCommon/bthhfpmictopo.cpp +++ b/audio/sysvad/EndpointsCommon/bthhfpmictopo.cpp @@ -275,3 +275,5 @@ PropertyHandler_BthHfpMicTopoFilterEvent #pragma code_seg() #endif // SYSVAD_BTH_BYPASS + + diff --git a/audio/sysvad/EndpointsCommon/micarraywavtable.h b/audio/sysvad/EndpointsCommon/micarraywavtable.h index 0db6e6a0..55309092 100644 --- a/audio/sysvad/EndpointsCommon/micarraywavtable.h +++ b/audio/sysvad/EndpointsCommon/micarraywavtable.h @@ -711,6 +711,14 @@ DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed); DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed); DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorMatchResult); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorReset2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorStreamingSupport2); + + static SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = { @@ -725,7 +733,9 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = 0, NULL, NULL, - NULL + NULL, + NULL, + 0 }, { { @@ -738,7 +748,9 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = 0, NULL, NULL, - NULL + NULL, + NULL, + 0 }, { { @@ -751,7 +763,9 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = 0, NULL, NULL, - NULL + NULL, + NULL, + 0 }, { { @@ -764,7 +778,9 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = 0, NULL, NULL, - NULL + NULL, + NULL, + 0 }, { { @@ -777,7 +793,9 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = sizeof(CONTOSO_SUPPORTEDPATTERNSVALUE), CMiniportWaveRT_Get_SoundDetectorSupportedPatterns, NULL, - NULL + NULL, + NULL, + 0 }, { { @@ -790,7 +808,9 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = (sizeof(KSMULTIPLE_ITEM) + sizeof(CONTOSO_KEYWORDCONFIGURATION)), NULL, CMiniportWaveRT_Set_SoundDetectorPatterns, - NULL + NULL, + NULL, + 0 }, { { @@ -803,7 +823,9 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = sizeof(BOOL), CMiniportWaveRT_Get_SoundDetectorArmed, CMiniportWaveRT_Set_SoundDetectorArmed, - NULL + NULL, + NULL, + 0 }, { { @@ -816,7 +838,84 @@ SYSVADPROPERTY_ITEM PropertiesMicArrayWaveFilter[] = sizeof(CONTOSO_KEYWORDDETECTIONRESULT), CMiniportWaveRT_Get_SoundDetectorMatchResult, NULL, - NULL + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_SUPPORTEDPATTERNS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(CONTOSO_SUPPORTEDPATTERNSVALUE), + CMiniportWaveRT_Get_SoundDetectorSupportedPatterns2, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_PATTERNS, + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + (sizeof(KSMULTIPLE_ITEM) + sizeof(CONTOSO_KEYWORDCONFIGURATION)), + NULL, + CMiniportWaveRT_Set_SoundDetectorPatterns2, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_ARMED, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(BOOL), + CMiniportWaveRT_Get_SoundDetectorArmed2, + CMiniportWaveRT_Set_SoundDetectorArmed2, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_RESET, + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(BOOL), + NULL, + CMiniportWaveRT_Set_SoundDetectorReset2, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_STREAMINGSUPPORT, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(BOOL), + CMiniportWaveRT_Get_SoundDetectorStreamingSupport2, + NULL, + NULL, + NULL, + 0 }, }; diff --git a/audio/sysvad/EndpointsCommon/mintopo.cpp b/audio/sysvad/EndpointsCommon/mintopo.cpp index 128fa15c..28ddf419 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.cpp +++ b/audio/sysvad/EndpointsCommon/mintopo.cpp @@ -110,13 +110,13 @@ Return Value: DPF_ENTER(("[CMiniportTopology::~CMiniportTopology]")); -#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) || defined (SYSVAD_A2DP_SIDEBAND) if (IsSidebandDevice()) { ASSERT(m_pSidebandDevice != NULL); // - // Register with BthHfpDevice or UsbHsDevice to get notification events. + // Register with BthHfpDevice, A2dpHpDevice or UsbHsDevice to get notification events. // if(IsSidebandDevice()) { @@ -127,7 +127,7 @@ Return Value: SAFE_RELEASE(m_pSidebandDevice); // ISidebandDeviceCommon } -#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) || defined(SYSVAD_A2DP_SIDEBAND) } // ~CMiniportTopology @@ -281,7 +281,7 @@ Return Value: DPF(D_ERROR, ("Init: CMiniportTopologySYSVAD::Init failed, 0x%x", ntStatus)), Done); -#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) +#if defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) || defined(SYSVAD_A2DP_SIDEBAND) if (IsSidebandDevice()) { PSIDEBANDDEVICECOMMON sidebandDevice = NULL; @@ -306,7 +306,7 @@ Return Value: } else { - ASSERT(m_DeviceType == eBthHfpSpeakerDevice || m_DeviceType == eUsbHsSpeakerDevice); + ASSERT(m_DeviceType == eBthHfpSpeakerDevice || m_DeviceType == eUsbHsSpeakerDevice || m_DeviceType == eA2dpHpSpeakerDevice); sidebandDevice->SetVolumeHandler( m_DeviceType, @@ -319,7 +319,7 @@ Return Value: PCMiniportTopology(this)); // context. } } -#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) +#endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) || defined(SYSVAD_A2DP_SIDEBAND) Done: return ntStatus; diff --git a/audio/sysvad/EndpointsCommon/mintopo.h b/audio/sysvad/EndpointsCommon/mintopo.h index 7f573237..4aa3d2de 100644 --- a/audio/sysvad/EndpointsCommon/mintopo.h +++ b/audio/sysvad/EndpointsCommon/mintopo.h @@ -92,7 +92,8 @@ public: return (m_DeviceType == eBthHfpMicDevice || m_DeviceType == eBthHfpSpeakerDevice || m_DeviceType == eUsbHsMicDevice || - m_DeviceType == eUsbHsSpeakerDevice ) ? TRUE : FALSE; + m_DeviceType == eUsbHsSpeakerDevice || + m_DeviceType == eA2dpHpSpeakerDevice) ? TRUE : FALSE; } // Returns a weak ref to the Bluetooth HFP device. @@ -164,6 +165,14 @@ public: _In_ PPCPROPERTY_REQUEST PropertyRequest); friend NTSTATUS PropertyHandler_UsbHsMicMute( _In_ PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_A2dpHpJackContainerId( + _In_ PPCPROPERTY_REQUEST PropertyRequest, + _In_ ULONG cJackDescriptions, + _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION * JackDescriptions); + friend NTSTATUS PropertyHandler_A2dpHpVolumeLevel_BasicSupport( + _In_ PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_A2dpHpMute_BasicSupport( + _In_ PPCPROPERTY_REQUEST PropertyRequest); }; typedef CMiniportTopology *PCMiniportTopology; diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp index 1ad029f7..4cabc7c4 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.cpp +++ b/audio/sysvad/EndpointsCommon/minwavert.cpp @@ -1214,6 +1214,8 @@ BOOL CMiniportWaveRT::IsKeywordDetectorPin(ULONG nPinId) return (pinType == KeywordCapturePin); } + +//============================================================================= #pragma code_seg("PAGE") NTSTATUS CMiniportWaveRT::StreamCreated @@ -1739,7 +1741,24 @@ CMiniportWaveRT::PropertyHandlerProposedFormat ntStatus = STATUS_SUCCESS; } } + else #endif // defined(SYSVAD_BTH_BYPASS) || defined(SYSVAD_USB_SIDEBAND) + if (IsKeywordDetectorPin(kspPin->PinId)) + { + KSDATAFORMAT_WAVEFORMATEXTENSIBLE *propFormat = (KSDATAFORMAT_WAVEFORMATEXTENSIBLE *)PropertyRequest->Value; + ULONG numModes = 0; + MODE_AND_DEFAULT_FORMAT *modeInfo = NULL; + + numModes = GetPinSupportedDeviceModes(kspPin->PinId, &modeInfo); + if (numModes == 0 || modeInfo->DefaultFormat == NULL) + { + return STATUS_NOT_SUPPORTED; + } + + RtlCopyMemory(propFormat, modeInfo->DefaultFormat, modeInfo->DefaultFormat->FormatSize); + PropertyRequest->ValueSize = modeInfo->DefaultFormat->FormatSize; + ntStatus = STATUS_SUCCESS; + } } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { @@ -1815,6 +1834,49 @@ Arguments: } //============================================================================= +#pragma code_seg() +VOID +CMiniportWaveRT::SendPNPNotification( + _In_ const GUID * NotificationId, + _In_ PVOID NotificationBuffer, + _In_ USHORT NotificationBufferCb + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PPCNOTIFICATION_BUFFER buffer = NULL; + + PAGED_CODE(); + + DPF_ENTER(("[SendPNPNotification]")); + + // Allocate a notification buffer. + status = m_pPortClsNotifications->AllocNotificationBuffer(PagedPool, + NotificationBufferCb, + &buffer); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + // Notification buffer is only guaranteed to be LONG aligned, + // it is received as ULONGLONG aligned on the receiving end. + RtlCopyMemory(buffer, NotificationBuffer, NotificationBufferCb); + + // + // Generate notification (async). + // + m_pPortClsNotifications->SendNotification(NotificationId, buffer); + +exit: + if (buffer != NULL) + { + // Free notification buffer. + m_pPortClsNotifications->FreeNotificationBuffer(buffer); + buffer = NULL; + } +} + +//============================================================================= #pragma code_seg("PAGE") NTSTATUS CMiniportWaveRT::PropertyHandlerAudioEffectsDiscoveryEffectsList @@ -2675,7 +2737,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns) // No items so clear the configuration. if (itemsHeader->Count == 0) { - m_KeywordDetector.ResetDetector(); + m_KeywordDetector.ResetDetector(CONTOSO_KEYWORD1); return STATUS_SUCCESS; } @@ -2722,9 +2784,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns) pattern = (CONTOSO_KEYWORDCONFIGURATION*)(patternHeader); // Program the hardware. - m_KeywordDetector.DownloadDetectorData(pattern->ContosoDetectorConfigurationData); - - return STATUS_SUCCESS; + return m_KeywordDetector.DownloadDetectorData(CONTOSO_KEYWORD1, pattern->ContosoDetectorConfigurationData); } DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed) @@ -2736,9 +2796,8 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed) NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); RtlZeroMemory(PropertyRequest->Value, PropertyRequest->ValueSize); - *(BOOL*)PropertyRequest->Value = m_KeywordDetector.GetArmed(); - return STATUS_SUCCESS; + return m_KeywordDetector.GetArmed(CONTOSO_KEYWORD1, (BOOL*)PropertyRequest->Value); } DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed) @@ -2754,7 +2813,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed) armed = ((*(BOOL*)PropertyRequest->Value) != 0); - ntStatus = m_KeywordDetector.SetArmed(armed); + ntStatus = m_KeywordDetector.SetArmed(CONTOSO_KEYWORD1, armed); if (NT_SUCCESS(ntStatus) && armed) { @@ -2762,7 +2821,7 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed) // it is armed, but later, find a better way to demonstrate this from // within CKeywordDetector. m_pPortEvents->GenerateEventList(const_cast<GUID*>(&KSEVENTSETID_SoundDetector), KSEVENT_SOUNDDETECTOR_MATCHDETECTED, FALSE, 0, FALSE, 0); - m_KeywordDetector.SetArmed(FALSE); + m_KeywordDetector.SetArmed(CONTOSO_KEYWORD1, FALSE); } return ntStatus; @@ -2785,15 +2844,297 @@ DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorMatchResult) value->Header.Size = sizeof(CONTOSO_KEYWORDDETECTIONRESULT); value->Header.PatternType = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER; - value->ContosoDetectorResultData = m_KeywordDetector.GetDetectorData(); value->KeywordStartTimestamp = m_KeywordDetector.GetStartTimestamp(); value->KeywordStopTimestamp = m_KeywordDetector.GetStopTimestamp(); PropertyRequest->ValueSize = sizeof(*value); - + + return m_KeywordDetector.GetDetectorData(CONTOSO_KEYWORD1, &(value->ContosoDetectorResultData)); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns2) +{ + CONTOSO_SUPPORTEDPATTERNSVALUE *value; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(*value)); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // There is currently only support for 1 OEM DLL, and that CLSID is returned when + // the EventID is GUID_NULL. + if (propertyInstance->EventId != GUID_NULL) + { + return STATUS_INVALID_PARAMETER; + } + + // Does this filter support a sound detector? + if ((m_DeviceFlags & ENDPOINT_SOUNDDETECTOR_SUPPORTED) == 0) + { + return STATUS_NOT_SUPPORTED; + } + + value = (CONTOSO_SUPPORTEDPATTERNSVALUE*)PropertyRequest->Value; + + RtlZeroMemory(value, sizeof(*value)); + + value->MultipleItem.Size = sizeof(*value); + value->MultipleItem.Count = 1; + value->PatternType[0] = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + + PropertyRequest->ValueSize = sizeof(*value); + return STATUS_SUCCESS; } +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns2) +{ + KSMULTIPLE_ITEM *itemsHeader; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + SOUNDDETECTOR_PATTERNHEADER *patternHeader; + CONTOSO_KEYWORDCONFIGURATION *pattern; + ULONG cbRemaining; // Tracks bytes remaining in property value + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + cbRemaining = PropertyRequest->ValueSize; + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof KSMULTIPLE_ITEM. + if (cbRemaining < sizeof(KSMULTIPLE_ITEM)) + { + return STATUS_INVALID_PARAMETER; + } + + itemsHeader = (KSMULTIPLE_ITEM*)PropertyRequest->Value; + + // Verify property value is large enough to include the items + if (itemsHeader->Size > cbRemaining) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + // No items so clear the configuration. + if (itemsHeader->Count == 0) + { + m_KeywordDetector.ResetDetector(propertyInstance->EventId); + return STATUS_SUCCESS; + } + + // This sample supports only 1 pattern type. + if (itemsHeader->Count > 1) + { + PropertyRequest->ValueSize = 0; + return STATUS_NOT_SUPPORTED; + } + + // Bytes remaining after the items header + cbRemaining = itemsHeader->Size - sizeof(*itemsHeader); + + // Verify the property value is large enough to include the pattern header. + if (cbRemaining < sizeof(SOUNDDETECTOR_PATTERNHEADER)) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + patternHeader = (SOUNDDETECTOR_PATTERNHEADER*)(itemsHeader + 1); + + // Verify the pattern type is supported. + if (patternHeader->PatternType != CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2) + { + PropertyRequest->ValueSize = 0; + return STATUS_NOT_SUPPORTED; + } + + // Verify the property value is large enough for the pattern. + if (cbRemaining < patternHeader->Size) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + // Verify the pattern is large enough. + if (patternHeader->Size != sizeof(CONTOSO_KEYWORDCONFIGURATION)) + { + PropertyRequest->ValueSize = 0; + return STATUS_INVALID_PARAMETER; + } + + pattern = (CONTOSO_KEYWORDCONFIGURATION*)(patternHeader); + + return m_KeywordDetector.DownloadDetectorData(propertyInstance->EventId, pattern->ContosoDetectorConfigurationData); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed2) +{ + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + RtlZeroMemory(PropertyRequest->Value, PropertyRequest->ValueSize); + return m_KeywordDetector.GetArmed(propertyInstance->EventId, (BOOL*)PropertyRequest->Value); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed2) +{ + NTSTATUS ntStatus; + BOOL armed; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + armed = ((*(BOOL*)PropertyRequest->Value) != 0); + + ntStatus = m_KeywordDetector.SetArmed(propertyInstance->EventId, armed); + + // THIS BLOCK IS FOR SYSVAD TESTING ONLY AND WILL NEED TO BE REMOVED + if (NT_SUCCESS(ntStatus) && armed && + (propertyInstance->EventId == CONTOSO_KEYWORD1 || + propertyInstance->EventId == CONTOSO_KEYWORD2)) + { + CONTOSO_KEYWORDDETECTIONRESULT value = {0}; + + m_KeywordDetector.NotifyDetection(); + + value.EventId = propertyInstance->EventId; + value.Header.Size = sizeof(CONTOSO_KEYWORDDETECTIONRESULT); + value.Header.PatternType = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + value.KeywordStartTimestamp = m_KeywordDetector.GetStartTimestamp(); + value.KeywordStopTimestamp = m_KeywordDetector.GetStopTimestamp(); + m_KeywordDetector.GetDetectorData(propertyInstance->EventId, &(value.ContosoDetectorResultData)); + + SendPNPNotification(&KSNOTIFICATIONID_SoundDetector, &value, sizeof(value)); + } + + return ntStatus; +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorReset2) +{ + NTSTATUS ntStatus = STATUS_SUCCESS; + BOOL reset; + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + reset = ((*(BOOL*)PropertyRequest->Value) != 0); + + if (reset) + { + ntStatus = m_KeywordDetector.ResetDetector(propertyInstance->EventId); + } + + return ntStatus; +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorStreamingSupport2) +{ + PKSSOUNDDETECTORPROPERTY propertyInstance = NULL; + + PAGED_CODE(); + + if (PropertyRequest->InstanceSize < (sizeof(KSSOUNDDETECTORPROPERTY) - RTL_SIZEOF_THROUGH_FIELD(KSSOUNDDETECTORPROPERTY, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSSOUNDDETECTORPROPERTY, EventId); + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof BOOL. + NT_ASSERT(PropertyRequest->ValueSize >= sizeof(BOOL)); + + RtlZeroMemory(PropertyRequest->Value, PropertyRequest->ValueSize); + return m_KeywordDetector.GetStreamingSupport(propertyInstance->EventId, (BOOL*)PropertyRequest->Value); +} + +DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_InterleavedFormatInformation) +{ + PAGED_CODE(); + + PKSP_PIN propertyInstance = NULL; + + // being a SYSVADPROPERTY, the property item is a SYSVADPROPERTY_ITEM, which contains + // some context information from the endpoint + SYSVADPROPERTY_ITEM* item = (SYSVADPROPERTY_ITEM*)PropertyRequest->PropertyItem; + + // retrieve the pin information, so we can validate that this was called on the keyword pin + if (PropertyRequest->InstanceSize < (sizeof(KSP_PIN) - RTL_SIZEOF_THROUGH_FIELD(KSP_PIN, Property))) + { + return STATUS_INVALID_PARAMETER; + } + + propertyInstance = CONTAINING_RECORD(PropertyRequest->Instance, KSP_PIN, PinId); + + // Only Keyword burst pins may support interleaving loopback and microphone audio + if (!IsKeywordDetectorPin(propertyInstance->PinId)) + { + return STATUS_INVALID_PARAMETER; + } + + // If the context data provided for this endpoint is invalid, or if it is larger than the amount + // of data requested, then we have an invalid parameter + if (NULL == item->ContextData || item->ContextDataSize > PropertyRequest->ValueSize) + { + return STATUS_INVALID_PARAMETER; + } + + // copy the context data (which is interleaving information), into the output. + RtlCopyMemory(PropertyRequest->Value, item->ContextData , item->ContextDataSize); + + return STATUS_SUCCESS; +} + + #pragma code_seg() NTSTATUS CMiniportWaveRT_EventHandler_SoundDetectorMatchDetected ( @@ -3101,10 +3442,13 @@ exit: #pragma code_seg("PAGE") CKeywordDetector::CKeywordDetector() : + m_streamRunning(FALSE), m_qpcStartCapture(0), m_nLastQueuedPacket(-1), - m_SoundDetectorArmed(FALSE), - m_SoundDetectorData(0), + m_SoundDetectorArmed1(FALSE), + m_SoundDetectorArmed2(FALSE), + m_SoundDetectorData1(0), + m_SoundDetectorData2(0), m_ullKeywordStartTimestamp(0), m_ullKeywordStopTimestamp(0) { @@ -3165,29 +3509,96 @@ NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -VOID CKeywordDetector::ResetDetector() +NTSTATUS CKeywordDetector::ResetDetector(_In_ GUID eventId) { PAGED_CODE(); - m_SoundDetectorData = 0; + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else if(eventId == GUID_NULL) + { + // When DownloadDetectorData is called to set the pattern for multiple keywords + // at once, all keyword detectors must be reset. Also used during keyword detector + // initialization and cleanup to restore it back to initial state and power down. + m_SoundDetectorData1 = 0; + m_SoundDetectorArmed1 = FALSE; + m_SoundDetectorData2 = 0; + m_SoundDetectorArmed2 = FALSE; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; } #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -VOID CKeywordDetector::DownloadDetectorData(_In_ LONGLONG Data) +NTSTATUS CKeywordDetector::DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data) { PAGED_CODE(); - m_SoundDetectorData = Data; + // reset the detector for this event Id + ResetDetector(eventId); + + // In this example, the driver supports detection data + // set with a single call for both detectors, or each + // detector set individually. + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = Data; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = Data; + } + else if(eventId == GUID_NULL) + { + // in this simplified example "Data" is set on both detectors, + // however in a real system "Data" could be a data structure which + // contains different values for each detector. + m_SoundDetectorData1 = m_SoundDetectorData2 = Data; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; } +// The following function is only applicable to single keyword detection systems, +// and assumes keyword detector #1. #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -LONGLONG CKeywordDetector::GetDetectorData() +NTSTATUS CKeywordDetector::GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data) { PAGED_CODE(); - return m_SoundDetectorData; + if (eventId == CONTOSO_KEYWORD1) + { + *Data = m_SoundDetectorData1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Data = m_SoundDetectorData2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + + return STATUS_SUCCESS; } #pragma code_seg("PAGE") @@ -3228,30 +3639,85 @@ VOID CKeywordDetector::ResetFifo() #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS CKeywordDetector::SetArmed(_In_ BOOL Arm) +NTSTATUS CKeywordDetector::SetArmed(_In_ GUID eventId, _In_ BOOL Arm) { PAGED_CODE(); - BOOL previousArming = m_SoundDetectorArmed; + BOOL previousArming = FALSE; NTSTATUS ntStatus = STATUS_SUCCESS; - m_SoundDetectorArmed = Arm; + // the previous state is "armed" if either detector is armed. + // this reflects the fact that both detectors are sharing the + // same stream. + previousArming = m_SoundDetectorArmed1 || m_SoundDetectorArmed2; + + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorArmed1 = Arm; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorArmed2 = Arm; + } + else + { + return STATUS_INVALID_PARAMETER; + } if (Arm && !previousArming && m_qpcStartCapture == 0) { - ntStatus = ReadKeywordTimestampRegistry(); StartBufferingStream(); } + else if (!Arm && previousArming && !m_streamRunning) + { + // if it's not actively streaming and everything has been disarmed, + // then stop buffering. + ResetFifo(); + } + return ntStatus; } #pragma code_seg("PAGE") _IRQL_requires_max_(PASSIVE_LEVEL) -BOOL CKeywordDetector::GetArmed() +NTSTATUS CKeywordDetector::GetArmed(_In_ GUID eventId, _Out_ BOOL *Arm) { PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; - return m_SoundDetectorArmed; + if (eventId == CONTOSO_KEYWORD1) + { + *Arm = m_SoundDetectorArmed1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Arm = m_SoundDetectorArmed2; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return ntStatus; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetStreamingSupport(_In_ GUID eventId, _Out_ BOOL *Support) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (eventId == GUID_NULL) + { + *Support = TRUE; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return ntStatus; } #pragma code_seg("PAGE") @@ -3264,6 +3730,8 @@ VOID CKeywordDetector::Run() { StartBufferingStream(); } + + m_streamRunning = TRUE; } #pragma code_seg("PAGE") @@ -3273,6 +3741,7 @@ VOID CKeywordDetector::Stop() PAGED_CODE(); ResetFifo(); + m_streamRunning = FALSE; } #pragma code_seg("PAGE") @@ -3289,6 +3758,63 @@ VOID CKeywordDetector::StartBufferingStream() qpc = KeQueryPerformanceCounter(&qpcFrequency); m_qpcStartCapture = qpc.QuadPart; + m_qpcFrequency = qpcFrequency.QuadPart; + + return; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::NotifyDetection() +{ + PAGED_CODE(); + + // A detection will only happen if armed and the + // stream is already running. If there isn't a client + // running, then set the stream start time to align + // with this detection. + if (!m_streamRunning) + { + StartBufferingStream(); + + // The following code is for testing purposes only. + // m_qpcFrequency is defined to be the number of ticks in 1 second. + // Use the stream start time (the current time retrieved in StartBufferStream) to + // mark when the keyword ended, and the start time minus 1 second worth of ticks + // to mark when the keyword started. Also, adjust the stream start time to align + // to this new keyword start time, so that the simulated stream contains the full keyword. + + m_ullKeywordStopTimestamp = m_qpcStartCapture; // stop time is the current time + m_qpcStartCapture = m_qpcStartCapture - m_qpcFrequency; // buffer start time is 1 second ago + m_ullKeywordStartTimestamp = m_qpcStartCapture; // buffer start time = keyword start time + + } + else + { + // The following code is for testing purposes only. + // If the stream is running, we cannot modify qpcStartCapture to be in + // the past, so instead make the keyword start & stop times fit within the + // time period that the keyword has been running. If it has been running + // for more than 1 second, then set the keyword start time to be 1 second back + // into the stream, as though we just figured out there was a keyword there. + // If it has been running less than one second, then the keyword size ends + // up being however long the stream has been running. + + LARGE_INTEGER qpc; + qpc = KeQueryPerformanceCounter(NULL); + + m_ullKeywordStopTimestamp = qpc.QuadPart; // stop time is the current time + + if (m_qpcStartCapture < (qpc.QuadPart - m_qpcFrequency)) + { + m_ullKeywordStartTimestamp = (qpc.QuadPart - m_qpcFrequency); + } + else + { + m_ullKeywordStartTimestamp = m_qpcStartCapture; + } + + } return; } diff --git a/audio/sysvad/EndpointsCommon/minwavert.h b/audio/sysvad/EndpointsCommon/minwavert.h index 21c92542..00534650 100644 --- a/audio/sysvad/EndpointsCommon/minwavert.h +++ b/audio/sysvad/EndpointsCommon/minwavert.h @@ -40,13 +40,13 @@ public: CKeywordDetector(); _IRQL_requires_max_(PASSIVE_LEVEL) - VOID ResetDetector(); + NTSTATUS ResetDetector(_In_ GUID eventId); _IRQL_requires_max_(PASSIVE_LEVEL) - VOID DownloadDetectorData(_In_ LONGLONG Data); + NTSTATUS DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data); _IRQL_requires_max_(PASSIVE_LEVEL) - LONGLONG GetDetectorData(); + NTSTATUS GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data); _IRQL_requires_max_(PASSIVE_LEVEL) ULONGLONG GetStartTimestamp(); @@ -55,10 +55,16 @@ public: ULONGLONG GetStopTimestamp(); _IRQL_requires_max_(PASSIVE_LEVEL) - NTSTATUS SetArmed(_In_ BOOL Arm); + NTSTATUS SetArmed(_In_ GUID eventId, _In_ BOOL Arm); _IRQL_requires_max_(PASSIVE_LEVEL) - BOOL GetArmed(); + VOID NotifyDetection(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetArmed(_In_ GUID eventId, _Out_ BOOL *Arm); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetStreamingSupport(_In_ GUID eventId, _Out_ BOOL *Support); _IRQL_requires_max_(PASSIVE_LEVEL) VOID Run(); @@ -95,10 +101,15 @@ private: UINT16 Samples[SamplesPerPacket]; } PACKET_ENTRY; - BOOL m_SoundDetectorArmed; - LONGLONG m_SoundDetectorData; + BOOL m_streamRunning; + + BOOL m_SoundDetectorArmed1; + BOOL m_SoundDetectorArmed2; + LONGLONG m_SoundDetectorData1; + LONGLONG m_SoundDetectorData2; LONGLONG m_qpcStartCapture; + LONGLONG m_qpcFrequency; LONGLONG m_nLastQueuedPacket; ULONGLONG m_ullKeywordStartTimestamp; @@ -181,7 +192,17 @@ public: DECLARE_PROPERTYHANDLER(Get_SoundDetectorArmed); DECLARE_PROPERTYHANDLER(Set_SoundDetectorArmed); DECLARE_PROPERTYHANDLER(Get_SoundDetectorMatchResult); - + + DECLARE_PROPERTYHANDLER(Get_SoundDetectorSupportedPatterns2); + DECLARE_PROPERTYHANDLER(Set_SoundDetectorPatterns2); + DECLARE_PROPERTYHANDLER(Get_SoundDetectorArmed2); + DECLARE_PROPERTYHANDLER(Set_SoundDetectorArmed2); + DECLARE_PROPERTYHANDLER(Set_SoundDetectorReset2); + DECLARE_PROPERTYHANDLER(Get_SoundDetectorStreamingSupport2); + + DECLARE_PROPERTYHANDLER(Get_InterleavedFormatInformation); + + NTSTATUS EventHandler_PinCapsChange ( _In_ PPCEVENT_REQUEST EventRequest @@ -250,6 +271,12 @@ protected: _In_ ULONG NodeId ); + VOID SendPNPNotification( + _In_ const GUID * NotificationId, + _In_ PVOID NotificationBuffer, + _In_ USHORT NotificationBufferCb + ); + public: DECLARE_STD_UNKNOWN(); @@ -319,13 +346,13 @@ public: else { // - // >= comparison here because capture bridge pin comes first in the enumeration + // capture bridge pin comes first in the enumeration // - if (m_FilterDesc.PinCount >= KSPIN_WAVEIN_HOST) + if (m_FilterDesc.PinCount > KSPIN_WAVEIN_HOST) { m_ulMaxSystemStreams = m_FilterDesc.Pins[KSPIN_WAVEIN_HOST].MaxFilterInstanceCount; } - if (m_FilterDesc.PinCount >= KSPIN_WAVEIN_KEYWORD) + if (m_FilterDesc.PinCount > KSPIN_WAVEIN_KEYWORD) { m_ulMaxKeywordDetectorStreams = m_FilterDesc.Pins[KSPIN_WAVEIN_KEYWORD].MaxFilterInstanceCount; } @@ -534,6 +561,7 @@ protected: m_DeviceType == eSpdifRenderDevice || m_DeviceType == eBthHfpSpeakerDevice || m_DeviceType == eUsbHsSpeakerDevice || + m_DeviceType == eA2dpHpSpeakerDevice || m_DeviceType == eHandsetSpeakerDevice) ? TRUE : FALSE; } @@ -595,7 +623,6 @@ protected: return KSPIN_WAVE_RENDER_SINK_OFFLOAD; } -#pragma code_seg() ULONG GetAudioModuleDescriptorListCount() @@ -666,7 +693,8 @@ public: return (m_DeviceType == eBthHfpMicDevice || m_DeviceType == eBthHfpSpeakerDevice || m_DeviceType == eUsbHsMicDevice || - m_DeviceType == eUsbHsSpeakerDevice ) ? TRUE : FALSE; + m_DeviceType == eUsbHsSpeakerDevice || + m_DeviceType == eA2dpHpSpeakerDevice ) ? TRUE : FALSE; } // Returns a weak ref to the Bluetooth HFP device. diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp index 9ea47c56..93ecdcf3 100644 --- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp +++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp @@ -889,8 +889,7 @@ Done: // // Return value // -// Returns STATUS_OPERATION_IN_PROGRESS if no new packets are available and -// the next packet is in progress. +// Returns STATUS_DEVICE_NOT_READY if no new packets are available. // // IRQL - PASSIVE_LEVEL // @@ -900,6 +899,7 @@ Done: // // ISSUE-2014/10/4 Will this work correctly across pause/play? #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::GetReadPacket ( _Out_ ULONG *PacketNumber, @@ -993,24 +993,11 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket // Update the last packet read by the OS m_ulLastOsReadPacket = availablePacketNumber; -#if 0 - // For test, embed packet number and timestamp into first two LONGLONGs of the packet - LONG packetIndex = availablePacketNumber % m_ulNotificationsPerBuffer; - SIZE_T packetSize = m_ulDmaBufferSize / m_ulNotificationsPerBuffer; - BYTE *packetDataAsBytes = m_pDmaBuffer + (packetIndex * packetSize); - LONGLONG *packetDataAsLonglongs = (LONGLONG*)packetDataAsBytes; - for (int i = 0; i < packetSize / sizeof(LONGLONG); i++) - { - packetDataAsLonglongs[i] = i; - } - packetDataAsLonglongs[0] = availablePacketNumber; - packetDataAsLonglongs[1] = timeOfAvailablePacketInQpc; -#endif - return STATUS_SUCCESS; } #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::SetWritePacket ( _In_ ULONG PacketNumber, @@ -1103,6 +1090,7 @@ NTSTATUS CMiniportWaveRTStream::SetWritePacket //============================================================================= #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition ( _Out_ KSAUDIO_PRESENTATION_POSITION *pPresentationPosition @@ -1121,6 +1109,7 @@ NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition //============================================================================= #pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS CMiniportWaveRTStream::GetPacketCount ( _Out_ ULONG *pPacketCount diff --git a/audio/sysvad/EndpointsCommon/sources b/audio/sysvad/EndpointsCommon/sources deleted file mode 100644 index 4ac1b852..00000000 --- a/audio/sysvad/EndpointsCommon/sources +++ /dev/null @@ -1,48 +0,0 @@ - -# Copyright (c) Microsoft Corporation. All rights reserved. - - -TARGETNAME=EndpointsCommon -TARGETTYPE=LIBRARY -KM_LIBRARY=1 - -INCLUDES= \ - $(DDK_INC_PATH); \ - .. - - -C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS -DSYSVAD_USB_SIDEBAND -#C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ - -DDK_TARGET_PLATFORM=Universal - -# -# Indicate to the WDK that this sample only supports Win10[+] -# -MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) - -# -# Audio driver is a KMDF miniport. -# -KMDF_VERSION_MAJOR=1 - - -SOURCES=$(SOURCES) \ - AudioModuleHelper.cpp \ - bthhfptopo.cpp \ - bthhfpmictopo.cpp \ - bthhfpspeakertopo.cpp \ - bthhfpminwavert.cpp \ - micarraytopo.cpp \ - MiniportAudioEngineNode.cpp \ - MiniportStreamAudioEngineNode.cpp \ - mintopo.cpp \ - minwavert.cpp \ - minwavertstream.cpp \ - speakertopo.cpp \ - speakerhptopo.cpp \ - usbhstopo.cpp \ - usbhsmictopo.cpp \ - usbhsspeakertopo.cpp \ - usbhsminwavert.cpp \ - diff --git a/audio/sysvad/EndpointsCommon/speakerhptoptable.h b/audio/sysvad/EndpointsCommon/speakerhptoptable.h index dece62fa..3a851dce 100644 --- a/audio/sysvad/EndpointsCommon/speakerhptoptable.h +++ b/audio/sysvad/EndpointsCommon/speakerhptoptable.h @@ -15,7 +15,7 @@ Abstract: #ifndef _SYSVAD_SPEAKERHPTOPTABLE_H_ #define _SYSVAD_SPEAKERHPTOPTABLE_H_ -#include "mintopo.h" +#include <mintopo.h> //============================================================================= static diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.cpp b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.cpp index 088c0751..c88b1ae0 100644 --- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.cpp +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.cpp @@ -23,12 +23,12 @@ public: } STDMETHODIMP KeywordDetectorContosoAdapter::GetCapabilities( - BOOL* SupportsUserModels, - KEYWORDID** KeywordIds, - ULONG* NumKeywords, - LANGID** LangIds, - ULONG* NumLanguages, - IMFMediaType* *ppMediaType) + _Out_ BOOL* SupportsUserModels, + _Outptr_ KEYWORDID** KeywordIds, + _Out_ ULONG* NumKeywords, + _Outptr_ LANGID** LangIds, + _Out_ ULONG* NumLanguages, + _Outptr_ IMFMediaType* *ppMediaType) { HRESULT hr; ComPtr<IMFMediaType> spMFType; @@ -63,15 +63,20 @@ public: } } + if (*ppMediaType == nullptr) + { + return E_FAIL; + } + return hr; } STDMETHODIMP VerifyUserKeyword( - IStream* ModelData, - KEYWORDID KeywordId, - LANGID LangId, - LONG KeywordEndBytePos, - IMFMediaBuffer* UserRecording) + _In_ IStream* ModelData, + _In_ KEYWORDID KeywordId, + _In_ LANGID LangId, + _In_ LONG KeywordEndBytePos, + _In_ IMFMediaBuffer* UserRecording) { UNREFERENCED_PARAMETER(ModelData); UNREFERENCED_PARAMETER(KeywordId); @@ -83,11 +88,11 @@ public: } STDMETHODIMP ComputeAndAddUserModelData( - IStream* ModelData, - KEYWORDSELECTOR KeywordSelector, - LONG *KeywordEndBytePos, - IMFMediaBuffer **UserRecordings, - ULONG NumUserRecordings) + _Inout_ IStream* ModelData, + _In_ KEYWORDSELECTOR KeywordSelector, + _In_ LONG *KeywordEndBytePos, + _In_ IMFMediaBuffer **UserRecordings, + _In_ ULONG NumUserRecordings) { UNREFERENCED_PARAMETER(ModelData); UNREFERENCED_PARAMETER(KeywordSelector); @@ -99,10 +104,10 @@ public: } STDMETHODIMP BuildArmingPatternData( - IStream *ModelData, - KEYWORDSELECTOR *KeywordSelectors, - ULONG NumKeywordSelectors, - SOUNDDETECTOR_PATTERNHEADER **ppPatternData) + _In_ IStream *ModelData, + _In_ KEYWORDSELECTOR *KeywordSelectors, + _In_ ULONG NumKeywordSelectors, + _Outptr_ SOUNDDETECTOR_PATTERNHEADER **ppPatternData) { CONTOSO_KEYWORDCONFIGURATION *pPatternData = nullptr; @@ -135,15 +140,15 @@ public: } STDMETHODIMP ParseDetectionResultData( - IStream *ModelData, - SOUNDDETECTOR_PATTERNHEADER *Result, // ISSUE-2015/1/14-frankye should be const - KEYWORDID* KeywordId, - LANGID* LangId, - BOOL *pIsUserMatch, - ULONG64 *KeywordStartPerformanceCounterValue, - ULONG64 *KeywordEndPerformanceCounterValue) + _In_ IStream *ModelData, + _In_ SOUNDDETECTOR_PATTERNHEADER *Result, // ISSUE-2015/1/14-frankye should be const + _Out_ KEYWORDID* KeywordId, + _Out_ LANGID* LangId, + _Out_ BOOL *pIsUserMatch, + _Out_ ULONG64 *KeywordStartPerformanceCounterValue, + _Out_ ULONG64 *KeywordEndPerformanceCounterValue) { - const CONTOSO_KEYWORDDETECTIONRESULT *contosoResult; + // const CONTOSO_KEYWORDDETECTIONRESULT *contosoResult; UNREFERENCED_PARAMETER(ModelData); @@ -152,7 +157,7 @@ public: return E_INVALIDARG; } - contosoResult = (CONTOSO_KEYWORDDETECTIONRESULT*)Result; + // contosoResult = (CONTOSO_KEYWORDDETECTIONRESULT*)Result; // Do something with the result data to determine return parameters // PostProcessResult(contosoResult->ContosoDetectorResultData, contosoResult->KeywordStartTimestamp, contosoResult->KeywordStopTimestamp); @@ -169,3 +174,201 @@ public: }; CoCreatableClass(KeywordDetectorContosoAdapter); + +class EventDetectorContosoAdapter : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IEventDetectorOemAdapter> +{ +public: + EventDetectorContosoAdapter() + { + } + + STDMETHODIMP GetCapabilities( + _Out_ EVENTFEATURES* GlobalFeatureSupport, + _Outptr_ LANGID** LangIds, + _Out_ ULONG* NumLanguages, + _Out_ ULONG* NumUserRecordings, + _Outptr_ WAVEFORMATEX** ppFormat) + { + const WAVEFORMATEX waveFormat = { WAVE_FORMAT_PCM, 1, 16000, 32000, 2, 16, 0 }; + + *ppFormat = (WAVEFORMATEX *)CoTaskMemAlloc(sizeof(WAVEFORMATEX)); + if (*ppFormat == nullptr) + { + return E_OUTOFMEMORY; + } + + memcpy(*ppFormat, &waveFormat, sizeof(WAVEFORMATEX)); + + *GlobalFeatureSupport = EVENTFEATURES_NoEventFeatures; + + *LangIds = (LANGID *)CoTaskMemAlloc(sizeof(LANGID)); + + if (*LangIds == nullptr) + { + return E_OUTOFMEMORY; + } + + **LangIds = 0x0409; + *NumLanguages = 1; + *NumUserRecordings = 0; + + return S_OK; + } + + STDMETHODIMP GetCapabilitiesForLanguage( + _In_ LANGID LangId, + _Outptr_ DETECTIONEVENT** EventIds, + _Out_ ULONG* NumEvents) + { + if (LangId == 0x0409) + { + DETECTIONEVENT events[] = { { CONTOSO_KEYWORD1, EVENTFEATURES_NoEventFeatures, {0}, L"Contoso 1", TRUE }, + { CONTOSO_KEYWORD2, EVENTFEATURES_NoEventFeatures, {0}, L"Contoso 2", TRUE } }; + + *EventIds = (DETECTIONEVENT *)CoTaskMemAlloc(sizeof(events)); + if (*EventIds == nullptr) + { + return E_OUTOFMEMORY; + } + + memcpy(*EventIds, &events, sizeof(events)); + *NumEvents = 2; + } + else + { + return E_INVALIDARG; + } + + return S_OK; + } + + STDMETHODIMP VerifyUserEventData( + _In_ IStream* ModelData, + _In_ WAVEFORMATEX* UserRecording, + _In_ DETECTIONEVENTSELECTOR EventSelector, + _In_ LONG EventEndBytePos) + { + UNREFERENCED_PARAMETER(ModelData); + UNREFERENCED_PARAMETER(UserRecording); + UNREFERENCED_PARAMETER(EventSelector); + UNREFERENCED_PARAMETER(EventEndBytePos); + + return E_NOTIMPL; + } + + STDMETHODIMP ComputeAndAddUserModelData( + _Inout_ IStream* ModelData, + _In_ DETECTIONEVENTSELECTOR EventSelector, + _In_ LONG* EventEndBytePos, + _In_ WAVEFORMATEX** UserRecordings, + _In_ ULONG NumUserRecordings) + { + UNREFERENCED_PARAMETER(ModelData); + UNREFERENCED_PARAMETER(EventSelector); + UNREFERENCED_PARAMETER(EventEndBytePos); + UNREFERENCED_PARAMETER(UserRecordings); + UNREFERENCED_PARAMETER(NumUserRecordings); + + return E_NOTIMPL; + } + + STDMETHODIMP BuildArmingPatternData( + _In_ IStream* UserModelData, + _In_ DETECTIONEVENTSELECTOR* EventSelectors, + _In_ ULONG NumEventSelectors, + _Outptr_ SOUNDDETECTOR_PATTERNHEADER** ppPatternData) + { + CONTOSO_KEYWORDCONFIGURATION *pPatternData = nullptr; + + UNREFERENCED_PARAMETER(UserModelData); + + if (NumEventSelectors > 2) + { + return E_INVALIDARG; + } + + if ((EventSelectors[0].Event.EventId != CONTOSO_KEYWORD1 && EventSelectors[0].Event.EventId != CONTOSO_KEYWORD2) || + (EventSelectors[0].UserId != 0) || (EventSelectors[0].LangId != 0x0409)) + { + return E_INVALIDARG; + } + + pPatternData = (CONTOSO_KEYWORDCONFIGURATION*)CoTaskMemAlloc(sizeof(CONTOSO_KEYWORDCONFIGURATION)); + if (pPatternData == nullptr) + { + return E_OUTOFMEMORY; + } + + pPatternData->Header.Size = sizeof(*pPatternData); + pPatternData->Header.PatternType = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + pPatternData->ContosoDetectorConfigurationData = 0x12345678; + + *ppPatternData = &pPatternData->Header; + pPatternData = nullptr; + + return S_OK; + } + + STDMETHODIMP ParseDetectionResultData( + _In_ IStream* UserModelData, + _In_ SOUNDDETECTOR_PATTERNHEADER* Result, + _Outptr_ SOUNDDETECTOR_PATTERNHEADER** AssistantContext, + _Out_ DETECTIONEVENTSELECTOR* EventSelector, + _Out_ EVENTACTION* EventAction, + _Out_ ULONG64* EventStartPerformanceCounterValue, + _Out_ ULONG64* EventEndPerformanceCounterValue, + _Outptr_ WCHAR** DebugOutput) + { + const CONTOSO_KEYWORDDETECTIONRESULT *contosoResult; + + UNREFERENCED_PARAMETER(UserModelData); + UNREFERENCED_PARAMETER(DebugOutput); + UNREFERENCED_PARAMETER(AssistantContext); + + if (Result->PatternType != CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2 || Result->Size < sizeof(CONTOSO_KEYWORDDETECTIONRESULT)) + { + return E_INVALIDARG; + } + + contosoResult = (CONTOSO_KEYWORDDETECTIONRESULT*)Result; + + if (CONTOSO_KEYWORD1 == contosoResult->EventId) + { + wcscpy_s(EventSelector->Event.DisplayName, L"Contoso 1"); + } + else if (CONTOSO_KEYWORD2 == contosoResult->EventId) + { + wcscpy_s(EventSelector->Event.DisplayName, L"Contoso 2"); + } + else + { + return E_INVALIDARG; + } + + // Fill in event action information for the actual detection, based on what has been armed. + EventSelector->Event.EventId = contosoResult->EventId; + EventSelector->Armed = TRUE; + EventSelector->UserId = 0; + EventSelector->LangId = 0x0409; + + EventAction->EventdActionType = EVENTACTIONTYPE_Accept; + EventAction->EventActionContextType = EVENTACTIONCONTEXTTYPE_None; + + // Retrieve the event start/stop times for the payload + *EventStartPerformanceCounterValue = contosoResult->KeywordStartTimestamp; + *EventEndPerformanceCounterValue = contosoResult->KeywordStopTimestamp; + + return S_OK; + } + + STDMETHODIMP_(void) ReportOSDetectionResult( + _In_ DETECTIONEVENTSELECTOR EventSelector, + _In_ EVENTACTION EventAction) + { + UNREFERENCED_PARAMETER(EventSelector); + UNREFERENCED_PARAMETER(EventAction); + } +}; + +CoCreatableClass(EventDetectorContosoAdapter); + diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.idl b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.idl index 47431ce7..80c6342d 100644 --- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.idl +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.idl @@ -2,6 +2,7 @@ import "oaidl.idl"; import "ocidl.idl"; import "KeywordDetectorOemAdapter.idl"; +import "EventDetectorOemAdapter.idl"; [uuid(9D3E6826-CB8E-4D86-8B14-89F0D7EFCD01), version(1.0)] library KeywordDetectorContosoAdapterLib @@ -13,4 +14,14 @@ library KeywordDetectorContosoAdapterLib { [default] interface IKeywordDetectorOemAdapter; } + + // The class's uuid (i.e. the COM CLSID) must match that of the pattern + // type GUID returned by the audio driver + // 0x207f3d0c, 0x5c79, 0x496f, 0xa9, 0x4c, 0xd3, 0xd2, 0x93, 0x4d, 0xbf, 0xa9 + [uuid(207F3D0C-5C79-496F-A94C-D3D2934DBFA9), version(1.0)] + coclass EventDetectorContosoAdapter + { + [default] interface IKeywordDetectorOemAdapter; + } }; + diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj index 898fa184..d1675201 100644 --- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj +++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> @@ -13,10 +9,6 @@ <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> @@ -84,14 +76,6 @@ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> @@ -100,14 +84,6 @@ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> <ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType /> - <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> - <ConfigurationType>DynamicLibrary</ConfigurationType> - </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <OutDir>$(IntDir)</OutDir> @@ -127,15 +103,9 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>KeywordDetectorContosoAdapter</TargetName> @@ -152,15 +122,9 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <TargetName>KeywordDetectorContosoAdapter</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <TargetName>KeywordDetectorContosoAdapter</TargetName> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetName>KeywordDetectorContosoAdapter</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <TargetName>KeywordDetectorContosoAdapter</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> @@ -191,24 +155,12 @@ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Link> <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <Link> - <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> - <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> - </Link> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ClCompile> <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> @@ -329,30 +281,6 @@ <ModuleDefinitionFile>KeywordDetectorContosoAdapter.def</ModuleDefinitionFile> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> - <ModuleDefinitionFile>KeywordDetectorContosoAdapter.def</ModuleDefinitionFile> - </Link> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> @@ -377,30 +305,6 @@ <ModuleDefinitionFile>KeywordDetectorContosoAdapter.def</ModuleDefinitionFile> </Link> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <ClCompile> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> - <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> - </ResourceCompile> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> - <ModuleDefinitionFile>KeywordDetectorContosoAdapter.def</ModuleDefinitionFile> - </Link> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="dllmain.cpp" /> <ClCompile Include="KeywordDetectorContosoAdapter.cpp" /> diff --git a/audio/sysvad/KeywordDetectorAdapter/sources b/audio/sysvad/KeywordDetectorAdapter/sources deleted file mode 100644 index 8b17ac8b..00000000 --- a/audio/sysvad/KeywordDetectorAdapter/sources +++ /dev/null @@ -1,53 +0,0 @@ -TARGETTYPE=DYNLINK -TARGETNAME=KeywordDetectorContosoAdapter - -DLLENTRY=_DllMainCRTStartup -DLLDEF=KeywordDetectorContosoAdapter.def -#USE_ATL=1 - - -USE_LIBCMT=1 - -MSC_WARNING_LEVEL=-W4 \ - -WX - -C_DEFINES=$(C_DEFINES) \ - -D_WINDLL \ - -D_USRDLL \ - -DUNICODE \ - -D_UNICODE - -# -# Indicate to the WDK that this sample only supports Win10[+] -# -MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) - -# Indicate that this DLL must be included in the driver package -DDK_NO_PACKAGE_PROJECT=0 -DDK_INCLUDE_PACKAGE_PROJECT=1 - -INCLUDES= \ - $(DDK_INC_PATH); \ - ..\inc;..\; \ - -SOURCES=KeywordDetectorContosoAdapter.idl \ - KeywordDetectorContosoAdapter.rc \ - dllmain.cpp \ - KeywordDetectorContosoAdapter.cpp \ - stdafx.cpp \ - - -TARGETLIBS= \ - $(SDK_LIB_PATH)\onecore_downlevel.lib \ - $(SDK_LIB_PATH)\onecore_downlevel.lib \ - $(SDK_LIB_PATH)\oleaut32.lib \ - \ - $(ONECORE_PRIV_SDK_LIB_PATH)\OneCore_Forwarder_user32.lib \ - $(INTERNAL_SDK_LIB_PATH)\onecoreuapuuid.lib \ - $(SDK_LIB_PATH)\mfplat.lib \ - $(SDK_LIB_PATH)\runtimeobject.lib \ - - - -MUI_VERIFY_NO_LOC_RESOURCE=1 - diff --git a/audio/sysvad/Package/package.VcxProj b/audio/sysvad/Package/package.VcxProj index 2874ff42..dba6d6b4 100644 --- a/audio/sysvad/Package/package.VcxProj +++ b/audio/sysvad/Package/package.VcxProj @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> @@ -13,10 +9,6 @@ <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> @@ -47,6 +39,9 @@ <ProjectReference Include="..\APO\DelayAPO\DelayAPO.vcxproj"> <Project>{8851AB85-70B3-4798-A149-BA366DF9EC25}</Project> </ProjectReference> + <ProjectReference Include="..\APO\KWSApo\KwsAPO.vcxproj"> + <Project>{47358AD6-A48A-465B-965F-0A66F8BDFE23}</Project> + </ProjectReference> <ProjectReference Include="..\TabletAudioSample\TabletAudioSample.vcxproj"> <Project>{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}</Project> </ProjectReference> @@ -68,18 +63,10 @@ <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>true</UseDebugLibraries> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>true</UseDebugLibraries> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>false</UseDebugLibraries> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>false</UseDebugLibraries> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>true</UseDebugLibraries> diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj index 595ccfa6..49ccee70 100644 --- a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj +++ b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> @@ -13,10 +9,6 @@ <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> @@ -85,14 +77,6 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> @@ -101,14 +85,6 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <OutDir>$(IntDir)</OutDir> @@ -128,15 +104,9 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> @@ -248,28 +218,6 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> @@ -292,28 +240,6 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>PhoneAudioSample</TargetName> </PropertyGroup> @@ -329,15 +255,9 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <TargetName>PhoneAudioSample</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <TargetName>PhoneAudioSample</TargetName> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetName>PhoneAudioSample</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <TargetName>PhoneAudioSample</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> @@ -443,26 +363,6 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> </ResourceCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> @@ -483,26 +383,6 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> </ResourceCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="..\adapter.cpp" /> <ClCompile Include="..\basetopo.cpp" /> diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters index c6c87ad1..c57611a0 100644 --- a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters +++ b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters @@ -41,4 +41,4 @@ <Filter>Driver Files</Filter> </Inf> </ItemGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/audio/sysvad/PhoneAudioSample/phoneaudiosample.inx b/audio/sysvad/PhoneAudioSample/phoneaudiosample.inx Binary files differindex c7b6c110..a1d45cf4 100644 --- a/audio/sysvad/PhoneAudioSample/phoneaudiosample.inx +++ b/audio/sysvad/PhoneAudioSample/phoneaudiosample.inx diff --git a/audio/sysvad/PhoneAudioSample/sources b/audio/sysvad/PhoneAudioSample/sources deleted file mode 100644 index e16edb8e..00000000 --- a/audio/sysvad/PhoneAudioSample/sources +++ /dev/null @@ -1,59 +0,0 @@ - -# Copyright (c) Microsoft Corporation. All rights reserved. - - -!include ..\sources.inc - -TARGETNAME=PhoneAudioSample - -TARGETLIBS= \ - $(TARGETLIBS) \ - $(OBJ_PATH)\..\EndpointsCommon\$(O)\EndpointsCommon.lib - - -C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS -DSYSVAD_USB_SIDEBAND -#C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ - -# -# Indicate to the WDK that this sample only supports Win10[+] -# -MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) - -DDK_TARGET_PLATFORM=Universal - -# -# Audio driver is a KMDF miniport. -# -KMDF_VERSION_MAJOR=1 - -# -# Uncomment one of the following lines to select the right power management. -# Note that the single-component/multi-state feature requires also a registry -# value set via the INF. The name of the registry value is SingleComponentMultiFxStates. -# see INF file for more info. -# -C_DEFINES= $(C_DEFINES) -D_USE_IPortClsRuntimePower -#C_DEFINES= $(C_DEFINES) -D_USE_SingleComponentMultiFxStates - -INCLUDES= \ - $(INCLUDES); \ - ..\EndpointsCommon; \ - -SOURCES=$(SOURCES) \ - cellulartopo.cpp \ - fmtopo.cpp \ - handsetspeakertopo.cpp \ - handsetmictopo.cpp \ - michstopo.cpp \ - speakerhstopo.cpp \ - cellularwave.cpp \ - fmwave.cpp \ - PhoneAudioSample.rc \ - -# Indicate that this module must be included in the driver package -DDK_NO_PACKAGE_PROJECT=0 -DDK_INCLUDE_PACKAGE_PROJECT=1 - - -MUI_VERIFY_NO_LOC_RESOURCE=1 - diff --git a/audio/sysvad/README.md b/audio/sysvad/README.md index 0170087b..5a31ab12 100644 --- a/audio/sysvad/README.md +++ b/audio/sysvad/README.md @@ -17,7 +17,8 @@ urlFragment: sysvad-virtual-audio-device-driver-sample samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620183 ---> -# SysVAD Virtual Audio Device Driver Sample +SysVAD Virtual Audio Device Driver Sample +======================================== The Microsoft SysVAD Virtual Audio Device Driver (SYSVAD) shows how to develop a WDM audio driver that exposes support for multiple audio devices. @@ -36,11 +37,14 @@ Directory | Description TabletAudioSample | Endpoints that are present in TabletAudioSample driver. PhoneAudioSample | Endpoints that are present in PhoneAudioSample driver. EndpointsCommon | Endpoints that are present in both TabletAudioSample and PhoneAudioSample. It also contains other common code shared by both sample drivers. -SwapAPO | Sample APO. +SwapAPO | Sample APO that installs onto endpoints exposed by the SysVAD sample driver and swaps the left and right channels. +DelayAPO | Sample APO that adds a delay to the input samples. +KwsAPO | Sample APO that uses KSPROPERTY_INTERLEAVEDAUDIO_FORMATINFORMATION to determine if the keyword spotter pin is interleaving loopback audio with the microphone audio and identify which channels contain loopback audio. If it is interleaved the APO will strip out the loopback audio and deliver only the microphone audio upstream. Because channel data is removed, the APO negotiates an output format which is different than the input format. KeywordDetectorAdapter | Sample Keyword Detector Adapter. For more information about the Windows audio engine, see [Exposing Hardware-Offloaded Audio Processing in Windows](http://msdn.microsoft.com/en-us/windows/hardware/br259116), and note that audio hardware that is offload-capable replicates the architecture that is presented in the diagram shown in the topic. + Build the sample ---------------- @@ -52,11 +56,11 @@ Perform the following steps to build this sample driver. In Microsoft Visual Studio, Click **File** \> **Open** \> **Project/Solution...** and navigate to the folder that contains the sample files (for example, *C:\Windows-driver-samples\audio\sysvad*). Double-click the *sysvad* solution file. -In Visual Studio locate the Solution Explorer. (If this is not already open, choose **Solution Explorer** from the **View** menu.) In Solution Explorer, you can see one solution that has four projects. +In Visual Studio locate the Solution Explorer. (If this is not already open, choose **Solution Explorer** from the **View** menu.) In Solution Explorer, you can see one solution that has eight projects. **2. Set the sample's configuration and platform** -In Solution Explorer, right-click **Solution 'sysvad' (4 projects)**, and choose **Configuration Manager**. Make sure that the configuration and platform settings are the same for the four projects. By default, the configuration is set to **Debug**, and the platform is set to **Win32** for all the projects. If you make any configuration and/or platform changes for one project, you must make the same changes for the remaining three projects. +In Solution Explorer, right-click **Solution 'sysvad' (8 projects)**, and choose **Configuration Manager**. Make sure that the configuration and platform settings are the same for the eight projects. By default, the configuration is set to **Debug**, and the platform is set to **Win32** for all the projects. If you make any configuration and/or platform changes for one project, you must make the same changes for the remaining three projects. **3. Build the sample using Visual Studio** @@ -73,8 +77,9 @@ The package should contain these files: File | Description -----|------------ TabletAudioSample.sys OR PhoneAudioSample.sys| The driver file. -SwapAPO.dll | A sample APO. -DelayAPO.dll | A sample APO. +SwapAPO.dll | The swap APO. +DelayAPO.dll | The delay APO. +KWSApo.dll | The KWS APO. sysvad.cat | A signed catalog file, which serves as the signature for the entire package. TabletAudioSample.inf | An information (INF) file that contains information needed to install the driver. PhoneAudioSample.inf | An information (INF) file that contains information needed to install the driver. @@ -166,3 +171,4 @@ On the target computer, in a Command Prompt window, enter **devmgmt** to open De On the target computer, open Control Panel and navigate to **Hardware and Sound** \> **Manage audio devices**. In the Sound dialog box, select the speaker icon labeled as *Microsoft Virtual Audio Device (WDM) - Tablet Audio Sample*, then click **Set Default**, but do not click **OK**. This will keep the Sound dialog box open. Locate an MP3 or other audio file on the target computer and double-click to play it. Then in the Sound dialog box, verify that there is activity in the volume level indicator associated with the *Microsoft Virtual Audio Device (WDM) - Tablet Audio Sample* driver. + diff --git a/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx b/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx Binary files differindex 43457d73..4ee84101 100644 --- a/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx +++ b/audio/sysvad/TabletAudioSample/ComponentizedApoSample.inx diff --git a/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx b/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx Binary files differindex cd77bd98..a5e6e73f 100644 --- a/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx +++ b/audio/sysvad/TabletAudioSample/ComponentizedAudioSample.inx diff --git a/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx b/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx Binary files differindex a13515cc..4f29c985 100644 --- a/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx +++ b/audio/sysvad/TabletAudioSample/ComponentizedAudioSampleExtension.inx diff --git a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj index ba22dcf1..f7752502 100644 --- a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj +++ b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|ARM"> - <Configuration>Debug</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|ARM64"> <Configuration>Debug</Configuration> <Platform>ARM64</Platform> @@ -13,10 +9,6 @@ <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> - <ProjectConfiguration Include="Release|ARM"> - <Configuration>Release</Configuration> - <Platform>ARM</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Release|ARM64"> <Configuration>Release</Configuration> <Platform>ARM64</Platform> @@ -85,14 +77,6 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>False</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetVersion>Windows10</TargetVersion> <UseDebugLibraries>True</UseDebugLibraries> @@ -101,14 +85,6 @@ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> <ConfigurationType>Driver</ConfigurationType> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> - <TargetVersion>Windows10</TargetVersion> - <UseDebugLibraries>True</UseDebugLibraries> - <DriverTargetPlatform>Universal</DriverTargetPlatform> - <DriverType>KMDF</DriverType> - <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> - <ConfigurationType>Driver</ConfigurationType> - </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <PropertyGroup> <OutDir>$(IntDir)</OutDir> @@ -128,15 +104,9 @@ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> - </ImportGroup> <ItemGroup Label="WrappedTaskItems" /> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> @@ -248,28 +218,6 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> @@ -292,28 +240,6 @@ <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> </Midl> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\portcls.lib;$(DDK_LIB_PATH)\stdunk.lib;$(DDK_LIB_PATH)\libcntpr.lib</AdditionalDependencies> - </Link> - <ResourceCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ResourceCompile> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <TreatWarningAsError>true</TreatWarningAsError> - <WarningLevel>Level4</WarningLevel> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </ClCompile> - <Midl> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..</AdditionalIncludeDirectories> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_WIN32;UNICODE;_UNICODE;PC_IMPLEMENTATION</PreprocessorDefinitions> - <PreprocessorDefinitions>%(PreprocessorDefinitions);DEBUG_LEVEL=DEBUGLVL_TERSE</PreprocessorDefinitions> - </Midl> - </ItemDefinitionGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <TargetName>TabletAudioSample</TargetName> </PropertyGroup> @@ -329,15 +255,9 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <TargetName>TabletAudioSample</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <TargetName>TabletAudioSample</TargetName> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <TargetName>TabletAudioSample</TargetName> </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <TargetName>TabletAudioSample</TargetName> - </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> @@ -441,25 +361,6 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> </ResourceCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Link> <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> @@ -479,26 +380,6 @@ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> </ResourceCompile> </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> - <Link> - <AdditionalDependencies>%(AdditionalDependencies);.\..\EndpointsCommon\$(IntDir)\EndpointsCommon.lib</AdditionalDependencies> - </Link> - <ClCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon;.</AdditionalIncludeDirectories> - <ExceptionHandling> - </ExceptionHandling> - <DisableSpecificWarnings>4595;%(DisableSpecificWarnings)</DisableSpecificWarnings> - </ClCompile> - <Midl> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </Midl> - <ResourceCompile> - <PreprocessorDefinitions>%(PreprocessorDefinitions);_USE_WAVERT_;SYSVAD_BTH_BYPASS;SYSVAD_USB_SIDEBAND;_USE_IPortClsRuntimePower</PreprocessorDefinitions> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\EndpointsCommon</AdditionalIncludeDirectories> - </ResourceCompile> - </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="..\adapter.cpp" /> <ClCompile Include="..\basetopo.cpp" /> diff --git a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters index 643d5929..142c7f02 100644 --- a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters +++ b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters @@ -41,4 +41,4 @@ <Filter>Driver Files</Filter> </Inf> </ItemGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/audio/sysvad/TabletAudioSample/micarray2wavtable.h b/audio/sysvad/TabletAudioSample/micarray2wavtable.h new file mode 100644 index 00000000..1087d5eb --- /dev/null +++ b/audio/sysvad/TabletAudioSample/micarray2wavtable.h @@ -0,0 +1,990 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + micarray2wavtable.h + +Abstract: + + Declaration of wave miniport tables for the rear mic array. + +--*/ + +#ifndef _SYSVAD_MICARRAY2WAVTABLE_H_ +#define _SYSVAD_MICARRAY2WAVTABLE_H_ + +// +// Mic array range. +// +#define MICARRAY2_RAW_CHANNELS 2 // Channels for raw mode +#define MICARRAY2_PROCESSED_CHANNELS 1 // Channels for default mode +#define MICARRAY2_DEVICE_MAX_CHANNELS 2 // Max channels overall +#define MICARRAY2_16_BITS_PER_SAMPLE_PCM 16 // 16 Bits Per Sample +#define MICARRAY2_32_BITS_PER_SAMPLE_PCM 32 // 32 Bits Per Sample +#define MICARRAY2_RAW_SAMPLE_RATE 48000 // Raw sample rate +#define MICARRAY2_PROCESSED_MIN_SAMPLE_RATE 8000 // Min Sample Rate +#define MICARRAY2_PROCESSED_MAX_SAMPLE_RATE 48000 // Max Sample Rate + +// +// Max # of pin instances. +// +#define MICARRAY2_MAX_INPUT_STREAMS 4 + +//============================================================================= +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE MicArray2PinSupportedDeviceFormats[] = +{ + // 0 - Note the ENDPOINT_MINIPAIR structures for the mic arrays use this first element as the proposed DEFAULT format + // 48 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 48000, + 96000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 1 + // 8 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 8000, + 16000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 2 + // 11.025 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 11025, + 22050, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 3 - Note the ENDPOINT_MINIPAIR structures for the mic arrays use this element as the proposed SPEECH format + // 16 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, // One channel + 16000, // 16KHz + 32000, // average bytes per second + 2, // 2 bytes per frame + 16, // 16 bits per sample container + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, // valid bits per sample + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 4 + // 22.05 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 22050, + 44100, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 5 - Note the ENDPOINT_MINIPAIR structures for the mic arrays use this element as the proposed COMMUNICATIONS format + // 24 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 24000, + 48000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 6 + // 32 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 32000, + 64000, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 7 + // 44.1 KHz 16-bit mono + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 1, + 44100, + 88200, + 2, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_MONO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, + // 8 - Note the ENDPOINT_MINIPAIR structures for the mic arrays use this last element as the proposed RAW format + // 48 KHz 32-bit 2 channels + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 48000, + 384000, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 32, + 0, // No channel configuration for unprocessed mic array + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, +}; + +// +// Supported modes (only on streaming pins). +// +static +MODE_AND_DEFAULT_FORMAT MicArray2PinSupportedDeviceModes[] = +{ + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW, + &MicArray2PinSupportedDeviceFormats[SIZEOF_ARRAY(MicArray2PinSupportedDeviceFormats)-1].DataFormat + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + &MicArray2PinSupportedDeviceFormats[0].DataFormat + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_SPEECH, + &MicArray2PinSupportedDeviceFormats[3].DataFormat + }, + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, + &MicArray2PinSupportedDeviceFormats[5].DataFormat + } +}; + +// This structure goes along with the keyword supported device format, +// to indicate that the audio is interleaved microphone and loopback data. +INTERLEAVED_AUDIO_FORMAT_INFORMATION InterleavedFormatInformation = +{ + sizeof(INTERLEAVED_AUDIO_FORMAT_INFORMATION), + 4, // Microphone channel count + 0, // Microphone channel start position + 0, // No channel configuration for unprocessed mic array + 2, // Channel count for interleaved data + 2, // Interleaved audio start position + KSAUDIO_SPEAKER_STEREO // Channel mask for interleaved loopback data +}; + +//============================================================================= +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE KeywordPin2SupportedDeviceFormats[] = +{ + { + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 6, // six channels, make sure this matches InterleavedFormatInformation, if interleaving loopback audio + 16000, // 16KHz + 192000, // average bytes per second + 12, // 8 bytes per frame + 16, // 16 bits per sample container + sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) + }, + 16, // valid bits per sample + 0, // No channel configuration for unprocessed mic array + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } + }, +}; + +static +MODE_AND_DEFAULT_FORMAT KeywordPin2SupportedDeviceModes[] = +{ + // NOTE: Because we're using the KWS apo as an EFX, this endpoint may only support a single mode. + // You can not have an EFX when there are multiple modes supported by the driver, EFX must be implemented + // in the driver in that case. Because we are exposing a single mode the audio engine can insert the KWSAPO + // as an EFX. Further, in the INF associated to this driver the KWS EFX APO is registered as supporting default + // mode. That registration is not coupled to the mode enumerated in this list. + { + STATIC_AUDIO_SIGNALPROCESSINGMODE_SPEECH, + &KeywordPin2SupportedDeviceFormats[SIZEOF_ARRAY(KeywordPin2SupportedDeviceFormats) - 1].DataFormat + }, +}; + +// +// The entries here must follow the same order as the filter's pin +// descriptor array. +// +static +PIN_DEVICE_FORMATS_AND_MODES MicArray2PinDeviceFormatsAndModes[] = +{ + { + BridgePin, + NULL, + 0, + NULL, + 0 + }, + { + SystemCapturePin, + MicArray2PinSupportedDeviceFormats, + SIZEOF_ARRAY(MicArray2PinSupportedDeviceFormats), + MicArray2PinSupportedDeviceModes, + SIZEOF_ARRAY(MicArray2PinSupportedDeviceModes) + }, + { + KeywordCapturePin, + KeywordPin2SupportedDeviceFormats, + SIZEOF_ARRAY(KeywordPin2SupportedDeviceFormats), + KeywordPin2SupportedDeviceModes, + SIZEOF_ARRAY(KeywordPin2SupportedDeviceModes) + } +}; + +//============================================================================= +// Data ranges +// +// See CMiniportWaveRT::DataRangeIntersection. +// +// Both mono and two-channel formats are supported for the mic arrays. The +// design of this sample driver's data range intersection handler requires a +// separate data for each supported channel count. +// +static +KSDATARANGE_AUDIO MicArray2PinDataRangesRawStream[] = +{ + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_RAW_CHANNELS, + MICARRAY2_32_BITS_PER_SAMPLE_PCM, + MICARRAY2_32_BITS_PER_SAMPLE_PCM, + MICARRAY2_RAW_SAMPLE_RATE, + MICARRAY2_RAW_SAMPLE_RATE + }, +}; + +static +KSDATARANGE_AUDIO MicArray2PinDataRangesProcessedStream[] = +{ + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_PROCESSED_MIN_SAMPLE_RATE, + MICARRAY2_PROCESSED_MIN_SAMPLE_RATE + }, + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + 11025, + 11025 + }, + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + 16000, + 16000 + }, + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + 22050, + 22050 + }, + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + 24000, + 24000 + }, + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + 32000, + 32000 + }, + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + 44100, + 44100 + }, + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MICARRAY2_PROCESSED_CHANNELS, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_16_BITS_PER_SAMPLE_PCM, + MICARRAY2_PROCESSED_MAX_SAMPLE_RATE, + MICARRAY2_PROCESSED_MAX_SAMPLE_RATE + }, +}; + +// if MicArray2PinDataRangesProcessedStream is changed, we MUST update MicArray2PinDataRangePointersStream too! +C_ASSERT(SIZEOF_ARRAY(MicArray2PinDataRangesProcessedStream) == 8); + +static +PKSDATARANGE MicArray2PinDataRangePointersStream[] = +{ + // All supported device formats should be listed in the DataRange. + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[0]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[1]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[2]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[3]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[4]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[5]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[6]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesProcessedStream[7]), + PKSDATARANGE(&PinDataRangeAttributeList), + PKSDATARANGE(&MicArray2PinDataRangesRawStream[0]), + PKSDATARANGE(&PinDataRangeAttributeList), +}; + +//============================================================================= +static +KSDATARANGE MicArray2PinDataRangesBridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +static +PKSDATARANGE MicArray2PinDataRangePointersBridge[] = +{ + &MicArray2PinDataRangesBridge[0] +}; + +static +KSDATARANGE_AUDIO KeywordPin2DataRangesStream[] = +{ + { + { + sizeof(KSDATARANGE_AUDIO), + KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + 6, // max channels + 16, // min bits per sample + 16, // max bits per sample + 16000, // min sample rate + 16000 // max sample rate + }, +}; + +static +PKSDATARANGE KeywordPin2DataRangePointersStream[] = +{ + PKSDATARANGE(&KeywordPin2DataRangesStream[0]), + PKSDATARANGE(&PinDataRangeAttributeList), +}; + +//============================================================================= +static +PCPIN_DESCRIPTOR MicArray2WaveMiniportPins[] = +{ + // Wave In Bridge Pin (Capture - From Topology) KSPIN_WAVE_BRIDGE + { + 0, + 0, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(MicArray2PinDataRangePointersBridge), + MicArray2PinDataRangePointersBridge, + KSPIN_DATAFLOW_IN, + KSPIN_COMMUNICATION_NONE, + &KSCATEGORY_AUDIO, + NULL, + 0 + } + }, + // Wave In Streaming Pin (Capture) KSPIN_WAVE_HOST + { + MICARRAY2_MAX_INPUT_STREAMS, + MICARRAY2_MAX_INPUT_STREAMS, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(MicArray2PinDataRangePointersStream), + MicArray2PinDataRangePointersStream, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_SINK, + &KSCATEGORY_AUDIO, + &KSAUDFNAME_RECORDING_CONTROL, + 0 + } + }, + // Keyword Detector Streaming Pin (Capture) KSPIN_WAVEIN_KEYWORD + { + 1, + 1, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(KeywordPin2DataRangePointersStream), + KeywordPin2DataRangePointersStream, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_SINK, + &KSNODETYPE_AUDIO_KEYWORDDETECTOR, + NULL, + 0 + } + } +}; + +//============================================================================= +static +PCNODE_DESCRIPTOR MicArray2WaveMiniportNodes[] = +{ + // KSNODE_WAVE_ADC + { + 0, // Flags + NULL, // AutomationTable + &KSNODETYPE_ADC, // Type + NULL // Name + } +}; + +//============================================================================= +static +PCCONNECTION_DESCRIPTOR MicArray2WaveMiniportConnections[] = +{ + { PCFILTER_NODE, KSPIN_WAVE_BRIDGE, KSNODE_WAVE_ADC, 1 }, + { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_HOST }, + { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_KEYWORD }, +}; + +//============================================================================= +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorMatchResult); + +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorPatterns2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorArmed2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorArmed2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Set_SoundDetectorReset2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorStreamingSupport2); +DECLARE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_InterleavedFormatInformation); + + +static +SYSVADPROPERTY_ITEM PropertiesMicArray2WaveFilter[] = +{ + { + { + &KSPROPSETID_General, + KSPROPERTY_GENERAL_COMPONENTID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter, + }, + 0, + 0, + NULL, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PROPOSEDATAFORMAT, + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter, + }, + 0, + 0, + NULL, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PROPOSEDATAFORMAT2, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter, + }, + 0, + 0, + NULL, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_AudioEffectsDiscovery, + KSPROPERTY_AUDIOEFFECTSDISCOVERY_EFFECTSLIST, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_WaveFilter + }, + 0, + 0, + NULL, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector, + KSPROPERTY_SOUNDDETECTOR_SUPPORTEDPATTERNS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + 0, + sizeof(CONTOSO_SUPPORTEDPATTERNSVALUE), + CMiniportWaveRT_Get_SoundDetectorSupportedPatterns, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector, + KSPROPERTY_SOUNDDETECTOR_PATTERNS, + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + 0, + (sizeof(KSMULTIPLE_ITEM) + sizeof(CONTOSO_KEYWORDCONFIGURATION)), + NULL, + CMiniportWaveRT_Set_SoundDetectorPatterns, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector, + KSPROPERTY_SOUNDDETECTOR_ARMED, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + 0, + sizeof(BOOL), + CMiniportWaveRT_Get_SoundDetectorArmed, + CMiniportWaveRT_Set_SoundDetectorArmed, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector, + KSPROPERTY_SOUNDDETECTOR_MATCHRESULT, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + 0, + sizeof(CONTOSO_KEYWORDDETECTIONRESULT), + CMiniportWaveRT_Get_SoundDetectorMatchResult, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_SUPPORTEDPATTERNS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(CONTOSO_SUPPORTEDPATTERNSVALUE), + CMiniportWaveRT_Get_SoundDetectorSupportedPatterns2, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_PATTERNS, + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + (sizeof(KSMULTIPLE_ITEM) + sizeof(CONTOSO_KEYWORDCONFIGURATION)), + NULL, + CMiniportWaveRT_Set_SoundDetectorPatterns2, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_ARMED, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(BOOL), + CMiniportWaveRT_Get_SoundDetectorArmed2, + CMiniportWaveRT_Set_SoundDetectorArmed2, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_RESET, + KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(BOOL), + NULL, + CMiniportWaveRT_Set_SoundDetectorReset2, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_SoundDetector2, + KSPROPERTY_SOUNDDETECTOR_STREAMINGSUPPORT, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSSOUNDDETECTORPROPERTY) - sizeof(KSPROPERTY), + sizeof(BOOL), + CMiniportWaveRT_Get_SoundDetectorStreamingSupport2, + NULL, + NULL, + NULL, + 0 + }, + { + { + &KSPROPSETID_InterleavedAudio, + KSPROPERTY_INTERLEAVEDAUDIO_FORMATINFORMATION, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + SysvadPropertyDispatch, + }, + sizeof(KSP_PIN) - sizeof(KSPROPERTY), + sizeof(INTERLEAVED_AUDIO_FORMAT_INFORMATION), + CMiniportWaveRT_Get_InterleavedFormatInformation, + NULL, + NULL, + &InterleavedFormatInformation, // format interleaving information for this endpoint + sizeof(InterleavedFormatInformation) + }, +}; + +NTSTATUS CMiniportWaveRT_EventHandler_SoundDetectorMatchDetected( + _In_ PPCEVENT_REQUEST EventRequest + ); + +static +PCEVENT_ITEM EventsMicArray2WaveFilter[] = +{ + { + &KSEVENTSETID_SoundDetector, + KSEVENT_SOUNDDETECTOR_MATCHDETECTED, + KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT, + CMiniportWaveRT_EventHandler_SoundDetectorMatchDetected, + } +}; + +DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationMicArray2WaveFilter, PropertiesMicArray2WaveFilter, EventsMicArray2WaveFilter); + +//============================================================================= +static +PCFILTER_DESCRIPTOR MicArray2WaveMiniportFilterDescriptor = +{ + 0, // Version + &AutomationMicArray2WaveFilter, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(MicArray2WaveMiniportPins), // PinCount + MicArray2WaveMiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + SIZEOF_ARRAY(MicArray2WaveMiniportNodes), // NodeCount + MicArray2WaveMiniportNodes, // Nodes + SIZEOF_ARRAY(MicArray2WaveMiniportConnections), // ConnectionCount + MicArray2WaveMiniportConnections, // Connections + 0, // CategoryCount + NULL // Categories - use defaults (audio, render, capture) +}; + + +#endif // _SYSVAD_MICARRAY2WAVTABLE_H_ + diff --git a/audio/sysvad/TabletAudioSample/minipairs.h b/audio/sysvad/TabletAudioSample/minipairs.h index 0a3c82ef..d9060e9f 100644 --- a/audio/sysvad/TabletAudioSample/minipairs.h +++ b/audio/sysvad/TabletAudioSample/minipairs.h @@ -40,6 +40,7 @@ Abstract: #include "micarray2toptable.h" #include "micarray3toptable.h" #include "micarraywavtable.h" +#include "micarray2wavtable.h" #include "micarray3wavtable.h" NTSTATUS @@ -446,11 +447,12 @@ ENDPOINT_MINIPAIR MicArray2Miniports = L"WaveMicArray2", // make sure this or the template name matches with KSNAME_WaveMicArray2 in the inf's [Strings] section NULL, // optional template name CreateMiniportWaveRTSYSVAD, - &MicArrayWaveMiniportFilterDescriptor, - 0, NULL, // Interface properties - MICARRAY_DEVICE_MAX_CHANNELS, - MicArrayPinDeviceFormatsAndModes, - SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes), + &MicArray2WaveMiniportFilterDescriptor, + ARRAYSIZE(SysvadWaveFilterInterfacePropertiesCapture), // Interface properties + SysvadWaveFilterInterfacePropertiesCapture, + MICARRAY2_DEVICE_MAX_CHANNELS, + MicArray2PinDeviceFormatsAndModes, + SIZEOF_ARRAY(MicArray2PinDeviceFormatsAndModes), MicArray2TopologyPhysicalConnections, SIZEOF_ARRAY(MicArray2TopologyPhysicalConnections), ENDPOINT_SOUNDDETECTOR_SUPPORTED, diff --git a/audio/sysvad/TabletAudioSample/sources b/audio/sysvad/TabletAudioSample/sources deleted file mode 100644 index 07b14c18..00000000 --- a/audio/sysvad/TabletAudioSample/sources +++ /dev/null @@ -1,53 +0,0 @@ - -# Copyright (c) Microsoft Corporation. All rights reserved. - - -!include ..\sources.inc - -TARGETNAME=TabletAudioSample - -TARGETLIBS= \ - $(TARGETLIBS) \ - $(OBJ_PATH)\..\EndpointsCommon\$(O)\EndpointsCommon.lib \ - - -C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS -DSYSVAD_USB_SIDEBAND - - -#C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -# -# Indicate to the WDK that this sample only supports Win10[+] -# -MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD) - -# -# Audio driver is a KMDF miniport. -# -KMDF_VERSION_MAJOR=1 - -# -# Uncomment one of the following lines to select the right power management. -# Note that the single-component/multi-state feature requires also a registry -# value set via the INF. The name of the registry value is SingleComponentMultiFxStates. -# see INF file for more info. -# -#C_DEFINES= $(C_DEFINES) -D_USE_IPortClsRuntimePower -C_DEFINES= $(C_DEFINES) -D_USE_SingleComponentMultiFxStates - -INCLUDES= \ - $(INCLUDES); \ - ..\EndpointsCommon; \ - -SOURCES=$(SOURCES) \ - hdmitopo.cpp \ - spdiftopo.cpp \ - micintopo.cpp \ - TabletAudioSample.rc \ - - -# Indicate that this module must be included in the driver package -DDK_NO_PACKAGE_PROJECT=0 -DDK_INCLUDE_PACKAGE_PROJECT=1 - - -MUI_VERIFY_NO_LOC_RESOURCE=1 diff --git a/audio/sysvad/TabletAudioSample/tabletaudiosample.inx b/audio/sysvad/TabletAudioSample/tabletaudiosample.inx Binary files differindex e1c0512f..ba96faee 100644 --- a/audio/sysvad/TabletAudioSample/tabletaudiosample.inx +++ b/audio/sysvad/TabletAudioSample/tabletaudiosample.inx diff --git a/audio/sysvad/adapter.cpp b/audio/sysvad/adapter.cpp index 166b2283..7cfa54ee 100644 --- a/audio/sysvad/adapter.cpp +++ b/audio/sysvad/adapter.cpp @@ -648,9 +648,6 @@ Return Value: maxObjects = g_MaxMiniports; #ifdef SYSVAD_BTH_BYPASS - // - // Allow three (3) Bluetooth hands-free profile devices. - // maxObjects += g_MaxBthHfpMiniports; #endif // SYSVAD_BTH_BYPASS #ifdef SYSVAD_USB_SIDEBAND diff --git a/audio/sysvad/common.cpp b/audio/sysvad/common.cpp index bccef495..f88ca093 100644 --- a/audio/sysvad/common.cpp +++ b/audio/sysvad/common.cpp @@ -39,6 +39,7 @@ Abstract: #include "UsbHsDevice.h" #endif // SYSVAD_USB_SIDEBAND + //----------------------------------------------------------------------------- // CSaveData statics //----------------------------------------------------------------------------- @@ -56,6 +57,7 @@ class BthHfpDevice; // Forward declaration. class UsbHsDevice; // Forward declaration. #endif // SYSVAD_USB_SIDEBAND + /////////////////////////////////////////////////////////////////////////////// // CAdapterCommon // @@ -297,6 +299,7 @@ class CAdapterCommon : ); #endif // SYSVAD_USB_SIDEBAND + STDMETHODIMP_(VOID) Cleanup(); STDMETHODIMP_(NTSTATUS) UpdatePowerRelations(_In_ PIRP Irp); @@ -391,6 +394,7 @@ class CAdapterCommon : #endif // SYSVAD_USB_SIDEBAND + private: LIST_ENTRY m_SubdeviceCache; @@ -725,6 +729,7 @@ Return Value: m_UsbSidebandEnableCleanup = FALSE; #endif // SYSVAD_USB_SIDEBAND + m_pServiceGroupWave = NULL; m_pDeviceObject = DeviceObject; m_pPhysicalDeviceObject = NULL; @@ -2291,6 +2296,7 @@ CAdapterCommon::Cleanup() CleanupUsbSideband(); #endif // SYSVAD_USB_SIDEBAND + EmptySubdeviceCache(); } @@ -2373,6 +2379,7 @@ CAdapterCommon::UpdatePowerRelations(_In_ PIRP Irp) PSysVadPowerRelationsDo powerDepDo = CONTAINING_RECORD(pe, SysVadPowerRelationsDo, ListEntry); pe = pe->Flink; +#pragma prefast(suppress: __WARNING_BUFFER_OVERFLOW, "the access to newRelation->Objects is in-range") newRelations->Objects[newRelations->Count] = powerDepDo->Pdo; // Add a reference on the PDO before returning it as a dependency. @@ -4051,6 +4058,7 @@ Cleanup the USB Sideband environment. } #endif // SYSVAD_USB_SIDEBAND + #pragma code_seg("PAGE") NTSTATUS CopyRegistryValues(HANDLE _hSourceKey, HANDLE _hDestinationKey) diff --git a/audio/sysvad/common.h b/audio/sysvad/common.h index 98a3f9cd..794b3797 100644 --- a/audio/sysvad/common.h +++ b/audio/sysvad/common.h @@ -667,6 +667,7 @@ DECLARE_INTERFACE_(IAdapterCommon, IUnknown) #endif // SYSVAD_USB_SIDEBAND + STDMETHOD_(VOID, Cleanup)(); STDMETHOD_(NTSTATUS, UpdatePowerRelations)(_In_ PIRP Irp); diff --git a/audio/sysvad/ihvprivatepropertyset.h b/audio/sysvad/ihvprivatepropertyset.h index b865a2d9..d36454c4 100644 --- a/audio/sysvad/ihvprivatepropertyset.h +++ b/audio/sysvad/ihvprivatepropertyset.h @@ -11,4 +11,4 @@ DEFINE_GUIDSTRUCT("0FB05301-5A11-400a-996B-12DF992836DE", KSPROPSETID_OffloadPin typedef enum { KSPROPERTY_OFFLOAD_PIN_GET_STREAM_OBJECT_POINTER, KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER -} KSPROPERTY_OFFLOAD_PIN;
\ No newline at end of file +} KSPROPERTY_OFFLOAD_PIN; diff --git a/audio/sysvad/kshelper.h b/audio/sysvad/kshelper.h index 10c1cadc..a8cc4956 100644 --- a/audio/sysvad/kshelper.h +++ b/audio/sysvad/kshelper.h @@ -111,6 +111,8 @@ typedef struct PCPFNPROPERTY_HANDLER GetHandler; // Property get handler (NULL if GET not supported) PCPFNPROPERTY_HANDLER SetHandler; // Property set handler (NULL if SET not supported) PCPFNPROPERTY_HANDLER SupportHandler; // Property support handler (NULL for common handler) + VOID *ContextData; // Optional context information for the handler, NULL for unused + ULONG ContextDataSize; // Size of the data held at ContextData, 0 for unused } SYSVADPROPERTY_ITEM; // The following macros facilitate adding property handlers to a class, allowing diff --git a/audio/sysvad/sources.inc b/audio/sysvad/sources.inc deleted file mode 100644 index 31b879ab..00000000 --- a/audio/sysvad/sources.inc +++ /dev/null @@ -1,36 +0,0 @@ -TARGETTYPE=DRIVER - -TARGETLIBS= \ - $(DDK_LIB_PATH)\portcls.lib\ - $(DDK_LIB_PATH)\stdunk.lib \ - $(SDK_LIB_PATH)\libcntpr.lib - -INCLUDES= \ - $(DDK_INC_PATH); \ - .. - -MSC_WARNING_LEVEL=-W4 -WX - -C_DEFINES= $(C_DEFINES) -D_WIN32 -DUNICODE -D_UNICODE -DPC_IMPLEMENTATION - -# -# Different levels of debug printage. First is nothing but -# catastrophic errors, last is everything under the sun. -# -#C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_ERROR -C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_TERSE -#C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_VERBOSE -#C_DEFINES= $(C_DEFINES) -DDEBUG_LEVEL=DEBUGLVL_BLAB - -SOURCES=\ - ..\adapter.cpp \ - ..\basetopo.cpp \ - ..\BthhfpDevice.cpp \ - ..\common.cpp \ - ..\hw.cpp \ - ..\kshelper.cpp \ - ..\savedata.cpp \ - ..\tonegenerator.cpp \ - ..\UsbHsDevice.cpp \ - ..\wavereader.cpp \ - diff --git a/audio/sysvad/sysvad.sln b/audio/sysvad/sysvad.sln index d73ed4d6..2965165c 100644 --- a/audio/sysvad/sysvad.sln +++ b/audio/sysvad/sysvad.sln @@ -35,130 +35,114 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DelayAPO", "APO\DelayAPO\De EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SwapAPO", "APO\SwapAPO\SwapAPO.vcxproj", "{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KwsAPO", "APO\KWSApo\KwsAPO.vcxproj", "{47358AD6-A48A-465B-965F-0A66F8BDFE23}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM.ActiveCfg = Debug|ARM - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM.Build.0 = Debug|ARM {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.ActiveCfg = Debug|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.Build.0 = Debug|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.ActiveCfg = Debug|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.Build.0 = Debug|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.ActiveCfg = Debug|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.Build.0 = Debug|x64 - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM.ActiveCfg = Release|ARM - {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM.Build.0 = Release|ARM {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.ActiveCfg = Release|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.Build.0 = Release|ARM64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.ActiveCfg = Release|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.Build.0 = Release|Win32 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.ActiveCfg = Release|x64 {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM.ActiveCfg = Debug|ARM - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM.Build.0 = Debug|ARM {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM64.Build.0 = Debug|ARM64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.ActiveCfg = Debug|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.Build.0 = Debug|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.ActiveCfg = Debug|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.Build.0 = Debug|x64 - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM.ActiveCfg = Release|ARM - {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM.Build.0 = Release|ARM {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM64.ActiveCfg = Release|ARM64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM64.Build.0 = Release|ARM64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.ActiveCfg = Release|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.Build.0 = Release|Win32 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.ActiveCfg = Release|x64 {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.Build.0 = Release|x64 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM.ActiveCfg = Debug|ARM - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM.Build.0 = Debug|ARM {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.ActiveCfg = Debug|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.Build.0 = Debug|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.ActiveCfg = Debug|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.Build.0 = Debug|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.ActiveCfg = Debug|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.Build.0 = Debug|x64 - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM.ActiveCfg = Release|ARM - {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM.Build.0 = Release|ARM {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.ActiveCfg = Release|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.Build.0 = Release|ARM64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.ActiveCfg = Release|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|Win32 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.ActiveCfg = Release|x64 {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64 - {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM.ActiveCfg = Debug|ARM - {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM.Build.0 = Debug|ARM {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|ARM64.Build.0 = Debug|ARM64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.ActiveCfg = Debug|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|Win32.Build.0 = Debug|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.ActiveCfg = Debug|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Debug|x64.Build.0 = Debug|x64 - {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM.ActiveCfg = Release|ARM - {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM.Build.0 = Release|ARM {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM64.ActiveCfg = Release|ARM64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|ARM64.Build.0 = Release|ARM64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.ActiveCfg = Release|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.Build.0 = Release|Win32 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.ActiveCfg = Release|x64 {FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.Build.0 = Release|x64 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM.ActiveCfg = Debug|ARM - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM.Build.0 = Debug|ARM {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.Build.0 = Debug|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.ActiveCfg = Debug|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.Build.0 = Debug|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.ActiveCfg = Debug|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.Build.0 = Debug|x64 - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM.ActiveCfg = Release|ARM - {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM.Build.0 = Release|ARM {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.ActiveCfg = Release|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.Build.0 = Release|ARM64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.ActiveCfg = Release|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.Build.0 = Release|Win32 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.ActiveCfg = Release|x64 {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.Build.0 = Release|x64 - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|ARM.ActiveCfg = Debug|ARM - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|ARM.Build.0 = Debug|ARM {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|ARM64.ActiveCfg = Debug|ARM64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|ARM64.Build.0 = Debug|ARM64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|Win32.ActiveCfg = Debug|Win32 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|Win32.Build.0 = Debug|Win32 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|x64.ActiveCfg = Debug|x64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Debug|x64.Build.0 = Debug|x64 - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|ARM.ActiveCfg = Release|ARM - {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|ARM.Build.0 = Release|ARM {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|ARM64.ActiveCfg = Release|ARM64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|ARM64.Build.0 = Release|ARM64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|Win32.ActiveCfg = Release|Win32 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|Win32.Build.0 = Release|Win32 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|x64.ActiveCfg = Release|x64 {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|x64.Build.0 = Release|x64 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|ARM.ActiveCfg = Debug|ARM - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|ARM.Build.0 = Debug|ARM {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|ARM64.ActiveCfg = Debug|ARM64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|ARM64.Build.0 = Debug|ARM64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|Win32.ActiveCfg = Debug|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|Win32.Build.0 = Debug|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.ActiveCfg = Debug|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Debug|x64.Build.0 = Debug|x64 - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|ARM.ActiveCfg = Release|ARM - {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|ARM.Build.0 = Release|ARM {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|ARM64.ActiveCfg = Release|ARM64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|ARM64.Build.0 = Release|ARM64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|Win32.ActiveCfg = Release|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|Win32.Build.0 = Release|Win32 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|x64.ActiveCfg = Release|x64 {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|x64.Build.0 = Release|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM64.Build.0 = Debug|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|Win32.ActiveCfg = Debug|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|Win32.Build.0 = Debug|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|x64.ActiveCfg = Debug|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|x64.Build.0 = Debug|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM64.ActiveCfg = Release|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM64.Build.0 = Release|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|Win32.ActiveCfg = Release|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|Win32.Build.0 = Release|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|x64.ActiveCfg = Release|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -171,6 +155,7 @@ Global {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF} = {C06F6070-75EE-4F57-8D35-4AC2AB08D029} {8851AB85-70B3-4798-A149-BA366DF9EC25} = {D86F9A10-C48D-4048-A03C-DD7BCA6E165F} {691F1D0F-CA50-46CD-8BBA-A59E9E8EB601} = {D86F9A10-C48D-4048-A03C-DD7BCA6E165F} + {47358AD6-A48A-465B-965F-0A66F8BDFE23} = {D86F9A10-C48D-4048-A03C-DD7BCA6E165F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6DB4FE19-4FE0-4DC4-B898-C46E01E6BDF4} diff --git a/audio/tests/wavetest/HalfApp.cpp b/audio/tests/wavetest/HalfApp.cpp new file mode 100644 index 00000000..14a15c08 --- /dev/null +++ b/audio/tests/wavetest/HalfApp.cpp @@ -0,0 +1,1001 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// Module Name: +// +// HalfApp.cpp +// +// Abstract: +// +// Implementation for CHalfApp class +// +// ------------------------------------------------------------------------------- + +#include "PreComp.h" +#include "WaveTestTaef.h" +#include "HalfApp.h" +#include "TestResourceHelper.h" +#include "PropertyHelper.h" +#include <dithering.h> +#include <signal-source.h> +#include <sine-signal-source.h> +#include <dvmodule.h> + +HRESULT +CHalfApp::InitializeEndpoint +( + void +) +{ + HRESULT hr = S_OK; + + + + wil::unique_prop_variant varActivationParameter; + + + + WAVEFORMATEX* pWfx = m_pCurrentFormat.get(); + + if (!VERIFY_IS_NOT_NULL(pWfx)) { + hr = E_NOTFOUND; + return hr; + } + + + + + + + + + + // Allocate a structure for endpoint creation. + varActivationParameter.vt = VT_BLOB; + + // Fill the endpoint creation structure... + + + + + + + + + + + + + + + + + + // Activate the endpoint + if (m_DataFlow == render) { + wil::com_ptr_nothrow<IAudioOutputEndpointRT> spAudioOutputEndpointRT; + if (!VERIFY_SUCCEEDED(hr = m_pDevice->Activate( + __uuidof(IAudioOutputEndpointRT), + CLSCTX_INPROC_SERVER, + &varActivationParameter, + reinterpret_cast<void**>(&spAudioOutputEndpointRT)))) { + return hr; + } + spAudioOutputEndpointRT.query_to(&m_pAudioDeviceEndpoint); + if (!VERIFY_IS_NOT_NULL(m_pAudioDeviceEndpoint)) { + hr = E_FAIL; + return hr; + } + } + else { + wil::com_ptr_nothrow<IAudioInputEndpointRT> spAudioInputEndpointRT; + if (!VERIFY_SUCCEEDED(hr = m_pDevice->Activate( + __uuidof(IAudioInputEndpointRT), + CLSCTX_INPROC_SERVER, + &varActivationParameter, + reinterpret_cast<void**>(&spAudioInputEndpointRT)))) { + return hr; + } + spAudioInputEndpointRT.query_to(&m_pAudioDeviceEndpoint); + if (!VERIFY_IS_NOT_NULL(m_pAudioDeviceEndpoint)) { + hr = E_FAIL; + return hr; + } + } + + // Initialize other endpoint interfaces + if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint.query_to(&m_pAudioEndpointControl))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint.query_to(&m_pAudioEndpoint))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint.query_to(&m_pAudioEndpointRT))) { + return hr; + } + + return hr; +} + +HRESULT +CHalfApp::ReleaseEndpoint +( + void +) +{ + HRESULT hr = S_OK; + + if (m_pAudioEndpointControl) { + m_pAudioEndpointControl->Reset(); + } + + m_pAudioDeviceEndpoint.reset(); + m_pAudioEndpointControl.reset(); + m_pAudioEndpoint.reset(); + m_pAudioEndpointRT.reset(); + + return hr; +} + +HRESULT +CHalfApp::StartEndpoint +( + void +) +{ + HRESULT hr = S_OK; + auto lock = m_CritSec.lock(); + + if (!VERIFY_SUCCEEDED(hr = m_pAudioEndpointControl->Start())) { + return hr; + } + + return hr; +} + +HRESULT +CHalfApp::StopEndpoint +( + void +) +{ + HRESULT hr = S_OK; + auto lock = m_CritSec.lock(); + + if (!VERIFY_SUCCEEDED(hr = m_pAudioEndpointControl->Stop())) { + return hr; + } + + return hr; +} + +HRESULT +CHalfApp::ResetEndpoint +( + void +) +{ + HRESULT hr = S_OK; + auto lock = m_CritSec.lock(); + + if (!VERIFY_SUCCEEDED(hr = m_pAudioEndpointControl->Reset())) { + return hr; + } + + return hr; +} + +//////////////////////////////////////////////////////////////////////////////////// +// +// Creates a pre-load data buffer used by the stream render and capture routines. +// +// If the current endpoint is a render one, the data buffer consists of a sine tone +// wich gets loaded into a stream render routine. +// +// In the case of a capture endpoint, the pre-load data consists of silence. +// +//////////////////////////////////////////////////////////////////////////////////// +HRESULT +CHalfApp::CreateSineToneDataBuffer +( + WAVEFORMATEX* pWfx +) +{ + HRESULT hr = S_OK; + + if (!VERIFY_IS_NOT_NULL(pWfx)) { + hr = E_FAIL; + return hr; + } + + m_dwSineToneDataBufferSize = (DWORD)(((ULONGLONG)BUF_LEN_IN_MS * pWfx->nSamplesPerSec / 1000) * pWfx->nBlockAlign); + m_pbSineToneDataBuffer.reset((BYTE*)LocalAlloc(LPTR, m_dwSineToneDataBufferSize)); + if (!VERIFY_IS_NOT_NULL(m_pbSineToneDataBuffer)) { + hr = E_OUTOFMEMORY; + return hr; + } + + if (m_DataFlow == render) // Sine tone for render + { + if (!VERIFY_SUCCEEDED(hr = FillBufferWithSineSignal( + g_pBasicLog, XFAIL, + pWfx, + TEST_AMPLITUDE, // amplitude + TEST_FREQUENCY, // frequency + 0.0, // initial phase, + 0.0, // dc + Method_NoDithering, + m_pbSineToneDataBuffer.get(), + m_dwSineToneDataBufferSize / pWfx->nBlockAlign, + m_dwSineToneDataBufferSize + ))) { + return hr; + } + + m_dwSineToneDataBufferPosition = 0; + } + else // Silence for capture + { + memset(m_pbSineToneDataBuffer.get(), 0, m_dwSineToneDataBufferSize); + m_dwSineToneDataBufferPosition = 0; + } + + return hr; +} + +////////////////////////////////// +// +// Clears the current data buffer. +// +////////////////////////////////// +HRESULT +CHalfApp::ReleaseSineToneDataBuffer +( + void +) +{ + m_pbSineToneDataBuffer = nullptr; + m_dwSineToneDataBufferSize = 0; + m_dwSineToneDataBufferPosition = 0; + + return S_OK; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +HRESULT +CHalfApp::InitializeAndSetBuffer +( + HNSTIME requestedPeriodicity, + UINT32 u32LatencyCoefficient +) +{ + HRESULT hr = S_OK; + BOOL bIsEventCapable = false; + + // If no requested periodicity is provided, use default. + if (requestedPeriodicity == 0) { + m_hnsPeriod = FRAMES_TO_HNSTIME_DOUBLE(m_u32CurrentDefaultPeriodicityInFrames, m_pCurrentFormat->nSamplesPerSec); + } + else { + m_hnsPeriod = requestedPeriodicity; + } + + if (m_ConnectorType == eOffloadConnector) { + bIsEventCapable = true; + } + else { + if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint->GetEventDrivenCapable(&bIsEventCapable))) { + return hr; + } + } + + if (bIsEventCapable) + { + if (!VERIFY_SUCCEEDED(hr = m_pAudioEndpoint->SetStreamFlags(AUDCLNT_STREAMFLAGS_EVENTCALLBACK))) { + return hr; + } + } + + if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint->SetBuffer(m_hnsPeriod, u32LatencyCoefficient))) { + return hr; + } + + return hr; +} + +HRESULT +CHalfApp::GetCurrentAvailiablePinInstanceCount +( + UINT32 *pAvailablePinInstanceCount +) +{ + HRESULT hr = S_OK; + + // Read the current pin instance counts + if (!VERIFY_SUCCEEDED(hr = GetAvailiablePinInstanceCount(m_pDevice.get(), m_uConnectorId, pAvailablePinInstanceCount))) { + return hr; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// +// Gets a CHalfApp instance based on the current one, but with a different processing mode. +// +// The processing mode for the new instance is specified through the secondMode parameter. +// +/////////////////////////////////////////////////////////////////////////////////////////// +HRESULT +CHalfApp::GetSecondHalfApp +( + AUDIO_SIGNALPROCESSINGMODE secondMode, + CHalfApp** ppSecondHalfApp +) +{ + HRESULT hr = S_OK; + ULONG cFormatRecords = 0; + CComHeapPtr<FORMAT_RECORD> spFormatRecords; + wil::unique_cotaskmem_ptr<WAVEFORMATEX> pPreferredFormat; + UINT32 u32DefaultPeriodicityInFrames; + UINT32 u32FundamentalPeriodicityInFrames; + UINT32 u32MinPeriodicityInFrames; + UINT32 u32MaxPeriodicityInFrames; + UINT32 u32MaxPeriodicityInFramesExtended; + + if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecordsForConnector(m_pDevice.get(), m_uConnectorId, m_ConnectorType, secondMode, m_DataFlow, &cFormatRecords, &spFormatRecords))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatForConnector(m_pDevice.get(), m_uConnectorId, m_ConnectorType, secondMode, wil::out_param(pPreferredFormat)))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatPeriodicityCharacteristicsForConnector(m_pDevice.get(), m_ConnectorType, secondMode, m_DataFlow, pPreferredFormat.get(), cFormatRecords, spFormatRecords, &u32DefaultPeriodicityInFrames, &u32FundamentalPeriodicityInFrames, &u32MinPeriodicityInFrames, &u32MaxPeriodicityInFrames, &u32MaxPeriodicityInFramesExtended))) { + return hr; + } + + *ppSecondHalfApp = new CHalfApp(m_pDevice.get(), m_pwstrDeviceId.get(), m_pwstrDeviceFriendlyName.get(), m_DataFlow, m_ConnectorType, m_uConnectorId, secondMode, m_cModes, m_pModes, cFormatRecords, spFormatRecords, pPreferredFormat.get(), u32DefaultPeriodicityInFrames, u32FundamentalPeriodicityInFrames, u32MinPeriodicityInFrames, u32MaxPeriodicityInFrames); + if (*ppSecondHalfApp == NULL) { + hr = E_OUTOFMEMORY; + return hr; + } + + return hr; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Gets a CHalfApp instance corresponding to the host pin of the current audio endpoint. +// +// This function is usually called on a test method that involves a loopback pin, +// in order to be able to start and control a stream in the host pin and get loopback data. +// +//////////////////////////////////////////////////////////////////////////////////////////// +HRESULT +CHalfApp::GetHostHalfApp +( + CHalfApp** ppHostHalfApp +) +{ + HRESULT hr = S_OK; + bool bHasConnector = false; + UINT uConnectorId; + ULONG cModes = 0; + CComHeapPtr<AUDIO_SIGNALPROCESSINGMODE> spModes; + bool bRawSupport = false; + bool bDefaultSupport = false; + AUDIO_SIGNALPROCESSINGMODE mode; + ULONG cFormatRecords = 0; + CComHeapPtr<FORMAT_RECORD> spFormatRecords; + wil::unique_cotaskmem_ptr<WAVEFORMATEX> pPreferredFormat; + UINT32 u32DefaultPeriodicityInFrames; + UINT32 u32FundamentalPeriodicityInFrames; + UINT32 u32MinPeriodicityInFrames; + UINT32 u32MaxPeriodicityInFrames; + UINT32 u32MaxPeriodicityInFramesExtended; + + // It is only used when testing on loopback pin. When preparing loopback pin, we also need prepare the host pin. + VERIFY_IS_TRUE(m_ConnectorType == eLoopbackConnector); + + // Get host connector id + if (!VERIFY_SUCCEEDED(hr = GetConnectorId(m_pDevice.get(), eHostProcessConnector, &bHasConnector, &uConnectorId))) { + return hr; + } + if (!bHasConnector) { + return hr; + } + + // Get all signal processing modes for host connector + if (!VERIFY_SUCCEEDED(hr = GetProcessingModesForConnector(m_pDevice.get(), uConnectorId, eHostProcessConnector, &cModes, &spModes))) { + return hr; + } + + // It is possible that host pin support multiple processing modes so we pick up one mode. If host pin support default, use default mode. If host pin support raw, use raw mode. + for (ULONG i = 0; i < cModes; i++) { + if (spModes[i] == AUDIO_SIGNALPROCESSINGMODE_RAW) + bRawSupport = true; + if (spModes[i] == AUDIO_SIGNALPROCESSINGMODE_DEFAULT) + bDefaultSupport = true; + } + if (!VERIFY_IS_TRUE(bRawSupport || bDefaultSupport)) { + hr = E_FAIL; + return hr; + } + mode = bDefaultSupport ? AUDIO_SIGNALPROCESSINGMODE_DEFAULT : AUDIO_SIGNALPROCESSINGMODE_RAW; + + if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecordsForConnector(m_pDevice.get(), uConnectorId, eHostProcessConnector, mode, render, &cFormatRecords, &spFormatRecords))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatForConnector(m_pDevice.get(), uConnectorId, eHostProcessConnector, mode, wil::out_param(pPreferredFormat)))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatPeriodicityCharacteristicsForConnector(m_pDevice.get(), eHostProcessConnector, mode, render, pPreferredFormat.get(), cFormatRecords, spFormatRecords, &u32DefaultPeriodicityInFrames, &u32FundamentalPeriodicityInFrames, &u32MinPeriodicityInFrames, &u32MaxPeriodicityInFrames, &u32MaxPeriodicityInFramesExtended))) { + return hr; + } + + *ppHostHalfApp = new CHalfApp(m_pDevice.get(), m_pwstrDeviceId.get(), m_pwstrDeviceFriendlyName.get(), render, eHostProcessConnector, uConnectorId, mode, cModes, spModes, cFormatRecords, spFormatRecords, pPreferredFormat.get(), u32DefaultPeriodicityInFrames, u32FundamentalPeriodicityInFrames, u32MinPeriodicityInFrames, u32MaxPeriodicityInFrames); + if (*ppHostHalfApp == NULL) { + hr = E_OUTOFMEMORY; + return hr; + } + + return hr; +} + + +HRESULT +CHalfApp::InitializeStream +( + HNSTIME requestedPeriodicity, + UINT32 u32LatencyCoefficient +) +{ + HRESULT hr = S_OK; + BOOL bIsEventCapable; + wil::unique_cotaskmem_ptr<WAVEFORMATEX> pDeviceFormat; + + if (!VERIFY_IS_TRUE(!m_bStreamInitialized)) { + hr = AEERR_ALREADY_INITIALIZED; + } + + if (!VERIFY_SUCCEEDED(hr = InitializeAndSetBuffer(requestedPeriodicity, u32LatencyCoefficient))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = m_pAudioEndpoint->GetFrameFormat(out_param(pDeviceFormat)))) { + return hr; + } + m_f32EndpointFrameRate = (FLOAT32)pDeviceFormat->nAvgBytesPerSec / (FLOAT32)pDeviceFormat->nBlockAlign; + if (!VERIFY_SUCCEEDED(hr = m_pAudioEndpoint->GetLatency(&m_hnsEndpointLatency))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = m_hProcessThreadStartedEvent.create())) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = m_hTerminate.create(wil::EventOptions::ManualReset))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = m_pAudioDeviceEndpoint->GetEventDrivenCapable(&bIsEventCapable))) { + return hr; + } + + if (bIsEventCapable || m_ConnectorType == eOffloadConnector) { + m_bIsEventCapable = true; + } + + if (m_bIsEventCapable) + { + if (!VERIFY_SUCCEEDED(hr = m_hEndpointBufferCompleteEvent.create())) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = m_pAudioEndpoint->SetEventHandle(m_hEndpointBufferCompleteEvent.get()))) { + return hr; + } + } + + if (!m_bIsEventCapable) { + m_hTimer.reset(CreateWaitableTimerEx(NULL, NULL, 0, TIMER_ALL_ACCESS)); + } + + if (m_DataFlow == render) { + m_pStreamRoutine = RenderStreamRoutine; + } + else { + m_pStreamRoutine = CaptureStreamRoutine; + } + + // To-do: Adjust for offload streaming + + m_bStreamInitialized = true; + + return hr; +} + +HRESULT +CHalfApp::CleanupStream +( + void +) +{ + HRESULT hr = S_OK; + + // If the thread thread is still active, stop it + if (m_hStreamThread) + { + SignalAndWaitForThread(); + } + + m_hnsPeriod = 0; + m_f32EndpointFrameRate = 0.F; + m_hnsEndpointLatency = 0; + + m_pStreamRoutine = nullptr; + + m_hTerminate.reset(); + m_hEndpointBufferCompleteEvent.reset(); + m_hProcessThreadStartedEvent.reset(); + m_hTimer.reset(); + + m_bIsEventCapable = false; + m_bStreamInitialized = false; + m_bStreamThreadTerminate = false; + m_bYieldActive = false; + + return hr; +} + +DWORD CALLBACK +CHalfApp::RenderStreamRoutine +( + PVOID lpParameter +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +DWORD CALLBACK +CHalfApp::CaptureStreamRoutine +( + PVOID lpParameter +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +HRESULT +CHalfApp::StartStream +( + void +) +{ + HRESULT hr = S_OK; + + if (!VERIFY_IS_TRUE(m_bStreamInitialized)) { + hr = AEERR_NOT_INITIALIZED; + return hr; + } + if (!VERIFY_IS_TRUE(!m_hStreamThread)) { + hr = AEERR_ALREADY_RUNNING; + return hr; + } + + m_bStreamThreadTerminate = false; + m_hTerminate.ResetEvent(); + m_hProcessThreadStartedEvent.ResetEvent(); + + DWORD dwThreadID; + m_hStreamThread.reset(CreateThread(NULL, 0, m_pStreamRoutine, this, 0, &dwThreadID)); + if (!VERIFY_IS_NOT_NULL(m_hStreamThread)) { + DWORD dwError = GetLastError(); + hr = HRESULT_FROM_WIN32(dwError); + return hr; + } + if (m_hStreamThread) + { + SetThreadPriority(m_hStreamThread.get(), THREAD_PRIORITY_HIGHEST); + } + + // Wait for the processing thread to be started or to error out. To avoid the Start call from being blocked forever, give up waiting after 10 seconds, which is a duration quite unlikely to hit -- something must have gone wrong in the thread creation. + WaitForSingleObjectEx(m_hProcessThreadStartedEvent.get(), 10000, FALSE); + + // Set timer + if (!m_bIsEventCapable) { + SetTimer(m_hTimer.get(), m_hnsPeriod, true); + } + + if (!VERIFY_SUCCEEDED(hr = StartEndpoint())) { + return hr; + } + + return hr; +} + +HRESULT +CHalfApp::StopStream +( + void +) +{ + HRESULT hr = S_OK; + + m_bStreamThreadTerminate = true; + + if (!VERIFY_IS_TRUE(m_bStreamInitialized)) { + hr = AEERR_NOT_INITIALIZED; + return hr; + } + if (!VERIFY_IS_NOT_NULL(m_hStreamThread)) { + hr = AEERR_NOT_RUNNING; + return hr; + } + + SignalAndWaitForThread(); + + //Cancel timer + if (!m_bIsEventCapable) { + CancelTimer(m_hTimer.get()); + } + + if (!VERIFY_SUCCEEDED(hr = StopEndpoint())) { + return hr; + } + + return hr; +} + +void +CHalfApp::SignalAndWaitForThread +( + void +) +{ + DWORD dwReturn; + + m_bStreamThreadTerminate = true; + m_hTerminate.SetEvent(); + + dwReturn = WaitForSingleObjectEx(m_hStreamThread.get(), INFINITE, FALSE); + + VERIFY_IS_TRUE(WAIT_OBJECT_0 == dwReturn); + + m_hStreamThread.reset(); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +inline HRESULT CHalfApp::SetTimer(HANDLE timer, HNSTIME timeDuration, bool fireImmediatley) +{ + if (timer) + { + LARGE_INTEGER DueTime; + + if (fireImmediatley) + { + DueTime.QuadPart = 0; + } + else + { + // Negate this to mean relative in call to SetWaitableTimer + DueTime.QuadPart = -timeDuration; + } + + SetWaitableTimer(timer, &DueTime, + static_cast<UINT32>(MF_TO_MS(timeDuration)), + nullptr, nullptr, FALSE); + } + return S_OK; +} + +inline void CHalfApp::CancelTimer(HANDLE timer) +{ + if (timer) + { + // Cancel the waitable timer + CancelWaitableTimer(timer); + + // There is a race condition where the timer could have fired before it was canceled, which would leave the handle set to fire the next time events are waited upon. CancelWaitableTimer will not reset the state of the handle so + // wait for 0 ms for the timer to fire to clear it. + WaitForSingleObject(timer, 0); + } +} + +HRESULT CHalfApp::GetPosition(UINT64* pu64Position, UINT64* pu64hnsQPCPosition) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IAudioClock> spAudioClock; + auto lock = m_CritSec.lock(); + + if (!VERIFY_SUCCEEDED(m_pAudioDeviceEndpoint.query_to(&spAudioClock))) { + return hr; + } + if (!VERIFY_SUCCEEDED(spAudioClock->GetPosition(pu64Position, pu64hnsQPCPosition))) { + return hr; + } + + return S_OK; +} diff --git a/audio/tests/wavetest/HalfApp.h b/audio/tests/wavetest/HalfApp.h new file mode 100644 index 00000000..1bf14de9 --- /dev/null +++ b/audio/tests/wavetest/HalfApp.h @@ -0,0 +1,195 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// File Name: +// +// HalfApp.h +// +// Abstract: +// +// CHalfApp declarations +// +// ------------------------------------------------------------------------------- +#pragma once + +#define BUF_LEN_IN_MS 1000 // 1 second + +class CHalfApp +{ +public: + // Basic pin infos + wil::com_ptr_nothrow<IMMDevice> m_pDevice; + wil::unique_cotaskmem_string m_pwstrDeviceId; + wil::unique_cotaskmem_string m_pwstrDeviceFriendlyName; + STACKWISE_DATAFLOW m_DataFlow; + EndpointConnectorType m_ConnectorType; + UINT m_uConnectorId; + GUID m_Mode; + ULONG m_cModes; + GUID* m_pModes; // All processing modes + + // Formats + wil::unique_cotaskmem_ptr<WAVEFORMATEX> m_pPreferredFormat; + UINT32 m_u32DefaultPeriodicityInFrames; + UINT32 m_u32FundamentalPeriodicityInFrames; + UINT32 m_u32MinPeriodicityInFrames; + UINT32 m_u32MaxPeriodicityInFrames; + + PFORMAT_RECORD m_pFormatRecords; + ULONG m_cFormatRecords; + + wil::unique_cotaskmem_ptr<WAVEFORMATEX> m_pCurrentFormat; + UINT32 m_u32CurrentDefaultPeriodicityInFrames; + UINT32 m_u32CurrentFundamentalPeriodicityInFrames; + UINT32 m_u32CurrentMinPeriodicityInFrames; + UINT32 m_u32CurrentMaxPeriodicityInFrames; + + // Audio endpoint interfaces + wil::com_ptr_nothrow<IAudioDeviceEndpoint> m_pAudioDeviceEndpoint; + wil::com_ptr_nothrow<IAudioEndpoint> m_pAudioEndpoint; + wil::com_ptr_nothrow<IAudioEndpointControl> m_pAudioEndpointControl; + wil::com_ptr_nothrow<IAudioEndpointRT> m_pAudioEndpointRT; + + // Data buffer + wil::unique_hlocal_ptr<BYTE> m_pbSineToneDataBuffer; + DWORD m_dwSineToneDataBufferSize; + DWORD m_dwSineToneDataBufferPosition; + + // Stream + HNSTIME m_hnsPeriod = 0; + FLOAT32 m_f32EndpointFrameRate = 0.F; + HNSTIME m_hnsEndpointLatency = 0; + bool m_bIsEventCapable = false; + bool m_bStreamInitialized = false; + volatile bool m_bStreamThreadTerminate = false; + bool m_bYieldActive = false; + bool m_bIsBackupTimerRequired = true; + + wil::unique_handle m_hStreamThread; + + LPTHREAD_START_ROUTINE m_pStreamRoutine = nullptr; + wil::unique_event_nothrow m_hProcessThreadStartedEvent; + wil::unique_event_nothrow m_hTerminate; + wil::unique_event_nothrow m_hEndpointBufferCompleteEvent; + wil::unique_handle m_hTimer; + + wil::critical_section m_CritSec; + + typedef enum + { + ET_DO_NOTHING = 0x00, + ET_TERMINATE = 0x01, + ET_OBJECT_BUFFER_COMPLETE = 0x02, + ET_CLIENT_RELEASE_BUFFER = 0x04, + ET_TIMER = 0x08, + ET_PAUSE_PUMP = 0x10, + ET_RESUME_PUMP = 0x20, + } TEventType; + + CHalfApp( + _In_ IMMDevice* pDevice, + _In_ LPWSTR pwstrAudioEndpointId, + _In_ LPWSTR pwstrAudioEndpointFriendlyName, + _In_ STACKWISE_DATAFLOW dataFlow, + _In_ EndpointConnectorType eConnectorType, + _In_ UINT uConnectorId, + _In_ GUID mode, + _In_ ULONG cModes, + _In_ GUID* pModes, + _In_ ULONG cFormatRecords, + _In_ PFORMAT_RECORD pFormatRecords, + _In_ PWAVEFORMATEX pPreferredFormat, + _In_ UINT32 u32DefaultPeriodicityInFrames, + _In_ UINT32 u32FundamentalPeriodicityInFrames, + _In_ UINT32 u32MinPeriodicityInFrames, + _In_ UINT32 u32MaxPeriodicityInFrames + ) + : m_DataFlow(dataFlow) + , m_ConnectorType(eConnectorType) + , m_uConnectorId(uConnectorId) + , m_cModes(cModes) + , m_cFormatRecords(cFormatRecords) + , m_u32DefaultPeriodicityInFrames(u32DefaultPeriodicityInFrames) + , m_u32FundamentalPeriodicityInFrames(u32FundamentalPeriodicityInFrames) + , m_u32MinPeriodicityInFrames(u32MinPeriodicityInFrames) + , m_u32MaxPeriodicityInFrames(u32MaxPeriodicityInFrames) + , m_u32CurrentDefaultPeriodicityInFrames(u32DefaultPeriodicityInFrames) + , m_u32CurrentFundamentalPeriodicityInFrames(u32FundamentalPeriodicityInFrames) + , m_u32CurrentMinPeriodicityInFrames(u32MinPeriodicityInFrames) + , m_u32CurrentMaxPeriodicityInFrames(u32MaxPeriodicityInFrames) + { + m_pDevice = pDevice; + m_pAudioDeviceEndpoint = nullptr; + m_pAudioEndpointControl = nullptr; + + m_pwstrDeviceId = wil::make_cotaskmem_string_nothrow(pwstrAudioEndpointId, wcslen(pwstrAudioEndpointId)); + m_pwstrDeviceFriendlyName = wil::make_cotaskmem_string_nothrow(pwstrAudioEndpointFriendlyName, wcslen(pwstrAudioEndpointFriendlyName)); + m_Mode = mode; + + m_pModes = new GUID[cModes]; + memcpy(m_pModes, pModes, sizeof(GUID)*cModes); + m_pFormatRecords = new FORMAT_RECORD[cFormatRecords]; + memcpy(m_pFormatRecords, pFormatRecords, sizeof(FORMAT_RECORD)*cFormatRecords); + + CloneWaveFormat(pPreferredFormat, wil::out_param(m_pPreferredFormat)); + CloneWaveFormat(pPreferredFormat, wil::out_param(m_pCurrentFormat)); // Use preferred format as current format + } + + ~CHalfApp(void) + { + if (m_pModes) + delete[] m_pModes; + if (m_pFormatRecords) + delete[] m_pFormatRecords; + } + + // Audio endpoint interfaces + HRESULT InitializeEndpoint(); + HRESULT ReleaseEndpoint(); + HRESULT StartEndpoint(); + HRESULT StopEndpoint(); + HRESULT ResetEndpoint(); + + // Sine tone data buffer + HRESULT CreateSineToneDataBuffer(WAVEFORMATEX* pWfx); + HRESULT ReleaseSineToneDataBuffer(); + + + + + // Stream + HRESULT InitializeAndSetBuffer(HNSTIME hnsPeriod, UINT32 u32LatencyCoefficient); + HRESULT InitializeStream(HNSTIME requestedPeriodicity, UINT32 u32LatencyCoefficient); + HRESULT CleanupStream(); + HRESULT StartStream(); + HRESULT StopStream(); + static DWORD CALLBACK RenderStreamRoutine(PVOID lpParameter); + static DWORD CALLBACK CaptureStreamRoutine(PVOID lpParameter); + void SignalAndWaitForThread(); + + + + HRESULT SetTimer(HANDLE timer, HNSTIME timeDuration, bool fireImmediatley); + void CancelTimer(HANDLE timer); + HRESULT GetPosition(UINT64* pu64Position, UINT64* pu64hnsQPCPosition); + + // Multiple pin instances + HRESULT GetCurrentAvailiablePinInstanceCount(UINT32* pAvailablePinInstanceCount); + HRESULT GetSecondHalfApp(AUDIO_SIGNALPROCESSINGMODE secondMode, CHalfApp** ppSecondHalfApp); + + // Only for loopback testcases + HRESULT GetHostHalfApp(CHalfApp** ppHostHalfApp); +}; + +// {571BF784-A9D6-420A-BCA0-C579A8710236} +DEFINE_GUID(IID_IHalfAppContainer, + 0x571bf784, 0xa9d6, 0x420a, 0xbc, 0xa0, 0xc5, 0x79, 0xa8, 071, 0x02, 0x36); + +DECLARE_INTERFACE_IID_( +IHalfAppContainer, +IUnknown, +"571BF784-A9D6-420A-BCA0-C579A8710236") +{ + STDMETHOD(GetHalfApp)(THIS_ CHalfApp ** ppHalfApp) PURE; +}; diff --git a/audio/tests/wavetest/PreComp.h b/audio/tests/wavetest/PreComp.h new file mode 100644 index 00000000..2044d6b1 --- /dev/null +++ b/audio/tests/wavetest/PreComp.h @@ -0,0 +1,154 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// File Name: +// +// PreComp.h +// +// Abstract: +// +// Precompiled common headers +// +// ------------------------------------------------------------------------------- + +#include <basiclog.h> +#include <BasicLogHelper.h> +#include <mmsystem.h> +#include <atlbase.h> +#include <atlcom.h> +#include <initguid.h> + +#include <AudioEngineEndpoint.h> +#include <AudioEngineEndpointP.h> +#include <Audioclient.h> +#include <mmdeviceapi.h> +#include <mmdeviceapip.h> +#include <devicetopology.h> +#include <devicetopologyp.h> +#include <propvarutil.h> + +#include <wil\com.h> + +#include <winioctl.h> +#include <KsLib.h> +#include <Waveutil.h> +#include <aecommon.h> +#include <ilog.h> +#include <shlflags.h> +#include <basicprintf.h> +#include <wextestclass.h> +#include <resourcelist.h> + +// ------------------------------------------------------------------------------ +// Log +#define LOG(log, ...) BasicLogPrintf( log, XMSG, 1, __VA_ARGS__ ) +#define SKIP(log, ...) BasicLogPrintf( log, XSKIP, 1, __VA_ARGS__ ) +#define WARN(log, ...) BasicLogPrintf( log, XWARN, 1, __VA_ARGS__ ) +#define BLOCK(log, ...) BasicLogPrintf( log, XBLOCK, 1, __VA_ARGS__ ) +#define ERR(log, ...) BasicLogPrintf( log, XFAIL, 1, __VA_ARGS__ ) + +// ------------------------------------------------------------------------------ +// Data flow +enum STACKWISE_DATAFLOW { render, capture }; + +// ------------------------------------------------------------------------------ +// Structs used to hold results of format records +typedef struct +{ + WAVEFORMATEXTENSIBLE wfxEx; + UINT32 fundamentalPeriodInFrames; + UINT32 defaultPeriodInFrames; + UINT32 minPeriodInFrames; + UINT32 maxPeriodInFrames; + UINT32 maxPeriodInFramesExtended; +} FORMAT_RECORD, *PFORMAT_RECORD; + +// ---------------------------------------------------------- +// Parameters for test sine tone +#define TEST_AMPLITUDE 1.0f +#define TEST_FREQUENCY 200.0f + +// ---------------------------------------------------------- +// Predefined format list for offload streaming +#define COUNT_FORMATS 4 + +static WAVEFORMATEXTENSIBLE ListofFormats[COUNT_FORMATS] = +{ + // 1 + { + // Format + { + WAVE_FORMAT_EXTENSIBLE, // wFormatTag + 2, // nChannels + 44100, // nSamplesPerSec + 176400, // nAvgBytesPerSec + 4, // nBlockAlign + 16, // wBitsPerSample + 22 // cbSize + }, + // Samples + { + 16 // wValidBitsPerSample + }, + KSAUDIO_SPEAKER_STEREO, // dwChannelMask + KSDATAFORMAT_SUBTYPE_PCM // SubFormat + }, + // 2 + { + // Format + { + WAVE_FORMAT_EXTENSIBLE, // wFormatTag + 2, // nChannels + 48000, // nSamplesPerSec + 192000, // nAvgBytesPerSec + 4, // nBlockAlign + 16, // wBitsPerSample + 22 // cbSize + }, + // Samples + { + 16 // wValidBitsPerSample + }, + KSAUDIO_SPEAKER_STEREO, // dwChannelMask + KSDATAFORMAT_SUBTYPE_PCM // SubFormat + }, + // 3 + { + // Format + { + WAVE_FORMAT_EXTENSIBLE, // wFormatTag + 2, // nChannels + 88200, // nSamplesPerSec + 352800, // nAvgBytesPerSec + 4, // nBlockAlign + 16, // wBitsPerSample + 22 // cbSize + }, + // Samples + { + 16 // wValidBitsPerSample + }, + KSAUDIO_SPEAKER_STEREO, // dwChannelMask + KSDATAFORMAT_SUBTYPE_PCM // SubFormat + }, + // 4 + { + // Format + { + WAVE_FORMAT_EXTENSIBLE, // wFormatTag + 2, // nChannels + 96000, // nSamplesPerSec + 384000, // nAvgBytesPerSec + 4, // nBlockAlign + 16, // wBitsPerSample + 22 // cbSize + }, + // Samples + { + 16 // wValidBitsPerSample + }, + KSAUDIO_SPEAKER_STEREO, // dwChannelMask + KSDATAFORMAT_SUBTYPE_PCM // SubFormat + }, +};
\ No newline at end of file diff --git a/audio/tests/wavetest/PropertyHelper.cpp b/audio/tests/wavetest/PropertyHelper.cpp new file mode 100644 index 00000000..fb60d3cc --- /dev/null +++ b/audio/tests/wavetest/PropertyHelper.cpp @@ -0,0 +1,1095 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// Module Name: +// +// EndpointPropertyHelpers.cpp +// +// Abstract: +// +// Implementation for common helpers of endpoint property +// +// ------------------------------------------------------------------------------- +#include "PreComp.h" +#include <AVEndpointKeys.h> +#include <Functiondiscoverykeys_devpkey.h> +#include "PropertyHelper.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetConnectorId +// +// Retrieve the connector id from the property store and checks if the connector exists +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetConnectorId +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + bool* hasConnector, + UINT* pConnectorId +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetEndpointFriendlyName +// +// Retrieve the endpoint friendly name from the property store +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetEndpointFriendlyName +( + IMMDevice* pDevice, + LPWSTR* ppwszEndpointName +) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IPropertyStore> spPropertyStore; + wil::unique_prop_variant var; + wil::unique_cotaskmem_string pwszName; + + *ppwszEndpointName = NULL; + + // Retrieve the endpoint friendly name from the propertey store + if (!VERIFY_SUCCEEDED(hr = pDevice->OpenPropertyStore(STGM_READ, &spPropertyStore))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = spPropertyStore->GetValue(PKEY_Device_FriendlyName, &var))) { + return hr; + } + if (!VERIFY_IS_TRUE(var.vt == VT_LPWSTR)) { + hr = E_FAIL; + return hr; + } + + pwszName = wil::make_cotaskmem_string_nothrow(var.pwszVal); + if (!VERIFY_IS_TRUE(pwszName.get() && wcslen(pwszName.get()) != 0)) { + hr = E_FAIL; + return hr; + } + + *ppwszEndpointName = pwszName.release(); + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetAudioFilterAsDevice +// +// Get the audio filter from MMDevice. This method is called to activate IKsControl, IKsFormatSupport or IKsGetProposedFormat. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetAudioFilterAsDevice +( + IMMDevice* pDevice, + IMMDevice** ppAudioFilterAsDevice +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetCachedProcessingModes +// +// Read the processing mode characteristics from the property store and get all processing modes. This method applies to host and keyword detector pins only. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetCachedProcessingModes +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + ULONG *pCount, + AUDIO_SIGNALPROCESSINGMODE **ppModes +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetProcessingModes +// +// Query for connector's processing modes property +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetProcessingModes +( + IMMDevice* pDevice, + UINT pinId, + ULONG *pCount, + AUDIO_SIGNALPROCESSINGMODE **ppModes +) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IMMDevice> spAudioFilter; + wil::com_ptr_nothrow<IKsControl> spKsControl; + KSP_PIN pinProp; + ULONG cbNeeded = 0; + ULONG cbProperty; + PKSMULTIPLE_ITEM pProperty = NULL; + ULONG cbReturned = 0; + AUDIO_SIGNALPROCESSINGMODE* pModes = NULL; + CComHeapPtr<AUDIO_SIGNALPROCESSINGMODE> spModes; + + *pCount = 0; + *ppModes = NULL; + + // Get the audio filter + if (!VERIFY_SUCCEEDED(hr = GetAudioFilterAsDevice(pDevice, &spAudioFilter))) { + return hr; + } + + // Activate IKsControl + if (!VERIFY_SUCCEEDED(hr = spAudioFilter->Activate(__uuidof(IKsControl), CLSCTX_ALL, NULL, (VOID**)&spKsControl))) { + return hr; + } + + // Read the audio signal processing mode property + pinProp.Property.Set = KSPROPSETID_AudioSignalProcessing; + pinProp.Property.Id = KSPROPERTY_AUDIOSIGNALPROCESSING_MODES; + pinProp.Property.Flags = KSPROPERTY_TYPE_GET; + pinProp.PinId = pinId & PARTID_MASK; + pinProp.Reserved = 0; + + // Determined the needed size + if (!VERIFY_SUCCEEDED(hr = spKsControl->KsProperty(&pinProp.Property, sizeof(KSP_PIN), NULL, 0, &cbNeeded))) { + return hr; + } + if (!VERIFY_IS_TRUE(cbNeeded > 0) || !VERIFY_IS_TRUE((cbNeeded - sizeof(KSMULTIPLE_ITEM)) % sizeof(GUID) == 0)) { + hr = E_NOTFOUND; + return hr; + } + + cbProperty = cbNeeded; + pProperty = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(cbNeeded); + + if (!VERIFY_IS_NOT_NULL(pProperty)) { + hr = E_OUTOFMEMORY; + cbProperty = 0; + return hr; + } + + // Query the processing mode property + if (!VERIFY_SUCCEEDED(hr = spKsControl->KsProperty(&pinProp.Property, sizeof(KSP_PIN), pProperty, cbNeeded, &cbReturned))) { + goto Exit; + } + + if (!VERIFY_IS_NOT_NULL(pProperty)) { + hr = E_NOTFOUND; + goto Exit; + } + + if (!VERIFY_IS_TRUE(cbProperty >= (sizeof(KSMULTIPLE_ITEM) + pProperty->Count * sizeof(GUID)))) { + hr = E_NOTFOUND; + goto Exit; + } + + pModes = reinterpret_cast<GUID*>(pProperty + 1); + + if (!VERIFY_IS_TRUE(spModes.Allocate(pProperty->Count))) + { + hr = E_OUTOFMEMORY; + goto Exit; + } + + memcpy(spModes, pModes, sizeof(AUDIO_SIGNALPROCESSINGMODE)*(pProperty->Count)); + + *pCount = pProperty->Count; + *ppModes = spModes.Detach(); + +Exit: + if (pProperty != NULL) { + CoTaskMemFree(pProperty); + } + cbProperty = 0; + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetCachedSupportedFormatRecords +// +// Read the processing mode characteristics from the property store and get all supported formats for processing mode. This method applies to host and keyword detector pins only. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetCachedSupportedFormatRecords +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + ULONG *pCount, + FORMAT_RECORD **ppFormatRecords +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetSupportedFormatRecords +// +// For pins do not have cached supported formats information, such as offload pin, we provide our predefined format list and check whether each is supported by the pin. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetSupportedFormatRecords +( + IMMDevice* pDevice, + UINT pinId, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + STACKWISE_DATAFLOW dataFlow, + ULONG *pCount, + FORMAT_RECORD **ppFormatRecords +) +{ + HRESULT hr = S_OK; + FORMAT_RECORD *pFormatRecords; + UINT cFormatRecords = 0; + CComHeapPtr<FORMAT_RECORD> spFormatRecords; + BOOL isSupported = false; + WAVEFORMATEX *pWfx; + UINT32 u32DefaultPeriodicityInFrames = 0; + UINT32 u32FundamentalPeriodicityInFrames = 0; + UINT32 u32MinPeriodicityInFrames = 0; + UINT32 u32MaxPeriodicityInFrames = 0; + UINT32 u32MaxPeriodicityInFramesExtended = 0; + + // Init return + *pCount = 0; + *ppFormatRecords = NULL; + + pFormatRecords = new FORMAT_RECORD[COUNT_FORMATS]; + if (!VERIFY_IS_NOT_NULL(pFormatRecords)) { + hr = E_OUTOFMEMORY; + return hr; + } + memset(pFormatRecords, 0, sizeof(FORMAT_RECORD)*COUNT_FORMATS); + + for (ULONG i = 0; i < COUNT_FORMATS; i++) { + pWfx = (WAVEFORMATEX*)&ListofFormats[i]; + + // Check if format is supported + if (!VERIFY_SUCCEEDED(hr = IsFormatSupported(pDevice, pinId, pWfx, &isSupported))) { + return hr; + } + + // If the format is supported, we discover the periodicity characteristics for the format and store them along with the format in our FORMAT_RECORD struct. + if (isSupported) { + if (!VERIFY_SUCCEEDED(hr = DiscoverPeriodicityCharacteristicsForFormat(pDevice, eConnectorType, mode, pWfx, dataFlow, &u32DefaultPeriodicityInFrames, &u32FundamentalPeriodicityInFrames, &u32MinPeriodicityInFrames, &u32MaxPeriodicityInFrames, &u32MaxPeriodicityInFramesExtended))) { + return hr; + } + + pFormatRecords[cFormatRecords].defaultPeriodInFrames = u32DefaultPeriodicityInFrames; + pFormatRecords[cFormatRecords].fundamentalPeriodInFrames = u32FundamentalPeriodicityInFrames; + pFormatRecords[cFormatRecords].minPeriodInFrames = u32MinPeriodicityInFrames; + pFormatRecords[cFormatRecords].maxPeriodInFrames = u32MaxPeriodicityInFrames; + pFormatRecords[cFormatRecords].maxPeriodInFramesExtended = u32MaxPeriodicityInFramesExtended; + memcpy(&pFormatRecords[cFormatRecords].wfxEx, &ListofFormats[i], sizeof(WAVEFORMATEX) + ListofFormats[i].Format.cbSize); + cFormatRecords++; + } + } + + if (!VERIFY_IS_TRUE(spFormatRecords.Allocate(cFormatRecords))) { + hr = E_OUTOFMEMORY; + return hr; + } + + memcpy(spFormatRecords, pFormatRecords, sizeof(FORMAT_RECORD)*cFormatRecords); + delete[] pFormatRecords; + + *pCount = cFormatRecords; + *ppFormatRecords = spFormatRecords.Detach(); + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// IsFormatSupported +// +// Wrap up the IKsFormatSupport::IsFormatSupported method. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT IsFormatSupported +( + IMMDevice* pDevice, + UINT pinId, + WAVEFORMATEX *pWfx, + BOOL* pbSupported +) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IMMDevice> spAudioFilter; + wil::com_ptr_nothrow<IDeviceTopology> spAudioFilterTopology; + wil::com_ptr_nothrow<IPart> spPart; + wil::com_ptr_nothrow<IKsFormatSupport> spFormatSupport; + PKSDATAFORMAT_WAVEFORMATEXTENSIBLE pKsRequestedFormat = NULL; + PKSDATAFORMAT pKsFormat = NULL; + KSDATAFORMAT_WAVEFORMATEXTENSIBLE KsWfex = {}; + DWORD cbKsFormat = 0; + + // Init return + *pbSupported = FALSE; + + // Get the audio filter + if (!VERIFY_SUCCEEDED(hr = GetAudioFilterAsDevice(pDevice, &spAudioFilter))) { + return hr; + } + + // Activate an IDeviceTopology on the filter + if (!VERIFY_SUCCEEDED(hr = spAudioFilter->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spAudioFilterTopology))) { + return hr; + } + + // Get the connector + if (!VERIFY_SUCCEEDED(hr = spAudioFilterTopology->GetPartById(pinId, &spPart))) { + return hr; + } + + // Activate IKsFormatSupport interface + if (!VERIFY_SUCCEEDED(hr = spPart->Activate(CLSCTX_ALL, __uuidof(IKsFormatSupport), (void**)&spFormatSupport))) { + return hr; + } + + // Convert to KSDATAFORMAT_WAVEFORMATEX + if (!VERIFY_SUCCEEDED(hr = CreateKSFormatFromWFXFormat(pWfx, (KSDATAFORMAT_WAVEFORMATEX**)&pKsRequestedFormat))) { + return hr; + } + + if (pKsRequestedFormat->DataFormat.FormatSize < sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE)) + { + memcpy(&KsWfex, pKsRequestedFormat, pKsRequestedFormat->DataFormat.FormatSize); + pKsFormat = reinterpret_cast<KSDATAFORMAT *>(&KsWfex); + cbKsFormat = sizeof(KsWfex); + } + else + { + pKsFormat = reinterpret_cast<KSDATAFORMAT *>(pKsRequestedFormat); + cbKsFormat = pKsRequestedFormat->DataFormat.FormatSize; + } + + // Expect that pbFormat is really a KSDATAFORMAT + if (!VERIFY_IS_TRUE(cbKsFormat >= sizeof(KSDATAFORMAT))) { + hr = E_INVALIDARG; + return hr; + } + + // validate return pointers (this is an externally callable method) + if (!VERIFY_IS_TRUE(pKsFormat)) { + hr = E_POINTER; + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = spFormatSupport->IsFormatSupported(pKsFormat, cbKsFormat, pbSupported))) { + return hr; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// DiscoverPeriodicityCharacteristicsForFormat +// +// Discover the periodicity characteristics for given format. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT DiscoverPeriodicityCharacteristicsForFormat +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX *pWfx, + STACKWISE_DATAFLOW dataFlow, + UINT32 *pDefaultPeriodicityInFrames, + UINT32 *pFundamentalPeriodicityInFrames, + UINT32 *pMinPeriodicityInFrames, + UINT32 *pMaxPeriodicityInFrames, + UINT32 *pMaxPeriodicityInFramesExtended +) +{ + HRESULT hr = S_OK; + HNSTIME hnsDefaultPeriod = kSystemDefaultPeriod; + UINT32 ActualPeriodicityInFrames; + + // Verify format is not null + if (!VERIFY_IS_NOT_NULL(pWfx)) { + hr = E_INVALIDARG; + return hr; + } + + *pDefaultPeriodicityInFrames = + *pFundamentalPeriodicityInFrames = + *pMinPeriodicityInFrames = + *pMaxPeriodicityInFrames = HNSTIME_TO_FRAMES_DOUBLE(hnsDefaultPeriod, pWfx->nSamplesPerSec); + + // Check to see whether the endpoint supports the default periodicity and return the actual periodicity + if (!VERIFY_SUCCEEDED(hr = CheckConnectorSupportForPeriodicity(pDevice, eConnectorType, mode, pWfx, dataFlow, hnsDefaultPeriod, &ActualPeriodicityInFrames))) { + return hr; + } + + // Use what we get as the default, max, min and fundamental periodicity + *pDefaultPeriodicityInFrames = + *pFundamentalPeriodicityInFrames = + *pMinPeriodicityInFrames = + *pMaxPeriodicityInFrames = ActualPeriodicityInFrames; + + // Max periodicity is capped to the default periodicity for all clients except extended periodicity clients + *pMaxPeriodicityInFramesExtended = *pMaxPeriodicityInFrames; + if (*pMaxPeriodicityInFrames > *pDefaultPeriodicityInFrames) + { + *pMaxPeriodicityInFrames = *pDefaultPeriodicityInFrames; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// CheckConnectorSupportForPeriodicity +// +// Check to see if the connector supports the specified periodicity and return the actual periodicity. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CheckConnectorSupportForPeriodicity +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX *pWfx, + STACKWISE_DATAFLOW dataFlow, + HNSTIME RequestedPeriodicity, + UINT32 *pActualPeriodicityInFrames +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetCachedDefaultFormat +// +// Read the default device format from the property store. Use audio engine device format for all other pin types. For Keyword Detector pin, it has a different default device format. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetCachedDefaultFormat +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + WAVEFORMATEX** ppDefaultFormat +) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetProposedFormatForProcessingMode +// +// Wrap up the IKsGetProposedFormat::GetProposedFormatForMode method. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetProposedFormatForProcessingMode +( + IMMDevice* pDevice, + UINT pinId, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX **ppProposedFormat +) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IMMDevice> spAudioFilter; + wil::com_ptr_nothrow<IDeviceTopology> spAudioFilterTopology; + wil::com_ptr_nothrow<IPart> spPart; + + + + PKSDATAFORMAT pKsProposedFormat = NULL; + WAVEFORMATEXTENSIBLE* pWfxEx = NULL; + + // Init return + *ppProposedFormat = NULL; + + if (!VERIFY_SUCCEEDED(hr = GetAudioFilterAsDevice(pDevice, &spAudioFilter))) { + return hr; + } + + // Activate an IDeviceTopology on the filter + if (!VERIFY_SUCCEEDED(hr = spAudioFilter->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spAudioFilterTopology))) { + return hr; + } + + // Get the connector + if (!VERIFY_SUCCEEDED(hr = spAudioFilterTopology->GetPartById(pinId, &spPart))) { + return hr; + } + + // Retrieve the proposed format for a specific processing mode and store it in pKsProposedFormat... + + + + + + + + + + + + + // Allocate memory for ppOffloadDefaultFormat and copy pKsDataDeviceFormat to ppOffloadDefaultFormat + pWfxEx = (WAVEFORMATEXTENSIBLE *)CoTaskMemAlloc(sizeof(WAVEFORMATEX) + ((PKSDATAFORMAT_WAVEFORMATEX)pKsProposedFormat)->WaveFormatEx.cbSize); + if (!VERIFY_IS_NOT_NULL(pWfxEx)) { + CoTaskMemFree(pKsProposedFormat); + hr = E_OUTOFMEMORY; + return hr; + } + memcpy(pWfxEx, &(((PKSDATAFORMAT_WAVEFORMATEX)pKsProposedFormat)->WaveFormatEx), sizeof(WAVEFORMATEX) + ((PKSDATAFORMAT_WAVEFORMATEX)pKsProposedFormat)->WaveFormatEx.cbSize); + *ppProposedFormat = (WAVEFORMATEX*)pWfxEx; + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetCurrentAvailiablePinInstanceCount +// +// Query for the connector's pin instance count property. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetAvailiablePinInstanceCount +( + IMMDevice* pDevice, + UINT pinId, + UINT32* pAvailablePinInstanceCount +) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IMMDevice> spAudioFilter; + wil::com_ptr_nothrow<IKsControl> spKsControl; + KSP_PIN pinProp; + KSPIN_CINSTANCES pinInstances; + ULONG cbReturned = 0; + + *pAvailablePinInstanceCount = 0; + + if (!VERIFY_SUCCEEDED(hr = GetAudioFilterAsDevice(pDevice, &spAudioFilter))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = spAudioFilter->Activate(__uuidof(IKsControl), CLSCTX_ALL, NULL, (VOID**)&spKsControl))) { + return hr; + } + + // Read the pin instance count + pinProp.Property.Set = KSPROPSETID_Pin; + pinProp.Property.Id = KSPROPERTY_PIN_CINSTANCES; + pinProp.Property.Flags = KSPROPERTY_TYPE_GET; + pinProp.PinId = pinId & PARTID_MASK; + pinProp.Reserved = 0; + + if (!VERIFY_SUCCEEDED(hr = spKsControl->KsProperty(&pinProp.Property, sizeof(KSP_PIN), &pinInstances, sizeof(KSPIN_CINSTANCES), &cbReturned))) { + return hr; + } + + *pAvailablePinInstanceCount = pinInstances.PossibleCount - pinInstances.CurrentCount; + + return hr; +} diff --git a/audio/tests/wavetest/PropertyHelper.h b/audio/tests/wavetest/PropertyHelper.h new file mode 100644 index 00000000..9f01a9a7 --- /dev/null +++ b/audio/tests/wavetest/PropertyHelper.h @@ -0,0 +1,190 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// Module Name: +// +// PropertyHelpers.h +// +// Abstract: +// +// Header for common helpers/defines of property +// +// ------------------------------------------------------------------------------- +#pragma once + +#define kSystemDefaultPeriod 100000 // 10 milliseconds +#define kSystemMinPeriodForNonRTCapableEndpoints 20000 // 2 milliseconds + + + + + + + + + + + + + + + + + + + + + + + + + + + +// ---------------------------------------------------------------------- +HRESULT GetConnectorId +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + bool* hasConnector, + UINT* pConnectorId +); + +// ---------------------------------------------------------------------- +HRESULT GetEndpointFriendlyName +( + IMMDevice* pDevice, + LPWSTR* ppwszEndpointName +); + +// ---------------------------------------------------------------------- +HRESULT GetAudioFilterAsDevice +( + IMMDevice* pDevice, + IMMDevice** ppAudioFilterAsDevice +); + +// ---------------------------------------------------------------------- +HRESULT GetCachedProcessingModes +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + ULONG *pCount, + AUDIO_SIGNALPROCESSINGMODE **ppModes +); + + + + + + + + + + + + +// ---------------------------------------------------------------------- +HRESULT GetProcessingModes +( + IMMDevice* pDevice, + UINT pinId, + ULONG *pCount, + AUDIO_SIGNALPROCESSINGMODE **ppModes +); + +// ---------------------------------------------------------------------- +HRESULT GetCachedSupportedFormatRecords +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + ULONG *pCount, + FORMAT_RECORD **ppFormatRecords +); + + + + + + + + + + + + + +// ---------------------------------------------------------------------- +HRESULT GetSupportedFormatRecords +( + IMMDevice* pDevice, + UINT pinId, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + STACKWISE_DATAFLOW dataFlow, + ULONG *pCount, + FORMAT_RECORD **ppFormatRecords +); + +// ---------------------------------------------------------------------- +HRESULT IsFormatSupported +( + IMMDevice* pDevice, + UINT pinId, + WAVEFORMATEX *pWfx, + BOOL* pbSupported +); + +// ---------------------------------------------------------------------- +HRESULT DiscoverPeriodicityCharacteristicsForFormat +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX *pWfx, + STACKWISE_DATAFLOW dataFlow, + UINT32 *pDefaultPeriodicityInFrames, + UINT32 *pFundamentalPeriodicityInFrames, + UINT32 *pMinPeriodicityInFrames, + UINT32 *pMaxPeriodicityInFrames, + UINT32 *pMaxPeriodicityInFramesExtended +); + +// ---------------------------------------------------------------------- +HRESULT CheckConnectorSupportForPeriodicity +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX *pWfx, + STACKWISE_DATAFLOW dataFlow, + HNSTIME RequestedPeriodicity, + UINT32 *pActualPeriodicityInFrames +); + +// ---------------------------------------------------------------------- +HRESULT GetCachedDefaultFormat +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + WAVEFORMATEX** ppDefaultFormat +); + +// ---------------------------------------------------------------------- +HRESULT GetProposedFormatForProcessingMode +( + IMMDevice* pDevice, + UINT pinId, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX **ppProposedFormat +); + +// ---------------------------------------------------------------------- +HRESULT GetAvailiablePinInstanceCount +( + IMMDevice* pDevice, + UINT pinId, + UINT32* pAvailablePinInstanceCount +); diff --git a/audio/tests/wavetest/TestResource.cpp b/audio/tests/wavetest/TestResource.cpp new file mode 100644 index 00000000..67f3ca79 --- /dev/null +++ b/audio/tests/wavetest/TestResource.cpp @@ -0,0 +1,331 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// File Name: +// +// TestResource.cpp +// +// Abstract: +// +// TAEF Test Resource implementation +// +// ------------------------------------------------------------------------------- + +#include "PreComp.h" +#include "HalfApp.h" +#include "TestResource.h" + +using namespace WEX::Logging; +using namespace WEX::TestExecution; + +CPinTestResource::CPinTestResource() : + m_cRef(1) +{} + +CPinTestResource::~CPinTestResource() +{} + +HRESULT STDMETHODCALLTYPE +CPinTestResource::CreateInstance +( + CHalfApp * pHalf, + REFGUID guid, + ITestResource ** ppOut +) +{ + HRESULT hr = S_OK; + CPinTestResource * pTestResource; + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + + if (!VERIFY_IS_NOT_NULL(pHalf)) + { + return E_INVALIDARG; + } + + if (!VERIFY_IS_NOT_NULL(ppOut)) + { + return E_POINTER; + } + + pTestResource = new CPinTestResource(); + if (!VERIFY_IS_NOT_NULL(pTestResource)) + { + return E_OUTOFMEMORY; + } + + if (!VERIFY_SUCCEEDED(hr = pTestResource->Initialize( + pHalf, guid))) { + pTestResource->Release(); + return hr; + } + + *ppOut = pTestResource; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CPinTestResource::Initialize +( + CHalfApp * pHalf, + REFGUID guid +) +{ + HRESULT hr = S_OK; + + WCHAR szStr[MAX_PATH]; + LPWSTR szMode; + LPWSTR szPin; + + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + + m_guid = guid; + m_spHalfApp.Attach(pHalf); + + // Dataflow + if (m_spHalfApp->m_DataFlow == capture) + { + m_szType.Attach(W2BSTR(L"Capture")); + if (!VERIFY_IS_NOT_NULL(m_szType)) { return E_OUTOFMEMORY; } + } + else + { + m_szType.Attach(W2BSTR(L"Render")); + if (!VERIFY_IS_NOT_NULL(m_szType)) { return E_OUTOFMEMORY; } + } + + szMode = ModeName(m_spHalfApp->m_Mode); + szPin = PinName(m_spHalfApp->m_ConnectorType); + + // Id: Combine device Id, pin type and mode + m_szId.Attach(W2BSTR(m_spHalfApp->m_pwstrDeviceId.get())); + if (!VERIFY_SUCCEEDED(hr = StringCchPrintfW( + szStr, MAX_PATH, L"#%s#%s", + szPin, + szMode))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = m_szId.Append(szStr))) { + return hr; + } + if (!VERIFY_IS_NOT_NULL(m_szId)) { return E_OUTOFMEMORY; } + + // Name: Combine device friendly name, pin type, and mode + m_szName.Attach(W2BSTR(m_spHalfApp->m_pwstrDeviceFriendlyName.get())); + if (!VERIFY_SUCCEEDED(hr = StringCchPrintfW( + szStr, MAX_PATH, L" Pin %s Mode %s", + szPin, + szMode))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = m_szName.Append(szStr))) { + return hr; + } + if (!VERIFY_IS_NOT_NULL(m_szName)) { return E_OUTOFMEMORY; } + + // Mode + m_szMode.Attach(W2BSTR(szMode)); + if (!VERIFY_IS_NOT_NULL(m_szMode)) { return E_OUTOFMEMORY; } + + // Pin + m_szPin.Attach(W2BSTR(szPin)); + if (!VERIFY_IS_NOT_NULL(m_szPin)) { return E_OUTOFMEMORY; } + + return hr; +} + +STDMETHODIMP_(ULONG) +CPinTestResource::AddRef() +{ + return InterlockedIncrement(&m_cRef); +} + +STDMETHODIMP_(ULONG) +CPinTestResource::Release() +{ + ULONG cRef = InterlockedDecrement(&m_cRef); + if (0 == cRef) + { + delete this; + } + + return cRef; +} + +STDMETHODIMP +CPinTestResource::QueryInterface( + __in REFIID riid, + __deref_out void ** ppvObject +) +{ + HRESULT hr = S_OK; + + //IF_FALSE_EXIT_HR( (NULL != ppvObject), E_POINTER); + + if (IsEqualIID(riid, __uuidof(IUnknown))) + { + *ppvObject = static_cast<void *>(this); + } + else if (IsEqualIID(riid, __uuidof(ITestResource))) + { + *ppvObject = static_cast<ITestResource *>(this); + } + else if (IsEqualIID(riid, __uuidof(IHalfAppContainer))) + { + *ppvObject = static_cast<IHalfAppContainer *>(this); + } + else + { + *ppvObject = NULL; + hr = E_NOINTERFACE; + goto Exit; + } + + AddRef(); + +Exit: + return hr; +} + +STDMETHODIMP +CPinTestResource::GetGuid(GUID* pGuid) { + // don't want to see VERIFY spew + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + + if (!VERIFY_IS_NOT_NULL(pGuid)) { return E_POINTER; } + + *pGuid = m_guid; + return S_OK; +} + +STDMETHODIMP +CPinTestResource::SetGuid(GUID guid) { + m_guid = guid; + return S_OK; +} + +STDMETHODIMP +CPinTestResource::GetValue(BSTR name, BSTR* pValue) { + // don't want to see VERIFY spew + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + + if (!VERIFY_IS_NOT_NULL(name)) { return E_POINTER; } + if (!VERIFY_IS_NOT_NULL(pValue)) { return E_POINTER; } + + if (0 == wcscmp(name, TestResourceProperty::c_szName)) { + if (!VERIFY_IS_NOT_NULL(*pValue = SysAllocString(m_szName))) { return E_OUTOFMEMORY; } + return S_OK; + } + + if (0 == wcscmp(name, TestResourceProperty::c_szId)) { + if (!VERIFY_IS_NOT_NULL(*pValue = SysAllocString(m_szId))) { return E_OUTOFMEMORY; } + return S_OK; + } + + if (0 == wcscmp(name, TestResourceProperty::c_szType)) { + if (!VERIFY_IS_NOT_NULL(*pValue = SysAllocString(m_szType))) { return E_OUTOFMEMORY; } + return S_OK; + } + + if (0 == wcscmp(name, TestResourceProperty::c_szMode)) { + if (!VERIFY_IS_NOT_NULL(*pValue = SysAllocString(m_szMode))) { return E_OUTOFMEMORY; } + return S_OK; + } + + if (0 == wcscmp(name, TestResourceProperty::c_szPin)) { + if (!VERIFY_IS_NOT_NULL(*pValue = SysAllocString(m_szPin))) { return E_OUTOFMEMORY; } + return S_OK; + } + + Log::Error(L"CDevice::GetValue name not found"); + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); +} + +STDMETHODIMP +CPinTestResource::SetValue(BSTR name, BSTR value) { + // don't want to see VERIFY spew + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + + if (!VERIFY_IS_NOT_NULL(name)) { return E_POINTER; } + if (!VERIFY_IS_NOT_NULL(value)) { return E_POINTER; } + + if (0 == wcscmp(name, TestResourceProperty::c_szName)) { + return m_szName.AssignBSTR(value); + } + + if (0 == wcscmp(name, TestResourceProperty::c_szId)) { + return m_szId.AssignBSTR(value); + } + + if (0 == wcscmp(name, TestResourceProperty::c_szType)) { + return m_szType.AssignBSTR(value); + } + + if (0 == wcscmp(name, TestResourceProperty::c_szMode)) { + return m_szMode.AssignBSTR(value); + } + + if (0 == wcscmp(name, TestResourceProperty::c_szPin)) { + return m_szPin.AssignBSTR(value); + } + + Log::Error(L"CDevice::SetValue name not found"); + + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); +} + +STDMETHODIMP +CPinTestResource::GetHalfApp(CHalfApp ** ppHalfApp) +{ + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + + if (!VERIFY_IS_NOT_NULL(ppHalfApp)) { return E_POINTER; } + + *ppHalfApp = m_spHalfApp; + + return S_OK; +} + +static const struct +{ + GUID mode; + LPWSTR name; +}knownModes[] = +{ + { GUID_NULL, L"NO_MODE" }, + { AUDIO_SIGNALPROCESSINGMODE_RAW, L"RAW" }, + { AUDIO_SIGNALPROCESSINGMODE_DEFAULT, L"DEFAULT" }, + { AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, L"COMMUNICATIONS" }, + { AUDIO_SIGNALPROCESSINGMODE_SPEECH, L"SPEECH" }, + { AUDIO_SIGNALPROCESSINGMODE_MEDIA, L"MEDIA" }, + { AUDIO_SIGNALPROCESSINGMODE_MOVIE, L"MOVIE" }, + { AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION, L"NOTIFICATION" }, +}; + + +LPWSTR CPinTestResource::ModeName(REFGUID guidMode) +{ + for (auto m : knownModes) + { + if (m.mode == guidMode) { return m.name; } + } + + return L"UNKNOWN"; +} + +LPWSTR CPinTestResource::PinName(EndpointConnectorType eConnectorType) +{ + switch (eConnectorType) + { + case eHostProcessConnector: + return L"HOST"; + case eOffloadConnector: + return L"OFFLOAD"; + case eLoopbackConnector: + return L"LOOPBACK"; + case eKeywordDetectorConnector: + return L"KEYWORD"; + default: + return L"UNKNOWN"; + } +}
\ No newline at end of file diff --git a/audio/tests/wavetest/TestResource.h b/audio/tests/wavetest/TestResource.h new file mode 100644 index 00000000..49dee5a5 --- /dev/null +++ b/audio/tests/wavetest/TestResource.h @@ -0,0 +1,66 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// File Name: +// +// TestResource.h +// +// Abstract: +// +// TAEF Test Resource +// +// ------------------------------------------------------------------------------- +#include "WaveTestTaef.h" + +class CPinTestResource : + public WEX::TestExecution::ITestResource, + public IHalfAppContainer +{ +public: + //IUnknown + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + STDMETHODIMP QueryInterface( + __in REFIID riid, + __deref_out VOID **ppvObject + ); + // ITestResouce + STDMETHODIMP GetGuid(GUID* pGuid); + STDMETHODIMP SetGuid(GUID guid); + STDMETHODIMP GetValue(BSTR name, BSTR* pValue); + STDMETHODIMP SetValue(BSTR name, BSTR value); + + //IHalfAppContainer + STDMETHODIMP GetHalfApp(CHalfApp ** ppHalfApp); + + static HRESULT STDMETHODCALLTYPE CreateInstance( + CHalfApp * pHalf, + REFGUID guid, + WEX::TestExecution::ITestResource ** ppOut + ); + +private: + + CPinTestResource(); + ~CPinTestResource(); + + HRESULT STDMETHODCALLTYPE Initialize( + CHalfApp * pHalf, + REFGUID guid + ); + + LPWSTR ModeName(REFGUID guidMode); + LPWSTR PinName(EndpointConnectorType eConnectorType); + + CComBSTR m_szType; + CComBSTR m_szName; + CComBSTR m_szId; + CComBSTR m_szMode; + CComBSTR m_szPin; + + CAutoPtr<CHalfApp> m_spHalfApp; + + ULONG m_cRef; + GUID m_guid; +};
\ No newline at end of file diff --git a/audio/tests/wavetest/TestResourceBuild.cpp b/audio/tests/wavetest/TestResourceBuild.cpp new file mode 100644 index 00000000..51cce52d --- /dev/null +++ b/audio/tests/wavetest/TestResourceBuild.cpp @@ -0,0 +1,493 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// File Name: +// +// TestResourceBuild.cpp +// +// Abstract: +// +// TAEF BuildResourceList implementation +// +// ------------------------------------------------------------------------------ +#include "PreComp.h" +#include "TestResource.h" +#include "PropertyHelper.h" + +using namespace WEX::Common; +using namespace WEX::Logging; +using namespace WEX::TestExecution; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// CreateTestResource +// +// Create the test resource with MMDevice, device id, device name, data flow, connector type, connector id, mode, +// list of formats +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CreateTestResource +( + ResourceList& resourceList, + LPWSTR deviceId, + LPWSTR deviceName, + IMMDevice* pDevice, + STACKWISE_DATAFLOW dataFlow, + EndpointConnectorType eConnectorType, + UINT uConnectorId, + AUDIO_SIGNALPROCESSINGMODE mode, + ULONG cModes, + AUDIO_SIGNALPROCESSINGMODE* pModes, + ULONG cFormatRecords, + PFORMAT_RECORD pFormatRecords, + PWAVEFORMATEX pPreferredFormat, + UINT32 defaultPeriodicityInFrames, + UINT32 fundamentalPeriodicityInFrames, + UINT32 minPeriodicityInFrames, + UINT32 maxPeriodicityInFrames +) +{ + HRESULT hr = S_OK; + CComHeapPtr<CHalfApp> spHalfApp; + wil::com_ptr_nothrow<ITestResource> spTestResource; + GUID ResourceGUID; + CComBSTR szResourceName; + + // Create HalfApp + spHalfApp.Attach(new CHalfApp(pDevice, deviceId, deviceName, dataFlow, eConnectorType, uConnectorId, mode, cModes, pModes, cFormatRecords, pFormatRecords, pPreferredFormat, defaultPeriodicityInFrames, fundamentalPeriodicityInFrames, minPeriodicityInFrames, maxPeriodicityInFrames)); + if (!VERIFY_IS_NOT_NULL(spHalfApp)) { + hr = E_OUTOFMEMORY; + return hr; + } + + // Create PinTestResource + if (!VERIFY_SUCCEEDED(hr = CoCreateGuid(&ResourceGUID))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = CPinTestResource::CreateInstance( + spHalfApp, ResourceGUID, &spTestResource))) { + return hr; + } + + // Add to resource list + spHalfApp.Detach(); + if (!VERIFY_SUCCEEDED(hr = resourceList.Add(spTestResource.get()))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = spTestResource->GetValue(CComBSTR(TestResourceProperty::c_szName), &szResourceName))) { + return hr; + } + Log::Comment(String().Format(L"Test Resource (%s) added", (PCWSTR)szResourceName)); + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetProcessingModesForConnector +// +// For host/keyword detector pin, processing mode info is cached in property store and can be directly read. For offload +// pin, query for ks processing mode property. For loopback pin, it doesn't support any processing modes, return GUID_NULL. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetProcessingModesForConnector +( + IMMDevice* pDevice, + UINT uConnectorId, + EndpointConnectorType eConnectorType, + ULONG *pCount, + AUDIO_SIGNALPROCESSINGMODE **ppModes +) +{ + HRESULT hr = S_OK; + + *pCount = 0; + *ppModes = NULL; + + if (eConnectorType == eHostProcessConnector || eConnectorType == eKeywordDetectorConnector) { + if (!VERIFY_SUCCEEDED(hr = GetCachedProcessingModes(pDevice, eConnectorType, pCount, ppModes))) { + return hr; + } + } + else if (eConnectorType == eOffloadConnector) { + if (!VERIFY_SUCCEEDED(hr = GetProcessingModes(pDevice, uConnectorId, pCount, ppModes))) { + return hr; + } + } + else if (eConnectorType == eLoopbackConnector) { + // Loopback pin doesn't support any processing modes, so put 1 GUID_NULL + CComHeapPtr<AUDIO_SIGNALPROCESSINGMODE> spModes; + + if (!spModes.Allocate(1)) + return E_OUTOFMEMORY; + + spModes[0] = GUID_NULL; + + *pCount = 1; + *ppModes = spModes.Detach(); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetDefaultFormatForConnector +// +// Read audio engine device format from property store as default format. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetDefaultFormatForConnector +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + WAVEFORMATEX **ppDefaultFormat +) +{ + HRESULT hr = S_OK; + + *ppDefaultFormat = NULL; + if (!VERIFY_SUCCEEDED(hr = GetCachedDefaultFormat(pDevice, eConnectorType, ppDefaultFormat))){ + return hr; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetSupportedFormatsForConnector +// +// For host/keyword detector pin, supported formats info is cached in property store and can be directly read. For offload +// pin, provide with a predefined list of formats and check whether format is supported. For loopback pin, it matches the format +// of host pin so put 0 format record. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetSupportedFormatRecordsForConnector +( + IMMDevice* pDevice, + UINT uConnectorId, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + STACKWISE_DATAFLOW dataFlow, + ULONG *pCount, + FORMAT_RECORD **ppFormatRecords +) +{ + HRESULT hr = S_OK; + + *pCount = 0; + *ppFormatRecords = NULL; + + if (eConnectorType == eHostProcessConnector || eConnectorType == eKeywordDetectorConnector) { + if (!VERIFY_SUCCEEDED(hr = GetCachedSupportedFormatRecords(pDevice, eConnectorType, mode, pCount, ppFormatRecords))) { + return hr; + } + } + else if (eConnectorType == eOffloadConnector) { + if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecords(pDevice, uConnectorId, eConnectorType, mode, dataFlow, pCount, ppFormatRecords))) { + return hr; + } + } + else if (eConnectorType == eLoopbackConnector) { + *pCount = 0; + *ppFormatRecords = NULL; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetPreferredFormatForConnector +// +// If KSPROPERTY_PIN_PROPOSEDATAFORMAT2 is supported, use the proposed format for mode as preferred format for mode. +// Otherwise, use default format as preferred format. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetPreferredFormatForConnector +( + IMMDevice* pDevice, + UINT uConnectorId, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX **ppPreferredFormat +) +{ + HRESULT hr = S_OK; + wil::unique_cotaskmem_ptr<WAVEFORMATEX> pDefaultFormat; + wil::unique_cotaskmem_ptr<WAVEFORMATEX> pProposedFormat; + + *ppPreferredFormat = NULL; + + + // Get default format for connector + if (!VERIFY_SUCCEEDED(hr = GetDefaultFormatForConnector(pDevice, eConnectorType, wil::out_param(pDefaultFormat)))) { + return hr; + } + + // Return the processing mode specific format proposed by the driver + hr = GetProposedFormatForProcessingMode(pDevice, uConnectorId, mode, wil::out_param(pProposedFormat)); + if (hr == S_OK) { + CloneWaveFormat(pProposedFormat.get(), ppPreferredFormat); + } + else { + CloneWaveFormat(pDefaultFormat.get(), ppPreferredFormat); + hr = S_OK; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// GetPreferredFormatPeriodicityCharacteristicsForConnector +// +// Get periodicity characteristics for format. For host/keyword detector pin, periodicity info is cached along with format +// in property store and can be searched from supported format list. For offload pin, it should be calculate from +// DiscoverPeriodicityCharacteristicsForFormat. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT GetPreferredFormatPeriodicityCharacteristicsForConnector +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + STACKWISE_DATAFLOW dataFlow, + WAVEFORMATEX *pPreferredFormat, + ULONG cFormatRecords, + PFORMAT_RECORD pFormatRecords, + UINT32 *pDefaultPeriodicityInFrames, + UINT32 *pFundamentalPeriodicityInFrames, + UINT32 *pMinPeriodicityInFrames, + UINT32 *pMaxPeriodicityInFrames, + UINT32 *pMaxPeriodicityInFramesExtended +) +{ + HRESULT hr = S_OK; + bool bFormatInList = false; + + for (ULONG i = 0; i < cFormatRecords; i++) { + if (CompareWaveFormat((WAVEFORMATEX *)&pFormatRecords[i].wfxEx, pPreferredFormat)) { + bFormatInList = true; + *pDefaultPeriodicityInFrames = pFormatRecords[i].defaultPeriodInFrames; + *pFundamentalPeriodicityInFrames = pFormatRecords[i].fundamentalPeriodInFrames; + *pMinPeriodicityInFrames = pFormatRecords[i].minPeriodInFrames; + *pMaxPeriodicityInFrames = pFormatRecords[i].maxPeriodInFrames; + *pMaxPeriodicityInFramesExtended = pFormatRecords[i].maxPeriodInFramesExtended; + break; + } + } + + if (eConnectorType == eHostProcessConnector || eConnectorType == eKeywordDetectorConnector) { + if (!VERIFY_IS_TRUE(bFormatInList)) { + hr = E_NOTFOUND; + return hr; + } + } + else if (eConnectorType == eOffloadConnector || eConnectorType == eLoopbackConnector) { + if (!VERIFY_SUCCEEDED(hr = DiscoverPeriodicityCharacteristicsForFormat(pDevice, eConnectorType, mode, pPreferredFormat, dataFlow, pDefaultPeriodicityInFrames, pFundamentalPeriodicityInFrames, pMinPeriodicityInFrames, pMaxPeriodicityInFrames, pMaxPeriodicityInFramesExtended))) { + return hr; + } + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// AddTestResourceForConnector +// +// For each connector, read connector id, get all processing modes, identify default and preferred format for each mode +// and also enumerate a list of supported formats for each mode. Store all the infos in test resource. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT AddTestResourceForConnector +( + ResourceList& resourceList, + LPWSTR deviceId, + LPWSTR deviceName, + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + STACKWISE_DATAFLOW dataFlow +) +{ + HRESULT hr = S_OK; + bool bHasConnector = false; + UINT uConnectorId; + ULONG cModes = 0; + CComHeapPtr<AUDIO_SIGNALPROCESSINGMODE> spModes; + AUDIO_SIGNALPROCESSINGMODE mode; + ULONG cFormatRecords = 0; + CComHeapPtr<FORMAT_RECORD> spFormatRecords; + wil::unique_cotaskmem_ptr<WAVEFORMATEX> pPreferredFormat; + UINT32 u32DefaultPeriodicityInFrames; + UINT32 u32FundamentalPeriodicityInFrames; + UINT32 u32MinPeriodicityInFrames; + UINT32 u32MaxPeriodicityInFrames; + UINT32 u32MaxPeriodicityInFramesExtended; + + // Get connector id + if (!VERIFY_SUCCEEDED(hr = GetConnectorId(pDevice, eConnectorType, &bHasConnector, &uConnectorId))) { + return hr; + } + if (!bHasConnector) { + return hr; + } + + Log::Comment(String().Format(L"Adding Test Resource for pin [%u]:", (uConnectorId & PARTID_MASK))); + + // Get all signal processing modes for connector + if (!VERIFY_SUCCEEDED(hr = GetProcessingModesForConnector(pDevice, uConnectorId, eConnectorType, &cModes, &spModes))) { + return hr; + } + + // Loop through each mode, get preferred format and list of formats and create test resource for each mode + for (ULONG i = 0; i < cModes; i++) { + mode = spModes[i]; + + if (!VERIFY_SUCCEEDED(hr = GetSupportedFormatRecordsForConnector(pDevice, uConnectorId, eConnectorType, mode, dataFlow, &cFormatRecords, &spFormatRecords))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatForConnector(pDevice, uConnectorId, eConnectorType, mode, wil::out_param(pPreferredFormat)))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = GetPreferredFormatPeriodicityCharacteristicsForConnector(pDevice, eConnectorType, mode, dataFlow, pPreferredFormat.get(), cFormatRecords, spFormatRecords, &u32DefaultPeriodicityInFrames, &u32FundamentalPeriodicityInFrames, &u32MinPeriodicityInFrames, &u32MaxPeriodicityInFrames, &u32MaxPeriodicityInFramesExtended))) { + return hr; + } + + if (!VERIFY_SUCCEEDED(hr = CreateTestResource(resourceList, deviceId, deviceName, pDevice, dataFlow, eConnectorType, uConnectorId, mode, cModes, spModes, cFormatRecords, spFormatRecords, pPreferredFormat.get(), u32DefaultPeriodicityInFrames, u32FundamentalPeriodicityInFrames, u32MinPeriodicityInFrames, u32MaxPeriodicityInFrames))) { + return hr; + } + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// AddTestResourcesForDevice +// +// Identify the existence of all pin types and add test resources for each pin +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT AddTestResourcesForDevice +( + ResourceList& resourceList, + LPWSTR deviceId, + LPWSTR deviceName, + STACKWISE_DATAFLOW dataFlow +) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator; + wil::com_ptr_nothrow<IMMDevice> spDevice; + + Log::Comment(String().Format(L"Adding Test Resource for Device [%s]:", deviceName)); + + // Read the default device format from the property store + if (!VERIFY_SUCCEEDED(hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&spEnumerator))) { + return hr; + } + if (!VERIFY_SUCCEEDED(hr = spEnumerator->GetDevice(deviceId, &spDevice))) { + return hr; + } + + // Identify existence of host pin. Add test resources for host pin. + if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eHostProcessConnector, dataFlow))) { + return hr; + } + + // Identify existence of offload pin. Add test resources for offload pin. + if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eOffloadConnector, dataFlow))) { + return hr; + } + + // Identify existence of loopback pin. Add test resources for loopback pin. + if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eLoopbackConnector, capture ))) { + return hr; + } + + /* + // Identify existence of keyword detector pin. Add test resources for keyword detector pin. + if (!VERIFY_SUCCEEDED(hr = AddTestResourceForConnector(resourceList, deviceId, deviceName, spDevice.get(), eKeywordDetectorConnector, dataFlow))) { + return hr; + } + */ + + return hr; +} + +HRESULT __cdecl BuildResourceList(ResourceList& resourceList) +{ + HRESULT hr = S_OK; + wil::com_ptr_nothrow<IMMDeviceEnumerator> spEnumerator; + wil::com_ptr_nothrow<IMMDeviceCollection> spRenderEndpoints; + wil::com_ptr_nothrow<IMMDeviceCollection> spCaptureEndpoints; + wil::com_ptr_nothrow<IMMDevice> spEndpoint; + UINT cRenderDevices = 0; + UINT cCaptureDevices = 0; + UINT i = 0; + wil::unique_cotaskmem_string id; + wil::unique_cotaskmem_string friendlyName; + + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + DisableVerifyExceptions disable; + + VERIFY_SUCCEEDED(::CoInitializeEx(NULL, COINIT_MULTITHREADED)); + + Log::Comment(L"In BuildResourceList"); + + // Create IMMDevice Enumerator + VERIFY_SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void **)&spEnumerator)); + + // Enumerate all render endpoints + VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &spRenderEndpoints)); + VERIFY_SUCCEEDED(spRenderEndpoints->GetCount(&cRenderDevices)); + + // Enumerate all capture endpoints + VERIFY_SUCCEEDED(spEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &spCaptureEndpoints)); + VERIFY_SUCCEEDED(spCaptureEndpoints->GetCount(&cCaptureDevices)); + + if (!VERIFY_IS_TRUE(cRenderDevices | cCaptureDevices)) + { + hr = E_FAIL; + Log::Comment(L"No device was found!"); + goto Exit; + } + + Log::Comment(String().Format(L"Found %d viable rendering device!", cRenderDevices)); + // Add test resources for render endpoints + if (cRenderDevices) { + for (i = 0; i < cRenderDevices; i++) { + VERIFY_SUCCEEDED(spRenderEndpoints->Item(i, &spEndpoint)); + VERIFY_SUCCEEDED(spEndpoint->GetId(&id)); + VERIFY_SUCCEEDED(GetEndpointFriendlyName(spEndpoint.get(), &friendlyName)); + + Log::Comment(String().Format(L"\\\\ Device: %s (%s)", friendlyName.get(), id.get())); + VERIFY_SUCCEEDED(AddTestResourcesForDevice(resourceList, id.get(), friendlyName.get(), render)); + } + } + + Log::Comment(String().Format(L"Found %d viable capture device!", cCaptureDevices)); + // Add test resources for capture endpoints + if (cCaptureDevices) { + for (i = 0; i < cCaptureDevices; i++) { + VERIFY_SUCCEEDED(spCaptureEndpoints->Item(i, &spEndpoint)); + VERIFY_SUCCEEDED(spEndpoint->GetId(&id)); + VERIFY_SUCCEEDED(GetEndpointFriendlyName(spEndpoint.get(), &friendlyName)); + + Log::Comment(String().Format(L"\\\\ Device: %s (%s)", friendlyName.get(), id.get())); + VERIFY_SUCCEEDED(AddTestResourcesForDevice(resourceList, id.get(), friendlyName.get(), capture)); + } + } + + Log::Comment(L"Resource enumeration complete."); + Log::Comment(String().Format(L"Enumerated %u resources", resourceList.Count())); + +Exit: + return hr; +} diff --git a/audio/tests/wavetest/TestResourceHelper.h b/audio/tests/wavetest/TestResourceHelper.h new file mode 100644 index 00000000..24bae634 --- /dev/null +++ b/audio/tests/wavetest/TestResourceHelper.h @@ -0,0 +1,71 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// Module Name: +// +// TestResourceHelpers.h +// +// Abstract: +// +// Header for BuildResourceList helpers. +// +// ------------------------------------------------------------------------------- +#pragma once + +// ---------------------------------------------------------------------- +HRESULT GetProcessingModesForConnector +( + IMMDevice* pDevice, + UINT uConnectorId, + EndpointConnectorType eConnectorType, + ULONG* pCount, + AUDIO_SIGNALPROCESSINGMODE** ppModes +); + +// ---------------------------------------------------------------------- +HRESULT GetDefaultFormatForConnector +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + WAVEFORMATEX** ppDefaultFormat +); + +// ---------------------------------------------------------------------- +HRESULT GetPreferredFormatForConnector +( + IMMDevice* pDevice, + UINT uConnectorId, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + WAVEFORMATEX** ppPreferredFormat +); + +// ---------------------------------------------------------------------- +HRESULT GetPreferredFormatPeriodicityCharacteristicsForConnector +( + IMMDevice* pDevice, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + STACKWISE_DATAFLOW dataFlow, + WAVEFORMATEX* pPreferredFormat, + ULONG cFormatRecords, + PFORMAT_RECORD pFormatRecords, + UINT32* pDefaultPeriodicityInFrames, + UINT32* pFundamentalPeriodicityInFrames, + UINT32* pMinPeriodicityInFrames, + UINT32* pMaxPeriodicityInFrames, + UINT32* pMaxPeriodicityInFramesExtended +); + +// ---------------------------------------------------------------------- +HRESULT GetSupportedFormatRecordsForConnector +( + IMMDevice* pDevice, + UINT uConnectorId, + EndpointConnectorType eConnectorType, + AUDIO_SIGNALPROCESSINGMODE mode, + STACKWISE_DATAFLOW dataFlow, + ULONG* pCount, + FORMAT_RECORD** ppFormatRecords +);
\ No newline at end of file diff --git a/audio/tests/wavetest/WaveTestTaef.cpp b/audio/tests/wavetest/WaveTestTaef.cpp new file mode 100644 index 00000000..dacf44ab --- /dev/null +++ b/audio/tests/wavetest/WaveTestTaef.cpp @@ -0,0 +1,170 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// File Name: +// +// WaveTestTaef.cpp +// +// Abstract: +// +// Implementation file for WaveTestTaef +// +// ------------------------------------------------------------------------------- +#include "PreComp.h" +#include "WaveTestTaef.h" +#include "tests.h" + +using namespace WEX::Common; +using namespace WEX::Logging; +using namespace WEX::TestExecution; + +#define RUN_TEST_CASE(testfn) \ +{ \ + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); \ + testfn(); \ +} + +IBasicLog * g_pBasicLog = NULL; +WDMAudio::WaveTest * g_pWaveTest = NULL; + +// ------------------------------------------------------------------------------- +namespace WDMAudio +{ + BEGIN_MODULE() + MODULE_PROPERTY(L"Feature", L"PortCls HCK Tests") + MODULE_PROPERTY(L"TestResourceDependent", L"true") + END_MODULE() + + // Create WEXBasicLog, Coinitialize Etc + MODULE_SETUP(WDMAudioSetup) + + // Release stuff acquired in WDMAudioSetup + MODULE_CLEANUP(WDMAudioCleanup) +}; + +bool WDMAudio::WDMAudioSetup() +{ + if (NULL == g_pBasicLog) + { + if (!(VERIFY_SUCCEEDED(CreateWexBasicLog(&g_pBasicLog)))) + { + return false; + } + } + + return true; +} + +bool WDMAudio::WDMAudioCleanup() +{ + if (g_pBasicLog) + { + g_pBasicLog->Release(); + } + + return true; +} + +// ------------------------------------------------------------------------------- +bool WDMAudio::WaveTest::WaveTestSetup() +{ + g_pWaveTest = this; + + return true; +} + +bool WDMAudio::WaveTest::WaveTestCleanUp() +{ + g_pWaveTest = NULL; + + return true; +} + +// ------------------------------------------------------------------------------- +bool WDMAudio::WaveTest::TestCaseSetup() +{ + CComPtr<ITestResource> spResource; + CComQIPtr<IHalfAppContainer> spHalfContainer; + + SetVerifyOutput verifySettings(VerifyOutputSettings::LogOnlyFailures); + + Log::Comment(L""); + Log::Comment(L"------------------------------------------------------"); + Log::Comment(L"Running test case setup"); + + size_t count = Resources::Count(); + if (!VERIFY_ARE_EQUAL(count, (size_t)1)) { return false; } + if (!VERIFY_SUCCEEDED(Resources::Item(0, &spResource))) { return false; } + + // 1. Assign m_pHalf + spHalfContainer = spResource; + if (!VERIFY_IS_NOT_NULL(spHalfContainer)) { return false; } + if (!VERIFY_SUCCEEDED(spHalfContainer->GetHalfApp(&m_pHalf))) { return false; } + + return true; +} + +bool WDMAudio::WaveTest::TestCaseCleanUp() +{ + if (!CompareWaveFormat(m_pHalf->m_pCurrentFormat.get(), m_pHalf->m_pPreferredFormat.get())) { + CloneWaveFormat(m_pHalf->m_pPreferredFormat.get(), wil::out_param(m_pHalf->m_pCurrentFormat)); + m_pHalf->m_u32CurrentDefaultPeriodicityInFrames = m_pHalf->m_u32DefaultPeriodicityInFrames; + m_pHalf->m_u32CurrentFundamentalPeriodicityInFrames = m_pHalf->m_u32FundamentalPeriodicityInFrames; + m_pHalf->m_u32CurrentMinPeriodicityInFrames = m_pHalf->m_u32MinPeriodicityInFrames; + m_pHalf->m_u32CurrentMaxPeriodicityInFrames = m_pHalf->m_u32MaxPeriodicityInFrames; + } + + if (m_pHalf != NULL) { + if (!VERIFY_SUCCEEDED(m_pHalf->CleanupStream())) { return false; } + if (!VERIFY_SUCCEEDED(m_pHalf->ReleaseEndpoint())) { return false; } + if (!VERIFY_SUCCEEDED(m_pHalf->ReleaseSineToneDataBuffer())) { return false; } + + m_pHalf = NULL; + } + + return true; +} + +// ------------------------------------------------------------------------------- +void WDMAudio::WaveTest::TAEF_StreamStateControl() +{ + RUN_TEST_CASE(Test_StreamStateControl) +} + +void WDMAudio::WaveTest::TAEF_LoopbackStreamStateControl() +{ + RUN_TEST_CASE(Test_LoopbackStreamStateControl) +} + +void WDMAudio::WaveTest::TAEF_StreamMinBufferSize() +{ + RUN_TEST_CASE(Test_StreamMinBufferSize) +} + +void WDMAudio::WaveTest::TAEF_StreamMaxBufferSize() +{ + RUN_TEST_CASE(Test_StreamMaxBufferSize) +} + +void WDMAudio::WaveTest::TAEF_StreamDifferentFormat() +{ + RUN_TEST_CASE(Test_StreamDifferentFormat) + +} + +void WDMAudio::WaveTest::TAEF_LoopbackStreamDifferentFormat() +{ + RUN_TEST_CASE(Test_LoopbackStreamDifferentFormat) + +} + +void WDMAudio::WaveTest::TAEF_StreamMultipleModes() +{ + RUN_TEST_CASE(Test_StreamMultipleModes) +} + +void WDMAudio::WaveTest::TAEF_VerifyPinSupportsPullMode() +{ + RUN_TEST_CASE(Test_VerifyPinSupportsPullMode) +}
\ No newline at end of file diff --git a/audio/tests/wavetest/WaveTestTaef.h b/audio/tests/wavetest/WaveTestTaef.h new file mode 100644 index 00000000..a8d38305 --- /dev/null +++ b/audio/tests/wavetest/WaveTestTaef.h @@ -0,0 +1,124 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// File Name: +// +// WaveTestTaef.h +// +// Abstract: +// +// Include file for WaveTestTaef +// +// ------------------------------------------------------------------------------- +#pragma once + +#include "HalfApp.h" + +extern IBasicLog* g_pBasicLog; + +// Define custom test resource properties +namespace WEX { + namespace TestExecution { + namespace TestResourceProperty + { + static const wchar_t c_szMode[] = L"Mode"; + static const wchar_t c_szPin[] = L"Pin"; + } + } +} + +namespace WDMAudio +{ + + class WaveTest + { + BEGIN_TEST_CLASS(WaveTest) + TEST_CLASS_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client x86") + TEST_CLASS_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client x64") + TEST_CLASS_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client ARM") + TEST_CLASS_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Client ARM64") + TEST_CLASS_PROPERTY(L"Kits.SupportedOS", L"Windows v10.0 Server x64") + TEST_CLASS_PROPERTY(L"Kits.MinRelease", L"19H1") + TEST_CLASS_PROPERTY(L"Kits.CorePackageComposition", L"Full") + TEST_CLASS_PROPERTY(L"Kits.IsInProc", L"True") + TEST_CLASS_PROPERTY(L"Kits.Parameter", L"DeviceID") + TEST_CLASS_PROPERTY(L"Kits.Parameter.DeviceID.Description", L"Device id of device under test") + TEST_CLASS_PROPERTY(L"Kits.PublishingOrganization", L"Microsoft Corporation") + TEST_CLASS_PROPERTY(L"Kits.TestType", L"Development") + TEST_CLASS_PROPERTY(L"Kits.DevelopmentPhase", L"Development and Integration") + TEST_CLASS_PROPERTY(L"Subfeature", L"Wave Driver Tests") + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"onecore\\external\\ddk\\inc\\drmk.h") + TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"onecoreuap\\external\\ddk\\lib\\$(build.arch)\\drmk.lib") + TEST_CLASS_PROPERTY(L"ArtifactUnderTest", L"onecoreuap\\internal\\drivers\\inc\\private\\wdm\\audio\\inf\\wdmaudio.inf") + END_TEST_CLASS() + + TEST_CLASS_SETUP(WaveTestSetup) + TEST_CLASS_CLEANUP(WaveTestCleanUp) + + TEST_METHOD_SETUP(TestCaseSetup) + TEST_METHOD_CLEANUP(TestCaseCleanUp) + + BEGIN_TEST_METHOD(TAEF_StreamStateControl) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*HOST*' OR @Id = '*OFFLOAD*'") + END_TEST_METHOD() + + BEGIN_TEST_METHOD(TAEF_LoopbackStreamStateControl) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*LOOPBACK*'") + END_TEST_METHOD() + + BEGIN_TEST_METHOD(TAEF_StreamMinBufferSize) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*HOST*' OR @Id = '*OFFLOAD*'") + END_TEST_METHOD() + + BEGIN_TEST_METHOD(TAEF_StreamMaxBufferSize) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*HOST*' OR @Id = '*OFFLOAD*'") + END_TEST_METHOD() + + BEGIN_TEST_METHOD(TAEF_StreamDifferentFormat) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*HOST*' OR @Id = '*OFFLOAD*'") + END_TEST_METHOD() + + BEGIN_TEST_METHOD(TAEF_LoopbackStreamDifferentFormat) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*LOOPBACK*'") + END_TEST_METHOD() + + BEGIN_TEST_METHOD(TAEF_StreamMultipleModes) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Id = '*RAW' OR @Id = '*DEFAULT'") + END_TEST_METHOD() + + BEGIN_TEST_METHOD(TAEF_VerifyPinSupportsPullMode) + TEST_METHOD_PROPERTY(L"HCKCategory", L"Functional") + TEST_METHOD_PROPERTY(L"HCKCategory", L"Certification") + TEST_METHOD_PROPERTY(L"TestClassification:Scope", L"Feature") + TEST_METHOD_PROPERTY(L"ResourceSelection", L"@Type = 'Render' OR @Type = 'Capture'") + END_TEST_METHOD() + + public: + CHalfApp* m_pHalf; + }; +} + +extern WDMAudio::WaveTest* g_pWaveTest; diff --git a/audio/tests/wavetest/comptest.cpp b/audio/tests/wavetest/comptest.cpp new file mode 100644 index 00000000..ef41972c --- /dev/null +++ b/audio/tests/wavetest/comptest.cpp @@ -0,0 +1,37 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// Module Name: +// +// comptest.cpp +// +// Abstract: +// +// Implementation file for test cases +// +// ------------------------------------------------------------------------------- + +#include "PreComp.h" +#include "WaveTestTaef.h" +#include "tests.h" + +// ------------------------------------------------------------------------------ +// Test_VerifyPinSupportsPullMode: Test the requirement that WaveRT drivers must support pull mode audio streaming technology. +void Test_VerifyPinSupportsPullMode(void) +{ + CHalfApp* pHalfApp = g_pWaveTest->m_pHalf; + BOOL bIsRTCapable = false; + BOOL bIsEventCapable = false; + + VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint()); + + VERIFY_SUCCEEDED(pHalfApp->m_pAudioDeviceEndpoint->GetRTCaps(&bIsRTCapable)); + + // Only require pull mode for WaveRT drivers + if (bIsRTCapable) + { + VERIFY_SUCCEEDED(pHalfApp->m_pAudioDeviceEndpoint->GetEventDrivenCapable(&bIsEventCapable)); + VERIFY_IS_TRUE(bIsEventCapable); + } +}
\ No newline at end of file diff --git a/audio/tests/wavetest/pintest.cpp b/audio/tests/wavetest/pintest.cpp new file mode 100644 index 00000000..a8b356c9 --- /dev/null +++ b/audio/tests/wavetest/pintest.cpp @@ -0,0 +1,492 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// Module Name: +// +// pintest.cpp +// +// Abstract: +// +// Implementation file for test cases +// +// ------------------------------------------------------------------------------- + +#include "PreComp.h" +#include "WaveTestTaef.h" +#include "tests.h" + +#define DEFAULT_PERIODICITY 0 +#define DEFAULT_LATENCY_COEFFICIENT 0 + +static const struct +{ + GUID mode; + LPWSTR name; +}knownModes[] = +{ + { GUID_NULL, L"NO_MODE" }, +{ AUDIO_SIGNALPROCESSINGMODE_RAW, L"RAW" }, +{ AUDIO_SIGNALPROCESSINGMODE_DEFAULT, L"DEFAULT" }, +{ AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, L"COMMUNICATIONS" }, +{ AUDIO_SIGNALPROCESSINGMODE_SPEECH, L"SPEECH" }, +{ AUDIO_SIGNALPROCESSINGMODE_MEDIA, L"MEDIA" }, +{ AUDIO_SIGNALPROCESSINGMODE_MOVIE, L"MOVIE" }, +{ AUDIO_SIGNALPROCESSINGMODE_NOTIFICATION, L"NOTIFICATION" }, +}; + + +LPWSTR ModeName(REFGUID guidMode) +{ + for (auto m : knownModes) + { + if (m.mode == guidMode) { return m.name; } + } + + return L"UNKNOWN"; +} + +void LogWaveFormat(WAVEFORMATEX* pwfx) +{ + WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)pwfx; + + switch (pwfx->wFormatTag) + { + case WAVE_FORMAT_PCM: + LOG(g_pBasicLog, L" wFormatTag = WAVE_FORMAT_PCM"); + break; + case WAVE_FORMAT_IEEE_FLOAT: + LOG(g_pBasicLog, L" wFormatTag = WAVE_FORMAT_IEEE_FLOAT"); + break; + case WAVE_FORMAT_EXTENSIBLE: + LOG(g_pBasicLog, L" wFormatTag = WAVE_FORMAT_EXTENSIBLE"); + if (wfex->SubFormat.Data1 == WAVE_FORMAT_PCM) + LOG(g_pBasicLog, L" SubFormat = WAVE_FORMAT_PCM"); + if (wfex->SubFormat.Data1 == WAVE_FORMAT_IEEE_FLOAT) + LOG(g_pBasicLog, L" SubFormat = WAVE_FORMAT_IEEE_FLOAT"); + break; + default: + LOG(g_pBasicLog, L" wFormatTag = UNKNOWN!"); + } + LOG(g_pBasicLog, L" nChannel = %d", pwfx->nChannels); + LOG(g_pBasicLog, L" nSamplesPerSec = %d", pwfx->nSamplesPerSec); + LOG(g_pBasicLog, L" nAvgBytesPerSe = %d", pwfx->nAvgBytesPerSec); + LOG(g_pBasicLog, L" nBlockAlign = %d", pwfx->nBlockAlign); + LOG(g_pBasicLog, L" wBitsPerSample = %d", pwfx->wBitsPerSample); + + + if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + LOG(g_pBasicLog, L" wValidBitsPerSample = %d", wfex->Samples.wValidBitsPerSample); + LOG(g_pBasicLog, L" dwChannelMask = %hd", wfex->dwChannelMask); + } +} + +// ------------------------------------------------------------------------------ +// Test_StreamStateControl: Test the stream state contorl of an endpoint. In RUN state pin position should be moving, +// in PAUSE state pin position should be same all time, in STOP state pin position should be zero. +void Test_StreamStateControl(void) +{ + CHalfApp* pHalfApp = g_pWaveTest->m_pHalf; + UINT32 u32Index = 0; + UINT64 u64PreviousPosition; + UINT64 u64Position; + UINT64 u64CorrelatedSystemTime; + + // Log wave format + LOG(g_pBasicLog, L"Test case will be run on the following format:"); + LogWaveFormat(pHalfApp->m_pCurrentFormat.get()); + + VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pHalfApp->CreateSineToneDataBuffer(pHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + + // Stream start state + VERIFY_SUCCEEDED(pHalfApp->StartStream()); + Sleep(100); + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64PreviousPosition, &u64CorrelatedSystemTime)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position != u64PreviousPosition); + u64PreviousPosition = u64Position; + } + + // Stream stop state + // IAudioEndpointControl::Stop set pin to PAUSE state + VERIFY_SUCCEEDED(pHalfApp->StopEndpoint()); + Sleep(100); + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64PreviousPosition, &u64CorrelatedSystemTime)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position == u64PreviousPosition); + u64PreviousPosition = u64Position; + } + + // Stream reset state + // IAudioEndpointControl::Reset set pin to STOP state + VERIFY_SUCCEEDED(pHalfApp->ResetEndpoint()); + Sleep(100); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position == 0); + } + + VERIFY_SUCCEEDED(pHalfApp->StartEndpoint()); + Sleep(100); + + VERIFY_SUCCEEDED(pHalfApp->StopStream()); +} + +// ------------------------------------------------------------------------------ +// Test_StreamMinBufferSize: Test the stream with minimum processing time (buffer size). +void Test_StreamMinBufferSize(void) +{ + CHalfApp* pHalfApp = g_pWaveTest->m_pHalf; + + // Set buffer with mininum periodicity + Test_StreamBufferSize(FRAMES_TO_HNSTIME_DOUBLE(pHalfApp->m_u32CurrentMinPeriodicityInFrames, pHalfApp->m_pCurrentFormat->nSamplesPerSec)); +} + +// ------------------------------------------------------------------------------ +// Test_StreamMaxBufferSize: Test the stream with maximum processing time (buffer size). +void Test_StreamMaxBufferSize(void) +{ + CHalfApp* pHalfApp = g_pWaveTest->m_pHalf; + + // Set buffer with maximum periodicity + Test_StreamBufferSize(FRAMES_TO_HNSTIME_DOUBLE(pHalfApp->m_u32CurrentMaxPeriodicityInFrames, pHalfApp->m_pCurrentFormat->nSamplesPerSec)); +} + +// ------------------------------------------------------------------------------ +// Test_StreamBufferSize: Test the stream with requested processing time (buffer size). +void Test_StreamBufferSize(HNSTIME requestedPeriodicity) +{ + CHalfApp* pHalfApp = g_pWaveTest->m_pHalf; + UINT32 u32Index = 0; + UINT64 u64PreviousPosition; + UINT64 u64Position; + UINT64 u64CorrelatedSystemTime; + + // Log wave format + LOG(g_pBasicLog, L"Test case will be run on the following format:"); + LogWaveFormat(pHalfApp->m_pCurrentFormat.get()); + + VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pHalfApp->CreateSineToneDataBuffer(pHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pHalfApp->InitializeStream(requestedPeriodicity, DEFAULT_LATENCY_COEFFICIENT)); + VERIFY_SUCCEEDED(pHalfApp->StartStream()); + + Sleep(100); + + // Check pin position + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64PreviousPosition, &u64CorrelatedSystemTime)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position != u64PreviousPosition); + u64PreviousPosition = u64Position; + } + + VERIFY_SUCCEEDED(pHalfApp->StopStream()); +} + +// ------------------------------------------------------------------------------ +// Test_StreamDifferentFormat: Test the stream with all supported formats. +void Test_StreamDifferentFormat(void) +{ + CHalfApp* pHalfApp = g_pWaveTest->m_pHalf; + UINT32 u32FormatIndex = 0; + UINT32 u32Index = 0; + UINT64 u64PreviousPosition; + UINT64 u64Position; + UINT64 u64CorrelatedSystemTime; + + // Loop through supported formats and stream with different format + for (;u32FormatIndex < pHalfApp->m_cFormatRecords; u32FormatIndex++) { + + // Change the current format + CloneWaveFormat((WAVEFORMATEX *)&pHalfApp->m_pFormatRecords[u32FormatIndex].wfxEx, wil::out_param(pHalfApp->m_pCurrentFormat)); + pHalfApp->m_u32CurrentDefaultPeriodicityInFrames = pHalfApp->m_pFormatRecords[u32FormatIndex].defaultPeriodInFrames; + pHalfApp->m_u32CurrentFundamentalPeriodicityInFrames = pHalfApp->m_pFormatRecords[u32FormatIndex].fundamentalPeriodInFrames; + pHalfApp->m_u32CurrentMinPeriodicityInFrames = pHalfApp->m_pFormatRecords[u32FormatIndex].minPeriodInFrames; + pHalfApp->m_u32CurrentMaxPeriodicityInFrames = pHalfApp->m_pFormatRecords[u32FormatIndex].maxPeriodInFrames; + + // Log the current format + LOG(g_pBasicLog, L"Current format:"); + LogWaveFormat(pHalfApp->m_pCurrentFormat.get()); + + // Initialize endpoints and start stream with current format + VERIFY_SUCCEEDED(pHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pHalfApp->CreateSineToneDataBuffer(pHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + VERIFY_SUCCEEDED(pHalfApp->StartStream()); + + Sleep(100); + + // Check pin position + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64PreviousPosition, &u64CorrelatedSystemTime)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position != u64PreviousPosition); + u64PreviousPosition = u64Position; + } + + // Make sure to stop stearm and clean up stream, endpoints and data buffer before change to next format + VERIFY_SUCCEEDED(pHalfApp->StopStream()); + VERIFY_SUCCEEDED(pHalfApp->CleanupStream()); + VERIFY_SUCCEEDED(pHalfApp->ReleaseEndpoint()); + VERIFY_SUCCEEDED(pHalfApp->ReleaseSineToneDataBuffer()); + } +} + +// ------------------------------------------------------------------------------ +// Test_StreamMultipleModes: Create 2 pin instances in different mode (if supported) and test streaming. +void Test_StreamMultipleModes(void) +{ + CHalfApp* pMainHalfApp = g_pWaveTest->m_pHalf; + UINT32 u32PinInstanceCount = 0; + AUDIO_SIGNALPROCESSINGMODE secondMode; + CHalfApp* pSecondHalfApp; + UINT32 u32Index = 0; + UINT64 u64PreviousPosition1; + UINT64 u64PreviousPosition2; + UINT64 u64Position1; + UINT64 u64Position2; + UINT64 u64CorrelatedSystemTime1; + UINT64 u64CorrelatedSystemTime2; + + // Check processing mode count + if (pMainHalfApp->m_cModes < 2) { + SKIP(g_pBasicLog, L"SKIP: Current pin does not support multiple modes. Skipping multiple modes test. "); + return; + } + // Check pin instance count, if less that 2, then multiple pin streaming is not supported + VERIFY_SUCCEEDED(pMainHalfApp->GetCurrentAvailiablePinInstanceCount(&u32PinInstanceCount)); + if (u32PinInstanceCount < 2) { + SKIP(g_pBasicLog, L"SKIP: Current availiable pin instance count is less than 2. Skipping multiple modes test. "); + return; + } + + // Loop through each mode, create second half app, and start stream + for (ULONG i = 0; i < pMainHalfApp->m_cModes; i++) { + secondMode = pMainHalfApp->m_pModes[i]; + if (IsEqualGUID(pMainHalfApp->m_Mode, secondMode)) { + continue; + } + + VERIFY_SUCCEEDED(pMainHalfApp->GetSecondHalfApp(secondMode, &pSecondHalfApp)); + + // Log both modes and formats + LOG(g_pBasicLog, L"First stream is in %s mode", ModeName(pMainHalfApp->m_Mode)); + LOG(g_pBasicLog, L"First stream will be run on the following format:"); + LogWaveFormat(pMainHalfApp->m_pCurrentFormat.get()); + LOG(g_pBasicLog, L"Second stream is in %s mode", ModeName(pSecondHalfApp->m_Mode)); + LOG(g_pBasicLog, L"Second stream will be run on the following format:"); + LogWaveFormat(pSecondHalfApp->m_pCurrentFormat.get()); + + // Initialize and start first stream + VERIFY_SUCCEEDED(pMainHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pMainHalfApp->CreateSineToneDataBuffer(pMainHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pMainHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + VERIFY_SUCCEEDED(pMainHalfApp->StartStream()); + + Sleep(100); + + // Initialize and start second stream + VERIFY_SUCCEEDED(pSecondHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pSecondHalfApp->CreateSineToneDataBuffer(pSecondHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pSecondHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + VERIFY_SUCCEEDED(pSecondHalfApp->StartStream()); + + Sleep(100); + + // Check position for two streams + VERIFY_SUCCEEDED(pMainHalfApp->GetPosition(&u64PreviousPosition1, &u64CorrelatedSystemTime1)); + VERIFY_SUCCEEDED(pSecondHalfApp->GetPosition(&u64PreviousPosition2, &u64CorrelatedSystemTime2)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pMainHalfApp->GetPosition(&u64Position1, &u64CorrelatedSystemTime1)); + VERIFY_SUCCEEDED(pSecondHalfApp->GetPosition(&u64Position2, &u64CorrelatedSystemTime2)); + VERIFY_IS_TRUE(u64Position1 != u64PreviousPosition1); + VERIFY_IS_TRUE(u64Position2 != u64PreviousPosition2); + u64PreviousPosition1 = u64Position1; + u64PreviousPosition2 = u64Position2; + } + + // Stop and cleanup first stream + VERIFY_SUCCEEDED(pMainHalfApp->StopStream()); + VERIFY_SUCCEEDED(pMainHalfApp->CleanupStream()); + VERIFY_SUCCEEDED(pMainHalfApp->ReleaseEndpoint()); + VERIFY_SUCCEEDED(pMainHalfApp->ReleaseSineToneDataBuffer()); + + // Stop and cleanup second stream + VERIFY_SUCCEEDED(pSecondHalfApp->StopStream()); + VERIFY_SUCCEEDED(pSecondHalfApp->CleanupStream()); + VERIFY_SUCCEEDED(pSecondHalfApp->ReleaseEndpoint()); + VERIFY_SUCCEEDED(pSecondHalfApp->ReleaseSineToneDataBuffer()); + delete pSecondHalfApp; + } +} + +// ------------------------------------------------------------------------------ +// Test_LoopbackStreamStateControl: Test the stream state contorl of an loopback endpoint. In RUN state pin position should +// be moving, in PAUSE state pin position should be same all time, in STOP state pin position should be zero. +void Test_LoopbackStreamStateControl(void) +{ + CHalfApp* pLoopbackHalfApp = g_pWaveTest->m_pHalf; + CHalfApp* pHostHalfApp; + UINT32 u32Index = 0; + UINT64 u64PreviousPosition; + UINT64 u64Position; + UINT64 u64CorrelatedSystemTime; + + // Get the corresponding host half app. + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetHostHalfApp(&pHostHalfApp)); + + // Match loopback stream format with host stream format + CloneWaveFormat(pHostHalfApp->m_pCurrentFormat.get(), wil::out_param(pLoopbackHalfApp->m_pCurrentFormat)); + pLoopbackHalfApp->m_u32CurrentDefaultPeriodicityInFrames = pHostHalfApp->m_u32CurrentDefaultPeriodicityInFrames; + pLoopbackHalfApp->m_u32CurrentFundamentalPeriodicityInFrames = pHostHalfApp->m_u32CurrentFundamentalPeriodicityInFrames; + pLoopbackHalfApp->m_u32CurrentMinPeriodicityInFrames = pHostHalfApp->m_u32CurrentMinPeriodicityInFrames; + pLoopbackHalfApp->m_u32CurrentMaxPeriodicityInFrames = pHostHalfApp->m_u32CurrentMaxPeriodicityInFrames; + + // Log wave format + LOG(g_pBasicLog, L"Test case will be run on the following format:"); + LogWaveFormat(pLoopbackHalfApp->m_pCurrentFormat.get()); + + // Initialize and start host stream + VERIFY_SUCCEEDED(pHostHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pHostHalfApp->CreateSineToneDataBuffer(pHostHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pHostHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + VERIFY_SUCCEEDED(pHostHalfApp->StartStream()); + + // Initialize and start loopback stream + VERIFY_SUCCEEDED(pLoopbackHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pLoopbackHalfApp->CreateSineToneDataBuffer(pLoopbackHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pLoopbackHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + + // Stream start state + VERIFY_SUCCEEDED(pLoopbackHalfApp->StartStream()); + Sleep(100); + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetPosition(&u64PreviousPosition, &u64CorrelatedSystemTime)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position != u64PreviousPosition); + u64PreviousPosition = u64Position; + } + + // Stream stop state + // IAudioEndpointControl::Stop set pin to PAUSE state + VERIFY_SUCCEEDED(pLoopbackHalfApp->StopEndpoint()); + Sleep(100); + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetPosition(&u64PreviousPosition, &u64CorrelatedSystemTime)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position == u64PreviousPosition); + u64PreviousPosition = u64Position; + } + + // Stream reset state + // IAudioEndpointControl::Reset set pin to STOP state + VERIFY_SUCCEEDED(pLoopbackHalfApp->ResetEndpoint()); + Sleep(100); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position == 0); + } + + VERIFY_SUCCEEDED(pLoopbackHalfApp->StartEndpoint()); + Sleep(100); + + VERIFY_SUCCEEDED(pLoopbackHalfApp->StopStream()); + + // Stop and cleanup host stream + VERIFY_SUCCEEDED(pHostHalfApp->StopStream()); + VERIFY_SUCCEEDED(pHostHalfApp->CleanupStream()); + VERIFY_SUCCEEDED(pHostHalfApp->ReleaseEndpoint()); + VERIFY_SUCCEEDED(pHostHalfApp->ReleaseSineToneDataBuffer()); + + delete pHostHalfApp; +} + +// ------------------------------------------------------------------------------ +// Test_LoopbackStreamDifferentFormat: Test the loopback stream with all formats supported by host pin. +void Test_LoopbackStreamDifferentFormat(void) +{ + CHalfApp* pLoopbackHalfApp = g_pWaveTest->m_pHalf; + CHalfApp* pHostHalfApp; + UINT32 u32FormatIndex = 0; + UINT32 u32Index = 0; + UINT64 u64PreviousPosition; + UINT64 u64Position; + UINT64 u64CorrelatedSystemTime; + + // Get the corresponding host half app. + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetHostHalfApp(&pHostHalfApp)); + + // Loop through supported formats and stream with different format + for (;u32FormatIndex < pHostHalfApp->m_cFormatRecords; u32FormatIndex++) { + + // Change the current format + CloneWaveFormat((WAVEFORMATEX *)&pHostHalfApp->m_pFormatRecords[u32FormatIndex].wfxEx, wil::out_param(pHostHalfApp->m_pCurrentFormat)); + pHostHalfApp->m_u32CurrentDefaultPeriodicityInFrames = pHostHalfApp->m_pFormatRecords[u32FormatIndex].defaultPeriodInFrames; + pHostHalfApp->m_u32CurrentFundamentalPeriodicityInFrames = pHostHalfApp->m_pFormatRecords[u32FormatIndex].fundamentalPeriodInFrames; + pHostHalfApp->m_u32CurrentMinPeriodicityInFrames = pHostHalfApp->m_pFormatRecords[u32FormatIndex].minPeriodInFrames; + pHostHalfApp->m_u32CurrentMaxPeriodicityInFrames = pHostHalfApp->m_pFormatRecords[u32FormatIndex].maxPeriodInFrames; + + // Match loopback stream format with host stream format + CloneWaveFormat(pHostHalfApp->m_pCurrentFormat.get(), wil::out_param(pLoopbackHalfApp->m_pCurrentFormat)); + pLoopbackHalfApp->m_u32CurrentDefaultPeriodicityInFrames = pHostHalfApp->m_u32CurrentDefaultPeriodicityInFrames; + pLoopbackHalfApp->m_u32CurrentFundamentalPeriodicityInFrames = pHostHalfApp->m_u32CurrentFundamentalPeriodicityInFrames; + pLoopbackHalfApp->m_u32CurrentMinPeriodicityInFrames = pHostHalfApp->m_u32CurrentMinPeriodicityInFrames; + pLoopbackHalfApp->m_u32CurrentMaxPeriodicityInFrames = pHostHalfApp->m_u32CurrentMaxPeriodicityInFrames; + + // Log the current format + LOG(g_pBasicLog, L"Current format:"); + LogWaveFormat(pLoopbackHalfApp->m_pCurrentFormat.get()); + + // Initialize and start host stream + VERIFY_SUCCEEDED(pHostHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pHostHalfApp->CreateSineToneDataBuffer(pHostHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pHostHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + VERIFY_SUCCEEDED(pHostHalfApp->StartStream()); + + // Initialize and start loopback stream + VERIFY_SUCCEEDED(pLoopbackHalfApp->InitializeEndpoint()); + VERIFY_SUCCEEDED(pLoopbackHalfApp->CreateSineToneDataBuffer(pLoopbackHalfApp->m_pCurrentFormat.get())); + VERIFY_SUCCEEDED(pLoopbackHalfApp->InitializeStream(DEFAULT_PERIODICITY, DEFAULT_LATENCY_COEFFICIENT)); + VERIFY_SUCCEEDED(pLoopbackHalfApp->StartStream()); + + Sleep(100); + + // Check pin position + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetPosition(&u64PreviousPosition, &u64CorrelatedSystemTime)); + for (u32Index = 0; u32Index < 10; u32Index++) { + Sleep(50); + VERIFY_SUCCEEDED(pLoopbackHalfApp->GetPosition(&u64Position, &u64CorrelatedSystemTime)); + VERIFY_IS_TRUE(u64Position != u64PreviousPosition); + u64PreviousPosition = u64Position; + } + + // Make sure to stop and clean up loopback stream, endpoints and data buffer before change to next format + VERIFY_SUCCEEDED(pLoopbackHalfApp->StopStream()); + VERIFY_SUCCEEDED(pLoopbackHalfApp->CleanupStream()); + VERIFY_SUCCEEDED(pLoopbackHalfApp->ReleaseEndpoint()); + VERIFY_SUCCEEDED(pLoopbackHalfApp->ReleaseSineToneDataBuffer()); + + // Stop and cleanup host stream + VERIFY_SUCCEEDED(pHostHalfApp->StopStream()); + VERIFY_SUCCEEDED(pHostHalfApp->CleanupStream()); + VERIFY_SUCCEEDED(pHostHalfApp->ReleaseEndpoint()); + VERIFY_SUCCEEDED(pHostHalfApp->ReleaseSineToneDataBuffer()); + } + + delete pHostHalfApp; +}
\ No newline at end of file diff --git a/audio/tests/wavetest/tests.h b/audio/tests/wavetest/tests.h new file mode 100644 index 00000000..38a6aaa1 --- /dev/null +++ b/audio/tests/wavetest/tests.h @@ -0,0 +1,27 @@ +// ------------------------------------------------------------------------------ +// +// Copyright (C) Microsoft. All rights reserved. +// +// Module Name: +// +// tests.h +// +// Abstract: +// +// Header for testcases +// +// ------------------------------------------------------------------------------- +#pragma once + +// Stream test +void Test_StreamStateControl(void); +void Test_LoopbackStreamStateControl(void); +void Test_StreamMinBufferSize(void); +void Test_StreamMaxBufferSize(void); +void Test_StreamBufferSize(HNSTIME requestedPeriodicity); +void Test_StreamDifferentFormat(void); +void Test_LoopbackStreamDifferentFormat(void); +void Test_StreamMultipleModes(void); + +// Compliance test +void Test_VerifyPinSupportsPullMode(void);
\ No newline at end of file |
