38typedef HRESULT(__stdcall *API_XAudio2Create)(_Outptr_ IXAudio2 **ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor);
49 std::vector<BYTE> buffer;
52 IXAudio2SourceVoice *source_voice =
nullptr;
56 this->buffer.resize(buffer_length);
61 HRESULT SubmitBuffer()
64 if (this->source_voice ==
nullptr) {
68 MxMixSamples(this->buffer.data(),
static_cast<uint
>(this->buffer.size() / 4));
70 XAUDIO2_BUFFER buf = { 0 };
71 buf.AudioBytes =
static_cast<UINT32
>(this->buffer.size());
72 buf.pAudioData = this->buffer.data();
74 return source_voice->SubmitSourceBuffer(&buf);
77 STDMETHOD_(
void, OnVoiceProcessingPassStart)(UINT32)
override
81 STDMETHOD_(
void, OnVoiceProcessingPassEnd)()
override
85 STDMETHOD_(
void, OnStreamEnd)()
override
89 STDMETHOD_(
void, OnBufferStart)(
void*)
override
93 STDMETHOD_(
void, OnBufferEnd)(
void*)
override
98 STDMETHOD_(
void, OnLoopEnd)(
void*)
override
102 STDMETHOD_(
void, OnVoiceError)(
void*, HRESULT)
override
136 HRESULT hr = CoInitializeEx(
nullptr, COINIT_MULTITHREADED);
139 Debug(driver, 0,
"xaudio2_s: CoInitializeEx failed ({:08x})", (uint)hr);
140 return "Failed to initialise COM";
143 _xaudio_dll_handle = LoadLibraryA(XAUDIO2_DLL_A);
145 if (_xaudio_dll_handle ==
nullptr) {
148 Debug(driver, 0,
"xaudio2_s: Unable to load " XAUDIO2_DLL_A);
149 return "Failed to load XAudio2 DLL";
152 API_XAudio2Create xAudio2Create = (API_XAudio2Create) GetProcAddress(_xaudio_dll_handle,
"XAudio2Create");
154 if (xAudio2Create ==
nullptr) {
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";
166 FreeLibrary(_xaudio_dll_handle);
169 Debug(driver, 0,
"xaudio2_s: XAudio2Create failed ({:08x})", (uint)hr);
170 return "Failed to inititialise the XAudio2 engine";
174 hr = _xaudio2->CreateMasteringVoice(&_mastering_voice);
178 FreeLibrary(_xaudio_dll_handle);
181 Debug(driver, 0,
"xaudio2_s: CreateMasteringVoice failed ({:08x})", (uint)hr);
182 return "Failed to create a mastering voice";
188 wfex.wFormatTag = WAVE_FORMAT_PCM;
190 wfex.wBitsPerSample = 16;
192 wfex.nBlockAlign = (wfex.nChannels * wfex.wBitsPerSample) / 8;
193 wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
197 bufsize = std::min<int>(bufsize, UINT16_MAX);
199 _voice_context = std::make_unique<StreamingVoiceContext>(bufsize * 4);
201 if (_voice_context ==
nullptr) {
202 _mastering_voice->DestroyVoice();
204 FreeLibrary(_xaudio_dll_handle);
207 return "Failed to create streaming voice context";
210 hr = _xaudio2->CreateSourceVoice(&_source_voice, &wfex, 0, 1.0f, _voice_context.get());
213 _mastering_voice->DestroyVoice();
215 FreeLibrary(_xaudio_dll_handle);
218 Debug(driver, 0,
"xaudio2_s: CreateSourceVoice failed ({:08x})", (uint)hr);
219 return "Failed to create a source voice";
222 _voice_context->source_voice = _source_voice;
223 hr = _source_voice->Start(0, 0);
226 Debug(driver, 0,
"xaudio2_s: _source_voice->Start failed ({:08x})", (uint)hr);
229 return "Failed to start the source voice";
232 MxInitialize(wfex.nSamplesPerSec);
235 hr = _voice_context->SubmitBuffer();
238 Debug(driver, 0,
"xaudio2_s: _voice_context->SubmitBuffer failed ({:08x})", (uint)hr);
241 return "Failed to submit the first audio buffer";
Implementation of the IXAudio2VoiceCallback interface.
#define Debug(category, level, format_string,...)
Output a line of debugging information.