SasAudio: Some cleanup and debug overlay improvements

Shows "BAD" in the overlay if address out of range.

Which does happen in Afterburner, see issue #14010.
This commit is contained in:
Henrik Rydgård 2023-09-05 11:49:43 +02:00
parent 3f29b4c713
commit 95e86c73b8
3 changed files with 82 additions and 45 deletions

View file

@ -125,6 +125,7 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) {
WARN_LOG_REPORT(SASMIX, "Bad VAG samples address? %08x / %d", read_, numBlocks_);
return;
}
const u8 *readp = Memory::GetPointerUnchecked(read_);
const u8 *origp = readp;
@ -146,6 +147,7 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) {
return;
}
}
_dbg_assert_(curSample < 28);
outSamples[i] = samples[curSample++];
}
@ -320,13 +322,13 @@ static int getSustainLevel(int bitfield1) {
void ADSREnvelope::SetEnvelope(int flag, int a, int d, int s, int r) {
if ((flag & 0x1) != 0)
attackType = a;
attackType = (SasADSRCurveMode)a;
if ((flag & 0x2) != 0)
decayType = d;
decayType = (SasADSRCurveMode)d;
if ((flag & 0x4) != 0)
sustainType = s;
sustainType = (SasADSRCurveMode)s;
if ((flag & 0x8) != 0)
releaseType = r;
releaseType = (SasADSRCurveMode)r;
if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) {
sustainType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE;
@ -346,13 +348,13 @@ void ADSREnvelope::SetRate(int flag, int a, int d, int s, int r) {
void ADSREnvelope::SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2) {
attackRate = getAttackRate(ADSREnv1);
attackType = getAttackType(ADSREnv1);
attackType = (SasADSRCurveMode)getAttackType(ADSREnv1);
decayRate = getDecayRate(ADSREnv1);
decayType = PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE;
sustainRate = getSustainRate(ADSREnv2);
sustainType = getSustainType(ADSREnv2);
sustainType = (SasADSRCurveMode)getSustainType(ADSREnv2);
releaseRate = getReleaseRate(ADSREnv2);
releaseType = getReleaseType(ADSREnv2);
releaseType = (SasADSRCurveMode)getReleaseType(ADSREnv2);
sustainLevel = getSustainLevel(ADSREnv1);
if (PSP_CoreParameter().compat.flags().RockmanDash2SoundFix && sustainType == PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE) {
@ -371,6 +373,7 @@ SasInstance::SasInstance() {
memset(&waveformEffect, 0, sizeof(waveformEffect));
waveformEffect.type = PSP_SAS_EFFECT_TYPE_OFF;
waveformEffect.isDryOn = 1;
memset(mixTemp_, 0, sizeof(mixTemp_)); // just to avoid a static analysis warning.
}
SasInstance::~SasInstance() {
@ -383,7 +386,24 @@ void SasInstance::GetDebugText(char *text, size_t bufsize) {
char *p = voiceBuf;
for (int i = 0; i < maxVoices; i++) {
if (voices[i].playing) {
p += snprintf(p, sizeof(voiceBuf) - (p - voiceBuf), " %d: Pitch %d L/R,FX: %d,%d|%d,%d VAG: %08x:%d:%08x Height:%d%%\n", i, voices[i].pitch, voices[i].volumeLeft, voices[i].volumeRight, voices[i].effectLeft, voices[i].effectRight, voices[i].vagAddr, voices[i].vagSize, voices[i].vag.GetReadPtr(), (int)((int64_t)voices[i].envelope.GetHeight() * 100 / PSP_SAS_ENVELOPE_HEIGHT_MAX));
uint32_t readAddr = voices[i].GetReadAddress();
const char *indicator = "";
switch (voices[i].type) {
case VOICETYPE_VAG:
if (readAddr < voices[i].vagAddr || readAddr > voices[i].vagAddr + voices[i].vagSize) {
indicator = " (BAD!)";
}
break;
}
p += snprintf(p, sizeof(voiceBuf) - (p - voiceBuf), " %d: Pitch %04x L/R,FX: %d,%d|%d,%d VAG: %08x:%d:%08x%s Height:%d%%\n", i,
voices[i].pitch, voices[i].volumeLeft, voices[i].volumeRight, voices[i].effectLeft, voices[i].effectRight,
voices[i].vagAddr, voices[i].vagSize, voices[i].GetReadAddress(), indicator, (int)((int64_t)voices[i].envelope.GetHeight() * 100 / PSP_SAS_ENVELOPE_HEIGHT_MAX));
p += snprintf(p, sizeof(voiceBuf) - (p - voiceBuf), " - ADSR: %s/%s/%s/%s\n",
ADSRCurveModeAsString(voices[i].envelope.attackType),
ADSRCurveModeAsString(voices[i].envelope.decayType),
ADSRCurveModeAsString(voices[i].envelope.sustainType),
ADSRCurveModeAsString(voices[i].envelope.releaseType)
);
}
}
@ -851,20 +871,6 @@ void SasVoice::DoState(PointerWrap &p) {
atrac3.DoState(p);
}
ADSREnvelope::ADSREnvelope()
: attackRate(0),
decayRate(0),
sustainRate(0),
releaseRate(0),
attackType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE),
decayType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE),
sustainType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE),
sustainLevel(0),
releaseType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE),
state_(STATE_OFF),
height_(0) {
}
void ADSREnvelope::WalkCurve(int type, int rate) {
s64 expDelta;
switch (type) {
@ -999,3 +1005,15 @@ void ADSREnvelope::DoState(PointerWrap &p) {
}
Do(p, height_);
}
const char *ADSRCurveModeAsString(SasADSRCurveMode mode) {
switch (mode) {
case PSP_SAS_ADSR_CURVE_MODE_DIRECT: return "D";
case PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE: return "L+";
case PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE: return "L-";
case PSP_SAS_ADSR_CURVE_MODE_LINEAR_BENT: return "LB";
case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE: return "E-";
case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE: return "E+";
default: return "N/A";
}
}

View file

@ -28,36 +28,41 @@
class PointerWrap;
// General constants.
enum {
PSP_SAS_VOICES_MAX = 32,
PSP_SAS_VOL_MAX = 0x1000,
PSP_SAS_MAX_GRAIN = 2048, // Matches the max value of the parameter to sceSasInit
PSP_SAS_PITCH_MIN = 0x0000,
PSP_SAS_PITCH_BASE = 0x1000,
PSP_SAS_PITCH_MASK = 0xFFF,
PSP_SAS_PITCH_BASE_SHIFT = 12,
PSP_SAS_PITCH_MAX = 0x4000,
PSP_SAS_ENVELOPE_HEIGHT_MAX = 0x40000000,
PSP_SAS_ENVELOPE_FREQ_MAX = 0x7FFFFFFF,
};
PSP_SAS_VOL_MAX = 0x1000,
PSP_SAS_MAX_GRAIN = 2048, // Matches the max value of the parameter to sceSasInit
// The type of these are baked into savestates.
enum SasADSRCurveMode : int {
PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE = 0,
PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE = 1,
PSP_SAS_ADSR_CURVE_MODE_LINEAR_BENT = 2,
PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE = 3,
PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE = 4,
PSP_SAS_ADSR_CURVE_MODE_DIRECT = 5,
};
enum {
PSP_SAS_ADSR_ATTACK = 1,
PSP_SAS_ADSR_DECAY = 2,
PSP_SAS_ADSR_SUSTAIN = 4,
PSP_SAS_ADSR_RELEASE = 8,
};
PSP_SAS_ENVELOPE_HEIGHT_MAX = 0x40000000,
PSP_SAS_ENVELOPE_FREQ_MAX = 0x7FFFFFFF,
enum SasEffectType {
PSP_SAS_EFFECT_TYPE_OFF = -1,
PSP_SAS_EFFECT_TYPE_ROOM = 0,
PSP_SAS_EFFECT_TYPE_STUDIO_SMALL= 1,
PSP_SAS_EFFECT_TYPE_STUDIO_SMALL = 1,
PSP_SAS_EFFECT_TYPE_STUDIO_MEDIUM = 2,
PSP_SAS_EFFECT_TYPE_STUDIO_LARGE = 3,
PSP_SAS_EFFECT_TYPE_HALL = 4,
@ -66,7 +71,9 @@ enum {
PSP_SAS_EFFECT_TYPE_DELAY = 7,
PSP_SAS_EFFECT_TYPE_PIPE = 8,
PSP_SAS_EFFECT_TYPE_MAX = 8,
};
enum SasOutputMode {
PSP_SAS_OUTPUTMODE_MIXED = 0,
PSP_SAS_OUTPUTMODE_RAW = 1,
};
@ -149,7 +156,6 @@ private:
class ADSREnvelope {
public:
ADSREnvelope();
void SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2);
void SetEnvelope(int flag, int a, int d, int s, int r);
void SetRate(int flag, int a, int d, int s, int r);
@ -177,6 +183,17 @@ public:
void DoState(PointerWrap &p);
int attackRate = 0;
int decayRate = 0;
int sustainRate = 0;
int sustainLevel = 0;
int releaseRate = 0;
SasADSRCurveMode attackType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE;
SasADSRCurveMode decayType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE;
SasADSRCurveMode sustainType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE;
SasADSRCurveMode releaseType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE;
private:
// Actual PSP values.
enum ADSRState {
@ -192,18 +209,8 @@ private:
};
void SetState(ADSRState state);
int attackRate;
int decayRate;
int sustainRate;
int releaseRate;
int attackType;
int decayType;
int sustainType;
int sustainLevel;
int releaseType;
ADSRState state_;
s64 height_; // s64 to avoid having to care about overflow when calculating. TODO: this should be fine as s32
ADSRState state_ = STATE_OFF;
s64 height_ = 0; // s64 to avoid having to care about overflow when calculating. TODO: this should be fine as s32
};
// A SAS voice.
@ -243,6 +250,15 @@ struct SasVoice {
void ReadSamples(s16 *output, int numSamples);
bool HaveSamplesEnded() const;
// For debugging.
u32 GetReadAddress() const {
if (type == VOICETYPE_VAG) {
return vag.GetReadPtr();
} else {
return 0; // TODO.
}
}
bool playing;
bool paused; // a voice can be playing AND paused. In that case, it won't play.
bool on; // key-on, key-off.
@ -273,6 +289,7 @@ struct SasVoice {
ADSREnvelope envelope;
// TODO: Union these two?
VagDecoder vag;
SasAtrac3 atrac3;
};
@ -318,3 +335,5 @@ private:
int grainSize = 0;
int16_t mixTemp_[PSP_SAS_MAX_GRAIN * 4 + 2 + 8]; // some extra margin for very high pitches.
};
const char *ADSRCurveModeAsString(SasADSRCurveMode mode);

View file

@ -44,11 +44,11 @@ static void DrawAudioDebugStats(UIContext *ctx, const Bounds &bounds) {
ctx->Flush();
ctx->BindFontTexture();
ctx->Draw()->SetFontScale(0.7f, 0.7f);
ctx->Draw()->SetFontScale(0.5f, 0.5f);
ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
float left = std::max(bounds.w / 2 - 20.0f, 550.0f);
float left = std::max(bounds.w / 2 - 20.0f, 500.0f);
__SasGetDebugStats(statbuf, sizeof(statbuf));
ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + left + 21, bounds.y + 31, bounds.w - left, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII);