diff --git a/include/Release.htm b/include/Release.htm
index a88ce70..9a2d9cb 100644
--- a/include/Release.htm
+++ b/include/Release.htm
@@ -25,9 +25,16 @@
exhale - ecodis extended high-efficiency and low-complexity encoder
Software Release Notes, Version History, Known Issues, Upcoming Feature Roadmap
- The version of this distribution of the «exhale» software release is 1.0.8 (official public minor release) from October 2020. Please check www.ecodis.de 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.
+ The version of this distribution of the «exhale» software release is 1.1RC (preliminary public major release) from Nov. 2020. Please check www.ecodis.de 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.
Chronological Version History
- Version 1.0.8 Oct. 2020, this release
+ Version 1.1RC Nov. 2020, this release
+
+ addition of basic SBR functionality for lower-rate coding down to 18 kbps/channel
+ exhaleApp: add support for CVBR modes a—g for encoding with SBR functionality
+ exhaleApp: show «ARM» in header and '-v' command on corresponding platforms
+ exhaleLib: basic 2:1 SBR encoding with ccfl = 2048, minor fixes and code cleanup
+
+ Version 1.0.8 Oct. 2020
minor quality improvements at low and high rates, some license text clarifications
exhaleApp: slightly improved loudness calculation for low and high sampling rates
@@ -111,7 +118,7 @@
exhaleLib: speed-ups and further quality tuning for difficult signals, as necessary.
-Written by C. R. Helmrich for exhale 1.0.8, Oct. 2020. Available at www.ecodis.de/exhale/release.htm.
+Written by C. R. Helmrich for exhale 1.1RC, Nov. 2020. Available at www.ecodis.de/exhale/release.htm.
|
diff --git a/src/app/exhaleApp.cpp b/src/app/exhaleApp.cpp
index 0ed3295..3c2bf25 100644
--- a/src/app/exhaleApp.cpp
+++ b/src/app/exhaleApp.cpp
@@ -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",
diff --git a/src/lib/bitAllocation.cpp b/src/lib/bitAllocation.cpp
index 5d06367..6189ba5 100644
--- a/src/lib/bitAllocation.cpp
+++ b/src/lib/bitAllocation.cpp
@@ -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;
diff --git a/src/lib/exhaleEnc.cpp b/src/lib/exhaleEnc.cpp
index 799839f..8201a2f 100644
--- a/src/lib/exhaleEnc.cpp
+++ b/src/lib/exhaleEnc.cpp
@@ -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;
diff --git a/src/lib/exhaleEnc.h b/src/lib/exhaleEnc.h
index 0cb4fd2..d88b11a 100644
--- a/src/lib/exhaleEnc.h
+++ b/src/lib/exhaleEnc.h
@@ -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;
diff --git a/src/lib/exhaleLibPch.cpp b/src/lib/exhaleLibPch.cpp
index dd0a4c5..8ecaea8 100644
--- a/src/lib/exhaleLibPch.cpp
+++ b/src/lib/exhaleLibPch.cpp
@@ -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)
{
diff --git a/src/lib/exhaleLibPch.h b/src/lib/exhaleLibPch.h
index 8ccaa4c..ce10451 100644
--- a/src/lib/exhaleLibPch.h
+++ b/src/lib/exhaleLibPch.h
@@ -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);
diff --git a/src/lib/tempAnalysis.cpp b/src/lib/tempAnalysis.cpp
index b4a6a8a..baac0e6 100644
--- a/src/lib/tempAnalysis.cpp
+++ b/src/lib/tempAnalysis.cpp
@@ -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;
|