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

View file

@ -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)

View file

@ -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::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 Play() = 0;
virtual bool Stop() = 0;
void SetAudioDelayOverride(uint32 delay);
uint32 GetAudioDelay() const;
static void PrintLogging();
static void InitializeStatic();
@ -77,9 +79,10 @@ protected:
bool m_playing = false;
static std::array<bool, AudioAPIEnd> 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);
};

View file

@ -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 <EFBFBD> wBitsPerSample) / 8
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.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();
}

View file

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

View file

@ -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();
}

View file

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