10 #include "../stdafx.h"
11 #include "../openttd.h"
12 #include "../driver.h"
15 #include "../core/alloc_func.hpp"
16 #include "../core/bitmath_func.hpp"
17 #include "../core/math_func.hpp"
23 #define NTDDI_VERSION NTDDI_WIN8
24 #define _WIN32_WINNT _WIN32_WINNT_WIN8
30 #include <wrl\client.h>
33 using Microsoft::WRL::ComPtr;
35 #include "../os/windows/win32.h"
36 #include "../safeguards.h"
39 typedef HRESULT(__stdcall *API_XAudio2Create)(_Outptr_ IXAudio2 **ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor);
54 IXAudio2SourceVoice *SourceVoice;
58 this->bufferLength = bufferLength;
59 this->buffer = MallocT<char>(bufferLength);
67 HRESULT SubmitBuffer()
70 if (this->SourceVoice ==
nullptr)
75 MxMixSamples(this->buffer, this->bufferLength / 4);
77 XAUDIO2_BUFFER buf = { 0 };
78 buf.AudioBytes = this->bufferLength;
79 buf.pAudioData = (
const BYTE *) this->buffer;
81 return SourceVoice->SubmitSourceBuffer(&buf);
84 STDMETHOD_(
void, OnVoiceProcessingPassStart)(UINT32)
override
88 STDMETHOD_(
void, OnVoiceProcessingPassEnd)()
override
92 STDMETHOD_(
void, OnStreamEnd)()
override
96 STDMETHOD_(
void, OnBufferStart)(
void*)
override
100 STDMETHOD_(
void, OnBufferEnd)(
void*)
override
105 STDMETHOD_(
void, OnLoopEnd)(
void*)
override
109 STDMETHOD_(
void, OnVoiceError)(
void*, HRESULT)
override
114 static HMODULE _xaudio_dll_handle;
115 static IXAudio2SourceVoice *_source_voice =
nullptr;
116 static IXAudio2MasteringVoice *_mastering_voice =
nullptr;
117 static ComPtr<IXAudio2> _xaudio2;
126 hr = xAudio2Create(_xaudio2.GetAddressOf(), flags, XAUDIO2_DEFAULT_PROCESSOR);
127 } __except (EXCEPTION_EXECUTE_HANDLER) {
128 hr = GetExceptionCode();
143 HRESULT hr = CoInitializeEx(
nullptr, COINIT_MULTITHREADED);
147 Debug(driver, 0,
"xaudio2_s: CoInitializeEx failed ({:08x})", (uint)hr);
148 return "Failed to initialise COM";
151 _xaudio_dll_handle = LoadLibraryA(XAUDIO2_DLL_A);
153 if (_xaudio_dll_handle ==
nullptr)
157 Debug(driver, 0,
"xaudio2_s: Unable to load " XAUDIO2_DLL_A);
158 return "Failed to load XAudio2 DLL";
161 API_XAudio2Create xAudio2Create = (API_XAudio2Create) GetProcAddress(_xaudio_dll_handle,
"XAudio2Create");
163 if (xAudio2Create ==
nullptr)
165 FreeLibrary(_xaudio_dll_handle);
168 Debug(driver, 0,
"xaudio2_s: Unable to find XAudio2Create function in DLL");
169 return "Failed to load XAudio2 DLL";
177 FreeLibrary(_xaudio_dll_handle);
180 Debug(driver, 0,
"xaudio2_s: XAudio2Create failed ({:08x})", (uint)hr);
181 return "Failed to inititialise the XAudio2 engine";
185 hr = _xaudio2->CreateMasteringVoice(&_mastering_voice);
190 FreeLibrary(_xaudio_dll_handle);
193 Debug(driver, 0,
"xaudio2_s: CreateMasteringVoice failed ({:08x})", (uint)hr);
194 return "Failed to create a mastering voice";
200 wfex.wFormatTag = WAVE_FORMAT_PCM;
202 wfex.wBitsPerSample = 16;
204 wfex.nBlockAlign = (wfex.nChannels * wfex.wBitsPerSample) / 8;
205 wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
209 bufsize = std::min<int>(bufsize, UINT16_MAX);
213 if (_voice_context ==
nullptr)
215 _mastering_voice->DestroyVoice();
217 FreeLibrary(_xaudio_dll_handle);
220 return "Failed to create streaming voice context";
223 hr = _xaudio2->CreateSourceVoice(&_source_voice, &wfex, 0, 1.0f, _voice_context);
227 _mastering_voice->DestroyVoice();
229 FreeLibrary(_xaudio_dll_handle);
232 Debug(driver, 0,
"xaudio2_s: CreateSourceVoice failed ({:08x})", (uint)hr);
233 return "Failed to create a source voice";
236 _voice_context->SourceVoice = _source_voice;
237 hr = _source_voice->Start(0, 0);
241 Debug(driver, 0,
"xaudio2_s: _source_voice->Start failed ({:08x})", (uint)hr);
244 return "Failed to start the source voice";
247 MxInitialize(wfex.nSamplesPerSec);
250 hr = _voice_context->SubmitBuffer();
254 Debug(driver, 0,
"xaudio2_s: _voice_context->SubmitBuffer failed ({:08x})", (uint)hr);
257 return "Failed to submit the first audio buffer";
269 _source_voice->DestroyVoice();
271 delete _voice_context;
272 _voice_context =
nullptr;
274 _mastering_voice->DestroyVoice();
278 FreeLibrary(_xaudio_dll_handle);
Factory for the XAudio2 sound driver.
std::optional< std::string_view > Start(const StringList ¶m) override
Initialises the XAudio2 driver.
void Stop() override
Terminates the XAudio2 driver.
Implementation of the IXAudio2VoiceCallback interface.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
int GetDriverParamInt(const StringList &parm, const char *name, int def)
Get an integer parameter the list of parameters.
void free(const void *ptr)
Version of the standard free that accepts const pointers.
std::vector< std::string > StringList
Type for a list of strings.
static HRESULT CreateXAudio(API_XAudio2Create xAudio2Create)
Create XAudio2 context with SEH exception checking.
Base for XAudio2 sound handling.