[PATCH] xaudio2_0: Add compatibility implementation and forward to xaudio2_7

Andrew Eikum aeikum at codeweavers.com
Wed Oct 7 11:19:35 CDT 2015


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
 configure.ac                      |   1 +
 dlls/xaudio2_0/Makefile.in        |   7 +
 dlls/xaudio2_0/xaudio2_0.spec     |   4 +
 dlls/xaudio2_0/xaudio_classes.idl |  42 ++
 dlls/xaudio2_0/xaudio_dll.c       |  52 +++
 dlls/xaudio2_7/compat.c           | 859 ++++++++++++++++++++++++++++++++++++++
 dlls/xaudio2_7/xaudio_dll.c       | 271 +++++++-----
 dlls/xaudio2_7/xaudio_private.h   |  11 +
 include/xapo.idl                  |  16 +
 include/xaudio2.idl               | 243 +++++++++++
 include/xaudio2fx.idl             |  14 +
 11 files changed, 1415 insertions(+), 105 deletions(-)
 create mode 100644 dlls/xaudio2_0/Makefile.in
 create mode 100644 dlls/xaudio2_0/xaudio2_0.spec
 create mode 100644 dlls/xaudio2_0/xaudio_classes.idl
 create mode 100644 dlls/xaudio2_0/xaudio_dll.c

diff --git a/configure.ac b/configure.ac
index ce631e4..5e83d39 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3463,6 +3463,7 @@ WINE_CONFIG_DLL(xapofx1_2)
 WINE_CONFIG_DLL(xapofx1_3)
 WINE_CONFIG_DLL(xapofx1_4)
 WINE_CONFIG_DLL(xapofx1_5)
+WINE_CONFIG_DLL(xaudio2_0,,[clean])
 WINE_CONFIG_DLL(xaudio2_1,,[clean])
 WINE_CONFIG_DLL(xaudio2_2,,[clean])
 WINE_CONFIG_DLL(xaudio2_3,,[clean])
