Fix no audio on zero latency bug. make Xaudio consistent with other APIs

This commit is contained in:
goeiecool9999 2023-12-23 23:13:01 +01:00
parent 4468e7a7f2
commit da9c3c84e8
9 changed files with 45 additions and 16 deletions

View file

@ -833,12 +833,15 @@ void LatteShaderCache_StreamBootSound()
try try
{ {
bootSndAudioDev = IAudioAPI::CreateDeviceFromConfig(true, 48000, 2, samplesPerBlock, 16); bootSndAudioDev = IAudioAPI::CreateDeviceFromConfig(true, 48000, 2, samplesPerBlock, 16);
if(!bootSndAudioDev)
return;
} }
catch (const std::runtime_error& ex) catch (const std::runtime_error& ex)
{ {
cemuLog_log(LogType::Force, "Failed to initialise audio device for bootup sound"); cemuLog_log(LogType::Force, "Failed to initialise audio device for bootup sound");
return; return;
} }
bootSndAudioDev->SetAudioDelayOverride(4);
bootSndAudioDev->Play(); bootSndAudioDev->Play();
std::string sndPath = fmt::format("{}/meta/{}", CafeSystem::GetMlcStoragePath(CafeSystem::GetForegroundTitleId()), "bootSound.btsnd"); std::string sndPath = fmt::format("{}/meta/{}", CafeSystem::GetMlcStoragePath(CafeSystem::GetForegroundTitleId()), "bootSound.btsnd");
@ -853,10 +856,10 @@ void LatteShaderCache_StreamBootSound()
{ {
while(audiothread_keeprunning) while(audiothread_keeprunning)
{ {
if (bootSndAudioDev->NeedAdditionalBlocks()) while (bootSndAudioDev->NeedAdditionalBlocks())
bootSndAudioDev->FeedBlock(bootSndFileReader->getSamples()); bootSndAudioDev->FeedBlock(bootSndFileReader->getSamples());
// sleep for half the duration of a single block // sleep for the duration of a single block
std::this_thread::sleep_for(std::chrono::milliseconds(samplesPerBlock / (48'000/ 1'000) / 2)); std::this_thread::sleep_for(std::chrono::milliseconds(samplesPerBlock / (48'000/ 1'000)));
} }
} }

View file

@ -114,7 +114,7 @@ CubebAPI::~CubebAPI()
bool CubebAPI::NeedAdditionalBlocks() const bool CubebAPI::NeedAdditionalBlocks() const
{ {
std::shared_lock lock(m_mutex); 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) bool CubebAPI::FeedBlock(sint16* data)

View file

@ -210,7 +210,7 @@ void DirectSoundAPI::SetVolume(sint32 volume)
bool DirectSoundAPI::NeedAdditionalBlocks() const bool DirectSoundAPI::NeedAdditionalBlocks() const
{ {
std::shared_lock lock(m_mutex); std::shared_lock lock(m_mutex);
return m_buffer.size() < s_audioDelay; return m_buffer.size() < GetAudioDelay();
} }
std::vector<DirectSoundAPI::DeviceDescriptionPtr> DirectSoundAPI::GetDevices() std::vector<DirectSoundAPI::DeviceDescriptionPtr> DirectSoundAPI::GetDevices()

View file

@ -200,3 +200,12 @@ std::vector<IAudioAPI::DeviceDescriptionPtr> IAudioAPI::GetDevices(AudioAPI api)
} }
} }
void IAudioAPI::SetAudioDelayOverride(uint32 delay)
{
m_audioDelayOverride = delay;
}
uint32 IAudioAPI::GetAudioDelay() const
{
return m_audioDelayOverride > 0 ? m_audioDelayOverride : s_audioDelay;
}

View file

@ -55,6 +55,8 @@ public:
virtual bool FeedBlock(sint16* data) = 0; virtual bool FeedBlock(sint16* data) = 0;
virtual bool Play() = 0; virtual bool Play() = 0;
virtual bool Stop() = 0; virtual bool Stop() = 0;
void SetAudioDelayOverride(uint32 delay);
uint32 GetAudioDelay() const;
static void PrintLogging(); static void PrintLogging();
static void InitializeStatic(); static void InitializeStatic();
@ -77,9 +79,10 @@ protected:
bool m_playing = false; bool m_playing = false;
static std::array<bool, AudioAPIEnd> s_availableApis; static std::array<bool, AudioAPIEnd> s_availableApis;
static uint32 s_audioDelay; uint32 m_audioDelayOverride = 0;
private: private:
static uint32 s_audioDelay;
void InitWFX(sint32 samplerate, sint32 channels, sint32 bits_per_sample); void InitWFX(sint32 samplerate, sint32 channels, sint32 bits_per_sample);
}; };

