aboutsummaryrefslogtreecommitdiffstats
path: root/libSBRdec/src
diff options
context:
space:
mode:
authorJean-Michel Trivi <jmtrivi@google.com>2016-04-09 05:44:33 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-04-09 05:44:33 +0000
commit3b6fe4a90f0e82094a7e5826bf0b3517faf9cfcc (patch)
tree359ed01256a717b0161bfba21783634f1250471a /libSBRdec/src
parent4a5a256a01c0f6aa0ebd1b94bba77a70fcac75ee (diff)
parent3fbcee802021fc12db8fd6e9e346a2111fe333a9 (diff)
downloadfdk-aac-3b6fe4a90f0e82094a7e5826bf0b3517faf9cfcc.tar.gz
fdk-aac-3b6fe4a90f0e82094a7e5826bf0b3517faf9cfcc.tar.bz2
fdk-aac-3b6fe4a90f0e82094a7e5826bf0b3517faf9cfcc.zip
AAC/SBR decoder improvements and bugfixes am: 203e3f2
am: 3fbcee8 * commit '3fbcee802021fc12db8fd6e9e346a2111fe333a9': AAC/SBR decoder improvements and bugfixes Change-Id: Ic370a51ba08eb6079ab1b74413385e35bf29ecba
Diffstat (limited to 'libSBRdec/src')
-rw-r--r--libSBRdec/src/env_calc.cpp204
-rw-r--r--libSBRdec/src/env_dec.cpp4
-rw-r--r--libSBRdec/src/env_extr.cpp4
-rw-r--r--libSBRdec/src/env_extr.h12
-rw-r--r--libSBRdec/src/sbr_dec.cpp62
-rw-r--r--libSBRdec/src/sbr_dec.h8
-rw-r--r--libSBRdec/src/sbr_ram.h3
-rw-r--r--libSBRdec/src/sbr_rom.cpp11
-rw-r--r--libSBRdec/src/sbr_rom.h3
-rw-r--r--libSBRdec/src/sbrdecoder.cpp177
10 files changed, 389 insertions, 99 deletions
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index ade57fc..fa5330a 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -151,13 +151,13 @@ typedef struct
}
ENV_CALC_NRGS;
-/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,
+static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,
SCHAR *filtBuffer_e,
FIXP_DBL *NrgGain,
SCHAR *NrgGain_e,
int subbands);
-/*static*/ void calcNrgPerSubband(FIXP_DBL **analysBufferReal,
+static void calcNrgPerSubband(FIXP_DBL **analysBufferReal,
FIXP_DBL **analysBufferImag,
int lowSubband, int highSubband,
int start_pos, int next_pos,
@@ -165,7 +165,7 @@ ENV_CALC_NRGS;
FIXP_DBL *nrgEst,
SCHAR *nrgEst_e );
-/*static*/ void calcNrgPerSfb(FIXP_DBL **analysBufferReal,
+static void calcNrgPerSfb(FIXP_DBL **analysBufferReal,
FIXP_DBL **analysBufferImag,
int nSfb,
UCHAR *freqBandTable,
@@ -174,13 +174,13 @@ ENV_CALC_NRGS;
FIXP_DBL *nrg_est,
SCHAR *nrg_est_e );
-/*static*/ void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c,
+static void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c,
FIXP_DBL tmpNoise, SCHAR tmpNoise_e,
UCHAR sinePresentFlag,
UCHAR sineMapped,
int noNoiseFlag);
-/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs,
+static void calcAvgGain(ENV_CALC_NRGS* nrgs,
int lowSubband,
int highSubband,
FIXP_DBL *sumRef_m,
@@ -188,7 +188,7 @@ ENV_CALC_NRGS;
FIXP_DBL *ptrAvgGain_m,
SCHAR *ptrAvgGain_e);
-/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal,
+static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal,
ENV_CALC_NRGS* nrgs,
UCHAR *ptrHarmIndex,
int lowSubbands,
@@ -196,8 +196,17 @@ ENV_CALC_NRGS;
int scale_change,
int noNoiseFlag,
int *ptrPhaseIndex,
- int fCldfb);
-/*static*/ void adjustTimeSlotHQ(FIXP_DBL *ptrReal,
+ int scale_diff_low);
+
+static void adjustTimeSlotLC(FIXP_DBL *ptrReal,
+ ENV_CALC_NRGS* nrgs,
+ UCHAR *ptrHarmIndex,
+ int lowSubbands,
+ int noSubbands,
+ int scale_change,
+ int noNoiseFlag,
+ int *ptrPhaseIndex);
+static void adjustTimeSlotHQ(FIXP_DBL *ptrReal,
FIXP_DBL *ptrImag,
HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
ENV_CALC_NRGS* nrgs,
@@ -224,7 +233,7 @@ ENV_CALC_NRGS;
Additionally, the flags in harmFlagsPrev are being updated by this function
for the next frame.
*/
-/*static*/ void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */
+static void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */
int nSfb, /*!< Number of bands in the table */
UCHAR *addHarmonics, /*!< vector with 1 flag per sfb */
int *harmFlagsPrev, /*!< Packed 'addHarmonics' */
@@ -990,7 +999,6 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling
/* Prevent the smoothing filter from running on constant levels */
if (j-start_pos < smooth_length)
smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos];
-
else
smooth_ratio = FL2FXCONST_SGL(0.0f);
@@ -1007,7 +1015,8 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling
}
else
{
- adjustTimeSlotLC(&analysBufferReal[j][lowSubband],
+ if (flags & SBRDEC_ELD_GRID) {
+ adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband],
pNrgs,
&h_sbr_cal_env->harmIndex,
lowSubband,
@@ -1015,7 +1024,18 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling
scale_change,
noNoiseFlag,
&h_sbr_cal_env->phaseIndex,
- (flags & SBRDEC_ELD_GRID));
+ EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale);
+ } else
+ {
+ adjustTimeSlotLC(&analysBufferReal[j][lowSubband],
+ pNrgs,
+ &h_sbr_cal_env->harmIndex,
+ lowSubband,
+ noSubbands,
+ scale_change,
+ noNoiseFlag,
+ &h_sbr_cal_env->phaseIndex);
+ }
}
} // for
@@ -1176,7 +1196,7 @@ resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to env
can be performed.
This function is called once for each envelope before adjusting.
*/
-/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains */
+static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains */
SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */
FIXP_DBL *nrgGain, /*!< gains for current envelope */
SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */
@@ -1331,7 +1351,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
This function is used when interpolFreq is true.
*/
-/*static*/ void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */
+static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */
FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */
int lowSubband, /*!< Begin of the SBR frequency range */
int highSubband, /*!< High end of the SBR frequency range */
@@ -1452,7 +1472,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
This function is used when interpolFreq is false.
*/
-/*static*/ void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */
+static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */
FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */
int nSfb, /*!< Number of scale factor bands */
UCHAR *freqBandTable, /*!< First Subband for each Sfb */
@@ -1585,7 +1605,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
The resulting energy gain is given by mantissa and exponent.
*/
-/*static*/ void calcSubbandGain(FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */
+static void calcSubbandGain(FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */
SCHAR nrgRef_e, /*!< Reference Energy according to envelope data (exponent) */
ENV_CALC_NRGS* nrgs,
int i,
@@ -1689,7 +1709,7 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
The result is used as a relative limit for all gains within the
current "limiter band" (a certain frequency range).
*/
-/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs,
+static void calcAvgGain(ENV_CALC_NRGS* nrgs,
int lowSubband, /*!< Begin of the limiter band */
int highSubband, /*!< High end of the limiter band */
FIXP_DBL *ptrSumRef,
@@ -1728,21 +1748,101 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
*ptrSumRef_e = sumRef_e;
}
+static void adjustTimeSlot_EldGrid(
+ FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */
+ ENV_CALC_NRGS* nrgs,
+ UCHAR *ptrHarmIndex, /*!< Harmonic index */
+ int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */
+ int noSubbands, /*!< Number of QMF subbands */
+ int scale_change, /*!< Number of bits to shift adjusted samples */
+ int noNoiseFlag, /*!< Flag to suppress noise addition */
+ int *ptrPhaseIndex, /*!< Start index to random number array */
+ int scale_diff_low) /*!< */
+{
+ int k;
+ FIXP_DBL signalReal, sbNoise;
+ int tone_count = 0;
+
+ FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */
+ FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */
+ FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */
+
+ int phaseIndex = *ptrPhaseIndex;
+ UCHAR harmIndex = *ptrHarmIndex;
+
+ static const INT harmonicPhase [2][4] = {
+ { 1, 0, -1, 0},
+ { 0, 1, 0, -1}
+ };
+
+ static const FIXP_DBL harmonicPhaseX [2][4] = {
+ { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001) },
+ { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001) }
+ };
+
+ for (k=0; k < noSubbands; k++) {
+
+ phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1);
+
+ if( (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) || (noNoiseFlag == 1) ){
+ sbNoise = FL2FXCONST_DBL(0.0f);
+ } else {
+ sbNoise = pNoiseLevel[0];
+ }
+
+ signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change);
+
+ signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise)<<4);
+
+ signalReal += pSineLevel[0] * harmonicPhase[0][harmIndex];
+
+ *ptrReal = signalReal;
+
+ if (k == 0) {
+ *(ptrReal-1) += scaleValue(fMultDiv2(harmonicPhaseX[lowSubband&1][harmIndex], pSineLevel[0]), -scale_diff_low) ;
+ if (k < noSubbands - 1) {
+ *(ptrReal) += fMultDiv2(pSineLevel[1], harmonicPhaseX[(lowSubband+1)&1][harmIndex]);
+ }
+ }
+ if (k > 0 && k < noSubbands - 1 && tone_count < 16) {
+ *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1] [harmIndex]);
+ *(ptrReal) += fMultDiv2(pSineLevel[+ 1], harmonicPhaseX [(lowSubband+k+1)&1][harmIndex]);
+ }
+ if (k == noSubbands - 1 && tone_count < 16) {
+ if (k > 0) {
+ *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1][harmIndex]);
+ }
+ if (k + lowSubband + 1< 63) {
+ *(ptrReal+1) += fMultDiv2(pSineLevel[0], harmonicPhaseX[(lowSubband+k+1)&1][harmIndex]);
+ }
+ }
+
+ if(pSineLevel[0] != FL2FXCONST_DBL(0.0f)){
+ tone_count++;
+ }
+ ptrReal++;
+ pNoiseLevel++;
+ pGain++;
+ pSineLevel++;
+ }
+
+ *ptrHarmIndex = (harmIndex + 1) & 3;
+ *ptrPhaseIndex = phaseIndex & (SBR_NF_NO_RANDOM_VAL - 1);
+}
/*!
\brief Amplify one timeslot of the signal with the calculated gains
and add the noisefloor.
*/
-/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */
+static void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */
ENV_CALC_NRGS* nrgs,
UCHAR *ptrHarmIndex, /*!< Harmonic index */
int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */
int noSubbands, /*!< Number of QMF subbands */
int scale_change, /*!< Number of bits to shift adjusted samples */
int noNoiseFlag, /*!< Flag to suppress noise addition */
- int *ptrPhaseIndex, /*!< Start index to random number array */
- int fCldfb) /*!< CLDFB 80 flag */
+ int *ptrPhaseIndex) /*!< Start index to random number array */
{
FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */
FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */
@@ -1775,41 +1875,10 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f);
if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++;
-
else if (!noNoiseFlag)
/* Add noisefloor to the amplified signal */
signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
- if (fCldfb) {
-
- if (!(harmIndex&0x1)) {
- /* harmIndex 0,2 */
- signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel;
- *ptrReal++ = signalReal;
- }
- else {
- /* harmIndex 1,3 in combination with freqInvFlag */
- int shift = (int) (scale_change+1);
- shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift);
-
- FIXP_DBL tmp1 = scaleValue( fMultDiv2(C1_CLDFB, sineLevel), -shift );
-
- FIXP_DBL tmp2 = fMultDiv2(C1_CLDFB, sineLevelNext);
-
-
- /* save switch and compare operations and reduce to XOR statement */
- if ( ((harmIndex>>1)&0x1)^freqInvFlag) {
- *(ptrReal-1) += tmp1;
- signalReal -= tmp2;
- } else {
- *(ptrReal-1) -= tmp1;
- signalReal += tmp2;
- }
- *ptrReal++ = signalReal;
- freqInvFlag = !freqInvFlag;
- }
-
- } else
{
if (!(harmIndex&0x1)) {
/* harmIndex 0,2 */
@@ -1933,8 +2002,9 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output
*ptrHarmIndex = (harmIndex + 1) & 3;
*ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1);
}
-void adjustTimeSlotHQ(FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */
- FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */
+static void adjustTimeSlotHQ(
+ FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */
+ FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */
HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
ENV_CALC_NRGS* nrgs,
int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */
@@ -2137,7 +2207,6 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM
UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1];
int patchBorders[MAX_NUM_PATCHES + 1];
int kx, k2;
- FIXP_DBL temp;
int lowSubband = freqBandTable[0];
int highSubband = freqBandTable[noFreqBands];
@@ -2169,13 +2238,32 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM
while (hiLimIndex <= tempNoLim) {
+ FIXP_DBL div_m, oct_m, temp;
+ INT div_e = 0, oct_e = 0, temp_e = 0;
+
k2 = workLimiterBandTable[hiLimIndex] + lowSubband;
kx = workLimiterBandTable[loLimIndex] + lowSubband;
- temp = FX_SGL2FX_DBL(FDK_getNumOctavesDiv8(kx,k2)); /* Number of octaves */
- temp = fMult(temp, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[limiterBands]);
+ div_m = fDivNorm(k2, kx, &div_e);
+
+ /* calculate number of octaves */
+ oct_m = fLog2(div_m, div_e, &oct_e);
+
+ /* multiply with limiterbands per octave */
+ /* values 1, 1.2, 2, 3 -> scale factor of 2 */
+ temp = fMultNorm(oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], &temp_e);
+
+ /* overall scale factor of temp ist addition of scalefactors from log2 calculation,
+ limiter bands scalefactor (2) and limiter bands multiplication */
+ temp_e += oct_e + 2;
+
+ /* div can be a maximum of 64 (k2 = 64 and kx = 1)
+ -> oct can be a maximum of 6
+ -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum factor of 3)
+ -> we need a scale factor of 5 for comparisson
+ */
+ if (temp >> (5 - temp_e) < FL2FXCONST_DBL (0.49f) >> 5) {
- if (temp < FL2FXCONST_DBL (0.49f)>>5) {
if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) {
workLimiterBandTable[hiLimIndex] = highSubband;
nBands--;
diff --git a/libSBRdec/src/env_dec.cpp b/libSBRdec/src/env_dec.cpp
index 24b2d3b..c65c169 100644
--- a/libSBRdec/src/env_dec.cpp
+++ b/libSBRdec/src/env_dec.cpp
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -369,7 +369,7 @@ leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d
FIXP_SGL step; /* speed of fade */
int i;
- int currentStartPos = h_prev_data->stopPos - hHeaderData->numberTimeSlots;
+ int currentStartPos = FDKmax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots);
int currentStopPos = hHeaderData->numberTimeSlots;
diff --git a/libSBRdec/src/env_extr.cpp b/libSBRdec/src/env_extr.cpp
index 6cb0b99..dacd951 100644
--- a/libSBRdec/src/env_extr.cpp
+++ b/libSBRdec/src/env_extr.cpp
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -327,7 +327,7 @@ sbrGetHeaderData (HANDLE_SBR_HEADER_DATA hHeaderData,
}
/* Look for new settings. IEC 14496-3, 4.6.18.3.1 */
- if(hHeaderData->syncState != SBR_ACTIVE ||
+ if(hHeaderData->syncState < SBR_HEADER ||
lastHeader.startFreq != pBsData->startFreq ||
lastHeader.stopFreq != pBsData->stopFreq ||
lastHeader.freqScale != pBsData->freqScale ||
diff --git a/libSBRdec/src/env_extr.h b/libSBRdec/src/env_extr.h
index ab6b704..0518ea9 100644
--- a/libSBRdec/src/env_extr.h
+++ b/libSBRdec/src/env_extr.h
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -125,6 +125,7 @@ amm-info@iis.fraunhofer.de
typedef enum
{
HEADER_NOT_PRESENT,
+ HEADER_ERROR,
HEADER_OK,
HEADER_RESET
}
@@ -132,10 +133,10 @@ SBR_HEADER_STATUS;
typedef enum
{
- SBR_NOT_INITIALIZED,
- UPSAMPLING,
- SBR_HEADER,
- SBR_ACTIVE
+ SBR_NOT_INITIALIZED = 0,
+ UPSAMPLING = 1,
+ SBR_HEADER = 2,
+ SBR_ACTIVE = 3
}
SBR_SYNC_STATE;
@@ -179,6 +180,7 @@ typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA;
#define SBRDEC_LOW_POWER 16 /* Flag indicating that Low Power QMF mode shall be used. */
#define SBRDEC_PS_DECODED 32 /* Flag indicating that PS was decoded and rendered. */
#define SBRDEC_LD_MPS_QMF 512 /* Flag indicating that the LD-MPS QMF shall be used. */
+#define SBRDEC_SYNTAX_DRM 2048 /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */
#define SBRDEC_DOWNSAMPLE 8192 /* Flag indicating that the downsampling mode is used. */
#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */
#define SBRDEC_FORCE_RESET 32768 /* Flag is used to force a reset of all elements in use. */
diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp
index 1282338..0864348 100644
--- a/libSBRdec/src/sbr_dec.cpp
+++ b/libSBRdec/src/sbr_dec.cpp
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -225,7 +225,14 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand
}
if (resetAnaQmf) {
- int qmfErr = qmfInitAnalysisFilterBank (
+ QMF_FILTER_BANK prvAnaQmf;
+ int qmfErr;
+
+ /* Store current configuration */
+ FDKmemcpy(&prvAnaQmf, &hSbrDec->AnalysiscQMF, sizeof(QMF_FILTER_BANK));
+
+ /* Reset analysis QMF */
+ qmfErr = qmfInitAnalysisFilterBank (
&hSbrDec->AnalysiscQMF,
hSbrDec->anaQmfStates,
hSbrDec->AnalysiscQMF.no_col,
@@ -234,13 +241,22 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand
hSbrDec->AnalysiscQMF.no_channels,
anaQmfFlags | QMF_FLAG_KEEP_STATES
);
+
if (qmfErr != 0) {
- FDK_ASSERT(0);
+ /* Restore old configuration of analysis QMF */
+ FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK));
}
}
if (resetSynQmf) {
- int qmfErr = qmfInitSynthesisFilterBank (
+ QMF_FILTER_BANK prvSynQmf;
+ int qmfErr;
+
+ /* Store current configuration */
+ FDKmemcpy(&prvSynQmf, &hSbrDec->SynthesisQMF, sizeof(QMF_FILTER_BANK));
+
+ /* Reset synthesis QMF */
+ qmfErr = qmfInitSynthesisFilterBank (
&hSbrDec->SynthesisQMF,
hSbrDec->pSynQmfStates,
hSbrDec->SynthesisQMF.no_col,
@@ -251,7 +267,8 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand
);
if (qmfErr != 0) {
- FDK_ASSERT(0);
+ /* Restore old configuration of synthesis QMF */
+ FDKmemcpy(&hSbrDec->SynthesisQMF, &prvSynQmf, sizeof(QMF_FILTER_BANK));
}
}
}
@@ -321,7 +338,8 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */
HANDLE_PS_DEC h_ps_d,
- const UINT flags
+ const UINT flags,
+ const int codecFrameSize
)
{
int i, slot, reserve;
@@ -348,6 +366,33 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
if (flags & SBRDEC_ELD_GRID) {
/* Choose the right low delay filter bank */
changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 );
+
+ /* If the LD-MPS QMF is not available delay the signal by (96-48*ldSbrSamplingRate)
+ * samples according to ISO/IEC 14496-3:2009/FDAM 2:2010(E) chapter 4.5.2.13. */
+ if ( (flags & SBRDEC_LD_MPS_QMF)
+ && (hSbrDec->AnalysiscQMF.flags & QMF_FLAG_CLDFB) )
+ {
+ INT_PCM *pDlyBuf = hSbrDec->coreDelayBuf; /* DLYBUF */
+ int smpl, delay = 96 >> (!(flags & SBRDEC_DOWNSAMPLE) ? 1 : 0);
+ /* Create TMPBUF */
+ C_AALLOC_SCRATCH_START(pcmTemp, INT_PCM, (96));
+ /* Copy delay samples from INBUF to TMPBUF */
+ for (smpl = 0; smpl < delay; smpl += 1) {
+ pcmTemp[smpl] = timeIn[(codecFrameSize-delay+smpl)*strideIn];
+ }
+ /* Move input signal remainder to the very end of INBUF */
+ for (smpl = (codecFrameSize-delay-1)*strideIn; smpl >= 0; smpl -= strideIn) {
+ timeIn[smpl+delay] = timeIn[smpl];
+ }
+ /* Copy delayed samples from last frame from DLYBUF to the very beginning of INBUF */
+ for (smpl = 0; smpl < delay; smpl += 1) {
+ timeIn[smpl*strideIn] = pDlyBuf[smpl];
+ }
+ /* Copy TMPBUF to DLYBUF */
+ FDKmemcpy(pDlyBuf, pcmTemp, delay*sizeof(INT_PCM));
+ /* Destory TMPBUF */
+ C_AALLOC_SCRATCH_END(pcmTemp, INT_PCM, (96));
+ }
}
/*
@@ -761,7 +806,7 @@ createSbrDec (SBR_CHANNEL * hSbrChannel,
{
int qmfErr;
/* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */
- const UINT downSampledFlag = (downsampleFac==2) ? QMF_FLAG_DOWNSAMPLED : 0;
+ const UINT downSampledFlag = (flags & SBRDEC_DOWNSAMPLE) ? QMF_FLAG_DOWNSAMPLED : 0;
qmfErr = qmfInitAnalysisFilterBank (
&hs->AnalysiscQMF,
@@ -836,6 +881,9 @@ createSbrDec (SBR_CHANNEL * hSbrChannel,
}
}
+ /* Clear input delay line */
+ FDKmemclear(hs->coreDelayBuf, (96)*sizeof(INT_PCM));
+
/* assign qmf time slots */
assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP);
diff --git a/libSBRdec/src/sbr_dec.h b/libSBRdec/src/sbr_dec.h
index 175e7b2..edde637 100644
--- a/libSBRdec/src/sbr_dec.h
+++ b/libSBRdec/src/sbr_dec.h
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -118,6 +118,9 @@ typedef struct
FIXP_DBL * WorkBuffer1;
FIXP_DBL * WorkBuffer2;
+ /* Delayed time input signal needed to align CLDFD with LD-MPS QMF. */
+ INT_PCM coreDelayBuf[(96)];
+
/* QMF filter states */
FIXP_QAS anaQmfStates[(320)];
FIXP_QSS * pSynQmfStates;
@@ -182,7 +185,8 @@ sbr_dec (HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */
HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */
const int applyProcessing, /*!< Flag for SBR operation */
HANDLE_PS_DEC h_ps_d,
- const UINT flags
+ const UINT flags,
+ const int codecFrameSize
);
diff --git a/libSBRdec/src/sbr_ram.h b/libSBRdec/src/sbr_ram.h
index f12631d..7ab5044 100644
--- a/libSBRdec/src/sbr_ram.h
+++ b/libSBRdec/src/sbr_ram.h
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -135,6 +135,7 @@ struct SBR_DECODER_INSTANCE
USHORT codecFrameSize;
UCHAR synDownsampleFac;
UCHAR numDelayFrames; /* The current number of additional delay frames used for processing. */
+ UCHAR numFlushedFrames; /* The variable counts the number of frames which are flushed consecutively. */
UINT flags;
diff --git a/libSBRdec/src/sbr_rom.cpp b/libSBRdec/src/sbr_rom.cpp
index e84c3cd..c48ce35 100644
--- a/libSBRdec/src/sbr_rom.cpp
+++ b/libSBRdec/src/sbr_rom.cpp
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -189,6 +189,15 @@ const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] =
FL2FXCONST_SGL(3.0f / 4.0f)
};
+/*! Constants for calculating the number of limiter bands */
+const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] =
+{
+ FL2FXCONST_DBL(1.0f / 4.0f),
+ FL2FXCONST_DBL(1.2f / 4.0f),
+ FL2FXCONST_DBL(2.0f / 4.0f),
+ FL2FXCONST_DBL(3.0f / 4.0f)
+};
+
/*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope */
const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = {
FL2FXCONST_SGL(0.66666666666666f),
diff --git a/libSBRdec/src/sbr_rom.h b/libSBRdec/src/sbr_rom.h
index c318870..1f800bc 100644
--- a/libSBRdec/src/sbr_rom.h
+++ b/libSBRdec/src/sbr_rom.h
@@ -2,7 +2,7 @@
/* -----------------------------------------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
+© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
All rights reserved.
1. INTRODUCTION
@@ -124,6 +124,7 @@ extern const FIXP_DBL FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRI
extern const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4];
extern const UCHAR FDK_sbrDecoder_sbr_limGains_e[4];
extern const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4];
+extern const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4];
extern const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4];
extern const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2];
extern const FIXP_SGL harmonicPhaseX [2][4];
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index e15145a..f9ded54 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -128,6 +128,7 @@ amm-info@iis.fraunhofer.de
#include "lpp_tran.h"
#include "transcendent.h"
+#include "FDK_crc.h"
#include "sbrdec_drc.h"
@@ -137,7 +138,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define SBRDECODER_LIB_VL0 2
#define SBRDECODER_LIB_VL1 2
-#define SBRDECODER_LIB_VL2 7
+#define SBRDECODER_LIB_VL2 12
#define SBRDECODER_LIB_TITLE "SBR Decoder"
#ifdef __ANDROID__
#define SBRDECODER_LIB_BUILD_DATE ""
@@ -194,6 +195,33 @@ static void copySbrHeader( HANDLE_SBR_HEADER_DATA hDst, const HANDLE_SBR_HEADER_
hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi;
}
+static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SBR_HEADER_DATA hHdr2 )
+{
+ int result = 0;
+
+ /* compare basic data */
+ result |= (hHdr1->syncState != hHdr2->syncState) ? 1 : 0;
+ result |= (hHdr1->status != hHdr2->status) ? 1 : 0;
+ result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0;
+ result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0;
+ result |= (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0;
+ result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0;
+ result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0;
+
+ /* compare bitstream data */
+ result |= FDKmemcmp( &hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS) );
+ result |= FDKmemcmp( &hHdr1->bs_info, &hHdr2->bs_info, sizeof(SBR_HEADER_DATA_BS_INFO) );
+
+ /* compare frequency band data */
+ result |= FDKmemcmp( &hHdr1->freqBandData, &hHdr2->freqBandData, (8+MAX_NUM_LIMITERS+1)*sizeof(UCHAR) );
+ result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableLo, hHdr2->freqBandData.freqBandTableLo, (MAX_FREQ_COEFFS/2+1)*sizeof(UCHAR) );
+ result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableHi, hHdr2->freqBandData.freqBandTableHi, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) );
+ result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableNoise, hHdr2->freqBandData.freqBandTableNoise, (MAX_NOISE_COEFFS+1)*sizeof(UCHAR) );
+ result |= FDKmemcmp( hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) );
+
+ return result;
+}
+
/*!
\brief Reset SBR decoder.
@@ -391,6 +419,7 @@ int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec)
case AOT_PS:
case AOT_ER_AAC_SCAL:
case AOT_ER_AAC_ELD:
+ case AOT_DRM_AAC:
return 1;
default:
return 0;
@@ -463,6 +492,8 @@ SBR_ERROR sbrDecoder_InitElement (
self->flags = 0;
self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0;
+ self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0;
+ self->flags |= (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL|SBRDEC_SYNTAX_DRM : 0;
/* Init SBR elements */
{
@@ -928,24 +959,73 @@ SBR_ERROR sbrDecoder_Parse(
)
{
SBR_DECODER_ELEMENT *hSbrElement;
- HANDLE_SBR_HEADER_DATA hSbrHeader;
+ HANDLE_SBR_HEADER_DATA hSbrHeader = NULL;
HANDLE_SBR_CHANNEL *pSbrChannel;
SBR_FRAME_DATA *hFrameDataLeft;
SBR_FRAME_DATA *hFrameDataRight;
SBR_ERROR errorStatus = SBRDEC_OK;
- SBR_SYNC_STATE initialSyncState;
SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT;
INT startPos;
INT CRCLen = 0;
+ HANDLE_FDK_BITSTREAM hBsOriginal = hBs;
+ FDK_CRCINFO crcInfo; /* shall be used for all other CRCs in the future (TBD) */
+ INT crcReg = 0;
+ USHORT drmSbrCrc = 0;
int stereo;
int fDoDecodeSbrData = 1;
int lastSlot, lastHdrSlot = 0, thisHdrSlot;
+ /* Reverse bits of DRM SBR payload */
+ if ( (self->flags & SBRDEC_SYNTAX_DRM) && *count > 0 )
+ {
+ UCHAR *bsBufferDrm = (UCHAR*)self->workBuffer1;
+ HANDLE_FDK_BITSTREAM hBsBwd = (HANDLE_FDK_BITSTREAM) (bsBufferDrm + (512));
+ int dataBytes, dataBits;
+
+ dataBits = *count;
+
+ if (dataBits > ((512)*8)) {
+ /* do not flip more data than needed */
+ dataBits = (512)*8;
+ }
+
+ dataBytes = (dataBits+7)>>3;
+
+ int j;
+
+ if ((j = (int)FDKgetValidBits(hBs)) != 8) {
+ FDKpushBiDirectional(hBs, (j-8));
+ }
+
+ j = 0;
+ for ( ; dataBytes > 0; dataBytes--)
+ {
+ int i;
+ UCHAR tmpByte;
+ UCHAR buffer = 0x00;
+
+ tmpByte = (UCHAR) FDKreadBits(hBs, 8);
+ for (i = 0; i < 4; i++) {
+ int shift = 2 * i + 1;
+ buffer |= (tmpByte & (0x08>>i)) << shift;
+ buffer |= (tmpByte & (0x10<<i)) >> shift;
+ }
+ bsBufferDrm[j++] = buffer;
+ FDKpushBack(hBs, 16);
+ }
+
+ FDKinitBitStream(hBsBwd, bsBufferDrm, (512), dataBits, BS_READER);
+
+ /* Use reversed data */
+ hBs = hBsBwd;
+ bsPayLen = *count;
+ }
+
/* Remember start position of SBR element */
startPos = FDKgetValidBits(hBs);
@@ -970,7 +1050,6 @@ SBR_ERROR sbrDecoder_Parse(
hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
- initialSyncState = hSbrHeader->syncState;
/* reset PS flag; will be set after PS was found */
self->flags &= ~SBRDEC_PS_DECODED;
@@ -1006,12 +1085,19 @@ SBR_ERROR sbrDecoder_Parse(
*/
if (fDoDecodeSbrData)
{
- if (crcFlag == 1) {
+ if (crcFlag) {
switch (self->coreCodec) {
case AOT_ER_AAC_ELD:
FDKpushFor (hBs, 10);
/* check sbrcrc later: we don't know the payload length now */
break;
+ case AOT_DRM_AAC:
+ drmSbrCrc = (USHORT)FDKreadBits(hBs, 8);
+ /* Setup CRC decoder */
+ FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8);
+ /* Start CRC region */
+ crcReg = FDKcrcStartReg(&crcInfo, hBs, 0);
+ break;
default:
CRCLen = bsPayLen - 10; /* change: 0 => i */
if (CRCLen < 0) {
@@ -1056,6 +1142,7 @@ SBR_ERROR sbrDecoder_Parse(
hSbrHeader->syncState = SBR_HEADER;
} else {
hSbrHeader->syncState = SBR_NOT_INITIALIZED;
+ headerStatus = HEADER_ERROR;
}
}
@@ -1105,7 +1192,7 @@ SBR_ERROR sbrDecoder_Parse(
valBits = (INT)FDKgetValidBits(hBs);
}
- if ( crcFlag == 1 ) {
+ if ( crcFlag ) {
switch (self->coreCodec) {
case AOT_ER_AAC_ELD:
{
@@ -1117,6 +1204,14 @@ SBR_ERROR sbrDecoder_Parse(
FDKpushFor(hBs, crcLen);
}
break;
+ case AOT_DRM_AAC:
+ /* End CRC region */
+ FDKcrcEndReg(&crcInfo, hBs, crcReg);
+ /* Check CRC */
+ if ((FDKcrcGetCRC(&crcInfo)^0xFF) != drmSbrCrc) {
+ fDoDecodeSbrData = 0;
+ }
+ break;
default:
break;
}
@@ -1167,8 +1262,25 @@ SBR_ERROR sbrDecoder_Parse(
}
bail:
- if (errorStatus == SBRDEC_OK) {
- if (headerStatus == HEADER_NOT_PRESENT) {
+
+ if ( self->flags & SBRDEC_SYNTAX_DRM )
+ {
+ hBs = hBsOriginal;
+ }
+
+ if ( (errorStatus == SBRDEC_OK)
+ || ( (errorStatus == SBRDEC_PARSE_ERROR)
+ && (headerStatus != HEADER_ERROR) ) )
+ {
+ int useOldHdr = ( (headerStatus == HEADER_NOT_PRESENT)
+ || (headerStatus == HEADER_ERROR) ) ? 1 : 0;
+
+ if (!useOldHdr && (thisHdrSlot != lastHdrSlot)) {
+ useOldHdr |= ( compareSbrHeader( hSbrHeader,
+ &self->sbrHeader[elementIndex][lastHdrSlot] ) == 0 ) ? 1 : 0;
+ }
+
+ if (useOldHdr != 0) {
/* Use the old header for this frame */
hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot;
} else {
@@ -1229,12 +1341,21 @@ sbrDecoder_DecodeElement (
int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */
if (self->flags & SBRDEC_FLUSH) {
- /* Move frame pointer to the next slot which is up to be decoded/applied next */
- hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
- /* Update header and frame data pointer because they have already been set */
- hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
- hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
- hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+ if ( self->numFlushedFrames > self->numDelayFrames ) {
+ int hdrIdx;
+ /* No valid SBR payload available, hence switch to upsampling (in all headers) */
+ for (hdrIdx = 0; hdrIdx < ((1)+1); hdrIdx += 1) {
+ self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
+ }
+ }
+ else {
+ /* Move frame pointer to the next slot which is up to be decoded/applied next */
+ hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
+ /* Update header and frame data pointer because they have already been set */
+ hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
+ hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
+ hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
+ }
}
/* Update the header error flag */
@@ -1354,7 +1475,8 @@ sbrDecoder_DecodeElement (
&pSbrChannel[0]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE),
h_ps_d,
- self->flags
+ self->flags,
+ codecFrameSize
);
if (stereo) {
@@ -1371,7 +1493,8 @@ sbrDecoder_DecodeElement (
&pSbrChannel[1]->prevFrameData,
(hSbrHeader->syncState == SBR_ACTIVE),
NULL,
- self->flags
+ self->flags,
+ codecFrameSize
);
}
@@ -1387,20 +1510,21 @@ sbrDecoder_DecodeElement (
if ( !(self->flags & SBRDEC_PS_DECODED) ) {
/* A decoder which is able to decode PS has to produce a stereo output even if no PS data is availble. */
/* So copy left channel to right channel. */
+ int copyFrameSize = codecFrameSize * 2 / self->synDownsampleFac;
if (interleaved) {
INT_PCM *ptr;
INT i;
FDK_ASSERT(strideOut == 2);
ptr = timeData;
- for (i = codecFrameSize; i--; )
+ for (i = copyFrameSize>>1; i--; )
{
INT_PCM tmp; /* This temporal variable is required because some compilers can't do *ptr++ = *ptr++ correctly. */
tmp = *ptr++; *ptr++ = tmp;
tmp = *ptr++; *ptr++ = tmp;
}
} else {
- FDKmemcpy( timeData+2*codecFrameSize, timeData, 2*codecFrameSize*sizeof(INT_PCM) );
+ FDKmemcpy( timeData+copyFrameSize, timeData, copyFrameSize*sizeof(INT_PCM) );
}
}
*numOutChannels = 2; /* Output minimum two channels when PS is enabled. */
@@ -1464,14 +1588,23 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
self->flags &= ~SBRDEC_PS_DECODED;
}
+ if ( self->flags & SBRDEC_FLUSH ) {
+ /* flushing is signalized, hence increment the flush frame counter */
+ self->numFlushedFrames++;
+ }
+ else {
+ /* no flushing is signalized, hence reset the flush frame counter */
+ self->numFlushedFrames = 0;
+ }
+
/* Loop over SBR elements */
for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++)
{
int numElementChan;
if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) {
- errorStatus = SBRDEC_UNSUPPORTED_CONFIG;
- goto bail;
+ /* Disable PS and try decoding SBR mono. */
+ psPossible = 0;
}
numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1;
@@ -1579,6 +1712,7 @@ INT sbrDecoder_GetLibInfo( LIB_INFO *info )
| CAPF_SBR_HQ
| CAPF_SBR_LP
| CAPF_SBR_PS_MPEG
+ | CAPF_SBR_DRM_BS
| CAPF_SBR_CONCEALMENT
| CAPF_SBR_DRC
;
@@ -1607,6 +1741,9 @@ UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self )
/* Low delay SBR: */
{
outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */
+ if (flags & SBRDEC_LD_MPS_QMF) {
+ outputDelay += 32;
+ }
}
}
else if (!IS_USAC(self->coreCodec)) {