mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Remove XAudio2
Audio on Windows is provided by the cubeb (shared mode) and WASAPI (exclusive mode) backends, both of which exhibit lower latency.
This commit is contained in:
Vendored
-1282
File diff suppressed because it is too large
Load Diff
Vendored
-263
@@ -1,263 +0,0 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* File: audiodefs.h
|
||||
* Content: Basic constants and data types for audio work.
|
||||
*
|
||||
* Remarks: This header file defines all of the audio format constants and
|
||||
* structures required for XAudio2 and XACT work. Providing these
|
||||
* in a single location avoids certain dependency problems in the
|
||||
* legacy audio headers (mmreg.h, mmsystem.h, ksmedia.h).
|
||||
*
|
||||
* NOTE: Including the legacy headers after this one may cause a
|
||||
* compilation error, because they define some of the same types
|
||||
* defined here without preprocessor guards to avoid multiple
|
||||
* definitions. If a source file needs one of the old headers,
|
||||
* it must include it before including audiodefs.h.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __AUDIODEFS_INCLUDED__
|
||||
#define __AUDIODEFS_INCLUDED__
|
||||
|
||||
#include <windef.h> // For WORD, DWORD, etc.
|
||||
|
||||
#pragma pack(push, 1) // Pack structures to 1-byte boundaries
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* WAVEFORMATEX: Base structure for many audio formats. Format-specific
|
||||
* extensions can be defined for particular formats by using a non-zero
|
||||
* cbSize value and adding extra fields to the end of this structure.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _WAVEFORMATEX_
|
||||
|
||||
#define _WAVEFORMATEX_
|
||||
typedef struct tWAVEFORMATEX
|
||||
{
|
||||
WORD wFormatTag; // Integer identifier of the format
|
||||
WORD nChannels; // Number of audio channels
|
||||
DWORD nSamplesPerSec; // Audio sample rate
|
||||
DWORD nAvgBytesPerSec; // Bytes per second (possibly approximate)
|
||||
WORD nBlockAlign; // Size in bytes of a sample block (all channels)
|
||||
WORD wBitsPerSample; // Size in bits of a single per-channel sample
|
||||
WORD cbSize; // Bytes of extra data appended to this struct
|
||||
} WAVEFORMATEX;
|
||||
|
||||
#endif
|
||||
|
||||
// Defining pointer types outside of the #if block to make sure they are
|
||||
// defined even if mmreg.h or mmsystem.h is #included before this file
|
||||
|
||||
typedef WAVEFORMATEX *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX;
|
||||
typedef const WAVEFORMATEX *PCWAVEFORMATEX, *LPCWAVEFORMATEX;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* WAVEFORMATEXTENSIBLE: Extended version of WAVEFORMATEX that should be
|
||||
* used as a basis for all new audio formats. The format tag is replaced
|
||||
* with a GUID, allowing new formats to be defined without registering a
|
||||
* format tag with Microsoft. There are also new fields that can be used
|
||||
* to specify the spatial positions for each channel and the bit packing
|
||||
* used for wide samples (e.g. 24-bit PCM samples in 32-bit containers).
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||
|
||||
#define _WAVEFORMATEXTENSIBLE_
|
||||
typedef struct
|
||||
{
|
||||
WAVEFORMATEX Format; // Base WAVEFORMATEX data
|
||||
union
|
||||
{
|
||||
WORD wValidBitsPerSample; // Valid bits in each sample container
|
||||
WORD wSamplesPerBlock; // Samples per block of audio data; valid
|
||||
// if wBitsPerSample=0 (but rarely used).
|
||||
WORD wReserved; // Zero if neither case above applies.
|
||||
} Samples;
|
||||
DWORD dwChannelMask; // Positions of the audio channels
|
||||
GUID SubFormat; // Format identifier GUID
|
||||
} WAVEFORMATEXTENSIBLE;
|
||||
|
||||
#endif
|
||||
|
||||
typedef WAVEFORMATEXTENSIBLE *PWAVEFORMATEXTENSIBLE, *LPWAVEFORMATEXTENSIBLE;
|
||||
typedef const WAVEFORMATEXTENSIBLE *PCWAVEFORMATEXTENSIBLE, *LPCWAVEFORMATEXTENSIBLE;
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Define the most common wave format tags used in WAVEFORMATEX formats.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef WAVE_FORMAT_PCM // Pulse Code Modulation
|
||||
|
||||
// If WAVE_FORMAT_PCM is not defined, we need to define some legacy types
|
||||
// for compatibility with the Windows mmreg.h / mmsystem.h header files.
|
||||
|
||||
// Old general format structure (information common to all formats)
|
||||
typedef struct waveformat_tag
|
||||
{
|
||||
WORD wFormatTag;
|
||||
WORD nChannels;
|
||||
DWORD nSamplesPerSec;
|
||||
DWORD nAvgBytesPerSec;
|
||||
WORD nBlockAlign;
|
||||
} WAVEFORMAT, *PWAVEFORMAT, NEAR *NPWAVEFORMAT, FAR *LPWAVEFORMAT;
|
||||
|
||||
// Specific format structure for PCM data
|
||||
typedef struct pcmwaveformat_tag
|
||||
{
|
||||
WAVEFORMAT wf;
|
||||
WORD wBitsPerSample;
|
||||
} PCMWAVEFORMAT, *PPCMWAVEFORMAT, NEAR *NPPCMWAVEFORMAT, FAR *LPPCMWAVEFORMAT;
|
||||
|
||||
#define WAVE_FORMAT_PCM 0x0001
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_ADPCM // Microsoft Adaptive Differental PCM
|
||||
|
||||
// Replicate the Microsoft ADPCM type definitions from mmreg.h.
|
||||
|
||||
typedef struct adpcmcoef_tag
|
||||
{
|
||||
short iCoef1;
|
||||
short iCoef2;
|
||||
} ADPCMCOEFSET;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) // Disable zero-sized array warnings
|
||||
|
||||
typedef struct adpcmwaveformat_tag {
|
||||
WAVEFORMATEX wfx;
|
||||
WORD wSamplesPerBlock;
|
||||
WORD wNumCoef;
|
||||
ADPCMCOEFSET aCoef[]; // Always 7 coefficient pairs for MS ADPCM
|
||||
} ADPCMWAVEFORMAT;
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#define WAVE_FORMAT_ADPCM 0x0002
|
||||
|
||||
#endif
|
||||
|
||||
// Other frequently used format tags
|
||||
|
||||
#ifndef WAVE_FORMAT_UNKNOWN
|
||||
#define WAVE_FORMAT_UNKNOWN 0x0000 // Unknown or invalid format tag
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003 // 32-bit floating-point
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_MPEGLAYER3
|
||||
#define WAVE_FORMAT_MPEGLAYER3 0x0055 // ISO/MPEG Layer3
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
|
||||
#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 // Dolby Audio Codec 3 over S/PDIF
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_WMAUDIO2
|
||||
#define WAVE_FORMAT_WMAUDIO2 0x0161 // Windows Media Audio
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_WMAUDIO3
|
||||
#define WAVE_FORMAT_WMAUDIO3 0x0162 // Windows Media Audio Pro
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_WMASPDIF
|
||||
#define WAVE_FORMAT_WMASPDIF 0x0164 // Windows Media Audio over S/PDIF
|
||||
#endif
|
||||
|
||||
#ifndef WAVE_FORMAT_EXTENSIBLE
|
||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE // All WAVEFORMATEXTENSIBLE formats
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Define the most common wave format GUIDs used in WAVEFORMATEXTENSIBLE
|
||||
* formats. Note that including the Windows ksmedia.h header after this
|
||||
* one will cause build problems; this cannot be avoided, since ksmedia.h
|
||||
* defines these macros without preprocessor guards.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef __cplusplus // uuid() and __uuidof() are only available in C++
|
||||
|
||||
#ifndef KSDATAFORMAT_SUBTYPE_PCM
|
||||
struct __declspec(uuid("00000001-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_PCM_STRUCT;
|
||||
#define KSDATAFORMAT_SUBTYPE_PCM __uuidof(KSDATAFORMAT_SUBTYPE_PCM_STRUCT)
|
||||
#endif
|
||||
|
||||
#ifndef KSDATAFORMAT_SUBTYPE_ADPCM
|
||||
struct __declspec(uuid("00000002-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT;
|
||||
#define KSDATAFORMAT_SUBTYPE_ADPCM __uuidof(KSDATAFORMAT_SUBTYPE_ADPCM_STRUCT)
|
||||
#endif
|
||||
|
||||
#ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
|
||||
struct __declspec(uuid("00000003-0000-0010-8000-00aa00389b71")) KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT;
|
||||
#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT __uuidof(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_STRUCT)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Speaker positions used in the WAVEFORMATEXTENSIBLE dwChannelMask field.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SPEAKER_FRONT_LEFT
|
||||
#define SPEAKER_FRONT_LEFT 0x00000001
|
||||
#define SPEAKER_FRONT_RIGHT 0x00000002
|
||||
#define SPEAKER_FRONT_CENTER 0x00000004
|
||||
#define SPEAKER_LOW_FREQUENCY 0x00000008
|
||||
#define SPEAKER_BACK_LEFT 0x00000010
|
||||
#define SPEAKER_BACK_RIGHT 0x00000020
|
||||
#define SPEAKER_FRONT_LEFT_OF_CENTER 0x00000040
|
||||
#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x00000080
|
||||
#define SPEAKER_BACK_CENTER 0x00000100
|
||||
#define SPEAKER_SIDE_LEFT 0x00000200
|
||||
#define SPEAKER_SIDE_RIGHT 0x00000400
|
||||
#define SPEAKER_TOP_CENTER 0x00000800
|
||||
#define SPEAKER_TOP_FRONT_LEFT 0x00001000
|
||||
#define SPEAKER_TOP_FRONT_CENTER 0x00002000
|
||||
#define SPEAKER_TOP_FRONT_RIGHT 0x00004000
|
||||
#define SPEAKER_TOP_BACK_LEFT 0x00008000
|
||||
#define SPEAKER_TOP_BACK_CENTER 0x00010000
|
||||
#define SPEAKER_TOP_BACK_RIGHT 0x00020000
|
||||
#define SPEAKER_RESERVED 0x7FFC0000
|
||||
#define SPEAKER_ALL 0x80000000
|
||||
#define _SPEAKER_POSITIONS_
|
||||
#endif
|
||||
|
||||
#ifndef SPEAKER_STEREO
|
||||
#define SPEAKER_MONO (SPEAKER_FRONT_CENTER)
|
||||
#define SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
|
||||
#define SPEAKER_2POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY)
|
||||
#define SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)
|
||||
#define SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
||||
#define SPEAKER_4POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
||||
#define SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
|
||||
#define SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER)
|
||||
#define SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)
|
||||
#define SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)
|
||||
#endif
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // #ifndef __AUDIODEFS_INCLUDED__
|
||||
Vendored
-59
@@ -1,59 +0,0 @@
|
||||
// comdecl.h: Macros to facilitate COM interface and GUID declarations.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
#ifndef _COMDECL_H_
|
||||
#define _COMDECL_H_
|
||||
|
||||
#ifndef _XBOX
|
||||
#include <basetyps.h> // For standard COM interface macros
|
||||
#else
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4061)
|
||||
#include <xtl.h> // Required by xobjbase.h
|
||||
#include <xobjbase.h> // Special definitions for Xbox build
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// The DEFINE_CLSID() and DEFINE_IID() macros defined below allow COM GUIDs to
|
||||
// be declared and defined in such a way that clients can obtain the GUIDs using
|
||||
// either the __uuidof() extension or the old-style CLSID_Foo / IID_IFoo names.
|
||||
// If using the latter approach, the client can also choose whether to get the
|
||||
// GUID definitions by defining the INITGUID preprocessor constant or by linking
|
||||
// to a GUID library. This works in either C or C++.
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#define DECLSPEC_UUID_WRAPPER(x) __declspec(uuid(#x))
|
||||
#ifdef INITGUID
|
||||
|
||||
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
class DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) className; \
|
||||
EXTERN_C const GUID DECLSPEC_SELECTANY CLSID_##className = __uuidof(className)
|
||||
|
||||
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
interface DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) interfaceName; \
|
||||
EXTERN_C const GUID DECLSPEC_SELECTANY IID_##interfaceName = __uuidof(interfaceName)
|
||||
|
||||
#else // INITGUID
|
||||
|
||||
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
class DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) className; \
|
||||
EXTERN_C const GUID CLSID_##className
|
||||
|
||||
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
interface DECLSPEC_UUID_WRAPPER(l##-##w1##-##w2##-##b1##b2##-##b3##b4##b5##b6##b7##b8) interfaceName; \
|
||||
EXTERN_C const GUID IID_##interfaceName
|
||||
|
||||
#endif // INITGUID
|
||||
|
||||
#else // __cplusplus
|
||||
|
||||
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
DEFINE_GUID(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
|
||||
|
||||
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
DEFINE_GUID(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // #ifndef _COMDECL_H_
|
||||
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
/*==========================================================================;
|
||||
*
|
||||
*
|
||||
* File: dxsdkver.h
|
||||
* Content: DirectX SDK Version Include File
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _DXSDKVER_H_
|
||||
#define _DXSDKVER_H_
|
||||
|
||||
#define _DXSDK_PRODUCT_MAJOR 9
|
||||
#define _DXSDK_PRODUCT_MINOR 29
|
||||
#define _DXSDK_BUILD_MAJOR 1962
|
||||
#define _DXSDK_BUILD_MINOR 0
|
||||
|
||||
#endif // _DXSDKVER_H_
|
||||
|
||||
Vendored
-718
File diff suppressed because it is too large
Load Diff
Vendored
-2
@@ -60,8 +60,6 @@ Dolphin includes or links code of the following third-party software projects:
|
||||
[LGPLv2+](http://www.surina.net/soundtouch/license.html)
|
||||
- [TAP-Windows](https://openvpn.net/):
|
||||
header only
|
||||
- [XAudio2](http://msdn.microsoft.com/en-us/library/windows/desktop/hh405049.aspx):
|
||||
headers only
|
||||
- [xxHash](https://github.com/Cyan4973/xxHash):
|
||||
[2-clause BSD](https://github.com/Cyan4973/xxHash/blob/master/LICENSE)
|
||||
- [zlib](http://www.zlib.net/):
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "AudioCommon/OpenSLESStream.h"
|
||||
#include "AudioCommon/PulseAudioStream.h"
|
||||
#include "AudioCommon/WASAPIStream.h"
|
||||
#include "AudioCommon/XAudio2Stream.h"
|
||||
#include "AudioCommon/XAudio2_7Stream.h"
|
||||
#include "Common/Common.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
@@ -38,13 +36,6 @@ void InitSoundStream()
|
||||
g_sound_stream = std::make_unique<OpenALStream>();
|
||||
else if (backend == BACKEND_NULLSOUND)
|
||||
g_sound_stream = std::make_unique<NullSound>();
|
||||
else if (backend == BACKEND_XAUDIO2)
|
||||
{
|
||||
if (XAudio2::isValid())
|
||||
g_sound_stream = std::make_unique<XAudio2>();
|
||||
else if (XAudio2_7::isValid())
|
||||
g_sound_stream = std::make_unique<XAudio2_7>();
|
||||
}
|
||||
else if (backend == BACKEND_ALSA && AlsaSound::isValid())
|
||||
g_sound_stream = std::make_unique<AlsaSound>();
|
||||
else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid())
|
||||
@@ -101,8 +92,6 @@ std::vector<std::string> GetSoundBackends()
|
||||
|
||||
backends.emplace_back(BACKEND_NULLSOUND);
|
||||
backends.emplace_back(BACKEND_CUBEB);
|
||||
if (XAudio2_7::isValid() || XAudio2::isValid())
|
||||
backends.emplace_back(BACKEND_XAUDIO2);
|
||||
if (AlsaSound::isValid())
|
||||
backends.emplace_back(BACKEND_ALSA);
|
||||
if (PulseAudio::isValid())
|
||||
@@ -127,8 +116,6 @@ bool SupportsDPL2Decoder(std::string_view backend)
|
||||
return true;
|
||||
if (backend == BACKEND_PULSEAUDIO)
|
||||
return true;
|
||||
if (backend == BACKEND_XAUDIO2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -142,8 +129,7 @@ bool SupportsVolumeChanges(std::string_view backend)
|
||||
// FIXME: this one should ask the backend whether it supports it.
|
||||
// but getting the backend from string etc. is probably
|
||||
// too much just to enable/disable a stupid slider...
|
||||
return backend == BACKEND_CUBEB || backend == BACKEND_OPENAL || backend == BACKEND_XAUDIO2 ||
|
||||
backend == BACKEND_WASAPI;
|
||||
return backend == BACKEND_CUBEB || backend == BACKEND_OPENAL || backend == BACKEND_WASAPI;
|
||||
}
|
||||
|
||||
void UpdateSoundStream()
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
<ClCompile Include="WASAPIStream.cpp" />
|
||||
<ClCompile Include="SurroundDecoder.cpp" />
|
||||
<ClCompile Include="WaveFile.cpp" />
|
||||
<ClCompile Include="XAudio2Stream.cpp" />
|
||||
<ClCompile Include="XAudio2_7Stream.cpp">
|
||||
<AdditionalIncludeDirectories>$(ExternalsDir)XAudio2_7;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AlsaSoundStream.h" />
|
||||
@@ -66,8 +62,6 @@
|
||||
<ClInclude Include="WASAPIStream.h" />
|
||||
<ClInclude Include="SurroundDecoder.h" />
|
||||
<ClInclude Include="WaveFile.h" />
|
||||
<ClInclude Include="XAudio2Stream.h" />
|
||||
<ClInclude Include="XAudio2_7Stream.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
|
||||
@@ -17,12 +17,6 @@
|
||||
<ClCompile Include="OpenALStream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XAudio2Stream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XAudio2_7Stream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CubebStream.cpp">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClCompile>
|
||||
@@ -43,12 +37,6 @@
|
||||
<ClInclude Include="OpenALStream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="XAudio2Stream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="XAudio2_7Stream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PulseAudioStream.h">
|
||||
<Filter>SoundStreams</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -71,19 +71,7 @@ if(WIN32)
|
||||
|
||||
WASAPIStream.cpp
|
||||
WASAPIStream.h
|
||||
XAudio2Stream.cpp
|
||||
XAudio2Stream.h
|
||||
)
|
||||
|
||||
add_library(audiocommon_xaudio27
|
||||
XAudio2_7Stream.cpp
|
||||
XAudio2_7Stream.h
|
||||
)
|
||||
target_include_directories(audiocommon_xaudio27 PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/Externals
|
||||
${PROJECT_SOURCE_DIR}/Externals/XAudio2_7
|
||||
)
|
||||
target_link_libraries(audiocommon PRIVATE audiocommon_xaudio27)
|
||||
endif()
|
||||
|
||||
target_link_libraries(audiocommon PRIVATE cubeb SoundTouch FreeSurround)
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <xaudio2.h>
|
||||
#include "AudioCommon/AudioCommon.h"
|
||||
#include "AudioCommon/XAudio2Stream.h"
|
||||
#include "Common/Event.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#ifndef XAUDIO2_DLL
|
||||
#error You are building this module against the wrong version of DirectX. You probably need to remove DXSDK_DIR from your include path.
|
||||
#endif
|
||||
|
||||
struct StreamingVoiceContext : public IXAudio2VoiceCallback
|
||||
{
|
||||
private:
|
||||
Mixer* const m_mixer;
|
||||
Common::Event& m_sound_sync_event;
|
||||
IXAudio2SourceVoice* m_source_voice;
|
||||
std::variant<std::unique_ptr<short[]>, std::unique_ptr<float[]>> xaudio_buffer;
|
||||
|
||||
void SubmitBuffer(PBYTE buf_data);
|
||||
|
||||
bool m_use_surround = SConfig::GetInstance().bDPL2Decoder;
|
||||
|
||||
public:
|
||||
StreamingVoiceContext(IXAudio2* pXAudio2, Mixer* pMixer, Common::Event& pSyncEvent);
|
||||
virtual ~StreamingVoiceContext();
|
||||
|
||||
void Stop();
|
||||
void Play();
|
||||
|
||||
STDMETHOD_(void, OnVoiceError)(THIS_ void* pBufferContext, HRESULT Error) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart)(UINT32) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd)() {}
|
||||
STDMETHOD_(void, OnBufferStart)(void*) {}
|
||||
STDMETHOD_(void, OnLoopEnd)(void*) {}
|
||||
STDMETHOD_(void, OnStreamEnd)() {}
|
||||
STDMETHOD_(void, OnBufferEnd)(void* context);
|
||||
};
|
||||
|
||||
const int NUM_BUFFERS = 3;
|
||||
const int SAMPLES_PER_BUFFER = 96;
|
||||
const int SAMPLES_PER_BUFFER_SURROUND = 256;
|
||||
|
||||
const int NUM_CHANNELS = 2;
|
||||
const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS;
|
||||
const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16);
|
||||
|
||||
const int NUM_CHANNELS_SURROUND = 6;
|
||||
const int BUFFER_SIZE_SURROUND = SAMPLES_PER_BUFFER_SURROUND * NUM_CHANNELS_SURROUND;
|
||||
const int BUFFER_SIZE_BYTES_SURROUND = BUFFER_SIZE_SURROUND * sizeof(float);
|
||||
void StreamingVoiceContext::SubmitBuffer(PBYTE buf_data)
|
||||
{
|
||||
XAUDIO2_BUFFER buf = {};
|
||||
if (m_use_surround)
|
||||
{
|
||||
buf.AudioBytes = BUFFER_SIZE_BYTES_SURROUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.AudioBytes = BUFFER_SIZE_BYTES;
|
||||
}
|
||||
buf.pContext = buf_data;
|
||||
buf.pAudioData = buf_data;
|
||||
|
||||
m_source_voice->SubmitSourceBuffer(&buf);
|
||||
}
|
||||
|
||||
StreamingVoiceContext::StreamingVoiceContext(IXAudio2* pXAudio2, Mixer* pMixer,
|
||||
Common::Event& pSyncEvent)
|
||||
: m_mixer(pMixer), m_sound_sync_event(pSyncEvent)
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE wfx = {};
|
||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate();
|
||||
|
||||
// More information about these values:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971(v=vs.85).aspx
|
||||
if (m_use_surround)
|
||||
{
|
||||
xaudio_buffer = std::make_unique<float[]>(NUM_BUFFERS * BUFFER_SIZE_SURROUND);
|
||||
|
||||
wfx.Format.nChannels = 6;
|
||||
wfx.Format.wBitsPerSample = 32;
|
||||
wfx.Samples.wValidBitsPerSample = 32;
|
||||
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
|
||||
SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
wfx.Format.cbSize = sizeof(wfx.Samples) + sizeof(wfx.dwChannelMask) + sizeof(wfx.SubFormat);
|
||||
}
|
||||
else
|
||||
{
|
||||
xaudio_buffer = std::make_unique<short[]>(NUM_BUFFERS * BUFFER_SIZE);
|
||||
|
||||
wfx.Format.nChannels = 2;
|
||||
wfx.Format.wBitsPerSample = 16;
|
||||
wfx.Samples.wValidBitsPerSample = 16;
|
||||
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
}
|
||||
|
||||
wfx.Format.nBlockAlign = wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8;
|
||||
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
|
||||
|
||||
// create source voice
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = pXAudio2->CreateSourceVoice(&m_source_voice, &wfx.Format, XAUDIO2_VOICE_NOSRC,
|
||||
1.0f, this)))
|
||||
{
|
||||
PanicAlert("XAudio2 CreateSourceVoice failed: %#X", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
m_source_voice->Start();
|
||||
|
||||
// start buffers with silence
|
||||
if (m_use_surround)
|
||||
{
|
||||
for (int i = 0; i != NUM_BUFFERS; ++i)
|
||||
{
|
||||
SubmitBuffer(
|
||||
reinterpret_cast<BYTE*>(std::get<std::unique_ptr<float[]>>(xaudio_buffer).get()) +
|
||||
(i * BUFFER_SIZE_BYTES_SURROUND));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i != NUM_BUFFERS; ++i)
|
||||
{
|
||||
SubmitBuffer(
|
||||
reinterpret_cast<BYTE*>(std::get<std::unique_ptr<short[]>>(xaudio_buffer).get()) +
|
||||
(i * BUFFER_SIZE_BYTES));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StreamingVoiceContext::~StreamingVoiceContext()
|
||||
{
|
||||
if (m_source_voice)
|
||||
{
|
||||
m_source_voice->Stop();
|
||||
m_source_voice->DestroyVoice();
|
||||
}
|
||||
}
|
||||
|
||||
void StreamingVoiceContext::Stop()
|
||||
{
|
||||
if (m_source_voice)
|
||||
m_source_voice->Stop();
|
||||
}
|
||||
|
||||
void StreamingVoiceContext::Play()
|
||||
{
|
||||
if (m_source_voice)
|
||||
m_source_voice->Start();
|
||||
}
|
||||
|
||||
void StreamingVoiceContext::OnBufferEnd(void* context)
|
||||
{
|
||||
// buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer
|
||||
|
||||
if (!m_source_voice || !context)
|
||||
return;
|
||||
|
||||
// m_sound_sync_event->Wait(); // sync
|
||||
// m_sound_sync_event->Spin(); // or tight sync
|
||||
|
||||
if (m_use_surround)
|
||||
{
|
||||
m_mixer->MixSurround(static_cast<float*>(context), SAMPLES_PER_BUFFER_SURROUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mixer->Mix(static_cast<short*>(context), SAMPLES_PER_BUFFER);
|
||||
}
|
||||
SubmitBuffer(reinterpret_cast<BYTE*>(context));
|
||||
}
|
||||
|
||||
HMODULE XAudio2::m_xaudio2_dll = nullptr;
|
||||
typedef decltype(&XAudio2Create) XAudio2Create_t;
|
||||
void* XAudio2::PXAudio2Create = nullptr;
|
||||
|
||||
bool XAudio2::InitLibrary()
|
||||
{
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
m_xaudio2_dll = ::LoadLibrary(XAUDIO2_DLL);
|
||||
if (!m_xaudio2_dll)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PXAudio2Create)
|
||||
{
|
||||
PXAudio2Create = (XAudio2Create_t)::GetProcAddress(m_xaudio2_dll, "XAudio2Create");
|
||||
if (!PXAudio2Create)
|
||||
{
|
||||
::FreeLibrary(m_xaudio2_dll);
|
||||
m_xaudio2_dll = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
XAudio2::XAudio2()
|
||||
: m_mastering_voice(nullptr), m_volume(1.0f),
|
||||
m_cleanup_com(SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)))
|
||||
{
|
||||
}
|
||||
|
||||
XAudio2::~XAudio2()
|
||||
{
|
||||
Stop();
|
||||
if (m_cleanup_com)
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
bool XAudio2::Init()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// callback doesn't seem to run on a specific CPU anyways
|
||||
IXAudio2* xaudptr;
|
||||
if (FAILED(hr = ((XAudio2Create_t)PXAudio2Create)(&xaudptr, 0, XAUDIO2_DEFAULT_PROCESSOR)))
|
||||
{
|
||||
PanicAlert("XAudio2 init failed: %#X", hr);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
m_xaudio2 = std::unique_ptr<IXAudio2, Releaser>(xaudptr);
|
||||
|
||||
// XAudio2 master voice
|
||||
// XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion?
|
||||
uint channels = NUM_CHANNELS;
|
||||
if (SConfig::GetInstance().bDPL2Decoder)
|
||||
channels = NUM_CHANNELS_SURROUND;
|
||||
|
||||
if (FAILED(hr = m_xaudio2->CreateMasteringVoice(&m_mastering_voice, channels,
|
||||
m_mixer->GetSampleRate())))
|
||||
{
|
||||
PanicAlert("XAudio2 master voice creation failed: %#X", hr);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Volume
|
||||
m_mastering_voice->SetVolume(m_volume);
|
||||
|
||||
m_voice_context = std::unique_ptr<StreamingVoiceContext>(
|
||||
new StreamingVoiceContext(m_xaudio2.get(), m_mixer.get(), m_sound_sync_event));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XAudio2::SetVolume(int volume)
|
||||
{
|
||||
// linear 1- .01
|
||||
m_volume = (float)volume / 100.f;
|
||||
|
||||
if (m_mastering_voice)
|
||||
m_mastering_voice->SetVolume(m_volume);
|
||||
}
|
||||
|
||||
bool XAudio2::SetRunning(bool running)
|
||||
{
|
||||
if (!m_voice_context)
|
||||
return false;
|
||||
|
||||
if (running)
|
||||
m_voice_context->Play();
|
||||
else
|
||||
m_voice_context->Stop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XAudio2::Stop()
|
||||
{
|
||||
// m_sound_sync_event.Set();
|
||||
|
||||
m_voice_context.reset();
|
||||
|
||||
if (m_mastering_voice)
|
||||
{
|
||||
m_mastering_voice->DestroyVoice();
|
||||
m_mastering_voice = nullptr;
|
||||
}
|
||||
|
||||
m_xaudio2.reset(); // release interface
|
||||
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
::FreeLibrary(m_xaudio2_dll);
|
||||
m_xaudio2_dll = nullptr;
|
||||
PXAudio2Create = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// This audio backend uses XAudio2 via XAUDIO2_DLL
|
||||
// It works on Windows 8+, where it is included as an OS component.
|
||||
// This backend is always compiled, but only available if running on Win8+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "AudioCommon/SoundStream.h"
|
||||
#include "Common/Event.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
struct StreamingVoiceContext;
|
||||
struct IXAudio2;
|
||||
struct IXAudio2MasteringVoice;
|
||||
|
||||
#endif
|
||||
|
||||
class XAudio2 final : public SoundStream
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
private:
|
||||
class Releaser
|
||||
{
|
||||
public:
|
||||
template <typename R>
|
||||
void operator()(R* ptr)
|
||||
{
|
||||
ptr->Release();
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<IXAudio2, Releaser> m_xaudio2;
|
||||
std::unique_ptr<StreamingVoiceContext> m_voice_context;
|
||||
IXAudio2MasteringVoice* m_mastering_voice;
|
||||
|
||||
Common::Event m_sound_sync_event;
|
||||
float m_volume;
|
||||
|
||||
const bool m_cleanup_com;
|
||||
|
||||
static HMODULE m_xaudio2_dll;
|
||||
static void* PXAudio2Create;
|
||||
|
||||
static bool InitLibrary();
|
||||
void Stop();
|
||||
|
||||
public:
|
||||
XAudio2();
|
||||
~XAudio2() override;
|
||||
|
||||
bool Init() override;
|
||||
|
||||
bool SetRunning(bool running) override;
|
||||
void SetVolume(int volume) override;
|
||||
|
||||
static bool isValid() { return InitLibrary(); }
|
||||
#endif
|
||||
};
|
||||
@@ -1,295 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Note that this file *and this file only* must include XAudio2.h from the old
|
||||
// DXSDK instead of other possible places.
|
||||
|
||||
#include <XAudio2_7/XAudio2.h>
|
||||
#include <variant>
|
||||
|
||||
#include "AudioCommon/AudioCommon.h"
|
||||
#include "AudioCommon/XAudio2_7Stream.h"
|
||||
#include "Common/Event.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
struct StreamingVoiceContext2_7 : public IXAudio2VoiceCallback
|
||||
{
|
||||
private:
|
||||
Mixer* const m_mixer;
|
||||
Common::Event& m_sound_sync_event;
|
||||
IXAudio2SourceVoice* m_source_voice;
|
||||
std::variant<std::unique_ptr<short[]>, std::unique_ptr<float[]>> xaudio_buffer;
|
||||
|
||||
void SubmitBuffer(PBYTE buf_data);
|
||||
|
||||
bool m_use_surround = SConfig::GetInstance().bDPL2Decoder;
|
||||
|
||||
public:
|
||||
StreamingVoiceContext2_7(IXAudio2* pXAudio2, Mixer* pMixer, Common::Event& pSyncEvent);
|
||||
virtual ~StreamingVoiceContext2_7();
|
||||
|
||||
void Stop();
|
||||
void Play();
|
||||
|
||||
STDMETHOD_(void, OnVoiceError)(THIS_ void* pBufferContext, HRESULT Error) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart)(UINT32) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd)() {}
|
||||
STDMETHOD_(void, OnBufferStart)(void*) {}
|
||||
STDMETHOD_(void, OnLoopEnd)(void*) {}
|
||||
STDMETHOD_(void, OnStreamEnd)() {}
|
||||
STDMETHOD_(void, OnBufferEnd)(void* context);
|
||||
};
|
||||
|
||||
const int NUM_BUFFERS = 3;
|
||||
const int SAMPLES_PER_BUFFER = 96;
|
||||
const int SAMPLES_PER_BUFFER_SURROUND = 256;
|
||||
|
||||
const int NUM_CHANNELS = 2;
|
||||
const int BUFFER_SIZE = SAMPLES_PER_BUFFER * NUM_CHANNELS;
|
||||
const int BUFFER_SIZE_BYTES = BUFFER_SIZE * sizeof(s16);
|
||||
|
||||
const int NUM_CHANNELS_SURROUND = 6;
|
||||
const int BUFFER_SIZE_SURROUND = SAMPLES_PER_BUFFER_SURROUND * NUM_CHANNELS_SURROUND;
|
||||
const int BUFFER_SIZE_BYTES_SURROUND = BUFFER_SIZE_SURROUND * sizeof(float);
|
||||
void StreamingVoiceContext2_7::SubmitBuffer(PBYTE buf_data)
|
||||
{
|
||||
XAUDIO2_BUFFER buf = {};
|
||||
if (m_use_surround)
|
||||
{
|
||||
buf.AudioBytes = BUFFER_SIZE_BYTES_SURROUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.AudioBytes = BUFFER_SIZE_BYTES;
|
||||
}
|
||||
buf.pContext = buf_data;
|
||||
buf.pAudioData = buf_data;
|
||||
|
||||
m_source_voice->SubmitSourceBuffer(&buf);
|
||||
}
|
||||
|
||||
StreamingVoiceContext2_7::StreamingVoiceContext2_7(IXAudio2* pXAudio2, Mixer* pMixer,
|
||||
Common::Event& pSyncEvent)
|
||||
: m_mixer(pMixer), m_sound_sync_event(pSyncEvent)
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE wfx = {};
|
||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx.Format.nSamplesPerSec = m_mixer->GetSampleRate();
|
||||
|
||||
// More information about these values:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd390971(v=vs.85).aspx
|
||||
if (m_use_surround)
|
||||
{
|
||||
xaudio_buffer = std::make_unique<float[]>(NUM_BUFFERS * BUFFER_SIZE_SURROUND);
|
||||
|
||||
wfx.Format.nChannels = 6;
|
||||
wfx.Format.wBitsPerSample = 32;
|
||||
wfx.Samples.wValidBitsPerSample = 32;
|
||||
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
|
||||
SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
wfx.Format.cbSize = sizeof(wfx.Samples) + sizeof(wfx.dwChannelMask) + sizeof(wfx.SubFormat);
|
||||
}
|
||||
else
|
||||
{
|
||||
xaudio_buffer = std::make_unique<short[]>(NUM_BUFFERS * BUFFER_SIZE);
|
||||
|
||||
wfx.Format.nChannels = 2;
|
||||
wfx.Format.wBitsPerSample = 16;
|
||||
wfx.Samples.wValidBitsPerSample = 16;
|
||||
wfx.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
}
|
||||
|
||||
wfx.Format.nBlockAlign = wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8;
|
||||
wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
|
||||
|
||||
// create source voice
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = pXAudio2->CreateSourceVoice(&m_source_voice, &wfx.Format, XAUDIO2_VOICE_NOSRC,
|
||||
1.0f, this)))
|
||||
{
|
||||
PanicAlert("XAudio2_7 CreateSourceVoice failed: %#X", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
m_source_voice->Start();
|
||||
|
||||
// start buffers with silence
|
||||
if (m_use_surround)
|
||||
{
|
||||
for (int i = 0; i != NUM_BUFFERS; ++i)
|
||||
{
|
||||
SubmitBuffer(
|
||||
reinterpret_cast<BYTE*>(std::get<std::unique_ptr<float[]>>(xaudio_buffer).get()) +
|
||||
(i * BUFFER_SIZE_BYTES_SURROUND));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i != NUM_BUFFERS; ++i)
|
||||
{
|
||||
SubmitBuffer(
|
||||
reinterpret_cast<BYTE*>(std::get<std::unique_ptr<short[]>>(xaudio_buffer).get()) +
|
||||
(i * BUFFER_SIZE_BYTES));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StreamingVoiceContext2_7::~StreamingVoiceContext2_7()
|
||||
{
|
||||
if (m_source_voice)
|
||||
{
|
||||
m_source_voice->Stop();
|
||||
m_source_voice->DestroyVoice();
|
||||
}
|
||||
}
|
||||
|
||||
void StreamingVoiceContext2_7::Stop()
|
||||
{
|
||||
if (m_source_voice)
|
||||
m_source_voice->Stop();
|
||||
}
|
||||
|
||||
void StreamingVoiceContext2_7::Play()
|
||||
{
|
||||
if (m_source_voice)
|
||||
m_source_voice->Start();
|
||||
}
|
||||
|
||||
void StreamingVoiceContext2_7::OnBufferEnd(void* context)
|
||||
{
|
||||
// buffer end callback; gets SAMPLES_PER_BUFFER samples for a new buffer
|
||||
|
||||
if (!m_source_voice || !context)
|
||||
return;
|
||||
|
||||
// m_sound_sync_event->Wait(); // sync
|
||||
// m_sound_sync_event->Spin(); // or tight sync
|
||||
|
||||
if (m_use_surround)
|
||||
{
|
||||
m_mixer->MixSurround(static_cast<float*>(context), SAMPLES_PER_BUFFER_SURROUND);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mixer->Mix(static_cast<short*>(context), SAMPLES_PER_BUFFER);
|
||||
}
|
||||
SubmitBuffer(reinterpret_cast<BYTE*>(context));
|
||||
}
|
||||
|
||||
HMODULE XAudio2_7::m_xaudio2_dll = nullptr;
|
||||
|
||||
void XAudio2_7::ReleaseIXAudio2(IXAudio2* ptr)
|
||||
{
|
||||
ptr->Release();
|
||||
}
|
||||
|
||||
bool XAudio2_7::InitLibrary()
|
||||
{
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
m_xaudio2_dll = ::LoadLibrary(TEXT("xaudio2_7.dll"));
|
||||
|
||||
return m_xaudio2_dll != nullptr;
|
||||
}
|
||||
|
||||
XAudio2_7::XAudio2_7()
|
||||
: m_mastering_voice(nullptr), m_volume(1.0f),
|
||||
m_cleanup_com(SUCCEEDED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)))
|
||||
{
|
||||
}
|
||||
|
||||
XAudio2_7::~XAudio2_7()
|
||||
{
|
||||
Stop();
|
||||
if (m_cleanup_com)
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
bool XAudio2_7::Init()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// callback doesn't seem to run on a specific CPU anyways
|
||||
IXAudio2* xaudptr;
|
||||
if (FAILED(hr = XAudio2Create(&xaudptr, 0, XAUDIO2_DEFAULT_PROCESSOR)))
|
||||
{
|
||||
PanicAlert("XAudio2_7 init failed: %#X", hr);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
m_xaudio2 = std::unique_ptr<IXAudio2, Releaser>(xaudptr);
|
||||
|
||||
// XAudio2 master voice
|
||||
// XAUDIO2_DEFAULT_CHANNELS instead of 2 for expansion?
|
||||
uint channels = NUM_CHANNELS;
|
||||
if (SConfig::GetInstance().bDPL2Decoder)
|
||||
channels = NUM_CHANNELS_SURROUND;
|
||||
|
||||
if (FAILED(hr = m_xaudio2->CreateMasteringVoice(&m_mastering_voice, channels,
|
||||
m_mixer->GetSampleRate())))
|
||||
{
|
||||
PanicAlert("XAudio2_7 master voice creation failed: %#X", hr);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Volume
|
||||
m_mastering_voice->SetVolume(m_volume);
|
||||
|
||||
m_voice_context = std::unique_ptr<StreamingVoiceContext2_7>(
|
||||
new StreamingVoiceContext2_7(m_xaudio2.get(), m_mixer.get(), m_sound_sync_event));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XAudio2_7::SetVolume(int volume)
|
||||
{
|
||||
// linear 1- .01
|
||||
m_volume = (float)volume / 100.f;
|
||||
|
||||
if (m_mastering_voice)
|
||||
m_mastering_voice->SetVolume(m_volume);
|
||||
}
|
||||
|
||||
bool XAudio2_7::SetRunning(bool running)
|
||||
{
|
||||
if (!m_voice_context)
|
||||
return false;
|
||||
|
||||
if (running)
|
||||
m_voice_context->Play();
|
||||
else
|
||||
m_voice_context->Stop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XAudio2_7::Stop()
|
||||
{
|
||||
// m_sound_sync_event.Set();
|
||||
|
||||
m_voice_context.reset();
|
||||
|
||||
if (m_mastering_voice)
|
||||
{
|
||||
m_mastering_voice->DestroyVoice();
|
||||
m_mastering_voice = nullptr;
|
||||
}
|
||||
|
||||
m_xaudio2.reset(); // release interface
|
||||
|
||||
if (m_xaudio2_dll)
|
||||
{
|
||||
::FreeLibrary(m_xaudio2_dll);
|
||||
m_xaudio2_dll = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// This audio backend uses XAudio2 via XAudio2_7.dll
|
||||
// This version of the library is included in the June 2010 DirectX SDK and
|
||||
// works on all versions of Windows, however the SDK and/or redist must be
|
||||
// separately installed.
|
||||
// Therefore this backend is available iff:
|
||||
// * SDK is available at compile-time
|
||||
// * runtime dll is available at runtime
|
||||
// Dolphin ships the relevant SDK headers in Externals, so it's always available.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "AudioCommon/SoundStream.h"
|
||||
#include "Common/Event.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
struct StreamingVoiceContext2_7;
|
||||
struct IXAudio2;
|
||||
struct IXAudio2MasteringVoice;
|
||||
|
||||
#endif
|
||||
|
||||
class XAudio2_7 final : public SoundStream
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
private:
|
||||
static void ReleaseIXAudio2(IXAudio2* ptr);
|
||||
|
||||
class Releaser
|
||||
{
|
||||
public:
|
||||
template <typename R>
|
||||
void operator()(R* ptr)
|
||||
{
|
||||
ReleaseIXAudio2(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<IXAudio2, Releaser> m_xaudio2;
|
||||
std::unique_ptr<StreamingVoiceContext2_7> m_voice_context;
|
||||
IXAudio2MasteringVoice* m_mastering_voice;
|
||||
|
||||
Common::Event m_sound_sync_event;
|
||||
float m_volume;
|
||||
|
||||
const bool m_cleanup_com;
|
||||
|
||||
static HMODULE m_xaudio2_dll;
|
||||
|
||||
static bool InitLibrary();
|
||||
void Stop();
|
||||
|
||||
public:
|
||||
XAudio2_7();
|
||||
~XAudio2_7() override;
|
||||
|
||||
bool Init() override;
|
||||
|
||||
bool SetRunning(bool running) override;
|
||||
void SetVolume(int volume) override;
|
||||
|
||||
static bool isValid() { return InitLibrary(); }
|
||||
#endif
|
||||
};
|
||||
@@ -53,7 +53,6 @@ struct BootParameters;
|
||||
#define BACKEND_CUBEB "Cubeb"
|
||||
#define BACKEND_OPENAL "OpenAL"
|
||||
#define BACKEND_PULSEAUDIO "Pulse"
|
||||
#define BACKEND_XAUDIO2 "XAudio2"
|
||||
#define BACKEND_OPENSLES "OpenSLES"
|
||||
#define BACKEND_WASAPI _trans("WASAPI (Exclusive Mode)")
|
||||
|
||||
|
||||
@@ -73,10 +73,10 @@
|
||||
This numeral indicates the "minimum system required" to run the resulting
|
||||
program. Dolphin targets Vista+, so it should be 0x0600. However in practice,
|
||||
_WIN32_WINNT just removes up-level API declarations from headers. This is a
|
||||
problem for XAudio2 and XInput, where Dolphin expects to compile against the
|
||||
Win8+ versions of their headers. So while we really need Vista+ level of
|
||||
support, we declare Win8+ here globally. If this becomes a problem, the
|
||||
higher declaration can be contained to just the XAudio2/XInput related code.
|
||||
problem for XInput, where Dolphin expects to compile against the Win8+
|
||||
versions of the headers. So while we really need Vista+ level of support,
|
||||
we declare Win8+ here globally. If this becomes a problem, the higher
|
||||
declaration can be contained to just the XInput related code.
|
||||
-->
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x0602;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
|
||||
Reference in New Issue
Block a user