From 203e3f28fbebec7011342017fafc2a0bda0ce530 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 8 Apr 2016 12:05:12 -0700 Subject: AAC/SBR decoder improvements and bugfixes * AAC-Decoder - Add support for AOT 20 (ER-AAC scalable) (base layer only) - Add support for AAC as used in Digital Radio Mondiale (DRM30/DRM+) Modified file(s): libAACdec/src/aacdecoder.cpp libAACdec/src/aacdecoder_lib.cpp libFDK/src/FDK_core.cpp libFDK/src/FDK_tools_rom.cpp libMpegTPDec/src/tpdec_asc.cpp libMpegTPDec/src/tpdec_lib.cpp libMpegTPDec/src/version libSBRdec/include/sbrdecoder.h libSBRdec/src/env_extr.h libSBRdec/src/sbrdecoder.cpp Added file(s): libMpegTPDec/src/tpdec_drm.cpp libMpegTPDec/src/tpdec_drm.h - Fix sanity check in HCR module that was performed at the wrong point in time. Modified file(s): libAACdec/src/aacdecoder_lib.cpp libAACdec/src/block.cpp - Extend core sampling rate support up to 96 kHz. Modified file(s): libAACdec/src/aac_rom.cpp libAACdec/src/aacdecoder.cpp libAACdec/src/aacdecoder_lib.cpp - Return correct audio output channel description according number of output channels. Modified file(s): libAACdec/src/aacdecoder_lib.cpp - Indroduce decoder intern output buffer. This change allows to use framework output buffer with the actual size of the deocder output channels. Modified file(s): libAACdec/include/aacdecoder_lib.h libAACdec/src/aacdecoder.h libAACdec/src/aacdecoder_lib.cpp * SBR-Decoder - Increase robustness for erroneous input data. - Improve error concealment performance. - Fix handling of lowest sub-band for LD-SBR Modified file(s): libAACdec/src/aacdecoder.cpp libAACdec/src/aacdecoder_lib.cpp libSBRdec/src/env_calc.cpp libSBRdec/src/env_dec.cpp libSBRdec/src/env_extr.cpp libSBRdec/src/env_extr.h libSBRdec/src/sbr_dec.cpp libSBRdec/src/sbr_rom.cpp libSBRdec/src/sbr_rom.h libSBRdec/src/sbrdecoder.cpp - Add QMF delay compensation for ELD v2 streams decoded with the complex low delay filter-bank. Modified file(s): libSBRdec/src/sbr_dec.cpp libSBRdec/src/sbr_dec.h libSBRdec/src/sbrdecoder.cpp - Introduce a different handling of frames to be flushed dependent on whether there are delayed frames available or not. Modified file(s): libSBRdec/src/sbr_ram.h libSBRdec/src/sbrdecoder.cpp - Calculate the correct number of samples for dual-mono copy in case of no available PS data. Modified file(s): libSBRdec/src/sbrdecoder.cpp * SYS-Library - Change include order of genericStds.h to prevent conflict with definitions which are also used in math.h. Modified file(s): libSYS/src/genericStds.cpp Change-Id: I3ecffbad85f39b056213107955cfadbeb3f4b6e1 --- libSBRdec/src/env_calc.cpp | 204 +++++++++++++++++++++++++++++++------------ libSBRdec/src/env_dec.cpp | 4 +- libSBRdec/src/env_extr.cpp | 4 +- libSBRdec/src/env_extr.h | 12 +-- libSBRdec/src/sbr_dec.cpp | 62 +++++++++++-- libSBRdec/src/sbr_dec.h | 8 +- libSBRdec/src/sbr_ram.h | 3 +- libSBRdec/src/sbr_rom.cpp | 11 ++- libSBRdec/src/sbr_rom.h | 3 +- libSBRdec/src/sbrdecoder.cpp | 177 ++++++++++++++++++++++++++++++++----- 10 files changed, 389 insertions(+), 99 deletions(-) (limited to 'libSBRdec/src') 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<> 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; sbrElementNumnumSbrElements; 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)) { -- cgit v1.2.3