SPU: Add missing clamp in ADPCM decoder
This commit is contained in:
parent
b16ecd7a86
commit
be9033b6c0
|
@ -814,7 +814,7 @@ void GPU::WriteGP1(u32 value)
|
||||||
|
|
||||||
case 0x04: // DMA Direction
|
case 0x04: // DMA Direction
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("DMA direction <- 0x%02X", static_cast<u32>(m_GPUSTAT.dma_direction.GetValue()));
|
Log_DebugPrintf("DMA direction <- 0x%02X", static_cast<u32>(param));
|
||||||
if (m_GPUSTAT.dma_direction != static_cast<DMADirection>(param))
|
if (m_GPUSTAT.dma_direction != static_cast<DMADirection>(param))
|
||||||
{
|
{
|
||||||
m_GPUSTAT.dma_direction = static_cast<DMADirection>(param);
|
m_GPUSTAT.dma_direction = static_cast<DMADirection>(param);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||||
static constexpr u32 SAVE_STATE_VERSION = 27;
|
static constexpr u32 SAVE_STATE_VERSION = 28;
|
||||||
|
|
||||||
#pragma pack(push, 4)
|
#pragma pack(push, 4)
|
||||||
struct SAVE_STATE_HEADER
|
struct SAVE_STATE_HEADER
|
||||||
|
|
|
@ -1269,7 +1269,7 @@ void SPU::Voice::DecodeBlock(const ADPCMBlock& block)
|
||||||
const u8 filter_index = block.GetFilter();
|
const u8 filter_index = block.GetFilter();
|
||||||
const s32 filter_pos = filter_table_pos[filter_index];
|
const s32 filter_pos = filter_table_pos[filter_index];
|
||||||
const s32 filter_neg = filter_table_neg[filter_index];
|
const s32 filter_neg = filter_table_neg[filter_index];
|
||||||
s32 last_samples[2] = {adpcm_last_samples[0], adpcm_last_samples[1]};
|
s16 last_samples[2] = {adpcm_last_samples[0], adpcm_last_samples[1]};
|
||||||
|
|
||||||
// samples
|
// samples
|
||||||
for (u32 i = 0; i < NUM_SAMPLES_PER_ADPCM_BLOCK; i++)
|
for (u32 i = 0; i < NUM_SAMPLES_PER_ADPCM_BLOCK; i++)
|
||||||
|
@ -1279,9 +1279,8 @@ void SPU::Voice::DecodeBlock(const ADPCMBlock& block)
|
||||||
sample += (last_samples[0] * filter_pos) >> 6;
|
sample += (last_samples[0] * filter_pos) >> 6;
|
||||||
sample += (last_samples[1] * filter_neg) >> 6;
|
sample += (last_samples[1] * filter_neg) >> 6;
|
||||||
|
|
||||||
current_block_samples[i] = Clamp16(sample);
|
|
||||||
last_samples[1] = last_samples[0];
|
last_samples[1] = last_samples[0];
|
||||||
last_samples[0] = sample;
|
current_block_samples[i] = last_samples[0] = Clamp16(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::copy(last_samples, last_samples + countof(last_samples), adpcm_last_samples.begin());
|
std::copy(last_samples, last_samples + countof(last_samples), adpcm_last_samples.begin());
|
||||||
|
@ -1299,9 +1298,9 @@ s16 SPU::Voice::SampleBlock(s32 index) const
|
||||||
return current_block_samples[index];
|
return current_block_samples[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 SPU::Voice::Interpolate() const
|
s32 SPU::Voice::Interpolate() const
|
||||||
{
|
{
|
||||||
static constexpr std::array<s32, 0x200> gauss = {{
|
static constexpr std::array<s16, 0x200> gauss = {{
|
||||||
-0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, //
|
-0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, //
|
||||||
-0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, //
|
-0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, -0x001, //
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, //
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, //
|
||||||
|
@ -1371,11 +1370,11 @@ s16 SPU::Voice::Interpolate() const
|
||||||
const u8 i = counter.interpolation_index;
|
const u8 i = counter.interpolation_index;
|
||||||
const s32 s = static_cast<s32>(ZeroExtend32(counter.sample_index.GetValue()));
|
const s32 s = static_cast<s32>(ZeroExtend32(counter.sample_index.GetValue()));
|
||||||
|
|
||||||
s16 out = s16(gauss[0x0FF - i] * s32(SampleBlock(s - 3)) >> 15);
|
s32 out = s32(gauss[0x0FF - i]) * s32(SampleBlock(s - 3));
|
||||||
out += s16(gauss[0x1FF - i] * s32(SampleBlock(s - 2)) >> 15);
|
out += s32(gauss[0x1FF - i]) * s32(SampleBlock(s - 2));
|
||||||
out += s16(gauss[0x100 + i] * s32(SampleBlock(s - 1)) >> 15);
|
out += s32(gauss[0x100 + i]) * s32(SampleBlock(s - 1));
|
||||||
out += s16(gauss[0x000 + i] * s32(SampleBlock(s - 0)) >> 15);
|
out += s32(gauss[0x000 + i]) * s32(SampleBlock(s - 0));
|
||||||
return out;
|
return out >> 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPU::ReadADPCMBlock(u16 address, ADPCMBlock* block)
|
void SPU::ReadADPCMBlock(u16 address, ADPCMBlock* block)
|
||||||
|
@ -1430,7 +1429,7 @@ std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
|
||||||
if (voice.regs.adsr_volume != 0)
|
if (voice.regs.adsr_volume != 0)
|
||||||
{
|
{
|
||||||
// interpolate/sample and apply ADSR volume
|
// interpolate/sample and apply ADSR volume
|
||||||
s16 sample;
|
s32 sample;
|
||||||
if (IsVoiceNoiseEnabled(voice_index))
|
if (IsVoiceNoiseEnabled(voice_index))
|
||||||
sample = GetVoiceNoiseLevel();
|
sample = GetVoiceNoiseLevel();
|
||||||
else
|
else
|
||||||
|
@ -1456,7 +1455,7 @@ std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
|
||||||
const u16 old_step = step;
|
const u16 old_step = step;
|
||||||
step = Truncate16(static_cast<u32>((SignExtend32(step) * factor) >> 15));
|
step = Truncate16(static_cast<u32>((SignExtend32(step) * factor) >> 15));
|
||||||
}
|
}
|
||||||
step = std::min<u16>(step, 0x4000);
|
step = std::min<u16>(step, 0x3FFF);
|
||||||
|
|
||||||
// Shouldn't ever overflow because if sample_index == 27, step == 0x4000 there won't be a carry out from the
|
// Shouldn't ever overflow because if sample_index == 27, step == 0x4000 there won't be a carry out from the
|
||||||
// interpolation index. If there is a carry out, bit 12 will never be 1, so it'll never add more than 4 to
|
// interpolation index. If there is a carry out, bit 12 will never be 1, so it'll never add more than 4 to
|
||||||
|
|
|
@ -254,7 +254,7 @@ private:
|
||||||
ADPCMFlags current_block_flags;
|
ADPCMFlags current_block_flags;
|
||||||
std::array<s16, NUM_SAMPLES_PER_ADPCM_BLOCK> current_block_samples;
|
std::array<s16, NUM_SAMPLES_PER_ADPCM_BLOCK> current_block_samples;
|
||||||
std::array<s16, 3> previous_block_last_samples;
|
std::array<s16, 3> previous_block_last_samples;
|
||||||
std::array<s32, 2> adpcm_last_samples;
|
std::array<s16, 2> adpcm_last_samples;
|
||||||
s32 last_volume;
|
s32 last_volume;
|
||||||
|
|
||||||
VolumeSweep left_volume;
|
VolumeSweep left_volume;
|
||||||
|
@ -274,7 +274,7 @@ private:
|
||||||
|
|
||||||
void DecodeBlock(const ADPCMBlock& block);
|
void DecodeBlock(const ADPCMBlock& block);
|
||||||
s16 SampleBlock(s32 index) const;
|
s16 SampleBlock(s32 index) const;
|
||||||
s16 Interpolate() const;
|
s32 Interpolate() const;
|
||||||
|
|
||||||
// Switches to the specified phase, filling in target.
|
// Switches to the specified phase, filling in target.
|
||||||
void SetADSRPhase(ADSRPhase phase);
|
void SetADSRPhase(ADSRPhase phase);
|
||||||
|
|
Loading…
Reference in New Issue