CDROM: Fix upper bound for XA audio frames and sync SPU

This commit is contained in:
Connor McLaughlin 2020-03-07 17:29:38 +10:00
parent 6fa8031569
commit 34ae0dae13
2 changed files with 18 additions and 20 deletions

View File

@ -1475,16 +1475,18 @@ static constexpr s16 SaturateVolume(s32 volume)
}
template<bool STEREO, bool SAMPLE_RATE>
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<std::array<u8, 2>, 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<true, true>(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<false, true>(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);

View File

@ -1128,19 +1128,15 @@ std::tuple<s32, s32> 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()