Please don't merge these patches. I got some feedback on IRC and will be sending improved versions.
Andrew
On Mon, Aug 24, 2015 at 10:31:36AM -0500, Andrew Eikum wrote:
This adds a build-time dependency on openal, and a run-time dependency on openal-soft's ALC_SOFT_loopback extension.
configure.ac | 3 +- dlls/xaudio2_7/Makefile.in | 1 + dlls/xaudio2_7/xaudio_dll.c | 274 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 274 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac index 004e79d..dea394f 100644 --- a/configure.ac +++ b/configure.ac @@ -1738,8 +1738,9 @@ then AC_DEFINE_UNQUOTED(HAVE_OPENAL,1,[Define to 1 if OpenAL is available])],,) fi WINE_NOTICE_WITH(openal,[test "x$ac_cv_lib_openal" != xyes],
[libopenal ${notice_platform}development files not found (or too old), OpenAL won't be supported.])
[libopenal ${notice_platform}development files not found (or too old), OpenAL and XAudio2 won't be supported])
test "x$ac_cv_lib_openal" = xyes || enable_openal32=${enable_openal32:-no} +test "x$ac_cv_lib_openal" = xyes || enable_xaudio2_7=${enable_xaudio2_7:-no}
dnl **** Check for libkstat **** if test "$ac_cv_header_kstat_h" = "yes" diff --git a/dlls/xaudio2_7/Makefile.in b/dlls/xaudio2_7/Makefile.in index 6bdf362..5a09c82 100644 --- a/dlls/xaudio2_7/Makefile.in +++ b/dlls/xaudio2_7/Makefile.in @@ -1,5 +1,6 @@ MODULE = xaudio2_7.dll IMPORTS = advapi32 kernel32 ole32 user32 uuid +EXTRALIBS = $(OPENAL_LIBS)
C_SRCS = \ xaudio_dll.c diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c index 6bb48e6..95740fa 100644 --- a/dlls/xaudio2_7/xaudio_dll.c +++ b/dlls/xaudio2_7/xaudio_dll.c @@ -41,8 +41,14 @@ #include "mmdeviceapi.h" #include "audioclient.h"
+#include <AL/al.h> +#include <AL/alc.h> +#include <AL/alext.h>
WINE_DEFAULT_DEBUG_CHANNEL(xaudio2);
+static ALCdevice *(ALC_APIENTRY *palcLoopbackOpenDeviceSOFT)(const ALCchar*);
static HINSTANCE instance;
static void dump_fmt(const WAVEFORMATEX *fmt) @@ -86,6 +92,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, void *pReserved) case DLL_PROCESS_ATTACH: instance = hinstDLL; DisableThreadLibraryCalls( hinstDLL );
if(!alcIsExtensionPresent(NULL, "ALC_SOFT_loopback") ||
!(palcLoopbackOpenDeviceSOFT = alGetProcAddress("alcLoopbackOpenDeviceSOFT"))){
ERR("XAudio2 requires the ALC_SOFT_loopback extension (OpenAL-Soft >= 1.14)\n");
return FALSE;
}
} return TRUE;break;
@@ -173,6 +186,14 @@ struct _IXAudio2Impl {
WCHAR **devids; UINT32 ndevs;
- IAudioClient *aclient;
- IAudioRenderClient *render;
- WAVEFORMATEXTENSIBLE fmt;
- ALCdevice *al_device;
- ALCcontext *al_ctx;
};
static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface) @@ -190,6 +211,32 @@ IXAudio2Impl *impl_from_IXAudio2MasteringVoice(IXAudio2MasteringVoice *iface) return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio2MasteringVoice_iface); }
+static DWORD get_channel_mask(unsigned int channels) +{
- switch(channels){
- case 0:
return 0;
- case 1:
return KSAUDIO_SPEAKER_MONO;
- case 2:
return KSAUDIO_SPEAKER_STEREO;
- case 3:
return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
- case 4:
return KSAUDIO_SPEAKER_QUAD; /* not _SURROUND */
- case 5:
return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
- case 6:
return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
- case 7:
return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
- case 8:
return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
- }
- FIXME("Unknown speaker configuration: %u\n", channels);
- return 0;
+}
static void WINAPI XA2SRC_GetVoiceDetails(IXAudio2SourceVoice *iface, XAUDIO2_VOICE_DETAILS *pVoiceDetails) { @@ -891,7 +938,29 @@ static void WINAPI XA2M_GetOutputMatrix(IXAudio2MasteringVoice *iface, static void WINAPI XA2M_DestroyVoice(IXAudio2MasteringVoice *iface) { IXAudio2Impl *This = impl_from_IXAudio2MasteringVoice(iface);
- TRACE("%p\n", This);
- EnterCriticalSection(&This->lock);
- if(!This->aclient){
LeaveCriticalSection(&This->lock);
return;
- }
- IAudioRenderClient_Release(This->render);
- This->render = NULL;
- IAudioClient_Release(This->aclient);
- This->aclient = NULL;
- alcCloseDevice(This->al_device);
- This->al_device = NULL;
- alcDestroyContext(This->al_ctx);
- This->al_ctx = NULL;
- LeaveCriticalSection(&This->lock);
}
/* not present in XAudio2 2.7 */ @@ -1164,6 +1233,8 @@ static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface) HeapFree(GetProcessHeap(), 0, sub); }
IXAudio2MasteringVoice_DestroyVoice(&This->IXAudio2MasteringVoice_iface);
if(This->devenum) IMMDeviceEnumerator_Release(This->devenum); for(i = 0; i < This->ndevs; ++i)
@@ -1322,6 +1393,28 @@ static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface, return S_OK; }
+static ALenum al_get_loopback_format(const WAVEFORMATEXTENSIBLE *fmt) +{
- if(fmt->Format.wFormatTag == WAVE_FORMAT_PCM ||
(fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
IsEqualGUID(&fmt->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
switch(fmt->Format.wBitsPerSample){
case 8:
return AL_UNSIGNED_BYTE_SOFT;
case 16:
return AL_SHORT_SOFT;
case 32:
return AL_INT_SOFT;
}
- }else if(fmt->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
(fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
IsEqualGUID(&fmt->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
if(fmt->Format.wBitsPerSample == 32)
return AL_FLOAT_SOFT;
- }
- return 0;
+}
static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface, IXAudio2MasteringVoice **ppMasteringVoice, UINT32 inputChannels, UINT32 inputSampleRate, UINT32 flags, const WCHAR *deviceId, @@ -1329,8 +1422,12 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface, AUDIO_STREAM_CATEGORY streamCategory) { IXAudio2Impl *This = impl_from_IXAudio2(iface);
- IMMDevice *dev;
- HRESULT hr;
- WAVEFORMATEX *fmt;
- ALCint attrs[7];
- FIXME("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x): stub!\n", This,
- TRACE("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x)\n", This, ppMasteringVoice, inputChannels, inputSampleRate, flags, wine_dbgstr_w(deviceId), pEffectChain, streamCategory);
@@ -1340,12 +1437,183 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface, if(pEffectChain) WARN("Effect chain is unimplemented\n");
- /* TODO: Initialize mmdevice */
EnterCriticalSection(&This->lock);
/* there can only be one Mastering Voice, so just build it into XA2 */
if(This->aclient){
LeaveCriticalSection(&This->lock);
return XAUDIO2_E_INVALID_CALL;
}
if(!deviceId){
if(This->ndevs == 0){
LeaveCriticalSection(&This->lock);
return ERROR_NOT_FOUND;
}
deviceId = This->devids[0];
}
hr = IMMDeviceEnumerator_GetDevice(This->devenum, deviceId, &dev);
if(FAILED(hr)){
WARN("GetDevice failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
hr = IMMDevice_Activate(dev, &IID_IAudioClient,
CLSCTX_INPROC_SERVER, NULL, (void**)&This->aclient);
if(FAILED(hr)){
WARN("Activate(IAudioClient) failed: %08x\n", hr);
IMMDevice_Release(dev);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
IMMDevice_Release(dev);
hr = IAudioClient_GetMixFormat(This->aclient, &fmt);
if(FAILED(hr)){
WARN("GetMixFormat failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
if(sizeof(WAVEFORMATEX) + fmt->cbSize > sizeof(WAVEFORMATEXTENSIBLE)){
FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
if(inputChannels == XAUDIO2_DEFAULT_CHANNELS)
inputChannels = fmt->nChannels;
if(inputSampleRate == XAUDIO2_DEFAULT_SAMPLERATE)
inputSampleRate = fmt->nSamplesPerSec;
memcpy(&This->fmt, fmt, sizeof(WAVEFORMATEX) + fmt->cbSize);
This->fmt.Format.nChannels = inputChannels;
This->fmt.Format.nSamplesPerSec = inputSampleRate;
This->fmt.Format.nBlockAlign = This->fmt.Format.nChannels * This->fmt.Format.wBitsPerSample / 8;
This->fmt.Format.nAvgBytesPerSec = This->fmt.Format.nSamplesPerSec * This->fmt.Format.nBlockAlign;
This->fmt.dwChannelMask = get_channel_mask(This->fmt.Format.nChannels);
CoTaskMemFree(fmt);
fmt = NULL;
hr = IAudioClient_IsFormatSupported(This->aclient,
AUDCLNT_SHAREMODE_SHARED, &This->fmt.Format, &fmt);
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;
goto exit;
}
memcpy(&This->fmt, fmt, sizeof(WAVEFORMATEX) + fmt->cbSize);
}
CoTaskMemFree(fmt);
hr = IAudioClient_Initialize(This->aclient, AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK, inputSampleRate /* 1s buffer */,
0, &This->fmt.Format, NULL);
if(FAILED(hr)){
WARN("Initialize failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
hr = IAudioClient_GetService(This->aclient, &IID_IAudioRenderClient,
(void**)&This->render);
if(FAILED(hr)){
WARN("GetService(IAudioRenderClient) failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
/* setup openal context */
attrs[0] = ALC_FORMAT_CHANNELS_SOFT;
switch(inputChannels){
case 1:
attrs[1] = ALC_MONO_SOFT;
break;
case 2:
attrs[1] = ALC_STEREO_SOFT;
break;
case 4:
attrs[1] = ALC_QUAD_SOFT;
break;
case 6:
attrs[1] = ALC_5POINT1_SOFT;
break;
case 7:
attrs[1] = ALC_6POINT1_SOFT;
break;
case 8:
attrs[1] = ALC_7POINT1_SOFT;
break;
default:
WARN("OpenAL doesn't support %u channels\n", inputChannels);
LeaveCriticalSection(&This->lock);
return AUDCLNT_E_UNSUPPORTED_FORMAT;
}
attrs[2] = ALC_FREQUENCY;
attrs[3] = inputSampleRate;
attrs[4] = ALC_FORMAT_TYPE_SOFT;
attrs[5] = al_get_loopback_format(&This->fmt);
attrs[6] = 0;
if(!attrs[5]){
WARN("OpenAL can't output samples in this format\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
This->al_device = palcLoopbackOpenDeviceSOFT(NULL);
if(!This->al_device){
WARN("alcLoopbackOpenDeviceSOFT failed\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
This->al_ctx = alcCreateContext(This->al_device, attrs);
if(!This->al_ctx){
WARN("alcCreateContext failed\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
if(alcMakeContextCurrent(This->al_ctx) == ALC_FALSE){
WARN("alcMakeContextCurrent failed\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
IAudioClient_Start(This->aclient);
*ppMasteringVoice = &This->IXAudio2MasteringVoice_iface;
- return S_OK;
+exit:
- if(FAILED(hr)){
if(This->render){
IAudioRenderClient_Release(This->render);
This->render = NULL;
}
if(This->aclient){
IAudioClient_Release(This->aclient);
This->aclient = NULL;
}
if(This->al_ctx){
alcDestroyContext(This->al_ctx);
This->al_ctx = NULL;
}
if(This->al_device){
alcCloseDevice(This->al_device);
This->al_device = NULL;
}
- }
- LeaveCriticalSection(&This->lock);
- return hr;
}
static HRESULT WINAPI IXAudio2Impl_StartEngine(IXAudio2 *iface)
2.5.0
Looks like it is too late :(
This appears to break the build on OSX. Any idea for when a patch will arrive?
-Matt
On Aug 24, 2015, at 3:29 PM, Andrew Eikum aeikum@codeweavers.com wrote:
Please don't merge these patches. I got some feedback on IRC and will be sending improved versions.
Andrew
On Mon, Aug 24, 2015 at 10:31:36AM -0500, Andrew Eikum wrote:
This adds a build-time dependency on openal, and a run-time dependency on openal-soft's ALC_SOFT_loopback extension.
configure.ac | 3 +- dlls/xaudio2_7/Makefile.in | 1 + dlls/xaudio2_7/xaudio_dll.c | 274 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 274 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac index 004e79d..dea394f 100644 --- a/configure.ac +++ b/configure.ac @@ -1738,8 +1738,9 @@ then AC_DEFINE_UNQUOTED(HAVE_OPENAL,1,[Define to 1 if OpenAL is available])],,) fi WINE_NOTICE_WITH(openal,[test "x$ac_cv_lib_openal" != xyes],
[libopenal ${notice_platform}development files not found (or too old), OpenAL won't be supported.])
[libopenal ${notice_platform}development files not found (or too old), OpenAL and XAudio2 won't be supported])
test "x$ac_cv_lib_openal" = xyes || enable_openal32=${enable_openal32:-no} +test "x$ac_cv_lib_openal" = xyes || enable_xaudio2_7=${enable_xaudio2_7:-no}
dnl **** Check for libkstat **** if test "$ac_cv_header_kstat_h" = "yes" diff --git a/dlls/xaudio2_7/Makefile.in b/dlls/xaudio2_7/Makefile.in index 6bdf362..5a09c82 100644 --- a/dlls/xaudio2_7/Makefile.in +++ b/dlls/xaudio2_7/Makefile.in @@ -1,5 +1,6 @@ MODULE = xaudio2_7.dll IMPORTS = advapi32 kernel32 ole32 user32 uuid +EXTRALIBS = $(OPENAL_LIBS)
C_SRCS = \ xaudio_dll.c diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c index 6bb48e6..95740fa 100644 --- a/dlls/xaudio2_7/xaudio_dll.c +++ b/dlls/xaudio2_7/xaudio_dll.c @@ -41,8 +41,14 @@ #include "mmdeviceapi.h" #include "audioclient.h"
+#include <AL/al.h> +#include <AL/alc.h> +#include <AL/alext.h>
WINE_DEFAULT_DEBUG_CHANNEL(xaudio2);
+static ALCdevice *(ALC_APIENTRY *palcLoopbackOpenDeviceSOFT)(const ALCchar*);
static HINSTANCE instance;
static void dump_fmt(const WAVEFORMATEX *fmt) @@ -86,6 +92,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, void *pReserved) case DLL_PROCESS_ATTACH: instance = hinstDLL; DisableThreadLibraryCalls( hinstDLL );
if(!alcIsExtensionPresent(NULL, "ALC_SOFT_loopback") ||
!(palcLoopbackOpenDeviceSOFT = alGetProcAddress("alcLoopbackOpenDeviceSOFT"))){
ERR("XAudio2 requires the ALC_SOFT_loopback extension (OpenAL-Soft >= 1.14)\n");
return FALSE;
}
} return TRUE;break;
@@ -173,6 +186,14 @@ struct _IXAudio2Impl {
WCHAR **devids; UINT32 ndevs;
- IAudioClient *aclient;
- IAudioRenderClient *render;
- WAVEFORMATEXTENSIBLE fmt;
- ALCdevice *al_device;
- ALCcontext *al_ctx;
};
static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface) @@ -190,6 +211,32 @@ IXAudio2Impl *impl_from_IXAudio2MasteringVoice(IXAudio2MasteringVoice *iface) return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio2MasteringVoice_iface); }
+static DWORD get_channel_mask(unsigned int channels) +{
- switch(channels){
- case 0:
return 0;
- case 1:
return KSAUDIO_SPEAKER_MONO;
- case 2:
return KSAUDIO_SPEAKER_STEREO;
- case 3:
return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
- case 4:
return KSAUDIO_SPEAKER_QUAD; /* not _SURROUND */
- case 5:
return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
- case 6:
return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
- case 7:
return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
- case 8:
return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
- }
- FIXME("Unknown speaker configuration: %u\n", channels);
- return 0;
+}
static void WINAPI XA2SRC_GetVoiceDetails(IXAudio2SourceVoice *iface, XAUDIO2_VOICE_DETAILS *pVoiceDetails) { @@ -891,7 +938,29 @@ static void WINAPI XA2M_GetOutputMatrix(IXAudio2MasteringVoice *iface, static void WINAPI XA2M_DestroyVoice(IXAudio2MasteringVoice *iface) { IXAudio2Impl *This = impl_from_IXAudio2MasteringVoice(iface);
- TRACE("%p\n", This);
- EnterCriticalSection(&This->lock);
- if(!This->aclient){
LeaveCriticalSection(&This->lock);
return;
- }
- IAudioRenderClient_Release(This->render);
- This->render = NULL;
- IAudioClient_Release(This->aclient);
- This->aclient = NULL;
- alcCloseDevice(This->al_device);
- This->al_device = NULL;
- alcDestroyContext(This->al_ctx);
- This->al_ctx = NULL;
- LeaveCriticalSection(&This->lock);
}
/* not present in XAudio2 2.7 */ @@ -1164,6 +1233,8 @@ static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface) HeapFree(GetProcessHeap(), 0, sub); }
IXAudio2MasteringVoice_DestroyVoice(&This->IXAudio2MasteringVoice_iface);
if(This->devenum) IMMDeviceEnumerator_Release(This->devenum); for(i = 0; i < This->ndevs; ++i)
@@ -1322,6 +1393,28 @@ static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface, return S_OK; }
+static ALenum al_get_loopback_format(const WAVEFORMATEXTENSIBLE *fmt) +{
- if(fmt->Format.wFormatTag == WAVE_FORMAT_PCM ||
(fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
IsEqualGUID(&fmt->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))){
switch(fmt->Format.wBitsPerSample){
case 8:
return AL_UNSIGNED_BYTE_SOFT;
case 16:
return AL_SHORT_SOFT;
case 32:
return AL_INT_SOFT;
}
- }else if(fmt->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
(fmt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
IsEqualGUID(&fmt->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))){
if(fmt->Format.wBitsPerSample == 32)
return AL_FLOAT_SOFT;
- }
- return 0;
+}
static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface, IXAudio2MasteringVoice **ppMasteringVoice, UINT32 inputChannels, UINT32 inputSampleRate, UINT32 flags, const WCHAR *deviceId, @@ -1329,8 +1422,12 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface, AUDIO_STREAM_CATEGORY streamCategory) { IXAudio2Impl *This = impl_from_IXAudio2(iface);
- IMMDevice *dev;
- HRESULT hr;
- WAVEFORMATEX *fmt;
- ALCint attrs[7];
- FIXME("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x): stub!\n", This,
- TRACE("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x)\n", This, ppMasteringVoice, inputChannels, inputSampleRate, flags, wine_dbgstr_w(deviceId), pEffectChain, streamCategory);
@@ -1340,12 +1437,183 @@ static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface, if(pEffectChain) WARN("Effect chain is unimplemented\n");
- /* TODO: Initialize mmdevice */
EnterCriticalSection(&This->lock);
/* there can only be one Mastering Voice, so just build it into XA2 */
if(This->aclient){
LeaveCriticalSection(&This->lock);
return XAUDIO2_E_INVALID_CALL;
}
if(!deviceId){
if(This->ndevs == 0){
LeaveCriticalSection(&This->lock);
return ERROR_NOT_FOUND;
}
deviceId = This->devids[0];
}
hr = IMMDeviceEnumerator_GetDevice(This->devenum, deviceId, &dev);
if(FAILED(hr)){
WARN("GetDevice failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
hr = IMMDevice_Activate(dev, &IID_IAudioClient,
CLSCTX_INPROC_SERVER, NULL, (void**)&This->aclient);
if(FAILED(hr)){
WARN("Activate(IAudioClient) failed: %08x\n", hr);
IMMDevice_Release(dev);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
IMMDevice_Release(dev);
hr = IAudioClient_GetMixFormat(This->aclient, &fmt);
if(FAILED(hr)){
WARN("GetMixFormat failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
if(sizeof(WAVEFORMATEX) + fmt->cbSize > sizeof(WAVEFORMATEXTENSIBLE)){
FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
if(inputChannels == XAUDIO2_DEFAULT_CHANNELS)
inputChannels = fmt->nChannels;
if(inputSampleRate == XAUDIO2_DEFAULT_SAMPLERATE)
inputSampleRate = fmt->nSamplesPerSec;
memcpy(&This->fmt, fmt, sizeof(WAVEFORMATEX) + fmt->cbSize);
This->fmt.Format.nChannels = inputChannels;
This->fmt.Format.nSamplesPerSec = inputSampleRate;
This->fmt.Format.nBlockAlign = This->fmt.Format.nChannels * This->fmt.Format.wBitsPerSample / 8;
This->fmt.Format.nAvgBytesPerSec = This->fmt.Format.nSamplesPerSec * This->fmt.Format.nBlockAlign;
This->fmt.dwChannelMask = get_channel_mask(This->fmt.Format.nChannels);
CoTaskMemFree(fmt);
fmt = NULL;
hr = IAudioClient_IsFormatSupported(This->aclient,
AUDCLNT_SHAREMODE_SHARED, &This->fmt.Format, &fmt);
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;
goto exit;
}
memcpy(&This->fmt, fmt, sizeof(WAVEFORMATEX) + fmt->cbSize);
}
CoTaskMemFree(fmt);
hr = IAudioClient_Initialize(This->aclient, AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK, inputSampleRate /* 1s buffer */,
0, &This->fmt.Format, NULL);
if(FAILED(hr)){
WARN("Initialize failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
hr = IAudioClient_GetService(This->aclient, &IID_IAudioRenderClient,
(void**)&This->render);
if(FAILED(hr)){
WARN("GetService(IAudioRenderClient) failed: %08x\n", hr);
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
/* setup openal context */
attrs[0] = ALC_FORMAT_CHANNELS_SOFT;
switch(inputChannels){
case 1:
attrs[1] = ALC_MONO_SOFT;
break;
case 2:
attrs[1] = ALC_STEREO_SOFT;
break;
case 4:
attrs[1] = ALC_QUAD_SOFT;
break;
case 6:
attrs[1] = ALC_5POINT1_SOFT;
break;
case 7:
attrs[1] = ALC_6POINT1_SOFT;
break;
case 8:
attrs[1] = ALC_7POINT1_SOFT;
break;
default:
WARN("OpenAL doesn't support %u channels\n", inputChannels);
LeaveCriticalSection(&This->lock);
return AUDCLNT_E_UNSUPPORTED_FORMAT;
}
attrs[2] = ALC_FREQUENCY;
attrs[3] = inputSampleRate;
attrs[4] = ALC_FORMAT_TYPE_SOFT;
attrs[5] = al_get_loopback_format(&This->fmt);
attrs[6] = 0;
if(!attrs[5]){
WARN("OpenAL can't output samples in this format\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
This->al_device = palcLoopbackOpenDeviceSOFT(NULL);
if(!This->al_device){
WARN("alcLoopbackOpenDeviceSOFT failed\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
This->al_ctx = alcCreateContext(This->al_device, attrs);
if(!This->al_ctx){
WARN("alcCreateContext failed\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
if(alcMakeContextCurrent(This->al_ctx) == ALC_FALSE){
WARN("alcMakeContextCurrent failed\n");
hr = XAUDIO2_E_DEVICE_INVALIDATED;
goto exit;
}
IAudioClient_Start(This->aclient);
*ppMasteringVoice = &This->IXAudio2MasteringVoice_iface;
- return S_OK;
+exit:
- if(FAILED(hr)){
if(This->render){
IAudioRenderClient_Release(This->render);
This->render = NULL;
}
if(This->aclient){
IAudioClient_Release(This->aclient);
This->aclient = NULL;
}
if(This->al_ctx){
alcDestroyContext(This->al_ctx);
This->al_ctx = NULL;
}
if(This->al_device){
alcCloseDevice(This->al_device);
This->al_device = NULL;
}
- }
- LeaveCriticalSection(&This->lock);
- return hr;
}
static HRESULT WINAPI IXAudio2Impl_StartEngine(IXAudio2 *iface)
2.5.0
On 29.08.2015 03:51, Matt Durgavich wrote:
Looks like it is too late :(
This appears to break the build on OSX. Any idea for when a patch will arrive?
The following patch (submitted today) might help: http://source.winehq.org/patches/data/114068
(needs "autoreconf -f" to update the ./configure script)
-Matt
Unless I misapplied your patch, it looks like xaudio2 gets disabled on OS X due to lack of full OpenAL support. OS X does support some OpenAL APIs through CoreAudio in a 1:1 fashion, and the rest would likely need to be implemented.
I can take a pass at this, unless there’s some objection.
-Matt
On Aug 28, 2015, at 10:09 PM, Sebastian Lackner sebastian@fds-team.de wrote:
On 29.08.2015 03:51, Matt Durgavich wrote:
Looks like it is too late :(
This appears to break the build on OSX. Any idea for when a patch will arrive?
The following patch (submitted today) might help: http://source.winehq.org/patches/data/114068
(needs "autoreconf -f" to update the ./configure script)
-Matt
As explained on bug 39165, my xaudio2 work uses the ALC_SOFT_loopback extension, which OSX doesn't support. You'll need to install openal-soft on OSX and build against that to use this xaudio2 implementation.
Native xaudio2 installed through winetricks will also continue to work, of course.
Andrew
On Sat, Aug 29, 2015 at 02:36:38PM -0400, Matt Durgavich wrote:
Unless I misapplied your patch, it looks like xaudio2 gets disabled on OS X due to lack of full OpenAL support. OS X does support some OpenAL APIs through CoreAudio in a 1:1 fashion, and the rest would likely need to be implemented.
I can take a pass at this, unless there’s some objection.
-Matt
On Aug 28, 2015, at 10:09 PM, Sebastian Lackner sebastian@fds-team.de wrote:
On 29.08.2015 03:51, Matt Durgavich wrote:
Looks like it is too late :(
This appears to break the build on OSX. Any idea for when a patch will arrive?
The following patch (submitted today) might help: http://source.winehq.org/patches/data/114068
(needs "autoreconf -f" to update the ./configure script)
-Matt
On 08/29/2015 11:36 AM, Matt Durgavich wrote:
Unless I misapplied your patch, it looks like xaudio2 gets disabled on OS X due to lack of full OpenAL support. OS X does support some OpenAL APIs through CoreAudio in a 1:1 fashion, and the rest would likely need to be implemented.
I can take a pass at this, unless there’s some objection.
Knowing how MS's APIs tend to be designed, is it possible the XAudio2 device relies on knowing which mmdeviceapi device is used for output? At least I'd assume that's why the loopback extension is needed, to ensure output is properly synchronized with an IAudioClient.