audio: narrow render locking to snapshots

This commit is contained in:
2026-04-14 19:15:23 +08:00
parent 5a938935e1
commit 78556ea683
8 changed files with 420 additions and 188 deletions

View File

@@ -2,9 +2,10 @@
#include <XCEngine/Audio/AudioTypes.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <vector>
#include <map>
#include <mutex>
#include <string>
#include <vector>
namespace XCEngine {
namespace Audio {
@@ -17,19 +18,28 @@ public:
~AudioMixer();
void SetVolume(float volume);
float GetVolume() const { return m_volume; }
float GetVolume() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_volume;
}
void SetMute(bool mute);
bool IsMute() const { return m_mute; }
bool IsMute() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_mute;
}
void AddEffect(IAudioEffect* effect);
void RemoveEffect(IAudioEffect* effect);
void ClearEffects();
void ProcessAudio(float* buffer, uint32 sampleCount, uint32 channels);
void ProcessAudio(float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate = 48000);
void SetOutputMixer(AudioMixer* mixer);
AudioMixer* GetOutputMixer() const { return m_outputMixer; }
AudioMixer* GetOutputMixer() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_outputMixer;
}
void Set3DParams(const Audio3DParams& params);
const Audio3DParams& Get3DParams() const { return m_3DParams; }
@@ -40,8 +50,12 @@ public:
};
void SetChannelVolume(AudioChannel channel, float volume);
float GetChannelVolume(AudioChannel channel) const;
[[nodiscard]] std::unique_lock<std::recursive_mutex> AcquireStateLock() const {
return std::unique_lock<std::recursive_mutex>(m_stateMutex);
}
private:
mutable std::recursive_mutex m_stateMutex;
float m_volume = 1.0f;
bool m_mute = false;

View File

@@ -85,18 +85,40 @@ public:
const Stats& GetStats() const { return m_stats; }
private:
struct RenderStateSnapshot {
Math::Vector3 listenerPosition = Math::Vector3::Zero();
Math::Quaternion listenerRotation = Math::Quaternion::Identity();
Math::Vector3 listenerVelocity = Math::Vector3::Zero();
AudioMixer* listenerReverbMixer = nullptr;
float listenerReverbLevel = 1.0f;
float listenerDopplerLevel = 1.0f;
float speedOfSound = 343.0f;
};
AudioSystem();
~AudioSystem();
AudioSystem(const AudioSystem&) = delete;
AudioSystem& operator=(const AudioSystem&) = delete;
void ProcessSource(Components::AudioSourceComponent* source, float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate);
void RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sampleRate);
void CaptureRenderState(RenderStateSnapshot& snapshot);
void ProcessSource(
Components::AudioSourceComponent* source,
float* buffer,
uint32 frameCount,
uint32 channels,
uint32 sampleRate,
const RenderStateSnapshot& snapshot);
void RenderAudioBlock(
uint32 frameCount,
uint32 channels,
uint32 sampleRate,
const RenderStateSnapshot& snapshot);
void DetachMixerReferences(AudioMixer* mixer);
void UpdateStats();
private:
mutable std::recursive_mutex m_renderMutex;
mutable std::recursive_mutex m_stateMutex;
std::unique_ptr<IAudioBackend> m_backend;
AudioMixer m_masterMixer;

View File

@@ -3,6 +3,7 @@
#include <XCEngine/Components/Component.h>
#include <XCEngine/Components/TransformComponent.h>
#include <XCEngine/Audio/AudioTypes.h>
#include <mutex>
#include <vector>
namespace XCEngine {
@@ -17,33 +18,60 @@ public:
AudioListenerComponent();
~AudioListenerComponent() override;
float GetEnergy() const { return m_energy; }
float GetEnergy() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_energy;
}
const float* GetFrequencyData() const { return m_frequencyData.data(); }
size_t GetFrequencyDataSize() const { return m_frequencyData.size(); }
void SetMasterVolume(float volume);
float GetMasterVolume() const { return m_masterVolume; }
float GetMasterVolume() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_masterVolume;
}
void SetMute(bool mute);
bool IsMute() const { return m_mute; }
bool IsMute() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_mute;
}
void SetDopplerLevel(float level);
float GetDopplerLevel() const { return m_dopplerLevel; }
float GetDopplerLevel() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_dopplerLevel;
}
void SetSpeedOfSound(float metersPerSecond);
float GetSpeedOfSound() const { return m_speedOfSound; }
float GetSpeedOfSound() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_speedOfSound;
}
void SetReverbLevel(float level);
float GetReverbLevel() const { return m_reverbLevel; }
float GetReverbLevel() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_reverbLevel;
}
void SetReverb(Audio::AudioMixer* reverb);
Audio::AudioMixer* GetReverb() const { return m_reverb; }
Audio::AudioMixer* GetReverb() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_reverb;
}
void Update(float deltaTime) override;
void Serialize(std::ostream& os) const override;
void Deserialize(std::istream& is) override;
std::string GetName() const override { return "AudioListener"; }
[[nodiscard]] std::unique_lock<std::recursive_mutex> AcquireStateLock() const {
return std::unique_lock<std::recursive_mutex>(m_stateMutex);
}
private:
mutable std::recursive_mutex m_stateMutex;
float m_masterVolume = 1.0f;
bool m_mute = false;
float m_dopplerLevel = 1.0f;
@@ -52,6 +80,9 @@ private:
Audio::AudioMixer* m_reverb = nullptr;
Math::Vector3 m_lastPosition = Math::Vector3::Zero();
bool m_hasLastPosition = false;
float m_energy = 0.0f;
std::vector<float> m_frequencyData;
};

