From 0de71f27cbcd1a889b4458f6b3adedb0c640f7fd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Jan 2014 01:57:22 +0100 Subject: [PATCH] Optimize the VAGADPCM decoder. --- Core/HLE/sceSas.cpp | 8 ++++---- Core/HW/SasAudio.cpp | 35 ++++++++++++++++++++++------------- Core/HW/SasAudio.h | 16 +++++----------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 3bc169e0a8..481f70a4fd 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -394,15 +394,15 @@ u32 sceSasSetSimpleADSR(u32 core, int voiceNum, u32 ADSREnv1, u32 ADSREnv2) { } u32 sceSasGetEnvelopeHeight(u32 core, int voiceNum) { - DEBUG_LOG(SCESAS, "sceSasGetEnvelopeHeight(%08x, %i)", core, voiceNum); - if (voiceNum >= PSP_SAS_VOICES_MAX || voiceNum < 0) { - WARN_LOG(SCESAS, "%s: invalid voicenum %d", __FUNCTION__, voiceNum); + ERROR_LOG(SCESAS, "%s: invalid voicenum %d", __FUNCTION__, voiceNum); return ERROR_SAS_INVALID_VOICE; } SasVoice &v = sas->voices[voiceNum]; - return v.envelope.GetHeight(); + int height = v.envelope.GetHeight(); + DEBUG_LOG(SCESAS, "%i = sceSasGetEnvelopeHeight(%08x, %i)", height, core, voiceNum); + return height; } u32 sceSasRevType(u32 core, int type) { diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index db12e1dc3f..1a577db1f8 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -61,7 +61,8 @@ void VagDecoder::Start(u32 data, int vagSize, bool loopEnabled) { s_2 = 0; } -void VagDecoder::DecodeBlock(u8 *&readp) { +void VagDecoder::DecodeBlock(u8 *&read_pointer) { + u8 *readp = read_pointer; int predict_nr = *readp++; int shift_factor = predict_nr & 0xf; predict_nr >>= 4; @@ -79,24 +80,33 @@ void VagDecoder::DecodeBlock(u8 *&readp) { loopAtNextBlock_ = true; } } + + // Keep state in locals to avoid bouncing to memory. + int s1 = s_1; + int s2 = s_2; + + int coef1 = f[predict_nr][0]; + int coef2 = f[predict_nr][1]; + for (int i = 0; i < 28; i += 2) { - int d = *readp++; - int s = (short)((d & 0xf) << 12); - DecodeSample(i, s >> shift_factor, predict_nr); - s = (short)((d & 0xf0) << 8); - DecodeSample(i + 1, s >> shift_factor, predict_nr); + u8 d = *readp++; + int sample1 = (short)((d & 0xf) << 12) >> shift_factor; + int sample2 = (short)((d & 0xf0) << 8) >> shift_factor; + s2 = (int)(sample1 + ((s1 * coef1 + s2 * coef2) >> 6)); + s1 = (int)(sample2 + ((s2 * coef1 + s1 * coef2) >> 6)); + samples[i] = s2; + samples[i + 1] = s1; } + + s_1 = s1; + s_2 = s2; curSample = 0; curBlock_++; if (curBlock_ == numBlocks_) { end_ = true; } -} -inline void VagDecoder::DecodeSample(int i, int sample, int predict_nr) { - samples[i] = (int) (sample + ((s_1 * f[predict_nr][0] + s_2 * f[predict_nr][1]) >> 6)); - s_2 = s_1; - s_1 = samples[i]; + read_pointer = readp; } void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { @@ -137,8 +147,7 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { } } -void VagDecoder::DoState(PointerWrap &p) -{ +void VagDecoder::DoState(PointerWrap &p) { auto s = p.Section("VagDecoder", 1); if (!s) return; diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 35739aef6b..789223dca6 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -62,8 +62,7 @@ enum { PSP_SAS_EFFECT_TYPE_PIPE = 8, }; -struct WaveformEffect -{ +struct WaveformEffect { int type; int delay; int feedback; @@ -98,7 +97,6 @@ public: void DoState(PointerWrap &p); private: - void DecodeSample(int i, int sample, int predict_nr); int samples[28]; int curSample; @@ -132,9 +130,7 @@ private: BufferQueue *sampleQueue; }; -// Max height: 0x40000000 I think -class ADSREnvelope -{ +class ADSREnvelope { public: ADSREnvelope(); void SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2); @@ -184,14 +180,13 @@ private: ADSRState state_; int steps_; - s64 height_; // s64 to avoid having to care about overflow when calculatimg. TODO: this should be fine as s32 + s64 height_; // s64 to avoid having to care about overflow when calculating. TODO: this should be fine as s32 }; // A SAS voice. // TODO: Look into pre-decoding the VAG samples on SetVoice instead of decoding them on the fly. // It's not very likely that games encode VAG dynamically. -struct SasVoice -{ +struct SasVoice { SasVoice() : playing(false), paused(false), @@ -262,8 +257,7 @@ struct SasVoice SasAtrac3 atrac3; }; -class SasInstance -{ +class SasInstance { public: SasInstance(); ~SasInstance();