XAudio2 and Windows 8


The Windows 8 Consumer Preview includes version 2.8 of the XAudio2 game audio API built in, and this API is fully supported for both Windows Store apps (including x86, x64, and Windows on ARM) and desktop Win32 applications. The full details of the differences compared to XAudio2 2.7 which shipped in the DirectX SDK (June 2010) release are addressed on MSDN. The headers and libraries for XAudio 2.8 are included in the Windows SDK 8.0 that is part of Visual Studio 11 Beta.

Update: This information also applies to Windows 8 RTM, Visual Studio 2012 RTM, Windows 8.1, and Visual Studio 2013.

Windows phone: Windows phone 8 supports XAudio 2.8 as well.

REDIST: For XAudio 2.8 or later on Windows 8 and Windows RT, no redistribution is required since XAudio 2.8 is included with the OS. For XAudio 2.7 on any version of Windows, use the legacy DirectX SDK REDIST.

Since XAudio2 version 2.8 is not available on Windows 7, Win32 desktop games that support older versions of Windows will need to continue to use XAudio 2.7. In general it is fairly easy to write code that successfully complies both for “Windows 8 only” which is the case for Windows Store apps and for ‘down-level’, but requires you mix both the Windows SDK 8.0 and DirectX SDK headers (see “Where is the DirectX SDK?“).

  • When building an application that is ‘down-level’ using headers in the Windows 8.0 SDK, be sure to explicitly select the correct ‘minimum’ _WIN32_WINNT value. For Windows 8, that is 0x0602 (which is the default when building code with Visual Studio 2012 and for all Windows Store apps). For Windows 7 use 0x0601, and for Windows Vista use 0x0600. Typically this is done as part of the project configuration via Preprocessor Definitions.

If you set _WIN32_WINNT correctly and try building with the Windows 8.x SDK version of xaudio2.h headers, you’ll get an error letting you know that you have to use the DirectX SDK version of that header. You should follow the instructions on MSDN to use the Windows 8.x SDK headers and libraries, listing the DXSDK_DIR paths in VC++ Directories after the Windows SDK header/libs, and explicitly link to the headers in the ‘default’ location–environment variables in #include statements doesn’t work–where you need older versions to support older versions of Windows.

  • The DirectX SDK version of XAudio2 used CoCreateInstance and was registered with COM, and required an explicit Initialize method to be called. The DirectX SDK  ‘xaudio2.h’ header contained a wrapper inline function XAudio2Create that did this to simplify portability with the Xbox 360 version. For the Windows 8 version, you don’t use COM creation and instead call the XAudio2Create function and link with “xaudio2.lib”. For the DirectX SDK, you must explicitly enable the debugging support if desired, but the XAUDIO2_DEBUG_ENGINE flag doesn’t exist for the Windows 8 version.  Note: If using the xAPOs XAudio2CreateVolumeMeter or XAudio2CreateReverb from the xaudio2fx.h header, they have the same link requirement for XAudio 2.8.

 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
 #include <xaudio2.h>
 #pragma comment(lib,"xaudio2.lib")
 #else
 #include <C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\xaudio2.h>
 #endif
 #pragma comment(lib,"ole32.lib")
 
 CoInitializeEx( nullptr, 0 ); 
 
 UINT32 flags = 0;
 #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG)
 flags |= XAUDIO2_DEBUG_ENGINE;
 #endif
 
 hr = XAudio2Create( &pXAudio2, flags );
 if( FAILED( hr ) ) {
 ... 
 } 
 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG)
 // To see the debug output, you need to view ETW logs for this application:
 // Go to Control Panel, Administrative Tools, Event Viewer.
 // View->Show Analytic and Debug Logs.
 // Applications and Services Logs / Microsoft / Windows / XAudio2.
 // Right click on Microsoft Windows XAudio2 debug logging, Properties, then Enable Logging, and hit OK
 XAUDIO2_DEBUG_CONFIGURATION debug ={0};
 debug.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS;
 pXAudio2->SetDebugConfiguration( &debug, 0 );
 #endif 
  • Any calls to IXAudio2::GetDeviceCount() or IXAudio2::GetDeviceDetails() must be guarded since these APIs do not exist in the Windows 8 version. For Windows 8, all explicit device enumeration is done using WinRT APIs. If using the default audio device, the same code will compile for both as the default parameters in both versions do the same thing. If doing an explicit device selection, you must code two versions. The Windows 8 version requires a szDeviceId that is an LPWSTR. The XAudio 2.7 version requires a UINT32 DeviceIndex. Note this Windows 8 version is not the ideal usage since it forces the device enumeration to be synchronous.

 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
 using Windows::Devices::Enumeration::DeviceClass;
 using Windows::Devices::Enumeration::DeviceInformation;
 using Windows::Devices::Enumeration::DeviceInformationCollection;
 
 auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
 while (operation->Status != Windows::Foundation::AsyncStatus::Completed)
 ;
 
 DeviceInformationCollection^ devices = operation->GetResults();
 
 for (unsigned i=0; i < devices->Size; ++i)
 {
 using Windows::Devices::Enumeration::DeviceInformation;
 
 DeviceInformation^ d = devices->GetAt(i);
 // display name is d->Name->Data()
 // device id is d->Id->Data() used for creating the mastering voice
 }
