SBR bit allocation

This commit is contained in:
Christian R. Helmrich 2020-11-20 22:00:00 +01:00
parent 6fe06fa78b
commit 5373500b9c
8 changed files with 148 additions and 105 deletions

View File

@ -25,9 +25,16 @@
<td valign="top">
<h1><br><span class="pink">exhale</span> - <span class="pink">e</span>codis e<span class="pink">x</span>tended <span class="pink">h</span>igh-efficiency <span class="pink">a</span>nd <span class="pink">l</span>ow-complexity <span class="pink">e</span>ncoder<br><span class="gray"><sup><br>Software Release Notes, Version History, Known Issues, Upcoming Feature Roadmap</sup></span><br><br></h1>
<h3>&nbsp; &nbsp;The version of this distribution of the &laquo;exhale&raquo; software release is <b>1.0.8</b> (official pub&shy;lic minor release) from October 2020. Please check <a href="http://www.ecodis.de/audio.htm#mpeg">www.ecodis.de</a> regularly for new versions of this software. A summary of each version up to this release, a list of known issues with this release, and a roadmap of additional functionality are provided below.</h3>
<h3>&nbsp; &nbsp;The version of this distribution of the &laquo;exhale&raquo; software release is <b>1.1RC</b> (preliminary pub&shy;lic major release) from Nov. 2020. Please check <a href="http://www.ecodis.de/audio.htm#mpeg">www.ecodis.de</a> regularly for new versions of this software. A summary of each version up to this release, a list of known issues with this release, and a roadmap of additional functionality are provided below.</h3>
<h3><br><b>Chronological Version History</b></h3>
<h3>&nbsp; &nbsp;Version <b>1.0.8 <span class="gray">&nbsp;Oct. 2020, this release</span></b></h3>
<h3>&nbsp; &nbsp;Version <b>1.1RC <span class="gray">Nov. 2020, this release</span></b></h3>
<ul>
<li><h3>addition of basic SBR functionality for lower-rate coding down to 18 kbps/channel</h3></li>
<li><h3>exhaleApp: add support for CVBR modes a&#x2014;g for encoding with SBR functionality</h3></li>
<li><h3>exhaleApp: show &laquo;ARM&raquo; in header and '-v' command on corresponding platforms</h3></li>
<li><h3>exhaleLib: basic 2:1 SBR encoding with ccfl = 2048, minor fixes and code cleanup</h3></li>
</ul>
<h3>&nbsp; &nbsp;Version <b>1.0.8 <span class="gray">&nbsp;Oct. 2020</span></b></h3>
<ul>
<li><h3>minor quality improvements at low and high rates, some license text clarifications</h3></li>
<li><h3>exhaleApp: slightly improved loudness calculation for low and high sampling rates</h3></li>
@ -111,7 +118,7 @@
<li><h3>exhaleLib: speed-ups and further quality tuning for difficult signals, as necessary.</h3></li>
</ul>
<h3><br></h3>
<h4><span class="gray">Written by C. R. Helmrich for exhale 1.0.8, Oct. 2020. Available at www.ecodis.de/exhale/release.htm.</span><br><br></h4>
<h4><span class="gray">Written by C. R. Helmrich for exhale 1.1RC, Nov. 2020. Available at www.ecodis.de/exhale/release.htm.</span><br><br></h4>
</td>
<td valign="top" colspan="2">

View File