diff --git a/dlls/xaudio2_0/Makefile.in b/dlls/xaudio2_0/Makefile.in
new file mode 100644
index 0000000..cc9d161
--- /dev/null
+++ b/dlls/xaudio2_0/Makefile.in
@@ -0,0 +1,7 @@
+MODULE    = xaudio2_0.dll
+IMPORTS   = ole32
+
+C_SRCS = \
+	xaudio_dll.c
+
+IDL_SRCS = xaudio_classes.idl
diff --git a/dlls/xaudio2_0/xaudio2_0.spec b/dlls/xaudio2_0/xaudio2_0.spec
new file mode 100644
index 0000000..cb263d4
--- /dev/null
+++ b/dlls/xaudio2_0/xaudio2_0.spec
@@ -0,0 +1,4 @@
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr) xaudio2_7.DllGetClassObject
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
diff --git a/dlls/xaudio2_0/xaudio_classes.idl b/dlls/xaudio2_0/xaudio_classes.idl
new file mode 100644
index 0000000..4a81eb1
--- /dev/null
+++ b/dlls/xaudio2_0/xaudio_classes.idl
@@ -0,0 +1,42 @@
+/*
+ * COM Classes for xaudio
+ *
+ * Copyright 2015 Andrew Eikum for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep register
+
+[
+    helpstring("XAudio2.0 Class"),
+    threading(both),
+    uuid(e21a7345-eb21-468e-be50-804db97cf708)
+]
+coclass XAudio20 { interface IXAudio20; }
+
+[
+    helpstring("XAudio2.0 AudioReverb Class"),
+    threading(both),
+    uuid(6f6ea3a9-2cf5-41cf-91c1-2170b1540063)
+]
+coclass AudioReverb20 { interface IXAPO; }
+
+[
+    helpstring("XAudio2.0 AudioVolumeMeter Class"),
+    threading(both),
+    uuid(c0c56f46-29b1-44e9-9939-a32ce86867e2)
+]
+coclass AudioVolumeMeter20 { interface IXAPO; }
diff --git a/dlls/xaudio2_0/xaudio_dll.c b/dlls/xaudio2_0/xaudio_dll.c
new file mode 100644
index 0000000..7c95c28
--- /dev/null
+++ b/dlls/xaudio2_0/xaudio_dll.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Andrew Eikum for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "rpcproxy.h"
+
+static HINSTANCE instance;
+
+BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD reason, LPVOID reserved)
+{
+    switch (reason)
+    {
+    case DLL_PROCESS_ATTACH:
+        instance = hinstance;
+        DisableThreadLibraryCalls(hinstance);
+        break;
+    }
+    return TRUE;
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+    return S_FALSE;
+}
+
+HRESULT WINAPI DllRegisterServer(void)
+{
+    return __wine_register_resources(instance);
+}
+
+HRESULT WINAPI DllUnregisterServer(void)
+{
+    return __wine_unregister_resources(instance);
+}
diff --git a/dlls/xaudio2_7/compat.c b/dlls/xaudio2_7/compat.c
index bee57c6..8eb0efc 100644
--- a/dlls/xaudio2_7/compat.c
+++ b/dlls/xaudio2_7/compat.c
@@ -1435,3 +1435,862 @@ const IXAudio22Vtbl XAudio22_Vtbl = {
     XA22_GetPerformanceData,
     XA22_SetDebugConfiguration
 };
+
+XA2SourceImpl *impl_from_IXAudio20SourceVoice(IXAudio20SourceVoice *iface)
+{
+    return CONTAINING_RECORD(iface, XA2SourceImpl, IXAudio20SourceVoice_iface);
+}
+
+static void WINAPI XA20SRC_GetVoiceDetails(IXAudio20SourceVoice *iface,
+        XAUDIO2_VOICE_DETAILS *pVoiceDetails)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetVoiceDetails(&This->IXAudio2SourceVoice_iface, pVoiceDetails);
+}
+
+static HRESULT WINAPI XA20SRC_SetOutputVoices(IXAudio20SourceVoice *iface,
+        const XAUDIO23_VOICE_SENDS *pSendList)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    XAUDIO2_VOICE_SENDS sends;
+    HRESULT hr;
+    DWORD i;
+
+    TRACE("%p, %p\n", This, pSendList);
+
+    sends.SendCount = pSendList->OutputCount;
+    sends.pSends = HeapAlloc(GetProcessHeap(), 0, sends.SendCount * sizeof(*sends.pSends));
+    for(i = 0; i < sends.SendCount; ++i){
+        sends.pSends[i].Flags = 0;
+        sends.pSends[i].pOutputVoice = pSendList->pOutputVoices[i];
+    }
+
+    hr = IXAudio2SourceVoice_SetOutputVoices(&This->IXAudio2SourceVoice_iface, &sends);
+
+    HeapFree(GetProcessHeap(), 0, sends.pSends);
+
+    return hr;
+}
+
+static HRESULT WINAPI XA20SRC_SetEffectChain(IXAudio20SourceVoice *iface,
+        const XAUDIO2_EFFECT_CHAIN *pEffectChain)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SetEffectChain(&This->IXAudio2SourceVoice_iface, pEffectChain);
+}
+
+static HRESULT WINAPI XA20SRC_EnableEffect(IXAudio20SourceVoice *iface,
+        UINT32 EffectIndex, UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_EnableEffect(&This->IXAudio2SourceVoice_iface,
+            EffectIndex, OperationSet);
+}
+
+static HRESULT WINAPI XA20SRC_DisableEffect(IXAudio20SourceVoice *iface,
+        UINT32 EffectIndex, UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_DisableEffect(&This->IXAudio2SourceVoice_iface,
+            EffectIndex, OperationSet);
+}
+
+static void WINAPI XA20SRC_GetEffectState(IXAudio20SourceVoice *iface,
+        UINT32 EffectIndex, BOOL *pEnabled)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetEffectState(&This->IXAudio2SourceVoice_iface,
+            EffectIndex, pEnabled);
+}
+
+static HRESULT WINAPI XA20SRC_SetEffectParameters(IXAudio20SourceVoice *iface,
+        UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
+        UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SetEffectParameters(&This->IXAudio2SourceVoice_iface,
+            EffectIndex, pParameters, ParametersByteSize, OperationSet);
+}
+
+static HRESULT WINAPI XA20SRC_GetEffectParameters(IXAudio20SourceVoice *iface,
+        UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetEffectParameters(&This->IXAudio2SourceVoice_iface,
+            EffectIndex, pParameters, ParametersByteSize);
+}
+
+static HRESULT WINAPI XA20SRC_SetFilterParameters(IXAudio20SourceVoice *iface,
+        const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SetFilterParameters(&This->IXAudio2SourceVoice_iface,
+            pParameters, OperationSet);
+}
+
+static void WINAPI XA20SRC_GetFilterParameters(IXAudio20SourceVoice *iface,
+        XAUDIO2_FILTER_PARAMETERS *pParameters)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetFilterParameters(&This->IXAudio2SourceVoice_iface, pParameters);
+}
+
+static HRESULT WINAPI XA20SRC_SetVolume(IXAudio20SourceVoice *iface,
+        float Volume, UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SetVolume(&This->IXAudio2SourceVoice_iface,
+            Volume, OperationSet);
+}
+
+static void WINAPI XA20SRC_GetVolume(IXAudio20SourceVoice *iface,
+        float *pVolume)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetVolume(&This->IXAudio2SourceVoice_iface, pVolume);
+}
+
+static HRESULT WINAPI XA20SRC_SetChannelVolumes(IXAudio20SourceVoice *iface,
+        UINT32 Channels, const float *pVolumes, UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SetChannelVolumes(&This->IXAudio2SourceVoice_iface,
+            Channels, pVolumes, OperationSet);
+}
+
+static void WINAPI XA20SRC_GetChannelVolumes(IXAudio20SourceVoice *iface,
+        UINT32 Channels, float *pVolumes)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetChannelVolumes(&This->IXAudio2SourceVoice_iface,
+            Channels, pVolumes);
+}
+
+static HRESULT WINAPI XA20SRC_SetOutputMatrix(IXAudio20SourceVoice *iface,
+        IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
+        UINT32 DestinationChannels, const float *pLevelMatrix,
+        UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SetOutputMatrix(&This->IXAudio2SourceVoice_iface,
+            pDestinationVoice, SourceChannels, DestinationChannels,
+            pLevelMatrix, OperationSet);
+}
+
+static HRESULT WINAPI XA20SRC_GetOutputMatrix(IXAudio20SourceVoice *iface,
+        IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
+        UINT32 DestinationChannels, float *pLevelMatrix)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    IXAudio2SourceVoice_GetOutputMatrix(&This->IXAudio2SourceVoice_iface,
+            pDestinationVoice, SourceChannels, DestinationChannels,
+            pLevelMatrix);
+    return S_OK;
+}
+
+static void WINAPI XA20SRC_DestroyVoice(IXAudio20SourceVoice *iface)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_DestroyVoice(&This->IXAudio2SourceVoice_iface);
+}
+
+static HRESULT WINAPI XA20SRC_Start(IXAudio20SourceVoice *iface, UINT32 Flags,
+        UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_Start(&This->IXAudio2SourceVoice_iface, Flags, OperationSet);
+}
+
+static HRESULT WINAPI XA20SRC_Stop(IXAudio20SourceVoice *iface, UINT32 Flags,
+        UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_Stop(&This->IXAudio2SourceVoice_iface, Flags, OperationSet);
+}
+
+static HRESULT WINAPI XA20SRC_SubmitSourceBuffer(IXAudio20SourceVoice *iface,
+        const XAUDIO2_BUFFER *pBuffer, const XAUDIO2_BUFFER_WMA *pBufferWMA)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SubmitSourceBuffer(&This->IXAudio2SourceVoice_iface,
+            pBuffer, pBufferWMA);
+}
+
+static HRESULT WINAPI XA20SRC_FlushSourceBuffers(IXAudio20SourceVoice *iface)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_FlushSourceBuffers(&This->IXAudio2SourceVoice_iface);
+}
+
+static HRESULT WINAPI XA20SRC_Discontinuity(IXAudio20SourceVoice *iface)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_Discontinuity(&This->IXAudio2SourceVoice_iface);
+}
+
+static HRESULT WINAPI XA20SRC_ExitLoop(IXAudio20SourceVoice *iface,
+        UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_ExitLoop(&This->IXAudio2SourceVoice_iface, OperationSet);
+}
+
+static void WINAPI XA20SRC_GetState(IXAudio20SourceVoice *iface,
+        XAUDIO2_VOICE_STATE *pVoiceState)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetState(&This->IXAudio2SourceVoice_iface, pVoiceState, 0);
+}
+
+static HRESULT WINAPI XA20SRC_SetFrequencyRatio(IXAudio20SourceVoice *iface,
+        float Ratio, UINT32 OperationSet)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_SetFrequencyRatio(&This->IXAudio2SourceVoice_iface,
+            Ratio, OperationSet);
+}
+
+static void WINAPI XA20SRC_GetFrequencyRatio(IXAudio20SourceVoice *iface,
+        float *pRatio)
+{
+    XA2SourceImpl *This = impl_from_IXAudio20SourceVoice(iface);
+    return IXAudio2SourceVoice_GetFrequencyRatio(&This->IXAudio2SourceVoice_iface, pRatio);
+}
+
+const IXAudio20SourceVoiceVtbl XAudio20SourceVoice_Vtbl = {
+    XA20SRC_GetVoiceDetails,
+    XA20SRC_SetOutputVoices,
+    XA20SRC_SetEffectChain,
+    XA20SRC_EnableEffect,
+    XA20SRC_DisableEffect,
+    XA20SRC_GetEffectState,
+    XA20SRC_SetEffectParameters,
+    XA20SRC_GetEffectParameters,
+    XA20SRC_SetFilterParameters,
+    XA20SRC_GetFilterParameters,
+    XA20SRC_SetVolume,
+    XA20SRC_GetVolume,
+    XA20SRC_SetChannelVolumes,
+    XA20SRC_GetChannelVolumes,
+    XA20SRC_SetOutputMatrix,
+    XA20SRC_GetOutputMatrix,
+    XA20SRC_DestroyVoice,
+    XA20SRC_Start,
+    XA20SRC_Stop,
+    XA20SRC_SubmitSourceBuffer,
+    XA20SRC_FlushSourceBuffers,
+    XA20SRC_Discontinuity,
+    XA20SRC_ExitLoop,
+    XA20SRC_GetState,
+    XA20SRC_SetFrequencyRatio,
+    XA20SRC_GetFrequencyRatio,
+};
+
+XA2SubmixImpl *impl_from_IXAudio20SubmixVoice(IXAudio20SubmixVoice *iface)
+{
+    return CONTAINING_RECORD(iface, XA2SubmixImpl, IXAudio20SubmixVoice_iface);
+}
+
+static void WINAPI XA20SUB_GetVoiceDetails(IXAudio20SubmixVoice *iface,
+        XAUDIO2_VOICE_DETAILS *pVoiceDetails)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_GetVoiceDetails(&This->IXAudio2SubmixVoice_iface, pVoiceDetails);
+}
+
+static HRESULT WINAPI XA20SUB_SetOutputVoices(IXAudio20SubmixVoice *iface,
+        const XAUDIO23_VOICE_SENDS *pSendList)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    XAUDIO2_VOICE_SENDS sends;
+    HRESULT hr;
+    DWORD i;
+
+    TRACE("%p, %p\n", This, pSendList);
+
+    sends.SendCount = pSendList->OutputCount;
+    sends.pSends = HeapAlloc(GetProcessHeap(), 0, sends.SendCount * sizeof(*sends.pSends));
+    for(i = 0; i < sends.SendCount; ++i){
+        sends.pSends[i].Flags = 0;
+        sends.pSends[i].pOutputVoice = pSendList->pOutputVoices[i];
+    }
+
+    hr = IXAudio2SubmixVoice_SetOutputVoices(&This->IXAudio2SubmixVoice_iface, &sends);
+
+    HeapFree(GetProcessHeap(), 0, sends.pSends);
+
+    return hr;
+}
+
+static HRESULT WINAPI XA20SUB_SetEffectChain(IXAudio20SubmixVoice *iface,
+        const XAUDIO2_EFFECT_CHAIN *pEffectChain)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_SetEffectChain(&This->IXAudio2SubmixVoice_iface, pEffectChain);
+}
+
+static HRESULT WINAPI XA20SUB_EnableEffect(IXAudio20SubmixVoice *iface,
+        UINT32 EffectIndex, UINT32 OperationSet)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_EnableEffect(&This->IXAudio2SubmixVoice_iface,
+            EffectIndex, OperationSet);
+}
+
+static HRESULT WINAPI XA20SUB_DisableEffect(IXAudio20SubmixVoice *iface,
+        UINT32 EffectIndex, UINT32 OperationSet)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_DisableEffect(&This->IXAudio2SubmixVoice_iface,
+            EffectIndex, OperationSet);
+}
+
+static void WINAPI XA20SUB_GetEffectState(IXAudio20SubmixVoice *iface,
+        UINT32 EffectIndex, BOOL *pEnabled)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_GetEffectState(&This->IXAudio2SubmixVoice_iface,
+            EffectIndex, pEnabled);
+}
+
+static HRESULT WINAPI XA20SUB_SetEffectParameters(IXAudio20SubmixVoice *iface,
+        UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
+        UINT32 OperationSet)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_SetEffectParameters(&This->IXAudio2SubmixVoice_iface,
+            EffectIndex, pParameters, ParametersByteSize, OperationSet);
+}
+
+static HRESULT WINAPI XA20SUB_GetEffectParameters(IXAudio20SubmixVoice *iface,
+        UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_GetEffectParameters(&This->IXAudio2SubmixVoice_iface,
+            EffectIndex, pParameters, ParametersByteSize);
+}
+
+static HRESULT WINAPI XA20SUB_SetFilterParameters(IXAudio20SubmixVoice *iface,
+        const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_SetFilterParameters(&This->IXAudio2SubmixVoice_iface,
+            pParameters, OperationSet);
+}
+
+static void WINAPI XA20SUB_GetFilterParameters(IXAudio20SubmixVoice *iface,
+        XAUDIO2_FILTER_PARAMETERS *pParameters)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_GetFilterParameters(&This->IXAudio2SubmixVoice_iface, pParameters);
+}
+
+static HRESULT WINAPI XA20SUB_SetVolume(IXAudio20SubmixVoice *iface,
+        float Volume, UINT32 OperationSet)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_SetVolume(&This->IXAudio2SubmixVoice_iface,
+            Volume, OperationSet);
+}
+
+static void WINAPI XA20SUB_GetVolume(IXAudio20SubmixVoice *iface,
+        float *pVolume)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_GetVolume(&This->IXAudio2SubmixVoice_iface, pVolume);
+}
+
+static HRESULT WINAPI XA20SUB_SetChannelVolumes(IXAudio20SubmixVoice *iface,
+        UINT32 Channels, const float *pVolumes, UINT32 OperationSet)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_SetChannelVolumes(&This->IXAudio2SubmixVoice_iface,
+            Channels, pVolumes, OperationSet);
+}
+
+static void WINAPI XA20SUB_GetChannelVolumes(IXAudio20SubmixVoice *iface,
+        UINT32 Channels, float *pVolumes)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_GetChannelVolumes(&This->IXAudio2SubmixVoice_iface,
+            Channels, pVolumes);
+}
+
+static HRESULT WINAPI XA20SUB_SetOutputMatrix(IXAudio20SubmixVoice *iface,
+        IXAudio2Voice *pDestinationVoice, UINT32 SubmixChannels,
+        UINT32 DestinationChannels, const float *pLevelMatrix,
+        UINT32 OperationSet)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_SetOutputMatrix(&This->IXAudio2SubmixVoice_iface,
+            pDestinationVoice, SubmixChannels, DestinationChannels,
+            pLevelMatrix, OperationSet);
+}
+
+static HRESULT WINAPI XA20SUB_GetOutputMatrix(IXAudio20SubmixVoice *iface,
+        IXAudio2Voice *pDestinationVoice, UINT32 SubmixChannels,
+        UINT32 DestinationChannels, float *pLevelMatrix)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    IXAudio2SubmixVoice_GetOutputMatrix(&This->IXAudio2SubmixVoice_iface,
+            pDestinationVoice, SubmixChannels, DestinationChannels,
+            pLevelMatrix);
+    return S_OK;
+}
+
+static void WINAPI XA20SUB_DestroyVoice(IXAudio20SubmixVoice *iface)
+{
+    XA2SubmixImpl *This = impl_from_IXAudio20SubmixVoice(iface);
+    return IXAudio2SubmixVoice_DestroyVoice(&This->IXAudio2SubmixVoice_iface);
+}
+
+const IXAudio20SubmixVoiceVtbl XAudio20SubmixVoice_Vtbl = {
+    XA20SUB_GetVoiceDetails,
+    XA20SUB_SetOutputVoices,
+    XA20SUB_SetEffectChain,
+    XA20SUB_EnableEffect,
+    XA20SUB_DisableEffect,
+    XA20SUB_GetEffectState,
+    XA20SUB_SetEffectParameters,
+    XA20SUB_GetEffectParameters,
+    XA20SUB_SetFilterParameters,
+    XA20SUB_GetFilterParameters,
+    XA20SUB_SetVolume,
+    XA20SUB_GetVolume,
+    XA20SUB_SetChannelVolumes,
+    XA20SUB_GetChannelVolumes,
+    XA20SUB_SetOutputMatrix,
+    XA20SUB_GetOutputMatrix,
+    XA20SUB_DestroyVoice
+};
+
+IXAudio2Impl *impl_from_IXAudio20MasteringVoice(IXAudio20MasteringVoice *iface)
+{
+    return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio20MasteringVoice_iface);
+}
+
+static void WINAPI XA20M_GetVoiceDetails(IXAudio20MasteringVoice *iface,
+        XAUDIO2_VOICE_DETAILS *pVoiceDetails)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_GetVoiceDetails(&This->IXAudio2MasteringVoice_iface, pVoiceDetails);
+}
+
+static HRESULT WINAPI XA20M_SetOutputVoices(IXAudio20MasteringVoice *iface,
+        const XAUDIO23_VOICE_SENDS *pSendList)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    XAUDIO2_VOICE_SENDS sends;
+    HRESULT hr;
+    DWORD i;
+
+    TRACE("%p, %p\n", This, pSendList);
+
+    sends.SendCount = pSendList->OutputCount;
+    sends.pSends = HeapAlloc(GetProcessHeap(), 0, sends.SendCount * sizeof(*sends.pSends));
+    for(i = 0; i < sends.SendCount; ++i){
+        sends.pSends[i].Flags = 0;
+        sends.pSends[i].pOutputVoice = pSendList->pOutputVoices[i];
+    }
+
+    hr = IXAudio2MasteringVoice_SetOutputVoices(&This->IXAudio2MasteringVoice_iface, &sends);
+
+    HeapFree(GetProcessHeap(), 0, sends.pSends);
+
+    return hr;
+}
+
+static HRESULT WINAPI XA20M_SetEffectChain(IXAudio20MasteringVoice *iface,
+        const XAUDIO2_EFFECT_CHAIN *pEffectChain)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_SetEffectChain(&This->IXAudio2MasteringVoice_iface, pEffectChain);
+}
+
+static HRESULT WINAPI XA20M_EnableEffect(IXAudio20MasteringVoice *iface,
+        UINT32 EffectIndex, UINT32 OperationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_EnableEffect(&This->IXAudio2MasteringVoice_iface,
+            EffectIndex, OperationSet);
+}
+
+static HRESULT WINAPI XA20M_DisableEffect(IXAudio20MasteringVoice *iface,
+        UINT32 EffectIndex, UINT32 OperationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_DisableEffect(&This->IXAudio2MasteringVoice_iface,
+            EffectIndex, OperationSet);
+}
+
+static void WINAPI XA20M_GetEffectState(IXAudio20MasteringVoice *iface,
+        UINT32 EffectIndex, BOOL *pEnabled)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_GetEffectState(&This->IXAudio2MasteringVoice_iface,
+            EffectIndex, pEnabled);
+}
+
+static HRESULT WINAPI XA20M_SetEffectParameters(IXAudio20MasteringVoice *iface,
+        UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
+        UINT32 OperationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_SetEffectParameters(&This->IXAudio2MasteringVoice_iface,
+            EffectIndex, pParameters, ParametersByteSize, OperationSet);
+}
+
+static HRESULT WINAPI XA20M_GetEffectParameters(IXAudio20MasteringVoice *iface,
+        UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_GetEffectParameters(&This->IXAudio2MasteringVoice_iface,
+            EffectIndex, pParameters, ParametersByteSize);
+}
+
+static HRESULT WINAPI XA20M_SetFilterParameters(IXAudio20MasteringVoice *iface,
+        const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_SetFilterParameters(&This->IXAudio2MasteringVoice_iface,
+            pParameters, OperationSet);
+}
+
+static void WINAPI XA20M_GetFilterParameters(IXAudio20MasteringVoice *iface,
+        XAUDIO2_FILTER_PARAMETERS *pParameters)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_GetFilterParameters(&This->IXAudio2MasteringVoice_iface, pParameters);
+}
+
+static HRESULT WINAPI XA20M_SetVolume(IXAudio20MasteringVoice *iface,
+        float Volume, UINT32 OperationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_SetVolume(&This->IXAudio2MasteringVoice_iface,
+            Volume, OperationSet);
+}
+
+static void WINAPI XA20M_GetVolume(IXAudio20MasteringVoice *iface,
+        float *pVolume)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_GetVolume(&This->IXAudio2MasteringVoice_iface, pVolume);
+}
+
+static HRESULT WINAPI XA20M_SetChannelVolumes(IXAudio20MasteringVoice *iface,
+        UINT32 Channels, const float *pVolumes, UINT32 OperationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_SetChannelVolumes(&This->IXAudio2MasteringVoice_iface,
+            Channels, pVolumes, OperationSet);
+}
+
+static void WINAPI XA20M_GetChannelVolumes(IXAudio20MasteringVoice *iface,
+        UINT32 Channels, float *pVolumes)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_GetChannelVolumes(&This->IXAudio2MasteringVoice_iface,
+            Channels, pVolumes);
+}
+
+static HRESULT WINAPI XA20M_SetOutputMatrix(IXAudio20MasteringVoice *iface,
+        IXAudio2Voice *pDestinationVoice, UINT32 MasteringChannels,
+        UINT32 DestinationChannels, const float *pLevelMatrix,
+        UINT32 OperationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_SetOutputMatrix(&This->IXAudio2MasteringVoice_iface,
+            pDestinationVoice, MasteringChannels, DestinationChannels,
+            pLevelMatrix, OperationSet);
+}
+
+static HRESULT WINAPI XA20M_GetOutputMatrix(IXAudio20MasteringVoice *iface,
+        IXAudio2Voice *pDestinationVoice, UINT32 MasteringChannels,
+        UINT32 DestinationChannels, float *pLevelMatrix)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    IXAudio2MasteringVoice_GetOutputMatrix(&This->IXAudio2MasteringVoice_iface,
+            pDestinationVoice, MasteringChannels, DestinationChannels,
+            pLevelMatrix);
+    return S_OK;
+}
+
+static void WINAPI XA20M_DestroyVoice(IXAudio20MasteringVoice *iface)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20MasteringVoice(iface);
+    return IXAudio2MasteringVoice_DestroyVoice(&This->IXAudio2MasteringVoice_iface);
+}
+
+const IXAudio20MasteringVoiceVtbl XAudio20MasteringVoice_Vtbl = {
+    XA20M_GetVoiceDetails,
+    XA20M_SetOutputVoices,
+    XA20M_SetEffectChain,
+    XA20M_EnableEffect,
+    XA20M_DisableEffect,
+    XA20M_GetEffectState,
+    XA20M_SetEffectParameters,
+    XA20M_GetEffectParameters,
+    XA20M_SetFilterParameters,
+    XA20M_GetFilterParameters,
+    XA20M_SetVolume,
+    XA20M_GetVolume,
+    XA20M_SetChannelVolumes,
+    XA20M_GetChannelVolumes,
+    XA20M_SetOutputMatrix,
+    XA20M_GetOutputMatrix,
+    XA20M_DestroyVoice
+};
+
+static inline IXAudio2Impl *impl_from_IXAudio20(IXAudio20 *iface)
+{
+    return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio20_iface);
+}
+
+static HRESULT WINAPI XA20_QueryInterface(IXAudio20 *iface, REFIID riid,
+        void **ppvObject)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_QueryInterface(&This->IXAudio2_iface, riid, ppvObject);
+}
+
+static ULONG WINAPI XA20_AddRef(IXAudio20 *iface)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_AddRef(&This->IXAudio2_iface);
+}
+
+static ULONG WINAPI XA20_Release(IXAudio20 *iface)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_Release(&This->IXAudio2_iface);
+}
+
+static HRESULT WINAPI XA20_GetDeviceCount(IXAudio20 *iface, UINT32 *pCount)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+
+    TRACE("%p, %p\n", This, pCount);
+
+    *pCount = This->ndevs;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI XA20_GetDeviceDetails(IXAudio20 *iface, UINT32 index,
+        XAUDIO2_DEVICE_DETAILS *pDeviceDetails)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    HRESULT hr;
+    IMMDevice *dev;
+    IAudioClient *client;
+    IPropertyStore *ps;
+    WAVEFORMATEX *wfx;
+    PROPVARIANT var;
+
+    TRACE("%p, %u, %p\n", This, index, pDeviceDetails);
+
+    if(index >= This->ndevs)
+        return E_INVALIDARG;
+
+    hr = IMMDeviceEnumerator_GetDevice(This->devenum, This->devids[index], &dev);
+    if(FAILED(hr)){
+        WARN("GetDevice failed: %08x\n", hr);
+        return hr;
+    }
+
+    hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
+            NULL, (void**)&client);
+    if(FAILED(hr)){
+        WARN("Activate failed: %08x\n", hr);
+        IMMDevice_Release(dev);
+        return hr;
+    }
+
+    hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &ps);
+    if(FAILED(hr)){
+        WARN("OpenPropertyStore failed: %08x\n", hr);
+        IAudioClient_Release(client);
+        IMMDevice_Release(dev);
+        return hr;
+    }
+
+    PropVariantInit(&var);
+
+    hr = IPropertyStore_GetValue(ps, (PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &var);
+    if(FAILED(hr)){
+        WARN("GetValue failed: %08x\n", hr);
+        goto done;
+    }
+
+    lstrcpynW(pDeviceDetails->DisplayName, var.u.pwszVal, sizeof(pDeviceDetails->DisplayName)/sizeof(WCHAR));
+
+    PropVariantClear(&var);
+
+    hr = IAudioClient_GetMixFormat(client, &wfx);
+    if(FAILED(hr)){
+        WARN("GetMixFormat failed: %08x\n", hr);
+        goto done;
+    }
+
+    lstrcpyW(pDeviceDetails->DeviceID, This->devids[index]);
+
+    if(index == 0)
+        pDeviceDetails->Role = GlobalDefaultDevice;
+    else
+        pDeviceDetails->Role = NotDefaultDevice;
+
+    if(sizeof(WAVEFORMATEX) + wfx->cbSize > sizeof(pDeviceDetails->OutputFormat)){
+        FIXME("AudioClient format is too large to fit into WAVEFORMATEXTENSIBLE!\n");
+        CoTaskMemFree(wfx);
+        hr = E_FAIL;
+        goto done;
+    }
+    memcpy(&pDeviceDetails->OutputFormat, wfx, sizeof(WAVEFORMATEX) + wfx->cbSize);
+
+    CoTaskMemFree(wfx);
+
+done:
+    IPropertyStore_Release(ps);
+    IAudioClient_Release(client);
+    IMMDevice_Release(dev);
+
+    return hr;
+}
+
+static HRESULT WINAPI XA20_Initialize(IXAudio20 *iface, UINT32 flags,
+        XAUDIO2_PROCESSOR processor)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    TRACE("(%p)->(0x%x, 0x%x)\n", This, flags, processor);
+    return S_OK;
+}
+
+static HRESULT WINAPI XA20_RegisterForCallbacks(IXAudio20 *iface,
+        IXAudio2EngineCallback *pCallback)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_RegisterForCallbacks(&This->IXAudio2_iface, pCallback);
+}
+
+static void WINAPI XA20_UnregisterForCallbacks(IXAudio20 *iface,
+        IXAudio2EngineCallback *pCallback)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_UnregisterForCallbacks(&This->IXAudio2_iface, pCallback);
+}
+
+static HRESULT WINAPI XA20_CreateSourceVoice(IXAudio20 *iface,
+        IXAudio2SourceVoice **ppSourceVoice, const WAVEFORMATEX *pSourceFormat,
+        UINT32 flags, float maxFrequencyRatio,
+        IXAudio2VoiceCallback *pCallback, const XAUDIO2_VOICE_SENDS *pSendList,
+        const XAUDIO2_EFFECT_CHAIN *pEffectChain)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_CreateSourceVoice(&This->IXAudio2_iface, ppSourceVoice,
+            pSourceFormat, flags, maxFrequencyRatio, pCallback, pSendList,
+            pEffectChain);
+}
+
+static HRESULT WINAPI XA20_CreateSubmixVoice(IXAudio20 *iface,
+        IXAudio2SubmixVoice **ppSubmixVoice, UINT32 inputChannels,
+        UINT32 inputSampleRate, UINT32 flags, UINT32 processingStage,
+        const XAUDIO2_VOICE_SENDS *pSendList,
+        const XAUDIO2_EFFECT_CHAIN *pEffectChain)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_CreateSubmixVoice(&This->IXAudio2_iface, ppSubmixVoice,
+            inputChannels, inputSampleRate, flags, processingStage, pSendList,
+            pEffectChain);
+}
+
+static HRESULT WINAPI XA20_CreateMasteringVoice(IXAudio20 *iface,
+        IXAudio2MasteringVoice **ppMasteringVoice, UINT32 inputChannels,
+        UINT32 inputSampleRate, UINT32 flags, UINT32 deviceIndex,
+        const XAUDIO2_EFFECT_CHAIN *pEffectChain)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+
+    TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p)\n", This, ppMasteringVoice,
+            inputChannels, inputSampleRate, flags, deviceIndex,
+            pEffectChain);
+
+    if(deviceIndex >= This->ndevs)
+        return E_INVALIDARG;
+
+    return IXAudio2_CreateMasteringVoice(&This->IXAudio2_iface, ppMasteringVoice,
+            inputChannels, inputSampleRate, flags, This->devids[deviceIndex],
+            pEffectChain, AudioCategory_GameEffects);
+}
+
+static HRESULT WINAPI XA20_StartEngine(IXAudio20 *iface)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_StartEngine(&This->IXAudio2_iface);
+}
+
+static void WINAPI XA20_StopEngine(IXAudio20 *iface)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_StopEngine(&This->IXAudio2_iface);
+}
+
+static HRESULT WINAPI XA20_CommitChanges(IXAudio20 *iface, UINT32 operationSet)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_CommitChanges(&This->IXAudio2_iface, operationSet);
+}
+
+static void WINAPI XA20_GetPerformanceData(IXAudio20 *iface,
+        XAUDIO20_PERFORMANCE_DATA *pPerfData)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    XAUDIO2_PERFORMANCE_DATA data;
+
+    IXAudio2_GetPerformanceData(&This->IXAudio2_iface, &data);
+
+    pPerfData->AudioCyclesSinceLastQuery = data.AudioCyclesSinceLastQuery;
+    pPerfData->TotalCyclesSinceLastQuery = data.TotalCyclesSinceLastQuery;
+    pPerfData->MinimumCyclesPerQuantum = data.MinimumCyclesPerQuantum;
+    pPerfData->MaximumCyclesPerQuantum = data.MaximumCyclesPerQuantum;
+    pPerfData->MemoryUsageInBytes = data.MemoryUsageInBytes;
+    pPerfData->CurrentLatencyInSamples = data.CurrentLatencyInSamples;
+    pPerfData->GlitchesSinceLastQuery = data.GlitchesSinceEngineStarted - This->last_query_glitches;
+    This->last_query_glitches = data.GlitchesSinceEngineStarted;
+    pPerfData->ActiveSourceVoiceCount = data.ActiveSourceVoiceCount;
+    pPerfData->TotalSourceVoiceCount = data.TotalSourceVoiceCount;
+
+    pPerfData->ActiveSubmixVoiceCount = data.ActiveSubmixVoiceCount;
+    pPerfData->TotalSubmixVoiceCount = data.ActiveSubmixVoiceCount;
+
+    pPerfData->ActiveXmaSourceVoices = data.ActiveXmaSourceVoices;
+    pPerfData->ActiveXmaStreams = data.ActiveXmaStreams;
+}
+
+static void WINAPI XA20_SetDebugConfiguration(IXAudio20 *iface,
+        const XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration,
+        void *pReserved)
+{
+    IXAudio2Impl *This = impl_from_IXAudio20(iface);
+    return IXAudio2_SetDebugConfiguration(&This->IXAudio2_iface,
+            pDebugConfiguration, pReserved);
+}
+
+const IXAudio20Vtbl XAudio20_Vtbl = {
+    XA20_QueryInterface,
+    XA20_AddRef,
+    XA20_Release,
+    XA20_GetDeviceCount,
+    XA20_GetDeviceDetails,
+    XA20_Initialize,
+    XA20_RegisterForCallbacks,
+    XA20_UnregisterForCallbacks,
+    XA20_CreateSourceVoice,
+    XA20_CreateSubmixVoice,
+    XA20_CreateMasteringVoice,
+    XA20_StartEngine,
+    XA20_StopEngine,
+    XA20_CommitChanges,
+    XA20_GetPerformanceData,
+    XA20_SetDebugConfiguration
+};
diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c
index 868cca3..feab321 100644
--- a/dlls/xaudio2_7/xaudio_dll.c
+++ b/dlls/xaudio2_7/xaudio_dll.c
@@ -38,6 +38,9 @@ static void (ALC_APIENTRY *palcRenderSamplesSOFT)(ALCdevice*, ALCvoid*, ALCsizei
 
 static HINSTANCE instance;
 
+#define COMPAT_E_INVALID_CALL(v) (v == 20) ? E_INVALIDARG : XAUDIO2_E_INVALID_CALL
+#define COMPAT_E_DEVICE_INVALIDATED(v) (v == 20) ? XAUDIO20_E_DEVICE_INVALIDATED : XAUDIO2_E_DEVICE_INVALIDATED
+
 static void dump_fmt(const WAVEFORMATEX *fmt)
 {
     TRACE("wFormatTag: 0x%x (", fmt->wFormatTag);
@@ -501,7 +504,7 @@ static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
     if(This->nbufs >= XAUDIO2_MAX_QUEUED_BUFFERS){
         TRACE("Too many buffers queued!\n");
         LeaveCriticalSection(&This->lock);
-        return XAUDIO2_E_INVALID_CALL;
+        return COMPAT_E_INVALID_CALL(This->xa2->version);
     }
 
     buf_idx = (This->first_buf + This->nbufs) % XAUDIO2_MAX_QUEUED_BUFFERS;
@@ -512,6 +515,11 @@ static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
      * but pBuffer itself may be reused immediately */
     memcpy(&buf->xa2buffer, pBuffer, sizeof(*pBuffer));
 
