mirror of
https://gitlab.com/ecodis/exhale.git
synced 2025-01-21 11:25:47 +01:00
3-subband SBR mode
This commit is contained in:
parent
4002bff2bf
commit
f8d15db9fc
@ -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++;
|
||||
}
|
||||
}
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <limits.h> // for .._MAX, .._MIN
|
||||
#include <math.h> // for pow, sin, sqrt
|
||||
#include <stdint.h> // for (u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t
|
||||
#include <stdlib.h> // for abs, div, calloc, malloc, free, (__)max, (__)min, (s)rand
|
||||
#include <stdlib.h> // for abs, calloc, malloc, free, (__)max, (__)min
|
||||
#include <string.h> // for memcpy, memset
|
||||
#include <vector> // 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);
|
||||
|
@ -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)];
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user