summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGirish Pattabiraman <[email protected]>2017-05-03 15:02:49 -0700
committerGirish Pattabiraman <[email protected]>2017-05-03 17:20:15 -0700
commitb9027f2b8124f5853dac4355ff4d9e85379e0e56 (patch)
tree33487ba551e9e53ba5a000afc2ad8860892ef2fa
parent32dc5459e78107ce48412eef3653370f32274561 (diff)
Audio Modules Example
Delay APO Package Project Stream Position Bug Fix SAL
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModule0.h297
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModule1.h312
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModule2.h296
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp644
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModuleHelper.h95
-rw-r--r--audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj1
-rw-r--r--audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters62
-rw-r--r--audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp1
-rw-r--r--audio/sysvad/EndpointsCommon/minwavert.cpp427
-rw-r--r--audio/sysvad/EndpointsCommon/minwavert.h86
-rw-r--r--audio/sysvad/EndpointsCommon/minwavertstream.cpp75
-rw-r--r--audio/sysvad/EndpointsCommon/minwavertstream.h37
-rw-r--r--audio/sysvad/EndpointsCommon/sources46
-rw-r--r--audio/sysvad/EndpointsCommon/speakerhpwavtable.h127
-rw-r--r--audio/sysvad/EndpointsCommon/speakerwavtable.h126
-rw-r--r--audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj16
-rw-r--r--audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj.Filters39
-rw-r--r--audio/sysvad/KeywordDetectorAdapter/sources53
-rw-r--r--audio/sysvad/Package/package.VcxProj99
-rw-r--r--audio/sysvad/Package/package.VcxProj.Filters21
-rw-r--r--audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters73
-rw-r--r--audio/sysvad/PhoneAudioSample/minipairs.h29
-rw-r--r--audio/sysvad/PhoneAudioSample/sources58
-rw-r--r--audio/sysvad/SwapAPO/APO/SwapAPO.h37
-rw-r--r--audio/sysvad/SwapAPO/APO/SwapAPO.vcxproj.Filters45
-rw-r--r--audio/sysvad/SwapAPO/APO/makefile36
-rw-r--r--audio/sysvad/SwapAPO/APO/sources13
-rw-r--r--audio/sysvad/SwapAPO/APO/swap.cpp69
-rw-r--r--audio/sysvad/SwapAPO/APO/swapapomfx.cpp75
-rw-r--r--audio/sysvad/SwapAPO/APO/swapaposfx.cpp74
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/Delay.cpp112
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPO.h294
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPO.vcxproj250
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.cpp148
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.def6
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.idl54
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rc24
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rgs11
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPOInterface.idl29
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.cpp1031
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.rgs13
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.cpp662
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.rgs13
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/Resource.h20
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/delayapo.pngbin0 -> 1180 bytes
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/makefile34
-rw-r--r--audio/sysvad/SwapAPO/DelayAPO/sources12
-rw-r--r--audio/sysvad/SwapAPO/PropPageExtensions/PropPageExt.vcxproj.Filters51
-rw-r--r--audio/sysvad/SwapAPO/PropPageExtensions/makefile36
-rw-r--r--audio/sysvad/SwapAPO/PropPageExtensions/sources60
-rw-r--r--audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters58
-rw-r--r--audio/sysvad/TabletAudioSample/minipairs.h28
-rw-r--r--audio/sysvad/TabletAudioSample/sources53
-rw-r--r--audio/sysvad/TabletAudioSample/tabletaudiosample.infbin58098 -> 65586 bytes
-rw-r--r--audio/sysvad/common.h125
-rw-r--r--audio/sysvad/sources.inc34
-rw-r--r--audio/sysvad/sysvad.h14
-rw-r--r--audio/sysvad/sysvad.sln56
58 files changed, 6310 insertions, 287 deletions
diff --git a/audio/sysvad/EndpointsCommon/AudioModule0.h b/audio/sysvad/EndpointsCommon/AudioModule0.h
new file mode 100644
index 00000000..c1f07557
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModule0.h
@@ -0,0 +1,297 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModule0.h
+
+Abstract:
+
+ Declaration of Audio Module 0 (system module).
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULE0_H_
+#define _SYSVAD_AUDIOMODULE0_H_
+
+#include "AudioModuleHelper.h"
+
+#define AUDIOMODULE0_MAJOR 0x1
+#define AUDIOMODULE0_MINOR 0X0
+
+static const GUID AudioModule0Id =
+{ 0xe24c8b6f, 0xede7, 0x4255, 0x8b, 0x39, 0x77, 0x97, 0x60, 0x15, 0xd5, 0x93 };
+
+enum AudioModule0_Parameter {
+ AudioModule0Parameter1 = 0,
+ AudioModule0Parameter2
+};
+
+typedef struct _AUDIOMODULE0_CUSTOM_COMMAND {
+ ULONG Verb; // get, set and support
+ AudioModule0_Parameter ParameterId;
+} AUDIOMODULE0_CUSTOM_COMMAND, *PAUDIOMODULE0_CUSTOM_COMMAND;
+
+enum AudioModule0_Notification_Type {
+ AudioModule0ParameterChanged = 0,
+};
+
+typedef struct _AUDIOMODULE0_CUSTOM_NOTIFICATION {
+ ULONG Type;
+ union {
+ struct {
+ ULONG ParameterId;
+ } ParameterChanged;
+ };
+} AUDIOMODULE0_CUSTOM_NOTIFICATION, *PAUDIOMODULE0_CUSTOM_NOTIFICATION;
+
+typedef struct _AUDIOMODULE0_NOTIFICATION {
+ KSAUDIOMODULE_NOTIFICATION Header;
+ AUDIOMODULE0_CUSTOM_NOTIFICATION CustomNotification;
+} AUDIOMODULE0_NOTIFICATION, *PAUDIOMODULE0_NOTIFICATION;
+
+typedef struct _AUDIOMODULE0_CONTEXT {
+ ULONG Parameter1;
+ BYTE Parameter2;
+ ULONG InstanceId;
+ AUDIOMODULE0_NOTIFICATION Notification;
+ PPORTCLSNOTIFICATIONS PortNotifications;
+} AUDIOMODULE0_CONTEXT, *PAUDIOMODULE0_CONTEXT;
+
+static
+ULONG AudioModule0_ValidParameter1List[] =
+{
+ 1, 2, 5
+};
+
+static
+AUDIOMODULE_PARAMETER_INFO AudioModule0_ParameterInfo[] =
+{
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE0_CONTEXT, Parameter1),
+ VT_UI4,
+ AudioModule0_ValidParameter1List,
+ SIZEOF_ARRAY(AudioModule0_ValidParameter1List)
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ 0,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE0_CONTEXT, Parameter2),
+ VT_UI1,
+ NULL,
+ 0
+ },
+};
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule0_InitClass(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader,
+ _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications
+ )
+{
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(Size != 0);
+ RtlZeroMemory(Context, Size);
+
+ ctx->Notification.Header = *NotificationHeader;
+ ctx->PortNotifications = PortNotifications;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule0_InitInstance(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _In_opt_ PVOID TemplateContext,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ ULONG InstanceId
+ )
+{
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(TemplateContext != NULL);
+ ASSERT(Size != 0);
+
+ RtlCopyMemory(Context, TemplateContext, Size);
+
+ ctx->InstanceId = InstanceId;
+ ctx->Notification.Header.ProviderId.InstanceId = InstanceId;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+VOID
+AudioModule0_Cleanup(
+ _In_ PVOID Context
+ )
+{
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return;
+ }
+
+ SAFE_RELEASE(ctx->PortNotifications);
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule0_Handler(
+ _Inout_opt_ PVOID Context,
+ _In_reads_bytes_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOL fNewValue = FALSE;
+ PVOID currentValue;
+ PVOID inBuffer = NULL;
+ ULONG inBufferCb = 0;
+
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+ AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL;
+ AUDIOMODULE0_CUSTOM_COMMAND * command = NULL;
+
+ PAGED_CODE();
+
+ if (ctx == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ status = STATUS_INTERNAL_ERROR;
+ goto exit;
+ }
+
+ //
+ // Basic parameter validation (module specific).
+ //
+ if (InBuffer == NULL || InBufferCb == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (InBufferCb < sizeof(AUDIOMODULE0_CUSTOM_COMMAND))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ command = (AUDIOMODULE0_CUSTOM_COMMAND*)InBuffer;
+
+ //
+ // Validate the parameter referenced in the command.
+ //
+ switch (command->ParameterId)
+ {
+ case AudioModule0Parameter1:
+ currentValue = &ctx->Parameter1;
+ parameterInfo = &AudioModule0_ParameterInfo[AudioModule0Parameter1];
+ break;
+
+ case AudioModule0Parameter2:
+ currentValue = &ctx->Parameter2;
+ parameterInfo = &AudioModule0_ParameterInfo[AudioModule0Parameter2];
+ break;
+
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Update input buffer ptr/size.
+ //
+ inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE0_CUSTOM_COMMAND));
+ inBufferCb = InBufferCb - sizeof(AUDIOMODULE0_CUSTOM_COMMAND);
+
+ if (inBufferCb == 0)
+ {
+ inBuffer = NULL;
+ }
+
+ status = AudioModule_GenericHandler(
+ command->Verb,
+ command->ParameterId,
+ parameterInfo,
+ currentValue,
+ inBuffer,
+ inBufferCb,
+ OutBuffer,
+ OutBufferCb,
+ &fNewValue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto exit;
+ }
+
+ if (fNewValue && ctx->PortNotifications &&
+ (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION))
+ {
+ // This logic assumes that access to this function is serialized.
+ ctx->Notification.CustomNotification.Type = AudioModule0ParameterChanged;
+ ctx->Notification.CustomNotification.ParameterChanged.ParameterId =
+ command->ParameterId;
+
+ AudioModule_SendNotification(ctx->PortNotifications,
+ (PVOID)&ctx->Notification,
+ (USHORT)sizeof(ctx->Notification));
+ }
+
+ // Normalize error code.
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+#endif // _SYSVAD_AUDIOMODULE0_H_
+
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModule1.h b/audio/sysvad/EndpointsCommon/AudioModule1.h
new file mode 100644
index 00000000..9f01eaed
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModule1.h
@@ -0,0 +1,312 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModule1.h
+
+Abstract:
+
+ Declaration of Audio Module 1.
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULE1_H_
+#define _SYSVAD_AUDIOMODULE1_H_
+
+#include "AudioModuleHelper.h"
+
+#define AUDIOMODULE1_MAJOR 0x2
+#define AUDIOMODULE1_MINOR 0X1
+
+static const GUID AudioModule1Id =
+{ 0x5ce55c8e, 0x84df, 0x4317, 0x98, 0xc7, 0x79, 0x2d, 0xe8, 0x33, 0x66, 0xcc };
+
+enum AudioModule1_Parameter {
+ AudioModule1Parameter1 = 0,
+ AudioModule1Parameter2,
+ AudioModule1Parameter3
+};
+
+typedef struct _AUDIOMODULE1_CUSTOM_COMMAND {
+ ULONG Verb; // get, set and support
+ AudioModule1_Parameter ParameterId;
+} AUDIOMODULE1_CUSTOM_COMMAND, *PAUDIOMODULE1_CUSTOM_COMMAND;
+
+enum AudioModule1_Notification_Type {
+ AudioModule1ParameterChanged = 0,
+};
+
+typedef struct _AUDIOMODULE1_CUSTOM_NOTIFICATION {
+ ULONG Type;
+ union {
+ struct {
+ ULONG ParameterId;
+ } ParameterChanged;
+ };
+} AUDIOMODULE1_CUSTOM_NOTIFICATION, *PAUDIOMODULE1_CUSTOM_NOTIFICATION;
+
+typedef struct _AUDIOMODULE1_NOTIFICATION {
+ KSAUDIOMODULE_NOTIFICATION Header;
+ AUDIOMODULE1_CUSTOM_NOTIFICATION CustomNotification;
+} AUDIOMODULE1_NOTIFICATION, *PAUDIOMODULE1_NOTIFICATION;
+
+typedef struct _AUDIOMODULE1_CONTEXT {
+ BYTE Parameter1;
+ ULONGLONG Parameter2;
+ DWORD Parameter3;
+ ULONG InstanceId;
+ AUDIOMODULE1_NOTIFICATION Notification;
+ PPORTCLSNOTIFICATIONS PortNotifications;
+} AUDIOMODULE1_CONTEXT, *PAUDIOMODULE1_CONTEXT;
+
+static
+BYTE AudioModule1_ValidParameter1List[] =
+{
+ 0, 1, 2
+};
+
+static
+AUDIOMODULE_PARAMETER_INFO AudioModule1_ParameterInfo[] =
+{
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter1),
+ VT_UI1,
+ AudioModule1_ValidParameter1List,
+ SIZEOF_ARRAY(AudioModule1_ValidParameter1List)
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ 0,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter2),
+ VT_UI8,
+ NULL,
+ 0
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter3),
+ VT_UI4,
+ NULL,
+ 0
+ },
+};
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule1_InitClass(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader,
+ _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications
+ )
+{
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(Size != 0);
+ RtlZeroMemory(Context, Size);
+
+ ctx->Notification.Header = *NotificationHeader;
+ ctx->PortNotifications = PortNotifications;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule1_InitInstance(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _In_opt_ PVOID TemplateContext,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ ULONG InstanceId
+ )
+{
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(TemplateContext != NULL);
+ ASSERT(Size != 0);
+
+ RtlCopyMemory(Context, TemplateContext, Size);
+
+ ctx->InstanceId = InstanceId;
+ ctx->Notification.Header.ProviderId.InstanceId = InstanceId;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+VOID
+AudioModule1_Cleanup(
+ _In_ PVOID Context
+ )
+{
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return;
+ }
+
+ SAFE_RELEASE(ctx->PortNotifications);
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule1_Handler(
+ _Inout_opt_ PVOID Context,
+ _In_reads_bytes_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOL fNewValue = FALSE;
+ PVOID currentValue;
+ PVOID inBuffer = NULL;
+ ULONG inBufferCb = 0;
+
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+ AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL;
+ AUDIOMODULE1_CUSTOM_COMMAND * command = NULL;
+
+ PAGED_CODE();
+
+ if (ctx == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ status = STATUS_INTERNAL_ERROR;
+ goto exit;
+ }
+
+ //
+ // Basic parameter validation (module specific).
+ //
+ if (InBuffer == NULL || InBufferCb == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (InBufferCb < sizeof(AUDIOMODULE1_CUSTOM_COMMAND))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ command = (AUDIOMODULE1_CUSTOM_COMMAND*)InBuffer;
+
+ //
+ // Validate the parameter referenced in the command.
+ //
+ switch (command->ParameterId)
+ {
+ case AudioModule1Parameter1:
+ currentValue = &ctx->Parameter1;
+ parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter1];
+ break;
+
+ case AudioModule1Parameter2:
+ currentValue = &ctx->Parameter2;
+ parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter2];
+ break;
+
+ case AudioModule1Parameter3:
+ currentValue = &ctx->Parameter3;
+ parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter3];
+ break;
+
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Update input buffer ptr/size.
+ //
+ inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE1_CUSTOM_COMMAND));
+ inBufferCb = InBufferCb - sizeof(AUDIOMODULE1_CUSTOM_COMMAND);
+
+ if (inBufferCb == 0)
+ {
+ inBuffer = NULL;
+ }
+
+ status = AudioModule_GenericHandler(
+ command->Verb,
+ command->ParameterId,
+ parameterInfo,
+ currentValue,
+ inBuffer,
+ inBufferCb,
+ OutBuffer,
+ OutBufferCb,
+ &fNewValue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto exit;
+ }
+
+ if (fNewValue && ctx->PortNotifications &&
+ (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION))
+ {
+ // This logic assumes that access to this function is serialized.
+ ctx->Notification.CustomNotification.Type = AudioModule1ParameterChanged;
+ ctx->Notification.CustomNotification.ParameterChanged.ParameterId =
+ command->ParameterId;
+
+ AudioModule_SendNotification(ctx->PortNotifications,
+ (PVOID)&ctx->Notification,
+ (USHORT)sizeof(ctx->Notification));
+ }
+
+ // Normalize error code.
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+#endif // _SYSVAD_AUDIOMODULE1_H_
+
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModule2.h b/audio/sysvad/EndpointsCommon/AudioModule2.h
new file mode 100644
index 00000000..93d3fdf3
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModule2.h
@@ -0,0 +1,296 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModule2.h
+
+Abstract:
+
+ Declaration of Audio Module 2.
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULE2_H_
+#define _SYSVAD_AUDIOMODULE2_H_
+
+#include "AudioModuleHelper.h"
+
+#define AUDIOMODULE2_MAJOR 0x2
+#define AUDIOMODULE2_MINOR 0X0
+
+static const GUID AudioModule2Id =
+{ 0xcc2a9527, 0x19d9, 0x4784, 0x8d, 0xd4, 0x6c, 0x1f, 0xe0, 0x1e, 0x37, 0x26 };
+
+enum AudioModule2_Parameter {
+ AudioModule2Parameter1 = 0,
+ AudioModule2Parameter2
+};
+
+typedef struct _AUDIOMODULE2_CUSTOM_COMMAND {
+ ULONG Verb; // get, set and support
+ AudioModule2_Parameter ParameterId;
+} AUDIOMODULE2_CUSTOM_COMMAND, *PAUDIOMODULE2_CUSTOM_COMMAND;
+
+enum AudioModule2_Notification_Type {
+ AudioModule2ParameterChanged = 0,
+};
+
+typedef struct _AUDIOMODULE2_CUSTOM_NOTIFICATION {
+ ULONG Type;
+ union {
+ struct {
+ ULONG ParameterId;
+ } ParameterChanged;
+ };
+} AUDIOMODULE2_CUSTOM_NOTIFICATION, *PAUDIOMODULE2_CUSTOM_NOTIFICATION;
+
+typedef struct _AUDIOMODULE2_NOTIFICATION {
+ KSAUDIOMODULE_NOTIFICATION Header;
+ AUDIOMODULE2_CUSTOM_NOTIFICATION CustomNotification;
+} AUDIOMODULE2_NOTIFICATION, *PAUDIOMODULE2_NOTIFICATION;
+
+typedef struct _AUDIOMODULE2_CONTEXT {
+ ULONG Parameter1;
+ USHORT Parameter2;
+ ULONG InstanceId;
+ AUDIOMODULE2_NOTIFICATION Notification;
+ PPORTCLSNOTIFICATIONS PortNotifications;
+} AUDIOMODULE2_CONTEXT, *PAUDIOMODULE2_CONTEXT;
+
+static
+ULONG AudioModule2_ValidParameter1List[] =
+{
+ 1, 0xfffffffe
+};
+
+static
+AUDIOMODULE_PARAMETER_INFO AudioModule2_ParameterInfo[] =
+{
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE2_CONTEXT, Parameter1),
+ VT_UI4,
+ AudioModule2_ValidParameter1List,
+ SIZEOF_ARRAY(AudioModule2_ValidParameter1List)
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ 0,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE2_CONTEXT, Parameter2),
+ VT_UI2,
+ NULL,
+ 0
+ },
+};
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule2_InitClass(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader,
+ _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications
+ )
+{
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(Size != 0);
+ RtlZeroMemory(Context, Size);
+
+ ctx->Notification.Header = *NotificationHeader;
+ ctx->PortNotifications = PortNotifications;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule2_InitInstance(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _In_opt_ PVOID TemplateContext,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ ULONG InstanceId
+ )
+{
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(TemplateContext != NULL);
+ ASSERT(Size != 0);
+
+ RtlCopyMemory(Context, TemplateContext, Size);
+
+ ctx->InstanceId = InstanceId;
+ ctx->Notification.Header.ProviderId.InstanceId = InstanceId;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+VOID
+AudioModule2_Cleanup(
+ _In_ PVOID Context
+ )
+{
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return;
+ }
+
+ SAFE_RELEASE(ctx->PortNotifications);
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule2_Handler(
+ _Inout_opt_ PVOID Context,
+ _In_reads_bytes_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOL fNewValue = FALSE;
+ PVOID currentValue;
+ PVOID inBuffer = NULL;
+ ULONG inBufferCb = 0;
+
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+ AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL;
+ AUDIOMODULE2_CUSTOM_COMMAND * command = NULL;
+
+ PAGED_CODE();
+
+ if (ctx == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ status = STATUS_INTERNAL_ERROR;
+ goto exit;
+ }
+
+ //
+ // Basic parameter validation (module specific).
+ //
+ if (InBuffer == NULL || InBufferCb == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (InBufferCb < sizeof(AUDIOMODULE2_CUSTOM_COMMAND))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ command = (AUDIOMODULE2_CUSTOM_COMMAND*)InBuffer;
+
+ //
+ // Validate the parameter referenced in the command.
+ //
+ switch (command->ParameterId)
+ {
+ case AudioModule2Parameter1:
+ currentValue = &ctx->Parameter1;
+ parameterInfo = &AudioModule2_ParameterInfo[AudioModule0Parameter1];
+ break;
+
+ case AudioModule2Parameter2:
+ currentValue = &ctx->Parameter2;
+ parameterInfo = &AudioModule2_ParameterInfo[AudioModule2Parameter2];
+ break;
+
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Update input buffer ptr/size.
+ //
+ inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE2_CUSTOM_COMMAND));
+ inBufferCb = InBufferCb - sizeof(AUDIOMODULE2_CUSTOM_COMMAND);
+
+ if (inBufferCb == 0)
+ {
+ inBuffer = NULL;
+ }
+
+ status = AudioModule_GenericHandler(
+ command->Verb,
+ command->ParameterId,
+ parameterInfo,
+ currentValue,
+ inBuffer,
+ inBufferCb,
+ OutBuffer,
+ OutBufferCb,
+ &fNewValue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto exit;
+ }
+
+ if (fNewValue && ctx->PortNotifications &&
+ (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION))
+ {
+ // This logic assumes that access to this function is serialized.
+ ctx->Notification.CustomNotification.Type = AudioModule2ParameterChanged;
+ ctx->Notification.CustomNotification.ParameterChanged.ParameterId =
+ command->ParameterId;
+
+ AudioModule_SendNotification(ctx->PortNotifications,
+ (PVOID)&ctx->Notification,
+ (USHORT)sizeof(ctx->Notification));
+ }
+
+ // Normalize error code.
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+#endif // _SYSVAD_AUDIOMODULE2_H_
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp b/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp
new file mode 100644
index 00000000..f93c2bff
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp
@@ -0,0 +1,644 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModuleHelper.cpp
+
+Abstract:
+
+ Simple helper for Audio Modules logic.
+
+--*/
+
+#pragma warning (disable : 4127)
+
+#include <sysvad.h>
+#include <limits.h>
+#include <ntintsafe.h>
+#include "SysVadShared.h"
+#include "AudioModuleHelper.h"
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_BasicSupport(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer,
+ _Inout_ ULONG * BufferCb
+ )
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ ULONG cbFullProperty = 0;
+ ULONG cbDataListSize = 0;
+
+ DPF_ENTER(("[AudioModule_GenericHandler_BasicSupport]"));
+
+ PAGED_CODE();
+
+ ASSERT(ParameterInfo);
+ ASSERT(BufferCb);
+
+ //
+ // Compute total size of property.
+ //
+ ntStatus = RtlULongMult(ParameterInfo->Size,
+ ParameterInfo->ValidSetCount,
+ &cbDataListSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ *BufferCb = 0;
+ return ntStatus;
+ }
+
+ ntStatus = RtlULongAdd(cbDataListSize,
+ (ULONG)(sizeof(KSPROPERTY_DESCRIPTION) +
+ sizeof(KSPROPERTY_MEMBERSHEADER)),
+ &cbFullProperty);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ *BufferCb = 0;
+ return ntStatus;
+ }
+
+ //
+ // Return the info the caller is asking for.
+ //
+ if (*BufferCb == 0)
+ {
+ // caller wants to know the size of the buffer.
+ *BufferCb = cbFullProperty;
+ ntStatus = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (*BufferCb >= (sizeof(KSPROPERTY_DESCRIPTION)))
+ {
+ PKSPROPERTY_DESCRIPTION propDesc = PKSPROPERTY_DESCRIPTION(Buffer);
+
+ propDesc->AccessFlags = ParameterInfo->AccessFlags;
+ propDesc->DescriptionSize = cbFullProperty;
+ propDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
+ propDesc->PropTypeSet.Id = ParameterInfo->VtType;
+ propDesc->PropTypeSet.Flags = 0;
+ propDesc->MembersListCount = 1;
+ propDesc->Reserved = 0;
+
+ // if return buffer can also hold a list description, return it too
+ if(*BufferCb >= cbFullProperty)
+ {
+ // fill in the members header
+ PKSPROPERTY_MEMBERSHEADER members =
+ PKSPROPERTY_MEMBERSHEADER(propDesc + 1);
+
+ members->MembersFlags = KSPROPERTY_MEMBER_VALUES;
+ members->MembersSize = ParameterInfo->Size;
+ members->MembersCount = ParameterInfo->ValidSetCount;
+ members->Flags = KSPROPERTY_MEMBER_FLAG_DEFAULT;
+
+ // fill in valid array.
+ BYTE* array = (BYTE*)(members + 1);
+
+ RtlCopyMemory(array, ParameterInfo->ValidSet, cbDataListSize);
+
+ // set the return value size
+ *BufferCb = cbFullProperty;
+ }
+ else
+ {
+ *BufferCb = sizeof(KSPROPERTY_DESCRIPTION);
+ }
+ }
+ else if(*BufferCb >= sizeof(ULONG))
+ {
+ // if return buffer can hold a ULONG, return the access flags
+ PULONG accessFlags = PULONG(Buffer);
+
+ *BufferCb = sizeof(ULONG);
+ *accessFlags = ParameterInfo->AccessFlags;
+ }
+ else
+ {
+ *BufferCb = 0;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ return ntStatus;
+} // PropertyHandlerBasicSupportVolume
+
+//=============================================================================
+#pragma code_seg("PAGE")
+BOOLEAN
+IsAudioModuleParameterValid(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _In_reads_bytes_opt_(BufferCb) PVOID Buffer,
+ _In_ ULONG BufferCb
+ )
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[IsAudioModuleParameterValid]"));
+
+ ULONG i = 0;
+ ULONG j = 0;
+ BOOLEAN validParam = FALSE;
+
+ //
+ // Validate buffer ptr and size.
+ //
+ if (Buffer == NULL || BufferCb == 0)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+
+ //
+ // Check its size.
+ //
+ if (BufferCb < ParameterInfo->Size)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+
+ //
+ // Check the valid list.
+ //
+ if (ParameterInfo->ValidSet && ParameterInfo->ValidSetCount)
+ {
+ BYTE* buffer = (BYTE*)ParameterInfo->ValidSet;
+ BYTE* pattern = (BYTE*)Buffer;
+
+ //
+ // Scan the valid list.
+ //
+ for (i = 0; i < ParameterInfo->ValidSetCount; ++i)
+ {
+ for (j=0; j < ParameterInfo->Size; ++j)
+ {
+ if (buffer[j] != pattern[j])
+ {
+ break;
+ }
+ }
+
+ if (j == ParameterInfo->Size)
+ {
+ // got a match.
+ break;
+ }
+
+ buffer += ParameterInfo->Size;
+ }
+
+ //
+ // If end of list, we didn't find the value.
+ //
+ if (i == ParameterInfo->ValidSetCount)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+ }
+ else
+ {
+ //
+ // Negative-testing support. Fail request if value is -1.
+ //
+ BYTE* buffer = (BYTE*)Buffer;
+
+ for (i = 0; i < ParameterInfo->Size; ++i)
+ {
+ if (buffer[i] != 0xFF)
+ {
+ break;
+ }
+ }
+
+ //
+ // If value is -1, return error.
+ //
+ if (i == ParameterInfo->Size)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+ }
+
+ validParam = TRUE;
+
+exit:
+ return validParam;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+AUDIOMODULE *
+AudioModule_FindModuleInList(
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount,
+ _In_ GUID * ClassId,
+ _In_ ULONG InstanceId
+ )
+{
+ for (ULONG i=0; i<AudioModuleCount; ++i)
+ {
+ AUDIOMODULE * module = &AudioModules[i];
+
+ if (IsEqualGUIDAligned(*(module->Descriptor->ClassId), *ClassId) &&
+ module->InstanceId == InstanceId)
+ {
+ return module;
+ }
+ }
+
+ return NULL;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler(
+ _In_ ULONG Verb,
+ _In_ ULONG ParameterId,
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue,
+ _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb,
+ _In_ BOOL * ParameterChanged
+ )
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_GenericHandler]"));
+
+ UNREFERENCED_PARAMETER(ParameterId);
+
+ *ParameterChanged = FALSE;
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ return AudioModule_GenericHandler_BasicSupport(ParameterInfo, OutBuffer, OutBufferCb);
+ }
+
+ ULONG cbMinSize = ParameterInfo->Size;
+
+ if (Verb & KSPROPERTY_TYPE_GET)
+ {
+ // Verify module parameter supports 'get'.
+ if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_GET))
+ {
+ *OutBufferCb = 0;
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Verify value size
+ if (*OutBufferCb == 0)
+ {
+ *OutBufferCb = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (*OutBufferCb < cbMinSize)
+ {
+ *OutBufferCb = 0;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ RtlCopyMemory(OutBuffer, CurrentValue, ParameterInfo->Size);
+ *OutBufferCb = cbMinSize;
+ return STATUS_SUCCESS;
+ }
+ }
+ else if (Verb & KSPROPERTY_TYPE_SET)
+ {
+ *OutBufferCb = 0;
+
+ // Verify it is a write prop.
+ if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_SET))
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Validate parameter.
+ if (!IsAudioModuleParameterValid(ParameterInfo, InBuffer, InBufferCb))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (ParameterInfo->Size !=
+ RtlCompareMemory(CurrentValue, InBuffer, ParameterInfo->Size))
+ {
+ RtlCopyMemory(CurrentValue, InBuffer, ParameterInfo->Size);
+ *ParameterChanged = TRUE;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModulesListRequest(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ )
+{
+ NTSTATUS ntStatus;
+
+ // This specific APO->driver communication example is mainly added to show how this communication is done.
+ // The module list only lives on the wave filter and it can have modules that are for all pins and some that
+ // are only on specific pins.
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_PropertyHandlerModulesListRequest]"));
+
+ //
+ // Note: return an empty list when no modules are present.
+ //
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT;
+ return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
+ }
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ PKSMULTIPLE_ITEM ksMultipleItem;
+ ULONG cbMinSize = 0;
+ PKSAUDIOMODULE_DESCRIPTOR modules = NULL;
+
+ //
+ // Compute min value size requirements
+ //
+ ntStatus = RtlULongMult(AudioModuleCount,
+ (ULONG)sizeof(KSAUDIOMODULE_DESCRIPTOR),
+ &cbMinSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ return ntStatus;
+ }
+
+ ntStatus = RtlULongAdd(cbMinSize, sizeof(KSMULTIPLE_ITEM), &cbMinSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ return ntStatus;
+ }
+
+ // Verify value size
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (PropertyRequest->ValueSize < cbMinSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ // Value is a KSMULTIPLE_ITEM followed by list of modules.
+ ksMultipleItem = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
+ modules = (PKSAUDIOMODULE_DESCRIPTOR)(ksMultipleItem + 1);
+
+ // Copy modules
+ for (ULONG i = 0; i<AudioModuleCount; ++i, ++modules)
+ {
+ const AUDIOMODULE_DESCRIPTOR * moduleDesc = AudioModules[i].Descriptor;
+
+ modules->ClassId = *moduleDesc->ClassId;
+ modules->InstanceId = AudioModules[i].InstanceId;
+
+ modules->VersionMajor = moduleDesc->VersionMajor;
+ modules->VersionMinor = moduleDesc->VersionMinor;
+
+
+ RtlStringCchCopyW(modules->Name,
+ AUDIOMODULE_MAX_NAME_CCH_SIZE, // includes null char
+ moduleDesc->Name);
+ }
+
+ // Miniport filled in the list of modules. Fill in the KSMULTIPLE_ITEM header.
+ ksMultipleItem->Size = cbMinSize;
+ ksMultipleItem->Count = AudioModuleCount;
+
+ PropertyRequest->ValueSize = ksMultipleItem->Size;
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+} // AudioModule_GenericHandler_ModulesListRequest
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleCommand(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ )
+{
+ AUDIOMODULE * module = NULL;
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_GenericHandler_ModuleCommand]"));
+
+ //
+ // Basic parameter validation.
+ //
+ if (AudioModules == NULL || AudioModuleCount == 0)
+ {
+ // endpoint/stream doesn't have any modules.
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Verify instance data stores at least KSAUDIOMODULE_PROPERTY fields
+ // beyond KSPPROPERTY.
+ if (PropertyRequest->InstanceSize < (sizeof(KSAUDIOMODULE_PROPERTY) -
+ RTL_SIZEOF_THROUGH_FIELD(KSAUDIOMODULE_PROPERTY, Property)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Extract property descriptor from property request instance data
+ PKSAUDIOMODULE_PROPERTY moduleProperty = CONTAINING_RECORD(
+ PropertyRequest->Instance, KSAUDIOMODULE_PROPERTY, ClassId);
+
+ // Get a ptr to the module.
+ module = AudioModule_FindModuleInList(AudioModules,
+ AudioModuleCount,
+ &moduleProperty->ClassId,
+ moduleProperty->InstanceId);
+ //
+ // Invoke the handler.
+ //
+ if (module == NULL ||
+ module->Descriptor == NULL ||
+ module->Descriptor->Handler == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT;
+
+ return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
+ }
+
+ // Only KS-get is supported.
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ NTSTATUS status;
+ ULONG inBufferCb = 0;
+ ULONG outBufferCb = 0;
+ PVOID inBuffer = NULL;
+ PVOID outBuffer = NULL;
+
+ outBufferCb = PropertyRequest->ValueSize;
+ outBuffer = PropertyRequest->Value;
+
+ ASSERT((outBufferCb != 0 && outBuffer != NULL) ||
+ (outBufferCb == 0 && outBuffer == NULL));
+
+ // this is guaranteed to work b/c of the validation above.
+ inBufferCb = PropertyRequest->InstanceSize +
+ sizeof(KSPROPERTY) -
+ sizeof(KSAUDIOMODULE_PROPERTY);
+
+ if (inBufferCb != 0)
+ {
+ inBuffer = (PVOID)(moduleProperty+1);
+ }
+
+ status = module->Descriptor->Handler(module->Context,
+ inBuffer,
+ inBufferCb,
+ outBuffer,
+ &outBufferCb);
+ //
+ // Set the size of the returned output data, or in the case of
+ // buffer overflow error, return the expected buffer length.
+ //
+ PropertyRequest->ValueSize = outBufferCb;
+ return status;
+ }
+
+ PropertyRequest->ValueSize = 0;
+ return STATUS_INVALID_DEVICE_REQUEST;
+} // AudioModule_GenericHandler_ModuleCommand
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleNotificationDeviceId(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ const GUID * NotificationDeviceId
+ )
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_GenericHandler_ModuleNotificationDeviceId]"));
+
+ //
+ // Basic parameter validation.
+ //
+ if (NotificationDeviceId == NULL)
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT;
+
+ return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
+ }
+
+ ULONG cbMinSize = sizeof(GUID);
+ GUID *dataPtr = static_cast<GUID*>(PropertyRequest->Value);
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ // Verify value size
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (PropertyRequest->ValueSize < cbMinSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ *dataPtr = *NotificationDeviceId;
+ PropertyRequest->ValueSize = cbMinSize;
+
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID
+AudioModule_SendNotification(
+ _In_ PPORTCLSNOTIFICATIONS PortNotifications,
+ _In_ PVOID NotificationBuffer,
+ _In_ USHORT NotificationBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PPCNOTIFICATION_BUFFER buffer = NULL;
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_SendNotification]"));
+
+ // Allocate a notification buffer.
+ status = PortNotifications->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).
+ //
+ PortNotifications->SendNotification(&KSNOTIFICATIONID_AudioModule, buffer);
+
+exit:
+ if (buffer != NULL)
+ {
+ // Free notification buffer.
+ PortNotifications->FreeNotificationBuffer(buffer);
+ buffer = NULL;
+ }
+}
+
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModuleHelper.h b/audio/sysvad/EndpointsCommon/AudioModuleHelper.h
new file mode 100644
index 00000000..fa7a2c23
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModuleHelper.h
@@ -0,0 +1,95 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModuleHelper.h
+
+Abstract:
+
+ Simple helper for Audio Modules logic.
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULEHELPER_H_
+#define _SYSVAD_AUDIOMODULEHELPER_H_
+
+//
+// Module helper functions.
+//
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_BasicSupport(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer,
+ _Inout_ ULONG * BufferCb
+ );
+
+#pragma code_seg("PAGE")
+BOOLEAN
+IsAudioModuleParameterValid(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _In_reads_bytes_opt_(BufferCb) PVOID Buffer,
+ _In_ ULONG BufferCb
+ );
+
+#pragma code_seg("PAGE")
+AUDIOMODULE *
+AudioModule_FindModuleInList(
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount,
+ _In_ GUID * ClassId,
+ _In_ ULONG InstanceId
+ );
+
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler(
+ _In_ ULONG Verb,
+ _In_ ULONG ParameterId,
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue,
+ _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb,
+ _In_ BOOL * ParameterChanged
+ );
+
+//
+// Miniport/Stream helper functions.
+//
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModulesListRequest(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ );
+
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleCommand(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ );
+
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleNotificationDeviceId(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ const GUID * NotificationDeviceId
+ );
+
+#pragma code_seg("PAGE")
+VOID
+AudioModule_SendNotification(
+ _In_ PPORTCLSNOTIFICATIONS PortNotifications,
+ _In_ PVOID NotificationBuffer,
+ _In_ USHORT NotificationBufferCb
+ );
+#endif // _SYSVAD_AUDIOMODULEHELPER_H_
+
+
diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
index 1956d106..4fb3fda6 100644
--- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
+++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
@@ -157,6 +157,7 @@
</Midl>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="AudioModuleHelper.cpp" />
<ClCompile Include="bthhfpmictopo.cpp" />
<ClCompile Include="bthhfpminwavert.cpp" />
<ClCompile Include="bthhfpspeakertopo.cpp" />
diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters
new file mode 100644
index 00000000..0579c299
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters
@@ -0,0 +1,62 @@
+<?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>{CDBBEDA3-98E9-4C7A-BDB1-25EC47D0B087}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{FA3DF57E-BA19-4783-831B-CF9D4D594F70}</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>{CB830E4F-01DA-4D35-9789-E7DB0D02A79C}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{49F92783-3B39-4D0C-A153-8C346F754749}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="AudioModuleHelper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfpmictopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfpminwavert.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfpspeakertopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfptopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="micarraytopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="MiniportAudioEngineNode.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="MiniportStreamAudioEngineNode.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mintopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="minwavert.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="minwavertstream.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="speakerhptopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="speakertopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp
index a210f77b..0f772155 100644
--- a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp
+++ b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp
@@ -996,3 +996,4 @@ NTSTATUS CMiniportWaveRTStream::SetStreamCurrentWritePositionForLastBuffer(_In_
return ntStatus;
}
+
diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp
index 53fcfac2..35923619 100644
--- a/audio/sysvad/EndpointsCommon/minwavert.cpp
+++ b/audio/sysvad/EndpointsCommon/minwavert.cpp
@@ -22,6 +22,8 @@ Abstract:
#include "minwavert.h"
#include "minwavertstream.h"
#include "IHVPrivatePropertySet.h"
+#include "AudioModuleHelper.h"
+
//=============================================================================
// CMiniportWaveRT
@@ -37,7 +39,7 @@ CreateMiniportWaveRTSYSVAD
_In_opt_ PUNKNOWN UnknownOuter,
_When_((PoolType & NonPagedPoolMustSucceed) != 0,
__drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
+ "Allocation failures cause a system crash"))
_In_ POOL_TYPE PoolType,
_In_ PUNKNOWN UnknownAdapter,
_In_opt_ PVOID DeviceContext,
@@ -161,6 +163,12 @@ Return Value:
m_pPortEvents = NULL;
}
+ if (m_pPortClsNotifications)
+ {
+ m_pPortClsNotifications->Release();
+ m_pPortClsNotifications = NULL;
+ }
+
if (m_SystemStreams)
{
ExFreePoolWithTag( m_SystemStreams, MINWAVERT_POOLTAG );
@@ -178,7 +186,13 @@ Return Value:
ExFreePoolWithTag( m_LoopbackStreams, MINWAVERT_POOLTAG );
m_LoopbackStreams = NULL;
}
-
+
+ if (m_pAudioModules)
+ {
+ FreeStreamAudioModules(m_pAudioModules, GetAudioModuleListCount());
+ m_pAudioModules = NULL;
+ }
+
#ifdef SYSVAD_BTH_BYPASS
if (IsBthHfpDevice())
{
@@ -392,6 +406,80 @@ Return Value:
m_LoopbackProtection = CONSTRICTOR_OPTION_DISABLE;
RtlZeroMemory(&m_MixDrmRights, sizeof(m_MixDrmRights));
+ //
+ // For port notification support.
+ //
+ if (!NT_SUCCESS(Port_->QueryInterface(IID_IPortClsNotifications, (PVOID *)&m_pPortClsNotifications)))
+ {
+ m_pPortClsNotifications = NULL;
+ }
+
+ //
+ // Init all the modules associated to this miniport.
+ //
+ ULONG cModules = GetAudioModuleListCount();
+ if (cModules)
+ {
+ //
+ // Module list size.
+ //
+ size = cModules * sizeof(AUDIOMODULE);
+ m_pAudioModules = (AUDIOMODULE *)ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+ if (m_pAudioModules == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(m_pAudioModules, size);
+
+ for (ULONG i=0; i<cModules; ++i)
+ {
+ PAUDIOMODULE_DESCRIPTOR moduleDesc = &m_pMiniportPair->ModuleList[i];
+
+ //
+ // Init run-time module element.
+ //
+ m_pAudioModules[i].Descriptor = moduleDesc;
+ m_pAudioModules[i].Context = NULL;
+ m_pAudioModules[i].InstanceId = moduleDesc->InstanceId;
+ m_pAudioModules[i].Enabled = TRUE;
+ //
+ // Module context size.
+ //
+ size = moduleDesc->ContextSize;
+ if (size)
+ {
+ m_pAudioModules[i].Context =
+ ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+
+ if (m_pAudioModules[i].Context == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(m_pAudioModules[i].Context, size);
+ }
+
+
+ if (moduleDesc->InitClass)
+ {
+ KSAUDIOMODULE_NOTIFICATION NotificationHeader;
+ NotificationHeader.ProviderId.DeviceId = *GetAudioModuleNotificationDeviceId();
+ NotificationHeader.ProviderId.ClassId = *moduleDesc->ClassId;
+ NotificationHeader.ProviderId.InstanceId = moduleDesc->InstanceId;
+
+ ntStatus = moduleDesc->InitClass(moduleDesc,
+ m_pAudioModules[i].Context,
+ size,
+ &NotificationHeader,
+ m_pPortClsNotifications);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ return ntStatus;
+ }
+ }
+ }
+ }
+
//
// Init the audio-engine used by the render devices.
//
@@ -1294,6 +1382,63 @@ CMiniportWaveRT::PropertyHandlerProposedFormat
return ntStatus;
} // PropertyHandlerProposedFormat
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerModulesListRequest
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ // This specific APO->driver communication example is mainly added to show how this communication is done.
+ // The module list only lives on the wave filter and it can have modules that are for all pins and some that
+ // are only on specific pins.
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModulesListRequest]"));
+
+ return AudioModule_GenericHandler_ModulesListRequest(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModulesListRequest
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerModuleCommand
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModuleCommand]"));
+
+ return AudioModule_GenericHandler_ModuleCommand(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModuleCommand
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerModuleNotificationDeviceId
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModuleNotificationDeviceId]"));
+
+ return AudioModule_GenericHandler_ModuleNotificationDeviceId(
+ PropertyRequest,
+ GetAudioModuleNotificationDeviceId());
+} // PropertyHandlerModuleNotificationDeviceId
+
//=============================================================================
#pragma code_seg("PAGE")
@@ -1677,6 +1822,203 @@ Return Value:
//=============================================================================
#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::AllocStreamAudioModules
+(
+ _In_ const GUID * SignalProcessingMode,
+ _Out_ AUDIOMODULE ** ppAudioModules,
+ _Out_ ULONG * pAudioModuleCount
+)
+{
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_STATE;
+ AUDIOMODULE * pAudioModules = NULL;
+ ULONG cModules = 0;
+ ULONG i, j;
+ size_t size;
+
+ PAGED_CODE();
+
+ //
+ // Init out parameters.
+ //
+ *ppAudioModules = NULL;
+ *pAudioModuleCount = 0;
+
+ //
+ // Nothing to do if there are no modules.
+ //
+ if (m_pAudioModules == NULL)
+ {
+ ntStatus = STATUS_SUCCESS;
+ goto exit;
+ }
+
+ //
+ // Find the # of modules associated with this stream.
+ //
+ for (i=0; i<GetAudioModuleListCount(); ++i)
+ {
+ const AUDIOMODULE_DESCRIPTOR * moduleDesc = m_pAudioModules[i].Descriptor;
+
+ if (IsEqualGUIDAligned(*moduleDesc->ProcessingMode, *SignalProcessingMode) ||
+ IsEqualGUIDAligned(*moduleDesc->ProcessingMode, NULL_GUID))
+ {
+ cModules++;
+ }
+ }
+
+ //
+ // All done if module count is zero.
+ //
+ if (cModules == 0)
+ {
+ ntStatus = STATUS_SUCCESS;
+ goto exit;
+ }
+
+ //
+ // Alloc modules infrastructure.
+ //
+ size = cModules * sizeof(AUDIOMODULE);
+#pragma prefast(suppress:__WARNING_MEMORY_LEAK,"No leaking, stream obj dtor calls FreeStreamAudioModules")
+ pAudioModules = (AUDIOMODULE *)ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+ if (pAudioModules == NULL)
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+ RtlZeroMemory(pAudioModules, size);
+
+ for (i=0, j=0; i<GetAudioModuleListCount() && j<cModules; ++i)
+ {
+ const AUDIOMODULE_DESCRIPTOR * moduleDesc = m_pAudioModules[i].Descriptor;
+
+ if (IsEqualGUIDAligned(*moduleDesc->ProcessingMode, *SignalProcessingMode) ||
+ IsEqualGUIDAligned(*moduleDesc->ProcessingMode, NULL_GUID))
+ {
+ ULONG CfgInstanceId;
+
+ //
+ // Init run-time module element.
+ //
+ pAudioModules[j].Descriptor = moduleDesc;
+ pAudioModules[j].Context = NULL;
+
+ //
+ // Create a unique InstanceId for this module instance.
+ // This sample uses 24bits index which wraps around after 16M
+ // module instances for a specific class ID/Class config id.
+ // A real driver should reuse instance ids of deleted module
+ // instances, i.e., the driver should use a mapping between
+ // index <--> module info.
+ //
+ CfgInstanceId = InterlockedIncrement((LONG*)&m_pAudioModules[i].NextCfgInstanceId);
+
+ pAudioModules[j].InstanceId =
+ AUDIOMODULE_INSTANCE_ID(AUDIOMODULE_GET_CLASSCFGID(m_pAudioModules[i].InstanceId),
+ CfgInstanceId);
+
+ pAudioModules[j].Enabled = m_pAudioModules[i].Enabled;
+
+ //
+ // Alloc context for module instance.
+ //
+ size = moduleDesc->ContextSize;
+ if (size)
+ {
+#pragma prefast(suppress:__WARNING_MEMORY_LEAK,"No leaking, stream obj dtor calls FreeStreamAudioModules")
+ pAudioModules[j].Context =
+ ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+
+ if (pAudioModules[j].Context == NULL)
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+ RtlZeroMemory(pAudioModules[j].Context, size);
+ }
+
+ //
+ // Init this module instance.
+ //
+ if (moduleDesc->InitInstance)
+ {
+ ntStatus = moduleDesc->InitInstance(moduleDesc,
+ m_pAudioModules[i].Context,
+ pAudioModules[j].Context,
+ size,
+ pAudioModules[j].InstanceId);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ goto exit;
+ }
+ }
+
+ //
+ // Update stream module array index.
+ //
+ j++;
+ }
+ }
+
+ //
+ // Return the list of modules.
+ //
+ *ppAudioModules = pAudioModules;
+ *pAudioModuleCount = cModules;
+
+ ntStatus = STATUS_SUCCESS;
+
+exit:
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ if (pAudioModules != NULL)
+ {
+ FreeStreamAudioModules(pAudioModules, cModules);
+ pAudioModules = NULL;
+ cModules = 0;
+ }
+ }
+
+ return ntStatus;
+}
+
+#pragma code_seg("PAGE")
+VOID
+CMiniportWaveRT::FreeStreamAudioModules
+(
+ _In_ AUDIOMODULE * pAudioModules,
+ _In_ ULONG AudioModuleCount
+)
+{
+ PAGED_CODE();
+
+ if (pAudioModules != NULL)
+ {
+ ASSERT(AudioModuleCount);
+
+ for (ULONG i=0; i<AudioModuleCount; ++i)
+ {
+ if (pAudioModules[i].Context)
+ {
+ if (pAudioModules[i].Descriptor->Cleanup)
+ {
+ pAudioModules[i].Descriptor->Cleanup(pAudioModules[i].Context);
+ }
+
+ ExFreePoolWithTag(pAudioModules[i].Context, MINWAVERT_POOLTAG);
+ pAudioModules[i].Context = NULL;
+ }
+ }
+
+ ExFreePoolWithTag(pAudioModules, MINWAVERT_POOLTAG);
+ }
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns)
{
@@ -1937,6 +2279,24 @@ Return Value:
DPF(D_TERSE, ("[PropertyHandler_WaveFilter: Invalid Device Request]"));
}
}
+ else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioModule))
+ {
+ switch (PropertyRequest->PropertyItem->Id)
+ {
+ case KSPROPERTY_AUDIOMODULE_DESCRIPTORS:
+ ntStatus = pWaveHelper->PropertyHandlerModulesListRequest(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_COMMAND:
+ ntStatus = pWaveHelper->PropertyHandlerModuleCommand(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID:
+ ntStatus = pWaveHelper->PropertyHandlerModuleNotificationDeviceId(PropertyRequest);
+ break;
+
+ default:
+ DPF(D_TERSE, ("[PropertyHandler_WaveFilter: Invalid Device Request]"));
+ }
+ }
else if ((pWaveHelper->m_DeviceType == eHdmiRenderDevice ||
pWaveHelper->m_DeviceType == eCellularDevice ||
pWaveHelper->m_DeviceType == eHandsetSpeakerDevice) &&
@@ -2061,6 +2421,69 @@ PropertyHandler_OffloadPin
return ntStatus;
}
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_GenericPin
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ CMiniportWaveRT* pWave = NULL;
+ CMiniportWaveRTStream * pStream = NULL;
+
+ PAGED_CODE();
+
+ if (PropertyRequest->MajorTarget == NULL ||
+ PropertyRequest->MinorTarget == NULL)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Get a ref to the miniport.
+ //
+ pWave = MajorTarget_to_Obj(PropertyRequest->MajorTarget);
+ pWave->AddRef();
+
+ //
+ // Get a ref to the stream.
+ //
+ pStream = MinorTarget_to_Obj(PropertyRequest->MinorTarget);
+ pStream->AddRef();
+
+ //
+ // Invoke appropriate handle.
+ //
+ if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioModule))
+ {
+ switch (PropertyRequest->PropertyItem->Id)
+ {
+ case KSPROPERTY_AUDIOMODULE_DESCRIPTORS:
+ ntStatus = pStream->PropertyHandlerModulesListRequest(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_COMMAND:
+ ntStatus = pStream->PropertyHandlerModuleCommand(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID:
+ // Filter handles this prop.
+ ntStatus = pWave->PropertyHandlerModuleNotificationDeviceId(PropertyRequest);
+ break;
+
+ default:
+ DPF(D_TERSE, ("[PropertyHandler_GenericPin: Invalid Device Request]"));
+ }
+ }
+
+exit:
+
+ SAFE_RELEASE(pStream);
+ SAFE_RELEASE(pWave);
+
+ return ntStatus;
+}
// ISSUE-2014/10/20 Add synchronization mechanism throughout this class
// ISSUE-2014/10/20 Add comment headers and commenting throughout
diff --git a/audio/sysvad/EndpointsCommon/minwavert.h b/audio/sysvad/EndpointsCommon/minwavert.h
index 4660cfa1..da31f172 100644
--- a/audio/sysvad/EndpointsCommon/minwavert.h
+++ b/audio/sysvad/EndpointsCommon/minwavert.h
@@ -148,11 +148,14 @@ private:
#endif // SYSVAD_BTH_BYPASS
};
+ AUDIOMODULE * m_pAudioModules;
+
protected:
PADAPTERCOMMON m_pAdapterCommon;
ULONG m_DeviceFlags;
eDeviceType m_DeviceType;
PPORTEVENTS m_pPortEvents;
+ PPORTCLSNOTIFICATIONS m_pPortClsNotifications;
PENDPOINT_MINIPAIR m_pMiniportPair;
@@ -231,7 +234,9 @@ public:
m_DeviceFormatsAndModes(MiniportPair->PinDeviceFormatsAndModes),
m_DeviceFormatsAndModesCount(MiniportPair->PinDeviceFormatsAndModesCount),
m_DeviceFlags(MiniportPair->DeviceFlags),
- m_pMiniportPair(MiniportPair)
+ m_pMiniportPair(MiniportPair),
+ m_pAudioModules(NULL),
+ m_pPortClsNotifications(NULL)
{
PAGED_CODE();
@@ -266,7 +271,6 @@ public:
}
}
-
#ifdef SYSVAD_BTH_BYPASS
if (IsBthHfpDevice())
{
@@ -316,6 +320,22 @@ public:
(
_In_ PPCPROPERTY_REQUEST PropertyRequest
);
+
+ NTSTATUS PropertyHandlerModulesListRequest
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerModuleCommand
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerModuleNotificationDeviceId
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
PADAPTERCOMMON GetAdapterCommObj()
{
@@ -629,8 +649,70 @@ protected:
ASSERT(!IsCellularDevice());
return KSPIN_WAVE_RENDER_SINK_OFFLOAD;
}
+
#pragma code_seg()
+ ULONG
+ GetAudioModuleDescriptorListCount()
+ {
+ return m_pMiniportPair->ModuleListCount;
+ }
+
+ const PAUDIOMODULE_DESCRIPTOR
+ GetAudioModuleDescriptor(
+ _In_ ULONG Index
+ )
+ {
+ ASSERT(Index < GetAudioModuleDescriptorListCount());
+ return &m_pMiniportPair->ModuleList[Index];
+ }
+
+ const PAUDIOMODULE_DESCRIPTOR
+ GetAudioModuleDescriptorList()
+ {
+ return m_pMiniportPair->ModuleList;
+ }
+
+ ULONG
+ GetAudioModuleListCount()
+ {
+ return GetAudioModuleDescriptorListCount();
+ }
+
+ AUDIOMODULE *
+ GetAudioModule(
+ _In_ ULONG Index
+ )
+ {
+ ASSERT(Index < GetAudioModuleListCount());
+ return &m_pAudioModules[Index];
+ }
+
+ AUDIOMODULE *
+ GetAudioModuleList()
+ {
+ return m_pAudioModules;
+ }
+
+ const GUID *
+ GetAudioModuleNotificationDeviceId()
+ {
+ return m_pMiniportPair->ModuleNotificationDeviceId;
+ }
+
+ NTSTATUS
+ AllocStreamAudioModules(
+ _In_ const GUID * SignalProcessingMode,
+ _Out_ AUDIOMODULE ** AudioModule,
+ _Out_ ULONG * AudioModuleCount
+ );
+
+ VOID
+ FreeStreamAudioModules(
+ _In_ AUDIOMODULE * AudioModule,
+ _In_ ULONG AudioModuleCount
+ );
+
#ifdef SYSVAD_BTH_BYPASS
public:
#pragma code_seg("PAGE")
diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp
index 58382639..1661b5fb 100644
--- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp
+++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp
@@ -5,6 +5,7 @@
#include "minwavert.h"
#include "minwavertstream.h"
#include "UnittestData.h"
+#include "AudioModuleHelper.h"
#define MINWAVERTSTREAM_POOLTAG 'SRWM'
#pragma warning (disable : 4127)
@@ -34,8 +35,16 @@ Return Value:
--*/
{
PAGED_CODE();
+
if (NULL != m_pMiniport)
{
+ if (m_pAudioModules)
+ {
+ m_pMiniport->FreeStreamAudioModules(m_pAudioModules, m_AudioModuleCount);
+ m_pAudioModules = NULL;
+ m_AudioModuleCount = 0;
+ }
+
if (m_bUnregisterStream)
{
m_pMiniport->StreamClosed(m_ulPin, this);
@@ -181,6 +190,8 @@ Return Value:
m_SignalProcessingMode = SignalProcessingMode;
m_bEoSReceived = FALSE;
m_bLastBufferRendered = FALSE;
+ m_pAudioModules = NULL;
+ m_AudioModuleCount = 0;
#ifdef SYSVAD_BTH_BYPASS
m_ScoOpen = FALSE;
@@ -268,6 +279,17 @@ Return Value:
}
RtlZeroMemory(m_plPeakMeter, m_pWfExt->Format.nChannels * sizeof(LONG));
+ //
+ // Allocate stream audio module resources.
+ //
+ ntStatus = m_pMiniport->AllocStreamAudioModules(&SignalProcessingMode,
+ &m_pAudioModules,
+ &m_AudioModuleCount);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
if (m_bCapture)
{
DWORD toneFrequency = 0;
@@ -784,6 +806,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,
@@ -854,7 +877,7 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket
// Compute and return timestamp corresponding to start of the available packet. In a real hardware
// driver, the timestamp would be computed in a driver and hardware specific manner. In this sample
- // driver, it is extrapolated from the sample driver's internal simulated position corrleation
+ // driver, it is extrapolated from the sample driver's internal simulated position correlation
// [m_ullLinearPosition @ m_ullDmaTimeStamp] and the sample's internal 64-bit packet counter, subtracting
// 1 from the packet counter to compute the time at the start of that last completed packet.
ULONGLONG linearPositionOfAvailablePacket = (packetCounter - 1) * (m_ulDmaBufferSize / m_ulNotificationsPerBuffer);
@@ -895,6 +918,7 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket
}
#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS CMiniportWaveRTStream::SetWritePacket
(
_In_ ULONG PacketNumber,
@@ -987,6 +1011,7 @@ NTSTATUS CMiniportWaveRTStream::SetWritePacket
//=============================================================================
#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition
(
_Out_ KSAUDIO_PRESENTATION_POSITION *pPresentationPosition
@@ -1005,6 +1030,7 @@ NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition
//=============================================================================
#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS CMiniportWaveRTStream::GetPacketCount
(
_Out_ ULONG *pPacketCount
@@ -1506,6 +1532,47 @@ Return Value:
#endif // SYSVAD_BTH_BYPASS
//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRTStream::PropertyHandlerModulesListRequest
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ // This specific APO->driver communication example is mainly added to show
+ // how this communication is done. The instance module list lives on the
+ // stream object and it can only have modules associated with the underline
+ // stream's pin.
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRTStream::PropertyHandlerModulesListRequest]"));
+
+ return AudioModule_GenericHandler_ModulesListRequest(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModulesListRequest
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRTStream::PropertyHandlerModuleCommand
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRTStream::PropertyHandlerModuleCommand]"));
+
+ return AudioModule_GenericHandler_ModuleCommand(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModuleCommand
+
+//=============================================================================
#pragma code_seg()
void
TimerNotifyRT
@@ -1550,10 +1617,10 @@ TimerNotifyRT
goto End;
}
- // Carry forward the remainder of this division
- _this->m_hnsDPCTimeCarryForward = (hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward) % 10000;
+ // Carry forward the time greater than notification interval to adjust time to signal next buffer completion event accordingly.
+ _this->m_hnsDPCTimeCarryForward = hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward - (_this->m_ulNotificationIntervalMs * 10000);
// Save the last time DPC ran at notification interval
- _this->m_ullLastDPCTimeStamp = (ULONG)hnsCurrentTime;
+ _this->m_ullLastDPCTimeStamp = hnsCurrentTime;
_this->UpdatePosition(qpc);
diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.h b/audio/sysvad/EndpointsCommon/minwavertstream.h
index 405ae35e..3034d630 100644
--- a/audio/sysvad/EndpointsCommon/minwavertstream.h
+++ b/audio/sysvad/EndpointsCommon/minwavertstream.h
@@ -125,6 +125,8 @@ protected:
BOOLEAN m_bEoSReceived;
BOOLEAN m_bLastBufferRendered;
KSPIN_LOCK m_PositionSpinLock;
+ AUDIOMODULE * m_pAudioModules;
+ ULONG m_AudioModuleCount;
#ifdef SYSVAD_BTH_BYPASS
BOOLEAN m_ScoOpen;
@@ -227,10 +229,45 @@ public:
{
return m_SignalProcessingMode;
}
+
+ NTSTATUS PropertyHandlerModulesListRequest
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerModuleCommand
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
private:
+ //
// Helper functions.
+ //
+
+#pragma code_seg()
+ ULONG
+ GetAudioModuleListCount()
+ {
+ return m_AudioModuleCount;
+ }
+
+ AUDIOMODULE *
+ GetAudioModule(
+ _In_ ULONG Index
+ )
+ {
+ ASSERT(Index < GetAudioModuleListCount());
+ return &m_pAudioModules[Index];
+ }
+
+ AUDIOMODULE *
+ GetAudioModuleList()
+ {
+ return m_pAudioModules;
+ }
+
VOID WriteBytes
(
_In_ ULONG ByteDisplacement
diff --git a/audio/sysvad/EndpointsCommon/sources b/audio/sysvad/EndpointsCommon/sources
new file mode 100644
index 00000000..ab930dbd
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/sources
@@ -0,0 +1,46 @@
+
+# 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
+#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) \
+ mintopo.cpp \
+ minwavert.cpp \
+ minwavertstream.cpp \
+ MiniportAudioEngineNode.cpp\
+ MiniportStreamAudioEngineNode.cpp\
+ micarraytopo.cpp \
+ speakertopo.cpp \
+ speakerhptopo.cpp \
+ bthhfptopo.cpp \
+ bthhfpmictopo.cpp \
+ bthhfpspeakertopo.cpp \
+ bthhfpminwavert.cpp \
+ AudioModuleHelper.cpp \
+
+
+
diff --git a/audio/sysvad/EndpointsCommon/speakerhpwavtable.h b/audio/sysvad/EndpointsCommon/speakerhpwavtable.h
index 2f36ac06..66fc9c8a 100644
--- a/audio/sysvad/EndpointsCommon/speakerhpwavtable.h
+++ b/audio/sysvad/EndpointsCommon/speakerhpwavtable.h
@@ -15,6 +15,9 @@ Abstract:
#ifndef _SYSVAD_SPEAKERHPWAVTABLE_H_
#define _SYSVAD_SPEAKERHPWAVTABLE_H_
+#include "AudioModule0.h"
+#include "AudioModule1.h"
+#include "AudioModule2.h"
// To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM)
@@ -579,6 +582,33 @@ PKSDATARANGE SpeakerHpPinDataRangePointersBridge[] =
//=============================================================================
static
+PCPROPERTY_ITEM PropertiesSpeakerHpHostPin[] =
+{
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpHostPin, PropertiesSpeakerHpHostPin);
+
+//=============================================================================
+
+static
PCPROPERTY_ITEM PropertiesSpeakerHpOffloadPin[] =
{
{
@@ -592,7 +622,25 @@ PCPROPERTY_ITEM PropertiesSpeakerHpOffloadPin[] =
KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties
KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_OffloadPin
- }
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
};
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpOffloadPin, PropertiesSpeakerHpOffloadPin);
@@ -606,7 +654,7 @@ PCPIN_DESCRIPTOR SpeakerHpWaveMiniportPins[] =
SPEAKERHP_MAX_INPUT_SYSTEM_STREAMS,
SPEAKERHP_MAX_INPUT_SYSTEM_STREAMS,
0,
- NULL,
+ &AutomationSpeakerHpHostPin, // AutomationTable
{
0,
NULL,
@@ -722,9 +770,84 @@ PCPROPERTY_ITEM PropertiesSpeakerHpWaveFilter[] =
KSPROPERTY_PIN_PROPOSEDATAFORMAT,
KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+};
+
+//
+// Endpoint audio module list.
+//
+static
+AUDIOMODULE_DESCRIPTOR SpeakerHpModulesWaveFilter[] =
+{
+ { // 0
+ &AudioModule0Id, // class id.
+ &NULL_GUID, // generic, mode independent.
+ L"Generic system module",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE0_MAJOR,
+ AUDIOMODULE0_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE0_CONTEXT),
+ AudioModule0_InitClass,
+ AudioModule0_InitInstance,
+ AudioModule0_Cleanup,
+ AudioModule0_Handler
+ },
+ { // 1
+ &AudioModule1Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_MOVIE,
+ L"Speaker HP endpoint, EQ effect module, Movie mode",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE1_MAJOR,
+ AUDIOMODULE1_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE1_CONTEXT),
+ AudioModule1_InitClass,
+ AudioModule1_InitInstance,
+ AudioModule1_Cleanup,
+ AudioModule1_Handler
+ },
+ { // 2
+ &AudioModule2Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
+ L"Speaker HP endpoint, Echo Cancellation effect module, Default mode",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE2_MAJOR,
+ AUDIOMODULE2_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE2_CONTEXT),
+ AudioModule2_InitClass,
+ AudioModule2_InitInstance,
+ AudioModule2_Cleanup,
+ AudioModule2_Handler
}
};
+//
+// Audio module notification device id.
+// NOTE: do not use this guid for real driver, generate a new one.
+//
+const GUID SpeakerHpModuleNotificationDeviceId =
+{0x3A66BE17,0x5440,0x48E7,0x83,0x76,0xB7,0x5A,0x0B,0x1A,0x92,0x2D};
+
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpWaveFilter, PropertiesSpeakerHpWaveFilter);
//=============================================================================
diff --git a/audio/sysvad/EndpointsCommon/speakerwavtable.h b/audio/sysvad/EndpointsCommon/speakerwavtable.h
index cb2c2481..94f7863b 100644
--- a/audio/sysvad/EndpointsCommon/speakerwavtable.h
+++ b/audio/sysvad/EndpointsCommon/speakerwavtable.h
@@ -16,6 +16,8 @@ Abstract:
#define _SYSVAD_SPEAKERWAVTABLE_H_
#include "SysVadShared.h"
+#include "AudioModule0.h"
+#include "AudioModule1.h"
// To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM)
@@ -581,6 +583,33 @@ PKSDATARANGE SpeakerPinDataRangePointersBridge[] =
//=============================================================================
static
+PCPROPERTY_ITEM PropertiesSpeakerHostPin[] =
+{
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHostPin, PropertiesSpeakerHostPin);
+
+//=============================================================================
+
+static
PCPROPERTY_ITEM PropertiesSpeakerOffloadPin[] =
{
{
@@ -594,7 +623,25 @@ PCPROPERTY_ITEM PropertiesSpeakerOffloadPin[] =
KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties
KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_OffloadPin
- }
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
};
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerOffloadPin, PropertiesSpeakerOffloadPin);
@@ -608,7 +655,7 @@ PCPIN_DESCRIPTOR SpeakerWaveMiniportPins[] =
SPEAKER_MAX_INPUT_SYSTEM_STREAMS,
SPEAKER_MAX_INPUT_SYSTEM_STREAMS,
0,
- NULL,
+ &AutomationSpeakerHostPin, // AutomationTable
{
0,
NULL,
@@ -730,9 +777,84 @@ PCPROPERTY_ITEM PropertiesSpeakerWaveFilter[] =
KSPROPERTY_SYSVAD_DEFAULTSTREAMEFFECTS,
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+};
+
+//
+// Endpoint audio module list.
+//
+static
+AUDIOMODULE_DESCRIPTOR SpeakerModulesWaveFilter[] =
+{
+ { // 0
+ &AudioModule0Id, // class id.
+ &NULL_GUID, // generic, mode independent.
+ L"Generic system module",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE0_MAJOR,
+ AUDIOMODULE0_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE0_CONTEXT),
+ AudioModule0_InitClass,
+ AudioModule0_InitInstance,
+ AudioModule0_Cleanup,
+ AudioModule0_Handler
+ },
+ { // 1
+ &AudioModule1Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_MOVIE,
+ L"Speaker endpoint, EQ effect module, Movie mode",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE1_MAJOR,
+ AUDIOMODULE1_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE1_CONTEXT),
+ AudioModule1_InitClass,
+ AudioModule1_InitInstance,
+ AudioModule1_Cleanup,
+ AudioModule1_Handler
+ },
+ { // 2
+ &AudioModule1Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
+ L"Speaker endpoint, EQ effect module, Default mode",
+ AUDIOMODULE_INSTANCE_ID(1,0),
+ AUDIOMODULE1_MAJOR,
+ AUDIOMODULE1_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE1_CONTEXT),
+ AudioModule1_InitClass,
+ AudioModule1_InitInstance,
+ AudioModule1_Cleanup,
+ AudioModule1_Handler
}
};
+//
+// Audio module notification device id.
+// NOTE: do not use this guid for real driver, generate a new one.
+//
+const GUID SpeakerModuleNotificationDeviceId =
+{0xC01C987A,0x30A9,0x4DB7,0x8D,0x69,0x69,0x6C,0xFF,0x41,0xE4,0xB9};
+
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerWaveFilter, PropertiesSpeakerWaveFilter);
//=============================================================================
diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj
index fdf37a5d..fc459cfa 100644
--- a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj
+++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj
@@ -115,8 +115,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary>
+ <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>
@@ -139,8 +139,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary>
+ <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>
@@ -163,8 +163,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary>
+ <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>
@@ -187,8 +187,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreadedDLL</RuntimeLibrary>
- <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebugDLL</RuntimeLibrary>
+ <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>
diff --git a/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj.Filters b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj.Filters
new file mode 100644
index 00000000..f0f2001a
--- /dev/null
+++ b/audio/sysvad/KeywordDetectorAdapter/KeywordDetectorContosoAdapter.vcxproj.Filters
@@ -0,0 +1,39 @@
+<?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>{75C3E63D-04EA-4EB3-B9F1-505497C51F71}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{5E8F8D4C-2886-4109-9E78-CE5EA6DB4AC4}</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>{75D3016A-4ED8-4FAF-9817-394BE1112534}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="KeywordDetectorContosoAdapter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <Midl Include="KeywordDetectorContosoAdapter.idl">
+ <Filter>Source Files</Filter>
+ </Midl>
+ <None Include="KeywordDetectorContosoAdapter.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="KeywordDetectorContosoAdapter.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/KeywordDetectorAdapter/sources b/audio/sysvad/KeywordDetectorAdapter/sources
new file mode 100644
index 00000000..8b17ac8b
--- /dev/null
+++ b/audio/sysvad/KeywordDetectorAdapter/sources
@@ -0,0 +1,53 @@
+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
new file mode 100644
index 00000000..0ea6ab39
--- /dev/null
+++ b/audio/sysvad/Package/package.VcxProj
@@ -0,0 +1,99 @@
+<?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|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</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>
+ <ItemGroup>
+ <ProjectReference Include="..\KeywordDetectorAdapter\KeywordDetectorContosoAdapter.vcxproj">
+ <Project>{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\PhoneAudioSample\PhoneAudioSample.vcxproj">
+ <Project>{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\SwapAPO\APO\SwapAPO.vcxproj">
+ <Project>{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\SwapAPO\DelayAPO\DelayAPO.vcxproj">
+ <Project>{8851AB85-70B3-4798-A149-BA366DF9EC25}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\SwapAPO\PropPageExtensions\PropPageExt.vcxproj">
+ <Project>{D253C552-154D-49E1-820A-B2CD9D9FF13E}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\TabletAudioSample\TabletAudioSample.vcxproj">
+ <Project>{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <PropertyGroup Label="PropertySheets">
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Utility</ConfigurationType>
+ <DriverType>Package</DriverType>
+ <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+ <Configuration>Debug</Configuration>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}</ProjectGuid>
+ <SampleGuid>{E9D167E6-E633-4284-8F02-FF86DF3B6D7F}</SampleGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" 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)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup>
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <ImportToStore>False</ImportToStore>
+ <InstallMode>None</InstallMode>
+ <HardwareIdString />
+ <CommandLine />
+ <ScriptPath />
+ <DeployFiles />
+ <ScriptName />
+ <ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery>
+ <EnableVerifier>False</EnableVerifier>
+ <AllDrivers>False</AllDrivers>
+ <VerifyProjectOutput>True</VerifyProjectOutput>
+ <VerifyDrivers />
+ <VerifyFlags>133563</VerifyFlags>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/Package/package.VcxProj.Filters b/audio/sysvad/Package/package.VcxProj.Filters
new file mode 100644
index 00000000..63b75548
--- /dev/null
+++ b/audio/sysvad/Package/package.VcxProj.Filters
@@ -0,0 +1,21 @@
+<?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>{0924612D-FBA7-477E-BBB9-B3B6EA7C6B03}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{97311738-0AD8-4F7E-AC88-9C9BEAF53AEE}</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>{8DC1C4F0-C285-400E-A983-77A339891354}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{9F086F34-79D2-4FAA-87FD-C2DBEFCED0BA}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters
new file mode 100644
index 00000000..981f44c4
--- /dev/null
+++ b/audio/sysvad/PhoneAudioSample/PhoneAudioSample.vcxproj.Filters
@@ -0,0 +1,73 @@
+<?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>{6BC89CB0-7C76-439F-8D55-E3125E355A42}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{02E55FC1-89F6-4E2D-A10B-A6476FF89B86}</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>{B836489B-8D2E-41DD-A232-0D6C40243B08}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{850E3B99-7C84-454B-9E04-6A7CF9852E6C}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\adapter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\basetopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\common.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\hw.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\kshelper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\savedata.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tonegenerator.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="cellulartopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="cellularwave.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="fmtopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="fmwave.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="handsetmictopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="handsetspeakertopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="michstopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="speakerhstopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\sysvad.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/PhoneAudioSample/minipairs.h b/audio/sysvad/PhoneAudioSample/minipairs.h
index 7f2c5fb8..eaa7a240 100644
--- a/audio/sysvad/PhoneAudioSample/minipairs.h
+++ b/audio/sysvad/PhoneAudioSample/minipairs.h
@@ -185,7 +185,10 @@ ENDPOINT_MINIPAIR SpeakerMiniports =
SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes),
SpeakerTopologyPhysicalConnections,
SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections),
- ENDPOINT_OFFLOAD_SUPPORTED
+ ENDPOINT_OFFLOAD_SUPPORTED,
+ SpeakerModulesWaveFilter,
+ SIZEOF_ARRAY(SpeakerModulesWaveFilter),
+ &SpeakerModuleNotificationDeviceId,
};
/*********************************************************************
@@ -227,7 +230,8 @@ ENDPOINT_MINIPAIR SpeakerHsMiniports =
SIZEOF_ARRAY(SpeakerHsPinDeviceFormatsAndModes),
SpeakerHsTopologyPhysicalConnections,
SIZEOF_ARRAY(SpeakerHsTopologyPhysicalConnections),
- ENDPOINT_OFFLOAD_SUPPORTED
+ ENDPOINT_OFFLOAD_SUPPORTED,
+ NULL, 0, NULL, // audio module settings.
};
//
@@ -271,7 +275,8 @@ ENDPOINT_MINIPAIR MicHsMiniports =
SIZEOF_ARRAY(MicHsPinDeviceFormatsAndModes),
MicHsTopologyPhysicalConnections,
SIZEOF_ARRAY(MicHsTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS
+ ENDPOINT_NO_FLAGS,
+ NULL, 0, NULL, // audio module settings.
};
@@ -317,7 +322,8 @@ ENDPOINT_MINIPAIR MicArray1Miniports =
SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes),
MicArray1TopologyPhysicalConnections,
SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections),
- ENDPOINT_SOUNDDETECTOR_SUPPORTED
+ ENDPOINT_SOUNDDETECTOR_SUPPORTED,
+ NULL, 0, NULL, // audio module settings.
};
/*********************************************************************
@@ -370,7 +376,8 @@ ENDPOINT_MINIPAIR CellularMiniports =
SIZEOF_ARRAY(CellularPinDeviceFormatsAndModes),
CellularTopologyPhysicalConnections,
SIZEOF_ARRAY(CellularTopologyPhysicalConnections),
- ENDPOINT_CELLULAR_PROVIDER1
+ ENDPOINT_CELLULAR_PROVIDER1,
+ NULL, 0, NULL, // audio module settings.
};
@@ -401,7 +408,8 @@ ENDPOINT_MINIPAIR CellularMiniports2 =
SIZEOF_ARRAY(CellularPinDeviceFormatsAndModes),
CellularTopologyPhysicalConnections2,
SIZEOF_ARRAY(CellularTopologyPhysicalConnections2),
- ENDPOINT_CELLULAR_PROVIDER2
+ ENDPOINT_CELLULAR_PROVIDER2,
+ NULL, 0, NULL, // audio module settings.
};
/*********************************************************************
@@ -443,7 +451,8 @@ ENDPOINT_MINIPAIR HandsetSpeakerMiniports =
SIZEOF_ARRAY(HandsetSpeakerPinDeviceFormatsAndModes),
HandsetSpeakerTopologyPhysicalConnections,
SIZEOF_ARRAY(HandsetSpeakerTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS
+ ENDPOINT_NO_FLAGS,
+ NULL, 0, NULL, // audio module settings.
};
//
@@ -487,7 +496,8 @@ ENDPOINT_MINIPAIR HandsetMicMiniports =
SIZEOF_ARRAY(HandsetMicPinDeviceFormatsAndModes),
HandsetMicTopologyPhysicalConnections,
SIZEOF_ARRAY(HandsetMicTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS
+ ENDPOINT_NO_FLAGS,
+ NULL, 0, NULL, // audio module settings.
};
/*********************************************************************
@@ -527,7 +537,8 @@ ENDPOINT_MINIPAIR FmRxMiniports =
SIZEOF_ARRAY(FmRxPinDeviceFormatsAndModes),
FmRxTopologyPhysicalConnections,
SIZEOF_ARRAY(FmRxTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS
+ ENDPOINT_NO_FLAGS,
+ NULL, 0, NULL, // audio module settings.
};
//=============================================================================
diff --git a/audio/sysvad/PhoneAudioSample/sources b/audio/sysvad/PhoneAudioSample/sources
new file mode 100644
index 00000000..0d1551ce
--- /dev/null
+++ b/audio/sysvad/PhoneAudioSample/sources
@@ -0,0 +1,58 @@
+
+# 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
+#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 \
+
+# 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/SwapAPO/APO/SwapAPO.h b/audio/sysvad/SwapAPO/APO/SwapAPO.h
index 2f687c04..fc279460 100644
--- a/audio/sysvad/SwapAPO/APO/SwapAPO.h
+++ b/audio/sysvad/SwapAPO/APO/SwapAPO.h
@@ -29,13 +29,6 @@ _Analysis_mode_(_Analysis_code_type_user_driver_)
//
// {B8EC75BA-00ED-434C-A732-064A0F00788E}
DEFINE_GUID(SwapEffectId, 0xb8ec75ba, 0x00ed, 0x434c, 0xa7, 0x32, 0x06, 0x4a, 0x0f, 0x00, 0x78, 0x8e);
-// {29FBFBB5-9002-4ABC-DCBC-DD45462478C8}
-DEFINE_GUID(DelayEffectId, 0x29FBFBB5, 0x9002, 0x4ABC, 0xDC, 0xBC, 0xDD, 0x45, 0x46, 0x24, 0x78, 0xC8);
-
-// 1000 ms of delay
-#define HNS_DELAY HNS_PER_SECOND
-
-#define FRAMES_FROM_HNS(hns) (ULONG)(1.0 * hns / HNS_PER_SECOND * GetFramesPerSecond() + 0.5)
LONG GetCurrentEffectsSetting(IPropertyStore* properties, PROPERTYKEY pkeyEnable, GUID processingMode);
@@ -59,9 +52,6 @@ public:
, m_hEffectsChangedEvent(NULL)
, m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT)
, m_fEnableSwapMFX(FALSE)
- , m_fEnableDelayMFX(FALSE)
- , m_nDelayFrames(0)
- , m_iDelayIndex(0)
{
m_pf32Coefficients = NULL;
}
@@ -141,7 +131,6 @@ public:
public:
LONG m_fEnableSwapMFX;
- LONG m_fEnableDelayMFX;
GUID m_AudioProcessingMode;
CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties;
CComPtr<IMMDeviceEnumerator> m_spEnumerator;
@@ -150,10 +139,6 @@ public:
// Locked memory
FLOAT32 *m_pf32Coefficients;
- CComHeapPtr<FLOAT32> m_pf32DelayBuffer;
- UINT32 m_nDelayFrames;
- UINT32 m_iDelayIndex;
-
private:
CCriticalSection m_EffectsLock;
HANDLE m_hEffectsChangedEvent;
@@ -182,8 +167,6 @@ public:
, m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT)
, m_fEnableSwapSFX(FALSE)
, m_fEnableDelaySFX(FALSE)
- , m_nDelayFrames(0)
- , m_iDelayIndex(0)
{
}
@@ -255,10 +238,6 @@ public:
CCriticalSection m_EffectsLock;
HANDLE m_hEffectsChangedEvent;
-
- CComHeapPtr<FLOAT32> m_pf32DelayBuffer;
- UINT32 m_nDelayFrames;
- UINT32 m_iDelayIndex;
};
#pragma AVRT_VTABLES_END
@@ -285,22 +264,6 @@ void ProcessSwapScale(
FLOAT32 *pf32Coefficients );
//
-// Declaration of the ProcessDelay routine.
-//
-void ProcessDelay(
- _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame)
- FLOAT32 *pf32OutputFrames,
- _In_reads_(u32ValidFrameCount * u32SamplesPerFrame)
- const FLOAT32 *pf32InputFrames,
- UINT32 u32ValidFrameCount,
- UINT32 u32SamplesPerFrame,
- _Inout_updates_(u32DelayFrames * u32SamplesPerFrame)
- FLOAT32 *pf32DelayBuffer,
- UINT32 u32DelayFrames,
- _Inout_
- UINT32 *pu32DelayIndex );
-
-//
// Convenience methods
//
diff --git a/audio/sysvad/SwapAPO/APO/SwapAPO.vcxproj.Filters b/audio/sysvad/SwapAPO/APO/SwapAPO.vcxproj.Filters
new file mode 100644
index 00000000..7cb395b8
--- /dev/null
+++ b/audio/sysvad/SwapAPO/APO/SwapAPO.vcxproj.Filters
@@ -0,0 +1,45 @@
+<?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>{296F0C2A-85AF-4624-97D4-6D3251998382}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{655A91B5-15BB-4151-B3B5-8185B5FA1ABB}</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>{A9DFA5D3-3035-416E-BBD8-8D0745973136}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Swap.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SwapAPODll.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SwapAPOMFX.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SwapAPOSFX.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <Midl Include="SwapAPODll.idl">
+ <Filter>Source Files</Filter>
+ </Midl>
+ <Midl Include="SwapAPOInterface.idl">
+ <Filter>Source Files</Filter>
+ </Midl>
+ <None Include="SwapAPODll.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="SwapAPODll.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/SwapAPO/APO/makefile b/audio/sysvad/SwapAPO/APO/makefile
new file mode 100644
index 00000000..c7837f4f
--- /dev/null
+++ b/audio/sysvad/SwapAPO/APO/makefile
@@ -0,0 +1,36 @@
+#############################################################################
+#
+# 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/SwapAPO/APO/sources b/audio/sysvad/SwapAPO/APO/sources
new file mode 100644
index 00000000..7baf3745
--- /dev/null
+++ b/audio/sysvad/SwapAPO/APO/sources
@@ -0,0 +1,13 @@
+!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/SwapAPO/APO/swap.cpp b/audio/sysvad/SwapAPO/APO/swap.cpp
index 0efe23f7..6fa39fa3 100644
--- a/audio/sysvad/SwapAPO/APO/swap.cpp
+++ b/audio/sysvad/SwapAPO/APO/swap.cpp
@@ -112,72 +112,3 @@ void ProcessSwapScale(
}
}
#pragma AVRT_CODE_END
-
-
-#pragma AVRT_CODE_BEGIN
-void ProcessDelay(
- _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame)
- FLOAT32 *pf32OutputFrames,
- _In_reads_(u32ValidFrameCount * u32SamplesPerFrame)
- const FLOAT32 *pf32InputFrames,
- UINT32 u32ValidFrameCount,
- UINT32 u32SamplesPerFrame,
- _Inout_updates_(u32DelayFrames * u32SamplesPerFrame)
- FLOAT32 *pf32DelayBuffer,
- UINT32 u32DelayFrames,
- _Inout_
- UINT32 *pu32DelayIndex )
-{
- ASSERT_REALTIME();
- ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) );
- ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32OutputFrames) );
-
- if (u32DelayFrames == 0)
- {
- CopyFrames( pf32OutputFrames,
- pf32InputFrames,
- u32ValidFrameCount,
- u32SamplesPerFrame );
- }
- else
- {
-
- // Invariants:
- // 0 <= (*pu32DelayIndex) < u32DelayFrames
- // pf32OutputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is writable
- // pf32InputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is readable
- while (u32ValidFrameCount > 0)
- {
- // copy either the rest of the input/output buffer,
- // or the rest of the delay buffer,
- // whichever is smaller
- UINT32 framesToCopy = min(u32ValidFrameCount, u32DelayFrames - (*pu32DelayIndex));
-
- // delay => output
-#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY, "this copy to pf32OutputFrames is in-range")
- CopyFrames( pf32OutputFrames,
- &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame],
- framesToCopy,
- u32SamplesPerFrame );
-
- // input => delay
- CopyFrames( &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame],
- pf32InputFrames,
- framesToCopy,
- u32SamplesPerFrame );
-
- pf32OutputFrames += framesToCopy * u32SamplesPerFrame;
- pf32InputFrames += framesToCopy * u32SamplesPerFrame;
- u32ValidFrameCount -= framesToCopy;
-
- *pu32DelayIndex += framesToCopy;
- if (*pu32DelayIndex == u32DelayFrames)
- {
- *pu32DelayIndex = 0;
- }
- }
-
- }
-}
-#pragma AVRT_CODE_END
-
diff --git a/audio/sysvad/SwapAPO/APO/swapapomfx.cpp b/audio/sysvad/SwapAPO/APO/swapapomfx.cpp
index 43cd78fb..b4e6e95a 100644
--- a/audio/sysvad/SwapAPO/APO/swapapomfx.cpp
+++ b/audio/sysvad/SwapAPO/APO/swapapomfx.cpp
@@ -181,36 +181,17 @@ STDMETHODIMP_(void) CSwapAPOMFX::APOProcess(
m_u32SamplesPerFrame, m_pf32Coefficients );
}
- // copy to the delay buffer
- if (
- !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) &&
- m_fEnableDelayMFX
- )
+ // copy the memory only if there is an output connection, and input/output pointers are unequal
+ if ( (0 != u32NumOutputConnections) &&
+ (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) )
{
- ProcessDelay(pf32OutputFrames, pf32InputFrames,
- ppInputConnections[0]->u32ValidFrameCount,
- GetSamplesPerFrame(),
- m_pf32DelayBuffer,
- m_nDelayFrames,
- &m_iDelayIndex);
-
- // we don't try to remember silence
- ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID;
- }
- else
- {
- // copy the memory only if there is an output connection, and input/output pointers are unequal
- if ( (0 != u32NumOutputConnections) &&
- (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) )
- {
- CopyFrames( pf32OutputFrames, pf32InputFrames,
- ppInputConnections[0]->u32ValidFrameCount,
- GetSamplesPerFrame() );
- }
-
- // pass along buffer flags
- ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags;
+ CopyFrames( pf32OutputFrames, pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame() );
}
+
+ // pass along buffer flags
+ ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags;
// Set the valid frame count.
ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount;
@@ -247,15 +228,8 @@ STDMETHODIMP CSwapAPOMFX::GetLatency(HNSTIME* pTime)
IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit);
- if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
- {
- *pTime = 0;
- }
- else
- {
- *pTime = (m_fEnableDelayMFX ? HNS_DELAY : 0);
- }
-
+ *pTime = 0;
+
Exit:
return hr;
}
@@ -290,29 +264,6 @@ STDMETHODIMP CSwapAPOMFX::LockForProcess(UINT32 u32NumInputConnections,
ppInputConnections, u32NumOutputConnections, ppOutputConnections);
IF_FAILED_JUMP(hr, Exit);
- if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelayMFX)
- {
- m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY);
- m_iDelayIndex = 0;
-
- m_pf32DelayBuffer.Free();
-
- // Allocate one second's worth of audio
- //
- // This allocation is being done using CoTaskMemAlloc because the delay is very large
- // This introduces a risk of glitches if the delay buffer gets paged out
- //
- // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory
- // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important
- m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames);
- WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame());
- if (nullptr == m_pf32DelayBuffer)
- {
- hr = E_OUTOFMEMORY;
- goto Exit;
- }
- }
-
Exit:
return hr;
}
@@ -460,7 +411,6 @@ HRESULT CSwapAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData)
if (m_spAPOSystemEffectsProperties != NULL)
{
m_fEnableSwapMFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Channel_Swap_MFX, m_AudioProcessingMode);
- m_fEnableDelayMFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_MFX, m_AudioProcessingMode);
}
//
@@ -549,7 +499,6 @@ STDMETHODIMP CSwapAPOMFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEff
EffectControl list[] =
{
{ SwapEffectId, m_fEnableSwapMFX },
- { DelayEffectId, m_fEnableDelayMFX },
};
if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
@@ -713,7 +662,6 @@ HRESULT CSwapAPOMFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT
// If either the master disable or our APO's enable properties changed...
if (PK_EQUAL(key, PKEY_Endpoint_Enable_Channel_Swap_MFX) ||
- PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_MFX) ||
PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx))
{
LONG nChanges = 0;
@@ -730,7 +678,6 @@ HRESULT CSwapAPOMFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT
KeyControl controls[] =
{
{ PKEY_Endpoint_Enable_Channel_Swap_MFX, &m_fEnableSwapMFX },
- { PKEY_Endpoint_Enable_Delay_MFX, &m_fEnableDelayMFX },
};
for (int i = 0; i < ARRAYSIZE(controls); i++)
diff --git a/audio/sysvad/SwapAPO/APO/swapaposfx.cpp b/audio/sysvad/SwapAPO/APO/swapaposfx.cpp
index 32ddb7fc..c7bba1e1 100644
--- a/audio/sysvad/SwapAPO/APO/swapaposfx.cpp
+++ b/audio/sysvad/SwapAPO/APO/swapaposfx.cpp
@@ -128,38 +128,19 @@ STDMETHODIMP_(void) CSwapAPOSFX::APOProcess(
ppInputConnections[0]->u32ValidFrameCount,
m_u32SamplesPerFrame);
}
-
- // copy to the delay buffer
- if (
- !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) &&
- m_fEnableDelaySFX
- )
- {
- ProcessDelay(pf32OutputFrames, pf32InputFrames,
- ppInputConnections[0]->u32ValidFrameCount,
- GetSamplesPerFrame(),
- m_pf32DelayBuffer,
- m_nDelayFrames,
- &m_iDelayIndex);
- // we don't try to remember silence
- ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID;
- }
- else
+ // copy the memory only if there is an output connection, and input/output pointers are unequal
+ if ( (0 != u32NumOutputConnections) &&
+ (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) )
{
- // copy the memory only if there is an output connection, and input/output pointers are unequal
- if ( (0 != u32NumOutputConnections) &&
- (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) )
- {
- CopyFrames( pf32OutputFrames, pf32InputFrames,
- ppInputConnections[0]->u32ValidFrameCount,
- GetSamplesPerFrame() );
- }
-
- // pass along buffer flags
- ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags;
+ CopyFrames( pf32OutputFrames, pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame() );
}
+ // pass along buffer flags
+ ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags;
+
// Set the valid frame count.
ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount;
@@ -195,14 +176,7 @@ STDMETHODIMP CSwapAPOSFX::GetLatency(HNSTIME* pTime)
IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit);
- if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
- {
- *pTime = 0;
- }
- else
- {
- *pTime = (m_fEnableDelaySFX ? HNS_DELAY : 0);
- }
+ *pTime = 0;
Exit:
return hr;
@@ -238,30 +212,6 @@ STDMETHODIMP CSwapAPOSFX::LockForProcess(UINT32 u32NumInputConnections,
ppInputConnections, u32NumOutputConnections, ppOutputConnections);
IF_FAILED_JUMP(hr, Exit);
- if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelaySFX)
- {
- m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY);
- m_iDelayIndex = 0;
-
- m_pf32DelayBuffer.Free();
-
- // Allocate one second's worth of audio
- //
- // This allocation is being done using CoTaskMemAlloc because the delay is very large
- // This introduces a risk of glitches if the delay buffer gets paged out
- //
- // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory
- // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important
- m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames);
-
- WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame());
- if (nullptr == m_pf32DelayBuffer)
- {
- hr = E_OUTOFMEMORY;
- goto Exit;
- }
- }
-
Exit:
return hr;
}
@@ -417,7 +367,6 @@ HRESULT CSwapAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData)
if (m_spAPOSystemEffectsProperties != NULL)
{
m_fEnableSwapSFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Channel_Swap_SFX, m_AudioProcessingMode);
- m_fEnableDelaySFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_SFX, m_AudioProcessingMode);
}
//
@@ -508,7 +457,6 @@ STDMETHODIMP CSwapAPOSFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEff
EffectControl list[] =
{
{ SwapEffectId, m_fEnableSwapSFX },
- { DelayEffectId, m_fEnableDelaySFX },
};
if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
@@ -591,7 +539,6 @@ HRESULT CSwapAPOSFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT
// If either the master disable or our APO's enable properties changed...
if (PK_EQUAL(key, PKEY_Endpoint_Enable_Channel_Swap_SFX) ||
- PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_SFX) ||
PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx))
{
LONG nChanges = 0;
@@ -608,7 +555,6 @@ HRESULT CSwapAPOSFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERT
KeyControl controls[] =
{
{ PKEY_Endpoint_Enable_Channel_Swap_SFX, &m_fEnableSwapSFX },
- { PKEY_Endpoint_Enable_Delay_SFX, &m_fEnableDelaySFX },
};
for (int i = 0; i < ARRAYSIZE(controls); i++)
diff --git a/audio/sysvad/SwapAPO/DelayAPO/Delay.cpp b/audio/sysvad/SwapAPO/DelayAPO/Delay.cpp
new file mode 100644
index 00000000..721de3ef
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/Delay.cpp
@@ -0,0 +1,112 @@
+//
+// Delay.cpp -- Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Description:
+//
+// Implementation of ProcessDelay
+//
+#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 "DelayAPO.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 CopyFrames(
+ _Out_writes_(u32FrameCount * u32SamplesPerFrame)
+ FLOAT32 *pf32OutFrames,
+ _In_reads_(u32FrameCount * u32SamplesPerFrame)
+ const FLOAT32 *pf32InFrames,
+ UINT32 u32FrameCount,
+ UINT32 u32SamplesPerFrame )
+{
+ CopyMemory(pf32OutFrames, pf32InFrames, sizeof(FLOAT32) * u32FrameCount * u32SamplesPerFrame);
+}
+#pragma AVRT_CODE_END
+
+#pragma AVRT_CODE_BEGIN
+void ProcessDelay(
+ _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame)
+ FLOAT32 *pf32OutputFrames,
+ _In_reads_(u32ValidFrameCount * u32SamplesPerFrame)
+ const FLOAT32 *pf32InputFrames,
+ UINT32 u32ValidFrameCount,
+ UINT32 u32SamplesPerFrame,
+ _Inout_updates_(u32DelayFrames * u32SamplesPerFrame)
+ FLOAT32 *pf32DelayBuffer,
+ UINT32 u32DelayFrames,
+ _Inout_
+ UINT32 *pu32DelayIndex )
+{
+ ASSERT_REALTIME();
+ ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) );
+ ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32OutputFrames) );
+
+ if (u32DelayFrames == 0)
+ {
+ CopyFrames( pf32OutputFrames,
+ pf32InputFrames,
+ u32ValidFrameCount,
+ u32SamplesPerFrame );
+ }
+ else
+ {
+
+ // Invariants:
+ // 0 <= (*pu32DelayIndex) < u32DelayFrames
+ // pf32OutputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is writable
+ // pf32InputFrames[0 ... u32ValidFrameCount * u32SamplesPerFrame - 1] is readable
+ while (u32ValidFrameCount > 0)
+ {
+ // copy either the rest of the input/output buffer,
+ // or the rest of the delay buffer,
+ // whichever is smaller
+ UINT32 framesToCopy = min(u32ValidFrameCount, u32DelayFrames - (*pu32DelayIndex));
+
+ // delay => output
+#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY, "this copy to pf32OutputFrames is in-range")
+ CopyFrames( pf32OutputFrames,
+ &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame],
+ framesToCopy,
+ u32SamplesPerFrame );
+
+ // input => delay
+ CopyFrames( &pf32DelayBuffer[(*pu32DelayIndex) * u32SamplesPerFrame],
+ pf32InputFrames,
+ framesToCopy,
+ u32SamplesPerFrame );
+
+ pf32OutputFrames += framesToCopy * u32SamplesPerFrame;
+ pf32InputFrames += framesToCopy * u32SamplesPerFrame;
+ u32ValidFrameCount -= framesToCopy;
+
+ *pu32DelayIndex += framesToCopy;
+ if (*pu32DelayIndex == u32DelayFrames)
+ {
+ *pu32DelayIndex = 0;
+ }
+ }
+
+ }
+}
+#pragma AVRT_CODE_END
+
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.h b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.h
new file mode 100644
index 00000000..e59fccf7
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.h
@@ -0,0 +1,294 @@
+//
+// DelayAPO.h -- Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Description:
+//
+// Declaration of the CDelayAPO class.
+//
+
+#pragma once
+
+#include <audioenginebaseapo.h>
+#include <BaseAudioProcessingObject.h>
+#include <DelayAPOInterface.h>
+#include <DelayAPODll.h>
+
+#include <commonmacros.h>
+#include <devicetopology.h>
+
+_Analysis_mode_(_Analysis_code_type_user_driver_)
+
+#define PK_EQUAL(x, y) ((x.fmtid == y.fmtid) && (x.pid == y.pid))
+
+//
+// Define a GUID identifying the type of this APO's custom effect.
+//
+// APOs generally should not define new GUIDs for types of effects and instead
+// should use predefined effect types. Only define a new GUID if the effect is
+// truly very different from all predefined types of effects.
+//
+// {29FBFBB5-9002-4ABC-DCBC-DD45462478C8}
+DEFINE_GUID(DelayEffectId, 0x29FBFBB5, 0x9002, 0x4ABC, 0xDC, 0xBC, 0xDD, 0x45, 0x46, 0x24, 0x78, 0xC8);
+
+// 1000 ms of delay
+#define HNS_DELAY HNS_PER_SECOND
+
+#define FRAMES_FROM_HNS(hns) (ULONG)(1.0 * hns / HNS_PER_SECOND * GetFramesPerSecond() + 0.5)
+
+LONG GetCurrentEffectsSetting(IPropertyStore* properties, PROPERTYKEY pkeyEnable, GUID processingMode);
+
+#pragma AVRT_VTABLES_BEGIN
+// Delay APO class - MFX
+class CDelayAPOMFX :
+ public CComObjectRootEx<CComMultiThreadModel>,
+ public CComCoClass<CDelayAPOMFX, &CLSID_DelayAPOMFX>,
+ public CBaseAudioProcessingObject,
+ public IMMNotificationClient,
+ public IAudioSystemEffects2,
+ // IAudioSystemEffectsCustomFormats may be optionally supported
+ // by APOs that attach directly to the connector in the DEFAULT mode streaming graph
+ public IAudioSystemEffectsCustomFormats,
+ public IDelayAPOMFX
+{
+public:
+ // constructor
+ CDelayAPOMFX()
+ : CBaseAudioProcessingObject(sm_RegProperties)
+ , m_hEffectsChangedEvent(NULL)
+ , m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT)
+ , m_fEnableDelayMFX(FALSE)
+ , m_nDelayFrames(0)
+ , m_iDelayIndex(0)
+ {
+ m_pf32Coefficients = NULL;
+ }
+
+ virtual ~CDelayAPOMFX(); // destructor
+
+DECLARE_REGISTRY_RESOURCEID(IDR_DELAYAPOMFX)
+
+BEGIN_COM_MAP(CDelayAPOMFX)
+ COM_INTERFACE_ENTRY(IDelayAPOMFX)
+ COM_INTERFACE_ENTRY(IAudioSystemEffects)
+ COM_INTERFACE_ENTRY(IAudioSystemEffects2)
+ // IAudioSystemEffectsCustomFormats may be optionally supported
+ // by APOs that attach directly to the connector in the DEFAULT mode streaming graph
+ COM_INTERFACE_ENTRY(IAudioSystemEffectsCustomFormats)
+ 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);
+
+ virtual HRESULT ValidateAndCacheConnectionInfo(
+ UINT32 u32NumInputConnections,
+ APO_CONNECTION_DESCRIPTOR** ppInputConnections,
+ UINT32 u32NumOutputConnections,
+ APO_CONNECTION_DESCRIPTOR** ppOutputConnections);
+
+ // 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);
+
+ // IAudioSystemEffectsCustomFormats
+ // This interface may be optionally supported by APOs that attach directly to the connector in the DEFAULT mode streaming graph
+ STDMETHODIMP GetFormatCount(UINT* pcFormats);
+ STDMETHODIMP GetFormat(UINT nFormat, IAudioMediaType** ppFormat);
+ STDMETHODIMP GetFormatRepresentation(UINT nFormat, _Outptr_ LPWSTR* ppwstrFormatRep);
+
+public:
+ LONG m_fEnableDelayMFX;
+ GUID m_AudioProcessingMode;
+ CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties;
+ CComPtr<IMMDeviceEnumerator> m_spEnumerator;
+ static const CRegAPOProperties<1> sm_RegProperties; // registration properties
+
+ // Locked memory
+ FLOAT32 *m_pf32Coefficients;
+
+ CComHeapPtr<FLOAT32> m_pf32DelayBuffer;
+ UINT32 m_nDelayFrames;
+ UINT32 m_iDelayIndex;
+
+private:
+ CCriticalSection m_EffectsLock;
+ HANDLE m_hEffectsChangedEvent;
+
+ HRESULT ProprietaryCommunicationWithDriver(APOInitSystemEffects2 *_pAPOSysFxInit2);
+
+};
+#pragma AVRT_VTABLES_END
+
+
+#pragma AVRT_VTABLES_BEGIN
+// Delay APO class - SFX
+class CDelayAPOSFX :
+ public CComObjectRootEx<CComMultiThreadModel>,
+ public CComCoClass<CDelayAPOSFX, &CLSID_DelayAPOSFX>,
+ public CBaseAudioProcessingObject,
+ public IMMNotificationClient,
+ public IAudioSystemEffects2,
+ public IDelayAPOSFX
+{
+public:
+ // constructor
+ CDelayAPOSFX()
+ : CBaseAudioProcessingObject(sm_RegProperties)
+ , m_hEffectsChangedEvent(NULL)
+ , m_AudioProcessingMode(AUDIO_SIGNALPROCESSINGMODE_DEFAULT)
+ , m_fEnableDelaySFX(FALSE)
+ , m_nDelayFrames(0)
+ , m_iDelayIndex(0)
+ {
+ }
+
+ virtual ~CDelayAPOSFX(); // destructor
+
+DECLARE_REGISTRY_RESOURCEID(IDR_DELAYAPOSFX)
+
+BEGIN_COM_MAP(CDelayAPOSFX)
+ COM_INTERFACE_ENTRY(IDelayAPOSFX)
+ 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);
+
+ // 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);
+
+public:
+ LONG m_fEnableDelaySFX;
+ GUID m_AudioProcessingMode;
+ CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties;
+ CComPtr<IMMDeviceEnumerator> m_spEnumerator;
+ static const CRegAPOProperties<1> sm_RegProperties; // registration properties
+
+ CCriticalSection m_EffectsLock;
+ HANDLE m_hEffectsChangedEvent;
+
+ CComHeapPtr<FLOAT32> m_pf32DelayBuffer;
+ UINT32 m_nDelayFrames;
+ UINT32 m_iDelayIndex;
+};
+#pragma AVRT_VTABLES_END
+
+OBJECT_ENTRY_AUTO(__uuidof(DelayAPOMFX), CDelayAPOMFX)
+OBJECT_ENTRY_AUTO(__uuidof(DelayAPOSFX), CDelayAPOSFX)
+
+//
+// Declaration of the ProcessDelay routine.
+//
+void ProcessDelay(
+ _Out_writes_(u32ValidFrameCount * u32SamplesPerFrame)
+ FLOAT32 *pf32OutputFrames,
+ _In_reads_(u32ValidFrameCount * u32SamplesPerFrame)
+ const FLOAT32 *pf32InputFrames,
+ UINT32 u32ValidFrameCount,
+ UINT32 u32SamplesPerFrame,
+ _Inout_updates_(u32DelayFrames * u32SamplesPerFrame)
+ FLOAT32 *pf32DelayBuffer,
+ UINT32 u32DelayFrames,
+ _Inout_
+ UINT32 *pu32DelayIndex );
+
+//
+// Convenience methods
+//
+
+void WriteSilence(
+ _Out_writes_(u32FrameCount * u32SamplesPerFrame)
+ FLOAT32 *pf32Frames,
+ UINT32 u32FrameCount,
+ UINT32 u32SamplesPerFrame );
+
+void CopyFrames(
+ _Out_writes_(u32FrameCount * u32SamplesPerFrame)
+ FLOAT32 *pf32OutFrames,
+ _In_reads_(u32FrameCount * u32SamplesPerFrame)
+ const FLOAT32 *pf32InFrames,
+ UINT32 u32FrameCount,
+ UINT32 u32SamplesPerFrame );
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.vcxproj b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.vcxproj
new file mode 100644
index 00000000..229ce262
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPO.vcxproj
@@ -0,0 +1,250 @@
+<?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|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</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>{8851ab85-70b3-4798-a149-ba366df9ec25}</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>Desktop</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>Desktop</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>Desktop</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>Desktop</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 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 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>DelayAPO</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>DelayAPO</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>DelayAPO</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>DelayAPO</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)'=='Debug|x64'">
+ <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)'=='Debug|x64'">
+ <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>DelayAPODll.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>DelayAPODll.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>DelayAPODll.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>DelayAPODll.def</ModuleDefinitionFile>
+ <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="Delay.cpp" />
+ <ClCompile Include="DelayAPODll.cpp" />
+ <ClCompile Include="DelayAPOMFX.cpp " />
+ <ClCompile Include="DelayAPOSFX.cpp" />
+ <Midl Include="DelayAPODll.idl" />
+ <Midl Include="DelayAPOInterface.idl" />
+ <ResourceCompile Include="DelayAPODll.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/SwapAPO/DelayAPO/DelayAPODll.cpp b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.cpp
new file mode 100644
index 00000000..032c3c9d
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.cpp
@@ -0,0 +1,148 @@
+//
+// DelayAPODll.cpp -- Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Author:
+//
+// Description:
+//
+// DelayAPODll.cpp : Implementation of DLL Exports.
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlcoll.h>
+#include <atlsync.h>
+#include <mmreg.h>
+
+#include "resource.h"
+#include "DelayAPODll.h"
+#include <DelayAPO.h>
+
+#include <DelayAPODll_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[] =
+{
+ &CDelayAPOMFX::sm_RegProperties.m_Properties,
+ &CDelayAPOSFX::sm_RegProperties.m_Properties
+};
+
+// {secret}
+class CDelayAPODllModule : public CAtlDllModuleT< CDelayAPODllModule >
+{
+public :
+ DECLARE_LIBID(LIBID_DelayAPODlllib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_DELAYAPODLL, "{0A21D954-674A-4C09-806E-DB4FBE8F199C}")
+public:
+ HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw();
+ HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw();
+};
+
+// {secret}
+CDelayAPODllModule _AtlModule;
+
+
+HRESULT CDelayAPODllModule::DllRegisterServer(BOOL bRegTypeLib) throw()
+{
+ HRESULT hResult;
+ UINT32 u32APORegIndex = 0;
+ UINT32 u32APOUnregIndex = 0;
+
+ // Register all APOs implemented in this module.
+ for (u32APORegIndex = 0; u32APORegIndex < SIZEOF_ARRAY(gCoreAPOs); u32APORegIndex++)
+ {
+ hResult = RegisterAPO(gCoreAPOs[u32APORegIndex]);
+ if (FAILED(hResult))
+ {
+ goto ExitFailed;
+ }
+ }
+
+ // Register the module.
+ hResult = CAtlDllModuleT<CDelayAPODllModule>::DllRegisterServer(bRegTypeLib);
+ if (FAILED(hResult))
+ {
+ goto ExitFailed;
+ }
+
+ return hResult;
+
+ExitFailed:
+ // Unregister all registered APOs if something failed.
+ for (u32APOUnregIndex = 0; u32APOUnregIndex < u32APORegIndex; u32APOUnregIndex++)
+ {
+ ATLVERIFY(SUCCEEDED(UnregisterAPO(gCoreAPOs[u32APOUnregIndex]->clsid)));
+ }
+
+ return hResult;
+} // DllRegisterServer
+
+HRESULT CDelayAPODllModule::DllUnregisterServer(BOOL bUnRegTypeLib) throw()
+{
+ HRESULT hResult;
+ UINT32 u32APOUnregIndex = 0;
+
+ // Unregister the module.
+ hResult = CAtlDllModuleT<CDelayAPODllModule>::UnregisterServer(bUnRegTypeLib);
+ if (FAILED(hResult))
+ {
+ goto Exit;
+ }
+
+ // Unregister all the APOs that are implemented in this module.
+ for (u32APOUnregIndex = 0; u32APOUnregIndex < SIZEOF_ARRAY(gCoreAPOs); u32APOUnregIndex++)
+ {
+ hResult = UnregisterAPO(gCoreAPOs[u32APOUnregIndex]->clsid);
+ ATLASSERT(SUCCEEDED(hResult));
+ }
+
+Exit:
+ return hResult;
+} // DllUnregisterServer
+
+// {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);
+}
+
+
+// {secret}
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ HRESULT hr = _AtlModule.DllRegisterServer();
+ return hr;
+}
+
+
+// {secret}
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+ return hr;
+}
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.def b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.def
new file mode 100644
index 00000000..722ab4c4
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.def
@@ -0,0 +1,6 @@
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.idl b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.idl
new file mode 100644
index 00000000..46b4fe5b
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.idl
@@ -0,0 +1,54 @@
+//
+// DelayAPODll.idl -- Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Author:
+//
+// Description:
+//
+// DelayAPODll.idl : Definition of COM interfaces and coclasses for the DLL.
+
+import "oaidl.idl";
+import "ocidl.idl";
+import "DelayAPOInterface.idl";
+
+//-------------------------------------------------------------------------
+// DelayAPODlllib
+//
+[
+ uuid(8009693f-5bc2-42bb-86bf-82cc651f127f),
+ version(1.0)
+]
+library DelayAPODlllib
+{
+ importlib("stdole2.tlb");
+
+ // for Delay APO - MFX
+ [
+ uuid(b6c7032b-1f17-4cc6-bcdb-fd96deabc8a9)
+ ]
+ coclass DelayAPOMFX
+ {
+ interface IAudioProcessingObject;
+ interface IAudioProcessingObjectRT;
+ interface IAudioProcessingObjectConfiguration;
+ interface IMMNotificationClient;
+ interface IAudioSystemEffects;
+ [default] interface IDelayAPOMFX;
+ };
+
+ // for Delay APO - SFX
+ [
+ uuid(77802b45-a5a0-455a-8204-3dba30eee7b4)
+ ]
+ coclass DelayAPOSFX
+ {
+ interface IAudioProcessingObject;
+ interface IAudioProcessingObjectRT;
+ interface IAudioProcessingObjectConfiguration;
+ interface IMMNotificationClient;
+ interface IAudioSystemEffects;
+ [default] interface IDelayAPOSFX;
+ };
+
+
+}
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rc b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rc
new file mode 100644
index 00000000..8cdc8249
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rc
@@ -0,0 +1,24 @@
+#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 "Delay APO"
+#define VER_INTERNALNAME_STR "DELAYAPODll"
+#define VER_ORIGINALFILENAME_STR "DelayAPODll.Dll"
+#include <Common.ver>
+
+IDR_DELAYAPODLL REGISTRY "DelayAPODll.rgs"
+IDR_DELAYAPOMFX REGISTRY "DelayAPOMFX.rgs"
+IDR_DELAYAPOSFX REGISTRY "DelayAPOSFX.rgs"
+
+// ICON
+IDI_EFFECT_ICON RCDATA "DelayApo.png"
+
+#if 0
+1 TYPELIB "DelayAPODll.tlb"
+#endif
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rgs b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rgs
new file mode 100644
index 00000000..5ccba570
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPODll.rgs
@@ -0,0 +1,11 @@
+HKCR
+{
+ NoRemove AppID
+ {
+ '%APPID%' = s 'DelayAPODll'
+ 'DelayAPODll.DLL'
+ {
+ val AppID = s '%APPID%'
+ }
+ }
+}
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOInterface.idl b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOInterface.idl
new file mode 100644
index 00000000..f74cd5fb
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOInterface.idl
@@ -0,0 +1,29 @@
+//
+// DelayAPOInterface.idl -- Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Description:
+//
+// The interface and type definitions for Delay APO functionality.
+//
+import "oaidl.idl";
+import "ocidl.idl";
+import "audioenginebaseapo.idl";
+
+[
+ object,
+ uuid(4c0531b4-f2ca-4eae-80cd-020266923bc1),
+ pointer_default(unique)
+]
+interface IDelayAPOMFX : IUnknown
+{
+};
+
+[
+ object,
+ uuid(6269b338-5162-4f14-a94d-8422ee93ec13),
+ pointer_default(unique)
+]
+interface IDelayAPOSFX : IUnknown
+{
+};
+
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.cpp b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.cpp
new file mode 100644
index 00000000..5f5ad2c6
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.cpp
@@ -0,0 +1,1031 @@
+//
+// DelayAPOMFX.cpp -- Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Description:
+//
+// Implementation of CDelayAPOMFX
+//
+
+#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 "DelayAPO.h"
+#include "SysVadShared.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> CDelayAPOMFX::sm_RegProperties(
+ __uuidof(DelayAPOMFX), // clsid of this APO
+ L"CDelayAPOMFX", // friendly name of this APO
+ L"Copyright (c) Microsoft Corporation", // copyright info
+ 1, // major version #
+ 0, // minor version #
+ __uuidof(IDelayAPOMFX) // iid of primary interface
+//
+// If you need to change any of these attributes, uncomment everything up to
+// the point that you need to change something. If you need to add IIDs, uncomment
+// everything and add additional IIDs at the end.
+//
+// Enable inplace processing for this APO.
+// , DEFAULT_APOREG_FLAGS
+// , DEFAULT_APOREG_MININPUTCONNECTIONS
+// , DEFAULT_APOREG_MAXINPUTCONNECTIONS
+// , DEFAULT_APOREG_MINOUTPUTCONNECTIONS
+// , DEFAULT_APOREG_MAXOUTPUTCONNECTIONS
+// , DEFAULT_APOREG_MAXINSTANCES
+//
+ );
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// GetCurrentEffectsSetting
+// Gets the current aggregate effects-enable setting
+//
+// Parameters:
+//
+// properties - Property store holding configurable effects settings
+//
+// pkeyEnable - VT_UI4 property holding an enable/disable setting
+//
+// processingMode - Audio processing mode
+//
+// Return values:
+// LONG - true if the effect is enabled
+//
+// Remarks:
+// The routine considers the value of the specified property, the well known
+// master PKEY_AudioEndpoint_Disable_SysFx property, and the specified
+// processing mode.If the processing mode is RAW then the effect is off. If
+// PKEY_AudioEndpoint_Disable_SysFx is non-zero then the effect is off.
+//
+LONG GetCurrentEffectsSetting(IPropertyStore* properties, PROPERTYKEY pkeyEnable, GUID processingMode)
+{
+ HRESULT hr;
+ BOOL enabled;
+ PROPVARIANT var;
+
+ PropVariantInit(&var);
+
+ // Get the state of whether channel swap MFX is enabled or not.
+
+ // Check the master disable property defined by Windows
+ hr = properties->GetValue(PKEY_AudioEndpoint_Disable_SysFx, &var);
+ enabled = (SUCCEEDED(hr)) && !((var.vt == VT_UI4) && (var.ulVal != 0));
+
+ PropVariantClear(&var);
+
+ // Check the APO's enable property, defined by this APO.
+ hr = properties->GetValue(pkeyEnable, &var);
+ enabled = enabled && ((SUCCEEDED(hr)) && ((var.vt == VT_UI4) && (var.ulVal != 0)));
+
+ PropVariantClear(&var);
+
+ enabled = enabled && !IsEqualGUID(processingMode, AUDIO_SIGNALPROCESSINGMODE_RAW);
+
+ return (LONG)enabled;
+}
+
+#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) CDelayAPOMFX::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_READ_POINTER(pf32OutputFrames) );
+
+ if (BUFFER_SILENT == ppInputConnections[0]->u32BufferFlags)
+ {
+ WriteSilence( pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame() );
+ }
+
+ // copy to the delay buffer
+ if (
+ !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) &&
+ m_fEnableDelayMFX
+ )
+ {
+ ProcessDelay(pf32OutputFrames, pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame(),
+ m_pf32DelayBuffer,
+ m_nDelayFrames,
+ &m_iDelayIndex);
+
+ // we don't try to remember silence
+ ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID;
+ }
+ else
+ {
+ // copy the memory only if there is an output connection, and input/output pointers are unequal
+ if ( (0 != u32NumOutputConnections) &&
+ (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) )
+ {
+ CopyFrames( pf32OutputFrames, pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame() );
+ }
+
+ // pass along buffer flags
+ ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags;
+ }
+
+ // 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:
+//
+// Report delay added by the APO between samples given on input
+// and samples given on output.
+//
+// Parameters:
+//
+// pTime - [out] hundreds-of-nanoseconds of delay added
+//
+// Return values:
+//
+// S_OK on success, a failure code on failure
+STDMETHODIMP CDelayAPOMFX::GetLatency(HNSTIME* pTime)
+{
+ ASSERT_NONREALTIME();
+ HRESULT hr = S_OK;
+
+ IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit);
+
+ if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
+ {
+ *pTime = 0;
+ }
+ else
+ {
+ *pTime = (m_fEnableDelayMFX ? HNS_DELAY : 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 CDelayAPOMFX::LockForProcess(UINT32 u32NumInputConnections,
+ APO_CONNECTION_DESCRIPTOR** ppInputConnections,
+ UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections)
+{
+ ASSERT_NONREALTIME();
+ HRESULT hr = S_OK;
+
+ hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections,
+ ppInputConnections, u32NumOutputConnections, ppOutputConnections);
+ IF_FAILED_JUMP(hr, Exit);
+
+ if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelayMFX)
+ {
+ m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY);
+ m_iDelayIndex = 0;
+
+ m_pf32DelayBuffer.Free();
+
+ // Allocate one second's worth of audio
+ //
+ // This allocation is being done using CoTaskMemAlloc because the delay is very large
+ // This introduces a risk of glitches if the delay buffer gets paged out
+ //
+ // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory
+ // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important
+ m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames);
+ WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame());
+ if (nullptr == m_pf32DelayBuffer)
+ {
+ hr = E_OUTOFMEMORY;
+ goto 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 CDelayAPOMFX::Initialize(UINT32 cbDataSize, BYTE* pbyData)
+{
+ HRESULT hr = S_OK;
+ GUID processingMode;
+
+ 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;
+
+ // 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);
+
+ // Save the processing mode being initialized.
+ processingMode = papoSysFxInit2->AudioProcessingMode;
+
+ // There is information in the APOInitSystemEffects2 structure that could help facilitate
+ // proprietary communication between an APO instance and the KS pin that the APO is initialized on
+ // Eg, in the case that an APO is implemented as an effect proxy for the effect processing hosted inside
+ // an driver (either host CPU based or offload DSP based), the example below uses a combination of
+ // IDeviceTopology, IConnector, and IKsControl interfaces to communicate with the underlying audio driver.
+ // the following following routine demonstrates how to implement how to communicate to an audio driver from a APO.
+ ProprietaryCommunicationWithDriver(papoSysFxInit2);
+ }
+ else if (cbDataSize == sizeof(APOInitSystemEffects))
+ {
+ //
+ // Initialize for default signal processing
+ //
+ APOInitSystemEffects* papoSysFxInit = (APOInitSystemEffects*)pbyData;
+
+ // 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 = papoSysFxInit->pAPOSystemEffectsProperties;
+
+ // Assume default processing mode
+ processingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
+ }
+ else
+ {
+ // Invalid initialization size
+ hr = E_INVALIDARG;
+ goto Exit;
+ }
+
+ // Validate then save the processing mode. Note an endpoint effects APO
+ // does not depend on the mode. Windows sets the APOInitSystemEffects2
+ // AudioProcessingMode member to GUID_NULL for an endpoint effects APO.
+ IF_TRUE_ACTION_JUMP((processingMode != AUDIO_SIGNALPROCESSINGMODE_DEFAULT &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_RAW &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit);
+ m_AudioProcessingMode = processingMode;
+
+ //
+ // An APO that implements signal processing more complex than this sample
+ // would configure its processing for the processingMode determined above.
+ // If necessary, the APO would also use the IDeviceTopology and IConnector
+ // interfaces retrieved above to communicate with its counterpart audio
+ // driver to configure any additional signal processing in the driver and
+ // associated hardware.
+ //
+
+ //
+ // Get current effects settings
+ //
+ if (m_spAPOSystemEffectsProperties != NULL)
+ {
+ m_fEnableDelayMFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_MFX, m_AudioProcessingMode);
+ }
+
+ //
+ // 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;
+}
+
+//-------------------------------------------------------------------------
+//
+// GetEffectsList
+//
+// Retrieves the list of signal processing effects currently active and
+// stores an event to be signaled if the list changes.
+//
+// Parameters
+//
+// ppEffectsIds - returns a pointer to a list of GUIDs each identifying a
+// class of effect. The caller is responsible for freeing this memory by
+// calling CoTaskMemFree.
+//
+// pcEffects - returns a count of GUIDs in the list.
+//
+// Event - passes an event handle. The APO signals this event when the list
+// of effects changes from the list returned from this function. The APO
+// uses this event until either this function is called again or the APO
+// is destroyed. The passed handle may be NULL. In this case, the APO
+// stops using any previous handle and does not signal an event.
+//
+// Remarks
+//
+// An APO imlements this method to allow Windows to discover the current
+// effects applied by the APO. The list of effects may depend on what signal
+// processing mode the APO initialized (see AudioProcessingMode in the
+// APOInitSystemEffects2 structure) as well as any end user configuration.
+//
+// If there are no effects then the function still succeeds, ppEffectsIds
+// returns a NULL pointer, and pcEffects returns a count of 0.
+//
+STDMETHODIMP CDelayAPOMFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event)
+{
+ HRESULT hr;
+ BOOL effectsLocked = FALSE;
+ UINT cEffects = 0;
+
+ IF_TRUE_ACTION_JUMP(ppEffectsIds == NULL, hr = E_POINTER, Exit);
+ IF_TRUE_ACTION_JUMP(pcEffects == NULL, hr = E_POINTER, Exit);
+
+ // Synchronize access to the effects list and effects changed event
+ m_EffectsLock.Enter();
+ effectsLocked = TRUE;
+
+ // Always close existing effects change event handle
+ if (m_hEffectsChangedEvent != NULL)
+ {
+ CloseHandle(m_hEffectsChangedEvent);
+ m_hEffectsChangedEvent = NULL;
+ }
+
+ // If an event handle was specified, save it here (duplicated to control lifetime)
+ if (Event != NULL)
+ {
+ if (!DuplicateHandle(GetCurrentProcess(), Event, GetCurrentProcess(), &m_hEffectsChangedEvent, EVENT_MODIFY_STATE, FALSE, 0))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit;
+ }
+ }
+
+ // naked scope to force the initialization of list[] to be after we enter the critical section
+ {
+ struct EffectControl
+ {
+ GUID effect;
+ BOOL control;
+ };
+
+ EffectControl list[] =
+ {
+ { DelayEffectId, m_fEnableDelayMFX },
+ };
+
+ if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
+ {
+ // count the active effects
+ for (UINT i = 0; i < ARRAYSIZE(list); i++)
+ {
+ if (list[i].control)
+ {
+ cEffects++;
+ }
+ }
+ }
+
+ if (0 == cEffects)
+ {
+ *ppEffectsIds = NULL;
+ *pcEffects = 0;
+ }
+ else
+ {
+ GUID *pEffectsIds = (LPGUID)CoTaskMemAlloc(sizeof(GUID) * cEffects);
+ if (pEffectsIds == nullptr)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // pick up the active effects
+ UINT j = 0;
+ for (UINT i = 0; i < ARRAYSIZE(list); i++)
+ {
+ if (list[i].control)
+ {
+ pEffectsIds[j++] = list[i].effect;
+ }
+ }
+
+ *ppEffectsIds = pEffectsIds;
+ *pcEffects = cEffects;
+ }
+
+ hr = S_OK;
+ }
+
+Exit:
+ if (effectsLocked)
+ {
+ m_EffectsLock.Leave();
+ }
+ return hr;
+}
+
+HRESULT CDelayAPOMFX::ProprietaryCommunicationWithDriver(APOInitSystemEffects2 *_pAPOSysFxInit2)
+{
+ HRESULT hr = S_OK;
+ CComPtr<IMMDevice> spMyDevice;
+ CComPtr<IDeviceTopology> spMyDeviceTopology;
+ CComPtr<IConnector> spMyConnector;
+ CComPtr<IPart> spMyConnectorPart;
+ CComPtr<IKsControl> spKsControl;
+ UINT uKsPinId = 0;
+ UINT myPartId = 0;
+
+ ULONG ulBytesReturned = 0;
+ CComHeapPtr<KSMULTIPLE_ITEM> spKsMultipleItem;
+ KSP_PIN ksPin = {0};
+
+ UINT nSoftwareIoDeviceInCollection = 0 ;
+ UINT nSoftwareIoConnectorIndex = 0 ;
+
+ nSoftwareIoDeviceInCollection = _pAPOSysFxInit2->nSoftwareIoDeviceInCollection;
+ nSoftwareIoConnectorIndex = _pAPOSysFxInit2->nSoftwareIoConnectorIndex;
+
+ // Get the target IMMDevice
+ hr = _pAPOSysFxInit2->pDeviceCollection->Item(nSoftwareIoDeviceInCollection, &spMyDevice);
+ IF_FAILED_JUMP(hr, Exit);
+
+ // Instantiate a device topology instance
+ hr = spMyDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology);
+ IF_FAILED_JUMP(hr, Exit);
+
+ // retrieve connect instance
+ hr = spMyDeviceTopology->GetConnector(nSoftwareIoConnectorIndex, &spMyConnector);
+ IF_FAILED_JUMP(hr, Exit);
+
+ // activate IKsControl on the IMMDevice
+ hr = spMyDevice->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, NULL, (void**)&spKsControl);
+ IF_FAILED_JUMP(hr, Exit);
+
+ // get KS pin id
+ hr = spMyConnector->QueryInterface(__uuidof(IPart), (void**)&spMyConnectorPart);
+ IF_FAILED_JUMP(hr, Exit);
+ hr = spMyConnectorPart->GetLocalId(&myPartId);
+ IF_FAILED_JUMP(hr, Exit);
+
+ uKsPinId = myPartId & 0x0000ffff;
+
+ ksPin.Property.Set = KSPROPSETID_SysVAD;
+ ksPin.Property.Id = KSPROPERTY_SYSVAD_DEFAULTSTREAMEFFECTS;
+ ksPin.Property.Flags = KSPROPERTY_TYPE_GET;
+ ksPin.PinId = uKsPinId;
+
+ // First, get size of array returned by driver
+ hr = spKsControl->KsProperty( &ksPin.Property,
+ sizeof(KSP_PIN),
+ NULL,
+ 0,
+ &ulBytesReturned );
+ IF_FAILED_JUMP(hr, Exit);
+
+ if( !spKsMultipleItem.AllocateBytes(ulBytesReturned) )
+ {
+ hr = E_OUTOFMEMORY;
+ IF_FAILED_JUMP(hr, Exit);
+ }
+
+ // Second, now get the active effects from the driver
+ hr = spKsControl->KsProperty( &ksPin.Property,
+ sizeof(KSP_PIN),
+ spKsMultipleItem,
+ ulBytesReturned,
+ &ulBytesReturned );
+ IF_FAILED_JUMP(hr, Exit);
+
+ // Upon successful return, effect guids could be found in the memory following (spKsMultipleItem.m_pData + 1)
+ // and effectcount could be found in spKsMultipleItem->Count;
+
+Exit:
+ return hr;
+}
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Implementation of IMMNotificationClient::OnPropertyValueChanged
+//
+// Parameters:
+//
+// pwstrDeviceId - [in] the id of the device whose property has changed
+// key - [in] the property that changed
+//
+// Return values:
+//
+// Ignored by caller
+//
+// Remarks:
+//
+// This method is called asynchronously. No UI work should be done here.
+//
+HRESULT CDelayAPOMFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key)
+{
+ HRESULT hr = S_OK;
+
+ UNREFERENCED_PARAMETER(pwstrDeviceId);
+
+ if (!m_spAPOSystemEffectsProperties)
+ {
+ return hr;
+ }
+
+ // If either the master disable or our APO's enable properties changed...
+ if (PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_MFX) ||
+ PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx))
+ {
+ LONG nChanges = 0;
+
+ // Synchronize access to the effects list and effects changed event
+ m_EffectsLock.Enter();
+
+ struct KeyControl
+ {
+ PROPERTYKEY key;
+ LONG *value;
+ };
+
+ KeyControl controls[] =
+ {
+ { PKEY_Endpoint_Enable_Delay_MFX, &m_fEnableDelayMFX },
+ };
+
+ for (int i = 0; i < ARRAYSIZE(controls); i++)
+ {
+ LONG fOldValue;
+ LONG fNewValue = true;
+
+ // Get the state of whether channel swap MFX is enabled or not
+ fNewValue = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, controls[i].key, m_AudioProcessingMode);
+
+ // Delay in the new setting
+ fOldValue = InterlockedExchange(controls[i].value, fNewValue);
+
+ if (fNewValue != fOldValue)
+ {
+ nChanges++;
+ }
+ }
+
+ // If anything changed and a change event handle exists
+ if ((nChanges > 0) && (m_hEffectsChangedEvent != NULL))
+ {
+ SetEvent(m_hEffectsChangedEvent);
+ }
+
+ m_EffectsLock.Leave();
+ }
+
+ return hr;
+}
+
+//-------------------------------------------------------------------------
+// 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.
+//
+CDelayAPOMFX::~CDelayAPOMFX(void)
+{
+ if (m_bIsInitialized)
+ {
+ //
+ // unregister for callbacks
+ //
+ if (m_spEnumerator != NULL)
+ {
+ m_spEnumerator->UnregisterEndpointNotificationCallback(this);
+ }
+ }
+
+ if (m_hEffectsChangedEvent != NULL)
+ {
+ CloseHandle(m_hEffectsChangedEvent);
+ }
+
+ // Free locked memory allocations
+ if (NULL != m_pf32Coefficients)
+ {
+ AERT_Free(m_pf32Coefficients);
+ m_pf32Coefficients = NULL;
+ }
+} // ~CDelayAPOMFX
+
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Validates input/output format pair during LockForProcess.
+//
+// Parameters:
+//
+// u32NumInputConnections - [in] number of input connections attached to this APO
+// ppInputConnections - [in] format of each input connection attached to this APO
+// u32NumOutputConnections - [in] number of output connections attached to this APO
+// ppOutputConnections - [in] format of each output connection attached to this APO
+//
+// Return values:
+//
+// S_OK Connections are valid.
+//
+// See Also:
+//
+// CBaseAudioProcessingObject::LockForProcess
+//
+// Remarks:
+//
+// This method is an internal call that is called by the default implementation of
+// CBaseAudioProcessingObject::LockForProcess(). This is called after the connections
+// are validated for simple conformance to the APO's registration properties. It may be
+// used to verify that the APO is initialized properly and that the connections that are passed
+// agree with the data used for initialization. Any failure code passed back from this
+// function will get returned by LockForProcess, and cause it to fail.
+//
+// By default, this routine just ASSERTS and returns S_OK.
+//
+HRESULT CDelayAPOMFX::ValidateAndCacheConnectionInfo(UINT32 u32NumInputConnections,
+ APO_CONNECTION_DESCRIPTOR** ppInputConnections,
+ UINT32 u32NumOutputConnections,
+ APO_CONNECTION_DESCRIPTOR** ppOutputConnections)
+{
+ ASSERT_NONREALTIME();
+ HRESULT hResult;
+ CComPtr<IAudioMediaType> pFormat;
+ UNCOMPRESSEDAUDIOFORMAT UncompInputFormat, UncompOutputFormat;
+ FLOAT32 f32InverseChannelCount;
+
+ UNREFERENCED_PARAMETER(u32NumInputConnections);
+ UNREFERENCED_PARAMETER(u32NumOutputConnections);
+
+ _ASSERTE(!m_bIsLocked);
+ _ASSERTE(((0 == u32NumInputConnections) || (NULL != ppInputConnections)) &&
+ ((0 == u32NumOutputConnections) || (NULL != ppOutputConnections)));
+
+ EnterCriticalSection(&m_CritSec);
+
+ // get the uncompressed formats and channel masks
+ hResult = ppInputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompInputFormat);
+ IF_FAILED_JUMP(hResult, Exit);
+
+ hResult = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompOutputFormat);
+ IF_FAILED_JUMP(hResult, Exit);
+
+ // Since we haven't overridden the IsIn{Out}putFormatSupported APIs in this example, this APO should
+ // always have input channel count == output channel count. The sampling rates should also be eqaul,
+ // and formats 32-bit float.
+ _ASSERTE(UncompOutputFormat.fFramesPerSecond == UncompInputFormat.fFramesPerSecond);
+ _ASSERTE(UncompOutputFormat. dwSamplesPerFrame == UncompInputFormat.dwSamplesPerFrame);
+
+ // Allocate some locked memory. We will use these as scaling coefficients during APOProcess->ProcessDelayScale
+ hResult = AERT_Allocate(sizeof(FLOAT32)*m_u32SamplesPerFrame, (void**)&m_pf32Coefficients);
+ IF_FAILED_JUMP(hResult, Exit);
+
+ // Set scalars to decrease volume from 1.0 to 1.0/N where N is the number of channels
+ // starting with the first channel.
+ f32InverseChannelCount = 1.0f/m_u32SamplesPerFrame;
+ for (UINT16 u16Index=0; u16Index<m_u32SamplesPerFrame; u16Index++)
+ {
+ m_pf32Coefficients[u16Index] = 1.0f - (FLOAT32)(f32InverseChannelCount)*u16Index;
+ }
+
+
+Exit:
+ LeaveCriticalSection(&m_CritSec);
+ return hResult;}
+
+// ----------------------------------------------------------------------
+// ----------------------------------------------------------------------
+// IAudioSystemEffectsCustomFormats implementation
+
+//
+// For demonstration purposes we will add 44.1KHz, 16-bit stereo and 48KHz, 16-bit
+// stereo formats. These formats should already be available in mmsys.cpl. We
+// embellish the labels to make it obvious that these formats are coming from
+// the APO.
+//
+
+//
+// Note that the IAudioSystemEffectsCustomFormats interface, if present, is invoked only on APOs
+// that attach directly to the connector in the 'DEFAULT' mode streaming graph. For example:
+// - APOs implementing global effects
+// - APOs implementing endpoint effects
+// - APOs implementing DEFAULT mode effects which attach directly to a connector supporting DEFAULT processing mode
+
+struct CUSTOM_FORMAT_ITEM
+{
+ WAVEFORMATEXTENSIBLE wfxFmt;
+ LPCWSTR pwszRep;
+};
+
+#define STATIC_KSDATAFORMAT_SUBTYPE_AC3\
+ DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF)
+DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_AC3);
+#define KSDATAFORMAT_SUBTYPE_AC3 DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_AC3)
+
+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)"}
+};
+
+#define _cCustomFormats (ARRAYSIZE(_rgCustomFormats))
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Implementation of IAudioSystemEffectsCustomFormats::GetFormatCount
+//
+// Parameters:
+//
+// pcFormats - [out] receives the number of formats to be added
+//
+// Return values:
+//
+// S_OK Success
+// E_POINTER Null pointer passed
+//
+// Remarks:
+//
+STDMETHODIMP CDelayAPOMFX::GetFormatCount
+(
+ UINT* pcFormats
+)
+{
+ if (pcFormats == NULL)
+ return E_POINTER;
+
+ *pcFormats = _cCustomFormats;
+ return S_OK;
+}
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Implementation of IAudioSystemEffectsCustomFormats::GetFormat
+//
+// Parameters:
+//
+// nFormat - [in] which format is being requested
+// IAudioMediaType - [in] address of a variable that will receive a ptr
+// to a new IAudioMediaType object
+//
+// Return values:
+//
+// S_OK Success
+// E_INVALIDARG nFormat is out of range
+// E_POINTER Null pointer passed
+//
+// Remarks:
+//
+STDMETHODIMP CDelayAPOMFX::GetFormat
+(
+ UINT nFormat,
+ IAudioMediaType** ppFormat
+)
+{
+ HRESULT hr;
+
+ IF_TRUE_ACTION_JUMP((nFormat >= _cCustomFormats), hr = E_INVALIDARG, Exit);
+ IF_TRUE_ACTION_JUMP((ppFormat == NULL), hr = E_POINTER, Exit);
+
+ *ppFormat = NULL;
+
+ hr = CreateAudioMediaType( (const WAVEFORMATEX*)&_rgCustomFormats[nFormat].wfxFmt,
+ sizeof(_rgCustomFormats[nFormat].wfxFmt),
+ ppFormat);
+
+Exit:
+ return hr;
+}
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Implementation of IAudioSystemEffectsCustomFormats::GetFormatRepresentation
+//
+// Parameters:
+//
+// nFormat - [in] which format is being requested
+// ppwstrFormatRep - [in] address of a variable that will receive a ptr
+// to a new string description of the requested format
+//
+// Return values:
+//
+// S_OK Success
+// E_INVALIDARG nFormat is out of range
+// E_POINTER Null pointer passed
+//
+// Remarks:
+//
+STDMETHODIMP CDelayAPOMFX::GetFormatRepresentation
+(
+ UINT nFormat,
+ _Outptr_ LPWSTR* ppwstrFormatRep
+)
+{
+ HRESULT hr;
+ size_t cbRep;
+ LPWSTR pwstrLocal;
+
+ IF_TRUE_ACTION_JUMP((nFormat >= _cCustomFormats), hr = E_INVALIDARG, Exit);
+ IF_TRUE_ACTION_JUMP((ppwstrFormatRep == NULL), hr = E_POINTER, Exit);
+
+ cbRep = (wcslen(_rgCustomFormats[nFormat].pwszRep) + 1) * sizeof(WCHAR);
+
+ pwstrLocal = (LPWSTR)CoTaskMemAlloc(cbRep);
+ IF_TRUE_ACTION_JUMP((pwstrLocal == NULL), hr = E_OUTOFMEMORY, Exit);
+
+ hr = StringCbCopyW(pwstrLocal, cbRep, _rgCustomFormats[nFormat].pwszRep);
+ if (FAILED(hr))
+ {
+ CoTaskMemFree(pwstrLocal);
+ }
+ else
+ {
+ *ppwstrFormatRep = pwstrLocal;
+ }
+
+Exit:
+ return hr;
+}
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.rgs b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.rgs
new file mode 100644
index 00000000..0d1f19e2
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOMFX.rgs
@@ -0,0 +1,13 @@
+HKCR
+{
+ NoRemove CLSID
+ {
+ ForceRemove {b6c7032b-1f17-4cc6-bcdb-fd96deabc8a9} = s 'DelayAPOMFX Class'
+ {
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Both'
+ }
+ }
+ }
+}
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.cpp b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.cpp
new file mode 100644
index 00000000..81594bb7
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.cpp
@@ -0,0 +1,662 @@
+//
+// DelayAPOSFX.cpp -- Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// Description:
+//
+// Implementation of CDelayAPOSFX
+//
+
+#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 "DelayAPO.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> CDelayAPOSFX::sm_RegProperties(
+ __uuidof(DelayAPOSFX), // clsid of this APO
+ L"CDelayAPOSFX", // friendly name of this APO
+ L"Copyright (c) Microsoft Corporation", // copyright info
+ 1, // major version #
+ 0, // minor version #
+ __uuidof(IDelayAPOSFX) // iid of primary interface
+
+//
+// If you need to change any of these attributes, uncomment everything up to
+// the point that you need to change something. If you need to add IIDs, uncomment
+// everything and add additional IIDs at the end.
+//
+// , DEFAULT_APOREG_FLAGS
+// , 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) CDelayAPOSFX::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( pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame() );
+ }
+
+ // copy to the delay buffer
+ if (
+ !IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) &&
+ m_fEnableDelaySFX
+ )
+ {
+ ProcessDelay(pf32OutputFrames, pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame(),
+ m_pf32DelayBuffer,
+ m_nDelayFrames,
+ &m_iDelayIndex);
+
+ // we don't try to remember silence
+ ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID;
+ }
+ else
+ {
+ // copy the memory only if there is an output connection, and input/output pointers are unequal
+ if ( (0 != u32NumOutputConnections) &&
+ (ppOutputConnections[0]->pBuffer != ppInputConnections[0]->pBuffer) )
+ {
+ CopyFrames( pf32OutputFrames, pf32InputFrames,
+ ppInputConnections[0]->u32ValidFrameCount,
+ GetSamplesPerFrame() );
+ }
+
+ // pass along buffer flags
+ ppOutputConnections[0]->u32BufferFlags = ppInputConnections[0]->u32BufferFlags;
+ }
+
+ // 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:
+//
+// Report delay added by the APO between samples given on input
+// and samples given on output.
+//
+// Parameters:
+//
+// pTime - [out] hundreds-of-nanoseconds of delay added
+//
+// Return values:
+//
+// S_OK on success, a failure code on failure
+STDMETHODIMP CDelayAPOSFX::GetLatency(HNSTIME* pTime)
+{
+ ASSERT_NONREALTIME();
+ HRESULT hr = S_OK;
+
+ IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit);
+
+ if (IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
+ {
+ *pTime = 0;
+ }
+ else
+ {
+ *pTime = (m_fEnableDelaySFX ? HNS_DELAY : 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 CDelayAPOSFX::LockForProcess(UINT32 u32NumInputConnections,
+ APO_CONNECTION_DESCRIPTOR** ppInputConnections,
+ UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections)
+{
+ ASSERT_NONREALTIME();
+ HRESULT hr = S_OK;
+
+ hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections,
+ ppInputConnections, u32NumOutputConnections, ppOutputConnections);
+ IF_FAILED_JUMP(hr, Exit);
+
+ if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelaySFX)
+ {
+ m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY);
+ m_iDelayIndex = 0;
+
+ m_pf32DelayBuffer.Free();
+
+ // Allocate one second's worth of audio
+ //
+ // This allocation is being done using CoTaskMemAlloc because the delay is very large
+ // This introduces a risk of glitches if the delay buffer gets paged out
+ //
+ // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory
+ // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important
+ m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames);
+
+ WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame());
+ if (nullptr == m_pf32DelayBuffer)
+ {
+ hr = E_OUTOFMEMORY;
+ goto 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 CDelayAPOSFX::Initialize(UINT32 cbDataSize, BYTE* pbyData)
+{
+ HRESULT hr = S_OK;
+ CComPtr<IMMDevice> spMyDevice;
+ CComPtr<IDeviceTopology> spMyDeviceTopology;
+ CComPtr<IConnector> spMyConnector;
+ GUID processingMode;
+
+ 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;
+
+ // 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(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology);
+ IF_FAILED_JUMP(hr, Exit);
+
+ hr = spMyDeviceTopology->GetConnector(papoSysFxInit2->nSoftwareIoConnectorIndex, &spMyConnector);
+ IF_FAILED_JUMP(hr, Exit);
+
+ // Save the processing mode being initialized.
+ processingMode = papoSysFxInit2->AudioProcessingMode;
+
+ }
+ else if (cbDataSize == sizeof(APOInitSystemEffects))
+ {
+ //
+ // Initialize for default signal processing
+ //
+ APOInitSystemEffects* papoSysFxInit = (APOInitSystemEffects*)pbyData;
+
+ // 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 = papoSysFxInit->pAPOSystemEffectsProperties;
+
+ // Assume default processing mode
+ processingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
+ }
+ else
+ {
+ // Invalid initialization size
+ hr = E_INVALIDARG;
+ goto Exit;
+ }
+
+ // Validate then save the processing mode. Note an endpoint effects APO
+ // does not depend on the mode. Windows sets the APOInitSystemEffects2
+ // AudioProcessingMode member to GUID_NULL for an endpoint effects APO.
+ IF_TRUE_ACTION_JUMP((processingMode != AUDIO_SIGNALPROCESSINGMODE_DEFAULT &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_RAW &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_SPEECH &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_MEDIA &&
+ processingMode != AUDIO_SIGNALPROCESSINGMODE_MOVIE), hr = E_INVALIDARG, Exit);
+ m_AudioProcessingMode = processingMode;
+
+ //
+ // An APO that implements signal processing more complex than this sample
+ // would configure its processing for the processingMode determined above.
+ // If necessary, the APO would also use the IDeviceTopology and IConnector
+ // interfaces retrieved above to communicate with its counterpart audio
+ // driver to configure any additional signal processing in the driver and
+ // associated hardware.
+ //
+
+ //
+ // Get the current values
+ //
+ if (m_spAPOSystemEffectsProperties != NULL)
+ {
+ m_fEnableDelaySFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Delay_SFX, m_AudioProcessingMode);
+ }
+
+ //
+ // 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;
+}
+
+//-------------------------------------------------------------------------
+//
+// GetEffectsList
+//
+// Retrieves the list of signal processing effects currently active and
+// stores an event to be signaled if the list changes.
+//
+// Parameters
+//
+// ppEffectsIds - returns a pointer to a list of GUIDs each identifying a
+// class of effect. The caller is responsible for freeing this memory by
+// calling CoTaskMemFree.
+//
+// pcEffects - returns a count of GUIDs in the list.
+//
+// Event - passes an event handle. The APO signals this event when the list
+// of effects changes from the list returned from this function. The APO
+// uses this event until either this function is called again or the APO
+// is destroyed. The passed handle may be NULL. In this case, the APO
+// stops using any previous handle and does not signal an event.
+//
+// Remarks
+//
+// An APO imlements this method to allow Windows to discover the current
+// effects applied by the APO. The list of effects may depend on what signal
+// processing mode the APO initialized (see AudioProcessingMode in the
+// APOInitSystemEffects2 structure) as well as any end user configuration.
+//
+// If there are no effects then the function still succeeds, ppEffectsIds
+// returns a NULL pointer, and pcEffects returns a count of 0.
+//
+STDMETHODIMP CDelayAPOSFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event)
+{
+ HRESULT hr;
+ BOOL effectsLocked = FALSE;
+ UINT cEffects = 0;
+
+ IF_TRUE_ACTION_JUMP(ppEffectsIds == NULL, hr = E_POINTER, Exit);
+ IF_TRUE_ACTION_JUMP(pcEffects == NULL, hr = E_POINTER, Exit);
+
+ // Synchronize access to the effects list and effects changed event
+ m_EffectsLock.Enter();
+ effectsLocked = TRUE;
+
+ // Always close existing effects change event handle
+ if (m_hEffectsChangedEvent != NULL)
+ {
+ CloseHandle(m_hEffectsChangedEvent);
+ m_hEffectsChangedEvent = NULL;
+ }
+
+ // If an event handle was specified, save it here (duplicated to control lifetime)
+ if (Event != NULL)
+ {
+ if (!DuplicateHandle(GetCurrentProcess(), Event, GetCurrentProcess(), &m_hEffectsChangedEvent, EVENT_MODIFY_STATE, FALSE, 0))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit;
+ }
+ }
+
+ // naked scope to force the initialization of list[] to be after we enter the critical section
+ {
+ struct EffectControl
+ {
+ GUID effect;
+ BOOL control;
+ };
+
+ EffectControl list[] =
+ {
+ { DelayEffectId, m_fEnableDelaySFX },
+ };
+
+ if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW))
+ {
+ // count the active effects
+ for (UINT i = 0; i < ARRAYSIZE(list); i++)
+ {
+ if (list[i].control)
+ {
+ cEffects++;
+ }
+ }
+ }
+
+ if (0 == cEffects)
+ {
+ *ppEffectsIds = NULL;
+ *pcEffects = 0;
+ }
+ else
+ {
+ GUID *pEffectsIds = (LPGUID)CoTaskMemAlloc(sizeof(GUID) * cEffects);
+ if (pEffectsIds == nullptr)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // pick up the active effects
+ UINT j = 0;
+ for (UINT i = 0; i < ARRAYSIZE(list); i++)
+ {
+ if (list[i].control)
+ {
+ pEffectsIds[j++] = list[i].effect;
+ }
+ }
+
+ *ppEffectsIds = pEffectsIds;
+ *pcEffects = cEffects;
+ }
+
+ hr = S_OK;
+ }
+
+Exit:
+ if (effectsLocked)
+ {
+ m_EffectsLock.Leave();
+ }
+ return hr;
+}
+
+//-------------------------------------------------------------------------
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+//
+// Return values:
+//
+//
+//
+// Remarks:
+//
+//
+HRESULT CDelayAPOSFX::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key)
+{
+ HRESULT hr = S_OK;
+
+ UNREFERENCED_PARAMETER(pwstrDeviceId);
+
+ if (!m_spAPOSystemEffectsProperties)
+ {
+ return hr;
+ }
+
+ // If either the master disable or our APO's enable properties changed...
+ if (PK_EQUAL(key, PKEY_Endpoint_Enable_Delay_SFX) ||
+ PK_EQUAL(key, PKEY_AudioEndpoint_Disable_SysFx))
+ {
+ LONG nChanges = 0;
+
+ // Synchronize access to the effects list and effects changed event
+ m_EffectsLock.Enter();
+
+ struct KeyControl
+ {
+ PROPERTYKEY key;
+ LONG *value;
+ };
+
+ KeyControl controls[] =
+ {
+ { PKEY_Endpoint_Enable_Delay_SFX, &m_fEnableDelaySFX },
+ };
+
+ for (int i = 0; i < ARRAYSIZE(controls); i++)
+ {
+ LONG fOldValue;
+ LONG fNewValue = true;
+
+ // Get the state of whether channel swap MFX is enabled or not
+ fNewValue = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, controls[i].key, m_AudioProcessingMode);
+
+ // Delay in the new setting
+ fOldValue = InterlockedExchange(controls[i].value, fNewValue);
+
+ if (fNewValue != fOldValue)
+ {
+ nChanges++;
+ }
+ }
+
+ // If anything changed and a change event handle exists
+ if ((nChanges > 0) && (m_hEffectsChangedEvent != NULL))
+ {
+ SetEvent(m_hEffectsChangedEvent);
+ }
+
+ m_EffectsLock.Leave();
+ }
+
+ return hr;
+}
+
+
+//-------------------------------------------------------------------------
+// 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.
+//
+CDelayAPOSFX::~CDelayAPOSFX(void)
+{
+ //
+ // unregister for callbacks
+ //
+ if (m_bIsInitialized)
+ {
+ m_spEnumerator->UnregisterEndpointNotificationCallback(this);
+ }
+
+ if (m_hEffectsChangedEvent != NULL)
+ {
+ CloseHandle(m_hEffectsChangedEvent);
+ }
+} // ~CDelayAPOSFX
diff --git a/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.rgs b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.rgs
new file mode 100644
index 00000000..1a100539
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/DelayAPOSFX.rgs
@@ -0,0 +1,13 @@
+HKCR
+{
+ NoRemove CLSID
+ {
+ ForceRemove {77802b45-a5a0-455a-8204-3dba30eee7b4} = s 'DelayAPOSFX Class'
+ {
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Both'
+ }
+ }
+ }
+}
diff --git a/audio/sysvad/SwapAPO/DelayAPO/Resource.h b/audio/sysvad/SwapAPO/DelayAPO/Resource.h
new file mode 100644
index 00000000..eda62a7a
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/Resource.h
@@ -0,0 +1,20 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by DelayAPODll.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_DELAYAPODLL 101
+#define IDR_DELAYAPOMFX 110
+#define IDR_DELAYAPOSFX 111
+#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/SwapAPO/DelayAPO/delayapo.png b/audio/sysvad/SwapAPO/DelayAPO/delayapo.png
new file mode 100644
index 00000000..055bdc2c
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/delayapo.png
Binary files differ
diff --git a/audio/sysvad/SwapAPO/DelayAPO/makefile b/audio/sysvad/SwapAPO/DelayAPO/makefile
new file mode 100644
index 00000000..593ab379
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/makefile
@@ -0,0 +1,34 @@
+#############################################################################
+#
+# 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/SwapAPO/DelayAPO/sources b/audio/sysvad/SwapAPO/DelayAPO/sources
new file mode 100644
index 00000000..355dc80f
--- /dev/null
+++ b/audio/sysvad/SwapAPO/DelayAPO/sources
@@ -0,0 +1,12 @@
+!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/SwapAPO/PropPageExtensions/PropPageExt.vcxproj.Filters b/audio/sysvad/SwapAPO/PropPageExtensions/PropPageExt.vcxproj.Filters
new file mode 100644
index 00000000..98832fba
--- /dev/null
+++ b/audio/sysvad/SwapAPO/PropPageExtensions/PropPageExt.vcxproj.Filters
@@ -0,0 +1,51 @@
+<?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>{413921B3-AEE4-4E51-B616-E356BEC9E42E}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{0B044B82-EDD8-49A9-ACEE-2E7C98CCA3DC}</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>{1E3956FB-B7AD-48BF-AD18-28527349BEED}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="AdvEndpointPropPage.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CplExt.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Parts.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="stdafxsrc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SwapPropPage.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="TopologyExaminers.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="UIWidgets.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <Midl Include="CplExt.idl">
+ <Filter>Source Files</Filter>
+ </Midl>
+ <None Include="PropPageExt.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="CplExt.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/SwapAPO/PropPageExtensions/makefile b/audio/sysvad/SwapAPO/PropPageExtensions/makefile
new file mode 100644
index 00000000..c7837f4f
--- /dev/null
+++ b/audio/sysvad/SwapAPO/PropPageExtensions/makefile
@@ -0,0 +1,36 @@
+#############################################################################
+#
+# 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/SwapAPO/PropPageExtensions/sources b/audio/sysvad/SwapAPO/PropPageExtensions/sources
new file mode 100644
index 00000000..898884b6
--- /dev/null
+++ b/audio/sysvad/SwapAPO/PropPageExtensions/sources
@@ -0,0 +1,60 @@
+TARGETNAME=PropPageExt
+TARGETTYPE=DYNLINK
+
+USE_ATL=1
+
+USE_NATIVE_EH=1
+
+
+DLLENTRY=_DllMainCRTStartup
+PRECOMPILED_CXX=1
+PRECOMPILED_INCLUDE=stdafx.h
+PRECOMPILED_PCH=stdafx.pch
+
+MSC_WARNING_LEVEL=-W4 \
+ -WX
+
+#
+# stdafx.h defines _ATL_ALL_WARNINGS
+# Disabling 4127 is necessary to allow this driver to build in the WDK environment.
+#
+USER_C_FLAGS=/wd4127
+
+C_DEFINES=-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=$(INCLUDES); \
+ ..\Inc; \
+ $(DDK_INC_PATH);
+SOURCES=CplExt.idl \
+ CplExt.rc \
+ CplExt.cpp \
+ SwapPropPage.cpp \
+ AdvEndpointPropPage.cpp \
+ UIWidgets.cpp \
+ TopologyExaminers.cpp \
+ Parts.cpp \
+
+
+TARGETLIBS= \
+ \
+ $(SDK_LIB_PATH)\onecore_downlevel.lib \
+ $(ONECORE_PRIV_SDK_LIB_PATH)\OneCore_Forwarder_user32.lib \
+ $(SDK_LIB_PATH)\onecore_downlevel.lib \
+ $(SDK_LIB_PATH)\oleaut32.lib \
+ $(INTERNAL_SDK_LIB_PATH)\onecoreuapuuid.lib \
+ $(SDK_LIB_PATH)\shlwapi.lib \
+ $(SDK_LIB_PATH)\comctl32.lib \
+ $(SDK_LIB_PATH)\rpcrt4.lib \
+
+
+
diff --git a/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters
new file mode 100644
index 00000000..cc7dcd30
--- /dev/null
+++ b/audio/sysvad/TabletAudioSample/TabletAudioSample.vcxproj.Filters
@@ -0,0 +1,58 @@
+<?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>{7FE326AE-6214-4FE0-A27B-F229A098BDBC}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{64C16D2B-849C-4264-A615-18A8E8AC9505}</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>{46FAF4E8-F18C-4797-9CFA-2F3473BCB316}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{EE8F0A00-C1F0-4CB4-80E3-5FCC378E0BF4}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\adapter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\basetopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\common.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\hw.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\kshelper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\savedata.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tonegenerator.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="hdmitopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="micintopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="spdiftopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\sysvad.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/TabletAudioSample/minipairs.h b/audio/sysvad/TabletAudioSample/minipairs.h
index 320aed6f..e955791e 100644
--- a/audio/sysvad/TabletAudioSample/minipairs.h
+++ b/audio/sysvad/TabletAudioSample/minipairs.h
@@ -177,7 +177,10 @@ ENDPOINT_MINIPAIR SpeakerMiniports =
SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes),
SpeakerTopologyPhysicalConnections,
SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections),
- ENDPOINT_OFFLOAD_SUPPORTED
+ ENDPOINT_OFFLOAD_SUPPORTED,
+ SpeakerModulesWaveFilter,
+ SIZEOF_ARRAY(SpeakerModulesWaveFilter),
+ &SpeakerModuleNotificationDeviceId,
};
/*********************************************************************
@@ -219,7 +222,10 @@ ENDPOINT_MINIPAIR SpeakerHpMiniports =
SIZEOF_ARRAY(SpeakerHpPinDeviceFormatsAndModes),
SpeakerHpTopologyPhysicalConnections,
SIZEOF_ARRAY(SpeakerHpTopologyPhysicalConnections),
- ENDPOINT_OFFLOAD_SUPPORTED
+ ENDPOINT_OFFLOAD_SUPPORTED,
+ SpeakerHpModulesWaveFilter,
+ SIZEOF_ARRAY(SpeakerHpModulesWaveFilter),
+ &SpeakerHpModuleNotificationDeviceId,
};
/*********************************************************************
@@ -261,7 +267,8 @@ ENDPOINT_MINIPAIR HdmiMiniports =
SIZEOF_ARRAY(HdmiPinDeviceFormatsAndModes),
HdmiTopologyPhysicalConnections,
SIZEOF_ARRAY(HdmiTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS
+ ENDPOINT_NO_FLAGS,
+ NULL, 0, NULL, // audio module settings.
};
/*********************************************************************
@@ -304,7 +311,8 @@ ENDPOINT_MINIPAIR SpdifMiniports =
SIZEOF_ARRAY(SpdifPinDeviceFormatsAndModes),
SpdifTopologyPhysicalConnections,
SIZEOF_ARRAY(SpdifTopologyPhysicalConnections),
- ENDPOINT_OFFLOAD_SUPPORTED
+ ENDPOINT_OFFLOAD_SUPPORTED,
+ NULL, 0, NULL, // audio module settings.
};
//
@@ -348,7 +356,8 @@ ENDPOINT_MINIPAIR MicInMiniports =
SIZEOF_ARRAY(MicInPinDeviceFormatsAndModes),
MicInTopologyPhysicalConnections,
SIZEOF_ARRAY(MicInTopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS
+ ENDPOINT_NO_FLAGS,
+ NULL, 0, NULL, // audio module settings.
};
/*********************************************************************
@@ -389,7 +398,8 @@ ENDPOINT_MINIPAIR MicArray1Miniports =
SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes),
MicArray1TopologyPhysicalConnections,
SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections),
- ENDPOINT_SOUNDDETECTOR_SUPPORTED
+ ENDPOINT_SOUNDDETECTOR_SUPPORTED,
+ NULL, 0, NULL, // audio module settings.
};
/*********************************************************************
@@ -429,7 +439,8 @@ ENDPOINT_MINIPAIR MicArray2Miniports =
SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes),
MicArray2TopologyPhysicalConnections,
SIZEOF_ARRAY(MicArray2TopologyPhysicalConnections),
- ENDPOINT_SOUNDDETECTOR_SUPPORTED
+ ENDPOINT_SOUNDDETECTOR_SUPPORTED,
+ NULL, 0, NULL, // audio module settings.
};
/*********************************************************************
@@ -469,7 +480,8 @@ ENDPOINT_MINIPAIR MicArray3Miniports =
SIZEOF_ARRAY(MicArray3PinDeviceFormatsAndModes),
MicArray3TopologyPhysicalConnections,
SIZEOF_ARRAY(MicArray3TopologyPhysicalConnections),
- ENDPOINT_NO_FLAGS
+ ENDPOINT_NO_FLAGS,
+ NULL, 0, NULL, // audio module settings.
};
//=============================================================================
diff --git a/audio/sysvad/TabletAudioSample/sources b/audio/sysvad/TabletAudioSample/sources
new file mode 100644
index 00000000..39d0de57
--- /dev/null
+++ b/audio/sysvad/TabletAudioSample/sources
@@ -0,0 +1,53 @@
+
+# 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
+
+
+#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 \
+
+
+# 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.inf b/audio/sysvad/TabletAudioSample/tabletaudiosample.inf
index 0e85d33b..c9f533af 100644
--- a/audio/sysvad/TabletAudioSample/tabletaudiosample.inf
+++ b/audio/sysvad/TabletAudioSample/tabletaudiosample.inf
Binary files differ
diff --git a/audio/sysvad/common.h b/audio/sysvad/common.h
index ee37445a..d46a9090 100644
--- a/audio/sysvad/common.h
+++ b/audio/sysvad/common.h
@@ -187,6 +187,126 @@ typedef struct _PIN_DEVICE_FORMATS_AND_MODES
} PIN_DEVICE_FORMATS_AND_MODES, *PPIN_DEVICE_FORMATS_AND_MODES;
+//
+// Parameter module handler function prototypes.
+//
+static const GUID NULL_GUID =
+{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};
+
+static const GUID MODULETYPE_HWEFFECT =
+{0x2608993c,0x361e,0x488c,{0xa0,0xbc,0x8f,0x3d,0xe7,0xba,0x12,0xb4}};
+
+//
+// Forward declaration.
+//
+struct AUDIOMODULE_DESCRIPTOR;
+typedef AUDIOMODULE_DESCRIPTOR *PAUDIOMODULE_DESCRIPTOR;
+
+typedef struct _AUDIOMODULE_PARAMETER_INFO
+{
+ USHORT AccessFlags; // get/set/basic-support attributes.
+ USHORT Flags;
+ ULONG Size;
+ DWORD VtType;
+ PVOID ValidSet;
+ ULONG ValidSetCount;
+} AUDIOMODULE_PARAMETER_INFO, *PAUDIOMODULE_PARAMETER_INFO;
+
+#define AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION 0x00000001
+
+//
+// Module callbacks.
+//
+typedef
+NTSTATUS
+(*FN_AUDIOMODULE_INIT_CLASS)
+(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader,
+ _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications
+);
+
+typedef
+NTSTATUS
+(*FN_AUDIOMODULE_INIT_INSTANCE)
+(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _In_opt_ PVOID TemplateContext,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ ULONG InstanceId
+);
+
+typedef
+VOID
+(*FN_AUDIOMODULE_CLEANUP)
+(
+ _In_ PVOID Context
+);
+
+typedef
+NTSTATUS
+(*FN_AUDIOMODULE_HANDLER)
+(
+ _Inout_opt_ PVOID Context,
+ _In_reads_bytes_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb
+);
+
+//
+// Module description.
+//
+struct AUDIOMODULE_DESCRIPTOR
+{
+ const GUID * ClassId;
+ const GUID * ProcessingMode;
+ WCHAR Name[AUDIOMODULE_MAX_NAME_CCH_SIZE];
+ ULONG InstanceId;
+ ULONG VersionMajor;
+ ULONG VersionMinor;
+ ULONG Flags;
+ size_t ContextSize;
+ FN_AUDIOMODULE_INIT_CLASS InitClass;
+ FN_AUDIOMODULE_INIT_INSTANCE InitInstance;
+ FN_AUDIOMODULE_CLEANUP Cleanup;
+ FN_AUDIOMODULE_HANDLER Handler;
+};
+
+#define AUDIOMODULE_DESCRIPTOR_FLAG_NONE 0x00000000
+
+//
+// Audio module instance defintion.
+// This sample driver generates an instance id by combinding the
+// configuration set # for a class module id with the instance of that
+// configuration. Real driver should use a more robust scheme, such as
+// an indirect mapping from/to an instance id to/from a configuration set
+// + location in the pipeline + any other info the driver needs.
+//
+#define AUDIOMODULE_CLASS_CFG_ID_MASK 0xFF
+#define AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK 0xFFFFFF
+
+#define AUDIOMODULE_INSTANCE_ID(ClassCfgId, ClassCfgInstanceId) \
+ ((ULONG(ClassCfgId & AUDIOMODULE_CLASS_CFG_ID_MASK) << 24) | \
+ (ULONG(ClassCfgInstanceId & AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK)))
+
+#define AUDIOMODULE_GET_CLASSCFGID(InstanceId) \
+ (ULONG(InstanceId) >> 24 & AUDIOMODULE_CLASS_CFG_ID_MASK)
+
+//
+// Used to track run-time audio module changes.
+//
+struct AUDIOMODULE
+{
+ const AUDIOMODULE_DESCRIPTOR * Descriptor;
+ PVOID Context;
+ ULONG InstanceId;
+ ULONG NextCfgInstanceId; // used by filter modules
+ BOOL Enabled;
+};
// forward declaration.
typedef struct _ENDPOINT_MINIPAIR *PENDPOINT_MINIPAIR;
@@ -252,6 +372,11 @@ typedef struct _ENDPOINT_MINIPAIR
// General endpoint flags (one of more ENDPOINT_<flag-type>, see above)
ULONG DeviceFlags;
+
+ // Static module list description.
+ AUDIOMODULE_DESCRIPTOR * ModuleList;
+ ULONG ModuleListCount;
+ const GUID * ModuleNotificationDeviceId;
} ENDPOINT_MINIPAIR;
//=============================================================================
diff --git a/audio/sysvad/sources.inc b/audio/sysvad/sources.inc
new file mode 100644
index 00000000..7396cf46
--- /dev/null
+++ b/audio/sysvad/sources.inc
@@ -0,0 +1,34 @@
+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 \
+ ..\common.cpp \
+ ..\hw.cpp \
+ ..\kshelper.cpp \
+ ..\savedata.cpp \
+ ..\tonegenerator.cpp \
+ ..\sysvad.rc
+
diff --git a/audio/sysvad/sysvad.h b/audio/sysvad/sysvad.h
index 0e35aebd..0065f3e3 100644
--- a/audio/sysvad/sysvad.h
+++ b/audio/sysvad/sysvad.h
@@ -230,6 +230,15 @@ typedef struct _PortClassDeviceContext // 32 64 Byte off
} PortClassDeviceContext;
//
+// Major/MinorTarget to object casting.
+//
+#define MajorTarget_to_Obj(ptr) \
+ reinterpret_cast<CMiniportWaveRT*>(ptr)
+
+#define MinorTarget_to_Obj(ptr) \
+ static_cast<CMiniportWaveRTStream*>(reinterpret_cast<PMINIPORTWAVERTSTREAM>(ptr))
+
+//
// Global settings.
//
extern DWORD g_DoNotCreateDataFiles;
@@ -257,6 +266,11 @@ NTSTATUS PropertyHandler_OffloadPin
_In_ PPCPROPERTY_REQUEST PropertyRequest
);
+NTSTATUS PropertyHandler_GenericPin
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+);
+
// common.h uses some of the above definitions.
#include "common.h"
#include "kshelper.h"
diff --git a/audio/sysvad/sysvad.sln b/audio/sysvad/sysvad.sln
index 026c0790..d504350b 100644
--- a/audio/sysvad/sysvad.sln
+++ b/audio/sysvad/sysvad.sln
@@ -1,8 +1,10 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
+VisualStudioVersion = 14.0.25431.01
MinimumVisualStudioVersion = 12.0
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{FA56D96B-290B-4C73-A5E1-02C1861D3224}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "KeywordDetectorAdapter", "KeywordDetectorAdapter", "{DBD14E7B-7F95-4743-86E3-4E16FA43F990}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PropPageExtensions", "PropPageExtensions", "{50D3DF82-019A-4434-B17F-72BBC291415F}"
@@ -17,12 +19,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PhoneAudioSample", "PhoneAu
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TabletAudioSample", "TabletAudioSample", "{C06F6070-75EE-4F57-8D35-4AC2AB08D029}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "package\package.VcxProj", "{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeywordDetectorContosoAdapter", "KeywordDetectorAdapter\KeywordDetectorContosoAdapter.vcxproj", "{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropPageExt", "SwapAPO\PropPageExtensions\PropPageExt.vcxproj", "{D253C552-154D-49E1-820A-B2CD9D9FF13E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SwapAPO", "SwapAPO\APO\SwapAPO.vcxproj", "{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DelayAPO", "SwapAPO\DelayAPO\DelayAPO.vcxproj", "{8851AB85-70B3-4798-A149-BA366DF9EC25}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EndpointsCommon", "EndpointsCommon\EndpointsCommon.vcxproj", "{33E61864-6F2C-4F9F-BE70-8F8985A4F283}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PhoneAudioSample", "PhoneAudioSample\PhoneAudioSample.vcxproj", "{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}"
@@ -38,57 +44,73 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
- Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {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}.Release|Win32.ActiveCfg = Release|Win32
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.Build.0 = Release|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|x64.ActiveCfg = Release|x64
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64
{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|Win32.ActiveCfg = Release|Win32
{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.Build.0 = Release|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|x64.ActiveCfg = Release|x64
{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.Build.0 = Release|x64
{D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|Win32.ActiveCfg = Debug|Win32
{D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|Win32.Build.0 = Debug|Win32
- {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.ActiveCfg = Debug|x64
- {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.Build.0 = Debug|x64
{D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|Win32.ActiveCfg = Release|Win32
{D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|Win32.Build.0 = Release|Win32
+ {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.ActiveCfg = Debug|x64
+ {D253C552-154D-49E1-820A-B2CD9D9FF13E}.Debug|x64.Build.0 = Debug|x64
{D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|x64.ActiveCfg = Release|x64
{D253C552-154D-49E1-820A-B2CD9D9FF13E}.Release|x64.Build.0 = Release|x64
{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|Win32.ActiveCfg = Release|Win32
{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|Win32.Build.0 = Release|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|x64.ActiveCfg = Release|x64
{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601}.Release|x64.Build.0 = Release|x64
+ {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}.Release|Win32.ActiveCfg = Release|Win32
+ {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|Win32.Build.0 = Release|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|x64.ActiveCfg = Release|x64
+ {8851AB85-70B3-4798-A149-BA366DF9EC25}.Release|x64.Build.0 = Release|x64
{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|Win32.ActiveCfg = Release|Win32
{33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|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|x64.ActiveCfg = Release|x64
{33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64
{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|Win32.ActiveCfg = Release|Win32
{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|Win32.Build.0 = Release|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|x64.ActiveCfg = Release|x64
{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE}.Release|x64.Build.0 = Release|x64
{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|Win32.ActiveCfg = Release|Win32
{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.Build.0 = Release|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|x64.ActiveCfg = Release|x64
{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.Build.0 = Release|x64
EndGlobalSection
@@ -96,13 +118,15 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {50D3DF82-019A-4434-B17F-72BBC291415F} = {684FF1CF-64CC-430E-81F7-9D603EF56D59}
- {367FF255-7280-48C4-90AC-767124A8D5F7} = {684FF1CF-64CC-430E-81F7-9D603EF56D59}
+ {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A} = {FA56D96B-290B-4C73-A5E1-02C1861D3224}
{E0F02048-78A4-4FE8-B863-66E6CB6A2C37} = {DBD14E7B-7F95-4743-86E3-4E16FA43F990}
{D253C552-154D-49E1-820A-B2CD9D9FF13E} = {50D3DF82-019A-4434-B17F-72BBC291415F}
{691F1D0F-CA50-46CD-8BBA-A59E9E8EB601} = {367FF255-7280-48C4-90AC-767124A8D5F7}
+ {8851AB85-70B3-4798-A149-BA366DF9EC25} = {367FF255-7280-48C4-90AC-767124A8D5F7}
{33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {0B4B8E51-20A8-43A4-A8DA-42FF90D628AC}
{FABA4668-DB5E-4F6C-9D25-A0B25AD084EE} = {D0DBEBE9-0DCC-4EA7-966B-C029C1334D9E}
{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF} = {C06F6070-75EE-4F57-8D35-4AC2AB08D029}
+ {50D3DF82-019A-4434-B17F-72BBC291415F} = {684FF1CF-64CC-430E-81F7-9D603EF56D59}
+ {367FF255-7280-48C4-90AC-767124A8D5F7} = {684FF1CF-64CC-430E-81F7-9D603EF56D59}
EndGlobalSection
EndGlobal