Don't change height immediately on keyon.

This replicates the PSP's behavior, which is a 32-grain lead in, plus the
height remains what it was before until processing happens.
This commit is contained in:
Unknown W. Brackets 2014-02-16 09:29:17 -08:00
parent 2e69aa913d
commit d53ab02e5b
2 changed files with 38 additions and 14 deletions

View File

@ -758,12 +758,26 @@ void ADSREnvelope::Step() {
case STATE_OFF:
// Do nothing
break;
case STATE_KEYON:
height_ = 0;
SetState(STATE_KEYON_STEP);
break;
case STATE_KEYON_STEP:
// This entire state is pretty much a hack to reproduce PSP behavior.
// The STATE_KEYON state is a real state, but not sure how it switches.
// It takes 32 steps at 0 for keyon to "kick in", 31 should shift to 0 anyway.
height_++;
if (height_ >= 31) {
height_ = 0;
SetState(STATE_ATTACK);
}
break;
}
}
void ADSREnvelope::KeyOn() {
SetState(STATE_ATTACK);
height_ = 0;
SetState(STATE_KEYON);
}
void ADSREnvelope::KeyOff() {
@ -779,7 +793,7 @@ void ADSREnvelope::End() {
}
void ADSREnvelope::DoState(PointerWrap &p) {
auto s = p.Section("ADSREnvelope", 1);
auto s = p.Section("ADSREnvelope", 1, 2);
if (!s) {
return;
}
@ -793,8 +807,15 @@ void ADSREnvelope::DoState(PointerWrap &p) {
p.Do(sustainType);
p.Do(sustainLevel);
p.Do(releaseType);
p.Do(state_);
int stepsLegacy;
p.Do(stepsLegacy);
if (s < 2) {
p.Do(state_);
if (state_ == 4) {
state_ = STATE_OFF;
}
int stepsLegacy;
p.Do(stepsLegacy);
} else {
p.Do(state_);
}
p.Do(height_);
}

View File

@ -144,7 +144,7 @@ public:
void Step();
int GetHeight() const {
return height_ > (s64)PSP_SAS_ENVELOPE_HEIGHT_MAX ? (s64)PSP_SAS_ENVELOPE_HEIGHT_MAX : height_;
return height_ > (s64)PSP_SAS_ENVELOPE_HEIGHT_MAX ? PSP_SAS_ENVELOPE_HEIGHT_MAX : height_;
}
bool HasEnded() const {
return state_ == STATE_OFF;
@ -162,14 +162,17 @@ public:
void DoState(PointerWrap &p);
private:
void ComputeDuration();
// Actual PSP values.
enum ADSRState {
STATE_ATTACK,
STATE_DECAY,
STATE_SUSTAIN,
STATE_RELEASE,
STATE_OFF,
// Okay, this one isn't a real value but it might be.
STATE_KEYON_STEP = -42,
STATE_KEYON = -2,
STATE_OFF = -1,
STATE_ATTACK = 0,
STATE_DECAY = 1,
STATE_SUSTAIN = 2,
STATE_RELEASE = 3,
};
void SetState(ADSRState state);