mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Optimize the VAGADPCM decoder.
This commit is contained in:
parent
53deef19c5
commit
0de71f27cb
3 changed files with 31 additions and 28 deletions
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue