From cd251af345c3ed97b459b7bdb9e068a4f3e168a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 15 Nov 2013 12:28:16 +0100 Subject: [PATCH] More minor SasAudio optimizations --- Core/HW/SasAudio.cpp | 49 ++++++++++++++++++++++++++------------------ Core/HW/SasAudio.h | 3 ++- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 5d7259ab80..28556e4e81 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -387,7 +387,7 @@ void SasInstance::MixVoice(SasVoice &voice) { case VOICETYPE_PCM: if (voice.type == VOICETYPE_PCM && !voice.pcmAddr) break; - default: + default: // Load resample history (so we can use a wide filter) resampleBuffer[0] = voice.resampleHist[0]; resampleBuffer[1] = voice.resampleHist[1]; @@ -396,7 +396,7 @@ void SasInstance::MixVoice(SasVoice &voice) { // Actually this is not entirely correct - we need to get one extra sample, and store it // for the next time around. A little complicated... // But for now, see Smoothness HACKERY below :P - u32 numSamples = (voice.sampleFrac + grainSize * voice.pitch) / PSP_SAS_PITCH_BASE; + u32 numSamples = (voice.sampleFrac + grainSize * voice.pitch) >> PSP_SAS_PITCH_SHIFT; if ((int)numSamples > grainSize * 4) { ERROR_LOG(SASMIX, "numSamples too large, clamping: %i vs %i", numSamples, grainSize * 4); numSamples = grainSize * 4; @@ -421,7 +421,7 @@ void SasInstance::MixVoice(SasVoice &voice) { if (volumeShift < 0) volumeShift = 0; for (int i = 0; i < grainSize; i++) { // For now: nearest neighbour, not even using the resample history at all. - int sample = resampleBuffer[sampleFrac / PSP_SAS_PITCH_BASE + 2]; + int sample = resampleBuffer[(sampleFrac >> PSP_SAS_PITCH_SHIFT) + 2]; sampleFrac += voice.pitch; // The maximum envelope height (PSP_SAS_ENVELOPE_HEIGHT_MAX) is (1 << 30) - 1. @@ -446,7 +446,7 @@ void SasInstance::MixVoice(SasVoice &voice) { voice.sampleFrac = sampleFrac; // Let's hope grainSize is a power of 2. //voice.sampleFrac &= grainSize * PSP_SAS_PITCH_BASE - 1; - voice.sampleFrac -= numSamples * PSP_SAS_PITCH_BASE; + voice.sampleFrac -= numSamples << PSP_SAS_PITCH_SHIFT; if (voice.envelope.HasEnded()) { @@ -685,16 +685,16 @@ static int durationFromRate(int rate) { const short expCurveReference = 0x7000; +const float expCurveToEnvelopeHeight = (float)PSP_SAS_ENVELOPE_HEIGHT_MAX / (float)expCurveReference; + // This needs a rewrite / rethink. Doing all this per sample is insane. -static int getExpCurveAt(int index, int duration) { - const short curveLength = sizeof(expCurve) / sizeof(short); +static float computeExpCurveAt(int index, float invDuration) { + const int curveLength = ARRAY_SIZE(expCurve); - if (duration == 0) { - // Avoid division by zero, and thus undefined behaviour in conversion to int. - return 0; - } + if (invDuration == 0.0f) + return 0.0f; - float curveIndex = (index * curveLength) / (float) duration; + float curveIndex = (index * curveLength) * invDuration; int curveIndex1 = (int) curveIndex; int curveIndex2 = curveIndex1 + 1; float curveIndexFraction = curveIndex - curveIndex1; @@ -705,8 +705,7 @@ static int getExpCurveAt(int index, int duration) { return expCurve[curveLength - 1]; } - float sample = expCurve[curveIndex1] * (1.f - curveIndexFraction) + expCurve[curveIndex2] * curveIndexFraction; - return (short)(sample); + return expCurve[curveIndex1] * (1.f - curveIndexFraction) + expCurve[curveIndex2] * curveIndexFraction; } ADSREnvelope::ADSREnvelope() @@ -721,11 +720,14 @@ ADSREnvelope::ADSREnvelope() releaseType(PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE), state_(STATE_OFF), steps_(0), - height_(0) { + height_(0), + type_(0), + rate_(0), + invDuration_(0) { } void ADSREnvelope::WalkCurve(int type) { - short expFactor; + float expFactor; switch (type) { case PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE: height_ += rate_; @@ -744,14 +746,14 @@ void ADSREnvelope::WalkCurve(int type) { break; case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE: - expFactor = getExpCurveAt(steps_, duration_); - height_ = (s64)expFactor * PSP_SAS_ENVELOPE_HEIGHT_MAX / expCurveReference; + expFactor = computeExpCurveAt(steps_, invDuration_); + height_ = (s64)(expFactor * expCurveToEnvelopeHeight); height_ = PSP_SAS_ENVELOPE_HEIGHT_MAX - height_; break; case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE: - expFactor = getExpCurveAt(steps_, duration_); - height_ = (s64)expFactor * PSP_SAS_ENVELOPE_HEIGHT_MAX / expCurveReference; + expFactor = computeExpCurveAt(steps_, invDuration_); + height_ = (s64)(expFactor * expCurveToEnvelopeHeight); break; case PSP_SAS_ADSR_CURVE_MODE_DIRECT: @@ -787,7 +789,14 @@ void ADSREnvelope::SetState(ADSRState state) { switch (type_) { case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_DECREASE: case PSP_SAS_ADSR_CURVE_MODE_EXPONENT_INCREASE: - duration_ = durationFromRate(rate_); + { + int duration = durationFromRate(rate_); + if (duration == 0) { + invDuration_ = 0.0f; + } else { + invDuration_ = 1.0f / (float)duration; + } + } break; default: break; diff --git a/Core/HW/SasAudio.h b/Core/HW/SasAudio.h index 18b0688faa..6c8b556dee 100644 --- a/Core/HW/SasAudio.h +++ b/Core/HW/SasAudio.h @@ -33,6 +33,7 @@ enum { PSP_SAS_PITCH_MIN = 1, PSP_SAS_PITCH_BASE = 0x1000, PSP_SAS_PITCH_MAX = 0x4000, + PSP_SAS_PITCH_SHIFT = 12, PSP_SAS_VOL_MAX = 0x1000, @@ -172,7 +173,7 @@ private: // No need to save in state int rate_; int type_; - int duration_; + float invDuration_; enum ADSRState { STATE_ATTACK,