#else
 UINT32 dCount = 0;
 hr = pXAudio2->GetDeviceCount( &dCount );
 if (FAILED(hr) )
 ...
 
 for( UINT32 index=0; index < dCount; ++index )
 {
 XAUDIO2_DEVICE_DETAILS details;
 hr = pXAudio2->GetDeviceDetails( index, &details );
 if (FAILED(hr))
 break;
 
 // display name is details.DisplayName
 // internal device ID is details.DeviceID
 // the 'index' is used for creating the mastering voice
 }
#endif
  • When creating the mastering voice, the two versions take very similar inputs. If using mostly default values, the same code can compile under both conditions. Otherwise, there are two differences: (1) The Windows 8 version takes a szDeviceId for specifying the device to use, while the XAudio 2.7 version uses a DeviceIndex (2) The Windows 8 version takes one additional parameter for registering the output with the correct AUDIO_STREAM_CATEGORY.
 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
 
 hr = pXAudio2->CreateMasteringVoice( &pMasteringVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, deviceID, NULL, AudioCategory_GameEffects );
 
 #else
 
 hr = pXAudio2->CreateMasteringVoice( &pMasteringVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, deviceIndex, NULL );
 
 #endif
  • If you are using X3DAudio you will need the mastering voice’s ‘channel mask’. If using the XAudio 2.7 version, you get this information back from IXAudio2::GetDeviceDetails. Since that method is not used for the Windows 8 version, you obtain that information from the mastering voice instead. You likely need the number of channels as well. For the XAudio 2.7 version you need to link to x3daudio.lib, but for the Windows 8 version it is included in xaudio2.lib.
 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
 #include <x3daudio.h>
 #pragma comment(lib,"xaudio2.lib")
 #else
 #include <C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\include\x3daudio.h>
 #pragma comment(lib,"x3daudio.lib")
 #endif

 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
 
 DWORD dwChannelMask;
 pMasteringVoice->GetChannelMask( &dwChannelMask );
 
 XAUDIO2_VOICE_DETAILS vdetails;
 pMasteringVoice->GetVoiceDetails( &vdetails );
 UINT32 nChannels = vdetails.InputChannels;
 
 #else
 
 XAUDIO2_DEVICE_DETAILS details;
 hr = pXAudio2->GetDeviceDetails( deviceIndex, &details );
 if ( FAILED(hr) )
 ...
 
 DWORD dwChannelMask = details.OutputFormat.dwChannelMask;
 UINT32 nChannels = details.OutputFormat.Format.nChannels;
 
 #endif
 
 X3DAUDIO_HANDLE x3DInstance;
 X3DAudioInitialize( dwChannelMask, X3DAUDIO_SPEED_OF_SOUND, x3DInstance );
  • The xAPO function CreateFX in XAudio 2.8 takes an optional initial parameters structure. When using the xAPO CreateFX with XAudio 2.7, you cannot pass the initial parameters until you bind to a voice and use SetEffectParameters and need to link to xapofx.lib.
 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
 #include <xapofx.h>
 #pragma comment(lib,"xaudio2.lib")
 #else
 #include <C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\include\xapofx.h>
 #pragma comment(lib,"xapofx.lib")
 #endif
 
 IUnknown* effect = nullptr;
 #if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
 hr = CreateFX( _uuidof(...), &effect, &params, sizeof(params) );
 #else
 hr = CreateFX( _uuidof(...), &effect );
 ...
 voice->SetEffectParameters( 0, &params, sizeof(params) );
 #endif
  • From here the rest of XAudio2 API calls should be the same. The only further difference is that the Windows 8 version will not process audio data compressed using ‘xWMA’, but it does support both PCM and ADPCM data that would work with XAudio 2.7. For advanced compression options for the Windows 8 version, the solution is to use Media Foundation to do the decompression and then pass the resulting data to XAudio 2.8 which is demonstrated in the Windows Store app XAudio2 Audio Stream Effect sample and the XAudio2MFStream sample.

