mirror of
https://gitlab.com/ecodis/exhale.git
synced 2025-03-11 00:30:17 +01:00
finish 1.1.8 release
This commit is contained in:
parent
f145f63fe5
commit
7688ab502e
@ -16,7 +16,7 @@ if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
|
||||
project(exhale VERSION 1.1.7 LANGUAGES CXX)
|
||||
project(exhale VERSION 1.1.8 LANGUAGES CXX)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE Release
|
||||
|
@ -41,7 +41,7 @@ exhale is being made available under an open-source license which is
|
||||
based on the 3-clause BSD license but modified to address particular
|
||||
aspects dictated by the nature and the output of this application.
|
||||
|
||||
The license text and release notes for the current version 1.1.7 can
|
||||
The license text and release notes for the current version 1.1.8 can
|
||||
be found in the `include` subdirectory of the exhale distribution.
|
||||
|
||||
|
||||
|
@ -25,9 +25,14 @@
|
||||
<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> The version of this distribution of the «exhale» software release is <b>1.1.7</b> (official pub­lic minor release) from August 2021. 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> The version of this distribution of the «exhale» software release is <b>1.1.8</b> (official pub­lic minor release) from October 2021. 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> Version <b>1.1.7 <span class="gray"> Aug. 2021, this release</span></b></h3>
|
||||
<h3> Version <b>1.1.8 <span class="gray"> Oct. 2021, this release</span></b></h3>
|
||||
<ul>
|
||||
<li><h3>some final code cleanup, small code corrections and editorial changes for this year</h3></li>
|
||||
<li><h3>exhaleLib: minor stereo quality tuning for low rates, optional CBR mode via macro</h3></li>
|
||||
</ul>
|
||||
<h3> Version <b>1.1.7 <span class="gray"> Aug. 2021</span></b></h3>
|
||||
<ul>
|
||||
<li><h3>minor tuning at low SBR rates, enabled SBR coding at 22050 Hz input sample rate</h3></li>
|
||||
<li><h3>exhaleApp: added expert modes for loudness leveling, custom Intra frame interval</h3></li>
|
||||
@ -158,7 +163,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.1.7, Aug. 2021. Available at www.ecodis.de/exhale/release.htm.</span><br><br></h4>
|
||||
<h4><span class="gray">Written by C. R. Helmrich for exhale 1.1.8, Oct. 2021. Available at www.ecodis.de/exhale/release.htm.</span><br><br></h4>
|
||||
|
||||
</td>
|
||||
<td valign="top" colspan="2">
|
||||
|
@ -15,5 +15,5 @@
|
||||
# define EXHALELIB_VERSION_MINOR "1"
|
||||
#endif
|
||||
#ifndef EXHALELIB_VERSION_BUGFIX
|
||||
# define EXHALELIB_VERSION_BUGFIX ".7" // "RC" or ".0", ".1", ...
|
||||
# define EXHALELIB_VERSION_BUGFIX ".8" // "RC" or ".0", ".1", ...
|
||||
#endif
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
0 ICON "exhaleApp.ico"
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,7,1
|
||||
FILEVERSION 1,1,8
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
|
@ -107,11 +107,12 @@ uint16_t BitAllocator::getRateCtrlFac (const int32_t rateRatio, const unsigned s
|
||||
#if BA_MORE_CBR
|
||||
const int32_t ratioFac = rateRatio * (40 - 5 * m_rateIndex);
|
||||
const uint32_t brRatio = __max ((prevEightShorts ? (ratioFac * ratioFac + (1 << 16)) >> 17 : 0) - SHRT_MIN, __min (USHRT_MAX, ratioFac)) -
|
||||
(m_rateIndex == 2 ? (1 << 11) : 0);
|
||||
(m_rateIndex == 2 ? 1 << 12 : 0); // rate tuning
|
||||
const uint16_t mSfmSqr = (m_rateIndex <= 2 && samplingRate >= 27713 ? (specFlatness * specFlatness) >> m_rateIndex : 0);
|
||||
#else
|
||||
const uint32_t brRatio = __max (1 << 15, __min (USHRT_MAX, rateRatio * (36 - 9 * m_rateIndex)));
|
||||
#endif
|
||||
const uint16_t mSfmSqr = (m_rateIndex < 2 && samplingRate >= 27713 ? (specFlatness * specFlatness) >> m_rateIndex : 0);
|
||||
#endif
|
||||
const uint16_t mSfmFac = 256 - (((32 + m_rateIndex) * (specFlatness << 4) - mSfmSqr + (1 << 9)) >> 10);
|
||||
|
||||
return uint16_t ((brRatio * mSfmFac + (1 << 7)) >> 8);
|
||||
|
@ -1324,7 +1324,7 @@ unsigned ExhaleEncoder::quantizationCoding () // apply MDCT quantization and en
|
||||
}
|
||||
} // for el
|
||||
#if !RESTRICT_TO_AAC
|
||||
m_rateFactor = samplingRate; // for RC
|
||||
m_rateFactor = samplingRate; // rate ctrl
|
||||
#endif
|
||||
return (errorValue > 0 ? 0 : m_outStream.createAudioFrame (m_elementData, m_entropyCoder, m_mdctSignals, m_mdctQuantMag, m_indepFlag,
|
||||
m_numElements, m_numSwbShort, (uint8_t* const) m_tempIntBuf,
|
||||
@ -1389,9 +1389,8 @@ unsigned ExhaleEncoder::spectralProcessing () // complete ics_info(), calc TNS
|
||||
const uint8_t meanSpecFlat = (((m_specAnaCurr[ci] >> 16) & UCHAR_MAX) + ((m_specAnaCurr[ci + 1] >> 16) & UCHAR_MAX) + 1) >> 1;
|
||||
const uint16_t* const swbo = swbOffsetsL[m_swbTableIdx];
|
||||
const uint16_t nSamplesMax = (useMaxBandwidth ? nSamplesInFrame : swbo[brModeAndFsToMaxSfbLong (m_bitRateMode, samplingRate)]);
|
||||
const int16_t steAnaStats = m_specAnalyzer.stereoSigAnalysis (m_mdctSignals[ci], m_mdctSignals[ci + 1],
|
||||
m_mdstSignals[ci], m_mdstSignals[ci + 1], nSamplesMax,
|
||||
nSamplesInFrame, eightShorts, coreConfig.stereoDataCurr);
|
||||
const int16_t steAnaStats = m_specAnalyzer.stereoSigAnalysis (m_mdctSignals[ci], m_mdctSignals[ci + 1], m_mdstSignals[ci], m_mdstSignals[ci + 1],
|
||||
nSamplesMax, nSamplesInFrame, eightShorts, coreConfig.stereoDataCurr);
|
||||
if (steAnaStats == SHRT_MIN) errorValue = 1;
|
||||
|
||||
if ((s = abs (steAnaStats)) * m_perCorrHCurr[el] == 0) // transition to/from silence
|
||||
@ -1455,7 +1454,7 @@ unsigned ExhaleEncoder::spectralProcessing () // complete ics_info(), calc TNS
|
||||
{
|
||||
icsCurr.maxSfb = __min (icsCurr.maxSfb, brModeAndFsToMaxSfbShort (m_bitRateMode, samplingRate));
|
||||
}
|
||||
#if SA_OPT_WINDOW_GROUPING
|
||||
|
||||
if (ch > 0 && coreConfig.commonWindow) // resynchronize the scale_factor_grouping
|
||||
{
|
||||
if (icsCurr.windowGrouping != coreConfig.icsInfoCurr[0].windowGrouping)
|
||||
@ -1471,15 +1470,15 @@ unsigned ExhaleEncoder::spectralProcessing () // complete ics_info(), calc TNS
|
||||
}
|
||||
}
|
||||
memcpy (grpData.windowGroupLength, windowGroupingTable[icsCurr.windowGrouping], NUM_WINDOW_GROUPS * sizeof (uint8_t));
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
// compute and quantize optimal TNS coefficients, then find optimal TNS filter order
|
||||
s /*max. pred gain*/ = getOptParCorCoeffs (grpData, icsCurr.maxSfb, tnsData, ci,
|
||||
ch > 0 && coreConfig.commonWindow ? coreConfig.tnsData[0].firstTnsWindow : 0);
|
||||
s = getOptParCorCoeffs (grpData, icsCurr.maxSfb, tnsData, ci, (ch > 0 && coreConfig.commonWindow ? coreConfig.tnsData[0].firstTnsWindow : 0));
|
||||
|
||||
for (uint16_t n = 0, gr = 0; gr < grpData.numWindowGroups; gr++)
|
||||
{
|
||||
if (grpData.windowGroupLength[gr] == 1)
|
||||
@ -1780,6 +1779,7 @@ unsigned ExhaleEncoder::temporalProcessing () // determine time-domain aspects o
|
||||
|
||||
memcpy (coreConfig.stereoDataPrev, &coreConfig.stereoDataCurr[lastGrpOffset], __min (60 - lastGrpOffset, maxSfbStePrev) * sizeof (uint8_t));
|
||||
}
|
||||
coreConfig.stereoDataCurr[0] = (m_bitRateMode <= 1 ? m_tempAnalyzer.stereoPreAnalysis (&m_timeSignals[ci - 2], &m_specFlatPrev[ci - 2], nSamplesInFrame) : 0);
|
||||
} // if nrChannels > 1
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,6 @@ unsigned SpecAnalyzer::initSigAnaMemory (LinearPredictor* const linPredictor, co
|
||||
return 0; // no error
|
||||
}
|
||||
|
||||
#if SA_OPT_WINDOW_GROUPING
|
||||
unsigned SpecAnalyzer::optimizeGrouping (const unsigned channelIndex, const unsigned prefBandwidth, const unsigned prefGroupingIndex)
|
||||
{
|
||||
const uint32_t* meanAbsValCurr = m_meanAbsValue[channelIndex];
|
||||
@ -226,7 +225,6 @@ unsigned SpecAnalyzer::optimizeGrouping (const unsigned channelIndex, const unsi
|
||||
|
||||
return __min (grpIdxCurr, prefGroupingIndex); // final optimized grouping index
|
||||
}
|
||||
#endif // SA_OPT_WINDOW_GROUPING
|
||||
|
||||
unsigned SpecAnalyzer::spectralAnalysis (const int32_t* const mdctSignals[USAC_MAX_NUM_CHANNELS],
|
||||
const int32_t* const mdstSignals[USAC_MAX_NUM_CHANNELS],
|
||||
@ -349,14 +347,12 @@ unsigned SpecAnalyzer::spectralAnalysis (const int32_t* const mdctSignals[USAC_M
|
||||
|
||||
// --- spectral analysis statistics for frame
|
||||
b = 1;
|
||||
#if SA_IMPROVED_FILT_CALC
|
||||
if (samplingRate < 27713) sumAvgBand -= m_meanAbsValue[ch][b++];
|
||||
#endif
|
||||
|
||||
while (((unsigned) b + 1 < lpcStopBand16k) && ((uint64_t) m_meanAbsValue[ch][b] * (m_numAnaBands[ch] - 1) > sumAvgBand)) b++;
|
||||
b = __min (m_bandwidthOff[ch], b << SA_BW_SHIFT);
|
||||
#if SA_IMPROVED_FILT_CALC
|
||||
if (samplingRate < 27713) sumAvgBand += m_meanAbsValue[ch][1];
|
||||
#endif
|
||||
|
||||
// obtain prediction gain across spectrum
|
||||
m_tnsPredGains[ch] = m_tnsPredictor->calcParCorCoeffs (&chMdct[b], __min (m_bandwidthOff[ch], lpcStopBand16k << SA_BW_SHIFT) - b,
|
||||
MAX_PREDICTION_ORDER, m_parCorCoeffs[ch]);
|
||||
@ -378,7 +374,7 @@ unsigned SpecAnalyzer::spectralAnalysis (const int32_t* const mdctSignals[USAC_M
|
||||
int16_t SpecAnalyzer::stereoSigAnalysis (const int32_t* const mdctSignal1, const int32_t* const mdctSignal2,
|
||||
const int32_t* const mdstSignal1, const int32_t* const mdstSignal2,
|
||||
const unsigned nSamplesMax, const unsigned nSamplesInFrame, const bool shortTransforms,
|
||||
uint8_t* const stereoCorrValue /*= nullptr*/) // per-band perceptual correlation data
|
||||
uint8_t* const stereoCorrValue) // per-band LR correlation
|
||||
{
|
||||
const uint64_t anaBwOffset = SA_BW >> 1;
|
||||
const uint16_t numAnaBands = (shortTransforms ? nSamplesInFrame : nSamplesMax) >> SA_BW_SHIFT;
|
||||
@ -392,7 +388,8 @@ int16_t SpecAnalyzer::stereoSigAnalysis (const int32_t* const mdctSignal1, const
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t currPC = 0, numPC = 0; // frame-average correlation
|
||||
const uint16_t tempPreAnaPC = stereoCorrValue[0];
|
||||
uint16_t currPC = 0, numPC = 0;
|
||||
uint64_t sumReM = 0, sumReS = 0;// mid-side RMS distribution
|
||||
|
||||
for (b = numAnaBands - 1; b >= 0; b--)
|
||||
@ -457,6 +454,8 @@ int16_t SpecAnalyzer::stereoSigAnalysis (const int32_t* const mdctSignal1, const
|
||||
|
||||
if (numPC > 1) currPC = (currPC + (numPC >> 1)) / numPC; // frame's perceptual correlation
|
||||
|
||||
if (currPC < tempPreAnaPC) currPC = (currPC + tempPreAnaPC + 1) >> 1;
|
||||
|
||||
b = (int16_t) currPC * (sumReS * 2 > sumReM * 3 ? -1 : 1); // negation implies side > mid
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,6 @@
|
||||
#define SA_BW (1 << SA_BW_SHIFT)
|
||||
#define SA_EPS 1024
|
||||
#define SA_EXACT_COMPLEX_ABS 0
|
||||
#define SA_IMPROVED_FILT_CALC 1
|
||||
#define SA_OPT_WINDOW_GROUPING 1
|
||||
|
||||
// spectral signal analysis class
|
||||
class SpecAnalyzer
|
||||
@ -52,9 +50,7 @@ public:
|
||||
void getSpecAnalysisStats (uint32_t avgSpecAnaStats[USAC_MAX_NUM_CHANNELS], const unsigned nChannels);
|
||||
void getSpectralBandwidth (uint16_t bandwidthOffset[USAC_MAX_NUM_CHANNELS], const unsigned nChannels);
|
||||
unsigned initSigAnaMemory (LinearPredictor* const linPredictor, const unsigned nChannels, const unsigned maxTransfLength);
|
||||
#if SA_OPT_WINDOW_GROUPING
|
||||
unsigned optimizeGrouping (const unsigned channelIndex, const unsigned preferredBandwidth, const unsigned preferredGrouping);
|
||||
#endif
|
||||
unsigned spectralAnalysis (const int32_t* const mdctSignals[USAC_MAX_NUM_CHANNELS],
|
||||
const int32_t* const mdstSignals[USAC_MAX_NUM_CHANNELS],
|
||||
const unsigned nChannels, const unsigned nSamplesInFrame, const unsigned samplingRate,
|
||||
@ -62,7 +58,7 @@ public:
|
||||
int16_t stereoSigAnalysis (const int32_t* const mdctSignal1, const int32_t* const mdctSignal2,
|
||||
const int32_t* const mdstSignal1, const int32_t* const mdstSignal2,
|
||||
const unsigned nSamplesMax, const unsigned nSamplesInFrame, const bool shortTransforms,
|
||||
uint8_t* const stereoCorrValue = nullptr); // per-band perceptual correlation data
|
||||
uint8_t* const stereoCorrValue); // per-band LR correlation
|
||||
}; // SpecAnalyzer
|
||||
|
||||
#endif // _SPEC_ANALYSIS_H_
|
||||
|
@ -126,6 +126,46 @@ void TempAnalyzer::getTransientAndPitch (int16_t transIdxAndPitch[USAC_MAX_NUM_C
|
||||
memcpy (transIdxAndPitch, m_transientLoc, nChannels * sizeof (int16_t));
|
||||
}
|
||||
|
||||
uint8_t TempAnalyzer::stereoPreAnalysis (const int32_t* const timeSignals[2], const uint8_t specFlatness[2], const unsigned nSamplesInSig)
|
||||
{
|
||||
const double offsetSfmLR = __max (0.0, ((double) specFlatness[0] + specFlatness[1] - 256.0) * 0.5);
|
||||
const int32_t* const sigL = timeSignals[0] + (nSamplesInSig >> 1);
|
||||
const int32_t* const sigLM1 = sigL - 1;
|
||||
const int32_t* const sigR = timeSignals[1] + (nSamplesInSig >> 1);
|
||||
const int32_t* const sigRM1 = sigR - 1;
|
||||
int64_t hpNextL = sigL[nSamplesInSig] - sigLM1[nSamplesInSig];
|
||||
int64_t hpNextR = sigR[nSamplesInSig] - sigRM1[nSamplesInSig];
|
||||
int64_t sumSqrL = hpNextL * hpNextL, sumSqrR = hpNextR * hpNextR;
|
||||
int64_t sumPC00 = (hpNextL * hpNextR) >> 1, sumPC01 = 0, sumPC10 = 0;
|
||||
double d;
|
||||
|
||||
for (int s = nSamplesInSig - 1; s >= 0; s--)
|
||||
{
|
||||
// compute correlation between high-pass channel signals with and without 1 smp time delay
|
||||
const int64_t hpL = sigL[s] - sigLM1[s];
|
||||
const int64_t hpR = sigR[s] - sigRM1[s];
|
||||
|
||||
sumSqrL += hpL * hpL;
|
||||
sumSqrR += hpR * hpR;
|
||||
sumPC00 += hpL * hpR;
|
||||
sumPC01 += hpL * hpNextR;
|
||||
sumPC10 += hpR * hpNextL;
|
||||
|
||||
hpNextL = hpL;
|
||||
hpNextR = hpR;
|
||||
}
|
||||
|
||||
if (sumSqrL < nSamplesInSig || sumSqrR < nSamplesInSig) return 0; // stop on low-level input
|
||||
|
||||
sumPC00 = abs (sumPC00);
|
||||
sumPC01 = abs (sumPC01);
|
||||
sumPC10 = abs (sumPC10);
|
||||
|
||||
d = 256.0 * __max (sumPC00, __max (sumPC01, sumPC10)); // max. corr. regardless of the delay
|
||||
|
||||
return (uint8_t) __max (0.0, d / sqrt ((double) sumSqrL * sumSqrR) - offsetSfmLR);
|
||||
}
|
||||
|
||||
unsigned TempAnalyzer::temporalAnalysis (const int32_t* const timeSignals[USAC_MAX_NUM_CHANNELS], const unsigned nChannels,
|
||||
const int nSamplesInFrame, const unsigned lookaheadOffset, const uint8_t sbrShift,
|
||||
int32_t* const lrCoreTimeSignals[USAC_MAX_NUM_CHANNELS] /*= nullptr*/, // if using SBR
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* tempAnalysis.h - header file for class providing temporal analysis of PCM signals
|
||||
* 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-
|
||||
@ -40,6 +40,7 @@ public:
|
||||
// public functions
|
||||
void getTempAnalysisStats (uint32_t avgTempAnaStats[USAC_MAX_NUM_CHANNELS], const unsigned nChannels);
|
||||
void getTransientAndPitch (int16_t transIdxAndPitch[USAC_MAX_NUM_CHANNELS], const unsigned nChannels);
|
||||
uint8_t stereoPreAnalysis (const int32_t* const timeSignals[2], const uint8_t specFlatness[2], const unsigned nSamplesInSig);
|
||||
unsigned temporalAnalysis (const int32_t* const timeSignals[USAC_MAX_NUM_CHANNELS], const unsigned nChannels,
|
||||
const int nSamplesInFrame, const unsigned lookaheadOffset, const uint8_t sbrShift,
|
||||
int32_t* const lrCoreTimeSignals[USAC_MAX_NUM_CHANNELS] = nullptr, // if using SBR
|
||||
|
Loading…
x
Reference in New Issue
Block a user