From 34ae0dae13e56db9306b6dbb2762d71b2cadfb1d Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 7 Mar 2020 17:29:38 +1000 Subject: [PATCH] CDROM: Fix upper bound for XA audio frames and sync SPU --- src/core/cdrom.cpp | 18 ++++++++++-------- src/core/spu.cpp | 20 ++++++++------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index dccf73cae..88efb0c07 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -1475,16 +1475,18 @@ static constexpr s16 SaturateVolume(s32 volume) } template -static void ResampleXAADPCM(const s16* samples_in, u32 num_samples_in, SPU* spu, s16* left_ringbuf, s16* right_ringbuf, +static void ResampleXAADPCM(const s16* frames_in, u32 num_frames_in, SPU* spu, s16* left_ringbuf, s16* right_ringbuf, u8* p_ptr, u8* sixstep_ptr, const std::array, 2>& volume_matrix) { u8 p = *p_ptr; u8 sixstep = *sixstep_ptr; - for (u32 in_sample_index = 0; in_sample_index < num_samples_in; in_sample_index++) + spu->EnsureCDAudioSpace(((num_frames_in * 7) / 6) << BoolToUInt8(SAMPLE_RATE)); + + for (u32 in_sample_index = 0; in_sample_index < num_frames_in; in_sample_index++) { - const s16 left = *(samples_in++); - const s16 right = STEREO ? *(samples_in++) : left; + const s16 left = *(frames_in++); + const s16 right = STEREO ? *(frames_in++) : left; if constexpr (!STEREO) { @@ -1531,11 +1533,11 @@ void CDROM::ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannel if (m_muted || m_adpcm_muted) return; + m_spu->GeneratePendingSamples(); + if (m_last_sector_subheader.codinginfo.IsStereo()) { const u32 num_samples = m_last_sector_subheader.codinginfo.GetSamplesPerSector() / 2; - m_spu->EnsureCDAudioSpace(num_samples); - if (m_last_sector_subheader.codinginfo.IsHalfSampleRate()) { ResampleXAADPCM(sample_buffer.data(), num_samples, m_spu, m_xa_resample_ring_buffer[0].data(), @@ -1552,8 +1554,6 @@ void CDROM::ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannel else { const u32 num_samples = m_last_sector_subheader.codinginfo.GetSamplesPerSector(); - m_spu->EnsureCDAudioSpace(num_samples); - if (m_last_sector_subheader.codinginfo.IsHalfSampleRate()) { ResampleXAADPCM(sample_buffer.data(), num_samples, m_spu, m_xa_resample_ring_buffer[0].data(), @@ -1612,6 +1612,8 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ& if (m_muted) return; + m_spu->GeneratePendingSamples(); + constexpr bool is_stereo = true; constexpr u32 num_samples = RAW_SECTOR_OUTPUT_SIZE / sizeof(s16) / (is_stereo ? 2 : 1); m_spu->EnsureCDAudioSpace(num_samples); diff --git a/src/core/spu.cpp b/src/core/spu.cpp index 337679a5a..1ba2addfe 100644 --- a/src/core/spu.cpp +++ b/src/core/spu.cpp @@ -1128,19 +1128,15 @@ std::tuple SPU::SampleVoice(u32 voice_index) void SPU::EnsureCDAudioSpace(u32 remaining_frames) { - if (m_cd_audio_buffer.IsEmpty()) - { - // we want the audio to start playing at the right point, not a few cycles early, otherwise this'll cause sync - // issues. - m_sample_event->InvokeEarly(); - } + if (m_cd_audio_buffer.GetSpace() >= (remaining_frames * 2)) + return; - if (m_cd_audio_buffer.GetSpace() < (remaining_frames * 2)) - { - Log_WarningPrintf("SPU CD Audio buffer overflow - writing %u samples with %u samples space", remaining_frames, - m_cd_audio_buffer.GetSpace() / 2); - m_cd_audio_buffer.Remove((remaining_frames * 2) - m_cd_audio_buffer.GetSpace()); - } + const u32 frames_to_drop = (remaining_frames * 2) - m_cd_audio_buffer.GetSpace(); + Log_WarningPrintf( + "SPU CD Audio buffer overflow with %d pending ticks - writing %u frames with %u frames space. Dropping %u frames.", + m_sample_event->IsActive() ? (m_sample_event->GetTicksSinceLastExecution() / SYSCLK_TICKS_PER_SPU_TICK) : 0, + remaining_frames, m_cd_audio_buffer.GetSpace() / 2, frames_to_drop); + m_cd_audio_buffer.Remove(frames_to_drop); } void SPU::DrawDebugStateWindow()