2020-12-05 13:08:24 +01:00
|
|
|
#pragma once
|
2016-04-25 12:49:12 +02:00
|
|
|
|
2019-10-22 23:59:09 +02:00
|
|
|
#ifndef _WIN32
|
|
|
|
|
#error "XAudio2 can only be built on Windows."
|
|
|
|
|
#endif
|
2015-01-11 00:46:10 +01:00
|
|
|
|
2018-12-16 18:40:50 +01:00
|
|
|
#include "Emu/Audio/AudioBackend.h"
|
2015-11-16 16:04:49 +01:00
|
|
|
|
2023-08-19 19:12:26 +02:00
|
|
|
#include <initguid.h>
|
2023-07-11 20:40:30 +02:00
|
|
|
#include <xaudio2.h>
|
2020-02-17 22:31:49 +01:00
|
|
|
#include <wrl/client.h>
|
2022-07-08 17:13:38 +02:00
|
|
|
#include <MMDeviceAPI.h>
|
2018-12-21 03:13:22 +01:00
|
|
|
|
2022-07-08 17:13:38 +02:00
|
|
|
class XAudio2Backend final : public AudioBackend, public IXAudio2VoiceCallback, public IXAudio2EngineCallback, public IMMNotificationClient
|
2020-02-17 22:31:49 +01:00
|
|
|
{
|
2015-01-11 00:46:10 +01:00
|
|
|
public:
|
2018-12-16 18:40:50 +01:00
|
|
|
XAudio2Backend();
|
2021-04-09 21:12:47 +02:00
|
|
|
~XAudio2Backend() override;
|
2018-12-16 18:40:50 +01:00
|
|
|
|
2021-04-03 18:38:02 +02:00
|
|
|
XAudio2Backend(const XAudio2Backend&) = delete;
|
|
|
|
|
XAudio2Backend& operator=(const XAudio2Backend&) = delete;
|
|
|
|
|
|
2021-11-29 12:52:02 +01:00
|
|
|
std::string_view GetName() const override { return "XAudio2"sv; }
|
2018-12-16 18:40:50 +01:00
|
|
|
|
2021-12-01 22:36:01 +01:00
|
|
|
bool Initialized() override;
|
2021-11-24 19:41:05 +01:00
|
|
|
bool Operational() override;
|
2022-07-08 17:13:38 +02:00
|
|
|
bool DefaultDeviceChanged() override;
|
2020-02-18 20:42:55 +01:00
|
|
|
|
2024-03-26 19:39:37 +01:00
|
|
|
bool Open(std::string_view dev_id, AudioFreq freq, AudioSampleSize sample_size, AudioChannelCnt ch_cnt, audio_channel_layout layout) override;
|
2021-04-09 21:12:47 +02:00
|
|
|
void Close() override;
|
2018-12-20 23:35:49 +01:00
|
|
|
|
2021-11-24 19:41:05 +01:00
|
|
|
f64 GetCallbackFrameLen() override;
|
|
|
|
|
|
2021-04-09 21:12:47 +02:00
|
|
|
void Play() override;
|
|
|
|
|
void Pause() override;
|
2018-12-20 23:35:49 +01:00
|
|
|
|
2021-11-24 19:41:05 +01:00
|
|
|
private:
|
|
|
|
|
static constexpr u32 INTERNAL_BUF_SIZE_MS = 25;
|
|
|
|
|
|
|
|
|
|
Microsoft::WRL::ComPtr<IXAudio2> m_xaudio2_instance{};
|
|
|
|
|
IXAudio2MasteringVoice* m_master_voice{};
|
|
|
|
|
IXAudio2SourceVoice* m_source_voice{};
|
|
|
|
|
bool m_com_init_success = false;
|
|
|
|
|
|
2022-07-08 17:13:38 +02:00
|
|
|
Microsoft::WRL::ComPtr<IMMDeviceEnumerator> m_device_enumerator{};
|
|
|
|
|
|
2022-10-13 14:39:16 +02:00
|
|
|
// Protected by state callback mutex
|
2022-07-08 17:13:38 +02:00
|
|
|
std::string m_current_device{};
|
|
|
|
|
bool m_default_dev_changed = false;
|
|
|
|
|
|
2022-05-05 15:47:44 +02:00
|
|
|
std::vector<u8> m_data_buf{};
|
2022-01-11 12:40:06 +01:00
|
|
|
std::array<u8, sizeof(float) * static_cast<u32>(AudioChannelCnt::SURROUND_7_1)> m_last_sample{};
|
2021-11-24 19:41:05 +01:00
|
|
|
|
2022-07-08 17:13:38 +02:00
|
|
|
atomic_t<bool> m_reset_req = false;
|
2021-11-24 19:41:05 +01:00
|
|
|
|
|
|
|
|
// XAudio voice callbacks
|
|
|
|
|
void OnVoiceProcessingPassStart(UINT32 BytesRequired) override;
|
|
|
|
|
void OnVoiceProcessingPassEnd() override {}
|
|
|
|
|
void OnStreamEnd() override {}
|
|
|
|
|
void OnBufferStart(void* /* pBufferContext */) override {}
|
|
|
|
|
void OnBufferEnd(void* /* pBufferContext*/) override {}
|
|
|
|
|
void OnLoopEnd(void* /* pBufferContext */) override {}
|
|
|
|
|
void OnVoiceError(void* /* pBufferContext */, HRESULT /* Error */) override {}
|
|
|
|
|
|
|
|
|
|
// XAudio engine callbacks
|
|
|
|
|
void OnProcessingPassStart() override {};
|
|
|
|
|
void OnProcessingPassEnd() override {};
|
|
|
|
|
void OnCriticalError(HRESULT Error) override;
|
|
|
|
|
|
2022-07-08 17:13:38 +02:00
|
|
|
// IMMNotificationClient callbacks
|
|
|
|
|
IFACEMETHODIMP_(ULONG) AddRef() override { return 1; };
|
|
|
|
|
IFACEMETHODIMP_(ULONG) Release() override { return 1; };
|
|
|
|
|
IFACEMETHODIMP QueryInterface(REFIID /*iid*/, void** /*object*/) override { return E_NOINTERFACE; };
|
|
|
|
|
IFACEMETHODIMP OnPropertyValueChanged(LPCWSTR /*device_id*/, const PROPERTYKEY /*key*/) override { return S_OK; };
|
|
|
|
|
IFACEMETHODIMP OnDeviceAdded(LPCWSTR /*device_id*/) override { return S_OK; };
|
|
|
|
|
IFACEMETHODIMP OnDeviceRemoved(LPCWSTR /*device_id*/) override { return S_OK; };
|
|
|
|
|
IFACEMETHODIMP OnDeviceStateChanged(LPCWSTR /*device_id*/, DWORD /*new_state*/) override { return S_OK; };
|
|
|
|
|
IFACEMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR new_default_device_id) override;
|
|
|
|
|
|
2021-11-24 19:41:05 +01:00
|
|
|
void CloseUnlocked();
|
2015-01-11 00:46:10 +01:00
|
|
|
};
|