See Learning XAudio2, XAudio2 Win32 Samples, DirectXTK for Audio, Known Issues: XAudio 2.7

WIndows Server 2012: Note that XAudio 2.8 is not included in Windows Server 2012.

Windows phone 8: Windows phone 8 development uses XAudio 2.8.

Xbox One: Xbox One development uses XAudio 2.8 with additional support for xWMA. Xbox One XDK developers can also make use of XMA2.

Windows 10: Windows 10 SDK includes XAudio 2.9 which assumes you are building with _WIN32_WINT=0x0A00 when linking against xaudio2.lib. To continue to use XAudio 2.8, build with _WIN32_WINNT=0x0602 or _WIN32_WINNT=0x0603 and link against xaudio2_8.lib. See MSDN for more information about XAudio 2.9.

Comments (9)

  1. This is all a bit complex. Couldn't the Windows SDK include the old headers as well as new "xaudio2_8.h/lib" or something? Or even make the new version XAudio 3, with different numbers in the API names. As it stands, it sounds like everyone's going to need the old DXSDK installed, since we won't be able to exclusively target Windows 8 for many years.

  2. Including the old headers and import library would also require we include a way to redist the XAUDIO2 DLLs in the Windows SDK which only exists in the DirectX SDK. Since you need DirectSetup anyhow, you already have to know how to use the DirectX SDK for these 'down-level' scenarios.

    You can continue to use the DirectX SDK (June 2010) release as it is if it suits your needs. For "Metro" style applications you must use the Windows SDK. The key point of this blog post and the others in this series is to explain how to and when to 'mix' content between the new Windows SDK and the "legacy" DirectX SDK.

  3. Ah yeah, forgot about the redist. I always wondered why Xaudio and Xinput haven't been distributed through Windows Update to users on older versions of Windows, just as D3D11 was to Vista users. That would remove the need for a redist at all if you stuck to those technologies.

  4. The fact that XAudio2 interfaces are not COM-registered anymore and that XAudio2Create is defined in a statically linked library makes it impossible to use XAudio purely from C# (like it is possible with MediaFoundation APIs), right? This is quite frustrating.

  5. xaudio2.lib in the Windows 8.0 SDK is just an import library. The XAudio2Create function is inside XAUDIO2_8.DLL on Windows 8 so you can import it from there.

  6. Ozkan says:

    To clarify something: Since no COM'mery is needed anymore, that would imply no need for calling CoInitialize() and CoUninitialize(), yes? If that is so, the CoInitialize() call in the first code excerpt above was just a result of habit, or is it really still needed? Similarly, if COM isn't needed, shouldn't the "ole32.lib" #pragma go into the #else case?

  7. Ozkan says:

    Well, scratch that.. Without CoInitialize() & co, the thing crashes miserably, so it still needs it somewhere…

  8. @Ozkan: The CoInitialize is needed for the underlying use of the WASAPI API…

  9. Paolo Nunberg says:

    Hi,

    when I try to run an application that makes use of DirectSound on Windows 8.1 64 bit , I get a bad format exception for Microsoft.DirectX.DirectSound.dll, whereas the same application works on all 32 bit versions of Windows from XP to 10.

    Have a happy New Year