mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 13:27:45 -07:00
DSPHLE/AX: fix low-pass/biquad clipping
The low-pass and biquad filters run in set40 mode where accessing ac#.m returns the value of ac#.hm clamped to 16 bits. This fixes the crackling in "Need for Speed: Nitro" (issue 13610). Also make the lower bound match hardware (-0x8000 instead of -0x7FFF).
This commit is contained in:
parent
20f2320fcf
commit
eb54721475
@ -578,8 +578,8 @@ void AXUCode::OutputSamples(u32 lr_addr, u32 surround_addr)
|
||||
// Output samples clamped to 16 bits and interlaced RLRLRLRLRL...
|
||||
for (u32 i = 0; i < 5 * 32; ++i)
|
||||
{
|
||||
int left = std::clamp(m_samples_main_left[i], -32767, 32767);
|
||||
int right = std::clamp(m_samples_main_right[i], -32767, 32767);
|
||||
s16 left = ClampS16(m_samples_main_left[i]);
|
||||
s16 right = ClampS16(m_samples_main_right[i]);
|
||||
|
||||
buffer[2 * i + 0] = Common::swap16(right);
|
||||
buffer[2 * i + 1] = Common::swap16(left);
|
||||
|
@ -372,6 +372,11 @@ void GetInputSamples(HLEAccelerator* accelerator, PB_TYPE& pb, s16* samples, u16
|
||||
pb.adpcm.pred_scale = accelerator->GetPredScale();
|
||||
}
|
||||
|
||||
s16 ClampS16(s64 sample)
|
||||
{
|
||||
return std::clamp<s64>(sample, -0x8000, 0x7FFF);
|
||||
}
|
||||
|
||||
// Add samples to an output buffer, with optional volume ramping.
|
||||
void MixAdd(int* out, const s16* input, u32 count, VolumeData* vd, s16* dpop, bool ramp)
|
||||
{
|
||||
@ -389,21 +394,20 @@ void MixAdd(int* out, const s16* input, u32 count, VolumeData* vd, s16* dpop, bo
|
||||
s64 sample = input[i];
|
||||
sample *= volume;
|
||||
sample >>= 15;
|
||||
sample = std::clamp((s32)sample, -32767, 32767); // -32768 ?
|
||||
s16 sample16 = ClampS16((s32)sample);
|
||||
|
||||
out[i] += (s16)sample;
|
||||
out[i] += sample16;
|
||||
volume += volume_delta;
|
||||
|
||||
*dpop = (s16)sample;
|
||||
*dpop = sample16;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute a low pass filter on the samples using one history value. Returns
|
||||
// the new history value.
|
||||
// Execute a low pass filter on the samples using one history value.
|
||||
static void LowPassFilter(s16* samples, u32 count, PBLowPassFilter& f)
|
||||
{
|
||||
for (u32 i = 0; i < count; ++i)
|
||||
f.yn1 = samples[i] = (f.a0 * (s32)samples[i] + f.b0 * (s32)f.yn1) >> 15;
|
||||
f.yn1 = samples[i] = ClampS16((f.a0 * (s32)samples[i] + f.b0 * (s32)f.yn1) >> 15);
|
||||
}
|
||||
|
||||
#ifdef AX_WII
|
||||
@ -425,7 +429,7 @@ static void BiquadFilter(s16* samples, u32 count, PBBiquadFilter& f)
|
||||
else
|
||||
tmp += 0x7FFF;
|
||||
tmp >>= 16;
|
||||
s16 yn0 = s16(tmp);
|
||||
s16 yn0 = ClampS16(tmp);
|
||||
f.xn2 = f.xn1;
|
||||
f.yn2 = f.yn1;
|
||||
f.xn1 = xn0;
|
||||
@ -459,7 +463,7 @@ void ProcessVoice(HLEAccelerator* accelerator, PB_TYPE& pb, const AXBuffers& buf
|
||||
const s32 volume = (u16)pb.vol_env.cur_volume;
|
||||
#endif
|
||||
const s32 sample = ((s32)samples[i] * volume) >> 15;
|
||||
samples[i] = std::clamp(sample, -32767, 32767); // -32768 ?
|
||||
samples[i] = ClampS16(sample);
|
||||
pb.vol_env.cur_volume += pb.vol_env.cur_volume_delta;
|
||||
}
|
||||
|
||||
|
@ -602,15 +602,16 @@ void AXWiiUCode::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume, bool
|
||||
// Clamp internal buffers to 16 bits.
|
||||
for (size_t i = 0; i < volume_ramp.size(); ++i)
|
||||
{
|
||||
int left = m_samples_main_left[i];
|
||||
int right = m_samples_main_right[i];
|
||||
// Cast to s64 to avoid overflow.
|
||||
s64 left = m_samples_main_left[i];
|
||||
s64 right = m_samples_main_right[i];
|
||||
|
||||
// Apply global volume. Cast to s64 to avoid overflow.
|
||||
left = ((s64)left * volume_ramp[i]) >> 15;
|
||||
right = ((s64)right * volume_ramp[i]) >> 15;
|
||||
// Apply global volume.
|
||||
left = (left * volume_ramp[i]) >> 15;
|
||||
right = (right * volume_ramp[i]) >> 15;
|
||||
|
||||
m_samples_main_left[i] = std::clamp(left, -32767, 32767);
|
||||
m_samples_main_right[i] = std::clamp(right, -32767, 32767);
|
||||
m_samples_main_left[i] = ClampS16(left);
|
||||
m_samples_main_right[i] = ClampS16(right);
|
||||
}
|
||||
|
||||
std::array<s16, 3 * 32 * 2> buffer;
|
||||
@ -635,7 +636,7 @@ void AXWiiUCode::OutputWMSamples(u32* addresses)
|
||||
u16* out = (u16*)HLEMemory_Get_Pointer(memory, addresses[i]);
|
||||
for (u32 j = 0; j < 3 * 6; ++j)
|
||||
{
|
||||
int sample = std::clamp(in[j], -32767, 32767);
|
||||
s16 sample = ClampS16(in[j]);
|
||||
out[j] = Common::swap16((u16)sample);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user