Files
XCEngine/engine/include/XCEngine/Audio/WindowsAudioBackend.h
ssdfasd d575532966 docs: update TEST_SPEC.md and README.md to reflect new directory structure
- TEST_SPEC.md: Updated test directory structure to reflect Core/Asset,
  Core/IO, and Resources/<Type> subdirectories
- TEST_SPEC.md: Updated module names and test counts (852 total)
- TEST_SPEC.md: Updated build commands for new Resources subdirectories
- README.md: Updated engine structure with Core/Asset/ and Core/IO/
- README.md: Updated Resources section with layered architecture
- README.md: Updated test coverage table with accurate counts
2026-03-24 16:14:05 +08:00

103 lines
2.6 KiB
C++

#pragma once
#include <XCEngine/Audio/IAudioBackend.h>
#include <string>
#include <vector>
#include <thread>
#include <atomic>
#include <mutex>
#include <condition_variable>
#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
#endif
namespace XCEngine {
namespace Audio {
namespace WASAPI {
class WASAPIBackend : public IAudioBackend {
public:
WASAPIBackend();
~WASAPIBackend() override;
bool Initialize(const AudioConfig& config) override;
void Shutdown() override;
std::string GetDeviceName() const override;
void GetAvailableDevices(std::vector<std::string>& devices) override;
bool SetDevice(const std::string& deviceName) override;
float GetMasterVolume() const override;
void SetMasterVolume(float volume) override;
bool IsMuted() const override;
void SetMuted(bool muted) override;
void Start() override;
void Stop() override;
void Suspend() override;
void Resume() override;
void ProcessAudio(float* buffer, uint32 bufferSize,
uint32 channels, uint32 sampleRate) override;
bool IsRunning() const override { return m_isRunning.load(); }
AudioConfig GetConfig() const override { return m_config; }
private:
MMRESULT InitDevice();
MMRESULT InitBuffer();
static DWORD WINAPI AudioThreadProc(LPVOID lpParameter);
void AudioThread();
void OnAudioCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2);
static void CALLBACK StaticAudioCallback(HWAVEOUT hwo, UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2);
MMRESULT PlayFrontData();
void PrepareBackData();
void SwapBuffer();
private:
std::atomic<bool> m_isRunning{false};
std::thread m_audioThread;
AudioConfig m_config;
WAVEFORMATEX m_waveFormat = {};
HWAVEOUT m_hWaveOut = nullptr;
std::vector<float> m_mixBuffer;
uint32 m_mixBufferSize = 0;
std::vector<WAVEOUTCAPS> m_waveOutCaps;
std::string m_deviceName;
std::atomic<float> m_masterVolume{1.0f};
std::atomic<bool> m_muted{false};
static constexpr size_t BufferSize = 8192;
std::vector<int16_t> m_audioBuffer1;
std::vector<int16_t> m_audioBuffer2;
bool m_isBuffer1Front = true;
bool m_isBufferPrepared = false;
bool m_dataReady = false;
std::mutex m_bufferMutex;
std::condition_variable m_dataReadyCond;
WAVEHDR m_waveHeader1 = {};
WAVEHDR m_waveHeader2 = {};
};
} // namespace WASAPI
} // namespace Audio
} // namespace XCEngine