mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
SasAudio: Compute envelope duration on state changes only.
This commit is contained in:
parent
f1ed1a9a17
commit
21006dc6a7
2 changed files with 54 additions and 20 deletions
|
@ -664,8 +664,7 @@ static const short expCurve[] = {
|
|||
0x7000
|
||||
};
|
||||
|
||||
static int durationFromRate(int rate)
|
||||
{
|
||||
static int durationFromRate(int rate) {
|
||||
if (rate == 0) {
|
||||
return PSP_SAS_ENVELOPE_FREQ_MAX;
|
||||
} else {
|
||||
|
@ -711,7 +710,7 @@ static int getExpCurveAt(int index, int duration) {
|
|||
}
|
||||
|
||||
ADSREnvelope::ADSREnvelope()
|
||||
: attackRate(0),
|
||||
: attackRate(0),
|
||||
decayRate(0),
|
||||
sustainRate(0),
|
||||
releaseRate(0),
|
||||
|
@ -725,42 +724,38 @@ ADSREnvelope::ADSREnvelope()
|
|||
height_(0) {
|
||||
}
|
||||
|
||||
void ADSREnvelope::WalkCurve(int rate, int type) {
|
||||
void ADSREnvelope::WalkCurve(int type) {
|
||||
short expFactor;
|
||||
int duration;
|
||||
switch (type) {
|
||||
case PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE:
|
||||
height_ += rate;
|
||||
height_ += rate_;
|
||||
break;
|
||||
|
||||
case PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE:
|
||||
height_ -= rate;
|
||||
height_ -= rate_;
|
||||
break;
|
||||
|
||||
case PSP_SAS_ADSR_CURVE_MODE_LINEAR_BENT:
|
||||
if (height_ < (s64)PSP_SAS_ENVELOPE_HEIGHT_MAX * 3 / 4) {
|
||||
height_ += rate;
|
||||
height_ += rate_;
|
||||
} else {
|
||||
height_ += rate / 4;
|
||||
height_ += rate_ / 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE:
|
||||
// NOTICE_LOG(SAS, "UNIMPL EXP DECR");
|
||||
duration = durationFromRate(rate);
|
||||
expFactor = getExpCurveAt(steps_, duration);
|
||||
expFactor = getExpCurveAt(steps_, duration_);
|
||||
height_ = (s64)expFactor * PSP_SAS_ENVELOPE_HEIGHT_MAX / expCurveReference;
|
||||
height_ = PSP_SAS_ENVELOPE_HEIGHT_MAX - height_;
|
||||
break;
|
||||
|
||||
case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE:
|
||||
duration = durationFromRate(rate);
|
||||
expFactor = getExpCurveAt(steps_, duration);
|
||||
expFactor = getExpCurveAt(steps_, duration_);
|
||||
height_ = (s64)expFactor * PSP_SAS_ENVELOPE_HEIGHT_MAX / expCurveReference;
|
||||
break;
|
||||
|
||||
case PSP_SAS_ADSR_CURVE_MODE_DIRECT:
|
||||
height_ = rate; // Simple :)
|
||||
height_ = rate_; // Simple :)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -768,29 +763,55 @@ void ADSREnvelope::WalkCurve(int rate, int type) {
|
|||
void ADSREnvelope::SetState(ADSRState state) {
|
||||
steps_ = 0;
|
||||
state_ = state;
|
||||
switch (state) {
|
||||
case STATE_ATTACK:
|
||||
rate_ = attackRate;
|
||||
type_ = attackType;
|
||||
break;
|
||||
case STATE_DECAY:
|
||||
rate_ = decayRate;
|
||||
type_ = decayType;
|
||||
break;
|
||||
case STATE_SUSTAIN:
|
||||
rate_ = sustainRate;
|
||||
type_ = sustainType;
|
||||
break;
|
||||
case STATE_RELEASE:
|
||||
rate_ = releaseRate;
|
||||
type_ = releaseType;
|
||||
break;
|
||||
case STATE_OFF:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type_) {
|
||||
case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE:
|
||||
case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE:
|
||||
duration_ = durationFromRate(rate_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ADSREnvelope::Step() {
|
||||
WalkCurve(type_);
|
||||
switch (state_) {
|
||||
case STATE_ATTACK:
|
||||
WalkCurve(attackRate, attackType);
|
||||
if (height_ > PSP_SAS_ENVELOPE_HEIGHT_MAX || height_ < 0)
|
||||
SetState(STATE_DECAY);
|
||||
break;
|
||||
case STATE_DECAY:
|
||||
WalkCurve(decayRate, decayType);
|
||||
if (height_ > PSP_SAS_ENVELOPE_HEIGHT_MAX || height_ < sustainLevel)
|
||||
SetState(STATE_SUSTAIN);
|
||||
break;
|
||||
case STATE_SUSTAIN:
|
||||
WalkCurve(sustainRate, sustainType);
|
||||
if (height_ <= 0) {
|
||||
height_ = 0;
|
||||
SetState(STATE_RELEASE);
|
||||
}
|
||||
break;
|
||||
case STATE_RELEASE:
|
||||
WalkCurve(releaseRate, releaseType);
|
||||
if (height_ <= 0) {
|
||||
height_ = 0;
|
||||
SetState(STATE_OFF);
|
||||
|
@ -830,4 +851,9 @@ void ADSREnvelope::DoState(PointerWrap &p) {
|
|||
p.Do(state_);
|
||||
p.Do(steps_);
|
||||
p.Do(height_);
|
||||
|
||||
// If loading, recompute the per-state variables
|
||||
if (p.GetMode() == PointerWrap::MODE_READ) {
|
||||
SetState(state_);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ public:
|
|||
ADSREnvelope();
|
||||
void SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2);
|
||||
|
||||
void WalkCurve(int rate, int type);
|
||||
void WalkCurve(int type);
|
||||
|
||||
void KeyOn();
|
||||
void KeyOff();
|
||||
|
@ -166,6 +166,14 @@ public:
|
|||
void DoState(PointerWrap &p);
|
||||
|
||||
private:
|
||||
void ComputeDuration();
|
||||
|
||||
// Internal variables that are recomputed on state changes
|
||||
// No need to save in state
|
||||
int rate_;
|
||||
int type_;
|
||||
int duration_;
|
||||
|
||||
enum ADSRState {
|
||||
STATE_ATTACK,
|
||||
STATE_DECAY,
|
||||
|
|
Loading…
Add table
Reference in a new issue