Zelda HLE: Fix and genericize PCM ARAM loading functions.

Now also handles PCM16, and works for longer sounds. SMG1 main menu outputs
some sensible audio now, though volume seems slightly off.
This commit is contained in:
Pierre Bourdon 2014-12-22 01:25:14 +01:00
parent 0dc5a925b0
commit 8b9b9f033a
2 changed files with 31 additions and 18 deletions

View File

@ -503,7 +503,6 @@ struct ZeldaAudioRenderer::VPB
// Simple saw wave at 100% amplitude and frequency controlled via the
// resampling ratio.
SRC_SAW_WAVE = 1,
// Breaking the numerical ordering for these, but they are all related.
// Simple pattern stored in the data downloaded by command 01. Playback
// frequency is controlled by the resampling ratio.
@ -511,13 +510,15 @@ struct ZeldaAudioRenderer::VPB
SRC_CONST_PATTERN_1 = 4,
SRC_CONST_PATTERN_2 = 11,
SRC_CONST_PATTERN_3 = 12,
// Samples stored in ARAM in PCM8 format, at an arbitrary sampling rate
// (resampling is applied).
SRC_PCM8_FROM_ARAM = 8,
// Samples stored in ARAM at a rate of 16 samples/9 bytes, AFC encoded,
// at an arbitrary sample rate (resampling is applied).
SRC_AFC_HQ_FROM_ARAM = 9,
// Samples stored in ARAM in PCM16 format, at an arbitrary sampling
// rate (resampling is applied).
SRC_PCM16_FROM_ARAM = 16,
// Samples stored in MRAM at an arbitrary sample rate (resampling is
// applied, unlike PCM16_FROM_MRAM_RAW).
SRC_PCM16_FROM_MRAM = 33,
@ -622,6 +623,8 @@ void ZeldaAudioRenderer::PrepareFrame()
m_buf_back_left_reverb.fill(0);
m_buf_back_right_reverb.fill(0);
// TODO: Prepare patterns 2/3 - they are not constant unlike 0/1.
m_prepared = true;
}
@ -1000,8 +1003,8 @@ void ZeldaAudioRenderer::LoadInputSamples(MixingBuffer* buffer, VPB* vpb)
}
case VPB::SRC_PCM8_FROM_ARAM:
DownloadPCM8SamplesFromARAM(raw_input_samples.data() + 4, vpb,
NeededRawSamplesCount(*vpb));
DownloadPCMSamplesFromARAM<s8>(raw_input_samples.data() + 4, vpb,
NeededRawSamplesCount(*vpb));
Resample(vpb, raw_input_samples.data(), buffer);
break;
@ -1011,6 +1014,12 @@ void ZeldaAudioRenderer::LoadInputSamples(MixingBuffer* buffer, VPB* vpb)
Resample(vpb, raw_input_samples.data(), buffer);
break;
case VPB::SRC_PCM16_FROM_ARAM:
DownloadPCMSamplesFromARAM<s16>(raw_input_samples.data() + 4, vpb,
NeededRawSamplesCount(*vpb));
Resample(vpb, raw_input_samples.data(), buffer);
break;
case VPB::SRC_PCM16_FROM_MRAM:
DownloadRawSamplesFromMRAM(raw_input_samples.data() + 4, vpb,
NeededRawSamplesCount(*vpb));
@ -1083,8 +1092,8 @@ void* ZeldaAudioRenderer::GetARAMPtr() const
return DSP::GetARAMPtr();
}
void ZeldaAudioRenderer::DownloadPCM8SamplesFromARAM(
s16* dst, VPB* vpb, u16 requested_samples_count)
template <typename T>
void ZeldaAudioRenderer::DownloadPCMSamplesFromARAM(s16* dst, VPB* vpb, u16 requested_samples_count)
{
if (vpb->done)
{
@ -1093,10 +1102,15 @@ void ZeldaAudioRenderer::DownloadPCM8SamplesFromARAM(
return;
}
if (!vpb->reset_vpb)
if (vpb->reset_vpb)
{
vpb->end_reached = false;
vpb->SetRemainingLength(
vpb->GetLoopStartPosition() - vpb->GetCurrentPosition());
vpb->SetCurrentARAMAddr(
vpb->GetBaseAddress() + vpb->GetCurrentPosition() * sizeof (T));
}
vpb->end_reached = false;
while (requested_samples_count)
{
if (vpb->end_reached)
@ -1110,22 +1124,21 @@ void ZeldaAudioRenderer::DownloadPCM8SamplesFromARAM(
break;
}
vpb->SetCurrentPosition(vpb->GetLoopAddress());
vpb->SetRemainingLength(
vpb->GetLoopStartPosition() - vpb->GetCurrentPosition());
vpb->SetCurrentARAMAddr(
vpb->GetBaseAddress() + vpb->GetCurrentPosition() * sizeof (T));
}
vpb->SetRemainingLength(
vpb->GetLoopStartPosition() - vpb->GetCurrentPosition());
vpb->SetCurrentARAMAddr(
vpb->GetBaseAddress() + vpb->GetCurrentPosition());
s8* src_ptr = (s8*)GetARAMPtr() + vpb->GetCurrentARAMAddr();
T* src_ptr = (T*)((u8*)GetARAMPtr() + vpb->GetCurrentARAMAddr());
u16 samples_to_download = std::min(vpb->GetRemainingLength(),
(u32)requested_samples_count);
for (u16 i = 0; i < samples_to_download; ++i)
*dst++ = *src_ptr++ << 8;
*dst++ = Common::FromBigEndian<T>(*src_ptr++) << (16 - 8 * sizeof (T));
vpb->SetRemainingLength(vpb->GetRemainingLength() - samples_to_download);
vpb->SetCurrentARAMAddr(vpb->GetCurrentARAMAddr() + samples_to_download);
vpb->SetCurrentARAMAddr(vpb->GetCurrentARAMAddr() + samples_to_download * sizeof (T));
requested_samples_count -= samples_to_download;
if (!vpb->GetRemainingLength())
vpb->end_reached = true;

View File

@ -151,9 +151,9 @@ private:
u32 m_aram_base_addr = 0;
void* GetARAMPtr() const;
// Downloads PCM8 encoded samples from ARAM. Handles looping and other
// Downloads PCM encoded samples from ARAM. Handles looping and other
// parameters appropriately.
void DownloadPCM8SamplesFromARAM(s16* dst, VPB* vpb, u16 requested_samples_count);
template <typename T> void DownloadPCMSamplesFromARAM(s16* dst, VPB* vpb, u16 requested_samples_count);
// Downloads AFC encoded samples from ARAM and decode them. Handles looping
// and other parameters appropriately.