@ -287,7 +287,9 @@ int main (const int argc, char* argv[])
if ((argc > 1) && (strcmp (argv[1], "-V") == 0 || strcmp (argv[1], "-v") == 0))
#endif
{
#if defined (_WIN64) || defined (WIN64) || defined (_LP64) || defined (__LP64__) || defined (__x86_64) || defined (__x86_64__)
#if defined (__arm__) || defined (__aarch64__) || defined (__arm64__)
fprintf_s (stdout, "exhale %s.%s%s (ARM",
#elif defined (_WIN64) || defined (WIN64) || defined (_LP64) || defined (__LP64__) || defined (__x86_64) || defined (__x86_64__)
fprintf_s (stdout, "exhale %s.%s%s (x64",
#else // 32-bit OS
fprintf_s (stdout, "exhale %s.%s%s (x86",
@ -347,7 +349,9 @@ int main (const int argc, char* argv[])
fprintf_s (stdout, EXHALE_TEXT_INIT "ncoder |\n");
#endif
fprintf_s (stdout, " | |\n");
#if defined (_WIN64) || defined (WIN64) || defined (_LP64) || defined (__LP64__) || defined (__x86_64) || defined (__x86_64__)
#if defined (__arm__) || defined (__aarch64__) || defined (__arm64__)
fprintf_s (stdout, " | version %s.%s%s (ARM, built on %s) - written by C.R.Helmrich |\n",
#elif defined (_WIN64) || defined (WIN64) || defined (_LP64) || defined (__LP64__) || defined (__x86_64) || defined (__x86_64__)
fprintf_s (stdout, " | version %s.%s%s (x64, built on %s) - written by C.R.Helmrich |\n",
#else // 32-bit OS
fprintf_s (stdout, " | version %s.%s%s (x86, built on %s) - written by C.R.Helmrich |\n",

View File

@ -418,7 +418,7 @@ unsigned BitAllocator::imprSfbStepSizes (const SfbGroupData* const groupData[USA
const unsigned firstChannelIndex, const uint8_t* const sfm, const bool commonWindow,
const uint8_t* const sfbStereoData /*= nullptr*/, const uint8_t stereoConfig /*= 0*/)
{
const uint8_t maxSfbL16k = 16 + __min (35, (9 << 17) / __max (1, samplingRate)); // SFB index at 15.8 kHz
const uint8_t maxSfbL16k = 16 + __min (4 + (samplingRate >> 10), (9 << 17) / __max (1, samplingRate)); // SFB index at 15.8 kHz
const uint32_t redFactor = __max ((samplingRate < 27713 ? 2 : 1), __min (3, m_rateIndex)) - (stereoConfig >> 3);
const uint32_t redWeight = __min (4, 9 - __min (9, m_rateIndex));
short* const tempCoeffs = (short* const) m_tempSfbValue;

View File

@ -768,7 +768,7 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s
const unsigned lfeChannelIndex = (m_channelConf >= CCI_6_CH ? __max (5, nChannels - 1) : USAC_MAX_NUM_CHANNELS);
const bool useMaxBandwidth = (samplingRate < 37566 || m_shiftValSBR > 0);
const uint32_t maxSfbLong = (useMaxBandwidth ? m_numSwbLong : brModeAndFsToMaxSfbLong (m_bitRateMode, samplingRate));
const uint32_t scaleSBR = (m_shiftValSBR > 0 ? 8 : 0); // reduces core rate by 25 %
const uint32_t scaleSBR = (m_shiftValSBR > 0 || m_nonMpegExt ? (samplingRate < 23004 || m_bitRateMode == 0 ? 8 : 6 + ((m_bitRateMode + 1) >> 2)) : 0); // -25% rate
const uint64_t scaleSr = (samplingRate < 27713 ? (samplingRate < 23004 ? 32 : 34) - __min (3 << m_shiftValSBR, m_bitRateMode)
: (samplingRate < 37566 && m_bitRateMode != 3u ? 36 : 37)) - (nChannels >> 1);
const uint64_t scaleBr = (m_bitRateMode == 0 ? __min (32, 3 + (samplingRate >> 10) + (samplingRate >> 13) - (nChannels >> 1))
@ -926,8 +926,8 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s
}
else memset (coreConfig.stereoDataCurr, 0, (MAX_NUM_SWB_SHORT * NUM_WINDOW_GROUPS) * sizeof (uint8_t));
errorValue |= m_bitAllocator.imprSfbStepSizes (m_scaleFacData, m_numSwbShort, m_mdctSignals, nSamplesInFrame,
nrChannels, samplingRate, sfbStepSizes, ci, meanSpecFlat,
errorValue |= m_bitAllocator.imprSfbStepSizes (m_scaleFacData, m_numSwbShort, m_mdctSignals, nSamplesInFrame, nrChannels,
((32 + 5 * m_shiftValSBR) * samplingRate) >> 5, sfbStepSizes, ci, meanSpecFlat,
coreConfig.commonWindow, coreConfig.stereoDataCurr, coreConfig.stereoConfig);
for (unsigned ch = 0; ch < nrChannels; ch++) // channel loop
@ -1301,9 +1301,13 @@ unsigned ExhaleEncoder::quantizationCoding () // apply MDCT quantization and en
// NOTE: gap-filling SFB bit count might be inaccurate now since scale factors changed
if (coreConfig.specFillData[ch] == 1) errorValue |= 1;
#endif
s = ci + nrChannels - 1 - 2 * ch; // other channel in stereo
if ((coreConfig.elementType < ID_USAC_LFE) && (m_shiftValSBR > 0)) // collect SBR data
{
const uint8_t msfVal = (shortWinPrev ? 31 : __max (2, __max (m_meanFlatPrev[ci], meanSpecFlat[ci]) >> 3));
const uint8_t msfVal = (shortWinPrev ? 31 : __max (2, __max (m_meanSpecPrev[ci], meanSpecFlat[ci]) >> 3));
const uint8_t msfSte = (coreConfig.stereoMode == 0 ? 0 : (coreConfig.icsInfoPrev[s + ch - ci].windowSequence ==
EIGHT_SHORT ? 31 : __max (2, __max (m_meanSpecPrev[s ], meanSpecFlat[s ]) >> 3)));
int32_t tmpValSynch = 0;
memset (m_coreSignals[ci], 0, 10 * sizeof (int32_t));
#if ENABLE_INTERTES
@ -1312,86 +1316,21 @@ unsigned ExhaleEncoder::quantizationCoding () // apply MDCT quantization and en
m_coreSignals[ci][0] = (shortWinPrev ? 0 : 1) << 20; // bs_freq_res = low resp. high
#endif
m_coreSignals[ci][0] |= 4 - int32_t (sqrt (0.75 * msfVal)); // filter mode, 0 = none
#if 1
// TODO: start putting into function
int32_t* const sbrLevel = &m_coreSignals[ci][nSamplesTempAna - 64 + nSamplesInFrame];
uint64_t enValues[8] = {(uint64_t) sbrLevel[22] * (uint64_t) sbrLevel[22], (uint64_t) sbrLevel[23] * (uint64_t) sbrLevel[23],
(uint64_t) sbrLevel[24] * (uint64_t) sbrLevel[24], (uint64_t) sbrLevel[25] * (uint64_t) sbrLevel[25],
(uint64_t) sbrLevel[26] * (uint64_t) sbrLevel[26], (uint64_t) sbrLevel[27] * (uint64_t) sbrLevel[27],
(uint64_t) sbrLevel[28] * (uint64_t) sbrLevel[28], (uint64_t) sbrLevel[11] * (uint64_t) sbrLevel[11]};
uint64_t envTmp0[1] = { enValues[0] + enValues[1] + enValues[2] + enValues[3] +
enValues[4] + enValues[5] + enValues[6] + enValues[7]};
uint64_t envTmp1[2] = {(enValues[0] + enValues[1] + enValues[2] + enValues[3]) << 1,
(enValues[4] + enValues[5] + enValues[6] + enValues[7]) << 1};
uint64_t envTmp2[4] = {(enValues[0] + enValues[1]) << 2, (enValues[2] + enValues[3]) << 2,
(enValues[4] + enValues[5]) << 2, (enValues[6] + enValues[7]) << 2};
uint64_t envTmp3[8] = { enValues[0] << 3, enValues[1] << 3, enValues[2] << 3, enValues[3] << 3,
enValues[4] << 3, enValues[5] << 3, enValues[6] << 3, enValues[7] << 3};
uint64_t errTmp[4] = {0, 0, 0, 0};
uint64_t errBest;
int32_t tmpBest;
for (int unit = 0; unit < 8; unit++)
if (ch > 0 && coreConfig.stereoMode > 0) // synch. sbr_grid(), sbr_invf() for stereo
{
const int64_t ref = enValues[unit] << 3;
errTmp[0] += abs ((int64_t) envTmp0[unit >> 3] - ref); // abs() since
errTmp[1] += abs ((int64_t) envTmp1[unit >> 2] - ref); // both values
errTmp[2] += abs ((int64_t) envTmp2[unit >> 1] - ref); // are already
errTmp[3] += abs ((int64_t) envTmp3[unit >> 0] - ref); // squares
tmpValSynch = (m_coreSignals[ci - 1][0] >> 21) & 3; // nEnv, bits 23-22
m_coreSignals[ci][0] |= m_coreSignals[ci - 1][0] & 0x10000F; // bits 21
m_coreSignals[ci - 1][0] |= m_coreSignals[ci][0] & 0x10000F; // and 4-1
}
errBest = errTmp[0]; // find tmp value providing minimal weighted error
tmpBest = 0;
for (uint8_t t = 1; t < 3; t++)
m_coreSignals[ci][0] |= getSbrEnvelopeAndNoise (&m_coreSignals[ci][nSamplesTempAna - 64 + nSamplesInFrame], msfVal,
__max (m_meanTempPrev[ci], meanTempFlat[ci]) >> 3, m_bitRateMode == 0,
msfSte, tmpValSynch, nSamplesInFrame, &m_coreSignals[ci][1]) << 21;
if (ch + 1 == nrChannels) // update the flatness histories
{
if ((errTmp[t] << t) < errBest)
{
errBest = errTmp[t] << t;
tmpBest = t;
}
m_meanSpecPrev[ci] = meanSpecFlat[ci]; m_meanSpecPrev[s] = meanSpecFlat[s];
m_meanTempPrev[ci] = meanTempFlat[ci]; m_meanTempPrev[s] = meanTempFlat[s];
}
if ((errBest >> 3) > envTmp0[0]) tmpBest = (m_bitRateMode == 0 ? 2 : 3);
/*quant.*/ if (tmpBest == 0)
{
m_coreSignals[ci][1] = quantizeSbrEnvelopeLevel (envTmp0[0], nSamplesInFrame, msfVal);
}
else if (tmpBest == 1)
{
m_coreSignals[ci][1] = quantizeSbrEnvelopeLevel (envTmp1[0], nSamplesInFrame, msfVal);
m_coreSignals[ci][2] = quantizeSbrEnvelopeLevel (envTmp1[1], nSamplesInFrame, msfVal);
}
else if (tmpBest == 2)
{
m_coreSignals[ci][1] = quantizeSbrEnvelopeLevel (envTmp2[0], nSamplesInFrame, msfVal);
m_coreSignals[ci][2] = quantizeSbrEnvelopeLevel (envTmp2[1], nSamplesInFrame, msfVal);
m_coreSignals[ci][3] = quantizeSbrEnvelopeLevel (envTmp2[2], nSamplesInFrame, msfVal);
m_coreSignals[ci][4] = quantizeSbrEnvelopeLevel (envTmp2[3], nSamplesInFrame, msfVal);
}
else // (tmpBest == 3)
{
m_coreSignals[ci][1] = quantizeSbrEnvelopeLevel (envTmp3[0], nSamplesInFrame, msfVal);
m_coreSignals[ci][2] = quantizeSbrEnvelopeLevel (envTmp3[1], nSamplesInFrame, msfVal);
m_coreSignals[ci][3] = quantizeSbrEnvelopeLevel (envTmp3[2], nSamplesInFrame, msfVal);
m_coreSignals[ci][4] = quantizeSbrEnvelopeLevel (envTmp3[3], nSamplesInFrame, msfVal);
m_coreSignals[ci][5] = quantizeSbrEnvelopeLevel (envTmp3[4], nSamplesInFrame, msfVal);
m_coreSignals[ci][6] = quantizeSbrEnvelopeLevel (envTmp3[5], nSamplesInFrame, msfVal);
m_coreSignals[ci][7] = quantizeSbrEnvelopeLevel (envTmp3[6], nSamplesInFrame, msfVal);
m_coreSignals[ci][8] = quantizeSbrEnvelopeLevel (envTmp3[7], nSamplesInFrame, msfVal);
}
m_coreSignals[ci][9] = ((int32_t) msfVal << 13) | ((int32_t) msfVal << 26); // noise level(s), 31 = none
# if ENABLE_INTERTES
// m_auBitStream.write ((m_coreSignals[ci][9] >> (i=0..(1 << tmpBest)-1)) & 1, 1); // bs_temp_shape[ch][env=i]
# endif
memcpy (&sbrLevel[20], &sbrLevel[10] /*last*/, 10 * sizeof (int32_t));
memcpy (&sbrLevel[10], sbrLevel /*& current*/, 10 * sizeof (int32_t)); // delay line
// TODO: end putting into function
#endif
m_coreSignals[ci][0] |= tmpBest /* TODO: call function here, returning tmpBest */ << 21;
m_meanFlatPrev[ci] = meanSpecFlat[ci];
}
ci++;
}
@ -1937,7 +1876,8 @@ ExhaleEncoder::ExhaleEncoder (int32_t* const inputPcmData, unsigned ch
m_mdctQuantMag[ch] = nullptr;
m_mdctSignals[ch] = nullptr;
m_mdstSignals[ch] = nullptr;
m_meanFlatPrev[ch] = 0;
m_meanSpecPrev[ch] = 0;
m_meanTempPrev[ch] = 0;
m_scaleFacData[ch] = nullptr;
m_specAnaCurr[ch] = 0;
m_specFlatPrev[ch] = 0;

View File

@ -79,7 +79,8 @@ private:
uint8_t* m_mdctQuantMag[USAC_MAX_NUM_CHANNELS];
int32_t* m_mdctSignals[USAC_MAX_NUM_CHANNELS];
int32_t* m_mdstSignals[USAC_MAX_NUM_CHANNELS];
uint8_t m_meanFlatPrev[USAC_MAX_NUM_CHANNELS];
uint8_t m_meanSpecPrev[USAC_MAX_NUM_CHANNELS]; // for
uint8_t m_meanTempPrev[USAC_MAX_NUM_CHANNELS]; // SBR
#if !RESTRICT_TO_AAC
bool m_noiseFilling[USAC_MAX_NUM_ELEMENTS];
bool m_nonMpegExt;

View File

@ -52,14 +52,105 @@ static const unsigned allowedSamplingRates[USAC_NUM_SAMPLE_RATES] = {
57600, 51200, 40000, 38400, 34150, 28800, 25600, 20000, 19200, 17075, 14400, 12800, 9600 // USAC
};
// public SBR related functions
int8_t quantizeSbrEnvelopeLevel (const uint64_t energy, const unsigned divisor, const uint8_t noiseLevel)
static int8_t quantizeSbrEnvelopeLevel (const uint64_t energy, const uint32_t divisor, const uint8_t noiseLevel)
{
const double ener = (double) energy / (double) divisor;
return (ener > 8192.0 ? int8_t (1.375 - 0.03125 * noiseLevel + 6.64385619 * log10 (ener)) - 26 : 0);
}
// public SBR related functions
int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat5b, const uint8_t tempFlat5b, const bool lowBitRateMode,
const uint8_t specFlatSte, const int32_t tmpValSte, const uint32_t frameSize, int32_t* sbrArray)
{
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 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,
(enValue[4] + enValue[5] + enValue[6] + enValue[7]) << 1};
const uint64_t envTmp2[4] = {(enValue[0] + enValue[1]) << 2, (enValue[2] + enValue[3]) << 2,
(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};
uint64_t errTmp[4] = {0, 0, 0, 0};
uint64_t errBest;
int32_t tmpBest;
uint8_t t;
for (t = 0; t < 8; t++) // get energy errors due to temporal merging
{
const int64_t ref = enValue[t] << 3;
errTmp[0] += abs ((int64_t) envTmp0[t >> 3] - ref); // abs() since
errTmp[1] += abs ((int64_t) envTmp1[t >> 2] - ref); // both values
errTmp[2] += abs ((int64_t) envTmp2[t >> 1] - ref); // are already
errTmp[3] += abs ((int64_t) envTmp3[t >> 0] - ref); // squares
}
errBest = errTmp[0];
tmpBest = 0;
for (t = 1; t < 3; t++) // find tmp value for minimal weighted error
{
if ((errTmp[t] << t) < errBest)
{
errBest = errTmp[t] << t;
tmpBest = t;
}
}
if ((errBest >> 3) > envTmp0[0]) tmpBest = (lowBitRateMode ? 2 : 3);
if (tmpBest < tmpValSte) tmpBest = tmpValSte;
/*Q*/if (tmpBest == 0) // quantized envelopes for optimal tmp value
{
sbrArray[0] = quantizeSbrEnvelopeLevel (envTmp0[0], frameSize, specFlat5b);
}
else if (tmpBest == 1)
{
sbrArray[0] = quantizeSbrEnvelopeLevel (envTmp1[0], frameSize, specFlat5b);
sbrArray[1] = quantizeSbrEnvelopeLevel (envTmp1[1], frameSize, specFlat5b);
}
else if (tmpBest == 2)
{
sbrArray[0] = quantizeSbrEnvelopeLevel (envTmp2[0], frameSize, specFlat5b);
sbrArray[1] = quantizeSbrEnvelopeLevel (envTmp2[1], frameSize, specFlat5b);
sbrArray[2] = quantizeSbrEnvelopeLevel (envTmp2[2], frameSize, specFlat5b);
sbrArray[3] = quantizeSbrEnvelopeLevel (envTmp2[3], frameSize, specFlat5b);
}
else // (tmpBest == 3)
{
sbrArray[0] = quantizeSbrEnvelopeLevel (envTmp3[0], frameSize, specFlat5b);
sbrArray[1] = quantizeSbrEnvelopeLevel (envTmp3[1], frameSize, specFlat5b);
sbrArray[2] = quantizeSbrEnvelopeLevel (envTmp3[2], frameSize, specFlat5b);
sbrArray[3] = quantizeSbrEnvelopeLevel (envTmp3[3], frameSize, specFlat5b);
sbrArray[4] = quantizeSbrEnvelopeLevel (envTmp3[4], frameSize, specFlat5b);
sbrArray[5] = quantizeSbrEnvelopeLevel (envTmp3[5], frameSize, specFlat5b);
sbrArray[6] = quantizeSbrEnvelopeLevel (envTmp3[6], frameSize, specFlat5b);
sbrArray[7] = quantizeSbrEnvelopeLevel (envTmp3[7], frameSize, specFlat5b);
}
// quantized noise level for up to two temporal units, 31 = no noise
t = __max (specFlat5b, specFlatSte);
sbrArray[8] = ((int32_t) t << 13) | ((int32_t) t << 26);
#if ENABLE_INTERTES
if ((t < 12) && (tempFlat5b > (lowBitRateMode ? 15 : 26)) && (tmpBest < 3))
{
sbrArray[8] |= (1 << (1 << tmpBest)) - 1; // TODO: inter-TES mode = inv. filter mode
}
#endif
memcpy (&sbrLevels[20], &sbrLevels[10] /*last*/, 10 * sizeof (int32_t)); // update the
memcpy (&sbrLevels[10], sbrLevels /*& current*/, 10 * sizeof (int32_t)); // delay line
return tmpBest;
}
// public sampling rate functions
int8_t toSamplingFrequencyIndex (const unsigned samplingRate)
{

View File

@ -178,27 +178,27 @@ const uint8_t eightTimesSqrt256Minus[256] = {
static const uint8_t elementCountConfig[USAC_MAX_NUM_ELCONFIGS] = {0, 1, 1, 2, 3, 3, 4, 5, 2, 2, 2, 5, 5};
static const ELEM_TYPE elementTypeConfig[USAC_MAX_NUM_ELCONFIGS][USAC_MAX_NUM_ELEMENTS] = {
{ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_UNDEF
{ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_1_CH
{ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_2_CH
{ID_USAC_SCE, ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_3_CH
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_4_CH
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_5_CH
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_LFE, ID_EL_UNDEF}, // CCI_6_CH
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_LFE}, // CCI_8_CH
{ID_USAC_SCE, ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_2_CHM
{ID_USAC_CPE, ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_3_CHR
{ID_USAC_CPE, ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF}, // CCI_4_CHR
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_SCE, ID_USAC_LFE}, // CCI_7_CH
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_LFE} // CCI_8_CHM
{ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_SCE, ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_LFE, ID_EL_UNDEF},
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_LFE},
{ID_USAC_SCE, ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_CPE, ID_USAC_SCE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_CPE, ID_USAC_CPE, ID_EL_UNDEF, ID_EL_UNDEF, ID_EL_UNDEF},
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_SCE, ID_USAC_LFE},
{ID_USAC_SCE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_CPE, ID_USAC_LFE}
};
// fast calculation of x / den: (x * oneTwentyEightOver[den]) >> 7, accurate for 0 <= x <= 162
const uint8_t oneTwentyEightOver[14] = {0, 128, 64, 43, 32, 26, 22, 19, 16, 15, 13, 12, 11, 10};
// public SBR related functions
int8_t quantizeSbrEnvelopeLevel (const uint64_t energy, const unsigned divisor, const uint8_t noiseLevel);
int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat5b, const uint8_t tempFlat5b, const bool lowBitRateMode,
const uint8_t specFlatSte, const int32_t tmpValSte, const uint32_t frameSize, int32_t* sbrArray);
// public sampling rate functions
int8_t toSamplingFrequencyIndex (const unsigned samplingRate);
unsigned toSamplingRate (const int8_t samplingFrequencyIndex);

View File

@ -344,7 +344,7 @@ unsigned TempAnalyzer::temporalAnalysis (const int32_t* const timeSignals[USAC_M
m_tempAnaStats[ch] = packAvgTempAnalysisStats (sumAbsHpL, sumAbsHpR, m_avgAbsHpPrev[ch],
sumAbsPpL + sumAbsPpR, maxAbsValL + maxAbsValR);
u = maxAbsValR;
if ((m_maxHfLevPrev[ch] < (maxHfrLevL >> 3)) || (maxHfrLevL < (maxHfrLevR >> 3))) // transient
if ((m_maxHfLevPrev[ch] < (maxHfrLevL >> 4)) || (maxHfrLevL < (maxHfrLevR >> 4))) // transient
{
maxAbsValL = maxHfrLevL;
maxAbsValR = maxHfrLevR;