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