+    if(This->xa2->version == 20){
+        if(buf->xa2buffer.LoopCount == XAUDIO20_LOOP_INFINITE)
+            buf->xa2buffer.LoopCount = XAUDIO2_LOOP_INFINITE;
+    }
+
     /* convert samples offsets to bytes */
     if(This->fmt->wFormatTag == WAVE_FORMAT_ADPCM){
         /* ADPCM gives us a number of samples per block, so round down to
@@ -541,7 +549,7 @@ static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
         if(buf->xa2buffer.LoopBegin >= buf->play_end_bytes){
             /* this actually crashes on native xaudio 2.7 */
             LeaveCriticalSection(&This->lock);
-            return XAUDIO2_E_INVALID_CALL;
+            return COMPAT_E_INVALID_CALL(This->xa2->version);
         }
 
         buf->loop_end_bytes = buf->xa2buffer.LoopBegin + buf->xa2buffer.LoopLength;
@@ -551,12 +559,12 @@ static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
         if(This->xa2->version > 27){
             if(buf->loop_end_bytes > buf->play_end_bytes){
                 LeaveCriticalSection(&This->lock);
-                return XAUDIO2_E_INVALID_CALL;
+                return COMPAT_E_INVALID_CALL(This->xa2->version);
             }
 
             if(buf->loop_end_bytes <= buf->xa2buffer.PlayBegin){
                 LeaveCriticalSection(&This->lock);
-                return XAUDIO2_E_INVALID_CALL;
+                return COMPAT_E_INVALID_CALL(This->xa2->version);
             }
         }else{
             if(buf->loop_end_bytes <= buf->xa2buffer.PlayBegin){
@@ -732,7 +740,7 @@ static HRESULT WINAPI XA2SRC_SetSourceSampleRate(
 
     if(This->nbufs){
         LeaveCriticalSection(&This->lock);
-        return XAUDIO2_E_INVALID_CALL;
+        return COMPAT_E_INVALID_CALL(This->xa2->version);
     }
 
     This->fmt->nSamplesPerSec = NewSourceSampleRate;
@@ -1177,7 +1185,9 @@ static HRESULT WINAPI IXAudio2Impl_QueryInterface(IXAudio2 *iface, REFIID riid,
         *ppvObject = &This->IXAudio2_iface;
     else if(IsEqualGUID(riid, &IID_IXAudio27)){
         /* all xaudio versions before 28 share an IID */
-        if(This->version == 21 || This->version == 22)
+        if(This->version == 20)
+            *ppvObject = &This->IXAudio20_iface;
+        else if(This->version == 21 || This->version == 22)
             *ppvObject = &This->IXAudio22_iface;
         else
             *ppvObject = &This->IXAudio27_iface;
@@ -1352,6 +1362,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateSourceVoice(IXAudio2 *iface,
 
         list_add_head(&This->source_voices, &src->entry);
 
+        src->IXAudio20SourceVoice_iface.lpVtbl = &XAudio20SourceVoice_Vtbl;
         src->IXAudio23SourceVoice_iface.lpVtbl = &XAudio23SourceVoice_Vtbl;
         src->IXAudio27SourceVoice_iface.lpVtbl = &XAudio27SourceVoice_Vtbl;
         src->IXAudio2SourceVoice_iface.lpVtbl = &XAudio2SourceVoice_Vtbl;
@@ -1391,7 +1402,9 @@ static HRESULT WINAPI IXAudio2Impl_CreateSourceVoice(IXAudio2 *iface,
 
     alSourcePlay(src->al_src);
 
-    if(This->version <= 23)
+    if(This->version == 20)
+        *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio20SourceVoice_iface;
+    else if(This->version <= 23)
         *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio23SourceVoice_iface;
     else if(This->version <= 27)
         *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio27SourceVoice_iface;
@@ -1432,6 +1445,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface,
 
         list_add_head(&This->submix_voices, &sub->entry);
 
+        sub->IXAudio20SubmixVoice_iface.lpVtbl = &XAudio20SubmixVoice_Vtbl;
         sub->IXAudio23SubmixVoice_iface.lpVtbl = &XAudio23SubmixVoice_Vtbl;
         sub->IXAudio2SubmixVoice_iface.lpVtbl = &XAudio2SubmixVoice_Vtbl;
 
@@ -1443,7 +1457,9 @@ static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface,
 
     LeaveCriticalSection(&This->lock);
 
-    if(This->version <= 23)
+    if(This->version == 20)
+        *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio20SubmixVoice_iface;
+    else if(This->version <= 23)
         *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio23SubmixVoice_iface;
     else
         *ppSubmixVoice = &sub->IXAudio2SubmixVoice_iface;
@@ -1503,7 +1519,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
     /* there can only be one Mastering Voice, so just build it into XA2 */
     if(This->aclient){
         LeaveCriticalSection(&This->lock);
-        return XAUDIO2_E_INVALID_CALL;
+        return COMPAT_E_INVALID_CALL(This->version);
     }
 
     if(!deviceId){
@@ -1517,7 +1533,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
     hr = IMMDeviceEnumerator_GetDevice(This->devenum, deviceId, &dev);
     if(FAILED(hr)){
         WARN("GetDevice failed: %08x\n", hr);
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
@@ -1526,7 +1542,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
     if(FAILED(hr)){
         WARN("Activate(IAudioClient) failed: %08x\n", hr);
         IMMDevice_Release(dev);
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
@@ -1535,13 +1551,13 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
     hr = IAudioClient_GetMixFormat(This->aclient, &fmt);
     if(FAILED(hr)){
         WARN("GetMixFormat failed: %08x\n", hr);
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
     if(sizeof(WAVEFORMATEX) + fmt->cbSize > sizeof(WAVEFORMATEXTENSIBLE)){
         FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
@@ -1565,7 +1581,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
     if(hr == S_FALSE){
         if(sizeof(WAVEFORMATEX) + fmt->cbSize > sizeof(WAVEFORMATEXTENSIBLE)){
             FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
-            hr = XAUDIO2_E_DEVICE_INVALIDATED;
+            hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
             goto exit;
         }
         memcpy(&This->fmt, fmt, sizeof(WAVEFORMATEX) + fmt->cbSize);
@@ -1576,7 +1592,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
     hr = IAudioClient_GetDevicePeriod(This->aclient, &period, NULL);
     if(FAILED(hr)){
         WARN("GetDevicePeriod failed: %08x\n", hr);
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
@@ -1588,7 +1604,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
             0, &This->fmt.Format, NULL);
     if(FAILED(hr)){
         WARN("Initialize failed: %08x\n", hr);
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
@@ -1597,7 +1613,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
     hr = IAudioClient_SetEventHandle(This->aclient, This->mmevt);
     if(FAILED(hr)){
         WARN("Initialize failed: %08x\n", hr);
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
@@ -1605,7 +1621,7 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
             (void**)&This->render);
     if(FAILED(hr)){
         WARN("GetService(IAudioRenderClient) failed: %08x\n", hr);
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
@@ -1643,33 +1659,35 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
 
     if(!attrs[5]){
         WARN("OpenAL can't output samples in this format\n");
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
     This->al_device = palcLoopbackOpenDeviceSOFT(NULL);
     if(!This->al_device){
         WARN("alcLoopbackOpenDeviceSOFT failed\n");
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
     This->al_ctx = alcCreateContext(This->al_device, attrs);
     if(!This->al_ctx){
         WARN("alcCreateContext failed\n");
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
     if(alcMakeContextCurrent(This->al_ctx) == ALC_FALSE){
         WARN("alcMakeContextCurrent failed\n");
-        hr = XAUDIO2_E_DEVICE_INVALIDATED;
+        hr = COMPAT_E_DEVICE_INVALIDATED(This->version);
         goto exit;
     }
 
     IAudioClient_Start(This->aclient);
 
-    if(This->version <= 23)
+    if(This->version <= 20)
+        *ppMasteringVoice = (IXAudio2MasteringVoice*)&This->IXAudio20MasteringVoice_iface;
+    else if(This->version <= 23)
         *ppMasteringVoice = (IXAudio2MasteringVoice*)&This->IXAudio23MasteringVoice_iface;
     else
         *ppMasteringVoice = &This->IXAudio2MasteringVoice_iface;
@@ -1776,6 +1794,8 @@ typedef struct _VUMeterImpl {
     IXAPOParameters IXAPOParameters_iface;
 
     LONG ref;
+
+    DWORD version;
 } VUMeterImpl;
 
 static VUMeterImpl *VUMeterImpl_from_IXAPO(IXAPO *iface)
@@ -1838,6 +1858,7 @@ static HRESULT WINAPI VUMXAPO_GetRegistrationProperties(IXAPO *iface,
 {
     VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface);
     TRACE("%p, %p\n", This, props);
+    /* TODO: check for version == 20 and use XAPO20_REGISTRATION_PROPERTIES */
     return E_NOTIMPL;
 }
 
@@ -1978,6 +1999,8 @@ typedef struct _ReverbImpl {
     IXAPOParameters IXAPOParameters_iface;
 
     LONG ref;
+
+    DWORD version;
 } ReverbImpl;
 
 static ReverbImpl *ReverbImpl_from_IXAPO(IXAPO *iface)
@@ -2039,6 +2062,7 @@ static HRESULT WINAPI RVBXAPO_GetRegistrationProperties(IXAPO *iface,
 {
     ReverbImpl *This = ReverbImpl_from_IXAPO(iface);
     TRACE("%p, %p\n", This, props);
+    /* TODO: check for version == 20 and use XAPO20_REGISTRATION_PROPERTIES */
     return E_NOTIMPL;
 }
 
@@ -2308,9 +2332,11 @@ static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *p
     if(!object)
         return E_OUTOFMEMORY;
 
+    object->IXAudio20_iface.lpVtbl = &XAudio20_Vtbl;
     object->IXAudio22_iface.lpVtbl = &XAudio22_Vtbl;
     object->IXAudio27_iface.lpVtbl = &XAudio27_Vtbl;
     object->IXAudio2_iface.lpVtbl = &XAudio2_Vtbl;
+    object->IXAudio20MasteringVoice_iface.lpVtbl = &XAudio20MasteringVoice_Vtbl;
     object->IXAudio23MasteringVoice_iface.lpVtbl = &XAudio23MasteringVoice_Vtbl;
     object->IXAudio2MasteringVoice_iface.lpVtbl = &XAudio2MasteringVoice_Vtbl;
 
@@ -2346,70 +2372,83 @@ static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *p
     return hr;
 }
 
-static ULONG WINAPI static_AddRef(IClassFactory *iface)
+struct xapo_cf {
+    IClassFactory IClassFactory_iface;
+    LONG ref;
+    DWORD version;
+    const CLSID *class;
+};
+
+struct xapo_cf *xapo_impl_from_IClassFactory(IClassFactory *iface)
 {
-    return 2;
+    return CONTAINING_RECORD(iface, struct xapo_cf, IClassFactory_iface);
 }
 
-static ULONG WINAPI static_Release(IClassFactory *iface)
+static ULONG WINAPI xapo_AddRef(IClassFactory *iface)
 {
-    return 1;
+    struct xapo_cf *This = xapo_impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p)->(): Refcount now %u\n", This, ref);
+    return ref;
 }
 
-static HRESULT WINAPI VUMeterCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
-        REFIID riid, void **ppobj)
+static ULONG WINAPI xapo_Release(IClassFactory *iface)
 {
-    HRESULT hr;
-    VUMeterImpl *object;
-
-    TRACE("(static)->(%p,%s,%p)\n", pOuter, debugstr_guid(riid), ppobj);
-
-    *ppobj = NULL;
-
-    if(pOuter)
-        return CLASS_E_NOAGGREGATION;
-
-    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
-    if(!object)
-        return E_OUTOFMEMORY;
-
-    object->IXAPO_iface.lpVtbl = &VUMXAPO_Vtbl;
-    object->IXAPOParameters_iface.lpVtbl = &VUMXAPOParameters_Vtbl;
-
-    hr = IXAPO_QueryInterface(&object->IXAPO_iface, riid, ppobj);
-    if(FAILED(hr)){
-        HeapFree(GetProcessHeap(), 0, object);
-        return hr;
-    }
-
-    return S_OK;
+    struct xapo_cf *This = xapo_impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+    TRACE("(%p)->(): Refcount now %u\n", This, ref);
+    if (!ref)
+        HeapFree(GetProcessHeap(), 0, This);
+    return ref;
 }
 
-static HRESULT WINAPI ReverbCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
+static HRESULT WINAPI xapo_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
         REFIID riid, void **ppobj)
 {
+    struct xapo_cf *This = xapo_impl_from_IClassFactory(iface);
     HRESULT hr;
-    ReverbImpl *object;
 
-    TRACE("(static)->(%p,%s,%p)\n", pOuter, debugstr_guid(riid), ppobj);
+    TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
 
     *ppobj = NULL;
 
     if(pOuter)
         return CLASS_E_NOAGGREGATION;
 
-    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
-    if(!object)
-        return E_OUTOFMEMORY;
-
-    object->IXAPO_iface.lpVtbl = &RVBXAPO_Vtbl;
-    object->IXAPOParameters_iface.lpVtbl = &RVBXAPOParameters_Vtbl;
-
-    hr = IXAPO_QueryInterface(&object->IXAPO_iface, riid, ppobj);
-    if(FAILED(hr)){
-        HeapFree(GetProcessHeap(), 0, object);
-        return hr;
-    }
+    if(IsEqualGUID(This->class, &CLSID_AudioVolumeMeter)){
+        VUMeterImpl *object;
+
+        object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+        if(!object)
+            return E_OUTOFMEMORY;
+
+        object->IXAPO_iface.lpVtbl = &VUMXAPO_Vtbl;
+        object->IXAPOParameters_iface.lpVtbl = &VUMXAPOParameters_Vtbl;
+        object->version = This->version;
+
+        hr = IXAPO_QueryInterface(&object->IXAPO_iface, riid, ppobj);
+        if(FAILED(hr)){
+            HeapFree(GetProcessHeap(), 0, object);
+            return hr;
+        }
+    }else if(IsEqualGUID(This->class, &CLSID_AudioReverb)){
+        ReverbImpl *object;
+
+        object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
+        if(!object)
+            return E_OUTOFMEMORY;
+
+        object->IXAPO_iface.lpVtbl = &RVBXAPO_Vtbl;
+        object->IXAPOParameters_iface.lpVtbl = &RVBXAPOParameters_Vtbl;
+        object->version = This->version;
+
+        hr = IXAPO_QueryInterface(&object->IXAPO_iface, riid, ppobj);
+        if(FAILED(hr)){
+            HeapFree(GetProcessHeap(), 0, object);
+            return hr;
+        }
+    }else
+        return E_INVALIDARG;
 
     return S_OK;
 }
@@ -2429,43 +2468,43 @@ static const IClassFactoryVtbl XAudio2CF_Vtbl =
     XAudio2CF_LockServer
 };
 
-static const IClassFactoryVtbl VUMeterCF_Vtbl =
+static const IClassFactoryVtbl xapo_Vtbl =
 {
     XAudio2CF_QueryInterface,
-    static_AddRef,
-    static_Release,
-    VUMeterCF_CreateInstance,
+    xapo_AddRef,
+    xapo_Release,
+    xapo_CreateInstance,
     XAudio2CF_LockServer
 };
 
-static const IClassFactoryVtbl ReverbCF_Vtbl =
-{
-    XAudio2CF_QueryInterface,
-    static_AddRef,
-    static_Release,
-    ReverbCF_CreateInstance,
-    XAudio2CF_LockServer
-};
-
-static IClassFactory vumeter_cf = { &VUMeterCF_Vtbl };
-static IClassFactory reverb_cf = { &ReverbCF_Vtbl };
-
 static IClassFactory *make_xaudio2_factory(DWORD version)
 {
-    struct xaudio2_cf *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct xaudio2_cf));
+    struct xapo_cf *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct xaudio2_cf));
     ret->IClassFactory_iface.lpVtbl = &XAudio2CF_Vtbl;
     ret->version = version;
     ret->ref = 0;
     return &ret->IClassFactory_iface;
 }
 
+static IClassFactory *make_xapo_factory(REFCLSID clsid, DWORD version)
+{
+    struct xapo_cf *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct xaudio2_cf));
+    ret->IClassFactory_iface.lpVtbl = &XAudio2CF_Vtbl;
+    ret->version = version;
+    ret->class = clsid;
+    ret->ref = 0;
+    return &ret->IClassFactory_iface;
+}
+
 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
 {
     IClassFactory *factory = NULL;
 
     TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
 
-    if IsEqualGUID(rclsid, &CLSID_XAudio21){
+    if IsEqualGUID(rclsid, &CLSID_XAudio20){
+        factory = make_xaudio2_factory(20);
+    }else if IsEqualGUID(rclsid, &CLSID_XAudio21){
         factory = make_xaudio2_factory(21);
     }else if IsEqualGUID(rclsid, &CLSID_XAudio22){
         factory = make_xaudio2_factory(22);
@@ -2479,22 +2518,40 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
         factory = make_xaudio2_factory(26);
     }else if(IsEqualGUID(rclsid, &CLSID_XAudio2)){
         factory = make_xaudio2_factory(27);
-    }else if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter) ||
-            IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter21) ||
-            IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter22) ||
-            IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter23) ||
-            IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter24) ||
-            IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter25) ||
-            IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter26)){
-        factory = &vumeter_cf;
-    }else if(IsEqualGUID(rclsid, &CLSID_AudioReverb) ||
-            IsEqualGUID(rclsid, &CLSID_AudioReverb21) ||
-            IsEqualGUID(rclsid, &CLSID_AudioReverb22) ||
-            IsEqualGUID(rclsid, &CLSID_AudioReverb23) ||
-            IsEqualGUID(rclsid, &CLSID_AudioReverb24) ||
-            IsEqualGUID(rclsid, &CLSID_AudioReverb25) ||
-            IsEqualGUID(rclsid, &CLSID_AudioReverb26)){
-        factory = &reverb_cf;
+
+    }else if IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter20){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 20);
+    }else if IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter21){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 21);
+    }else if IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter22){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 22);
+    }else if IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter23){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 23);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter24)){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 24);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter25)){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 25);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter26)){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 26);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter)){
+        factory = make_xapo_factory(&CLSID_AudioVolumeMeter, 27);
+
+    }else if IsEqualGUID(rclsid, &CLSID_AudioReverb20){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 20);
+    }else if IsEqualGUID(rclsid, &CLSID_AudioReverb21){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 21);
+    }else if IsEqualGUID(rclsid, &CLSID_AudioReverb22){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 22);
+    }else if IsEqualGUID(rclsid, &CLSID_AudioReverb23){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 23);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioReverb24)){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 24);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioReverb25)){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 25);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioReverb26)){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 26);
+    }else if(IsEqualGUID(rclsid, &CLSID_AudioReverb)){
+        factory = make_xapo_factory(&CLSID_AudioReverb, 27);
     }
     if(!factory) return CLASS_E_CLASSNOTAVAILABLE;
 
