From 516e983dfbd40c5c2b280a38f22c1e71ac98ade1 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 6 Oct 2017 08:03:25 -0700 Subject: [PATCH 1/4] Refactor peakhold to avoid mixed signed/unsigned fixed-point math --- libraries/audio/src/AudioGate.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/audio/src/AudioGate.cpp b/libraries/audio/src/AudioGate.cpp index 13c794b923..30ebbab12a 100644 --- a/libraries/audio/src/AudioGate.cpp +++ b/libraries/audio/src/AudioGate.cpp @@ -100,10 +100,10 @@ protected: int _histogram[NHIST] = {}; // peakhold - int32_t _holdMin = 0x7fffffff; - int32_t _holdInc = 0x7fffffff; + uint32_t _holdMin = 0x7fffffff; + uint32_t _holdInc = 0x7fffffff; uint32_t _holdMax = 0x7fffffff; - int32_t _holdRel = 0x7fffffff; + uint32_t _holdRel = 0x7fffffff; int32_t _holdPeak = 0x7fffffff; // hysteresis @@ -177,7 +177,7 @@ void GateImpl::setThreshold(float threshold) { void GateImpl::setHold(float hold) { const double RELEASE = 100.0; // release = 100ms - const double PROGHOLD = 0.100; // progressive hold = 100ms + const double PROGHOLD = 100.0; // progressive hold = 100ms // pure hold = 1 to 1000ms hold = MAX(hold, 1.0f); @@ -185,10 +185,12 @@ void GateImpl::setHold(float hold) { _holdMin = msToTc(RELEASE, _sampleRate); - _holdInc = (int32_t)((_holdMin - 0x7fffffff) / (PROGHOLD * _sampleRate)); - _holdInc = MIN(_holdInc, -1); // prevent 0 on long releases - - _holdMax = 0x7fffffff - (uint32_t)(_holdInc * (double)hold/1000.0 * _sampleRate); + double progSamples = PROGHOLD/1000.0 * _sampleRate; + _holdInc = (uint32_t)((0x7fffffff - _holdMin) / progSamples); + _holdInc = MAX(_holdInc, 1); // prevent 0 on long releases + + double holdSamples = (double)hold/1000.0 * _sampleRate; + _holdMax = 0x7fffffff + (uint32_t)(_holdInc * holdSamples); } // @@ -336,10 +338,8 @@ int32_t GateImpl::peakhold(int32_t peak) { // (_holdRel > _holdMin) progressive hold // (_holdRel = _holdMin) release - _holdRel += _holdInc; // update progressive hold - _holdRel = MAX((uint32_t)_holdRel, (uint32_t)_holdMin); // saturate at final value - - int32_t tc = MIN((uint32_t)_holdRel, 0x7fffffff); + _holdRel -= _holdInc; // update progressive hold + int32_t tc = MIN(MAX(_holdRel, _holdMin), 0x7fffffff); // saturate to [_holdMin, 0x7fffffff] peak += MULQ31((_holdPeak - peak), tc); // apply release } else { From c6f3a9d9c34dff3d19c83da8b24ac174a1484c5c Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 6 Oct 2017 08:04:18 -0700 Subject: [PATCH 2/4] Better comments --- libraries/audio/src/AudioGate.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/audio/src/AudioGate.cpp b/libraries/audio/src/AudioGate.cpp index 30ebbab12a..deba3f8e58 100644 --- a/libraries/audio/src/AudioGate.cpp +++ b/libraries/audio/src/AudioGate.cpp @@ -183,12 +183,15 @@ void GateImpl::setHold(float hold) { hold = MAX(hold, 1.0f); hold = MIN(hold, 1000.0f); + // compute final tc _holdMin = msToTc(RELEASE, _sampleRate); + // compute tc increment, to progress from 0x7fffffff to _holdMin in PROGHOLD ms double progSamples = PROGHOLD/1000.0 * _sampleRate; _holdInc = (uint32_t)((0x7fffffff - _holdMin) / progSamples); _holdInc = MAX(_holdInc, 1); // prevent 0 on long releases + // compute initial tc, to progress from _holdMax to 0x7fffffff in hold ms double holdSamples = (double)hold/1000.0 * _sampleRate; _holdMax = 0x7fffffff + (uint32_t)(_holdInc * holdSamples); } From 4f193663495d2852d994b6801257f8ea4dcfc7cc Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Fri, 6 Oct 2017 08:05:55 -0700 Subject: [PATCH 3/4] Remove debug code --- libraries/audio/src/AudioGate.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/audio/src/AudioGate.cpp b/libraries/audio/src/AudioGate.cpp index deba3f8e58..ac72533806 100644 --- a/libraries/audio/src/AudioGate.cpp +++ b/libraries/audio/src/AudioGate.cpp @@ -323,8 +323,6 @@ void GateImpl::processHistogram(int numFrames) { // smooth threshold update _threshAdapt = threshold + MULQ31((_threshAdapt - threshold), tcThreshold); - - //printf("threshold = %0.1f\n", (_threshAdapt - (LOG2_HEADROOM_Q15 << LOG2_FRACBITS)) * -6.02f / (1 << LOG2_FRACBITS)); } // From b026a0461d77ee3f58b870dcac0ebc8e2ce02082 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 10 Oct 2017 09:13:06 -0700 Subject: [PATCH 4/4] Fix clang warnings for left-shift of signed int --- libraries/audio/src/AudioDynamics.h | 52 ++++++++++++++++------------- libraries/audio/src/AudioGate.cpp | 14 ++++---- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index b7c168bfab..6f36605025 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -135,6 +135,7 @@ static const int32_t exp2Table[1 << EXP2_TABBITS][3] = { static const int IEEE754_FABS_MASK = 0x7fffffff; static const int IEEE754_MANT_BITS = 23; +static const int IEEE754_EXPN_BITS = 8; static const int IEEE754_EXPN_BIAS = 127; // @@ -152,7 +153,7 @@ static inline int32_t peaklog2(float* input) { // split into e and x - 1.0 int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; - int32_t x = (peak << (31 - IEEE754_MANT_BITS)) & 0x7fffffff; + int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; // saturate if (e > 31) { @@ -191,7 +192,7 @@ static inline int32_t peaklog2(float* input0, float* input1) { // split into e and x - 1.0 int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; - int32_t x = (peak << (31 - IEEE754_MANT_BITS)) & 0x7fffffff; + int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; // saturate if (e > 31) { @@ -234,7 +235,7 @@ static inline int32_t peaklog2(float* input0, float* input1, float* input2, floa // split into e and x - 1.0 int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; - int32_t x = (peak << (31 - IEEE754_MANT_BITS)) & 0x7fffffff; + int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; // saturate if (e > 31) { @@ -259,30 +260,30 @@ static inline int32_t peaklog2(float* input0, float* input1, float* input2, floa // Count Leading Zeros // Emulates the CLZ (ARM) and LZCNT (x86) instruction // -static inline int CLZ(uint32_t x) { +static inline int CLZ(uint32_t u) { - if (x == 0) { + if (u == 0) { return 32; } int e = 0; - if (x < 0x00010000) { - x <<= 16; + if (u < 0x00010000) { + u <<= 16; e += 16; } - if (x < 0x01000000) { - x <<= 8; + if (u < 0x01000000) { + u <<= 8; e += 8; } - if (x < 0x10000000) { - x <<= 4; + if (u < 0x10000000) { + u <<= 4; e += 4; } - if (x < 0x40000000) { - x <<= 2; + if (u < 0x40000000) { + u <<= 2; e += 2; } - if (x < 0x80000000) { + if (u < 0x80000000) { e += 1; } return e; @@ -290,19 +291,19 @@ static inline int CLZ(uint32_t x) { // // Compute -log2(x) for x=[0,1] in Q31, result in Q26 -// x = 0 returns 0x7fffffff -// x < 0 undefined +// x <= 0 returns 0x7fffffff // static inline int32_t fixlog2(int32_t x) { - if (x == 0) { + if (x <= 0) { return 0x7fffffff; } // split into e and x - 1.0 - int e = CLZ((uint32_t)x); - x <<= e; // normalize to [0x80000000, 0xffffffff] - x &= 0x7fffffff; // x - 1.0 + uint32_t u = (uint32_t)x; + int e = CLZ(u); + u <<= e; // normalize to [0x80000000, 0xffffffff] + x = u & 0x7fffffff; // x - 1.0 int k = x >> (31 - LOG2_TABBITS); @@ -320,13 +321,18 @@ static inline int32_t fixlog2(int32_t x) { // // Compute exp2(-x) for x=[0,32] in Q26, result in Q31 -// x < 0 undefined +// x <= 0 returns 0x7fffffff // static inline int32_t fixexp2(int32_t x) { + if (x <= 0) { + return 0x7fffffff; + } + // split into e and 1.0 - x - int e = x >> LOG2_FRACBITS; - x = ~(x << LOG2_INTBITS) & 0x7fffffff; + uint32_t u = (uint32_t)x; + int e = u >> LOG2_FRACBITS; + x = ~(u << LOG2_INTBITS) & 0x7fffffff; int k = x >> (31 - EXP2_TABBITS); diff --git a/libraries/audio/src/AudioGate.cpp b/libraries/audio/src/AudioGate.cpp index ac72533806..5ef5ee25b5 100644 --- a/libraries/audio/src/AudioGate.cpp +++ b/libraries/audio/src/AudioGate.cpp @@ -40,7 +40,7 @@ class MonoDCBlock { public: void process(int32_t& x) { - x <<= 15; // scale to Q30 + x *= (1 << 15); // scale to Q30 x -= _dcOffset; // remove DC _dcOffset += x >> 13; // pole = (1.0 - 2^-13) = 0.9999 } @@ -53,8 +53,8 @@ class StereoDCBlock { public: void process(int32_t& x0, int32_t& x1) { - x0 <<= 15; - x1 <<= 15; + x0 *= (1 << 15); + x1 *= (1 << 15); x0 -= _dcOffset[0]; x1 -= _dcOffset[1]; @@ -71,10 +71,10 @@ class QuadDCBlock { public: void process(int32_t& x0, int32_t& x1, int32_t& x2, int32_t& x3) { - x0 <<= 15; - x1 <<= 15; - x2 <<= 15; - x3 <<= 15; + x0 *= (1 << 15); + x1 *= (1 << 15); + x2 *= (1 << 15); + x3 *= (1 << 15); x0 -= _dcOffset[0]; x1 -= _dcOffset[1];