aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TEST_MAPPING22
-rw-r--r--libAACdec/src/aacdec_hcrs.cpp6
-rw-r--r--libAACdec/src/ldfiltbank.cpp18
-rw-r--r--libAACdec/src/usacdec_acelp.cpp23
-rw-r--r--libDRCdec/src/drcDec_reader.cpp2
-rw-r--r--libFDK/include/scale.h8
-rw-r--r--libFDK/src/FDK_decorrelate.cpp80
-rw-r--r--libFDK/src/dct.cpp18
-rw-r--r--libFDK/src/qmf.cpp45
-rw-r--r--libFDK/src/scale.cpp26
-rw-r--r--libMpegTPDec/src/tpdec_asc.cpp12
-rw-r--r--libPCMutils/src/limiter.cpp6
-rw-r--r--libSACdec/src/sac_bitdec.cpp4
-rw-r--r--libSACdec/src/sac_stp.cpp114
-rw-r--r--libSBRdec/src/env_calc.cpp102
-rw-r--r--libSBRdec/src/lpp_tran.cpp11
-rw-r--r--libSBRdec/src/pvc_dec.cpp25
17 files changed, 313 insertions, 209 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..bc22166
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsMediaTestCases",
+ "options": [
+ { "include-filter": "android.media.cts.DecoderTest#testCodecResetsM4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecode51M4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeAacEldM4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeAacLcM4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeAacLcMcM4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeAacTs" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeHeAacM4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeHeAacMcM4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeHeAacV2M4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeM4a" },
+ { "include-filter": "android.media.cts.DecoderTest#testDecodeMonoM4a" },
+ { "include-filter": "android.media.cts.DecoderTestXheAac" },
+ { "include-filter": "android.media.cts.DecoderTestAacDrc" }
+ ]
+ }
+ ]
+}
diff --git a/libAACdec/src/aacdec_hcrs.cpp b/libAACdec/src/aacdec_hcrs.cpp
index d2bc867..44b32a5 100644
--- a/libAACdec/src/aacdec_hcrs.cpp
+++ b/libAACdec/src/aacdec_hcrs.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -1324,6 +1324,10 @@ UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr) {
/* count ones and store sum in escapePrefixUp */
if (carryBit == 1) {
escapePrefixUp += 1; /* update conter for ones */
+ if (escapePrefixUp > 8) {
+ pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX;
+ return BODY_SIGN_ESC__ESC_PREFIX;
+ }
/* store updated counter in sideinfo of current codeword */
pEscapeSequenceInfo[codewordOffset] &=
diff --git a/libAACdec/src/ldfiltbank.cpp b/libAACdec/src/ldfiltbank.cpp
index c7d2928..1898557 100644
--- a/libAACdec/src/ldfiltbank.cpp
+++ b/libAACdec/src/ldfiltbank.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -131,10 +131,12 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
FIXP_DBL z0, z2, tmp;
z2 = x[N / 2 + i];
- z0 = z2 + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1));
+ z0 = fAddSaturate(z2,
+ (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1)));
- z[N / 2 + i] = x[N / 2 - 1 - i] +
- (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1));
+ z[N / 2 + i] = fAddSaturate(
+ x[N / 2 - 1 - i],
+ (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1)));
tmp = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) +
fMultDiv2(z[i], fb[N + N / 2 + i]));
@@ -159,10 +161,12 @@ static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb,
FIXP_DBL z0, z2, tmp0, tmp1;
z2 = x[N / 2 + i];
- z0 = z2 + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1));
+ z0 = fAddSaturate(z2,
+ (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1)));
- z[N / 2 + i] = x[N / 2 - 1 - i] +
- (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1));
+ z[N / 2 + i] = fAddSaturate(
+ x[N / 2 - 1 - i],
+ (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1)));
tmp0 = (fMultDiv2(z[N / 2 + i], fb[N / 2 - 1 - i]) +
fMultDiv2(z[i], fb[N / 2 + i]));
diff --git a/libAACdec/src/usacdec_acelp.cpp b/libAACdec/src/usacdec_acelp.cpp
index 1ac8c9f..a8dadc0 100644
--- a/libAACdec/src/usacdec_acelp.cpp
+++ b/libAACdec/src/usacdec_acelp.cpp
@@ -465,7 +465,9 @@ void BuildAdaptiveExcitation(
/* Note: code[L_SUBFR] and exc2[L_SUBFR] share the same memory!
If exc2[i] is written, code[i] will be destroyed!
*/
-#define SF (SF_CODE + SF_GAIN_C + 1 - SF_EXC)
+#define SF_HEADROOM (1)
+#define SF (SF_CODE + SF_GAIN_C + 1 - SF_EXC - SF_HEADROOM)
+#define SF_GAIN_P2 (SF_GAIN_P - SF_HEADROOM)
int i;
FIXP_DBL tmp, cpe, code_smooth_prev, code_smooth;
@@ -477,8 +479,8 @@ void BuildAdaptiveExcitation(
cpe = (period_fac >> (2 - SF_PFAC)) + FL2FXCONST_DBL(0.25f);
/* u'(n) */
- tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1); /* v(0)*g_p */
- *exc++ = tmp + (fMultDiv2(code[0], gain_code) << SF);
+ tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1); /* v(0)*g_p */
+ *exc++ = (tmp + (fMultDiv2(code[0], gain_code) << SF)) << SF_HEADROOM;
/* u(n) */
code_smooth_prev = fMultDiv2(*code++, gain_code_smoothed)
@@ -487,15 +489,15 @@ void BuildAdaptiveExcitation(
code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF; /* c(1) * g_sc */
tmp += code_smooth_prev; /* tmp = v(0)*g_p + c(0)*g_sc */
cpe_code_smooth = fMultDiv2(cpe, code_smooth);
- *exc2++ = tmp - cpe_code_smooth;
+ *exc2++ = (tmp - cpe_code_smooth) << SF_HEADROOM;
cpe_code_smooth_prev = fMultDiv2(cpe, code_smooth_prev);
i = L_SUBFR - 2;
do /* ARM926: 22 cycles per iteration */
{
/* u'(n) */
- tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1);
- *exc++ = tmp + (fMultDiv2(code_i, gain_code) << SF);
+ tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1);
+ *exc++ = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM;
/* u(n) */
tmp += code_smooth; /* += g_sc * c(i) */
tmp -= cpe_code_smooth_prev;
@@ -503,16 +505,17 @@ void BuildAdaptiveExcitation(
code_i = *code++;
code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF;
cpe_code_smooth = fMultDiv2(cpe, code_smooth);
- *exc2++ = tmp - cpe_code_smooth; /* tmp - c_pe * g_sc * c(i+1) */
+ *exc2++ = (tmp - cpe_code_smooth)
+ << SF_HEADROOM; /* tmp - c_pe * g_sc * c(i+1) */
} while (--i != 0);
/* u'(n) */
- tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1);
- *exc = tmp + (fMultDiv2(code_i, gain_code) << SF);
+ tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P2 + 1);
+ *exc = (tmp + (fMultDiv2(code_i, gain_code) << SF)) << SF_HEADROOM;
/* u(n) */
tmp += code_smooth;
tmp -= cpe_code_smooth_prev;
- *exc2++ = tmp;
+ *exc2++ = tmp << SF_HEADROOM;
return;
}
diff --git a/libDRCdec/src/drcDec_reader.cpp b/libDRCdec/src/drcDec_reader.cpp
index a784457..9e37246 100644
--- a/libDRCdec/src/drcDec_reader.cpp
+++ b/libDRCdec/src/drcDec_reader.cpp
@@ -1018,6 +1018,7 @@ static DRC_ERROR _skipEqInstructions(HANDLE_FDK_BITSTREAM hBs,
int additionalDrcSetIdPresent, additionalDrcSetIdCount;
int dependsOnEqSetPresent, eqChannelGroupCount, tdFilterCascadePresent,
subbandGainsPresent, eqTransitionDurationPresent;
+ UCHAR eqChannelGroupForChannel[8];
FDKpushFor(hBs, 6); /* eqSetId */
FDKpushFor(hBs, 4); /* eqSetComplexityLevel */
@@ -1067,7 +1068,6 @@ static DRC_ERROR _skipEqInstructions(HANDLE_FDK_BITSTREAM hBs,
eqChannelGroupCount = 0;
for (c = 0; c < channelCount; c++) {
- UCHAR eqChannelGroupForChannel[8];
int newGroup = 1;
if (c >= 8) return DE_MEMORY_ERROR;
eqChannelGroupForChannel[c] = FDKreadBits(hBs, 7);
diff --git a/libFDK/include/scale.h b/libFDK/include/scale.h
index 655ccaf..a58614e 100644
--- a/libFDK/include/scale.h
+++ b/libFDK/include/scale.h
@@ -129,15 +129,13 @@ void scaleCplxValues(FIXP_DBL *r_dst, FIXP_DBL *i_dst, const FIXP_DBL *r_src,
void scaleValuesWithFactor(FIXP_DBL *vector, FIXP_DBL factor, INT len,
INT scalefactor);
void scaleValuesSaturate(FIXP_DBL *vector, INT len, INT scalefactor);
-void scaleValuesSaturate(FIXP_DBL *dst, FIXP_DBL *src, INT len,
+void scaleValuesSaturate(FIXP_DBL *dst, const FIXP_DBL *src, INT len,
INT scalefactor);
-void scaleValuesSaturate(FIXP_SGL *dst, FIXP_DBL *src, INT len,
+void scaleValuesSaturate(FIXP_SGL *dst, const FIXP_DBL *src, INT len,
INT scalefactor);
-void scaleValuesSaturate(INT_PCM *dst, FIXP_DBL *src, INT len, INT scalefactor);
void scaleValuesSaturate(FIXP_SGL *vector, INT len, INT scalefactor);
-void scaleValuesSaturate(FIXP_SGL *dst, FIXP_SGL *src, INT len,
+void scaleValuesSaturate(FIXP_SGL *dst, const FIXP_SGL *src, INT len,
INT scalefactor);
-void scaleValuesSaturate(INT_PCM *dst, INT_PCM *src, INT len, INT scalefactor);
INT getScalefactorShort(const SHORT *vector, INT len);
INT getScalefactorPCM(const INT_PCM *vector, INT len, INT stride);
INT getScalefactor(const FIXP_DBL *vector, INT len);
diff --git a/libFDK/src/FDK_decorrelate.cpp b/libFDK/src/FDK_decorrelate.cpp
index c5de79a..324983a 100644
--- a/libFDK/src/FDK_decorrelate.cpp
+++ b/libFDK/src/FDK_decorrelate.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -227,7 +227,7 @@ static inline int SpatialDecGetQmfBand(int paramBand, const UCHAR *tab) {
}
#define DUCKER_MAX_NRG_SCALE (24)
-#define DUCKER_HEADROOM_BITS (3)
+#define DUCKER_HEADROOM_BITS (2)
#define FILTER_SF (2)
@@ -606,10 +606,6 @@ static INT DecorrFilterApplyPASS(DECORR_FILTER_INSTANCE const filter[],
dataImagIn += start;
dataRealOut += start;
dataImagOut += start;
-#ifdef FUNCTION_DecorrFilterApplyPASS_func1
- DecorrFilterApplyPASS_func1(i, dataRealIn, dataImagIn, dataRealOut,
- dataImagOut, pDelayBuffer, offset);
-#else
do {
FIXP_DBL delay_re, delay_im, real, imag;
@@ -623,7 +619,6 @@ static INT DecorrFilterApplyPASS(DECORR_FILTER_INSTANCE const filter[],
*dataImagOut++ = delay_im;
pDelayBuffer += offset;
} while (--i != 0);
-#endif
}
}
@@ -1061,24 +1056,15 @@ static INT DuckerCalcEnergy(DUCKER_INSTANCE *const self,
FIXP_DBL maxVal = FL2FXCONST_DBL(-1.0f);
if (maxVal == FL2FXCONST_DBL(-1.0f)) {
-#ifdef FUNCTION_DuckerCalcEnergy_func2
- maxVal = DuckerCalcEnergy_func2(inputReal, inputImag, startHybBand,
- maxHybBand, maxHybridBand);
-#else
- FIXP_DBL localMaxVal = FL2FXCONST_DBL(0.0f);
- for (qs = startHybBand; qs <= maxHybBand; qs++) {
- localMaxVal |= fAbs(inputReal[qs]);
- localMaxVal |= fAbs(inputImag[qs]);
- }
- for (; qs <= maxHybridBand; qs++) {
- localMaxVal |= fAbs(inputReal[qs]);
- }
- maxVal = localMaxVal;
-#endif
+ clz = fMin(getScalefactor(&inputReal[startHybBand],
+ fMax(0, maxHybridBand - startHybBand + 1)),
+ getScalefactor(&inputImag[startHybBand],
+ fMax(0, maxHybBand - startHybBand + 1)));
+ } else {
+ clz = CntLeadingZeros(maxVal) - 1;
}
- clz = fixMax(0, CntLeadingZeros(maxVal) - DUCKER_HEADROOM_BITS);
- clz = fixMin(clz, DUCKER_MAX_NRG_SCALE);
+ clz = fMin(fMax(0, clz - DUCKER_HEADROOM_BITS), DUCKER_MAX_NRG_SCALE);
*nrgScale = (SCHAR)clz << 1;
/* Initialize pb since it would stay uninitialized for the case startHybBand
@@ -1086,9 +1072,10 @@ static INT DuckerCalcEnergy(DUCKER_INSTANCE *const self,
pb = SpatialDecGetProcessingBand(maxHybBand, self->mapHybBands2ProcBands);
for (qs = startHybBand; qs <= maxHybBand; qs++) {
pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands);
- energy[pb] =
- fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz) +
- fPow2Div2(inputImag[qs] << clz));
+ energy[pb] = SATURATE_LEFT_SHIFT(
+ (energy[pb] >> 1) + (fPow2Div2(inputReal[qs] << clz) >> 1) +
+ (fPow2Div2(inputImag[qs] << clz) >> 1),
+ 1, DFRACT_BITS);
}
pb++;
@@ -1112,43 +1099,29 @@ static INT DuckerCalcEnergy(DUCKER_INSTANCE *const self,
maxVal = inputMaxVal;
if (maxVal == FL2FXCONST_DBL(-1.0f)) {
-#ifdef FUNCTION_DuckerCalcEnergy_func2
- maxVal = DuckerCalcEnergy_func2(inputReal, inputImag, startHybBand,
- maxHybBand, maxHybridBand);
-#else
- FIXP_DBL localMaxVal = FL2FXCONST_DBL(0.0f);
- for (qs = startHybBand; qs <= maxHybBand; qs++) {
- localMaxVal |= fAbs(inputReal[qs]);
- localMaxVal |= fAbs(inputImag[qs]);
- }
- for (; qs <= maxHybridBand; qs++) {
- localMaxVal |= fAbs(inputReal[qs]);
- }
- maxVal = localMaxVal;
-#endif
+ clz = fMin(getScalefactor(&inputReal[startHybBand],
+ fMax(0, maxHybridBand - startHybBand + 1)),
+ getScalefactor(&inputImag[startHybBand],
+ fMax(0, maxHybBand - startHybBand + 1)));
+ } else {
+ clz = CntLeadingZeros(maxVal) - 1;
}
- clz = fixMax(0, CntLeadingZeros(maxVal) - DUCKER_HEADROOM_BITS);
- clz = fixMin(clz, DUCKER_MAX_NRG_SCALE);
+ clz = fMin(fMax(0, clz - DUCKER_HEADROOM_BITS), DUCKER_MAX_NRG_SCALE);
*nrgScale = (SCHAR)clz << 1;
-#ifdef FUNCTION_DuckerCalcEnergy_func4
- DuckerCalcEnergy_func4(inputReal, inputImag, energy,
- self->mapHybBands2ProcBands, clz, startHybBand,
- maxHybBand, maxHybridBand);
-#else
for (qs = startHybBand; qs <= maxHybBand; qs++) {
int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands);
- energy[pb] =
- fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz) +
- fPow2Div2(inputImag[qs] << clz));
+ energy[pb] = SATURATE_LEFT_SHIFT(
+ (energy[pb] >> 1) + (fPow2Div2(inputReal[qs] << clz) >> 1) +
+ (fPow2Div2(inputImag[qs] << clz) >> 1),
+ 1, DFRACT_BITS);
}
for (; qs <= maxHybridBand; qs++) {
int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands);
energy[pb] = fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz));
}
-#endif /* FUNCTION_DuckerCalcEnergy_func4 */
}
{
@@ -1295,10 +1268,6 @@ static INT DuckerApply(DUCKER_INSTANCE *const self,
}
}
-#ifdef FUNCTION_DuckerApply_func1
- qs = DuckerApply_func1(qs, hybBands, qs_next, outputReal, outputImag,
- duckGain);
-#else
/* general gain*output section */
if (qs < hybBands) { /* true for about 39% */
for (; qs < qs_next; qs++) { /* runs about 2 times */
@@ -1310,7 +1279,6 @@ static INT DuckerApply(DUCKER_INSTANCE *const self,
outputReal[qs] = fMultDiv2(outputReal[qs], duckGain) << 2;
}
}
-#endif
} /* pb */
self->headroomSmoothDirRevNrg =
diff --git a/libFDK/src/dct.cpp b/libFDK/src/dct.cpp
index 776493e..bd26736 100644
--- a/libFDK/src/dct.cpp
+++ b/libFDK/src/dct.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -489,18 +489,18 @@ void dst_IV(FIXP_DBL *pDat, int L, int *pDat_e) {
for (i = 0; i < M - 1; i += 2, pDat_0 += 2, pDat_1 -= 2) {
FIXP_DBL accu1, accu2, accu3, accu4;
- accu1 = pDat_1[1];
- accu2 = -pDat_0[0];
- accu3 = pDat_0[1];
- accu4 = -pDat_1[0];
+ accu1 = pDat_1[1] >> 1;
+ accu2 = -(pDat_0[0] >> 1);
+ accu3 = pDat_0[1] >> 1;
+ accu4 = -(pDat_1[0] >> 1);
cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]);
cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]);
- pDat_0[0] = accu2 >> 1;
- pDat_0[1] = accu1 >> 1;
- pDat_1[0] = accu4 >> 1;
- pDat_1[1] = -(accu3 >> 1);
+ pDat_0[0] = accu2;
+ pDat_0[1] = accu1;
+ pDat_1[0] = accu4;
+ pDat_1[1] = -accu3;
}
if (M & 1) {
FIXP_DBL accu1, accu2;
diff --git a/libFDK/src/qmf.cpp b/libFDK/src/qmf.cpp
index 69f7e05..19f1ea1 100644
--- a/libFDK/src/qmf.cpp
+++ b/libFDK/src/qmf.cpp
@@ -609,9 +609,9 @@ inline static void qmfInverseModulationLP_even(
FIXP_DBL *RESTRICT tImag = pTimeOut + L;
/* Move input to output vector with offset */
- scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, (int)scaleFactorLowBand);
- scaleValues(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb],
- synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand);
+ scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand);
+ scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb],
+ synQmf->usb - synQmf->lsb, scaleFactorHighBand);
FDKmemclear(&tReal[0 + synQmf->usb], (L - synQmf->usb) * sizeof(FIXP_DBL));
/* Dct type-2 transform */
@@ -662,9 +662,9 @@ inline static void qmfInverseModulationLP_odd(
int shift = 0;
/* Move input to output vector with offset */
- scaleValues(pTimeOut + M, qmfReal, synQmf->lsb, scaleFactorLowBand);
- scaleValues(pTimeOut + M + synQmf->lsb, qmfReal + synQmf->lsb,
- synQmf->usb - synQmf->lsb, scaleFactorHighBand);
+ scaleValuesSaturate(pTimeOut + M, qmfReal, synQmf->lsb, scaleFactorLowBand);
+ scaleValuesSaturate(pTimeOut + M + synQmf->lsb, qmfReal + synQmf->lsb,
+ synQmf->usb - synQmf->lsb, scaleFactorHighBand);
FDKmemclear(pTimeOut + M + synQmf->usb, (L - synQmf->usb) * sizeof(FIXP_DBL));
dct_IV(pTimeOut + M, L, &shift);
@@ -698,26 +698,27 @@ inline static void qmfInverseModulationHQ(
FIXP_DBL *RESTRICT tImag = pWorkBuffer + L;
if (synQmf->flags & QMF_FLAG_CLDFB) {
- for (i = 0; i < synQmf->lsb; i++) {
- cplxMult(&tImag[i], &tReal[i], scaleValue(qmfImag[i], scaleFactorLowBand),
- scaleValue(qmfReal[i], scaleFactorLowBand), synQmf->t_cos[i],
- synQmf->t_sin[i]);
- }
- for (; i < synQmf->usb; i++) {
- cplxMult(&tImag[i], &tReal[i],
- scaleValue(qmfImag[i], scaleFactorHighBand),
- scaleValue(qmfReal[i], scaleFactorHighBand), synQmf->t_cos[i],
- synQmf->t_sin[i]);
+ for (i = 0; i < synQmf->usb; i++) {
+ cplxMultDiv2(&tImag[i], &tReal[i], qmfImag[i], qmfReal[i],
+ synQmf->t_cos[i], synQmf->t_sin[i]);
}
+ scaleValuesSaturate(&tReal[0], synQmf->lsb, scaleFactorLowBand + 1);
+ scaleValuesSaturate(&tReal[0 + synQmf->lsb], synQmf->usb - synQmf->lsb,
+ scaleFactorHighBand + 1);
+ scaleValuesSaturate(&tImag[0], synQmf->lsb, scaleFactorLowBand + 1);
+ scaleValuesSaturate(&tImag[0 + synQmf->lsb], synQmf->usb - synQmf->lsb,
+ scaleFactorHighBand + 1);
}
if ((synQmf->flags & QMF_FLAG_CLDFB) == 0) {
- scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, (int)scaleFactorLowBand);
- scaleValues(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb],
- synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand);
- scaleValues(&tImag[0], &qmfImag[0], synQmf->lsb, (int)scaleFactorLowBand);
- scaleValues(&tImag[0 + synQmf->lsb], &qmfImag[0 + synQmf->lsb],
- synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand);
+ scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb,
+ scaleFactorLowBand);
+ scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb],
+ synQmf->usb - synQmf->lsb, scaleFactorHighBand);
+ scaleValuesSaturate(&tImag[0], &qmfImag[0], synQmf->lsb,
+ scaleFactorLowBand);
+ scaleValuesSaturate(&tImag[0 + synQmf->lsb], &qmfImag[0 + synQmf->lsb],
+ synQmf->usb - synQmf->lsb, scaleFactorHighBand);
}
FDKmemclear(&tReal[synQmf->usb],
diff --git a/libFDK/src/scale.cpp b/libFDK/src/scale.cpp
index 24a8a5b..6192170 100644
--- a/libFDK/src/scale.cpp
+++ b/libFDK/src/scale.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -250,10 +250,10 @@ void scaleValuesSaturate(FIXP_DBL *vector, /*!< Vector */
*/
#define FUNCTION_scaleValuesSaturate_DBL_DBL
SCALE_INLINE
-void scaleValuesSaturate(FIXP_DBL *dst, /*!< Output */
- FIXP_DBL *src, /*!< Input */
- INT len, /*!< Length */
- INT scalefactor /*!< Scalefactor */
+void scaleValuesSaturate(FIXP_DBL *dst, /*!< Output */
+ const FIXP_DBL *src, /*!< Input */
+ INT len, /*!< Length */
+ INT scalefactor /*!< Scalefactor */
) {
INT i;
@@ -285,10 +285,10 @@ void scaleValuesSaturate(FIXP_DBL *dst, /*!< Output */
*/
#define FUNCTION_scaleValuesSaturate_SGL_DBL
SCALE_INLINE
-void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */
- FIXP_DBL *src, /*!< Input */
- INT len, /*!< Length */
- INT scalefactor) /*!< Scalefactor */
+void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */
+ const FIXP_DBL *src, /*!< Input */
+ INT len, /*!< Length */
+ INT scalefactor) /*!< Scalefactor */
{
INT i;
scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1),
@@ -345,10 +345,10 @@ void scaleValuesSaturate(FIXP_SGL *vector, /*!< Vector */
*/
#define FUNCTION_scaleValuesSaturate_SGL_SGL
SCALE_INLINE
-void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */
- FIXP_SGL *src, /*!< Input */
- INT len, /*!< Length */
- INT scalefactor /*!< Scalefactor */
+void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */
+ const FIXP_SGL *src, /*!< Input */
+ INT len, /*!< Length */
+ INT scalefactor /*!< Scalefactor */
) {
INT i;
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index ad13378..82f840e 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -1325,9 +1325,9 @@ static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc,
CSTpCallBacks *cb) {
TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
CSEldSpecificConfig *esc = &asc->m_sc.m_eldSpecificConfig;
- ASC_ELD_EXT_TYPE eldExtType;
+ UINT eldExtType;
int eldExtLen, len, cnt, ldSbrLen = 0, eldExtLenSum, numSbrHeader = 0,
- sbrIndex;
+ sbrIndex, eldExtCnt = 0;
unsigned char downscale_fill_nibble;
@@ -1394,9 +1394,8 @@ static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc,
eldExtLenSum = FDKgetValidBits(hBs);
esc->m_downscaledSamplingFrequency = asc->m_samplingFrequency;
/* parse ExtTypeConfigData */
- while (
- ((eldExtType = (ASC_ELD_EXT_TYPE)FDKreadBits(hBs, 4)) != ELDEXT_TERM) &&
- ((INT)FDKgetValidBits(hBs) >= 0)) {
+ while (((eldExtType = FDKreadBits(hBs, 4)) != ELDEXT_TERM) &&
+ ((INT)FDKgetValidBits(hBs) >= 0) && (eldExtCnt++ < 15)) {
eldExtLen = len = FDKreadBits(hBs, 4);
if (len == 0xf) {
len = FDKreadBits(hBs, 8);
@@ -1455,6 +1454,9 @@ static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc,
break;
}
}
+ if (eldExtType != ELDEXT_TERM) {
+ return TRANSPORTDEC_PARSE_ERROR;
+ }
if ((INT)FDKgetValidBits(hBs) < 0) {
return TRANSPORTDEC_PARSE_ERROR;
diff --git a/libPCMutils/src/limiter.cpp b/libPCMutils/src/limiter.cpp
index a799a51..60e3e3b 100644
--- a/libPCMutils/src/limiter.cpp
+++ b/libPCMutils/src/limiter.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -239,8 +239,8 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
tmp1 = (FIXP_DBL)0;
for (j = 0; j < channels; j++) {
tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]);
- tmp2 = fAbs(tmp2);
- tmp2 = FIXP_DBL(INT(tmp2) ^ INT((tmp2 >> (SAMPLE_BITS_LIM - 1))));
+ tmp2 =
+ (tmp2 == (FIXP_DBL)MINVAL_DBL) ? (FIXP_DBL)MAXVAL_DBL : fAbs(tmp2);
tmp1 = fMax(tmp1, tmp2);
}
tmp = fMult(tmp1, additionalGain);
diff --git a/libSACdec/src/sac_bitdec.cpp b/libSACdec/src/sac_bitdec.cpp
index 4b47132..4485ccf 100644
--- a/libSACdec/src/sac_bitdec.cpp
+++ b/libSACdec/src/sac_bitdec.cpp
@@ -1610,6 +1610,10 @@ static SACDEC_ERROR mapIndexData(
} /* for( i = 0 ; i < numParameterSets; i++ ) */
if (extendFrame) {
+ if (paramType == t_IPD) {
+ llData->bsQuantCoarseXXX[numParameterSets] =
+ llData->bsQuantCoarseXXX[numParameterSets - 1];
+ }
for (band = startBand; band < stopBand; band++) {
outputDataIdx[xttIdx][numParameterSets][band] =
outputDataIdx[xttIdx][numParameterSets - 1][band];
diff --git a/libSACdec/src/sac_stp.cpp b/libSACdec/src/sac_stp.cpp
index 818e9df..6ac5a56 100644
--- a/libSACdec/src/sac_stp.cpp
+++ b/libSACdec/src/sac_stp.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -106,6 +106,8 @@ amm-info@iis.fraunhofer.de
#include "FDK_matrixCalloc.h"
#include "sac_rom.h"
+#define SF_FREQ_DOMAIN_HEADROOM (2 * (1))
+
#define BP_GF_START 6
#define BP_GF_SIZE 25
#define HP_SIZE 9
@@ -114,6 +116,16 @@ amm-info@iis.fraunhofer.de
#define SF_WET 5
#define SF_DRY \
3 /* SF_DRY == 2 would produce good conformance test results as well */
+#define SF_DRY_NRG \
+ (4 - 1) /* 8.495f = sum(BP_GF__FDK[i]) \
+ i=0,..,(sizeof(BP_GF__FDK)/sizeof(FIXP_CFG)-1) => energy \
+ calculation needs 4 bits headroom, headroom can be reduced by 1 \
+ bit due to fPow2Div2() usage */
+#define SF_WET_NRG \
+ (4 - 1) /* 8.495f = sum(BP_GF__FDK[i]) \
+ i=0,..,(sizeof(BP_GF__FDK)/sizeof(FIXP_CFG)-1) => energy \
+ calculation needs 4 bits headroom, headroom can be reduced by 1 \
+ bit due to fPow2Div2() usage */
#define SF_PRODUCT_BP_GF 13
#define SF_PRODUCT_BP_GF_GF 26
#define SF_SCALE 2
@@ -172,18 +184,6 @@ amm-info@iis.fraunhofer.de
STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO)
*/
-#define DRY_ENER_WEIGHT(DryEner) DryEner = DryEner >> dry_scale_dmx
-
-#define WET_ENER_WEIGHT(WetEner) WetEner = WetEner << wet_scale_dmx
-
-#define DRY_ENER_SUM_REAL(DryEner, dmxReal, n) \
- DryEner += \
- fMultDiv2(fPow2Div2(dmxReal << SF_DRY), pBP[n]) >> ((2 * SF_DRY) - 2)
-
-#define DRY_ENER_SUM_CPLX(DryEner, dmxReal, dmxImag, n) \
- DryEner += fMultDiv2( \
- fPow2Div2(dmxReal << SF_DRY) + fPow2Div2(dmxImag << SF_DRY), pBP[n])
-
#define CALC_WET_SCALE(dryIdx, wetIdx) \
if ((DryEnerLD64[dryIdx] - STP_SCALE_LIMIT_HI_LD64) > WetEnerLD64[wetIdx]) { \
scale[wetIdx] = STP_SCALE_LIMIT_HI; \
@@ -305,12 +305,10 @@ SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) {
for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE));
- self->oldWetEnerLD64[ch] =
- FL2FXCONST_DBL(0.34375f); /* 32768.0*32768.0/2^(44-26-10) */
+ self->oldWetEnerLD64[ch] = FL2FXCONST_DBL(0.0);
}
for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) {
- self->oldDryEnerLD64[ch] =
- FL2FXCONST_DBL(0.1875f); /* 32768.0*32768.0/2^(44-26) */
+ self->oldDryEnerLD64[ch] = FL2FXCONST_DBL(0.0);
}
self->BP = BP__FDK;
@@ -364,7 +362,12 @@ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
{
cplxBands = BP_GF_SIZE;
cplxHybBands = self->hybridBands;
- dry_scale_dmx = (2 * SF_DRY) - 2;
+ if (self->treeConfig == TREE_212) {
+ dry_scale_dmx = 2; /* 2 bits to compensate fMultDiv2() and fPow2Div2()
+ used in energy calculation */
+ } else {
+ dry_scale_dmx = (2 * SF_DRY) - 2;
+ }
wet_scale_dmx = 2;
}
@@ -390,8 +393,12 @@ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
}
for (ch = 0; ch < self->numOutputChannels; ch++) {
- hStpDec->oldWetEnerLD64[ch] =
- CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
+ if (self->treeConfig == TREE_212)
+ hStpDec->oldWetEnerLD64[ch] =
+ CalcLdData(hStpDec->runWetEner[ch] + ABS_THR__FDK);
+ else
+ hStpDec->oldWetEnerLD64[ch] =
+ CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
}
} else {
hStpDec->update_old_ener++;
@@ -411,12 +418,33 @@ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
pBP = hStpDec->BP_GF - BP_GF_START;
switch (self->treeConfig) {
case TREE_212:
+ INT sMin, sNorm, sReal, sImag;
+
+ sReal = fMin(getScalefactor(&qmfOutputRealDry[i_LF][BP_GF_START],
+ cplxBands - BP_GF_START),
+ getScalefactor(&qmfOutputRealDry[i_RF][BP_GF_START],
+ cplxBands - BP_GF_START));
+ sImag = fMin(getScalefactor(&qmfOutputImagDry[i_LF][BP_GF_START],
+ cplxBands - BP_GF_START),
+ getScalefactor(&qmfOutputImagDry[i_RF][BP_GF_START],
+ cplxBands - BP_GF_START));
+ sMin = fMin(sReal, sImag) - 1;
+
for (n = BP_GF_START; n < cplxBands; n++) {
- dmxReal0 = qmfOutputRealDry[i_LF][n] + qmfOutputRealDry[i_RF][n];
- dmxImag0 = qmfOutputImagDry[i_LF][n] + qmfOutputImagDry[i_RF][n];
- DRY_ENER_SUM_CPLX(DryEner0, dmxReal0, dmxImag0, n);
+ dmxReal0 = scaleValue(qmfOutputRealDry[i_LF][n], sMin) +
+ scaleValue(qmfOutputRealDry[i_RF][n], sMin);
+ dmxImag0 = scaleValue(qmfOutputImagDry[i_LF][n], sMin) +
+ scaleValue(qmfOutputImagDry[i_RF][n], sMin);
+
+ DryEner0 += (fMultDiv2(fPow2Div2(dmxReal0), pBP[n]) +
+ fMultDiv2(fPow2Div2(dmxImag0), pBP[n])) >>
+ SF_DRY_NRG;
}
- DRY_ENER_WEIGHT(DryEner0);
+
+ sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_DRY_NRG + dry_scale_dmx -
+ (2 * sMin) + nrgScale;
+ DryEner0 = scaleValueSaturate(
+ DryEner0, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1)));
break;
default:;
}
@@ -424,7 +452,7 @@ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
/* normalise the 'direct' signals */
for (ch = 0; ch < self->numInputChannels; ch++) {
- DryEner[ch] = DryEner[ch] << (nrgScale);
+ if (self->treeConfig != TREE_212) DryEner[ch] = DryEner[ch] << nrgScale;
hStpDec->runDryEner[ch] =
fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) +
fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]);
@@ -436,10 +464,8 @@ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
}
}
- if (self->treeConfig == TREE_212) {
- for (; ch < MAX_INPUT_CHANNELS; ch++) {
- DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
- }
+ for (; ch < MAX_INPUT_CHANNELS; ch++) {
+ DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
}
/* normalise the 'diffuse' signals */
@@ -450,14 +476,30 @@ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
}
WetEnerX = FL2FXCONST_DBL(0.0f);
- for (n = BP_GF_START; n < cplxBands; n++) {
- tmp = fPow2Div2(qmfOutputRealWet[ch][n] << SF_WET);
- tmp += fPow2Div2(qmfOutputImagWet[ch][n] << SF_WET);
- WetEnerX += fMultDiv2(tmp, pBP[n]);
- }
- WET_ENER_WEIGHT(WetEnerX);
- WetEnerX = WetEnerX << (nrgScale);
+ if (self->treeConfig == TREE_212) {
+ INT sMin, sNorm;
+
+ sMin = fMin(getScalefactor(&qmfOutputRealWet[ch][BP_GF_START],
+ cplxBands - BP_GF_START),
+ getScalefactor(&qmfOutputImagWet[ch][BP_GF_START],
+ cplxBands - BP_GF_START));
+
+ for (n = BP_GF_START; n < cplxBands; n++) {
+ WetEnerX +=
+ (fMultDiv2(fPow2Div2(scaleValue(qmfOutputRealWet[ch][n], sMin)),
+ pBP[n]) +
+ fMultDiv2(fPow2Div2(scaleValue(qmfOutputImagWet[ch][n], sMin)),
+ pBP[n])) >>
+ SF_WET_NRG;
+ }
+ sNorm = SF_FREQ_DOMAIN_HEADROOM + SF_WET_NRG + wet_scale_dmx -
+ (2 * sMin) + nrgScale;
+ WetEnerX = scaleValueSaturate(
+ WetEnerX, fMax(fMin(sNorm, DFRACT_BITS - 1), -(DFRACT_BITS - 1)));
+ } else
+ FDK_ASSERT(self->treeConfig == TREE_212);
+
hStpDec->runWetEner[ch] =
fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) +
fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX);
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index 41c9e88..81f03f3 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -151,6 +151,9 @@ amm-info@iis.fraunhofer.de
#include "genericStds.h" /* need FDKpow() for debug outputs */
+#define MAX_SFB_NRG_HEADROOM (1)
+#define MAX_VAL_NRG_HEADROOM ((((FIXP_DBL)MAXVAL_DBL) >> MAX_SFB_NRG_HEADROOM))
+
typedef struct {
FIXP_DBL nrgRef[MAX_FREQ_COEFFS];
FIXP_DBL nrgEst[MAX_FREQ_COEFFS];
@@ -986,7 +989,8 @@ void calculateSbrEnvelope(
*/
if (!useLP)
adj_e = h_sbr_cal_env->filtBufferNoise_e -
- getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands);
+ getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands) +
+ (INT)MAX_SFB_NRG_HEADROOM;
/*
Scan for maximum reference energy to be able
@@ -1006,7 +1010,7 @@ void calculateSbrEnvelope(
- Smoothing can smear high gains of the previous envelope into the
current
*/
- maxSfbNrg_e += 6;
+ maxSfbNrg_e += (6 + MAX_SFB_NRG_HEADROOM);
adj_e = maxSfbNrg_e;
// final_e should not exist for PVC fixfix framing
@@ -1032,7 +1036,7 @@ void calculateSbrEnvelope(
- Smoothing can smear high gains of the previous envelope into the
current
*/
- maxSfbNrg_e += 6;
+ maxSfbNrg_e += (6 + MAX_SFB_NRG_HEADROOM);
if (borders[i] < hHeaderData->numberTimeSlots)
/* This envelope affects timeslots that belong to the output frame */
@@ -2426,6 +2430,9 @@ static void adjustTimeSlot_EldGrid(
const FIXP_DBL *p_harmonicPhaseX = &harmonicPhaseX[harmIndex][0];
const INT *p_harmonicPhase = &harmonicPhase[harmIndex][0];
+ const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change;
+ const FIXP_DBL min_val = -max_val;
+
*(ptrReal - 1) = fAddSaturate(
*(ptrReal - 1),
SATURATE_SHIFT(fMultDiv2(p_harmonicPhaseX[lowSubband & 1], pSineLevel[0]),
@@ -2438,7 +2445,8 @@ static void adjustTimeSlot_EldGrid(
FIXP_DBL sineLevel_curr = *pSineLevel++;
phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1);
- signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change);
+ signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val)
+ << scale_change;
sbNoise = *pNoiseLevel++;
if (((INT)sineLevel_curr | noNoiseFlag) == 0) {
signalReal +=
@@ -2472,7 +2480,8 @@ static void adjustTimeSlot_EldGrid(
FIXP_DBL sineLevel_curr = *pSineLevel++;
phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1);
- signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change);
+ signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val)
+ << scale_change;
sbNoise = *pNoiseLevel++;
if (((INT)sineLevel_curr | noNoiseFlag) == 0) {
signalReal +=
@@ -2512,6 +2521,8 @@ static void adjustTimeSlotLC(
FIXP_DBL signalReal, sineLevel, sineLevelNext, sineLevelPrev;
int tone_count = 0;
int sineSign = 1;
+ const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change;
+ const FIXP_DBL min_val = -max_val;
#define C1 ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.00815f))
#define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.16773f))
@@ -2527,7 +2538,8 @@ static void adjustTimeSlotLC(
of the signal and should be carried out with full accuracy
(supplying #FRACT_BITS valid bits).
*/
- signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change);
+ signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val)
+ << scale_change;
sineLevel = *pSineLevel++;
sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f);
@@ -2555,10 +2567,10 @@ static void adjustTimeSlotLC(
/* save switch and compare operations and reduce to XOR statement */
if (((harmIndex >> 1) & 0x1) ^ freqInvFlag) {
- *(ptrReal - 1) += tmp1;
+ *(ptrReal - 1) = fAddSaturate(*(ptrReal - 1), tmp1);
signalReal -= tmp2;
} else {
- *(ptrReal - 1) -= tmp1;
+ *(ptrReal - 1) = fAddSaturate(*(ptrReal - 1), -tmp1);
signalReal += tmp2;
}
*ptrReal++ = signalReal;
@@ -2589,7 +2601,9 @@ static void adjustTimeSlotLC(
/* The next multiplication constitutes the actual envelope adjustment of
* the signal. */
- signalReal += fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change);
+ signalReal +=
+ fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val)
+ << scale_change;
pNoiseLevel++;
*ptrReal++ = signalReal;
@@ -2602,7 +2616,8 @@ static void adjustTimeSlotLC(
index++;
/* The next multiplication constitutes the actual envelope adjustment of
* the signal. */
- signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change);
+ signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain++), max_val), min_val)
+ << scale_change;
if (*pSineLevel++ != FL2FXCONST_DBL(0.0f))
tone_count++;
@@ -2630,7 +2645,8 @@ static void adjustTimeSlotLC(
index++;
/* The next multiplication constitutes the actual envelope adjustment of the
* signal. */
- signalReal = fMultDiv2(*ptrReal, *pGain) << ((int)scale_change);
+ signalReal = fMax(fMin(fMultDiv2(*ptrReal, *pGain), max_val), min_val)
+ << scale_change;
sineLevelPrev = fMultDiv2(pSineLevel[-1], FL2FX_SGL(0.0163f));
sineLevel = pSineLevel[0];
@@ -2699,6 +2715,9 @@ static void adjustTimeSlotHQ_GainAndNoise(
/*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio;
int index = *ptrPhaseIndex;
int shift;
+ FIXP_DBL max_val_noise = 0, min_val_noise = 0;
+ const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change;
+ const FIXP_DBL min_val = -max_val;
*ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1);
@@ -2708,6 +2727,8 @@ static void adjustTimeSlotHQ_GainAndNoise(
shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift);
} else {
shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift);
+ max_val_noise = MAX_VAL_NRG_HEADROOM >> shift;
+ min_val_noise = -max_val_noise;
}
if (smooth_ratio > FL2FXCONST_SGL(0.0f)) {
@@ -2723,8 +2744,10 @@ static void adjustTimeSlotHQ_GainAndNoise(
smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) +
fMult(direct_ratio, noiseLevel[k]);
} else {
- smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) << shift) +
- fMult(direct_ratio, noiseLevel[k]);
+ smoothedNoise = fMultDiv2(smooth_ratio, filtBufferNoise[k]);
+ smoothedNoise =
+ (fMax(fMin(smoothedNoise, max_val_noise), min_val_noise) << shift) +
+ fMult(direct_ratio, noiseLevel[k]);
}
/*
@@ -2732,8 +2755,12 @@ static void adjustTimeSlotHQ_GainAndNoise(
of the signal and should be carried out with full accuracy
(supplying #DFRACT_BITS valid bits).
*/
- signalReal = fMultDiv2(*ptrReal, smoothedGain) << ((int)scale_change);
- signalImag = fMultDiv2(*ptrImag, smoothedGain) << ((int)scale_change);
+ signalReal =
+ fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val)
+ << scale_change;
+ signalImag =
+ fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val)
+ << scale_change;
index++;
@@ -2755,8 +2782,12 @@ static void adjustTimeSlotHQ_GainAndNoise(
} else {
for (k = 0; k < noSubbands; k++) {
smoothedGain = gain[k];
- signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change;
- signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change;
+ signalReal =
+ fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val)
+ << scale_change;
+ signalImag =
+ fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val)
+ << scale_change;
index++;
@@ -2862,6 +2893,9 @@ static void adjustTimeSlotHQ(
int freqInvFlag = (lowSubband & 1);
FIXP_DBL sineLevel;
int shift;
+ FIXP_DBL max_val_noise = 0, min_val_noise = 0;
+ const FIXP_DBL max_val = MAX_VAL_NRG_HEADROOM >> scale_change;
+ const FIXP_DBL min_val = -max_val;
*ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1);
*ptrHarmIndex = (harmIndex + 1) & 3;
@@ -2877,10 +2911,13 @@ static void adjustTimeSlotHQ(
filtBufferNoiseShift +=
1; /* due to later use of fMultDiv2 instead of fMult */
- if (filtBufferNoiseShift < 0)
+ if (filtBufferNoiseShift < 0) {
shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift);
- else
+ } else {
shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift);
+ max_val_noise = MAX_VAL_NRG_HEADROOM >> shift;
+ min_val_noise = -max_val_noise;
+ }
if (smooth_ratio > FL2FXCONST_SGL(0.0f)) {
for (k = 0; k < noSubbands; k++) {
@@ -2896,8 +2933,10 @@ static void adjustTimeSlotHQ(
smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) +
fMult(direct_ratio, noiseLevel[k]);
} else {
- smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) << shift) +
- fMult(direct_ratio, noiseLevel[k]);
+ smoothedNoise = fMultDiv2(smooth_ratio, filtBufferNoise[k]);
+ smoothedNoise =
+ (fMax(fMin(smoothedNoise, max_val_noise), min_val_noise) << shift) +
+ fMult(direct_ratio, noiseLevel[k]);
}
/*
@@ -2905,8 +2944,12 @@ static void adjustTimeSlotHQ(
of the signal and should be carried out with full accuracy
(supplying #DFRACT_BITS valid bits).
*/
- signalReal = fMultDiv2(*ptrReal, smoothedGain) << ((int)scale_change);
- signalImag = fMultDiv2(*ptrImag, smoothedGain) << ((int)scale_change);
+ signalReal =
+ fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val)
+ << scale_change;
+ signalImag =
+ fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val)
+ << scale_change;
index++;
@@ -2959,8 +3002,12 @@ static void adjustTimeSlotHQ(
} else {
for (k = 0; k < noSubbands; k++) {
smoothedGain = gain[k];
- signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change;
- signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change;
+ signalReal =
+ fMax(fMin(fMultDiv2(*ptrReal, smoothedGain), max_val), min_val)
+ << scale_change;
+ signalImag =
+ fMax(fMin(fMultDiv2(*ptrImag, smoothedGain), max_val), min_val)
+ << scale_change;
index++;
@@ -3144,6 +3191,11 @@ ResetLimiterBands(
return SBRDEC_UNSUPPORTED_CONFIG;
}
+ /* Restrict maximum value of limiter band table */
+ if (workLimiterBandTable[tempNoLim] > highSubband) {
+ return SBRDEC_UNSUPPORTED_CONFIG;
+ }
+
/* Copy limiterbands from working buffer into final destination */
for (k = 0; k <= nBands; k++) {
limiterBandTable[k] = workLimiterBandTable[k];
diff --git a/libSBRdec/src/lpp_tran.cpp b/libSBRdec/src/lpp_tran.cpp
index 6acb626..93e1158 100644
--- a/libSBRdec/src/lpp_tran.cpp
+++ b/libSBRdec/src/lpp_tran.cpp
@@ -1014,8 +1014,8 @@ void lppTransposerHBE(
pSettings->nCols) +
lowBandShift);
- dynamicScale = fixMax(
- 0, dynamicScale - 1); /* one additional bit headroom to prevent -1.0 */
+ dynamicScale =
+ dynamicScale - 1; /* one additional bit headroom to prevent -1.0 */
/*
Scale temporal QMF buffer.
@@ -1194,6 +1194,9 @@ void lppTransposerHBE(
} else { /* bw <= 0 */
int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
+ dynamicScale +=
+ 1; /* prevent negativ scale factor due to 'one additional bit
+ headroom' */
for (i = startSample; i < stopSample; i++) {
FIXP_DBL accu1, accu2;
@@ -1210,9 +1213,9 @@ void lppTransposerHBE(
dynamicScale;
qmfBufferReal[i][loBand] =
- (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1);
+ (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << (1 + 1));
qmfBufferImag[i][loBand] =
- (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1);
+ (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << (1 + 1));
}
} /* bw <= 0 */
diff --git a/libSBRdec/src/pvc_dec.cpp b/libSBRdec/src/pvc_dec.cpp
index b477122..e1e3c2c 100644
--- a/libSBRdec/src/pvc_dec.cpp
+++ b/libSBRdec/src/pvc_dec.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -534,7 +534,8 @@ void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData,
for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) {
for (band = sg_borders[ksg]; band < sg_borders[ksg + 1]; band++) {
/* The division by 8 == (RATE*lbw) is required algorithmically */
- E[ksg] += (fPow2Div2(qmfR[band]) + fPow2Div2(qmfI[band])) >> 2;
+ E[ksg] +=
+ ((fPow2Div2(qmfR[band]) >> 1) + (fPow2Div2(qmfI[band]) >> 1)) >> 3;
}
}
}
@@ -542,7 +543,7 @@ void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData,
if (E[ksg] > (FIXP_DBL)0) {
/* 10/log2(10) = 0.752574989159953 * 2^2 */
int exp_log;
- FIXP_DBL nrg = CalcLog2(E[ksg], 2 * qmfExponent, &exp_log);
+ FIXP_DBL nrg = CalcLog2(E[ksg], 2 * qmfExponent + 2, &exp_log);
nrg = fMult(nrg, FL2FXCONST_SGL(LOG10FAC));
nrg = scaleValue(nrg, exp_log - PVC_ESG_EXP + 2);
pEsg[ksg] = fMax(nrg, FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)));
@@ -603,22 +604,22 @@ void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData,
E_high_exp[ksg] = 0;
/* residual part */
- accu = ((LONG)(SCHAR)*pTab2++) << (DFRACT_BITS - 8 - PVC_ESG_EXP +
+ accu = ((LONG)(SCHAR)*pTab2++) << (DFRACT_BITS - 8 - PVC_ESG_EXP - 2 +
pPvcDynamicData->pScalingCoef[3]);
/* linear combination of lower grouped energies part */
for (kb = 0; kb < PVC_NBLOW; kb++) {
predCoeff = (FIXP_SGL)(
(SHORT)(SCHAR)pTab1[kb * pPvcDynamicData->nbHigh + ksg] << 8);
- predCoeff_exp = pPvcDynamicData->pScalingCoef[kb] +
- 1; /* +1 to compensate for Div2 */
- accu += fMultDiv2(E[kb], predCoeff) << predCoeff_exp;
+ predCoeff_exp = -(pPvcDynamicData->pScalingCoef[kb] + 1 -
+ 2); /* +1 to compensate for Div2; -2 for accu */
+ accu += fMultDiv2(E[kb], predCoeff) >> predCoeff_exp;
}
/* convert back to linear domain */
accu = fMult(accu, FL2FXCONST_SGL(LOG10FAC_INV));
- accu = f2Pow(
- accu, PVC_ESG_EXP - 1,
- &predCoeff_exp); /* -1 compensates for exponent of LOG10FAC_INV */
+ accu = f2Pow(accu, PVC_ESG_EXP - 1 + 2,
+ &predCoeff_exp); /* -1 compensates for exponent of
+ LOG10FAC_INV; +2 for accu */
predictedEsgSlot[ksg] = accu;
E_high_exp[ksg] = predCoeff_exp;
if (predCoeff_exp > E_high_exp_max) {
@@ -628,8 +629,8 @@ void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData,
/* rescale output vector according to largest exponent */
for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) {
- int scale = E_high_exp[ksg] - E_high_exp_max;
- predictedEsgSlot[ksg] = scaleValue(predictedEsgSlot[ksg], scale);
+ int scale = fMin(E_high_exp_max - E_high_exp[ksg], DFRACT_BITS - 1);
+ predictedEsgSlot[ksg] = predictedEsgSlot[ksg] >> scale;
}
*predictedEsg_exp = E_high_exp_max;
}