12 #include "../stdafx.h" 13 #include "../openttd.h" 14 #include "../driver.h" 17 #include "../core/alloc_func.hpp" 18 #include "../core/bitmath_func.hpp" 19 #include "../core/math_func.hpp" 25 #define NTDDI_VERSION NTDDI_WIN8 26 #define _WIN32_WINNT _WIN32_WINNT_WIN8 32 #include <wrl\client.h> 35 using Microsoft::WRL::ComPtr;
37 #include "../os/windows/win32.h" 38 #include "../safeguards.h" 41 typedef HRESULT(__stdcall *API_XAudio2Create)(_Outptr_ IXAudio2** ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor);
49 class StreamingVoiceContext :
public IXAudio2VoiceCallback
56 IXAudio2SourceVoice* SourceVoice;
58 StreamingVoiceContext(
int bufferLength)
60 this->bufferLength = bufferLength;
61 this->buffer = MallocT<char>(bufferLength);
64 virtual ~StreamingVoiceContext()
69 HRESULT SubmitBuffer()
72 if (this->SourceVoice ==
nullptr)
77 MxMixSamples(this->buffer, this->bufferLength / 4);
79 XAUDIO2_BUFFER buf = { 0 };
80 buf.AudioBytes = this->bufferLength;
81 buf.pAudioData = (
const BYTE *) this->buffer;
83 return SourceVoice->SubmitSourceBuffer(&buf);
86 STDMETHOD_(
void, OnVoiceProcessingPassStart)(UINT32)
override 90 STDMETHOD_(
void, OnVoiceProcessingPassEnd)()
override 94 STDMETHOD_(
void, OnStreamEnd)()
override 98 STDMETHOD_(
void, OnBufferStart)(
void*)
override 102 STDMETHOD_(
void, OnBufferEnd)(
void*)
override 107 STDMETHOD_(
void, OnLoopEnd)(
void*)
override 111 STDMETHOD_(
void, OnVoiceError)(
void*, HRESULT)
override 116 static HMODULE _xaudio_dll_handle;
117 static IXAudio2SourceVoice* _source_voice =
nullptr;
118 static IXAudio2MasteringVoice* _mastering_voice =
nullptr;
119 static ComPtr<IXAudio2> _xaudio2;
120 static StreamingVoiceContext* _voice_context =
nullptr;
131 HRESULT hr = CoInitializeEx(
nullptr, COINIT_MULTITHREADED);
135 DEBUG(driver, 0,
"xaudio2_s: CoInitializeEx failed (%08x)", hr);
136 return "Failed to initialise COM";
139 _xaudio_dll_handle = LoadLibraryA(XAUDIO2_DLL_A);
141 if (_xaudio_dll_handle ==
nullptr)
145 DEBUG(driver, 0,
"xaudio2_s: Unable to load " XAUDIO2_DLL_A);
146 return "Failed to load XAudio2 DLL";
149 API_XAudio2Create xAudio2Create = (API_XAudio2Create) GetProcAddress(_xaudio_dll_handle,
"XAudio2Create");
151 if (xAudio2Create ==
nullptr)
153 FreeLibrary(_xaudio_dll_handle);
156 DEBUG(driver, 0,
"xaudio2_s: Unable to find XAudio2Create function in DLL");
157 return "Failed to load XAudio2 DLL";
162 hr = xAudio2Create(_xaudio2.GetAddressOf(), flags, XAUDIO2_DEFAULT_PROCESSOR);
166 FreeLibrary(_xaudio_dll_handle);
169 DEBUG(driver, 0,
"xaudio2_s: XAudio2Create failed (%08x)", hr);
170 return "Failed to inititialise the XAudio2 engine";
174 hr = _xaudio2->CreateMasteringVoice(&_mastering_voice);
179 FreeLibrary(_xaudio_dll_handle);
182 DEBUG(driver, 0,
"xaudio2_s: CreateMasteringVoice failed (%08x)", hr);
183 return "Failed to create a mastering voice";
189 wfex.wFormatTag = WAVE_FORMAT_PCM;
191 wfex.wBitsPerSample = 16;
193 wfex.nBlockAlign = (wfex.nChannels * wfex.wBitsPerSample) / 8;
194 wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
198 bufsize =
min(bufsize, UINT16_MAX);
200 _voice_context =
new StreamingVoiceContext(bufsize * 4);
202 if (_voice_context ==
nullptr)
204 _mastering_voice->DestroyVoice();
206 FreeLibrary(_xaudio_dll_handle);
209 return "Failed to create streaming voice context";
212 hr = _xaudio2->CreateSourceVoice(&_source_voice, &wfex, 0, 1.0f, _voice_context);
216 _mastering_voice->DestroyVoice();
218 FreeLibrary(_xaudio_dll_handle);
221 DEBUG(driver, 0,
"xaudio2_s: CreateSourceVoice failed (%08x)", hr);
222 return "Failed to create a source voice";
225 _voice_context->SourceVoice = _source_voice;
226 hr = _source_voice->Start(0, 0);
230 DEBUG(driver, 0,
"xaudio2_s: _source_voice->Start failed (%08x)", hr);
233 return "Failed to start the source voice";
236 MxInitialize(wfex.nSamplesPerSec);
239 hr = _voice_context->SubmitBuffer();
243 DEBUG(driver, 0,
"xaudio2_s: _voice_context->SubmitBuffer failed (%08x)", hr);
246 return "Failed to submit the first audio buffer";
258 _source_voice->DestroyVoice();
260 delete _voice_context;
261 _voice_context =
nullptr;
263 _mastering_voice->DestroyVoice();
267 FreeLibrary(_xaudio_dll_handle);
Factory for the XAudio2 sound driver.
void Stop() override
Stop this driver.
static T min(const T a, const T b)
Returns the minimum of two values.
#define DEBUG(name, level,...)
Output a line of debugging information.
const char * Start(const char *const *param) override
Start this driver.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
int GetDriverParamInt(const char *const *parm, const char *name, int def)
Get an integer parameter the list of parameters.
Base for XAudio2 sound handling.