mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-08 07:51:19 +12:00
Fix no audio on zero latency bug. make Xaudio consistent with other APIs
This commit is contained in:
parent
4468e7a7f2
commit
da9c3c84e8
9 changed files with 45 additions and 16 deletions
|
@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue