From f8d15db9fc5d4105d2181f7821a340b4e0a21dee Mon Sep 17 00:00:00 2001 From: "Christian R. Helmrich" Date: Tue, 29 Dec 2020 01:00:22 +0100 Subject: [PATCH] 3-subband SBR mode --- src/lib/bitStreamWriter.cpp | 57 ++++++++++------ src/lib/exhaleLibPch.cpp | 133 +++++++++++++++++++++++++++--------- src/lib/exhaleLibPch.h | 12 ++-- src/lib/tempAnalysis.cpp | 26 +++++-- src/lib/tempAnalysis.h | 1 + 5 files changed, 167 insertions(+), 62 deletions(-) diff --git a/src/lib/bitStreamWriter.cpp b/src/lib/bitStreamWriter.cpp index 1d87ff8..f51049a 100644 --- a/src/lib/bitStreamWriter.cpp +++ b/src/lib/bitStreamWriter.cpp @@ -60,6 +60,19 @@ static uint32_t getDeltaCodeTimeFlag (const uint8_t* const alphaQCurr, const uns return (bitCountFreq > bitCountTime ? 1 : 0); } +static uint8_t getNumEnvBits (const int32_t int32Value, const uint8_t maxBitCount, const uint8_t minBitCount) +{ + uint8_t bits = __max (1, maxBitCount); + int32_t mask = 1 << (bits - 1); + + while (bits > minBitCount && (int32Value & mask) == 0) // get MSB + { + bits--; + mask >>= 1; + } + return bits; +} + static uint8_t getOptMsMaskModeValue (const uint8_t* const msUsed, const unsigned numWinGroups, const unsigned numSwbShort, const uint8_t msMaskMode, const unsigned maxSfbSte) { @@ -128,14 +141,12 @@ unsigned BitStreamWriter::writeChannelWiseSbrData (const int32_t* const sbrDataC #endif const bool couple = (((ch1 >> 23) & 1) != 0); unsigned bitCount = (stereo ? (couple ? 2 : 7 + nb) : 0) + 6 + nb; - unsigned i, envCh0, envCh1, resCh0, resCh1; // bs_num_env[], bs_freq_res[] + unsigned i, envCh0, envCh1; // bs_num_env[], 1 - 8 if (nb == 0) return 0; envCh0 = 1 << ((ch0 >> 21) & 3); - resCh0 = (ch0 >> 20) & 1; envCh1 = 1 << (((stereo && !couple ? ch1 : ch0) >> 21) & 3); - resCh1 = ((stereo && !couple ? ch1 : ch0) >> 20) & 1; if (stereo) m_auBitStream.write (couple ? 1 : 0, 1); // _coupling @@ -166,12 +177,14 @@ unsigned BitStreamWriter::writeChannelWiseSbrData (const int32_t* const sbrDataC for (i = 1; i <= envCh0; i++) // dt loop { const uint8_t bits = ((ch0 & (1 << (11 + i))) != 0 ? 2 : (res > 0 && envCh0 > 1 ? 6 : 7)); - const uint8_t bitd = (2 + 3 * resCh0) * 2; // differential, <25 TODO: VLC words + uint8_t nCodedBits = getNumEnvBits (sbrDataCh0[i], 8, bits); - m_auBitStream.write (sbrDataCh0[i] & 127, bits); // bs_data_env - bitCount += bits; - m_auBitStream.write ((sbrDataCh0[i] >> 7) & ((1 << bitd) - 1), bitd); - bitCount += bitd; + m_auBitStream.write (sbrDataCh0[i] & ((1 << nCodedBits) - 1), nCodedBits); // 1st env. + bitCount += nCodedBits; + nCodedBits = getNumEnvBits (sbrDataCh0[i], 32, 9) - 9; // avoid writing MSB delimiter + + m_auBitStream.write ((sbrDataCh0[i] >> 8) & ((1 << nCodedBits) - 1), nCodedBits); + bitCount += nCodedBits; #if ENABLE_INTERTES if (issTes) { @@ -191,12 +204,14 @@ unsigned BitStreamWriter::writeChannelWiseSbrData (const int32_t* const sbrDataC for (i = 1; i <= envCh1; i++) // decoup. sbr_envelope() dt loop { const uint8_t bits = ((ch1 & (1 << (11 + i))) != 0 ? 2 : (res > 0 && envCh1 > 1 ? 6 : 7)); - const uint8_t bitd = (2 + 3 * resCh1) * 2; // TODO: VLC words + uint8_t nCodedBits = getNumEnvBits (sbrDataCh1[i], 8, bits); - m_auBitStream.write (sbrDataCh1[i] & 127, bits); - bitCount += bits; - m_auBitStream.write ((sbrDataCh1[i] >> 7) & ((1 << bitd) - 1), bitd); - bitCount += bitd; + m_auBitStream.write (sbrDataCh1[i] & ((1 << nCodedBits) - 1), nCodedBits); + bitCount += nCodedBits; + nCodedBits = getNumEnvBits (sbrDataCh1[i], 32, 9) - 9; + + m_auBitStream.write ((sbrDataCh1[i] >> 8) & ((1 << nCodedBits) - 1), nCodedBits); + bitCount += nCodedBits; #if ENABLE_INTERTES if (issTes) { @@ -221,7 +236,7 @@ unsigned BitStreamWriter::writeChannelWiseSbrData (const int32_t* const sbrDataC bitCount += bits; if (nb == 4) { - m_auBitStream.write ((sbrDataCh0[9] >> (13 * i - 5)) & 31, 1); // TODO: VLC word + m_auBitStream.write ((sbrDataCh0[9] >> (13 * i - 5)) & 31, 1); bitCount++; } } @@ -233,12 +248,14 @@ unsigned BitStreamWriter::writeChannelWiseSbrData (const int32_t* const sbrDataC for (i = 1; i <= envCh1; i++) // coup. sbr_envelope() dt loop { const uint8_t bits = ((ch1 & (1 << (11 + i))) != 0 ? 1 : (res > 0 && envCh1 > 1 ? 5 : 6)); - const uint8_t bitd = (2 + 3 * resCh1) * 1; // TODO: VLC words + uint8_t nCodedBits = getNumEnvBits (sbrDataCh1[i], 8, bits); - m_auBitStream.write (sbrDataCh1[i] & 63, bits); - bitCount += bits; - m_auBitStream.write ((sbrDataCh1[i] >> 7) & ((1 << bitd) - 1), bitd); - bitCount += bitd; + m_auBitStream.write (sbrDataCh1[i] & ((1 << nCodedBits) - 1), nCodedBits); + bitCount += nCodedBits; + nCodedBits = getNumEnvBits (sbrDataCh1[i], 32, 9) - 9; + + m_auBitStream.write ((sbrDataCh1[i] >> 8) & ((1 << nCodedBits) - 1), nCodedBits); + bitCount += nCodedBits; #if ENABLE_INTERTES if (issTes) { @@ -262,7 +279,7 @@ unsigned BitStreamWriter::writeChannelWiseSbrData (const int32_t* const sbrDataC bitCount += bits; if (nb == 4) { - m_auBitStream.write ((sbrDataCh1[9] >> (13 * i - 5)) & 31, 1); // TODO: VLC word + m_auBitStream.write ((sbrDataCh1[9] >> (13 * i - 5)) & 31, 1); bitCount++; } } diff --git a/src/lib/exhaleLibPch.cpp b/src/lib/exhaleLibPch.cpp index 4b1e21f..a97b8f3 100644 --- a/src/lib/exhaleLibPch.cpp +++ b/src/lib/exhaleLibPch.cpp @@ -52,25 +52,79 @@ static const unsigned allowedSamplingRates[USAC_NUM_SAMPLE_RATES] = { 57600, 51200, 40000, 38400, 34150, 28800, 25600, 20000, 19200, 17075, 14400, 12800, 9600 // USAC }; -static int8_t quantizeSbrEnvelopeLevel (const uint64_t energy, const uint32_t divisor, const uint8_t noiseLevel) +// ISO/IEC 14496-3, Annex 4.A.6.1 +static const uint8_t deltaHuffSbrF[14] = {0xFB, 0x7C, 0x3C, 0x1C, 0x0C, 0x05, 0x01, 0x00, 0x04, 0x0D, 0x1D, 0x3D, 0xFA, 0xFC}; +static const uint8_t deltaHuffSbrT[14] = {0xFD, 0x7D, 0x3D, 0x1D, 0x0D, 0x05, 0x01, 0x00, 0x04, 0x0C, 0x1C, 0x3C, 0x7C, 0xFC}; + +// static SBR related functions +static int32_t getSbrDeltaBitCount (const int32_t delta, const bool dt) { - const double ener = (double) energy / (double) divisor; + return (delta == 5 && !dt ? 8 : abs (delta) + 2 + (delta >> 31)); +} + +static int32_t getSbrDeltaHuffCode (const int32_t delta, const bool dt) +{ + const unsigned u = __max (-7, __min (6, delta)) + 7; + + return int32_t (dt ? deltaHuffSbrT[u] : deltaHuffSbrF[u]); +} + +static int8_t getSbrQuantizedLevel (const double energy, const uint32_t divisor, const uint8_t noiseLevel) +{ + const double ener = energy / divisor; return (ener > 8192.0 ? int8_t (1.375 - 0.03125 * noiseLevel + 6.64385619 * log10 (ener)) - 26 : 0); } +static int32_t packSbr3BandQuantLevels (const uint64_t energy, const uint32_t divisor, const uint8_t noiseLevel, + const uint32_t ratioL, const uint32_t ratioM, const uint32_t ratioH) +{ + int8_t val[4] = {getSbrQuantizedLevel (ratioL * (double) energy, divisor * 6144, noiseLevel), + getSbrQuantizedLevel (ratioM * (double) energy, divisor * 6144, noiseLevel), + getSbrQuantizedLevel (ratioH * (double) energy, divisor * 6144, noiseLevel), 0}; + unsigned iMax = 0; + + val[3] = val[0]; // find last peak band having maximum value + if (val[3] <= val[1]) { iMax = 1; val[3] = val[1]; } + if (val[3] <= val[2]) { iMax = 2; } + + if (iMax > 0) // limit delta-value increases below peak band + { + if (val[iMax - 1] + 6 < val[iMax]) val[iMax - 1] = val[iMax] - 6; + if ((iMax == 2) && (val[0] + 6 < val[1])) val[0] = val[1] - 6; + } + if (iMax < 2) // limit delta-value decreases above peak band + { + if (val[iMax + 1] + 7 < val[iMax]) val[iMax + 1] = val[iMax] - 7; + if ((iMax == 0) && (val[2] + 7 < val[1])) val[2] = val[1] - 7; + } + val[1] = __max (val[1], __min (val[0], val[2])); + + return int32_t (val[0]) | (int32_t (val[1]) << 8) | (int32_t (val[2]) << 16); +} + +static bool useSbr3BandDeltaTimeCoding (const int32_t dataCurr, const int32_t dataPrev) +{ + const int8_t curr[3] = {dataCurr & SCHAR_MAX, (dataCurr >> 8) & SCHAR_MAX, (dataCurr >> 16) & SCHAR_MAX}; + const int8_t prev[3] = {dataPrev & SCHAR_MAX, (dataPrev >> 8) & SCHAR_MAX, (dataPrev >> 16) & SCHAR_MAX}; + int32_t bDf = 7, bDt = 0; + + for (unsigned u = 0; u < 3; u++) // check delta range, count + { + if ((curr[u] > prev[u] + 6) || (curr[u] < prev[u] - 7)) return false; + if (u > 0) bDf += getSbrDeltaBitCount (curr[u] - curr[u - 1], false); + /*deltaT*/ bDt += getSbrDeltaBitCount (curr[u] - prev[u], true); + } + + return (bDf > bDt); +} + // public SBR related functions int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat5b, const uint8_t tempFlat5b, const bool lr, const bool ind, const uint8_t specFlatSte, const int32_t tmpValSte, const uint32_t frameSize, int32_t* sbrData) { - const uint64_t enValue[8] = {(uint64_t) sbrLevels[22] * (uint64_t) sbrLevels[22], - (uint64_t) sbrLevels[23] * (uint64_t) sbrLevels[23], - (uint64_t) sbrLevels[24] * (uint64_t) sbrLevels[24], - (uint64_t) sbrLevels[25] * (uint64_t) sbrLevels[25], - (uint64_t) sbrLevels[26] * (uint64_t) sbrLevels[26], - (uint64_t) sbrLevels[27] * (uint64_t) sbrLevels[27], - (uint64_t) sbrLevels[28] * (uint64_t) sbrLevels[28], - (uint64_t) sbrLevels[11] * (uint64_t) sbrLevels[11]}; + const uint64_t enValue[8] = {square (sbrLevels[21]), square (sbrLevels[22]), square (sbrLevels[23]), square (sbrLevels[24]), + square (sbrLevels[25]), square (sbrLevels[26]), square (sbrLevels[27]), square (sbrLevels[10])}; const uint64_t envTmp0[1] = { enValue[0] + enValue[1] + enValue[2] + enValue[3] + enValue[4] + enValue[5] + enValue[6] + enValue[7]}; const uint64_t envTmp1[2] = {(enValue[0] + enValue[1] + enValue[2] + enValue[3]) << 1, @@ -79,9 +133,12 @@ int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat (enValue[4] + enValue[5]) << 2, (enValue[6] + enValue[7]) << 2}; const uint64_t envTmp3[8] = { enValue[0] << 3, enValue[1] << 3, enValue[2] << 3, enValue[3] << 3, enValue[4] << 3, enValue[5] << 3, enValue[6] << 3, enValue[7] << 3}; + const uint32_t env3BandsL = sbrLevels[28] & USHRT_MAX; + const uint32_t env3BandsM = sbrLevels[28] >> 16; + const uint32_t env3BandsH = sbrLevels[29] & USHRT_MAX; uint64_t errTmp[4] = {0, 0, 0, 0}; uint64_t errBest; - int32_t tmpBest; + int32_t tmpBest, bitCount, diff; uint8_t t; for (t = 0; t < 8; t++) // get energy errors due to temporal merging @@ -110,30 +167,28 @@ int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat /*Q*/if (tmpBest == 0) // quantized envelopes for optimal tmp value { - sbrData[0] = quantizeSbrEnvelopeLevel (envTmp0[0], frameSize, specFlat5b); + sbrData[0] = packSbr3BandQuantLevels (envTmp0[0], frameSize, specFlat5b, env3BandsL, env3BandsM, env3BandsH); } else if (tmpBest == 1) { - sbrData[0] = quantizeSbrEnvelopeLevel (envTmp1[0], frameSize, specFlat5b); - sbrData[1] = quantizeSbrEnvelopeLevel (envTmp1[1], frameSize, specFlat5b); + for (t = 0; t < 2; t++) + { + sbrData[t] = packSbr3BandQuantLevels (envTmp1[t], frameSize, specFlat5b, env3BandsL, env3BandsM, env3BandsH); + } } else if (tmpBest == 2) { - sbrData[0] = quantizeSbrEnvelopeLevel (envTmp2[0], frameSize, specFlat5b); - sbrData[1] = quantizeSbrEnvelopeLevel (envTmp2[1], frameSize, specFlat5b); - sbrData[2] = quantizeSbrEnvelopeLevel (envTmp2[2], frameSize, specFlat5b); - sbrData[3] = quantizeSbrEnvelopeLevel (envTmp2[3], frameSize, specFlat5b); + for (t = 0; t < 4; t++) + { + sbrData[t] = packSbr3BandQuantLevels (envTmp2[t], frameSize, specFlat5b, env3BandsL, env3BandsM, env3BandsH); + } } else // (tmpBest == 3) { - sbrData[0] = quantizeSbrEnvelopeLevel (envTmp3[0], frameSize, specFlat5b); - sbrData[1] = quantizeSbrEnvelopeLevel (envTmp3[1], frameSize, specFlat5b); - sbrData[2] = quantizeSbrEnvelopeLevel (envTmp3[2], frameSize, specFlat5b); - sbrData[3] = quantizeSbrEnvelopeLevel (envTmp3[3], frameSize, specFlat5b); - sbrData[4] = quantizeSbrEnvelopeLevel (envTmp3[4], frameSize, specFlat5b); - sbrData[5] = quantizeSbrEnvelopeLevel (envTmp3[5], frameSize, specFlat5b); - sbrData[6] = quantizeSbrEnvelopeLevel (envTmp3[6], frameSize, specFlat5b); - sbrData[7] = quantizeSbrEnvelopeLevel (envTmp3[7], frameSize, specFlat5b); + for (t = 0; t < 8; t++) + { + sbrData[t] = packSbr3BandQuantLevels (envTmp3[t], frameSize, specFlat5b, env3BandsL, env3BandsM, env3BandsH); + } } // quantized noise level for up to two temporal units, 30 = no noise @@ -151,16 +206,30 @@ int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat tmpBest <<= 21; // config bits for (t = 0; t < (1 << (tmpBest >> 21)); t++) { - const int32_t sbrEnvel = sbrData[t] & 127; - const int32_t d = sbrLevels[30] - sbrEnvel; // two length-2 words! + const int32_t curr = sbrData[t], prev = sbrLevels[30]; - if ((t > 0 || !ind) && (d == 0 || d == 1)) + if ((t > 0 /*|| !ind*/) && useSbr3BandDeltaTimeCoding (curr, prev)) { tmpBest |= 1 << (12 + t); // delta-time coding flag for envelope - sbrData[t] -= sbrEnvel; - sbrData[t] |= d | (d << 7) | (d << 9) | (d << 11) | (d << 13) | (d << 15); + + diff = (curr & SCHAR_MAX) - (prev & SCHAR_MAX); + sbrData[t] = getSbrDeltaHuffCode (diff, true); bitCount = 8; // see bitStreamWriter.cpp, ll. 186, 213 + diff = ((curr >> 8) & SCHAR_MAX) - ((prev >> 8) & SCHAR_MAX); + sbrData[t] |= getSbrDeltaHuffCode (diff, true) << bitCount; bitCount += getSbrDeltaBitCount (diff, true); + diff = ((curr >> 16) & SCHAR_MAX) - ((prev >> 16) & SCHAR_MAX); + sbrData[t] |= getSbrDeltaHuffCode (diff, true) << bitCount; bitCount += getSbrDeltaBitCount (diff, true); } - sbrLevels[30] = sbrEnvel; + else // delta-frequency coding + { + diff = curr & SCHAR_MAX; + sbrData[t] = diff; bitCount = 8; // first envelope is PCM coded + diff = ((curr >> 8) & SCHAR_MAX) - (curr & SCHAR_MAX); + sbrData[t] |= getSbrDeltaHuffCode (diff, false) << bitCount; bitCount += getSbrDeltaBitCount (diff, false); + diff = ((curr >> 16) & SCHAR_MAX) - ((curr >> 8) & SCHAR_MAX); + sbrData[t] |= getSbrDeltaHuffCode (diff, false) << bitCount; bitCount += getSbrDeltaBitCount (diff, false); + } + sbrData[t] |= 1 << bitCount; // MSB delimiter for bitstream writer + sbrLevels[30] = curr; } for (t = 0; t < ((tmpBest >> 21) == 0 ? 1 : 2); t++) { diff --git a/src/lib/exhaleLibPch.h b/src/lib/exhaleLibPch.h index 2e34573..a58ce04 100644 --- a/src/lib/exhaleLibPch.h +++ b/src/lib/exhaleLibPch.h @@ -14,7 +14,7 @@ #include // for .._MAX, .._MIN #include // for pow, sin, sqrt #include // for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t -#include // for abs, div, calloc, malloc, free, (__)max, (__)min, (s)rand +#include // for abs, calloc, malloc, free, (__)max, (__)min #include // for memcpy, memset #include // for std::vector <> @@ -67,10 +67,10 @@ typedef enum ELEM_TYPE : int8_t { ID_EL_UNDEF = -1, - ID_USAC_SCE = 0, // single-channel element (CCI_1_CH) - ID_USAC_CPE = 1, // channel-pair element (CCI_2_CH) - ID_USAC_LFE = 2, // low-frequency effects element (CCI_1_CH) with ONLY_LONG_SEQUENCE, no TNS - ID_USAC_EXT = 3 // extension element (not to be used here!) + ID_USAC_SCE = 0, // single-channel element + ID_USAC_CPE = 1, // channel-pair element + ID_USAC_LFE = 2, // low-frequency effects element with ONLY_LONG_SEQUENCE, no TNS + ID_USAC_EXT = 3 // extension element, not used } ELEM_TYPE; // window_sequence defines for ICS @@ -199,6 +199,8 @@ const uint8_t oneTwentyEightOver[14] = {0, 128, 64, 43, 32, 26, 22, 19, 16, 15, // public SBR related functions int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat5b, const uint8_t tempFlat5b, const bool lr, const bool ind, const uint8_t specFlatSte, const int32_t tmpValSte, const uint32_t frameSize, int32_t* sbrData); +inline uint64_t square (const int64_t i) { return i * i; } + // public sampling rate functions int8_t toSamplingFrequencyIndex (const unsigned samplingRate); unsigned toSamplingRate (const int8_t samplingFrequencyIndex); diff --git a/src/lib/tempAnalysis.cpp b/src/lib/tempAnalysis.cpp index 607dd29..816a837 100644 --- a/src/lib/tempAnalysis.cpp +++ b/src/lib/tempAnalysis.cpp @@ -102,6 +102,8 @@ TempAnalyzer::TempAnalyzer () m_pitchLagPrev[ch] = 0; m_tempAnaStats[ch] = 0; m_transientLoc[ch] = -1; + + memset (m_filtSampPrev[ch], 0, 6 * sizeof (int64_t)); } } @@ -163,6 +165,8 @@ unsigned TempAnalyzer::temporalAnalysis (const int32_t* const timeSignals[USAC_M /*LF*/int32_t* lrSig = &lrCoreTimeSignals[ch][resamplerOffset >> sbrShift]; const int32_t* hrSig = &timeSignals[ch][resamplerOffset]; /*MF*/uint64_t ue[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // unit energies + int64_t* const rPrev = m_filtSampPrev[ch]; + uint64_t subSumL = 0, subSumM = 0, subSumH = 0; for (int i = nSamplesInFrame >> sbrShift; i > 0; i--, lrSig++, hrSig += 2) { @@ -184,7 +188,15 @@ unsigned TempAnalyzer::temporalAnalysis (const int32_t* const timeSignals[USAC_M for (s = 127; s > 0; s--/*u = s*/) r += (hrSig[-s] + (int64_t) hrSig[s]) * lpfc34[s]; r = (r + (1 << 17)) >> 18; // SBR env. band-pass at quarter rate - ue[i >> 7] += uint64_t (r * r); + ue[i >> 7] += square (r); + + // calculate 3 SBR subband envelope energies (low, mid and high) + subSumL += square ((6 * rPrev[2] + 5 * (rPrev[1] + rPrev[3]) + 3 * (rPrev[0] + rPrev[4]) + (r + rPrev[5]) + 8) >> 4); + subSumM += square ((2 * rPrev[2] - (rPrev[0] + rPrev[4]) + 2) >> 2); + subSumH += square ((6 * rPrev[2] - 5 * (rPrev[1] + rPrev[3]) + 3 * (rPrev[0] + rPrev[4]) - (r + rPrev[5]) + 8) >> 4); + + rPrev[5] = rPrev[4]; rPrev[4] = rPrev[3]; rPrev[3] = rPrev[2]; + rPrev[2] = rPrev[1]; rPrev[1] = rPrev[0]; rPrev[0] = r; } } @@ -196,13 +208,17 @@ unsigned TempAnalyzer::temporalAnalysis (const int32_t* const timeSignals[USAC_M for (u = numUnits; u > 0; ) { ue[8] += ue[--u]; - hfrLevel[numUnits - u] = int32_t (0.5 + sqrt ((double) ue[u])); + hfrLevel[numUnits - 1 - u] = int32_t (0.5 + sqrt ((double) ue[u])); } - hfrLevel[0] = int32_t (0.5 + sqrt ((double) ue[8])); - // stabilize transient detection below - for (u = numUnits >> 1; u > 0; u--) + if (ue[8] < 1) ue[8] = 1; // low, mid, high subband energy ratios + hfrLevel[numUnits] = int32_t (0.5 + __min (USHRT_MAX, (16384.0 * subSumL) / ue[8])); + hfrLevel[numUnits] |= int32_t (0.5 + __min ( SHRT_MAX, (16384.0 * subSumM) / ue[8])) << 16; + hfrLevel[numUnits+1] = int32_t (0.5 + __min (USHRT_MAX, (16384.0 * subSumH) / ue[8])); + + for (u = numUnits >> 1; u > 0; ) // stabilize transient detection { + u--; if (maxHfrLevL < hfrLevel[u]) /* update max. */ maxHfrLevL = hfrLevel[u]; if (maxHfrLevR < hfrLevel[u + (numUnits >> 1)]) maxHfrLevR = hfrLevel[u + (numUnits >> 1)]; } diff --git a/src/lib/tempAnalysis.h b/src/lib/tempAnalysis.h index 3abc8c8..c9eabd1 100644 --- a/src/lib/tempAnalysis.h +++ b/src/lib/tempAnalysis.h @@ -27,6 +27,7 @@ private: int32_t m_maxHfLevPrev[USAC_MAX_NUM_CHANNELS]; unsigned m_maxIdxHpPrev[USAC_MAX_NUM_CHANNELS]; unsigned m_pitchLagPrev[USAC_MAX_NUM_CHANNELS]; + int64_t m_filtSampPrev[USAC_MAX_NUM_CHANNELS][6]; // for SBR subband calculation (NOTE: only approximate) uint32_t m_tempAnaStats[USAC_MAX_NUM_CHANNELS]; int16_t m_transientLoc[USAC_MAX_NUM_CHANNELS];