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

@@ -9,6 +9,13 @@ 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;
@@ -27,31 +34,39 @@ AudioChannel ResolveChannel(uint32 channelIndex) {
AudioMixer::AudioMixer()
{
AudioSystem::Get().RegisterMixer(this);
if (AudioSystem* audioSystem = AudioSystem::TryGetExisting()) {
audioSystem->RegisterMixer(this);
}
for (int i = 0; i < static_cast<int>(AudioChannel::SideRight) + 1; ++i) {
m_channelVolumes[static_cast<AudioChannel>(i)] = ChannelVolume{1.0f, false};
}
}
AudioMixer::~AudioMixer() {
AudioSystem::Get().UnregisterMixer(this);
if (AudioSystem* audioSystem = AudioSystem::TryGetExisting()) {
audioSystem->UnregisterMixer(this);
}
}
void AudioMixer::SetVolume(float volume) {
auto audioStateLock = LockAudioState();
m_volume = std::max(0.0f, std::min(1.0f, volume));
}
void AudioMixer::SetMute(bool mute) {
auto audioStateLock = LockAudioState();
m_mute = mute;
}
void AudioMixer::AddEffect(IAudioEffect* effect) {
auto audioStateLock = LockAudioState();
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();
if (!effect) return;
auto it = std::find(m_effects.begin(), m_effects.end(), effect);
if (it != m_effects.end()) {
@@ -60,10 +75,12 @@ void AudioMixer::RemoveEffect(IAudioEffect* effect) {
}
void AudioMixer::ClearEffects() {
auto audioStateLock = LockAudioState();
m_effects.clear();
}
void AudioMixer::ProcessAudio(float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate) {
auto audioStateLock = LockAudioState();
if (!buffer || frameCount == 0 || channels == 0) {
return;
}
@@ -98,14 +115,17 @@ void AudioMixer::ProcessAudio(float* buffer, uint32 frameCount, uint32 channels,
}
void AudioMixer::SetOutputMixer(AudioMixer* mixer) {
auto audioStateLock = LockAudioState();
m_outputMixer = mixer;
}
void AudioMixer::Set3DParams(const Audio3DParams& params) {
auto audioStateLock = LockAudioState();
m_3DParams = params;
}
void AudioMixer::SetChannelVolume(AudioChannel channel, float volume) {
auto audioStateLock = LockAudioState();
auto it = m_channelVolumes.find(channel);
if (it != m_channelVolumes.end()) {
it->second.volume = std::max(0.0f, std::min(1.0f, volume));
@@ -113,6 +133,7 @@ void AudioMixer::SetChannelVolume(AudioChannel channel, float volume) {
}
float AudioMixer::GetChannelVolume(AudioChannel channel) const {
auto audioStateLock = LockAudioState();
auto it = m_channelVolumes.find(channel);
if (it != m_channelVolumes.end()) {
return it->second.volume;

View File

@@ -12,6 +12,8 @@ namespace Audio {
namespace {
AudioSystem* g_audioSystemInstance = nullptr;
void MixBufferInto(const std::vector<float>& source, std::vector<float>& destination) {
if (destination.size() < source.size()) {
destination.resize(source.size(), 0.0f);
@@ -93,79 +95,128 @@ AudioSystem& AudioSystem::Get() {
return instance;
}
void AudioSystem::Initialize(const AudioConfig& config) {
if (m_backend) {
Shutdown();
}
AudioSystem* AudioSystem::TryGetExisting() {
return g_audioSystemInstance;
}
m_backend = std::make_unique<Audio::WaveOut::WaveOutBackend>();
if (m_backend->Initialize(config)) {
m_backend->Start();
AudioSystem::AudioSystem() {
g_audioSystemInstance = this;
RegisterMixer(&m_masterMixer);
}
AudioSystem::~AudioSystem() {
g_audioSystemInstance = nullptr;
}
void AudioSystem::Initialize(const AudioConfig& config) {
Shutdown();
auto backend = std::make_unique<Audio::WaveOut::WaveOutBackend>();
backend->SetRenderCallback(
[this](float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate) {
RenderAudio(buffer, frameCount, channels, sampleRate);
});
if (backend->Initialize(config)) {
IAudioBackend* backendPtr = backend.get();
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_backend = std::move(backend);
}
backendPtr->Start();
std::cout << "AudioSystem initialized successfully" << std::endl;
} else {
std::cout << "Failed to initialize AudioSystem" << std::endl;
m_backend.reset();
}
}
void AudioSystem::Shutdown() {
if (m_backend) {
m_backend->Stop();
m_backend->Shutdown();
m_backend.reset();
std::unique_ptr<IAudioBackend> backend;
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
backend = std::move(m_backend);
}
if (backend) {
if (backend->IsRunning()) {
backend->Stop();
}
backend->Shutdown();
}
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_registeredMixers.clear();
m_registeredSourceComponents.clear();
m_registeredListenerComponents.clear();
m_activeSources.clear();
m_listenerReverbMixer = nullptr;
m_listenerReverbLevel = 1.0f;
m_listenerDopplerLevel = 1.0f;
m_speedOfSound = 343.0f;
m_listenerPosition = Math::Vector3::Zero();
m_listenerRotation = Math::Quaternion::Identity();
m_listenerVelocity = Math::Vector3::Zero();
m_activeSourceSnapshot.clear();
m_mixScratchBuffer.clear();
m_sourceScratchBuffer.clear();
m_mixerScratchBuffers.clear();
m_mixerScratchChildren.clear();
m_mixerScratchActiveMixers.clear();
m_mixerScratchVisiting.clear();
m_mixerScratchRendered.clear();
m_deltaTime = 0.0f;
m_stats = {};
}
m_registeredMixers.clear();
m_registeredSourceComponents.clear();
m_registeredListenerComponents.clear();
m_activeSources.clear();
m_listenerReverbMixer = nullptr;
m_listenerReverbLevel = 1.0f;
m_listenerDopplerLevel = 1.0f;
m_speedOfSound = 343.0f;
m_listenerPosition = Math::Vector3::Zero();
m_listenerRotation = Math::Quaternion::Identity();
m_listenerVelocity = Math::Vector3::Zero();
m_activeSourceSnapshot.clear();
m_mixScratchBuffer.clear();
m_sourceScratchBuffer.clear();
m_mixerScratchBuffers.clear();
m_mixerScratchChildren.clear();
m_mixerScratchActiveMixers.clear();
m_mixerScratchVisiting.clear();
m_mixerScratchRendered.clear();
}
void AudioSystem::Update(float deltaTime) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_deltaTime = deltaTime;
if (!m_backend || !m_backend->IsRunning()) {
return;
}
const auto& config = m_backend->GetConfig();
const uint32 frameCount = config.bufferSize;
RenderAudioBlock(frameCount, config.channels, config.sampleRate);
m_backend->ProcessAudio(
m_mixScratchBuffer.data(),
frameCount,
config.channels,
config.sampleRate);
uint32 activeCount = 0;
for (auto* source : m_activeSources) {
if (source && source->IsPlaying()) {
activeCount++;
}
if (!m_backend->UsesPullModel()) {
const auto& config = m_backend->GetConfig();
const uint32 frameCount = config.bufferSize;
RenderAudioBlock(frameCount, config.channels, config.sampleRate);
m_backend->ProcessAudio(
m_mixScratchBuffer.data(),
frameCount,
config.channels,
config.sampleRate);
} else {
UpdateStats();
}
m_stats.activeSources = activeCount;
m_stats.totalSources = static_cast<uint32>(m_activeSources.size());
}
void AudioSystem::SetBackend(std::unique_ptr<IAudioBackend> backend) {
m_backend = std::move(backend);
std::unique_ptr<IAudioBackend> previousBackend;
if (backend) {
backend->SetRenderCallback(
[this](float* buffer, uint32 frameCount, uint32 channels, uint32 sampleRate) {
RenderAudio(buffer, frameCount, channels, sampleRate);
});
}
{
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
previousBackend = std::move(m_backend);
m_backend = std::move(backend);
}
if (previousBackend) {
if (previousBackend->IsRunning()) {
previousBackend->Stop();
}
previousBackend->Shutdown();
}
}
std::string AudioSystem::GetCurrentDevice() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_backend) {
return m_backend->GetDeviceName();
}
@@ -173,50 +224,61 @@ std::string AudioSystem::GetCurrentDevice() const {
}
void AudioSystem::SetDevice(const std::string& deviceName) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_backend) {
m_backend->SetDevice(deviceName);
}
}
void AudioSystem::GetAvailableDevices(std::vector<std::string>& devices) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_backend) {
m_backend->GetAvailableDevices(devices);
}
}
float AudioSystem::GetMasterVolume() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_masterMixer.GetVolume();
}
void AudioSystem::SetMasterVolume(float volume) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_masterMixer.SetVolume(volume);
}
bool AudioSystem::IsMuted() const {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
return m_masterMixer.IsMute();
}
void AudioSystem::SetMuted(bool muted) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_masterMixer.SetMute(muted);
}
void AudioSystem::SetListenerReverbMixer(AudioMixer* mixer) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_listenerReverbMixer = mixer;
}
void AudioSystem::SetListenerReverbLevel(float level) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_listenerReverbLevel = std::clamp(level, 0.0f, 1.0f);
}
void AudioSystem::SetListenerDopplerLevel(float level) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_listenerDopplerLevel = std::clamp(level, 0.0f, 5.0f);
}
void AudioSystem::SetSpeedOfSound(float metersPerSecond) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_speedOfSound = std::max(1.0f, 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;
}
@@ -227,6 +289,7 @@ void AudioSystem::RenderAudio(float* buffer, uint32 frameCount, uint32 channels,
}
void AudioSystem::ProcessAudio(float* buffer, uint32 frameCount, uint32 channels) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (m_backend) {
const uint32 sampleRate =
m_backend->GetConfig().sampleRate != 0 ? m_backend->GetConfig().sampleRate : 48000;
@@ -235,15 +298,18 @@ void AudioSystem::ProcessAudio(float* buffer, uint32 frameCount, uint32 channels
}
void AudioSystem::SetListenerTransform(const Math::Vector3& position, const Math::Quaternion& rotation) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_listenerPosition = position;
m_listenerRotation = rotation;
}
void AudioSystem::SetListenerVelocity(const Math::Vector3& velocity) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
m_listenerVelocity = velocity;
}
void AudioSystem::RegisterSource(Components::AudioSourceComponent* source) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!source) {
return;
}
@@ -254,6 +320,7 @@ void AudioSystem::RegisterSource(Components::AudioSourceComponent* source) {
}
void AudioSystem::RegisterSourceComponent(Components::AudioSourceComponent* source) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!source) {
return;
}
@@ -265,6 +332,7 @@ void AudioSystem::RegisterSourceComponent(Components::AudioSourceComponent* sour
}
void AudioSystem::UnregisterSourceComponent(Components::AudioSourceComponent* source) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!source) {
return;
}
@@ -276,6 +344,7 @@ void AudioSystem::UnregisterSourceComponent(Components::AudioSourceComponent* so
}
void AudioSystem::RegisterListenerComponent(Components::AudioListenerComponent* listener) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!listener) {
return;
}
@@ -287,6 +356,7 @@ void AudioSystem::RegisterListenerComponent(Components::AudioListenerComponent*
}
void AudioSystem::UnregisterListenerComponent(Components::AudioListenerComponent* listener) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!listener) {
return;
}
@@ -297,6 +367,7 @@ void AudioSystem::UnregisterListenerComponent(Components::AudioListenerComponent
}
void AudioSystem::RegisterMixer(AudioMixer* mixer) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!mixer) {
return;
}
@@ -307,6 +378,7 @@ void AudioSystem::RegisterMixer(AudioMixer* mixer) {
}
void AudioSystem::UnregisterMixer(AudioMixer* mixer) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!mixer) {
return;
}
@@ -318,6 +390,7 @@ void AudioSystem::UnregisterMixer(AudioMixer* mixer) {
}
void AudioSystem::UnregisterSource(Components::AudioSourceComponent* source) {
std::lock_guard<std::recursive_mutex> lock(m_stateMutex);
if (!source) {
return;
}
@@ -377,8 +450,7 @@ void AudioSystem::RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sa
if (sampleCount == 0 || sampleRate == 0) {
m_mixScratchBuffer.clear();
m_sourceScratchBuffer.clear();
m_stats.activeSources = 0;
m_stats.totalSources = static_cast<uint32>(m_activeSources.size());
UpdateStats();
return;
}
@@ -481,6 +553,10 @@ void AudioSystem::RenderAudioBlock(uint32 frameCount, uint32 channels, uint32 sa
channels,
sampleRate);
UpdateStats();
}
void AudioSystem::UpdateStats() {
uint32 activeCount = 0;
for (auto* source : m_activeSources) {
if (source && source->IsPlaying()) {

View File

@@ -64,8 +64,7 @@ bool WaveOutBackend::Initialize(const AudioConfig& config) {
const size_t bufferSampleCount = static_cast<size_t>(config.bufferSize) * config.channels;
m_audioBuffer1.assign(bufferSampleCount, 0);
m_audioBuffer2.assign(bufferSampleCount, 0);
m_pendingMixBuffer.assign(bufferSampleCount, 0.0f);
m_hasPendingMix = false;
m_renderBuffer.assign(bufferSampleCount, 0.0f);
m_buffer1Available = true;
m_buffer2Available = true;
@@ -152,7 +151,7 @@ void WaveOutBackend::Start() {
void WaveOutBackend::Stop() {
m_isRunning = false;
m_dataReadyCond.notify_all();
m_bufferReadyCond.notify_all();
if (m_hWaveOut != nullptr) {
waveOutReset(m_hWaveOut);
@@ -180,20 +179,15 @@ void WaveOutBackend::Resume() {
void WaveOutBackend::ProcessAudio(float* buffer, uint32 frameCount,
uint32 channels, uint32 sampleRate) {
(void)buffer;
(void)frameCount;
(void)channels;
(void)sampleRate;
}
if (buffer == nullptr) {
return;
}
const uint32 sampleCount = frameCount * channels;
void WaveOutBackend::SetRenderCallback(RenderCallback callback) {
std::lock_guard<std::mutex> lock(m_bufferMutex);
m_pendingMixBuffer.assign(m_pendingMixBuffer.size(), 0.0f);
for (uint32 i = 0; i < sampleCount && i < m_pendingMixBuffer.size(); ++i) {
m_pendingMixBuffer[i] = buffer[i];
}
m_hasPendingMix = true;
m_dataReadyCond.notify_one();
m_renderCallback = std::move(callback);
}
MMRESULT WaveOutBackend::InitDevice() {
@@ -269,9 +263,8 @@ DWORD WINAPI WaveOutBackend::AudioThreadProc(LPVOID lpParameter) {
void WaveOutBackend::AudioThread() {
while (m_isRunning.load()) {
std::unique_lock<std::mutex> lock(m_bufferMutex);
m_dataReadyCond.wait(lock, [this] {
return !m_isRunning.load() ||
(m_hasPendingMix && (m_buffer1Available || m_buffer2Available));
m_bufferReadyCond.wait(lock, [this] {
return !m_isRunning.load() || m_buffer1Available || m_buffer2Available;
});
if (!m_isRunning.load()) {
@@ -293,10 +286,31 @@ void WaveOutBackend::AudioThread() {
continue;
}
FillPcm16Buffer(*targetBuffer, m_pendingMixBuffer);
m_hasPendingMix = false;
RenderCallback renderCallback;
const uint32 frameCount = m_config.bufferSize;
const uint32 channels = m_config.channels;
const uint32 sampleRate = m_config.sampleRate;
const size_t sampleCount = static_cast<size_t>(frameCount) * channels;
if (targetBuffer->size() != sampleCount) {
targetBuffer->assign(sampleCount, 0);
} else {
std::fill(targetBuffer->begin(), targetBuffer->end(), 0);
}
if (m_renderBuffer.size() != sampleCount) {
m_renderBuffer.assign(sampleCount, 0.0f);
} else {
std::fill(m_renderBuffer.begin(), m_renderBuffer.end(), 0.0f);
}
renderCallback = m_renderCallback;
lock.unlock();
if (renderCallback && !m_renderBuffer.empty()) {
renderCallback(m_renderBuffer.data(), frameCount, channels, sampleRate);
}
FillPcm16Buffer(*targetBuffer, m_renderBuffer);
if (SubmitBuffer(*targetHeader, *targetBuffer) != MMSYSERR_NOERROR) {
std::lock_guard<std::mutex> restoreLock(m_bufferMutex);
if (targetHeader == &m_waveHeader1) {
@@ -304,6 +318,7 @@ void WaveOutBackend::AudioThread() {
} else {
m_buffer2Available = true;
}
m_bufferReadyCond.notify_one();
}
}
}
@@ -322,7 +337,7 @@ void WaveOutBackend::OnAudioCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstan
} else if (completedHeader == &m_waveHeader2) {
m_buffer2Available = true;
}
m_dataReadyCond.notify_one();
m_bufferReadyCond.notify_one();
}
}

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;
}