audio: switch waveout backend to pull rendering

This commit is contained in:
2026-04-14 19:04:18 +08:00
parent e77dbe40b1
commit 882df1ae5a
10 changed files with 378 additions and 94 deletions

View File

@@ -7,6 +7,7 @@
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Core/Math/Quaternion.h>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -22,6 +23,7 @@ namespace Audio {
class AudioSystem {
public:
static AudioSystem& Get();
static AudioSystem* TryGetExisting();
void Initialize(const AudioConfig& config);
void Shutdown();
@@ -30,6 +32,9 @@ public:
void SetBackend(std::unique_ptr<IAudioBackend> backend);
IAudioBackend* GetBackend() const { return m_backend.get(); }
[[nodiscard]] std::unique_lock<std::recursive_mutex> AcquireStateLock() {
return std::unique_lock<std::recursive_mutex>(m_stateMutex);
}
AudioMixer& GetMasterMixer() { return m_masterMixer; }
const AudioMixer& GetMasterMixer() const { return m_masterMixer; }
@@ -80,8 +85,8 @@ public:
const Stats& GetStats() const { return m_stats; }
private:
AudioSystem() = default;
~AudioSystem() = default;
AudioSystem();
~AudioSystem();
AudioSystem(const AudioSystem&) = delete;
AudioSystem& operator=(const AudioSystem&) = delete;
@@ -89,8 +94,10 @@ private:
void ProcessSource(Components::AudioSourceComponent* source, float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate);
void RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sampleRate);
void DetachMixerReferences(AudioMixer* mixer);
void UpdateStats();
private:
mutable std::recursive_mutex m_stateMutex;
std::unique_ptr<IAudioBackend> m_backend;
AudioMixer m_masterMixer;
AudioMixer* m_listenerReverbMixer = nullptr;

View File

@@ -1,13 +1,17 @@
#pragma once
#include "AudioConfig.h"
#include <functional>
#include <string>
#include <vector>
namespace XCEngine {
namespace Audio {
class IAudioBackend {
public:
using RenderCallback = std::function<void(float*, uint32, uint32, uint32)>;
virtual ~IAudioBackend() = default;
virtual bool Initialize(const AudioConfig& config) = 0;
@@ -26,6 +30,8 @@ public:
virtual void ProcessAudio(float* buffer, uint32 frameCount,
uint32 channels, uint32 sampleRate) = 0;
virtual bool UsesPullModel() const { return false; }
virtual void SetRenderCallback(RenderCallback callback) { (void)callback; }
virtual bool IsRunning() const = 0;
virtual AudioConfig GetConfig() const = 0;

View File

@@ -39,6 +39,8 @@ public:
void ProcessAudio(float* buffer, uint32 frameCount,
uint32 channels, uint32 sampleRate) override;
bool UsesPullModel() const override { return true; }
void SetRenderCallback(RenderCallback callback) override;
bool IsRunning() const override { return m_isRunning.load(); }
AudioConfig GetConfig() const override { return m_config; }
@@ -76,9 +78,6 @@ private:
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::string m_requestedDeviceName;
@@ -86,13 +85,13 @@ private:
static constexpr size_t BufferSize = 8192;
std::vector<int16_t> m_audioBuffer1;
std::vector<int16_t> m_audioBuffer2;
std::vector<float> m_pendingMixBuffer;
bool m_hasPendingMix = false;
std::vector<float> m_renderBuffer;
bool m_buffer1Available = true;
bool m_buffer2Available = true;
RenderCallback m_renderCallback;
std::mutex m_bufferMutex;
std::condition_variable m_dataReadyCond;
std::condition_variable m_bufferReadyCond;
WAVEHDR m_waveHeader1 = {};
WAVEHDR m_waveHeader2 = {};