CDROM: Move audio FIFO to CDROM class and skip sectors when unempty

Fixes cutscene audio in Nickelodeon Rugrats - Search for Reptar.
This commit is contained in:
Connor McLaughlin
2020-07-22 00:03:44 +10:00
parent f9bbbbbaec
commit f28ef01d24
6 changed files with 90 additions and 105 deletions

View File

@ -345,7 +345,7 @@ void CDROM::SoftReset()
m_next_cd_audio_volume_matrix[1][0] = 0x00;
m_next_cd_audio_volume_matrix[1][1] = 0x80;
m_cd_audio_volume_matrix = m_next_cd_audio_volume_matrix;
ResetXAResampler();
ResetAudioDecoder();
m_param_fifo.Clear();
m_response_fifo.Clear();
@ -414,6 +414,8 @@ bool CDROM::DoState(StateWrapper& sw)
sw.Do(&m_sector_buffers[i].size);
}
sw.Do(&m_audio_fifo);
u32 requested_sector = (sw.IsWriting() ? (m_reader.WaitForReadToComplete(), m_reader.GetLastReadSector()) : 0);
sw.Do(&requested_sector);
@ -1551,7 +1553,7 @@ void CDROM::BeginReading(TickCount ticks_late /* = 0 */, bool after_seek /* = fa
m_current_read_sector_buffer = 0;
m_current_write_sector_buffer = 0;
ResetCurrentXAFile();
ResetXAResampler();
ResetAudioDecoder();
m_reader.QueueReadSector(m_current_lba);
}
@ -1593,6 +1595,8 @@ void CDROM::BeginPlaying(u8 track_bcd, TickCount ticks_late /* = 0 */, bool afte
m_drive_event->Schedule(first_sector_ticks);
m_current_read_sector_buffer = 0;
m_current_write_sector_buffer = 0;
ResetAudioDecoder();
ResetCurrentXAFile();
m_reader.QueueReadSector(m_current_lba);
}
@ -2079,14 +2083,21 @@ static constexpr s16 SaturateVolume(s32 volume)
}
template<bool STEREO, bool SAMPLE_RATE>
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)
void CDROM::ResampleXAADPCM(const s16* frames_in, u32 num_frames_in)
{
u8 p = *p_ptr;
u8 sixstep = *sixstep_ptr;
spu->EnsureCDAudioSpace(((num_frames_in * 7) / 6) << BoolToUInt8(SAMPLE_RATE));
// Since the disc reads and SPU are running at different speeds, we might be _slightly_ behind, which is fine, since
// the SPU will over-read in the next batch to catch up.
if (m_audio_fifo.GetSize() > AUDIO_FIFO_LOW_WATERMARK)
{
Log_DevPrintf("Dropping %u XA frames because audio FIFO still has %u frames", num_frames_in,
m_audio_fifo.GetSize());
return;
}
s16* left_ringbuf = m_xa_resample_ring_buffer[0].data();
s16* right_ringbuf = m_xa_resample_ring_buffer[1].data();
u8 p = m_xa_resample_p;
u8 sixstep = m_xa_resample_sixstep;
for (u32 in_sample_index = 0; in_sample_index < num_frames_in; in_sample_index++)
{
const s16 left = *(frames_in++);
@ -2113,19 +2124,18 @@ static void ResampleXAADPCM(const s16* frames_in, u32 num_frames_in, SPU* spu, s
const s16 left_interp = ZigZagInterpolate(left_ringbuf, s_zigzag_table[j].data(), p);
const s16 right_interp = STEREO ? ZigZagInterpolate(right_ringbuf, s_zigzag_table[j].data(), p) : left_interp;
const s16 left_out = SaturateVolume(ApplyVolume(left_interp, volume_matrix[0][0]) +
ApplyVolume(right_interp, volume_matrix[1][0]));
const s16 right_out = SaturateVolume(ApplyVolume(left_interp, volume_matrix[0][1]) +
ApplyVolume(right_interp, volume_matrix[1][1]));
spu->AddCDAudioSample(left_out, right_out);
const s16 left_out = SaturateVolume(ApplyVolume(left_interp, m_cd_audio_volume_matrix[0][0]) +
ApplyVolume(right_interp, m_cd_audio_volume_matrix[1][0]));
const s16 right_out = SaturateVolume(ApplyVolume(left_interp, m_cd_audio_volume_matrix[0][1]) +
ApplyVolume(right_interp, m_cd_audio_volume_matrix[1][1]));
AddCDAudioFrame(left_out, right_out);
}
}
}
}
*p_ptr = p;
*sixstep_ptr = sixstep;
m_xa_resample_p = p;
m_xa_resample_sixstep = sixstep;
}
void CDROM::ResetCurrentXAFile()
@ -2135,7 +2145,7 @@ void CDROM::ResetCurrentXAFile()
m_xa_current_set = false;
}
void CDROM::ResetXAResampler()
void CDROM::ResetAudioDecoder()
{
m_xa_last_samples.fill(0);
for (u32 i = 0; i < 2; i++)
@ -2144,6 +2154,7 @@ void CDROM::ResetXAResampler()
m_xa_resample_p = 0;
m_xa_resample_sixstep = 6;
}
m_audio_fifo.Clear();
}
void CDROM::ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannelQ& subq)
@ -2176,7 +2187,7 @@ void CDROM::ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannel
m_xa_current_file_number = m_last_sector_subheader.file_number;
m_xa_current_channel_number = m_last_sector_subheader.channel_number;
m_xa_current_set = true;
ResetXAResampler();
ResetAudioDecoder();
}
else if (m_last_sector_subheader.file_number != m_xa_current_file_number ||
m_last_sector_subheader.channel_number != m_xa_current_channel_number)
@ -2204,33 +2215,17 @@ void CDROM::ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannel
{
const u32 num_samples = m_last_sector_subheader.codinginfo.GetSamplesPerSector() / 2;
if (m_last_sector_subheader.codinginfo.IsHalfSampleRate())
{
ResampleXAADPCM<true, true>(sample_buffer.data(), num_samples, m_spu, m_xa_resample_ring_buffer[0].data(),
m_xa_resample_ring_buffer[1].data(), &m_xa_resample_p, &m_xa_resample_sixstep,
m_cd_audio_volume_matrix);
}
ResampleXAADPCM<true, true>(sample_buffer.data(), num_samples);
else
{
ResampleXAADPCM<true, false>(sample_buffer.data(), num_samples, m_spu, m_xa_resample_ring_buffer[0].data(),
m_xa_resample_ring_buffer[1].data(), &m_xa_resample_p, &m_xa_resample_sixstep,
m_cd_audio_volume_matrix);
}
ResampleXAADPCM<true, false>(sample_buffer.data(), num_samples);
}
else
{
const u32 num_samples = m_last_sector_subheader.codinginfo.GetSamplesPerSector();
if (m_last_sector_subheader.codinginfo.IsHalfSampleRate())
{
ResampleXAADPCM<false, true>(sample_buffer.data(), num_samples, m_spu, m_xa_resample_ring_buffer[0].data(),
m_xa_resample_ring_buffer[1].data(), &m_xa_resample_p, &m_xa_resample_sixstep,
m_cd_audio_volume_matrix);
}
ResampleXAADPCM<false, true>(sample_buffer.data(), num_samples);
else
{
ResampleXAADPCM<false, false>(sample_buffer.data(), num_samples, m_spu, m_xa_resample_ring_buffer[0].data(),
m_xa_resample_ring_buffer[1].data(), &m_xa_resample_p, &m_xa_resample_sixstep,
m_cd_audio_volume_matrix);
}
ResampleXAADPCM<false, false>(sample_buffer.data(), num_samples);
}
}
@ -2282,7 +2277,12 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ&
constexpr bool is_stereo = true;
constexpr u32 num_samples = CDImage::RAW_SECTOR_SIZE / sizeof(s16) / (is_stereo ? 2 : 1);
m_spu->EnsureCDAudioSpace(num_samples);
const u32 remaining_space = m_audio_fifo.GetSpace();
if (remaining_space < num_samples)
{
Log_WarningPrintf("Dropping %u frames from audio FIFO", num_samples - remaining_space);
m_audio_fifo.Remove(num_samples - remaining_space);
}
const u8* sector_ptr = raw_sector;
for (u32 i = 0; i < num_samples; i++)
@ -2296,7 +2296,7 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ&
ApplyVolume(samp_right, m_cd_audio_volume_matrix[1][0]));
const s16 right = SaturateVolume(ApplyVolume(samp_left, m_cd_audio_volume_matrix[0][1]) +
ApplyVolume(samp_right, m_cd_audio_volume_matrix[1][1]));
m_spu->AddCDAudioSample(left, right);
AddCDAudioFrame(left, right);
}
}