mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-14 01:59:34 +01:00
sceSas: Pass the send through at the full rate when no reverb is selected
The "off" path decimated the send to 22khz and then doubled every sample, which folded everything above 11khz down. The ME runs a separate full-rate loop for it instead: pspautotests' audio/reverb/upsample shows a 22.05khz tone surviving with no reverb selected. The comments on the reverb's resampling now cite that test too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
621c2a7e21
commit
cf94ea8886
2 files changed
+22
-13
No files matched your search
+18
-3
@@ -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) {
|
||||
|
||||
+4
-10
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user