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

@@ -9,13 +9,6 @@ namespace Audio {
namespace {
std::unique_lock<std::recursive_mutex> LockAudioState() {
if (AudioSystem* audioSystem = AudioSystem::TryGetExisting()) {
return audioSystem->AcquireStateLock();
}
return std::unique_lock<std::recursive_mutex>();
}
AudioChannel ResolveChannel(uint32 channelIndex) {
switch (channelIndex) {
case 0: return AudioChannel::FrontLeft;
@@ -49,24 +42,24 @@ AudioMixer::~AudioMixer() {
}
void AudioMixer::SetVolume(float volume) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_volume = std::max(0.0f, std::min(1.0f, volume));
}
void AudioMixer::SetMute(bool mute) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_mute = mute;
}
void AudioMixer::AddEffect(IAudioEffect* effect) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (effect && std::find(m_effects.begin(), m_effects.end(), effect) == m_effects.end()) {
m_effects.push_back(effect);
}
}
void AudioMixer::RemoveEffect(IAudioEffect* effect) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!effect) return;
auto it = std::find(m_effects.begin(), m_effects.end(), effect);
if (it != m_effects.end()) {
@@ -75,12 +68,12 @@ void AudioMixer::RemoveEffect(IAudioEffect* effect) {
}
void AudioMixer::ClearEffects() {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_effects.clear();
}
void AudioMixer::ProcessAudio(float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!buffer || frameCount == 0 || channels == 0) {
return;
}
@@ -115,17 +108,17 @@ void AudioMixer::ProcessAudio(float* buffer, uint32 frameCount, uint32 channels,
}
void AudioMixer::SetOutputMixer(AudioMixer* mixer) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_outputMixer = mixer;
}
void AudioMixer::Set3DParams(const Audio3DParams& params) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_3DParams = params;
}
void AudioMixer::SetChannelVolume(AudioChannel channel, float volume) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
auto it = m_channelVolumes.find(channel);
if (it != m_channelVolumes.end()) {
it->second.volume = std::max(0.0f, std::min(1.0f, volume));
@@ -133,7 +126,7 @@ void AudioMixer::SetChannelVolume(AudioChannel channel, float volume) {
}
float AudioMixer::GetChannelVolume(AudioChannel channel) const {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
auto it = m_channelVolumes.find(channel);
if (it != m_channelVolumes.end()) {
return it->second.volume;

View File

@@ -131,6 +131,7 @@ void AudioSystem::Initialize(const AudioConfig& config) {
}
void AudioSystem::Shutdown() {
std::lock_guard<std::recursive_mutex> renderLock(m_renderMutex);
std::unique_ptr<IAudioBackend> backend;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
@@ -171,25 +172,41 @@ void AudioSystem::Shutdown() {
}
void AudioSystem::Update(float deltaTime) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_deltaTime = deltaTime;
IAudioBackend* backend = nullptr;
AudioConfig config{};
bool usesPullModel = false;
if (!m_backend || !m_backend->IsRunning()) {
return;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_deltaTime = deltaTime;
if (!m_backend || !m_backend->IsRunning()) {
return;
}
backend = m_backend.get();
usesPullModel = backend->UsesPullModel();
if (!usesPullModel) {
config = backend->GetConfig();
}
}
if (!m_backend->UsesPullModel()) {
const auto& config = m_backend->GetConfig();
if (!usesPullModel) {
std::lock_guard<std::recursive_mutex> renderLock(m_renderMutex);
RenderStateSnapshot snapshot;
CaptureRenderState(snapshot);
const uint32 frameCount = config.bufferSize;
RenderAudioBlock(frameCount, config.channels, config.sampleRate);
m_backend->ProcessAudio(
RenderAudioBlock(frameCount, config.channels, config.sampleRate, snapshot);
backend->ProcessAudio(
m_mixScratchBuffer.data(),
frameCount,
config.channels,
config.sampleRate);
} else {
UpdateStats();
return;
}
UpdateStats();
}
void AudioSystem::SetBackend(std::unique_ptr<IAudioBackend> backend) {
@@ -278,12 +295,14 @@ void AudioSystem::SetSpeedOfSound(float metersPerSecond) {
}
void AudioSystem::RenderAudio(float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (buffer == nullptr || frameCount == 0 || channels == 0 || sampleRate == 0) {
return;
}
RenderAudioBlock(frameCount, channels, sampleRate);
std::lock_guard<std::recursive_mutex> renderLock(m_renderMutex);
RenderStateSnapshot snapshot;
CaptureRenderState(snapshot);
RenderAudioBlock(frameCount, channels, sampleRate, snapshot);
const size_t sampleCount = static_cast<size_t>(frameCount) * channels;
std::copy_n(m_mixScratchBuffer.data(), sampleCount, buffer);
}
@@ -332,6 +351,7 @@ void AudioSystem::RegisterSourceComponent(Components::AudioSourceComponent* sour
}
void AudioSystem::UnregisterSourceComponent(Components::AudioSourceComponent* source) {
std::lock_guard<std::recursive_mutex> renderLock(m_renderMutex);
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!source) {
return;
@@ -378,6 +398,7 @@ void AudioSystem::RegisterMixer(AudioMixer* mixer) {
}
void AudioSystem::UnregisterMixer(AudioMixer* mixer) {
std::lock_guard<std::recursive_mutex> renderLock(m_renderMutex);
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!mixer) {
return;
@@ -390,6 +411,7 @@ void AudioSystem::UnregisterMixer(AudioMixer* mixer) {
}
void AudioSystem::UnregisterSource(Components::AudioSourceComponent* source) {
std::lock_guard<std::recursive_mutex> renderLock(m_renderMutex);
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!source) {
return;
@@ -428,7 +450,25 @@ void AudioSystem::DetachMixerReferences(AudioMixer* mixer) {
}
}
void AudioSystem::ProcessSource(Components::AudioSourceComponent* source, float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate) {
void AudioSystem::CaptureRenderState(RenderStateSnapshot& snapshot) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_activeSourceSnapshot = m_activeSources;
snapshot.listenerPosition = m_listenerPosition;
snapshot.listenerRotation = m_listenerRotation;
snapshot.listenerVelocity = m_listenerVelocity;
snapshot.listenerReverbMixer = m_listenerReverbMixer;
snapshot.listenerReverbLevel = m_listenerReverbLevel;
snapshot.listenerDopplerLevel = m_listenerDopplerLevel;
snapshot.speedOfSound = m_speedOfSound;
}
void AudioSystem::ProcessSource(
Components::AudioSourceComponent* source,
float* buffer,
uint32 frameCount,
uint32 channels,
uint32 sampleRate,
const RenderStateSnapshot& snapshot) {
if (!source || !buffer) {
return;
}
@@ -437,15 +477,19 @@ void AudioSystem::ProcessSource(Components::AudioSourceComponent* source, float*
buffer,
frameCount,
channels,
m_listenerPosition,
m_listenerRotation,
m_listenerVelocity,
m_listenerDopplerLevel,
m_speedOfSound,
snapshot.listenerPosition,
snapshot.listenerRotation,
snapshot.listenerVelocity,
snapshot.listenerDopplerLevel,
snapshot.speedOfSound,
sampleRate);
}
void AudioSystem::RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sampleRate) {
void AudioSystem::RenderAudioBlock(
uint32 frameCount,
uint32 channels,
uint32 sampleRate,
const RenderStateSnapshot& snapshot) {
const size_t sampleCount = static_cast<size_t>(frameCount) * channels;
if (sampleCount == 0 || sampleRate == 0) {
m_mixScratchBuffer.clear();
@@ -466,7 +510,6 @@ void AudioSystem::RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sa
std::fill(m_sourceScratchBuffer.begin(), m_sourceScratchBuffer.end(), 0.0f);
}
m_activeSourceSnapshot = m_activeSources;
m_mixerScratchChildren.clear();
m_mixerScratchActiveMixers.clear();
m_mixerScratchVisiting.clear();
@@ -504,14 +547,20 @@ void AudioSystem::RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sa
}
};
if (m_listenerReverbMixer != nullptr) {
registerMixerChain(m_listenerReverbMixer);
if (snapshot.listenerReverbMixer != nullptr) {
registerMixerChain(snapshot.listenerReverbMixer);
}
for (auto* source : m_activeSourceSnapshot) {
if (source && source->IsEnabled() && source->IsPlaying()) {
std::fill(m_sourceScratchBuffer.begin(), m_sourceScratchBuffer.end(), 0.0f);
ProcessSource(source, m_sourceScratchBuffer.data(), frameCount, channels, sampleRate);
ProcessSource(
source,
m_sourceScratchBuffer.data(),
frameCount,
channels,
sampleRate,
snapshot);
AudioMixer* outputMixer = source->GetOutputMixer();
if (outputMixer != nullptr) {
@@ -521,14 +570,14 @@ void AudioSystem::RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sa
MixBufferInto(m_sourceScratchBuffer, m_mixScratchBuffer);
}
if (m_listenerReverbMixer != nullptr && m_listenerReverbLevel > 0.0f) {
if (snapshot.listenerReverbMixer != nullptr && snapshot.listenerReverbLevel > 0.0f) {
const float sendGain = std::clamp(
source->GetReverbZoneMix() * m_listenerReverbLevel,
source->GetReverbZoneMix() * snapshot.listenerReverbLevel,
0.0f,
1.0f);
MixScaledBufferInto(
m_sourceScratchBuffer,
ensureMixerBuffer(m_listenerReverbMixer),
ensureMixerBuffer(snapshot.listenerReverbMixer),
sendGain);
}
}
@@ -557,14 +606,24 @@ void AudioSystem::RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sa
}
void AudioSystem::UpdateStats() {
std::vector<Components::AudioSourceComponent*> activeSources;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
activeSources = m_activeSources;
}
uint32 activeCount = 0;
for (auto* source : m_activeSources) {
for (auto* source : activeSources) {
if (source && source->IsPlaying()) {
activeCount++;
}
}
m_stats.activeSources = activeCount;
m_stats.totalSources = static_cast<uint32>(m_activeSources.size());
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_stats.activeSources = activeCount;
m_stats.totalSources = static_cast<uint32>(activeSources.size());
}
}
} // namespace Audio

View File

@@ -7,17 +7,6 @@
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);
@@ -28,43 +17,66 @@ 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);
float masterVolume = 0.0f;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_masterVolume = std::max(0.0f, std::min(1.0f, volume));
masterVolume = m_masterVolume;
}
Audio::AudioSystem::Get().SetMasterVolume(masterVolume);
}
void AudioListenerComponent::SetMute(bool mute) {
auto audioStateLock = LockAudioState();
m_mute = mute;
Audio::AudioSystem::Get().SetMuted(m_mute);
bool isMute = false;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_mute = mute;
isMute = m_mute;
}
Audio::AudioSystem::Get().SetMuted(isMute);
}
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);
float dopplerLevel = 1.0f;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_dopplerLevel = std::max(0.0f, std::min(5.0f, level));
dopplerLevel = m_dopplerLevel;
}
Audio::AudioSystem::Get().SetListenerDopplerLevel(dopplerLevel);
}
void AudioListenerComponent::SetSpeedOfSound(float metersPerSecond) {
auto audioStateLock = LockAudioState();
m_speedOfSound = std::max(1.0f, metersPerSecond);
Audio::AudioSystem::Get().SetSpeedOfSound(m_speedOfSound);
float speedOfSound = 343.0f;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_speedOfSound = std::max(1.0f, metersPerSecond);
speedOfSound = m_speedOfSound;
}
Audio::AudioSystem::Get().SetSpeedOfSound(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);
float reverbLevel = 1.0f;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_reverbLevel = std::max(0.0f, std::min(1.0f, level));
reverbLevel = m_reverbLevel;
}
Audio::AudioSystem::Get().SetListenerReverbLevel(reverbLevel);
}
void AudioListenerComponent::SetReverb(Audio::AudioMixer* reverb) {
auto audioStateLock = LockAudioState();
m_reverb = reverb;
Audio::AudioSystem::Get().SetListenerReverbMixer(m_reverb);
Audio::AudioMixer* reverbMixer = nullptr;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_reverb = reverb;
reverbMixer = m_reverb;
}
Audio::AudioSystem::Get().SetListenerReverbMixer(reverbMixer);
}
void AudioListenerComponent::Update(float deltaTime) {
auto audioStateLock = LockAudioState();
if (!m_gameObject) {
return;
}
@@ -73,19 +85,21 @@ void AudioListenerComponent::Update(float deltaTime) {
const Math::Quaternion rotation = transform().GetRotation();
Math::Vector3 velocity = Math::Vector3::Zero();
if (m_hasLastPosition && deltaTime > 0.0f) {
velocity = (position - m_lastPosition) / deltaTime;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_hasLastPosition && deltaTime > 0.0f) {
velocity = (position - m_lastPosition) / deltaTime;
}
m_lastPosition = position;
m_hasLastPosition = true;
}
Audio::AudioSystem::Get().SetListenerTransform(position, rotation);
Audio::AudioSystem::Get().SetListenerVelocity(velocity);
m_lastPosition = position;
m_hasLastPosition = true;
}
void AudioListenerComponent::Serialize(std::ostream& os) const {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
os << "masterVolume=" << m_masterVolume << ";";
os << "mute=" << (m_mute ? 1 : 0) << ";";
os << "dopplerLevel=" << m_dopplerLevel << ";";
@@ -94,7 +108,6 @@ 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,13 +144,6 @@ 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,68 +151,96 @@ AudioSourceComponent::AudioSourceComponent() {
}
AudioSourceComponent::~AudioSourceComponent() {
bool wasPlaying = false;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
wasPlaying = (m_playState == Audio::PlayState::Playing);
m_playState = Audio::PlayState::Stopped;
}
Audio::AudioSystem::Get().UnregisterSourceComponent(this);
if (m_playState == Audio::PlayState::Playing) {
if (wasPlaying) {
Audio::AudioSystem::Get().UnregisterSource(this);
}
}
void AudioSourceComponent::Play() {
auto audioStateLock = LockAudioState();
if (!m_clip || !m_clip->IsValid()) {
return;
bool registerSource = false;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!m_clip || !m_clip->IsValid()) {
return;
}
if (m_playState == Audio::PlayState::Playing) {
m_samplePosition = 0;
m_playbackPosition = 0.0;
m_lastingTime = 0.0;
m_velocity = Math::Vector3::Zero();
m_hasLastPosition = false;
m_hrtf.ResetState();
return;
}
if (m_playState == Audio::PlayState::Paused) {
m_playState = Audio::PlayState::Playing;
registerSource = true;
} else {
m_samplePosition = 0;
m_playbackPosition = 0.0;
m_lastingTime = 0.0;
m_velocity = Math::Vector3::Zero();
m_hasLastPosition = false;
m_hrtf.ResetState();
m_playState = Audio::PlayState::Playing;
registerSource = true;
}
}
if (m_playState == Audio::PlayState::Playing) {
m_samplePosition = 0;
m_playbackPosition = 0.0;
m_lastingTime = 0.0;
m_velocity = Math::Vector3::Zero();
m_hasLastPosition = false;
m_hrtf.ResetState();
return;
}
if (m_playState == Audio::PlayState::Paused) {
m_playState = Audio::PlayState::Playing;
if (registerSource) {
Audio::AudioSystem::Get().RegisterSource(this);
return;
}
m_samplePosition = 0;
m_playbackPosition = 0.0;
m_lastingTime = 0.0;
m_velocity = Math::Vector3::Zero();
m_hasLastPosition = false;
m_hrtf.ResetState();
m_playState = Audio::PlayState::Playing;
Audio::AudioSystem::Get().RegisterSource(this);
}
void AudioSourceComponent::Pause() {
auto audioStateLock = LockAudioState();
if (m_playState == Audio::PlayState::Playing) {
m_playState = Audio::PlayState::Paused;
bool unregisterSource = false;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_playState == Audio::PlayState::Playing) {
m_playState = Audio::PlayState::Paused;
unregisterSource = true;
}
}
if (unregisterSource) {
Audio::AudioSystem::Get().UnregisterSource(this);
}
}
void AudioSourceComponent::Stop(Audio::StopMode mode) {
auto audioStateLock = LockAudioState();
if (m_playState != Audio::PlayState::Stopped) {
m_playState = Audio::PlayState::Stopped;
m_samplePosition = 0;
m_playbackPosition = 0.0;
m_lastingTime = 0.0;
m_velocity = Math::Vector3::Zero();
m_hasLastPosition = false;
m_hrtf.ResetState();
(void)mode;
bool unregisterSource = false;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_playState != Audio::PlayState::Stopped) {
m_playState = Audio::PlayState::Stopped;
m_samplePosition = 0;
m_playbackPosition = 0.0;
m_lastingTime = 0.0;
m_velocity = Math::Vector3::Zero();
m_hasLastPosition = false;
m_hrtf.ResetState();
unregisterSource = true;
}
}
if (unregisterSource) {
Audio::AudioSystem::Get().UnregisterSource(this);
}
}
void AudioSourceComponent::SetClip(Resources::AudioClip* clip) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_clipHandle = Resources::ResourceHandle<Resources::AudioClip>(clip);
m_clip = clip;
m_clipPath.clear();
@@ -246,7 +267,7 @@ void AudioSourceComponent::SetClip(Resources::AudioClip* clip) {
}
void AudioSourceComponent::SetClipPath(const std::string& clipPath) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_clipRef.Reset();
m_clipPath = clipPath;
if (!m_clipPath.empty() &&
@@ -278,29 +299,29 @@ void AudioSourceComponent::SetClipPath(const std::string& clipPath) {
}
void AudioSourceComponent::ClearClip() {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_clipRef.Reset();
m_clipPath.clear();
SetClip(nullptr);
}
void AudioSourceComponent::SetVolume(float volume) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_volume = std::max(0.0f, std::min(1.0f, volume));
}
void AudioSourceComponent::SetPitch(float pitch) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_pitch = std::max(0.0f, std::min(3.0f, pitch));
}
void AudioSourceComponent::SetPan(float pan) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_pan = std::max(-1.0f, std::min(1.0f, pan));
}
void AudioSourceComponent::SetHRTFEnabled(bool enabled) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_useHRTF = enabled;
if (!enabled) {
m_hrtf.ResetState();
@@ -308,27 +329,27 @@ void AudioSourceComponent::SetHRTFEnabled(bool enabled) {
}
void AudioSourceComponent::SetHRTFCrossFeed(float crossFeed) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_hrtf.SetCrossFeed(crossFeed);
}
void AudioSourceComponent::SetHRTFQuality(Audio::uint32 level) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_hrtf.SetQualityLevel(level);
}
void AudioSourceComponent::SetLooping(bool loop) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_isLooping = loop;
}
void AudioSourceComponent::SetSpatialize(bool spatialize) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_spatialize = spatialize;
}
void AudioSourceComponent::Set3DParams(const Audio::Audio3DParams& params) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_3DParams = params;
m_3DParams.dopplerLevel = std::max(0.0f, m_3DParams.dopplerLevel);
m_3DParams.speedOfSound = std::max(1.0f, m_3DParams.speedOfSound);
@@ -340,27 +361,27 @@ void AudioSourceComponent::Set3DParams(const Audio::Audio3DParams& params) {
}
void AudioSourceComponent::SetDopplerLevel(float level) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_3DParams.dopplerLevel = std::max(0.0f, level);
}
void AudioSourceComponent::SetSpread(float spread) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_3DParams.spread = std::max(0.0f, std::min(1.0f, spread));
}
void AudioSourceComponent::SetReverbZoneMix(float mix) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_3DParams.reverbZoneMix = std::max(0.0f, std::min(1.0f, mix));
}
void AudioSourceComponent::SetOutputMixer(Audio::AudioMixer* mixer) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_outputMixer = mixer;
}
void AudioSourceComponent::SetTime(float seconds) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!m_clip || !m_clip->IsValid()) {
return;
}
@@ -386,10 +407,12 @@ void AudioSourceComponent::SetTime(float seconds) {
}
float AudioSourceComponent::GetTime() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return static_cast<float>(m_lastingTime);
}
float AudioSourceComponent::GetDuration() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!m_clip || !m_clip->IsValid()) {
return 0.0f;
}
@@ -397,18 +420,18 @@ float AudioSourceComponent::GetDuration() const {
}
void AudioSourceComponent::StartEnergyDetect() {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_isEnergyDetecting = true;
m_energyHistory.clear();
}
void AudioSourceComponent::StopEnergyDetect() {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_isEnergyDetecting = false;
}
void AudioSourceComponent::Update(float deltaTime) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_gameObject) {
const Math::Vector3 position = transform().GetPosition();
if (m_hasLastPosition && deltaTime > 0.0f) {
@@ -433,15 +456,23 @@ void AudioSourceComponent::Update(float deltaTime) {
}
void AudioSourceComponent::OnEnable() {
auto audioStateLock = LockAudioState();
if (m_playState == Audio::PlayState::Playing) {
bool registerSource = false;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
registerSource = (m_playState == Audio::PlayState::Playing);
}
if (registerSource) {
Audio::AudioSystem::Get().RegisterSource(this);
}
}
void AudioSourceComponent::OnDisable() {
auto audioStateLock = LockAudioState();
if (m_playState == Audio::PlayState::Playing) {
bool unregisterSource = false;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
unregisterSource = (m_playState == Audio::PlayState::Playing);
}
if (unregisterSource) {
Audio::AudioSystem::Get().UnregisterSource(this);
}
}
@@ -451,7 +482,7 @@ void AudioSourceComponent::OnDestroy() {
}
void AudioSourceComponent::Serialize(std::ostream& os) const {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
Resources::AssetRef serializedClipRef = m_clipRef;
std::string serializedClipPath = m_clipPath;
if (serializedClipPath.empty() && m_clip != nullptr) {
@@ -491,7 +522,7 @@ void AudioSourceComponent::Serialize(std::ostream& os) const {
}
void AudioSourceComponent::Deserialize(std::istream& is) {
auto audioStateLock = LockAudioState();
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
ClearClip();
SetVolume(1.0f);
SetPitch(1.0f);
@@ -589,7 +620,7 @@ void AudioSourceComponent::ProcessAudio(float* buffer, Audio::uint32 frameCount,
float listenerDopplerLevel,
float speedOfSound,
Audio::uint32 outputSampleRate) {
auto audioStateLock = LockAudioState();
std::unique_lock<std::recursive_mutex> lock(m_stateMutex);
if (m_playState != Audio::PlayState::Playing || !m_clip) {
return;
}
@@ -654,6 +685,7 @@ void AudioSourceComponent::ProcessAudio(float* buffer, Audio::uint32 frameCount,
double playbackPosition = m_playbackPosition;
bool reachedClipEnd = false;
Audio::uint32 renderedFrameCount = 0;
bool unregisterSource = false;
for (Audio::uint32 i = 0; i < frameCount; ++i) {
if (!m_isLooping && playbackPosition >= static_cast<double>(totalFrames)) {
@@ -779,13 +811,25 @@ void AudioSourceComponent::ProcessAudio(float* buffer, Audio::uint32 frameCount,
m_samplePosition = static_cast<Audio::uint64>(m_playbackPosition);
m_lastingTime = m_playbackPosition / static_cast<double>(clipSampleRate);
} else {
Stop();
m_playState = Audio::PlayState::Stopped;
m_samplePosition = 0;
m_playbackPosition = 0.0;
m_lastingTime = 0.0;
m_velocity = Math::Vector3::Zero();
m_hasLastPosition = false;
m_hrtf.ResetState();
unregisterSource = true;
}
}
if (m_isEnergyDetecting) {
UpdateEnergy(buffer, renderedFrameCount * channels);
}
lock.unlock();
if (unregisterSource) {
Audio::AudioSystem::Get().UnregisterSource(this);
}
}
float AudioSourceComponent::Compute3DAttenuation(const Math::Vector3& listenerPosition) const {