From aaf8b0aa5a61fea0e1d0c2e79afa673556ed29f6 Mon Sep 17 00:00:00 2001 From: "Christian R. Helmrich" Date: Thu, 6 May 2021 22:00:00 +0200 Subject: [PATCH] finish reader, SBR --- src/app/basicWavReader.cpp | 44 +++++++++++++++++++++----------------- src/lib/exhaleEnc.cpp | 7 +++--- src/lib/exhaleLibPch.cpp | 42 +++++++++++++++++++----------------- 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/src/app/basicWavReader.cpp b/src/app/basicWavReader.cpp index d9bbc9f..73ca68c 100644 --- a/src/app/basicWavReader.cpp +++ b/src/app/basicWavReader.cpp @@ -1,11 +1,11 @@ /* basicWavReader.cpp - source file for class with basic WAVE file reading capability - * written by C. R. Helmrich, last modified in 2020 - see License.htm for legal notices + * written by C. R. Helmrich, last modified in 2021 - see License.htm for legal notices * * The copyright in this software is being made available under the exhale Copyright License * and comes with ABSOLUTELY NO WARRANTY. This software may be subject to other third- * party rights, including patent rights. No such rights are granted under this License. * - * Copyright (c) 2018-2020 Christian R. Helmrich, project ecodis. All rights reserved. + * Copyright (c) 2018-2021 Christian R. Helmrich, project ecodis. All rights reserved. */ #include "exhaleAppPch.h" @@ -25,6 +25,22 @@ static int64_t fourBytesToLength (const uint8_t* b, const int64_t lengthLimit) return __min (lengthLimit, chunkLength); // for security } +#if BWR_BUFFERED_READ +static inline unsigned getFrames (const int fileHandle, void* dataBuf, const unsigned frameCount, + const bool roundSize, const unsigned bytesPerFrame) +{ + const int size = ((frameCount + (roundSize ? 1 << (BWR_READ_FRACT - 1) : 0)) >> BWR_READ_FRACT) * bytesPerFrame; + int bytesRead = _READ (fileHandle, dataBuf, size); // 1 + + if ((bytesRead = __max (0, bytesRead)) < size) + { + const int br = _READ (fileHandle, (uint8_t*) dataBuf + bytesRead, size - bytesRead); + + bytesRead += __max (0, br); // bytes of read attempt 2 + } + return bytesRead / bytesPerFrame; // num of frames read +} +#endif // private reader functions bool BasicWavReader::readRiffHeader () @@ -124,9 +140,7 @@ unsigned BasicWavReader::readDataFloat16 (const int fileHandle, int32_t* frameBu for (unsigned fract = 0; fract < (1 << BWR_READ_FRACT) + rest; fract++) { const int16_t* fBuf = (const int16_t*) tempBuf; // words - const unsigned size = (frameCount + ((fract & 1) > 0 ? 1 << (BWR_READ_FRACT - 1) : 0)) >> BWR_READ_FRACT; - const int bytesRead = _READ (fileHandle, tempBuf, size * chanCount * 2); - const unsigned read = __max (0, bytesRead / (chanCount * 2)); + const unsigned read = getFrames (fileHandle, tempBuf, frameCount, (fract & 1), chanCount * 2); for (unsigned i = read * chanCount; i > 0; i--) { @@ -175,9 +189,7 @@ unsigned BasicWavReader::readDataFloat32 (const int fileHandle, int32_t* frameBu for (unsigned fract = 0; fract < (1 << BWR_READ_FRACT) + rest; fract++) { const float* fBuf = (const float*) tempBuf; // 4 bytes - const unsigned size = (frameCount + ((fract & 1) > 0 ? 1 << (BWR_READ_FRACT - 1) : 0)) >> BWR_READ_FRACT; - const int bytesRead = _READ (fileHandle, tempBuf, size * chanCount * 4); - const unsigned read = __max (0, bytesRead / (chanCount * 4)); + const unsigned read = getFrames (fileHandle, tempBuf, frameCount, (fract & 1), chanCount * 4); for (unsigned i = read * chanCount; i > 0; i--) { @@ -224,9 +236,7 @@ unsigned BasicWavReader::readDataLnPcm08 (const int fileHandle, int32_t* frameBu for (unsigned fract = 0; fract < (1 << BWR_READ_FRACT) + rest; fract++) { const uint8_t* iBuf = (const uint8_t*) tempBuf; // 1b - const unsigned size = (frameCount + ((fract & 1) > 0 ? 1 << (BWR_READ_FRACT - 1) : 0)) >> BWR_READ_FRACT; - const int bytesRead = _READ (fileHandle, tempBuf, size * chanCount); - const unsigned read = __max (0, bytesRead / chanCount); + const unsigned read = getFrames (fileHandle, tempBuf, frameCount, (fract & 1), chanCount); for (unsigned i = read * chanCount; i > 0; i--) { @@ -263,9 +273,7 @@ unsigned BasicWavReader::readDataLnPcm16 (const int fileHandle, int32_t* frameBu for (unsigned fract = 0; fract < (1 << BWR_READ_FRACT) + rest; fract++) { const int16_t* iBuf = (const int16_t*) tempBuf; // words - const unsigned size = (frameCount + ((fract & 1) > 0 ? 1 << (BWR_READ_FRACT - 1) : 0)) >> BWR_READ_FRACT; - const int bytesRead = _READ (fileHandle, tempBuf, size * chanCount * 2); - const unsigned read = __max (0, bytesRead / (chanCount * 2)); + const unsigned read = getFrames (fileHandle, tempBuf, frameCount, (fract & 1), chanCount * 2); for (unsigned i = read * chanCount; i > 0; i--) { @@ -302,9 +310,7 @@ unsigned BasicWavReader::readDataLnPcm24 (const int fileHandle, int32_t* frameBu for (unsigned fract = 0; fract < (1 << BWR_READ_FRACT) + rest; fract++) { const uint8_t* iBuf = (const uint8_t*) tempBuf; // 3b - const unsigned size = (frameCount + ((fract & 1) > 0 ? 1 << (BWR_READ_FRACT - 1) : 0)) >> BWR_READ_FRACT; - const int bytesRead = _READ (fileHandle, tempBuf, size * chanCount * 3); - const unsigned read = __max (0, bytesRead / (chanCount * 3)); + const unsigned read = getFrames (fileHandle, tempBuf, frameCount, (fract & 1), chanCount * 3); for (unsigned i = read * chanCount; i > 0; i--) { @@ -343,9 +349,7 @@ unsigned BasicWavReader::readDataLnPcm32 (const int fileHandle, int32_t* frameBu for (unsigned fract = 0; fract < (1 << BWR_READ_FRACT) + rest; fract++) { const int32_t* iBuf = (const int32_t*) tempBuf; // dword - const unsigned size = (frameCount + ((fract & 1) > 0 ? 1 << (BWR_READ_FRACT - 1) : 0)) >> BWR_READ_FRACT; - const int bytesRead = _READ (fileHandle, tempBuf, size * chanCount * 4); - const unsigned read = __max (0, bytesRead / (chanCount * 4)); + const unsigned read = getFrames (fileHandle, tempBuf, frameCount, (fract & 1), chanCount * 4); for (unsigned i = read * chanCount; i > 0; i--) { diff --git a/src/lib/exhaleEnc.cpp b/src/lib/exhaleEnc.cpp index 791f54b..e052a4c 100644 --- a/src/lib/exhaleEnc.cpp +++ b/src/lib/exhaleEnc.cpp @@ -783,7 +783,6 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s // get means of spectral and temporal flatness for every channel m_bitAllocator.getChAverageSpecFlat (meanSpecFlat, nChannels); -//m_bitAllocator.getChAverageTempFlat (meanTempFlat, nChannels); for (unsigned el = 0; el < m_numElements; el++) // element loop { @@ -920,7 +919,6 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s m_specAnaCurr[ci ] = (m_specAnaCurr[ci ] & (UINT_MAX - 65504)) | peakIndexSte; m_specAnaCurr[ci + 1] = (m_specAnaCurr[ci + 1] & (UINT_MAX - 65504)) | peakIndexSte; meanSpecFlat[ci] = meanSpecFlat[ci + 1] = ((uint16_t) meanSpecFlat[ci] + (uint16_t) meanSpecFlat[ci + 1]) >> 1; - // meanTempFlat[ci] = meanTempFlat[ci + 1] = ((uint16_t) meanTempFlat[ci] + (uint16_t) meanTempFlat[ci + 1]) >> 1; } else memset (coreConfig.stereoDataCurr, 0, (eightShorts0 || !coreConfig.commonWindow ? MAX_NUM_SWB_SHORT * NUM_WINDOW_GROUPS : MAX_NUM_SWB_LONG) * sizeof (uint8_t)); @@ -958,7 +956,10 @@ unsigned ExhaleEncoder::psychBitAllocation () // perceptual bit-allocation via s // scale step-sizes according to VBR mode & derive scale factors from step-sizes grpStepSizes[b] = uint32_t (__max (BA_EPS, ((1u << 17) + grpStepSizes[b] * scale) >> 18)); - +#if !RESTRICT_TO_AAC + if (!m_noiseFilling[el] || (m_bitRateMode > 0) || (m_shiftValSBR == 0) || (samplingRate < 23004) || + (b + 3 - (meanSpecFlat[ci] >> 6) < m_numSwbLong)) // HF +#endif grpScaleFacs[b] = m_bitAllocator.getScaleFac (grpStepSizes[b], &m_mdctSignals[ci][grpOff[b]], sfbWidth, grpRms[b]); } } // for gr diff --git a/src/lib/exhaleLibPch.cpp b/src/lib/exhaleLibPch.cpp index d7c838d..903f3c0 100644 --- a/src/lib/exhaleLibPch.cpp +++ b/src/lib/exhaleLibPch.cpp @@ -1,11 +1,11 @@ /* exhaleLibPch.cpp - pre-compiled source file for classes of exhaleLib coding library - * written by C. R. Helmrich, last modified in 2020 - see License.htm for legal notices + * written by C. R. Helmrich, last modified in 2021 - see License.htm for legal notices * * The copyright in this software is being made available under the exhale Copyright License * and comes with ABSOLUTELY NO WARRANTY. This software may be subject to other third- * party rights, including patent rights. No such rights are granted under this License. * - * Copyright (c) 2018-2020 Christian R. Helmrich, project ecodis. All rights reserved. + * Copyright (c) 2018-2021 Christian R. Helmrich, project ecodis. All rights reserved. */ #include "exhaleLibPch.h" @@ -59,7 +59,9 @@ static const uint8_t deltaHuffSbrT[14] = {0xFD, 0x7D, 0x3D, 0x1D, 0x0D, 0x05, 0x // static SBR related functions static int32_t getSbrDeltaBitCount (const int32_t delta, const bool dt) { - return (delta == 5 && !dt ? 8 : abs (delta) + 2 + (delta >> 31)); + const int dLimit = __max (-7, __min (6, delta)); + + return (delta != dLimit ? 85 : (delta == 5 && !dt ? 8 : abs (delta) + 2 + (delta >> 31))); } static int32_t getSbrDeltaHuffCode (const int32_t delta, const bool dt) @@ -126,13 +128,14 @@ 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 uint8_t noiseLevel = __min (30, __max (specFlat5b, specFlatSte)); + const uint8_t noiseLimit = uint8_t (envTmp0[0] < frameSize * 30 ? 30 - envTmp0[0] / frameSize : 1); + const uint8_t noiseLevel = __max (noiseLimit, __min (30, __max (specFlat5b, specFlatSte))); const uint32_t rat3BandsL = sbrLevels[28] & USHRT_MAX; const uint32_t rat3BandsM = sbrLevels[28] >> 16; const uint32_t rat3BandsH = sbrLevels[29] & USHRT_MAX; uint64_t errTmp[4] = {0, 0, 0, 0}; uint64_t errBest; - int32_t tmpBest, bitCount, diff; + int32_t tmpBest = 0; uint8_t t; for (t = 0; t < 8; t++) // get energy errors due to temporal merging @@ -145,7 +148,6 @@ int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat 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 { @@ -203,27 +205,27 @@ int32_t getSbrEnvelopeAndNoise (int32_t* const sbrLevels, const uint8_t specFlat const int32_t c[3] = {curr & SCHAR_MAX, (curr >> 8) & SCHAR_MAX, (curr >> 16) & SCHAR_MAX}; const int32_t prev = sbrLevels[30]; const int32_t p[3] = {prev & SCHAR_MAX, (prev >> 8) & SCHAR_MAX, (prev >> 16) & SCHAR_MAX}; + const int df[3] = {c[0]/*PCM*/, c[1] - c[0], c[2] - c[1]}; + const int dt[3] = {c[0] - p[0], c[1] - p[1], c[2] - p[2]}; + const int* dp = df; + bool useDTime = false; + int32_t bitCount = 8; - if ((t > 0 || !ind) && (getSbrDeltaBitCount (c[0] - p[0], true) + getSbrDeltaBitCount (c[1] - p[1], true) + - getSbrDeltaBitCount (c[2] - p[2], true) < 13)) // approximate! + if ((t > 0 || !ind) && (7/*PCM bits*/ + getSbrDeltaBitCount (df[1],false) + getSbrDeltaBitCount (df[2], false) > + getSbrDeltaBitCount (dt[0], true) + getSbrDeltaBitCount (dt[1], true) + getSbrDeltaBitCount (dt[2], true))) { tmpBest |= 1 << (12 + t); // delta-time coding flag for envelope + dp = dt; + useDTime = true; - diff = c[0] - p[0]; - sbrData[t] = getSbrDeltaHuffCode (diff, true ); bitCount = 8; // see bitStreamWriter.cpp, lines 186 and 213 - diff = c[2] - p[2]; - sbrData[t] |= getSbrDeltaHuffCode (diff, true ) << bitCount; bitCount += getSbrDeltaBitCount (diff, true ); - diff = c[1] - p[1]; - sbrData[t] |= getSbrDeltaHuffCode (diff, true ) << bitCount; bitCount += getSbrDeltaBitCount (diff, true ); + sbrData[t] = getSbrDeltaHuffCode (dt[0], true); } - else // delta-frequency coding + else // delta-frequency { - sbrData[t] = c[0]; bitCount = 8; // first envelope is PCM coded - diff = c[2] - c[1]; - sbrData[t] |= getSbrDeltaHuffCode (diff, false) << bitCount; bitCount += getSbrDeltaBitCount (diff, false); - diff = c[1] - c[0]; - sbrData[t] |= getSbrDeltaHuffCode (diff, false) << bitCount; bitCount += getSbrDeltaBitCount (diff, false); + sbrData[t] = df[0]; } + sbrData[t] |= getSbrDeltaHuffCode (dp[2], useDTime) << bitCount; bitCount += getSbrDeltaBitCount (dp[2], useDTime); + sbrData[t] |= getSbrDeltaHuffCode (dp[1], useDTime) << bitCount; bitCount += getSbrDeltaBitCount (dp[1], useDTime); sbrData[t] |= 1 << bitCount; // MSB delimiter for bitstream writer sbrLevels[30] = curr; }