Navigation Menu

Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
WinRT: got the XAudio2 backend compiling (but not running, yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidLudwig committed Nov 23, 2012
1 parent 65dfa99 commit 30e298d
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 12 deletions.
30 changes: 24 additions & 6 deletions VisualC/SDL/SDL_VS2012_WinRT.vcxproj
Expand Up @@ -37,6 +37,22 @@
<ClCompile Include="..\..\src\audio\SDL_audiotypecvt.c" />
<ClCompile Include="..\..\src\audio\SDL_mixer.c" />
<ClCompile Include="..\..\src\audio\SDL_wave.c" />
<ClCompile Include="..\..\src\audio\xaudio2\SDL_xaudio2.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">CompileAsCpp</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">CompileAsCpp</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompileAsCpp</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CompileAsCpp</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">CompileAsCpp</CompileAs>
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">CompileAsCpp</CompileAs>
</ClCompile>
<ClCompile Include="..\..\src\audio\xaudio2\SDL_xaudio2_winrthelpers.cpp">
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
</ClCompile>
<ClCompile Include="..\..\src\cpuinfo\SDL_cpuinfo.c" />
<ClCompile Include="..\..\src\events\SDL_clipboardevents.c" />
<ClCompile Include="..\..\src\events\SDL_dropevents.c" />
Expand Down Expand Up @@ -206,6 +222,8 @@
<ClInclude Include="..\..\src\audio\SDL_audio_c.h" />
<ClInclude Include="..\..\src\audio\SDL_sysaudio.h" />
<ClInclude Include="..\..\src\audio\SDL_wave.h" />
<ClInclude Include="..\..\src\audio\xaudio2\SDL_xaudio2_winrthelpers.h" />
<ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
<ClInclude Include="..\..\src\events\blank_cursor.h" />
<ClInclude Include="..\..\src\events\default_cursor.h" />
<ClInclude Include="..\..\src\events\SDL_clipboardevents_c.h" />
Expand Down Expand Up @@ -384,7 +402,7 @@
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<AdditionalDependencies>d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>xaudio2.lib;d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
Expand All @@ -398,7 +416,7 @@
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<AdditionalDependencies>d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>xaudio2.lib;d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm'">
Expand All @@ -412,7 +430,7 @@
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<AdditionalDependencies>d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>xaudio2.lib;d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm'">
Expand All @@ -426,7 +444,7 @@
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<AdditionalDependencies>d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>xaudio2.lib;d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
Expand All @@ -440,7 +458,7 @@
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<AdditionalDependencies>d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>xaudio2.lib;d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
Expand All @@ -454,7 +472,7 @@
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<AdditionalDependencies>d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>xaudio2.lib;d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;kernel32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Expand Down
2 changes: 1 addition & 1 deletion include/SDL_config_windowsrt.h
Expand Up @@ -144,7 +144,7 @@ typedef unsigned int uintptr_t;
#endif

/* Enable various audio drivers */
//#define SDL_AUDIO_DRIVER_XAUDIO2 1 // TODO, WinRT: see if SDL's XAudio2 driver can compile
#define SDL_AUDIO_DRIVER_XAUDIO2 1
#define SDL_AUDIO_DRIVER_DISK 1
#define SDL_AUDIO_DRIVER_DUMMY 1

Expand Down
135 changes: 130 additions & 5 deletions src/audio/xaudio2/SDL_xaudio2.c
Expand Up @@ -18,22 +18,90 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

/* WinRT NOTICE:
A number of changes were warranted to SDL's XAudio2 backend in order to
get it compiling for Windows RT.
When compiling for WinRT, XAudio2.h requires that it be compiled in a C++
file, and not a straight C file. Trying to compile it as C leads to lots
of errors, at least with MSVC 2012 and Windows SDK 8.0, as of Nov 22, 2012.
To address this specific issue, a few changes were made to SDL_xaudio2.c:
1. SDL_xaudio2.c is compiled as a C++ file in WinRT builds. Exported
symbols, namely XAUDIO2_bootstrap, uses 'extern "C"' to make sure the
rest of SDL can access it. Non-WinRT builds continue to compile
SDL_xaudio2.c as a C file.
2. A macro redefines variables named 'this' to '_this', to prevent compiler
errors (C2355 in Visual C++) related to 'this' being a reserverd keyword.
This hack may need to be altered in the future, particularly if C++'s
'this' keyword needs to be used (within SDL_xaudio2.c). At the time
WinRT support was initially added to SDL's XAudio2 backend, this
capability was not needed.
3. The C-style macros to invoke XAudio2's COM-based methods were
rewritten to be C++-friendly. These are provided in the file,
SDL_xaudio2_winrthelpers.h.
4. IXAudio2::CreateSourceVoice, when used in C++, requires its callbacks to
be specified via a C++ class. SDL's XAudio2 backend was written with
C-style callbacks. A class to bridge these two interfaces,
SDL_XAudio2VoiceCallback, was written to make XAudio2 happy. Its methods
just call SDL's existing, C-style callbacks.
5. Multiple checks for the __cplusplus macro were made, in appropriate
places.
A few additional changes to SDL's XAudio2 backend were warranted by API
changes to Windows. Many, but not all of these are documented by Microsoft
at:
http://blogs.msdn.com/b/chuckw/archive/2012/04/02/xaudio2-and-windows-8-consumer-preview.aspx
1. Windows' thread synchronization function, CreateSemaphore, was removed
from Windows RT. SDL's semaphore API was substituted instead.
2. The method calls, IXAudio2::GetDeviceCount and IXAudio2::GetDeviceDetails
were removed from the XAudio2 API. Microsoft is telling developers to
use APIs in Windows::Foundation instead.
For SDL, the missing methods were reimplemented using the APIs Microsoft
said to use.
3. CoInitialize and CoUninitialize are not available in Windows RT.
These calls were removed, as COM will have been initialized earlier,
at least by the call to the WinRT app's main function
(aka 'int main(Platform::Array<Platform::String^>^)). (DLudwig:
This was my understanding of how WinRT: the 'main' function uses
a tag of [MTAThread], which should initialize COM. My understanding
of COM is somewhat limited, and I may be incorrect here.)
4. IXAudio2::CreateMasteringVoice changed its integer-based 'DeviceIndex'
argument to a string-based one, 'szDeviceId'. In Windows RT, the
string-based argument will be used.
*/

#include "SDL_config.h"

#if SDL_AUDIO_DRIVER_XAUDIO2

#ifdef __cplusplus
extern "C" {
#endif
#include "../../core/windows/SDL_windows.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
#include "SDL_assert.h"
#ifdef __cplusplus
}
#endif

#if defined(__WINRT__)
# define SDL_XAUDIO2_HAS_SDK 1
#endif
#if defined(__WIN32__)
#include <dxsdkver.h> /* XAudio2 exists as of the March 2008 DirectX SDK */
#if (!defined(_DXSDK_BUILD_MAJOR) || (_DXSDK_BUILD_MAJOR < 1284))
# pragma message("Your DirectX SDK is too old. Disabling XAudio2 support.")
#else
# define SDL_XAUDIO2_HAS_SDK 1
#endif
#endif

#ifdef SDL_XAUDIO2_HAS_SDK

Expand All @@ -43,12 +111,17 @@
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this

#ifdef __cplusplus
#define this _this
#include "SDL_xaudio2_winrthelpers.h"
#endif

struct SDL_PrivateAudioData
{
IXAudio2 *ixa2;
IXAudio2SourceVoice *source;
IXAudio2MasteringVoice *mastering;
HANDLE semaphore;
SDL_sem * semaphore;
Uint8 *mixbuf;
int mixlen;
Uint8 *nextbuf;
Expand Down Expand Up @@ -102,7 +175,7 @@ VoiceCBOnBufferEnd(THIS_ void *data)
{
/* Just signal the SDL audio thread and get out of XAudio2's way. */
SDL_AudioDevice *this = (SDL_AudioDevice *) data;
ReleaseSemaphore(this->hidden->semaphore, 1, NULL);
SDL_SemPost(this->hidden->semaphore);
}

static void STDMETHODCALLTYPE
Expand All @@ -119,6 +192,33 @@ static void STDMETHODCALLTYPE VoiceCBOnVoiceProcessPassEnd(THIS) {}
static void STDMETHODCALLTYPE VoiceCBOnBufferStart(THIS_ void *data) {}
static void STDMETHODCALLTYPE VoiceCBOnLoopEnd(THIS_ void *data) {}

#if defined(__cplusplus)
class SDL_XAudio2VoiceCallback : public IXAudio2VoiceCallback
{
public:
STDMETHOD_(void, OnBufferEnd)(void *pBufferContext) {
VoiceCBOnBufferEnd(pBufferContext);
}
STDMETHOD_(void, OnBufferStart)(void *pBufferContext) {
VoiceCBOnBufferEnd(pBufferContext);
}
STDMETHOD_(void, OnLoopEnd)(void *pBufferContext) {
VoiceCBOnLoopEnd(pBufferContext);
}
STDMETHOD_(void, OnStreamEnd)() {
VoiceCBOnStreamEnd();
}
STDMETHOD_(void, OnVoiceError)(void *pBufferContext, HRESULT Error) {
VoiceCBOnVoiceError(pBufferContext, Error);
}
STDMETHOD_(void, OnVoiceProcessingPassEnd)() {
VoiceCBOnVoiceProcessPassEnd();
}
STDMETHOD_(void, OnVoiceProcessingPassStart)(UINT32 BytesRequired) {
VoiceCBOnVoiceProcessPassStart(BytesRequired);
}
};
#endif

static Uint8 *
XAUDIO2_GetDeviceBuf(_THIS)
Expand Down Expand Up @@ -168,7 +268,7 @@ static void
XAUDIO2_WaitDevice(_THIS)
{
if (this->enabled) {
WaitForSingleObject(this->hidden->semaphore, INFINITE);
SDL_SemWait(this->hidden->semaphore);
}
}

Expand All @@ -181,7 +281,7 @@ XAUDIO2_WaitDone(_THIS)
IXAudio2SourceVoice_Discontinuity(source);
IXAudio2SourceVoice_GetState(source, &state);
while (state.BuffersQueued > 0) {
WaitForSingleObject(this->hidden->semaphore, INFINITE);
SDL_SemWait(this->hidden->semaphore);
IXAudio2SourceVoice_GetState(source, &state);
}
}
Expand Down Expand Up @@ -230,8 +330,15 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
IXAudio2 *ixa2 = NULL;
IXAudio2SourceVoice *source = NULL;
#if defined(__WINRT__)
WCHAR devId[256];
#else
UINT32 devId = 0; /* 0 == system default device. */
#endif

#if defined(__cplusplus)
static SDL_XAudio2VoiceCallback callbacks;
#else
static IXAudio2VoiceCallbackVtbl callbacks_vtable = {
VoiceCBOnVoiceProcessPassStart,
VoiceCBOnVoiceProcessPassEnd,
Expand All @@ -243,6 +350,11 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
};

static IXAudio2VoiceCallback callbacks = { &callbacks_vtable };
#endif // ! defined(__cplusplus)

#if defined(__WINRT__)
SDL_zero(devId);
#endif

if (iscapture) {
SDL_SetError("XAudio2: capture devices unsupported.");
Expand All @@ -269,7 +381,11 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
const int match = (SDL_strcmp(str, devname) == 0);
SDL_free(str);
if (match) {
#if defined(__WINRT__)
wcsncpy_s(devId, ARRAYSIZE(devId), details.DeviceID, _TRUNCATE);
#else
devId = i;
#endif
break;
}
}
Expand All @@ -294,7 +410,7 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
SDL_memset(this->hidden, 0, (sizeof *this->hidden));

this->hidden->ixa2 = ixa2;
this->hidden->semaphore = CreateSemaphore(NULL, 1, 2, NULL);
this->hidden->semaphore = SDL_CreateSemaphore(1);
if (this->hidden->semaphore == NULL) {
XAUDIO2_CloseDevice(this);
SDL_SetError("XAudio2: CreateSemaphore() failed!");
Expand Down Expand Up @@ -395,7 +511,9 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
static void
XAUDIO2_Deinitialize(void)
{
#if defined(__WIN32__)
WIN_CoUninitialize();
#endif
}

#endif /* SDL_XAUDIO2_HAS_SDK */
Expand All @@ -410,13 +528,17 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl)
#else
/* XAudio2Create() is a macro that uses COM; we don't load the .dll */
IXAudio2 *ixa2 = NULL;
#if defined(__WIN32__)
if (FAILED(WIN_CoInitialize())) {
SDL_SetError("XAudio2: CoInitialize() failed");
return 0;
}
#endif

if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
#if defined(__WIN32__)
WIN_CoUninitialize();
#endif
SDL_SetError("XAudio2: XAudio2Create() failed");
return 0; /* not available. */
}
Expand All @@ -436,6 +558,9 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl)
#endif
}

