fix upsampler

This commit is contained in:
Christian R. Helmrich 2020-06-25 00:00:11 +02:00
parent 12bb57155a
commit 74518caef4
3 changed files with 56 additions and 9 deletions

View File

@ -33,6 +33,7 @@
<li><h3>exhaleApp: support for Unicode text on Windows&trade;, 44100 Hz with CVBR mode 1</h3></li>
<li><h3>exhaleApp: automatic upsampling of low-sample-rate input, better WAVE reading</h3></li>
<li><h3>exhaleLib: optimized noise filling tool for slightly lower bit-rates at CVBR mode &lt;4</h3></li>
<li><h3>compilation: exhaleApp.exe -> exhale.exe (issue 8), support for Arm&trade;, C header</h3></li>
</ul>
<h3>&nbsp; &nbsp;Version <b>1.0.4 <span class="gray">&nbsp;May 2020</span></b></h3>
<ul>

View File

@ -55,7 +55,7 @@
#if ENABLE_RESAMPLING
static const int16_t usfc2x[32] = { // 2x upsampling filter coefficients
0, -13785, 8142, -5681, 4281, -3367, 2716, -2225, 1840, -1530, 1275, -1062, 883, -732,
8913, -13785, 8142, -5681, 4281, -3367, 2716, -2225, 1840, -1530, 1275, -1062, 883, -732,
604, -495, 402, -325, 260, -205, 160, -124, 94, -70, 51, -36, 25, -16, 11, -6, 3, -1
};
@ -89,7 +89,7 @@ static void eaApplyUpsampler2x (int32_t* const pcmBuffer, int32_t* const upsampl
{
int32_t* chPcmBuf = &pcmBuffer[ch];
int32_t* chUpsBuf = &upsampleBuffer[chLength * ch];
# if 0
# if 1
if (firstFrame) // construct leading sample values via extrapolation
{
for (int8_t i = 0; i < 32; i++) chUpsBuf[i] = (*chPcmBuf * i + (32 >> 1)) >> 5;
@ -112,7 +112,7 @@ static void eaApplyUpsampler2x (int32_t* const pcmBuffer, int32_t* const upsampl
for (uint16_t i = (frameSize >> 1); i > 0; i--, chPcmBuf += numChannels, chUpsBuf++)
{
int64_t r = (chUpsBuf[0] + (int64_t) chUpsBuf[1]) * 41681;
int64_t r = (chUpsBuf[0] + (int64_t) chUpsBuf[1]) * (usfc2x[0] - SHRT_MIN);
for (int16_t c = 32 - 1; c > 0; c--) r += (chUpsBuf[-c] + (int64_t) chUpsBuf[c + 1]) * usfc2x[c];
*chPcmBuf = *chUpsBuf; chPcmBuf += numChannels; // 1-to-1 mapping
@ -510,7 +510,7 @@ int main (const int argc, char* argv[])
#if ENABLE_RESAMPLING
const bool enableUpsampler = eaInitUpsampler2x (&inPcmRsmp, variableCoreBitRateMode, i, frameLength, numChannels);
const uint16_t firstLength = uint16_t (enableUpsampler ? (frameLength >> 1) + 32 : frameLength); // upsampler look-ahead
const int64_t expectLength = wavReader.getDataBytesLeft () / int64_t ((numChannels * inSampDepth) >> (enableUpsampler ? 4 : 3));
const int64_t expectLength = (wavReader.getDataBytesLeft () << (enableUpsampler ? 1 : 0)) / int64_t ((numChannels * inSampDepth) >> 3);
#else
const int64_t expectLength = wavReader.getDataBytesLeft () / int64_t ((numChannels * inSampDepth) >> 3);
#endif
@ -703,7 +703,7 @@ int main (const int argc, char* argv[])
byteCount += bw;
#if ENABLE_RESAMPLING
const int64_t actualLength = wavReader.getDataBytesRead () / int64_t ((numChannels * inSampDepth) >> (enableUpsampler ? 4 : 3));
const int64_t actualLength = (wavReader.getDataBytesRead () << (enableUpsampler ? 1 : 0)) / int64_t ((numChannels * inSampDepth) >> 3);
#else
const int64_t actualLength = wavReader.getDataBytesRead () / int64_t ((numChannels * inSampDepth) >> 3);
#endif

View File

@ -293,6 +293,41 @@ static inline uint8_t brModeAndFsToMaxSfbShort(const unsigned bitRateMode, const
return (samplingRate > 51200 ? 11 : 13) - 2 + (bitRateMode >> 2);
}
static inline void findActualBandwidthShort (uint8_t* const maxSfbShort, const uint16_t* sfbOffsets,
const int32_t* mdctSignals, const int32_t* mdstSignals, const unsigned nSamplesInShort)
{
const uint16_t b = sfbOffsets[1]; // beginning of search region
uint8_t maxSfb = __max (1, *maxSfbShort);
uint16_t sfbOffs = sfbOffsets[maxSfb - 1];
for (uint16_t e = sfbOffsets[maxSfb] - 1; e >= b; e--) // search
{
int32_t maxAbs = abs (mdctSignals[e]);
if (mdstSignals != nullptr)
{
maxAbs = __max (maxAbs, abs (mdstSignals[e]));
for (uint16_t w = 7; w > 0; w--)
{
maxAbs = __max (maxAbs, abs (mdctSignals[e + w * nSamplesInShort]));
maxAbs = __max (maxAbs, abs (mdstSignals[e + w * nSamplesInShort]));
}
}
else
{
for (uint16_t w = 7; w > 0; w--)
{
maxAbs = __max (maxAbs, abs (mdctSignals[e + w * nSamplesInShort]));
}
}
if (maxAbs > maxSfb * (SA_EPS >> 1)) break;
if (e == sfbOffs) sfbOffs = sfbOffsets[(--maxSfb) - 1];
}
if (*maxSfbShort > maxSfb) *maxSfbShort = maxSfb;
}
static inline uint32_t squareMeanRoot (const uint32_t value1, const uint32_t value2)
{
const double meanRoot = (sqrt ((double) value1) + sqrt ((double) value2)) * 0.5;
@ -986,8 +1021,9 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s
#if !RESTRICT_TO_AAC
if ((maxSfbCh > 0) && m_noiseFilling[el] && (m_bitRateMode <= 3 || !eightShorts))
{
const uint8_t numSwbFrame = __min (numSwbCh, (eightShorts ? maxSfbCh : maxSfbLong) +
(m_bitRateMode < 2 || m_bitRateMode > 3 || samplingRate < 37566 ? 0 : 1));
const uint32_t maxSfbCurr = (eightShorts ? (samplingRate < 37566 ? 14 : brModeAndFsToMaxSfbShort (m_bitRateMode, samplingRate)) : maxSfbLong);
const uint8_t numSwbFrame = __min ((numSwbCh * ((maxSfbCh == maxSfbCurr) || (m_bitRateMode <= 2) ? 4u : 3u)) >> 2,
(eightShorts ? maxSfbCh : maxSfbLong) + (m_bitRateMode < 2 || m_bitRateMode > 3 || samplingRate < 37566 ? 0 : 1));
#ifndef NO_DTX_MODE
const bool prvEightShorts = (coreConfig.icsInfoPrev[ch].windowSequence == EIGHT_SHORT);
@ -1033,7 +1069,17 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s
}
grpData.sfbsPerGroup = coreConfig.icsInfoCurr[ch].maxSfb = numSwbFrame;
}
if (ch > 0) coreConfig.commonMaxSfb = (coreConfig.icsInfoCurr[0].maxSfb == coreConfig.icsInfoCurr[1].maxSfb);
if (ch > 0 && coreConfig.commonWindow) // resynchronize the two max_sfb for stereo
{
uint8_t& maxSfb0 = coreConfig.icsInfoCurr[0].maxSfb;
uint8_t& maxSfb1 = coreConfig.icsInfoCurr[1].maxSfb;
if (coreConfig.stereoMode > 0)
{
maxSfb0 = maxSfb1 = coreConfig.groupingData[0].sfbsPerGroup = grpData.sfbsPerGroup = __max (maxSfb0, maxSfb1);
}
coreConfig.commonMaxSfb = (maxSfb0 == maxSfb1);
}
}
#ifndef NO_DTX_MODE
else if (m_noiseFilling[el] && (m_bitRateMode < 1) && (m_numElements == 1) && (samplingRate <= 24000))
@ -1447,7 +1493,7 @@ unsigned ExhaleEncoder::spectralProcessing () // complete ics_info(), calc TNS
}
memcpy (grpData.windowGroupLength, windowGroupingTable[icsCurr.windowGrouping], NUM_WINDOW_GROUPS * sizeof (uint8_t));
#endif
while (grpSO[icsCurr.maxSfb] > __max (m_bandwidCurr[ci], m_bandwidPrev[ci])) icsCurr.maxSfb--; // not a bug!!
findActualBandwidthShort (&icsCurr.maxSfb, grpSO, m_mdctSignals[ci], nChannels < 2 ? nullptr : m_mdstSignals[ci], nSamplesInShort);
errorValue |= eightShortGrouping (grpData, grpSO, m_mdctSignals[ci], nChannels < 2 ? nullptr : m_mdstSignals[ci]);
} // if EIGHT_SHORT