diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 7cc23ea566..2f53008eb3 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -778,14 +778,29 @@ void SasInstance::SetWaveformEffectParams(int delay, int feedback) { // See http://report.ppsspp.org/logs/kind/772 for a list of games that use different types. Maybe can help us figure out // which is which. void SasInstance::ApplyWaveformEffect() { - // First, downsample the send buffer to 22khz. We do this naively for now. + // Volume max is 0x1000, while our factor is up to 0x8000. Shifting left by 3 fixes that. + const int volLeft = (uint16_t)(waveformEffect.leftVol << 3); + const int volRight = (uint16_t)(waveformEffect.rightVol << 3); + + if (reverb_.GetPreset() == -1) { + // With no reverb selected, the ME runs a separate loop at the full 44.1khz, so the send + // goes straight through (tests/audio/reverb/upsample: a 22.05khz tone survives). + for (int i = 0; i < grainSize * 2; i += 2) { + sendBufferProcessed[i + 0] = clamp_s16(clamp_s16(sendBuffer[i + 0]) * volLeft >> 15); + sendBufferProcessed[i + 1] = clamp_s16(clamp_s16(sendBuffer[i + 1]) * volRight >> 15); + } + return; + } + + // First, downsample the send buffer to 22khz. The ME keeps one frame of each pair, with no + // filter (tests/audio/reverb/upsample: a 22.05khz tone reaches the reverb as DC). It keeps the + // second frame; we keep the first. for (int i = 0; i < grainSize / 2; i++) { sendBufferDownsampled[i * 2] = clamp_s16(sendBuffer[i * 4]); sendBufferDownsampled[i * 2 + 1] = clamp_s16(sendBuffer[i * 4 + 1]); } - // Volume max is 0x1000, while our factor is up to 0x8000. Shifting left by 3 fixes that. - reverb_.ProcessReverb(sendBufferProcessed, sendBufferDownsampled, grainSize / 2, (uint16_t)(waveformEffect.leftVol << 3), (uint16_t)(waveformEffect.rightVol << 3)); + reverb_.ProcessReverb(sendBufferProcessed, sendBufferDownsampled, grainSize / 2, volLeft, volRight); } void SasInstance::DoState(PointerWrap &p) { diff --git a/Core/HW/SasReverb.cpp b/Core/HW/SasReverb.cpp index e6ebd4011a..d3543a4f23 100644 --- a/Core/HW/SasReverb.cpp +++ b/Core/HW/SasReverb.cpp @@ -272,7 +272,8 @@ private: int size_; }; -// The hardware upsamples the reverb's 22khz output by zero-stuffing, with no filter after it. That +// The hardware upsamples the reverb's 22khz output by zero-stuffing, with no filter after it +// (tests/audio/reverb/upsample: with dry off, every odd frame is exactly zero). That // leaves a mirror image of the whole wet signal just below 22khz, at full amplitude: it is barely // audible itself, but it eats the headroom of the final mix, so loud scenes clip much more (Outrun // 2006 while racing). We deliberately replace that with a proper interpolation filter. @@ -330,16 +331,9 @@ void SasReverb::UpsampleWet(int16_t *out, int count) { } void SasReverb::ProcessReverb(int16_t *output, const int16_t *input, size_t inputSize, int volLeft, int volRight) { - // This means replicate the input signal in the processed buffer. - // Can also be used to verify that the error is in here... + // "Off" runs at the full rate and never gets here (see SasInstance::ApplyWaveformEffect). if (preset_ == -1) { - // Strangely, OFF is not filled with zeroes every other. Seems special cased. - for (size_t i = 0; i < inputSize; ++i) { - output[i * 4 + 0] = clamp_s16((int)input[i * 2 + 0] * volLeft >> 15); - output[i * 4 + 1] = clamp_s16((int)input[i * 2 + 1] * volRight >> 15); - output[i * 4 + 2] = clamp_s16((int)input[i * 2 + 0] * volLeft >> 15); - output[i * 4 + 3] = clamp_s16((int)input[i * 2 + 1] * volRight >> 15); - } + memset(output, 0, inputSize * 4 * sizeof(int16_t)); return; }