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,17 @@
namespace XCEngine {
namespace Components {
namespace {
std::unique_lock<std::recursive_mutex> LockAudioState() {
if (Audio::AudioSystem* audioSystem = Audio::AudioSystem::TryGetExisting()) {
return audioSystem->AcquireStateLock();
}
return std::unique_lock<std::recursive_mutex>();
}
} // namespace
AudioListenerComponent::AudioListenerComponent()
{
Audio::AudioSystem::Get().RegisterListenerComponent(this);
@@ -17,36 +28,43 @@ AudioListenerComponent::~AudioListenerComponent() {
}
void AudioListenerComponent::SetMasterVolume(float volume) {
auto audioStateLock = LockAudioState();
m_masterVolume = std::max(0.0f, std::min(1.0f, volume));
Audio::AudioSystem::Get().SetMasterVolume(m_masterVolume);
}
void AudioListenerComponent::SetMute(bool mute) {
auto audioStateLock = LockAudioState();
m_mute = mute;
Audio::AudioSystem::Get().SetMuted(m_mute);
}
void AudioListenerComponent::SetDopplerLevel(float level) {
auto audioStateLock = LockAudioState();
m_dopplerLevel = std::max(0.0f, std::min(5.0f, level));
Audio::AudioSystem::Get().SetListenerDopplerLevel(m_dopplerLevel);
}
void AudioListenerComponent::SetSpeedOfSound(float metersPerSecond) {
auto audioStateLock = LockAudioState();
m_speedOfSound = std::max(1.0f, metersPerSecond);
Audio::AudioSystem::Get().SetSpeedOfSound(m_speedOfSound);
}
void AudioListenerComponent::SetReverbLevel(float level) {
auto audioStateLock = LockAudioState();
m_reverbLevel = std::max(0.0f, std::min(1.0f, level));
Audio::AudioSystem::Get().SetListenerReverbLevel(m_reverbLevel);
}
void AudioListenerComponent::SetReverb(Audio::AudioMixer* reverb) {
auto audioStateLock = LockAudioState();
m_reverb = reverb;
Audio::AudioSystem::Get().SetListenerReverbMixer(m_reverb);
}
void AudioListenerComponent::Update(float deltaTime) {
auto audioStateLock = LockAudioState();
if (!m_gameObject) {
return;
}
@@ -67,6 +85,7 @@ void AudioListenerComponent::Update(float deltaTime) {
}
void AudioListenerComponent::Serialize(std::ostream& os) const {
auto audioStateLock = LockAudioState();
os << "masterVolume=" << m_masterVolume << ";";
os << "mute=" << (m_mute ? 1 : 0) << ";";
os << "dopplerLevel=" << m_dopplerLevel << ";";
@@ -75,6 +94,7 @@ void AudioListenerComponent::Serialize(std::ostream& os) const {
}
void AudioListenerComponent::Deserialize(std::istream& is) {
auto audioStateLock = LockAudioState();
SetMasterVolume(1.0f);
SetMute(false);
SetDopplerLevel(1.0f);

View File

@@ -144,6 +144,13 @@ void ApplyPanToBuffer(float* buffer, Audio::uint32 frameCount, Audio::uint32 cha
}
}
std::unique_lock<std::recursive_mutex> LockAudioState() {
if (Audio::AudioSystem* audioSystem = Audio::AudioSystem::TryGetExisting()) {
return audioSystem->AcquireStateLock();
}
return std::unique_lock<std::recursive_mutex>();
}
} // namespace
AudioSourceComponent::AudioSourceComponent() {
@@ -158,6 +165,7 @@ AudioSourceComponent::~AudioSourceComponent() {
}
void AudioSourceComponent::Play() {
auto audioStateLock = LockAudioState();
if (!m_clip || !m_clip->IsValid()) {
return;
}
@@ -189,6 +197,7 @@ void AudioSourceComponent::Play() {
}
void AudioSourceComponent::Pause() {
auto audioStateLock = LockAudioState();
if (m_playState == Audio::PlayState::Playing) {
m_playState = Audio::PlayState::Paused;
Audio::AudioSystem::Get().UnregisterSource(this);
@@ -196,6 +205,7 @@ void AudioSourceComponent::Pause() {
}
void AudioSourceComponent::Stop(Audio::StopMode mode) {
auto audioStateLock = LockAudioState();
if (m_playState != Audio::PlayState::Stopped) {
m_playState = Audio::PlayState::Stopped;
m_samplePosition = 0;
@@ -209,6 +219,7 @@ void AudioSourceComponent::Stop(Audio::StopMode mode) {
}
void AudioSourceComponent::SetClip(Resources::AudioClip* clip) {
auto audioStateLock = LockAudioState();
m_clipHandle = Resources::ResourceHandle<Resources::AudioClip>(clip);
m_clip = clip;
m_clipPath.clear();
@@ -235,6 +246,7 @@ void AudioSourceComponent::SetClip(Resources::AudioClip* clip) {
}
void AudioSourceComponent::SetClipPath(const std::string& clipPath) {
auto audioStateLock = LockAudioState();
m_clipRef.Reset();
m_clipPath = clipPath;
if (!m_clipPath.empty() &&
@@ -266,24 +278,29 @@ void AudioSourceComponent::SetClipPath(const std::string& clipPath) {
}
void AudioSourceComponent::ClearClip() {
auto audioStateLock = LockAudioState();
m_clipRef.Reset();
m_clipPath.clear();
SetClip(nullptr);
}
void AudioSourceComponent::SetVolume(float volume) {
auto audioStateLock = LockAudioState();
m_volume = std::max(0.0f, std::min(1.0f, volume));
}
void AudioSourceComponent::SetPitch(float pitch) {
auto audioStateLock = LockAudioState();
m_pitch = std::max(0.0f, std::min(3.0f, pitch));
}
void AudioSourceComponent::SetPan(float pan) {
auto audioStateLock = LockAudioState();
m_pan = std::max(-1.0f, std::min(1.0f, pan));
}
void AudioSourceComponent::SetHRTFEnabled(bool enabled) {
auto audioStateLock = LockAudioState();
m_useHRTF = enabled;
if (!enabled) {
m_hrtf.ResetState();
@@ -291,22 +308,27 @@ void AudioSourceComponent::SetHRTFEnabled(bool enabled) {
}
void AudioSourceComponent::SetHRTFCrossFeed(float crossFeed) {
auto audioStateLock = LockAudioState();
m_hrtf.SetCrossFeed(crossFeed);
}
void AudioSourceComponent::SetHRTFQuality(Audio::uint32 level) {
auto audioStateLock = LockAudioState();
m_hrtf.SetQualityLevel(level);
}
void AudioSourceComponent::SetLooping(bool loop) {
auto audioStateLock = LockAudioState();
m_isLooping = loop;
}
void AudioSourceComponent::SetSpatialize(bool spatialize) {
auto audioStateLock = LockAudioState();
m_spatialize = spatialize;
}
void AudioSourceComponent::Set3DParams(const Audio::Audio3DParams& params) {
auto audioStateLock = LockAudioState();
m_3DParams = params;
m_3DParams.dopplerLevel = std::max(0.0f, m_3DParams.dopplerLevel);
m_3DParams.speedOfSound = std::max(1.0f, m_3DParams.speedOfSound);
@@ -318,22 +340,27 @@ void AudioSourceComponent::Set3DParams(const Audio::Audio3DParams& params) {
}
void AudioSourceComponent::SetDopplerLevel(float level) {
auto audioStateLock = LockAudioState();
m_3DParams.dopplerLevel = std::max(0.0f, level);
}
void AudioSourceComponent::SetSpread(float spread) {
auto audioStateLock = LockAudioState();
m_3DParams.spread = std::max(0.0f, std::min(1.0f, spread));
}
void AudioSourceComponent::SetReverbZoneMix(float mix) {
auto audioStateLock = LockAudioState();
m_3DParams.reverbZoneMix = std::max(0.0f, std::min(1.0f, mix));
}
void AudioSourceComponent::SetOutputMixer(Audio::AudioMixer* mixer) {
auto audioStateLock = LockAudioState();
m_outputMixer = mixer;
}
void AudioSourceComponent::SetTime(float seconds) {
auto audioStateLock = LockAudioState();
if (!m_clip || !m_clip->IsValid()) {
return;
}
@@ -370,15 +397,18 @@ float AudioSourceComponent::GetDuration() const {
}
void AudioSourceComponent::StartEnergyDetect() {
auto audioStateLock = LockAudioState();
m_isEnergyDetecting = true;
m_energyHistory.clear();
}
void AudioSourceComponent::StopEnergyDetect() {
auto audioStateLock = LockAudioState();
m_isEnergyDetecting = false;
}
void AudioSourceComponent::Update(float deltaTime) {
auto audioStateLock = LockAudioState();
if (m_gameObject) {
const Math::Vector3 position = transform().GetPosition();
if (m_hasLastPosition && deltaTime > 0.0f) {
@@ -403,12 +433,14 @@ void AudioSourceComponent::Update(float deltaTime) {
}
void AudioSourceComponent::OnEnable() {
auto audioStateLock = LockAudioState();
if (m_playState == Audio::PlayState::Playing) {
Audio::AudioSystem::Get().RegisterSource(this);
}
}
void AudioSourceComponent::OnDisable() {
auto audioStateLock = LockAudioState();
if (m_playState == Audio::PlayState::Playing) {
Audio::AudioSystem::Get().UnregisterSource(this);
}
@@ -419,6 +451,7 @@ void AudioSourceComponent::OnDestroy() {
}
void AudioSourceComponent::Serialize(std::ostream& os) const {
auto audioStateLock = LockAudioState();
Resources::AssetRef serializedClipRef = m_clipRef;
std::string serializedClipPath = m_clipPath;
if (serializedClipPath.empty() && m_clip != nullptr) {
@@ -458,6 +491,7 @@ void AudioSourceComponent::Serialize(std::ostream& os) const {
}
void AudioSourceComponent::Deserialize(std::istream& is) {
auto audioStateLock = LockAudioState();
ClearClip();
SetVolume(1.0f);
SetPitch(1.0f);
@@ -555,6 +589,7 @@ void AudioSourceComponent::ProcessAudio(float* buffer, Audio::uint32 frameCount,
float listenerDopplerLevel,
float speedOfSound,
Audio::uint32 outputSampleRate) {
auto audioStateLock = LockAudioState();
if (m_playState != Audio::PlayState::Playing || !m_clip) {
return;
}