Optimize the VAGADPCM decoder.

This commit is contained in:
Henrik Rydgard 2014-01-04 01:57:22 +01:00
parent 53deef19c5
commit 0de71f27cb
3 changed files with 31 additions and 28 deletions

View file

@ -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) {

View file

@ -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;

View file

@ -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();