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 13c794b923..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]; @@ -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,18 +177,23 @@ 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); hold = MIN(hold, 1000.0f); + // compute final tc _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); + // 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); } // @@ -318,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)); } // @@ -336,10 +339,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 {