View File

@@ -9,9 +9,10 @@
#include <XCEngine/Resources/AudioClip/AudioClip.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Core/Math/Quaternion.h>
#include <vector>
#include <deque>
#include <mutex>
#include <string>
#include <vector>
namespace XCEngine {
namespace Audio {
@@ -28,61 +29,112 @@ public:
void Play();
void Pause();
void Stop(Audio::StopMode mode = Audio::StopMode::Immediate);
bool IsPlaying() const { return m_playState == Audio::PlayState::Playing; }
bool IsPaused() const { return m_playState == Audio::PlayState::Paused; }
bool IsPlaying() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_playState == Audio::PlayState::Playing;
}
bool IsPaused() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_playState == Audio::PlayState::Paused;
}
void SetClip(Resources::AudioClip* clip);
Resources::AudioClip* GetClip() const { return m_clip; }
Resources::AudioClip* GetClip() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_clip;
}
void SetClipPath(const std::string& clipPath);
void ClearClip();
const std::string& GetClipPath() const { return m_clipPath; }
const Resources::AssetRef& GetClipAssetRef() const { return m_clipRef; }
void SetVolume(float volume);
float GetVolume() const { return m_volume; }
float GetVolume() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_volume;
}
void SetPitch(float pitch);
float GetPitch() const { return m_pitch; }
float GetPitch() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_pitch;
}
void SetPan(float pan);
float GetPan() const { return m_pan; }
float GetPan() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_pan;
}
void SetHRTFEnabled(bool enabled);
bool IsHRTFEnabled() const { return m_useHRTF; }
bool IsHRTFEnabled() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_useHRTF;
}
void SetHRTFCrossFeed(float crossFeed);
float GetHRTFCrossFeed() const { return m_hrtf.GetCrossFeed(); }
float GetHRTFCrossFeed() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_hrtf.GetCrossFeed();
}
void SetHRTFQuality(Audio::uint32 level);
Audio::uint32 GetHRTFQuality() const { return m_hrtf.GetQualityLevel(); }
Audio::uint32 GetHRTFQuality() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_hrtf.GetQualityLevel();
}
void SetLooping(bool loop);
bool IsLooping() const { return m_isLooping; }
bool IsLooping() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_isLooping;
}
void SetSpatialize(bool spatialize);
bool IsSpatialize() const { return m_spatialize; }
bool IsSpatialize() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_spatialize;
}
void Set3DParams(const Audio::Audio3DParams& params);
const Audio::Audio3DParams& Get3DParams() const { return m_3DParams; }
void SetDopplerLevel(float level);
float GetDopplerLevel() const { return m_3DParams.dopplerLevel; }
float GetDopplerLevel() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_3DParams.dopplerLevel;
}
void SetSpread(float spread);
float GetSpread() const { return m_3DParams.spread; }
float GetSpread() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_3DParams.spread;
}
void SetReverbZoneMix(float mix);
float GetReverbZoneMix() const { return m_3DParams.reverbZoneMix; }
float GetReverbZoneMix() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_3DParams.reverbZoneMix;
}
void SetOutputMixer(Audio::AudioMixer* mixer);
Audio::AudioMixer* GetOutputMixer() const { return m_outputMixer; }
Audio::AudioMixer* GetOutputMixer() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_outputMixer;
}
void SetTime(float seconds);
float GetTime() const;
float GetDuration() const;
float GetEnergy() const { return m_energy; }
float GetEnergy() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_energy;
}
void StartEnergyDetect();
void StopEnergyDetect();
bool IsEnergyDetecting() const { return m_isEnergyDetecting; }
bool IsEnergyDetecting() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_isEnergyDetecting;
}
void Update(float deltaTime) override;
void OnEnable() override;
@@ -100,6 +152,9 @@ public:
Audio::uint32 outputSampleRate = 0);
std::string GetName() const override { return "AudioSource"; }
[[nodiscard]] std::unique_lock<std::recursive_mutex> AcquireStateLock() const {
return std::unique_lock<std::recursive_mutex>(m_stateMutex);
}
private:
float Compute3DAttenuation(const Math::Vector3& listenerPosition) const;
@@ -112,6 +167,7 @@ private:
void UpdateEnergy(const float* buffer, Audio::uint32 sampleCount);
private:
mutable std::recursive_mutex m_stateMutex;
Resources::ResourceHandle<Resources::AudioClip> m_clipHandle;
Resources::AudioClip* m_clip = nullptr;
std::string m_clipPath;