View file

@ -33,8 +33,8 @@ XAudio27API::XAudio27API(uint32 device_id, uint32 samplerate, uint32 channels, u
m_wfx.Format.nChannels = channels; m_wfx.Format.nChannels = channels;
m_wfx.Format.nSamplesPerSec = samplerate; m_wfx.Format.nSamplesPerSec = samplerate;
m_wfx.Format.wBitsPerSample = bits_per_sample; 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.nBlockAlign = (m_wfx.Format.nChannels * m_wfx.Format.wBitsPerSample) / 8; // must equal (nChannels <EFBFBD> wBitsPerSample) / 8
m_wfx.Format.nAvgBytesPerSec = m_wfx.Format.nSamplesPerSec * m_wfx.Format.nBlockAlign; // must equal nSamplesPerSec × nBlockAlign. m_wfx.Format.nAvgBytesPerSec = m_wfx.Format.nSamplesPerSec * m_wfx.Format.nBlockAlign; // must equal nSamplesPerSec <EFBFBD> nBlockAlign.
m_wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); m_wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
m_wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; m_wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
@ -199,9 +199,7 @@ bool XAudio27API::FeedBlock(sint16* data)
// check if we queued too many blocks // check if we queued too many blocks
if(m_blocks_queued >= kBlockCount) if(m_blocks_queued >= kBlockCount)
{ {
XAUDIO2_VOICE_STATE state{}; m_blocks_queued = GetQueuedBuffers();
m_source_voice->GetState(&state);
m_blocks_queued = state.BuffersQueued;
if (m_blocks_queued >= kBlockCount) if (m_blocks_queued >= kBlockCount)
{ {
@ -222,7 +220,14 @@ bool XAudio27API::FeedBlock(sint16* data)
return true; return true;
} }
uint32 XAudio27API::GetQueuedBuffers() const
{
XAUDIO2_VOICE_STATE state{};
m_source_voice->GetState(&state);
return state.BuffersQueued;
}
bool XAudio27API::NeedAdditionalBlocks() const bool XAudio27API::NeedAdditionalBlocks() const
{ {
return m_blocks_queued < s_audioDelay; return GetQueuedBuffers() < GetAudioDelay();
} }

View file

@ -47,6 +47,8 @@ public:
static std::vector<DeviceDescriptionPtr> GetDevices(); static std::vector<DeviceDescriptionPtr> GetDevices();
private: private:
uint32 GetQueuedBuffers() const;
struct XAudioDeleter struct XAudioDeleter
{ {
void operator()(IXAudio2* ptr) const; void operator()(IXAudio2* ptr) const;

View file

@ -270,9 +270,7 @@ bool XAudio2API::FeedBlock(sint16* data)
// check if we queued too many blocks // check if we queued too many blocks
if (m_blocks_queued >= kBlockCount) if (m_blocks_queued >= kBlockCount)
{ {
XAUDIO2_VOICE_STATE state{}; m_blocks_queued = GetQueuedBuffers();
m_source_voice->GetState(&state);
m_blocks_queued = state.BuffersQueued;
if (m_blocks_queued >= kBlockCount) if (m_blocks_queued >= kBlockCount)
{ {
@ -293,7 +291,14 @@ bool XAudio2API::FeedBlock(sint16* data)
return true; return true;
} }
uint32 XAudio2API::GetQueuedBuffers() const
{
XAUDIO2_VOICE_STATE state{};
m_source_voice->GetState(&state);
return state.BuffersQueued;
}
bool XAudio2API::NeedAdditionalBlocks() const bool XAudio2API::NeedAdditionalBlocks() const
{ {
return m_blocks_queued < s_audioDelay; return GetQueuedBuffers() < GetAudioDelay();
} }

View file

@ -46,6 +46,8 @@ public:
static const std::vector<DeviceDescriptionPtr>& GetDevices() { return s_devices; } static const std::vector<DeviceDescriptionPtr>& GetDevices() { return s_devices; }
private: private:
uint32 GetQueuedBuffers() const;
static const std::vector<DeviceDescriptionPtr>& RefreshDevices(); static const std::vector<DeviceDescriptionPtr>& RefreshDevices();
struct XAudioDeleter struct XAudioDeleter