rate reduction, speedup

This commit is contained in:
Christian R. Helmrich
2020-06-10 01:00:00 +02:00
parent 63b919d242
commit 119fa691eb
5 changed files with 71 additions and 42 deletions

View File

@@ -253,24 +253,29 @@ static const uint16_t arithCumFreqR[3][4] = { // arith_cf_r
{10827, 6884, 2929, 0} {10827, 6884, 2929, 0}
}; };
static const uint8_t arithFastPkIndex[32] = {
1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 58, 3, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62
};
// static helper functions // static helper functions
static inline unsigned arithGetPkIndex (const unsigned ctx) // cumul. frequency table index pki = arith_get_pk(c) static inline unsigned arithGetPkIndex (const unsigned ctx) // cumul. frequency table index pki = arith_get_pk(c)
{ {
int iMax = ARITH_SIZE - 1; if ((ctx & 0xEEEEE) == 0) return arithFastPkIndex[((ctx >> 12) & 16) | ((ctx >> 9) & 8) | ((ctx >> 6) & 4) | ((ctx >> 3) & 2) | (ctx & 1)];
int iMin = -1;
int i = iMin;
uint32_t j, k;
while (iMax > iMin + 1) int32_t iMax = ARITH_SIZE - 1;
int32_t iMin = -1;
do
{ {
i = iMin + ((iMax - iMin) >> 1); const int32_t i = iMin + ((iMax - iMin) >> 1);
j = arithHashM[i]; const uint32_t j = arithHashM[i];
k = j >> 8; const uint32_t k = j >> 8;
if (ctx < k) iMax = i; if (ctx < k) iMax = i;
else if (ctx > k) iMin = i; else if (ctx > k) iMin = i;
else return j & UCHAR_MAX; else return j & UCHAR_MAX;
} }
while (iMax > iMin + 1);
return arithLookupM[iMax]; // pki return arithLookupM[iMax]; // pki
} }
@@ -415,10 +420,9 @@ void EntropyCoder::arithSetContext (const unsigned newCtxState, const uint16_t s
{ {
m_csCurr = newCtxState; m_csCurr = newCtxState;
m_acBits = (m_csCurr >> 17) & 31; m_acBits = (m_csCurr >> 17) & 31;
for (uint16_t s = 1; s < 4; s++) if (sigEnd > 0) m_qcCurr[sigEnd - 1] = (m_csCurr >> 22) & 0xF;
{ if (sigEnd > 1) m_qcCurr[sigEnd - 2] = (m_csCurr >> 26) & 0xF;
if (sigEnd >= s) m_qcCurr[sigEnd - s] = (m_csCurr >> (18 + 4 * s)) & 0xF; if (sigEnd > 2) m_qcCurr[sigEnd - 3] = (m_csCurr >> 30);
}
} }
#endif #endif
@@ -466,7 +470,7 @@ unsigned EntropyCoder::arithCodeSigMagn (const uint8_t* const magn, const uint16
while ((i >= 0) && ((a[i] | b[i]) == 0)) i -= 2; while ((i >= 0) && ((a[i] | b[i]) == 0)) i -= 2;
i = (sigOffset + i + 2) >> 1; i = (sigOffset + i + 2) >> 1;
if (i + 28 < (int) sigEnd) sigEnd = (uint16_t) i; if (i + 26 < (int) sigEnd) sigEnd = (uint16_t) i;
} }
for (uint16_t s = sigOffset >> 1; s < sigEnd; s++) for (uint16_t s = sigOffset >> 1; s < sigEnd; s++)
@@ -523,11 +527,9 @@ unsigned EntropyCoder::arithCodeSigMagn (const uint8_t* const magn, const uint16
else else
{ {
m_csCurr = 0; m_csCurr = 0;
if (sigEnd > 0) m_csCurr |= m_qcCurr[sigEnd - 1] << 22;
for (uint16_t s = 1; s < 4; s++) if (sigEnd > 1) m_csCurr |= m_qcCurr[sigEnd - 2] << 26;
{ if (sigEnd > 2) m_csCurr |= __min (3, m_qcCurr[sigEnd - 3]) << 30;
if (sigEnd >= s) m_csCurr |= __min (255u >> (2 * s), m_qcCurr[sigEnd - s]) << (18 + 4 * s);
}
} }
m_csCurr |= ((unsigned) m_acBits << 17) | c; m_csCurr |= ((unsigned) m_acBits << 17) | c;

View File

@@ -982,7 +982,8 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s
#if !RESTRICT_TO_AAC #if !RESTRICT_TO_AAC
if ((maxSfbCh > 0) && m_noiseFilling[el] && (m_bitRateMode <= 3 || !eightShorts)) if ((maxSfbCh > 0) && m_noiseFilling[el] && (m_bitRateMode <= 3 || !eightShorts))
{ {
const uint8_t numSwbFrame = __min (numSwbCh, (eightShorts ? maxSfbCh : maxSfbLong) + (m_bitRateMode > 3 || samplingRate < 37566 ? 0 : 1)); const uint8_t numSwbFrame = __min (numSwbCh, (eightShorts ? maxSfbCh : maxSfbLong) +
(m_bitRateMode < 2 || m_bitRateMode > 3 || samplingRate < 37566 ? 0 : 1));
#ifndef NO_DTX_MODE #ifndef NO_DTX_MODE
const bool prvEightShorts = (coreConfig.icsInfoPrev[ch].windowSequence == EIGHT_SHORT); const bool prvEightShorts = (coreConfig.icsInfoPrev[ch].windowSequence == EIGHT_SHORT);
@@ -1287,9 +1288,9 @@ unsigned ExhaleEncoder::quantizationCoding () // apply MDCT quantization and en
memcpy (arithTuples, m_tempIntBuf, (nSamplesInFrame >> 1) * sizeof (char)); memcpy (arithTuples, m_tempIntBuf, (nSamplesInFrame >> 1) * sizeof (char));
entrCoder.setIsShortWindow (shortWinPrev); entrCoder.setIsShortWindow (shortWinPrev);
#if !RESTRICT_TO_AAC #if !RESTRICT_TO_AAC
// obtain channel-wise noise_level and noise_offset for USAC s = 22050 + 7350 * m_bitRateMode; // compute channel-wise noise_level and noise_offset
coreConfig.specFillData[ch] = (!m_noiseFilling[el] ? 0 : m_specGapFiller.getSpecGapFillParams (m_sfbQuantizer, m_mdctQuantMag[ci], coreConfig.specFillData[ch] = (!m_noiseFilling[el] ? 0 : m_specGapFiller.getSpecGapFillParams (m_sfbQuantizer, m_mdctQuantMag[ci], m_numSwbShort,
m_numSwbShort, grpData, nSamplesInFrame, grpData, nSamplesInFrame, samplingRate >= s,
shortWinCurr ? 0 : meanSpecFlat[ci])); shortWinCurr ? 0 : meanSpecFlat[ci]));
// NOTE: gap-filling SFB bit count might be inaccurate now since scale factors changed // NOTE: gap-filling SFB bit count might be inaccurate now since scale factors changed
if (coreConfig.specFillData[ch] == 1) errorValue |= 1; if (coreConfig.specFillData[ch] == 1) errorValue |= 1;

View File

@@ -286,10 +286,8 @@ uint32_t SfbQuantizer::quantizeMagnRDOC (EntropyCoder& entropyCoder, const uint8
{ {
tempCodState[is] = tempCodState[0]; tempCodState[is] = tempCodState[0];
tempCtxState[is] = tempCtxState[0]; tempCtxState[is] = tempCtxState[0];
for (ds = numStates - 1; ds >= 0; ds--) memset (currRate, UCHAR_MAX, numStates);
{
currRate[ds] = UCHAR_MAX;
}
continue; continue;
} }
tempQuant[0] = (coeffQuantA -= redA); tempQuant[0] = (coeffQuantA -= redA);
@@ -309,12 +307,8 @@ uint32_t SfbQuantizer::quantizeMagnRDOC (EntropyCoder& entropyCoder, const uint8
tempBitCount += (entropyCoder.arithGetCtxState () >> 17) & 31; // +new-old m_acBits tempBitCount += (entropyCoder.arithGetCtxState () >> 17) & 31; // +new-old m_acBits
tempBitCount -= __min ((ctxStart >> 17) & 31, tempBitCount); tempBitCount -= __min ((ctxStart >> 17) & 31, tempBitCount);
tempBitCount += numQ; // add sign bits to finish estimate
for (ds = numStates - 1; ds >= 0; ds--) memset (currRate, tempBitCount + numQ, numStates);
{
currRate[ds] = (uint8_t) __min (UCHAR_MAX, tempBitCount);
}
} }
else // tuple > 0, rate depends on decisions for last tuple else // tuple > 0, rate depends on decisions for last tuple
{ {
@@ -333,9 +327,8 @@ uint32_t SfbQuantizer::quantizeMagnRDOC (EntropyCoder& entropyCoder, const uint8
tempBitCount += (entropyCoder.arithGetCtxState () >> 17) & 31;// +new-old m_acBits tempBitCount += (entropyCoder.arithGetCtxState () >> 17) & 31;// +new-old m_acBits
tempBitCount -= __min ((prevCtxState[ds] >> 17) & 31, tempBitCount); tempBitCount -= __min ((prevCtxState[ds] >> 17) & 31, tempBitCount);
tempBitCount += numQ; // + sign bits to finish estimate
currRate[ds] = (uint8_t) __min (UCHAR_MAX, tempBitCount); currRate[ds] = uint8_t (tempBitCount + numQ);
} }
} }
// statistically best place to save states is after ds == 0 // statistically best place to save states is after ds == 0
@@ -785,8 +778,7 @@ unsigned SfbQuantizer::quantizeSpecRDOC (EntropyCoder& entropyCoder, uint8_t* co
const unsigned numSfb, uint8_t* const quantCoeffs) // returns RD optimization bit count const unsigned numSfb, uint8_t* const quantCoeffs) // returns RD optimization bit count
{ {
// numSfb: number of trellis stages. Based on: A. Aggarwal, S. L. Regunathan, and K. Rose, // numSfb: number of trellis stages. Based on: A. Aggarwal, S. L. Regunathan, and K. Rose,
// "Trellis-Based Optimization of MPEG-4 Advanced Audio Coding," in Proc. IEEE Workshop on // "Trellis-Based Optimization of MPEG-4 Advanced Audio Coding," see also quantizeMagnRDOC
// Speech Coding, pp. 142-144, Sep. 2000. Modified for arithmetic instead of Huffman coder
const uint32_t codStart = USHRT_MAX << 16; const uint32_t codStart = USHRT_MAX << 16;
const uint32_t ctxStart = m_quantRate[0][0]; // start context before call to quantizeSfb() const uint32_t ctxStart = m_quantRate[0][0]; // start context before call to quantizeSfb()
const uint32_t codFinal = entropyCoder.arithGetCodState (); const uint32_t codFinal = entropyCoder.arithGetCodState ();

View File

@@ -24,7 +24,7 @@ SpecGapFiller::SpecGapFiller ()
// public functions // public functions
uint8_t SpecGapFiller::getSpecGapFillParams (const SfbQuantizer& sfbQuantizer, const uint8_t* const quantMagn, uint8_t SpecGapFiller::getSpecGapFillParams (const SfbQuantizer& sfbQuantizer, const uint8_t* const quantMagn,
const uint8_t numSwbShort, SfbGroupData& grpData /*modified*/, const uint8_t numSwbShort, SfbGroupData& grpData /*modified*/,
const unsigned nSamplesInFrame /*= 1024*/, const uint8_t specFlat /*= 0*/) const unsigned nSamplesInFrame, const bool saveRate, const uint8_t specFlat)
{ {
const unsigned* const coeffMagn = sfbQuantizer.getCoeffMagnPtr (); const unsigned* const coeffMagn = sfbQuantizer.getCoeffMagnPtr ();
const double* const sfNormFacs = sfbQuantizer.getSfNormTabPtr (); const double* const sfNormFacs = sfbQuantizer.getSfNormTabPtr ();
@@ -180,7 +180,9 @@ uint8_t SpecGapFiller::getSpecGapFillParams (const SfbQuantizer& sfbQuantizer, c
const uint16_t* grpOff = &grpData.sfbOffsets[numSwbShort * gr]; const uint16_t* grpOff = &grpData.sfbOffsets[numSwbShort * gr];
const uint32_t* grpRms = &grpData.sfbRmsValues[numSwbShort * gr]; // quant/coder stats const uint32_t* grpRms = &grpData.sfbRmsValues[numSwbShort * gr]; // quant/coder stats
uint8_t* const grpScFacs = &grpData.scaleFactors[numSwbShort * gr]; uint8_t* const grpScFacs = &grpData.scaleFactors[numSwbShort * gr];
#if SGF_SF_PEAK_SMOOTHING
uint16_t lastNonZeroSfb = 0;
#endif
for (uint16_t b = m_1stGapFillSfb; b < sfbsPerGrp; b++) // get noise-fill scale factors for (uint16_t b = m_1stGapFillSfb; b < sfbsPerGrp; b++) // get noise-fill scale factors
{ {
if ((grpRms[b] >> 16) == 0) // the SFB is all-zero quantized if ((grpRms[b] >> 16) == 0) // the SFB is all-zero quantized
@@ -204,20 +206,52 @@ uint8_t SpecGapFiller::getSpecGapFillParams (const SfbQuantizer& sfbQuantizer, c
} }
#if SGF_SF_PEAK_SMOOTHING #if SGF_SF_PEAK_SMOOTHING
// save delta-code bits by smoothing scale factor peaks in zero quantized SFB ranges // save delta-code bits by smoothing scale factor peaks in zero quantized SFB ranges
if ((b > m_1stGapFillSfb) && ((grpRms[b - 1] >> 16) == 0) && ((grpRms[b - 2] >> 16) == 0) && if ((b > m_1stGapFillSfb) && ((grpRms[b - 1] >> 16) == 0) && ((grpRms[b - 2] >> 16) == 0))
(grpScFacs[b - 1] > grpScFacs[b]) && (grpScFacs[b - 1] > grpScFacs[b - 2]))
{ {
grpScFacs[b - 1] = (grpScFacs[b - 1] + __max (grpScFacs[b], grpScFacs[b - 2])) >> 1; const uint16_t next = grpScFacs[b];
const uint16_t prev = grpScFacs[b - 2];
uint8_t& curr = grpScFacs[b - 1];
if ((next | prev) && (curr > next) && (curr > prev)) curr = (curr + __max (next, prev)) >> 1;
else if (saveRate && (curr < next) && (curr < prev)) curr = (curr + __min (next, prev) + 1) >> 1;
} }
#endif #endif
} }
#if SGF_SF_PEAK_SMOOTHING
else if (saveRate) lastNonZeroSfb = b;
#endif
if ((b > m_1stGapFillSfb) && (((grpRms[b - 1] >> 16) > 0) ^ ((grpRms[b - 2] >> 16) > 0))) if ((b > m_1stGapFillSfb) && (((grpRms[b - 1] >> 16) > 0) ^ ((grpRms[b - 2] >> 16) > 0)))
{ {
diff += (int) grpScFacs[b - 1] - (int) grpScFacs[b - 2]; // sum up transition deltas diff += (int) grpScFacs[b - 1] - (int) grpScFacs[b - 2]; // sum up transition deltas
s++; s++;
} }
} // for b } // for b
#if SGF_SF_PEAK_SMOOTHING
if ((lastNonZeroSfb > 0) && (lastNonZeroSfb + 4 < sfbsPerGrp)) // HF factor line-fitting
{
const int32_t start = lastNonZeroSfb + 1;
const int32_t size = sfbsPerGrp - start - 1;
const int32_t xSum = (size * (size + 1)) >> 1;
int32_t ySum = 0, a = 0, b = 0;
uint16_t x;
for (x = start + 1; x < sfbsPerGrp; x++) ySum += grpScFacs[x]; // size * (mean factor)
for (x = start + 1; x < sfbsPerGrp; x++)
{
const int32_t xZ = size * (x - start) - xSum; // zero-mean
a += xZ * xZ;
b += xZ * (size * grpScFacs[x] - ySum);
}
if (a > 0) // complete line and adjust gap-fill scale factors
{
b = CLIP_PM (((b << 8) + (a >> 1)) / a, SHRT_MAX);
a = ((ySum << 8) - b * xSum + (size >> 1)) / size;
for (x = start + 1; x < sfbsPerGrp; x++) grpScFacs[x] = CLIP_UCHAR ((a + b * (x - start) - SCHAR_MIN) >> 8);
}
}
#endif
} // for gr } // for gr
if (s > 0) if (s > 0)

View File

@@ -38,7 +38,7 @@ public:
uint16_t getFirstGapFillSfb () const { return m_1stGapFillSfb; } uint16_t getFirstGapFillSfb () const { return m_1stGapFillSfb; }
uint8_t getSpecGapFillParams (const SfbQuantizer& sfbQuantizer, const uint8_t* const quantMagn, uint8_t getSpecGapFillParams (const SfbQuantizer& sfbQuantizer, const uint8_t* const quantMagn,
const uint8_t numSwbShort, SfbGroupData& grpData /*modified*/, const uint8_t numSwbShort, SfbGroupData& grpData /*modified*/,
const unsigned nSamplesInFrame = 1024, const uint8_t specFlat = 0); const unsigned nSamplesInFrame, const bool saveRate, const uint8_t specFlat);
}; // SpecGapFiller }; // SpecGapFiller
#endif // _SPEC_GAP_FILLING_H_ #endif // _SPEC_GAP_FILLING_H_