- 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
103 lines
2.6 KiB
C++
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
|