diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index 4ea6ebf80..d18e2d0d5 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -833,12 +833,15 @@ void LatteShaderCache_StreamBootSound() try { bootSndAudioDev = IAudioAPI::CreateDeviceFromConfig(true, 48000, 2, samplesPerBlock, 16); + if(!bootSndAudioDev) + return; } catch (const std::runtime_error& ex) { cemuLog_log(LogType::Force, "Failed to initialise audio device for bootup sound"); return; } + bootSndAudioDev->SetAudioDelayOverride(4); bootSndAudioDev->Play(); std::string sndPath = fmt::format("{}/meta/{}", CafeSystem::GetMlcStoragePath(CafeSystem::GetForegroundTitleId()), "bootSound.btsnd"); @@ -853,10 +856,10 @@ void LatteShaderCache_StreamBootSound() { while(audiothread_keeprunning) { - if (bootSndAudioDev->NeedAdditionalBlocks()) + while (bootSndAudioDev->NeedAdditionalBlocks()) bootSndAudioDev->FeedBlock(bootSndFileReader->getSamples()); - // sleep for half the duration of a single block - std::this_thread::sleep_for(std::chrono::milliseconds(samplesPerBlock / (48'000/ 1'000) / 2)); + // sleep for the duration of a single block + std::this_thread::sleep_for(std::chrono::milliseconds(samplesPerBlock / (48'000/ 1'000))); } } diff --git a/src/audio/CubebAPI.cpp b/src/audio/CubebAPI.cpp index 09e450113..3a87cd8de 100644 --- a/src/audio/CubebAPI.cpp +++ b/src/audio/CubebAPI.cpp @@ -114,7 +114,7 @@ CubebAPI::~CubebAPI() bool CubebAPI::NeedAdditionalBlocks() const { std::shared_lock lock(m_mutex); - return m_buffer.size() < s_audioDelay * m_bytesPerBlock; + return m_buffer.size() < GetAudioDelay() * m_bytesPerBlock; } bool CubebAPI::FeedBlock(sint16* data) diff --git a/src/audio/DirectSoundAPI.cpp b/src/audio/DirectSoundAPI.cpp index 8c2f7245b..eabd3a7ed 100644 --- a/src/audio/DirectSoundAPI.cpp +++ b/src/audio/DirectSoundAPI.cpp @@ -210,7 +210,7 @@ void DirectSoundAPI::SetVolume(sint32 volume) bool DirectSoundAPI::NeedAdditionalBlocks() const { std::shared_lock lock(m_mutex); - return m_buffer.size() < s_audioDelay; + return m_buffer.size() < GetAudioDelay(); } std::vector DirectSoundAPI::GetDevices() diff --git a/src/audio/IAudioAPI.cpp b/src/audio/IAudioAPI.cpp index d30d9f569..587526ab5 100644 --- a/src/audio/IAudioAPI.cpp +++ b/src/audio/IAudioAPI.cpp @@ -200,3 +200,12 @@ std::vector IAudioAPI::GetDevices(AudioAPI api) } } +void IAudioAPI::SetAudioDelayOverride(uint32 delay) +{ + m_audioDelayOverride = delay; +} + +uint32 IAudioAPI::GetAudioDelay() const +{ + return m_audioDelayOverride > 0 ? m_audioDelayOverride : s_audioDelay; +} diff --git a/src/audio/IAudioAPI.h b/src/audio/IAudioAPI.h index 5234b09bc..8fb510db9 100644 --- a/src/audio/IAudioAPI.h +++ b/src/audio/IAudioAPI.h @@ -55,6 +55,8 @@ class IAudioAPI virtual bool FeedBlock(sint16* data) = 0; virtual bool Play() = 0; virtual bool Stop() = 0; + void SetAudioDelayOverride(uint32 delay); + uint32 GetAudioDelay() const; static void PrintLogging(); static void InitializeStatic(); @@ -77,9 +79,10 @@ class IAudioAPI bool m_playing = false; static std::array s_availableApis; - static uint32 s_audioDelay; + uint32 m_audioDelayOverride = 0; private: + static uint32 s_audioDelay; void InitWFX(sint32 samplerate, sint32 channels, sint32 bits_per_sample); }; diff --git a/src/audio/XAudio27API.cpp b/src/audio/XAudio27API.cpp index 9901b29b0..401b78230 100644 --- a/src/audio/XAudio27API.cpp +++ b/src/audio/XAudio27API.cpp @@ -33,8 +33,8 @@ XAudio27API::XAudio27API(uint32 device_id, uint32 samplerate, uint32 channels, u m_wfx.Format.nChannels = channels; m_wfx.Format.nSamplesPerSec = samplerate; m_wfx.Format.wBitsPerSample = bits_per_sample; - m_wfx.Format.nBlockAlign = (m_wfx.Format.nChannels * m_wfx.Format.wBitsPerSample) / 8; // must equal (nChannels × wBitsPerSample) / 8 - m_wfx.Format.nAvgBytesPerSec = m_wfx.Format.nSamplesPerSec * m_wfx.Format.nBlockAlign; // must equal nSamplesPerSec × nBlockAlign. + m_wfx.Format.nBlockAlign = (m_wfx.Format.nChannels * m_wfx.Format.wBitsPerSample) / 8; // must equal (nChannels � wBitsPerSample) / 8 + m_wfx.Format.nAvgBytesPerSec = m_wfx.Format.nSamplesPerSec * m_wfx.Format.nBlockAlign; // must equal nSamplesPerSec � nBlockAlign. m_wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); m_wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; @@ -199,9 +199,7 @@ bool XAudio27API::FeedBlock(sint16* data) // check if we queued too many blocks if(m_blocks_queued >= kBlockCount) { - XAUDIO2_VOICE_STATE state{}; - m_source_voice->GetState(&state); - m_blocks_queued = state.BuffersQueued; + m_blocks_queued = GetQueuedBuffers(); if (m_blocks_queued >= kBlockCount) { @@ -222,7 +220,14 @@ bool XAudio27API::FeedBlock(sint16* data) return true; } +uint32 XAudio27API::GetQueuedBuffers() const +{ + XAUDIO2_VOICE_STATE state{}; + m_source_voice->GetState(&state); + return state.BuffersQueued; +} + bool XAudio27API::NeedAdditionalBlocks() const { - return m_blocks_queued < s_audioDelay; + return GetQueuedBuffers() < GetAudioDelay(); } diff --git a/src/audio/XAudio27API.h b/src/audio/XAudio27API.h index badab8f67..4288dcc7f 100644 --- a/src/audio/XAudio27API.h +++ b/src/audio/XAudio27API.h @@ -47,6 +47,8 @@ class XAudio27API : public IAudioAPI static std::vector GetDevices(); private: + uint32 GetQueuedBuffers() const; + struct XAudioDeleter { void operator()(IXAudio2* ptr) const; diff --git a/src/audio/XAudio2API.cpp b/src/audio/XAudio2API.cpp index 512bcccdf..c92fd4519 100644 --- a/src/audio/XAudio2API.cpp +++ b/src/audio/XAudio2API.cpp @@ -270,9 +270,7 @@ bool XAudio2API::FeedBlock(sint16* data) // check if we queued too many blocks if (m_blocks_queued >= kBlockCount) { - XAUDIO2_VOICE_STATE state{}; - m_source_voice->GetState(&state); - m_blocks_queued = state.BuffersQueued; + m_blocks_queued = GetQueuedBuffers(); if (m_blocks_queued >= kBlockCount) { @@ -293,7 +291,14 @@ bool XAudio2API::FeedBlock(sint16* data) return true; } +uint32 XAudio2API::GetQueuedBuffers() const +{ + XAUDIO2_VOICE_STATE state{}; + m_source_voice->GetState(&state); + return state.BuffersQueued; +} + bool XAudio2API::NeedAdditionalBlocks() const { - return m_blocks_queued < s_audioDelay; + return GetQueuedBuffers() < GetAudioDelay(); } diff --git a/src/audio/XAudio2API.h b/src/audio/XAudio2API.h index 1f7057f0a..b5bb02964 100644 --- a/src/audio/XAudio2API.h +++ b/src/audio/XAudio2API.h @@ -46,6 +46,8 @@ class XAudio2API : public IAudioAPI static const std::vector& GetDevices() { return s_devices; } private: + uint32 GetQueuedBuffers() const; + static const std::vector& RefreshDevices(); struct XAudioDeleter