14 #include "../stdafx.h" 15 #include "../openttd.h" 16 #include "../driver.h" 19 #include "../core/alloc_func.hpp" 20 #include "../core/bitmath_func.hpp" 21 #include "../core/math_func.hpp" 27 #define NTDDI_VERSION NTDDI_WIN8 28 #define _WIN32_WINNT _WIN32_WINNT_WIN8 34 #include <wrl\client.h> 37 using Microsoft::WRL::ComPtr;
39 #include "../os/windows/win32.h" 40 #include "../safeguards.h" 43 typedef HRESULT(__stdcall *API_XAudio2Create)(_Outptr_ IXAudio2** ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor);
51 class StreamingVoiceContext :
public IXAudio2VoiceCallback
58 IXAudio2SourceVoice* SourceVoice;
60 StreamingVoiceContext(
int bufferLength)
62 this->bufferLength = bufferLength;
63 this->buffer = MallocT<char>(bufferLength);
66 virtual ~StreamingVoiceContext()
71 HRESULT SubmitBuffer()
74 if (this->SourceVoice ==
nullptr)
79 MxMixSamples(this->buffer, this->bufferLength / 4);
81 XAUDIO2_BUFFER buf = { 0 };
82 buf.AudioBytes = this->bufferLength;
83 buf.pAudioData = (
const BYTE *) this->buffer;
85 return SourceVoice->SubmitSourceBuffer(&buf);
88 STDMETHOD_(
void, OnVoiceProcessingPassStart)(UINT32)
override 92 STDMETHOD_(
void, OnVoiceProcessingPassEnd)()
override 96 STDMETHOD_(
void, OnStreamEnd)()
override 100 STDMETHOD_(
void, OnBufferStart)(
void*)
override 104 STDMETHOD_(
void, OnBufferEnd)(
void*)
override 109 STDMETHOD_(
void, OnLoopEnd)(
void*)
override 113 STDMETHOD_(
void, OnVoiceError)(
void*, HRESULT)
override 118 static HMODULE _xaudio_dll_handle;
119 static IXAudio2SourceVoice* _source_voice =
nullptr;
120 static IXAudio2MasteringVoice* _mastering_voice =
nullptr;
121 static ComPtr<IXAudio2> _xaudio2;
122 static StreamingVoiceContext* _voice_context =
nullptr;
133 HRESULT hr = CoInitializeEx(
nullptr, COINIT_MULTITHREADED);
137 DEBUG(driver, 0,
"xaudio2_s: CoInitializeEx failed (%08x)", hr);
138 return "Failed to initialise COM";
141 _xaudio_dll_handle = LoadLibraryA(XAUDIO2_DLL_A);
143 if (_xaudio_dll_handle == NULL)
147 DEBUG(driver, 0,
"xaudio2_s: Unable to load " XAUDIO2_DLL_A);
148 return "Failed to load XAudio2 DLL";
151 API_XAudio2Create xAudio2Create = (API_XAudio2Create) GetProcAddress(_xaudio_dll_handle,
"XAudio2Create");
153 if (xAudio2Create == NULL)
155 FreeLibrary(_xaudio_dll_handle);
158 DEBUG(driver, 0,
"xaudio2_s: Unable to find XAudio2Create function in DLL");
159 return "Failed to load XAudio2 DLL";
164 hr = xAudio2Create(_xaudio2.GetAddressOf(), flags, XAUDIO2_DEFAULT_PROCESSOR);
168 FreeLibrary(_xaudio_dll_handle);
171 DEBUG(driver, 0,
"xaudio2_s: XAudio2Create failed (%08x)", hr);
172 return "Failed to inititialise the XAudio2 engine";
176 hr = _xaudio2->CreateMasteringVoice(&_mastering_voice);
181 FreeLibrary(_xaudio_dll_handle);
184 DEBUG(driver, 0,
"xaudio2_s: CreateMasteringVoice failed (%08x)", hr);
185 return "Failed to create a mastering voice";
191 wfex.wFormatTag = WAVE_FORMAT_PCM;
193 wfex.wBitsPerSample = 16;
195 wfex.nBlockAlign = (wfex.nChannels * wfex.wBitsPerSample) / 8;
196 wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
200 bufsize =
min(bufsize, UINT16_MAX);
202 _voice_context =
new StreamingVoiceContext(bufsize * 4);
204 if (_voice_context ==
nullptr)
206 _mastering_voice->DestroyVoice();
208 FreeLibrary(_xaudio_dll_handle);
211 return "Failed to create streaming voice context";
214 hr = _xaudio2->CreateSourceVoice(&_source_voice, &wfex, 0, 1.0f, _voice_context);
218 _mastering_voice->DestroyVoice();
220 FreeLibrary(_xaudio_dll_handle);
223 DEBUG(driver, 0,
"xaudio2_s: CreateSourceVoice failed (%08x)", hr);
224 return "Failed to create a source voice";
227 _voice_context->SourceVoice = _source_voice;
228 hr = _source_voice->Start(0, 0);
232 DEBUG(driver, 0,
"xaudio2_s: _source_voice->Start failed (%08x)", hr);
235 return "Failed to start the source voice";
238 MxInitialize(wfex.nSamplesPerSec);
241 hr = _voice_context->SubmitBuffer();
245 DEBUG(driver, 0,
"xaudio2_s: _voice_context->SubmitBuffer failed (%08x)", hr);
248 return "Failed to submit the first audio buffer";
260 _source_voice->DestroyVoice();
262 delete _voice_context;
263 _voice_context =
nullptr;
265 _mastering_voice->DestroyVoice();
269 FreeLibrary(_xaudio_dll_handle);
Factory for the XAudio2 sound driver.
void Stop()
Stop this driver.
static T min(const T a, const T b)
Returns the minimum of two values.
const char * Start(const char *const *param)
Start this driver.
#define DEBUG(name, level,...)
Output a line of debugging information.
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.