@@ -2679,9 +2736,13 @@ static void do_engine_tick(IXAudio2Impl *This)
             continue;
         }
 
-        if(src->cb)
-            /* TODO: detect incoming underrun and inform callback */
-            IXAudio2VoiceCallback_OnVoiceProcessingPassStart(src->cb, 0);
+        if(src->cb){
+            if(This->version == 20)
+                IXAudio20VoiceCallback_OnVoiceProcessingPassStart((IXAudio20VoiceCallback*)src->cb);
+            else
+                /* TODO: detect incoming underrun and inform callback */
+                IXAudio2VoiceCallback_OnVoiceProcessingPassStart(src->cb, 0);
+        }
 
         update_source_state(src);
 
diff --git a/dlls/xaudio2_7/xaudio_private.h b/dlls/xaudio2_7/xaudio_private.h
index 91966ca..7772a5b 100644
--- a/dlls/xaudio2_7/xaudio_private.h
+++ b/dlls/xaudio2_7/xaudio_private.h
@@ -42,6 +42,7 @@ typedef struct _XA2Buffer {
 typedef struct _IXAudio2Impl IXAudio2Impl;
 
 typedef struct _XA2SourceImpl {
+    IXAudio20SourceVoice IXAudio20SourceVoice_iface;
     IXAudio23SourceVoice IXAudio23SourceVoice_iface;
     IXAudio27SourceVoice IXAudio27SourceVoice_iface;
     IXAudio2SourceVoice IXAudio2SourceVoice_iface;
@@ -81,6 +82,7 @@ typedef struct _XA2SourceImpl {
 } XA2SourceImpl;
 
 typedef struct _XA2SubmixImpl {
+    IXAudio20SubmixVoice IXAudio20SubmixVoice_iface;
     IXAudio23SubmixVoice IXAudio23SubmixVoice_iface;
     IXAudio2SubmixVoice IXAudio2SubmixVoice_iface;
 
@@ -92,9 +94,11 @@ typedef struct _XA2SubmixImpl {
 } XA2SubmixImpl;
 
 struct _IXAudio2Impl {
+    IXAudio20 IXAudio20_iface;
     IXAudio22 IXAudio22_iface;
     IXAudio27 IXAudio27_iface;
     IXAudio2 IXAudio2_iface;
+    IXAudio20MasteringVoice IXAudio20MasteringVoice_iface;
     IXAudio23MasteringVoice IXAudio23MasteringVoice_iface;
     IXAudio2MasteringVoice IXAudio2MasteringVoice_iface;
 
@@ -115,6 +119,8 @@ struct _IXAudio2Impl {
     WCHAR **devids;
     UINT32 ndevs;
 
+    UINT32 last_query_glitches;
+
     IAudioClient *aclient;
     IAudioRenderClient *render;
 
@@ -139,3 +145,8 @@ extern const IXAudio23SubmixVoiceVtbl XAudio23SubmixVoice_Vtbl DECLSPEC_HIDDEN;
 extern const IXAudio23MasteringVoiceVtbl XAudio23MasteringVoice_Vtbl DECLSPEC_HIDDEN;
 
 extern const IXAudio22Vtbl XAudio22_Vtbl DECLSPEC_HIDDEN;
+
+extern const IXAudio20Vtbl XAudio20_Vtbl DECLSPEC_HIDDEN;
+extern const IXAudio20SourceVoiceVtbl XAudio20SourceVoice_Vtbl DECLSPEC_HIDDEN;
+extern const IXAudio20SubmixVoiceVtbl XAudio20SubmixVoice_Vtbl DECLSPEC_HIDDEN;
+extern const IXAudio20MasteringVoiceVtbl XAudio20MasteringVoice_Vtbl DECLSPEC_HIDDEN;
diff --git a/include/xapo.idl b/include/xapo.idl
index 9055775..de09ba0 100644
--- a/include/xapo.idl
+++ b/include/xapo.idl
@@ -60,6 +60,22 @@ typedef struct XAPO_REGISTRATION_PROPERTIES
     UINT32 MaxOutputBufferCount;
 } XAPO_REGISTRATION_PROPERTIES;
 
+typedef struct XAPO20_REGISTRATION_PROPERTIES
+{
+    CLSID clsid;
+    WCHAR FriendlyName[XAPO_REGISTRATION_STRING_LENGTH];
+    WCHAR CopyrightInfo[XAPO_REGISTRATION_STRING_LENGTH];
+    UINT32 MajorVersion;
+    UINT32 MinorVersion;
+    UINT32 Flags;
+    UINT32 MinInputBufferCount;
+    UINT32 MaxInputBufferCount;
+    UINT32 MinOutputBufferCount;
+    UINT32 MaxOutputBufferCount;
+    UINT32 InterfaceCount;
+    IID InterfaceArray[1];
+} XAPO20_REGISTRATION_PROPERTIES;
+
 typedef struct XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS {
     const WAVEFORMATEX *pFormat;
     UINT32 MaxFrameCount;
diff --git a/include/xaudio2.idl b/include/xaudio2.idl
index 5d4726a..84bd456 100644
--- a/include/xaudio2.idl
+++ b/include/xaudio2.idl
@@ -31,6 +31,13 @@ coclass XAudio2 {
 }
 
 [
+    uuid(fac23f48-31f5-45a8-b49b-5225d61401aa)
+]
+coclass XAudio20 {
+    interface IUnknown;
+}
+
+[
     uuid(e21a7345-eb21-468e-be50-804db97cf708)
 ]
 coclass XAudio21 {
@@ -180,6 +187,23 @@ typedef struct XAUDIO22_PERFORMANCE_DATA
     UINT32 ActiveXmaStreams;
 } XAUDIO22_PERFORMANCE_DATA;
 
+typedef struct XAUDIO20_PERFORMANCE_DATA
+{
+    UINT64 AudioCyclesSinceLastQuery;
+    UINT64 TotalCyclesSinceLastQuery;
+    UINT32 MinimumCyclesPerQuantum;
+    UINT32 MaximumCyclesPerQuantum;
+    UINT32 MemoryUsageInBytes;
+    UINT32 CurrentLatencyInSamples;
+    UINT32 GlitchesSinceLastQuery;
+    UINT32 ActiveSourceVoiceCount;
+    UINT32 TotalSourceVoiceCount;
+    UINT32 ActiveSubmixVoiceCount;
+    UINT32 TotalSubmixVoiceCount;
+    UINT32 ActiveXmaSourceVoices;
+    UINT32 ActiveXmaStreams;
+} XAUDIO20_PERFORMANCE_DATA;
+
 typedef enum XAUDIO2_DEVICE_ROLE
 {
     NotDefaultDevice            = 0x0,
@@ -251,12 +275,14 @@ const float XAUDIO2_DEFAULT_FREQ_RATIO = 2.0;
 const float XAUDIO2_MAX_FILTER_ONEOVERQ = 1.5;
 const float XAUDIO2_MAX_FILTER_FREQUENCY = 1.0;
 const UINT32 XAUDIO2_MAX_LOOP_COUNT = 254;
+const UINT32 XAUDIO20_MAX_LOOP_COUNT = 0x100000; /* xaudio 2.0 */
 
 const UINT32 XAUDIO2_COMMIT_NOW = 0;
 const UINT32 XAUDIO2_COMMIT_ALL = 0;
 const UINT32 XAUDIO2_INVALID_OPSET = 0xffffffff;
 const UINT32 XAUDIO2_NO_LOOP_REGION = 0;
 const UINT32 XAUDIO2_LOOP_INFINITE = 255;
+const UINT32 XAUDIO20_LOOP_INFINITE = ((UINT)-1); /* xaudio 2.0 */
 const UINT32 XAUDIO2_DEFAULT_CHANNELS = 0;
 const UINT32 XAUDIO2_DEFAULT_SAMPLERATE = 0;
 
@@ -288,6 +314,81 @@ typedef struct XAUDIO2_FILTER_PARAMETERS
     float OneOverQ;
 } XAUDIO2_FILTER_PARAMETERS;
 
+/* XAudio 2.0's IXAudio2Voice */
+/* XAudio2 2.0's IXAudio2Voice interface. Actually called
+ * IXAudio2Voice in the Mar 2008 DX SDK */
+[
+    object,
+    local
+]
+interface IXAudio20Voice
+{
+    void GetVoiceDetails([out] XAUDIO2_VOICE_DETAILS* pVoiceDetails);
+
+    HRESULT SetOutputVoices([in] const XAUDIO23_VOICE_SENDS* pSendList);
+
+    HRESULT SetEffectChain([in] const XAUDIO2_EFFECT_CHAIN* pEffectChain);
+
+    HRESULT EnableEffect(
+        [in] UINT32 EffectIndex,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    HRESULT DisableEffect(
+        [in] UINT32 EffectIndex,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    void GetEffectState(
+        [in] UINT32 EffectIndex,
+        [out] BOOL* pEnabled);
+
+    HRESULT SetEffectParameters(
+        [in] UINT32 EffectIndex,
+        [in] const void* pParameters,
+        [in] UINT32 ParametersByteSize,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    HRESULT GetEffectParameters(
+        [in] UINT32 EffectIndex,
+        [out] void* pParameters,
+        [in] UINT32 ParametersByteSize);
+
+    HRESULT SetFilterParameters(
+        [in] const XAUDIO2_FILTER_PARAMETERS* pParameters,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    void GetFilterParameters([out] XAUDIO2_FILTER_PARAMETERS* pParameters);
+
+    HRESULT SetVolume(
+        [in] float Volume,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    void GetVolume([out] float* pVolume);
+
+    HRESULT SetChannelVolumes(
+        [in] UINT32 Channels,
+        [in, size_is(Channels)] const float* pVolumes,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    void GetChannelVolumes(
+        [in] UINT32 Channels,
+        [out, size_is(Channels)] float* pVolumes);
+
+    HRESULT SetOutputMatrix(
+        [in] IXAudio2Voice* pDestinationVoice,
+        [in] UINT32 SourceChannels,
+        [in] UINT32 DestinationChannels,
+        [in, size_is(SourceChannels * DestinationChannels)] const float* pLevelMatrix,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    HRESULT GetOutputMatrix(
+        [in] IXAudio2Voice* pDestinationVoice,
+        [in] UINT32 SourceChannels,
+        [in] UINT32 DestinationChannels,
+        [out, size_is(SourceChannels * DestinationChannels)] float* pLevelMatrix);
+
+    void DestroyVoice();
+}
+
 /* XAudio 2.3's IXAudio2Voice */
 /* XAudio2 2.3's IXAudio2Voice interface. Actually called
  * IXAudio2Voice in the Nov 2008 DX SDK */
@@ -362,6 +463,7 @@ interface IXAudio23Voice
 
     void DestroyVoice();
 }
+
 [
     object,
     local
@@ -472,6 +574,40 @@ typedef struct XAUDIO2_VOICE_STATE
 [
     local
 ]
+/* XAudio2 2.0's IXAudio2SourceVoice interface. Actually called
+ * IXAudio2SourceVoice in the Mar 2008 DX SDK */
+interface IXAudio20SourceVoice : IXAudio20Voice
+{
+    HRESULT Start(
+        [in, defaultvalue(0)] UINT32 Flags,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    HRESULT Stop(
+        [in, defaultvalue(0)] UINT32 Flags,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    HRESULT SubmitSourceBuffer(
+        [in] const XAUDIO2_BUFFER* pBuffer,
+        [in, defaultvalue(NULL)] const XAUDIO2_BUFFER_WMA* pBufferWMA);
+
+    HRESULT FlushSourceBuffers();
+
+    HRESULT Discontinuity();
+
+    HRESULT ExitLoop([in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    void GetState([out] XAUDIO2_VOICE_STATE* pVoiceState);
+
+    HRESULT SetFrequencyRatio(
+        [in] float Ratio,
+        [in, defaultvalue(XAUDIO2_COMMIT_NOW)] UINT32 OperationSet);
+
+    void GetFrequencyRatio([out] float* pRatio);
+}
+
+[
+    local
+]
 /* XAudio2 2.3's IXAudio2SourceVoice interface. Actually called
  * IXAudio2SourceVoice in the Nov 2008 DX SDK */
 interface IXAudio23SourceVoice : IXAudio23Voice
@@ -577,6 +713,15 @@ interface IXAudio2SourceVoice : IXAudio2Voice
 [
     local
 ]
+/* XAudio2 2.0's IXAudio2SubmixVoice interface. Actually called
+ * IXAudio2SubmixVoice in the Mar 2008 DX SDK */
+interface IXAudio20SubmixVoice : IXAudio20Voice
+{
+}
+
+[
+    local
+]
 /* XAudio2 2.3's IXAudio2SubmixVoice interface. Actually called
  * IXAudio2SubmixVoice in the Nov 2008 DX SDK */
 interface IXAudio23SubmixVoice : IXAudio23Voice
@@ -593,6 +738,15 @@ interface IXAudio2SubmixVoice : IXAudio2Voice
 [
     local
 ]
+/* XAudio2 2.0's IXAudio2MasteringVoice interface. Actually called
+ * IXAudio2MasteringVoice in the Mar 2008 DX SDK */
+interface IXAudio20MasteringVoice : IXAudio20Voice
+{
+}
+
+[
+    local
+]
 /* XAudio2 2.3's IXAudio2MasteringVoice interface. Actually called
  * IXAudio2MasteringVoice in the Nov 2008 DX SDK */
 interface IXAudio23MasteringVoice : IXAudio23Voice
@@ -612,6 +766,29 @@ interface IXAudio2MasteringVoice : IXAudio2Voice
     object,
     local
 ]
+interface IXAudio20VoiceCallback
+{
+    void OnVoiceProcessingPassStart();
+
+    void OnVoiceProcessingPassEnd();
+
+    void OnStreamEnd();
+
+    void OnBufferStart([in] void* pBufferContext);
+
+    void OnBufferEnd([in] void* pBufferContext);
+
+    void OnLoopEnd([in] void* pBufferContext);
+
+    void OnVoiceError(
+        [in] void* pBuffercontext,
+        [in] HRESULT Error);
+}
+
+[
+    object,
+    local
+]
 interface IXAudio2VoiceCallback
 {
     void OnVoiceProcessingPassStart([in] UINT32 BytesRequired);
@@ -645,6 +822,67 @@ typedef struct XAUDIO2_DEBUG_CONFIGURATION
     object,
     uuid(8bcf1f58-9fe7-4583-8ac6-e2adc465c8bb), /* all versions before 28 share IID_IXAudio */
 ]
+/* XAudio2 2.0's IXAudio2 interface. Actually called IXAudio2 in the Mar 2008
+ * DX SDK */
+interface IXAudio20 : IUnknown
+{
+    HRESULT GetDeviceCount([out] UINT32* pCount);
+
+    HRESULT GetDeviceDetails(
+        [in] UINT32 Index,
+        [out] XAUDIO2_DEVICE_DETAILS* pDeviceDetails);
+
+    HRESULT Initialize(
+        [in, defaultvalue(0)] UINT32 Flags,
+        [in, defaultvalue(XAUDIO2_DEFAULT_PROCESSOR)] XAUDIO2_PROCESSOR XAudio2Processor);
+
+    HRESULT RegisterForCallbacks([in] IXAudio2EngineCallback* pCallback);
+
+    void UnregisterForCallbacks([in] IXAudio2EngineCallback* pCallback);
+
+    HRESULT CreateSourceVoice(
+        [out] IXAudio2SourceVoice** ppSourceVoice,
+        [in] const WAVEFORMATEX* pSourceFormat,
+        [in, defaultvalue(0)] UINT32 Flags,
+        [in, defaultvalue(XAUDIO2_DEFAULT_FREQ_RATIO)] float MaxFrequencyRatio,
+        [in, defaultvalue(NULL)] IXAudio2VoiceCallback* pCallback,
+        [in, defaultvalue(NULL)] const XAUDIO2_VOICE_SENDS* pSendList,
+        [in, defaultvalue(NULL)] const XAUDIO2_EFFECT_CHAIN* pEffectChain);
+
+    HRESULT CreateSubmixVoice(
+        [out] IXAudio2SubmixVoice** ppSubmixVoice,
+        [in] UINT32 InputChannels,
+        [in] UINT32 InputSampleRate,
+        [in, defaultvalue(0)] UINT32 Flags,
+        [in, defaultvalue(0)] UINT32 ProcessingStage,
+        [in, defaultvalue(NULL)] const XAUDIO2_VOICE_SENDS* pSendList,
+        [in, defaultvalue(NULL)] const XAUDIO2_EFFECT_CHAIN* pEffectChain);
+
+    HRESULT CreateMasteringVoice(
+        [out] IXAudio2MasteringVoice** ppMasteringVoice,
+        [in, defaultvalue(XAUDIO2_DEFAULT_CHANNELS)] UINT32 InputChannels,
+        [in, defaultvalue(XAUDIO2_DEFAULT_SAMPLERATE)] UINT32 InputSampleRate,
+        [in, defaultvalue(0)] UINT32 Flags,
+        [in, defaultvalue(0)] UINT32 DeviceIndex,
+        [in, defaultvalue(NULL)] const XAUDIO2_EFFECT_CHAIN* pEffectChain);
+
+    HRESULT StartEngine();
+
+    void StopEngine();
+
+    HRESULT CommitChanges([in] UINT32 OperationSet);
+
+    void GetPerformanceData([out] XAUDIO20_PERFORMANCE_DATA* pPerfData);
+
+    [local] void SetDebugConfiguration(
+        [in] const XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration,
+        [in, defaultvalue(NULL)] void* pReserved);
+}
+
+[
+    object,
+    uuid(8bcf1f58-9fe7-4583-8ac6-e2adc465c8bb), /* all versions before 28 share IID_IXAudio */
+]
 /* XAudio2 2.2's IXAudio2 interface. Actually called IXAudio2 in the Jun 2010
  * DX SDK */
 interface IXAudio22 : IUnknown
@@ -836,6 +1074,11 @@ const HRESULT XAUDIO2_E_XMA_DECODER_ERROR = 0x88960002;
 const HRESULT XAUDIO2_E_XAPO_CREATION_FAILED = 0x88960003;
 const HRESULT XAUDIO2_E_DEVICE_INVALIDATED = 0x88960004;
 
+/* xaudio 2.0 error codes */
+const HRESULT XAUDIO20_E_XMA_DECODER_ERROR = 0x88960001;
+const HRESULT XAUDIO20_E_XAPO_CREATION_FAILED = 0x88960002;
+const HRESULT XAUDIO20_E_DEVICE_INVALIDATED = 0x88960003;
+
 cpp_quote("#ifdef XAUDIO2_HELPER_FUNCTIONS")
 cpp_quote("#define _USE_MATH_DEFINES")
 cpp_quote("#include <math.h>")
diff --git a/include/xaudio2fx.idl b/include/xaudio2fx.idl
index c152b98..ad58232 100644
--- a/include/xaudio2fx.idl
+++ b/include/xaudio2fx.idl
@@ -26,6 +26,13 @@ coclass AudioVolumeMeter {
 }
 
 [
+    uuid(c0c56f46-29b1-44e9-9939-a32ce86867e2)
+]
+coclass AudioVolumeMeter20 {
+    interface IUnknown;
+}
+
+[
     uuid(c1e3f122-a2ea-442c-854f-20d98f8357a1)
 ]
 coclass AudioVolumeMeter21 {
@@ -75,6 +82,13 @@ coclass AudioReverb {
 }
 
 [
+    uuid(6f6ea3a9-2cf5-41cf-91c1-2170b1540063)
+]
+coclass AudioReverb20 {
+    interface IUnknown;
+}
+
+[
     uuid(f4769300-b949-4df9-b333-00d33932e9a6)
 ]
 coclass AudioReverb21 {
-- 
2.6.1




More information about the wine-patches mailing list