#if defined(__cplusplus)
extern "C"
#endif
AudioBootStrap XAUDIO2_bootstrap = {
"xaudio2", "XAudio2", XAUDIO2_Init, 0
};
Expand Down
41 changes: 41 additions & 0 deletions src/audio/xaudio2/SDL_xaudio2_winrthelpers.cpp
@@ -0,0 +1,41 @@

#include <xaudio2.h>
#include "SDL_xaudio2_winrthelpers.h"

using Windows::Devices::Enumeration::DeviceClass;
using Windows::Devices::Enumeration::DeviceInformation;
using Windows::Devices::Enumeration::DeviceInformationCollection;

HRESULT IXAudio2_GetDeviceCount(IXAudio2 * ixa2, UINT32 * devcount)
{
auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
while (operation->Status != Windows::Foundation::AsyncStatus::Completed)
{
}

DeviceInformationCollection^ devices = operation->GetResults();
*devcount = devices->Size;
return S_OK;
}

HRESULT IXAudio2_GetDeviceDetails(IXAudio2 * unused, UINT32 index, XAUDIO2_DEVICE_DETAILS * details)
{
auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
while (operation->Status != Windows::Foundation::AsyncStatus::Completed)
{
}

DeviceInformationCollection^ devices = operation->GetResults();
if (index >= devices->Size)
{
return XAUDIO2_E_INVALID_CALL;
}

DeviceInformation^ d = devices->GetAt(index);
if (details)
{
wcsncpy_s(details->DeviceID, ARRAYSIZE(details->DeviceID), d->Id->Data(), _TRUNCATE);
wcsncpy_s(details->DisplayName, ARRAYSIZE(details->DisplayName), d->Name->Data(), _TRUNCATE);
}
return S_OK;
}

0 comments on commit 30e298d

Please sign in to comment.