diff options
author | Martin Storsjo <martin@martin.st> | 2020-11-17 12:38:51 +0200 |
---|---|---|
committer | Martin Storsjo <martin@martin.st> | 2020-11-17 12:38:51 +0200 |
commit | c7a3808a2fd18bb4dad24d281cbb862b241806a9 (patch) | |
tree | 2cea66fef9961cd71efc817fed7e857ef27099b0 /libFDK | |
parent | d23a21ab427da642c8f32bb0659ae63a86f98e96 (diff) | |
parent | f4adff7fbb0968a13fd5077ea3df734870aef3cf (diff) | |
download | fdk-aac-c7a3808a2fd18bb4dad24d281cbb862b241806a9.tar.gz fdk-aac-c7a3808a2fd18bb4dad24d281cbb862b241806a9.tar.bz2 fdk-aac-c7a3808a2fd18bb4dad24d281cbb862b241806a9.zip |
Merge remote-tracking branch 'aosp/master'
Diffstat (limited to 'libFDK')
-rw-r--r-- | libFDK/include/FDK_qmf_domain.h | 20 | ||||
-rw-r--r-- | libFDK/include/fixpoint_math.h | 43 | ||||
-rw-r--r-- | libFDK/include/mdct.h | 14 | ||||
-rw-r--r-- | libFDK/include/qmf.h | 105 | ||||
-rw-r--r-- | libFDK/include/qmf_pcm.h | 218 | ||||
-rw-r--r-- | libFDK/include/scale.h | 8 | ||||
-rw-r--r-- | libFDK/src/FDK_bitbuffer.cpp | 9 | ||||
-rw-r--r-- | libFDK/src/FDK_core.cpp | 6 | ||||
-rw-r--r-- | libFDK/src/FDK_decorrelate.cpp | 80 | ||||
-rw-r--r-- | libFDK/src/FDK_hybrid.cpp | 34 | ||||
-rw-r--r-- | libFDK/src/FDK_qmf_domain.cpp | 49 | ||||
-rw-r--r-- | libFDK/src/dct.cpp | 18 | ||||
-rw-r--r-- | libFDK/src/fixpoint_math.cpp | 8 | ||||
-rw-r--r-- | libFDK/src/mdct.cpp | 6 | ||||
-rw-r--r-- | libFDK/src/qmf.cpp | 384 | ||||
-rw-r--r-- | libFDK/src/scale.cpp | 26 |
16 files changed, 485 insertions, 543 deletions
diff --git a/libFDK/include/FDK_qmf_domain.h b/libFDK/include/FDK_qmf_domain.h index 5c12682..0e83da3 100644 --- a/libFDK/include/FDK_qmf_domain.h +++ b/libFDK/include/FDK_qmf_domain.h @@ -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 @@ -123,11 +123,10 @@ typedef enum { #define QMF_WB_SECTION_SIZE (1024 * 2) H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL) -H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore2, FIXP_DBL) H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL) H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL) -H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore5, FIXP_DBL) H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore7, FIXP_DBL) #define QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS (64) #define QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS (QMF_MAX_SYNTHESIS_BANDS) @@ -145,15 +144,15 @@ H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL) #define QMF_DOMAIN_OV_TIMESLOTS_16 (3) #define QMF_DOMAIN_OV_TIMESLOTS_32 (6) -H_ALLOC_MEM(AnaQmfStates, FIXP_QAS) +H_ALLOC_MEM(AnaQmfStates, FIXP_DBL) H_ALLOC_MEM(SynQmfStates, FIXP_QSS) H_ALLOC_MEM(QmfSlotsReal, FIXP_DBL *) H_ALLOC_MEM(QmfSlotsImag, FIXP_DBL *) H_ALLOC_MEM(QmfOverlapBuffer, FIXP_DBL) -H_ALLOC_MEM(AnaQmfStates16, FIXP_QAS) -H_ALLOC_MEM(AnaQmfStates24, FIXP_QAS) -H_ALLOC_MEM(AnaQmfStates32, FIXP_QAS) +H_ALLOC_MEM(AnaQmfStates16, FIXP_DBL) +H_ALLOC_MEM(AnaQmfStates24, FIXP_DBL) +H_ALLOC_MEM(AnaQmfStates32, FIXP_DBL) H_ALLOC_MEM(QmfSlotsReal16, FIXP_DBL *) H_ALLOC_MEM(QmfSlotsReal32, FIXP_DBL *) H_ALLOC_MEM(QmfSlotsImag16, FIXP_DBL *) @@ -161,8 +160,6 @@ H_ALLOC_MEM(QmfSlotsImag32, FIXP_DBL *) H_ALLOC_MEM(QmfOverlapBuffer16, FIXP_DBL) H_ALLOC_MEM(QmfOverlapBuffer32, FIXP_DBL) -#define QDOM_PCM INT_PCM - /** * Structure to hold the configuration data which is global whithin a QMF domain * instance. @@ -182,9 +179,6 @@ typedef struct { park a channel if only one processing channel is available. */ UCHAR parkChannel_requested; - QDOM_PCM - *TDinput; /*!< Pointer to time domain data used as input for the QMF - analysis. */ FIXP_DBL * pWorkBuffer[QMF_MAX_WB_SECTIONS]; /*!< Pointerarray to volatile memory. */ UINT flags; /*!< Flags to be set on all QMF analysis/synthesis filter @@ -244,7 +238,7 @@ typedef struct { (workBuf_nTimeSlots * workBuf_nBands * CMPLX_MOD). */ USHORT workBufferOffset; /*!< Offset within work buffer. */ USHORT workBufferSectSize; /*!< Size of work buffer section. */ - FIXP_QAS * + FIXP_DBL * pAnaQmfStates; /*!< Pointer to QMF analysis states (persistent memory). */ FIXP_DBL *pOverlapBuffer; /*!< Pointer to QMF overlap/delay memory (persistent diff --git a/libFDK/include/fixpoint_math.h b/libFDK/include/fixpoint_math.h index 3805892..51df4d7 100644 --- a/libFDK/include/fixpoint_math.h +++ b/libFDK/include/fixpoint_math.h @@ -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 @@ -171,6 +171,19 @@ extern const FIXP_DBL invSqrtTab[SQRT_VALUES]; * \return non-zero if (a_m*2^a_e) < (b_m*2^b_e), 0 otherwise */ FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e) { + INT n; + + n = fixnorm_D(a_m); + a_m <<= n; + a_e -= n; + + n = fixnorm_D(b_m); + b_m <<= n; + b_e -= n; + + if (a_m == (FIXP_DBL)0) a_e = b_e; + if (b_m == (FIXP_DBL)0) b_e = a_e; + if (a_e > b_e) { return ((b_m >> fMin(a_e - b_e, DFRACT_BITS - 1)) > a_m); } else { @@ -179,6 +192,19 @@ FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e) { } FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e) { + INT n; + + n = fixnorm_S(a_m); + a_m <<= n; + a_e -= n; + + n = fixnorm_S(b_m); + b_m <<= n; + b_e -= n; + + if (a_m == (FIXP_SGL)0) a_e = b_e; + if (b_m == (FIXP_SGL)0) b_e = a_e; + if (a_e > b_e) { return ((b_m >> fMin(a_e - b_e, FRACT_BITS - 1)) > a_m); } else { @@ -545,15 +571,20 @@ inline INT fMultIceil(FIXP_DBL a, INT b) { m = fMultNorm(a, (FIXP_DBL)b, &m_e); if (m_e < (INT)0) { - if (m_e > (INT)-DFRACT_BITS) { + if (m_e > (INT) - (DFRACT_BITS - 1)) { mi = (m >> (-m_e)); if ((LONG)m & ((1 << (-m_e)) - 1)) { mi = mi + (FIXP_DBL)1; } } else { - mi = (FIXP_DBL)1; - if (m < (FIXP_DBL)0) { - mi = (FIXP_DBL)0; + if (m > (FIXP_DBL)0) { + mi = (FIXP_DBL)1; + } else { + if ((m_e == -(DFRACT_BITS - 1)) && (m == (FIXP_DBL)MINVAL_DBL)) { + mi = (FIXP_DBL)-1; + } else { + mi = (FIXP_DBL)0; + } } } } else { @@ -744,7 +775,7 @@ FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, /** * \brief return (base_m * 2^base_e) ^ N - * \param base_m mantissa of the base + * \param base_m mantissa of the base. Must not be negative. * \param base_e exponent of the base * \param N power to be calculated of the base * \param result_e pointer to a INT where the exponent of the result will be diff --git a/libFDK/include/mdct.h b/libFDK/include/mdct.h index 1382374..e7cf3ad 100644 --- a/libFDK/include/mdct.h +++ b/libFDK/include/mdct.h @@ -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,18 +106,16 @@ amm-info@iis.fraunhofer.de #include "common_fix.h" #define MDCT_OUT_HEADROOM 2 /* Output additional headroom */ -#define PCM_OUT_BITS SAMPLE_BITS + +#define PCM_OUT_BITS DFRACT_BITS #define PCM_OUT_HEADROOM 8 /* Must have the same values as DMXH_HEADROOM */ -#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - SAMPLE_BITS)) +#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - PCM_OUT_BITS)) /* Refer to "Output word length" in ISO/IEC 14496-3:2008(E) 23.2.3.6 */ #define MDCT_OUTPUT_GAIN 16 -#if (MDCT_OUTPUT_SCALE >= 0) -#define IMDCT_SCALE(x) SATURATE_RIGHT_SHIFT(x, MDCT_OUTPUT_SCALE, PCM_OUT_BITS) -#else -#define IMDCT_SCALE(x) SATURATE_LEFT_SHIFT(x, -MDCT_OUTPUT_SCALE, PCM_OUT_BITS) -#endif +#define IMDCT_SCALE(x, s) \ + SATURATE_RIGHT_SHIFT((x), ((s) + MDCT_OUTPUT_SCALE), PCM_OUT_BITS) #define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x) #define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS) diff --git a/libFDK/include/qmf.h b/libFDK/include/qmf.h index 609c6f1..78770b3 100644 --- a/libFDK/include/qmf.h +++ b/libFDK/include/qmf.h @@ -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 @@ -116,6 +116,7 @@ amm-info@iis.fraunhofer.de #define FIXP_QAS FIXP_PCM #define QAS_BITS SAMPLE_BITS +#define INT_PCM_QMFIN INT_PCM #define FIXP_QSS FIXP_DBL #define QSS_BITS DFRACT_BITS @@ -201,66 +202,70 @@ struct QMF_FILTER_BANK { typedef struct QMF_FILTER_BANK *HANDLE_QMF_FILTER_BANK; +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_QAS *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ +#if SAMPLE_BITS == 16 + +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_DBL *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ +#endif + void qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ - const LONG *timeIn, /*!< Time signal */ + const INT_PCM *timeIn, /*!< Time signal */ const int timeIn_e, /*!< Exponent of audio data */ const int stride, /*!< Stride factor of audio data */ - FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ ); +#if SAMPLE_BITS == 16 void qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ - const INT_PCM *timeIn, /*!< Time signal */ + const LONG *timeIn, /*!< Time signal */ const int timeIn_e, /*!< Exponent of audio data */ const int stride, /*!< Stride factor of audio data */ - FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ -); - -void qmfSynthesisFiltering( - HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ - FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */ - FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */ - const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ - const int ov_len, /*!< Length of band overlap */ - INT_PCM *timeOut, /*!< Time signal */ - const INT stride, /*!< Stride factor of audio data */ - FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer. It must be - aligned */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ ); - -int qmfInitAnalysisFilterBank( - HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ - FIXP_QAS *pFilterStates, /*!< Pointer to filter state buffer */ - int noCols, /*!< Number of time slots */ - int lsb, /*!< Number of lower bands */ - int usb, /*!< Number of upper bands */ - int no_channels, /*!< Number of critically sampled bands */ - int flags); /*!< Flags */ +#endif void qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ FIXP_DBL *qmfReal, /*!< Low and High band, real */ FIXP_DBL *qmfImag, /*!< Low and High band, imag */ - const LONG *timeIn, /*!< Pointer to input */ + const INT_PCM *timeIn, /*!< Pointer to input */ const int stride, /*!< stride factor of input */ - FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ ); +#if SAMPLE_BITS == 16 void qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ FIXP_DBL *qmfReal, /*!< Low and High band, real */ FIXP_DBL *qmfImag, /*!< Low and High band, imag */ - const INT_PCM *timeIn, /*!< Pointer to input */ + const LONG *timeIn, /*!< Pointer to input */ const int stride, /*!< stride factor of input */ - FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ ); +#endif + int qmfInitSynthesisFilterBank( HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ FIXP_QSS *pFilterStates, /*!< Pointer to filter state buffer */ @@ -270,12 +275,46 @@ int qmfInitSynthesisFilterBank( int no_channels, /*!< Number of critically sampled bands */ int flags); /*!< Flags */ +void qmfSynthesisFiltering( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */ + FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */ + const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const int ov_len, /*!< Length of band overlap */ + INT_PCM *timeOut, /*!< Time signal */ + const INT stride, /*!< Stride factor of audio data */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer. It must be + aligned */ +); +#if SAMPLE_BITS == 16 + +void qmfSynthesisFiltering( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */ + FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */ + const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const int ov_len, /*!< Length of band overlap */ + LONG *timeOut, /*!< Time signal */ + const int timeOut_e, /*!< Target exponent for timeOut */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ +); +#endif + void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, const FIXP_DBL *realSlot, const FIXP_DBL *imagSlot, const int scaleFactorLowBand, const int scaleFactorHighBand, INT_PCM *timeOut, const int timeOut_e, FIXP_DBL *pWorkBuffer); +#if SAMPLE_BITS == 16 + +void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_DBL *realSlot, + const FIXP_DBL *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, LONG *timeOut, + const int timeOut_e, FIXP_DBL *pWorkBuffer); +#endif void qmfChangeOutScalefactor( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ @@ -291,11 +330,5 @@ void qmfChangeOutGain( FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */ int outputGainScale /*!< New gain for output data (exponent) */ ); -void qmfSynPrototypeFirSlot( - HANDLE_QMF_FILTER_BANK qmf, - FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ - FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ - INT_PCM *RESTRICT timeOut, /*!< Time domain data */ - const int timeOut_e); #endif /*ifndef QMF_H */ diff --git a/libFDK/include/qmf_pcm.h b/libFDK/include/qmf_pcm.h index f24e0cd..5da53db 100644 --- a/libFDK/include/qmf_pcm.h +++ b/libFDK/include/qmf_pcm.h @@ -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 @@ -402,4 +402,220 @@ void qmfSynthesisFiltering( timeOut + (i * L * stride), stride, pWorkBuffer); } /* no_col loop i */ } + +/*! + * + * \brief Create QMF filter bank instance + * + * + * \return 0 if successful + * + */ +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ + FIXP_QAS *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< lower end of QMF */ + int usb, /*!< upper end of QMF */ + int no_channels, /*!< Number of channels (bands) */ + int flags) /*!< Low Power flag */ +{ + int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, + no_channels, flags, 0); + if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) { + FDKmemclear(h_Qmf->FilterStates, + (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS)); + } + + FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); + + return err; +} + +#ifndef FUNCTION_qmfAnaPrototypeFirSlot +/*! + \brief Perform Analysis Prototype Filtering on a single slot of input data. +*/ +static void qmfAnaPrototypeFirSlot( + FIXP_DBL *analysisBuffer, + INT no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates) { + INT k; + + FIXP_DBL accu; + const FIXP_PFT *RESTRICT p_flt = p_filter; + FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1; + FIXP_DBL *RESTRICT pData_1 = analysisBuffer; + + FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; + FIXP_QAS *RESTRICT sta_1 = + (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1; + INT pfltStep = QMF_NO_POLY * (p_stride); + INT staStep1 = no_channels << 1; + INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */ + + /* FIR filters 127..64 0..63 */ + for (k = 0; k < no_channels; k++) { + accu = fMultDiv2(p_flt[0], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[1], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[2], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[3], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[4], *sta_1); + *pData_1++ = (accu << 1); + sta_1 += staStep2; + + p_flt += pfltStep; + accu = fMultDiv2(p_flt[0], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[1], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[2], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[3], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[4], *sta_0); + *pData_0-- = (accu << 1); + sta_0 -= staStep2; + } +} +#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */ + +#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric +/*! + \brief Perform Analysis Prototype Filtering on a single slot of input data. +*/ +static void qmfAnaPrototypeFirSlot_NonSymmetric( + FIXP_DBL *analysisBuffer, + int no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates) { + const FIXP_PFT *RESTRICT p_flt = p_filter; + int p, k; + + for (k = 0; k < 2 * no_channels; k++) { + FIXP_DBL accu = (FIXP_DBL)0; + + p_flt += QMF_NO_POLY * (p_stride - 1); + + /* + Perform FIR-Filter + */ + for (p = 0; p < QMF_NO_POLY; p++) { + accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]); + } + analysisBuffer[2 * no_channels - 1 - k] = (accu << 1); + pFilterStates++; + } +} +#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */ + +/* + * \brief Perform one QMF slot analysis of the time domain data of timeIn + * with specified stride and stores the real part of the subband + * samples in rSubband, and the imaginary part in iSubband + * + * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case + * of implicit resampling (USAC with reduced 3/4 core frame length). + */ +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const INT_PCM_QMFIN *RESTRICT timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); + /* + Feed time signal into oldest anaQmf->no_channels states + */ + { + FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset; + + /* Feed and scale actual time in slot */ + for (int i = anaQmf->no_channels >> 1; i != 0; i--) { + /* Place INT_PCM value left aligned in scaledTimeIn */ + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; + } + } + + if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, + anaQmf->p_filter, anaQmf->p_stride, + (FIXP_QAS *)anaQmf->FilterStates); + } else { + qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, + anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); + } + + if (anaQmf->flags & QMF_FLAG_LP) { + if (anaQmf->flags & QMF_FLAG_CLDFB) + qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); + else + qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); + + } else { + qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); + } + /* + Shift filter states + + Should be realized with modulo addressing on a DSP instead of a true buffer + shift + */ + FDKmemmove(anaQmf->FilterStates, + (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, + offset * sizeof(FIXP_QAS)); +} + +/*! + * + * \brief Perform complex-valued subband filtering of the time domain + * data of timeIn and stores the real part of the subband + * samples in rAnalysis, and the imaginary part in iAnalysis + * The qmf coefficient table is symmetric. The symmetry is expoited by + * shrinking the coefficient table to half the size. The addressing mode + * takes care of the symmetries. + * + * + * \sa PolyphaseFiltering + */ +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, + const INT_PCM_QMFIN *timeIn, /*!< Time signal */ + const int timeIn_e, const int stride, + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int i; + int no_channels = anaQmf->no_channels; + + scaleFactor->lb_scale = + -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; + scaleFactor->lb_scale -= anaQmf->filterScale; + + for (i = 0; i < anaQmf->no_col; i++) { + FIXP_DBL *qmfImagSlot = NULL; + + if (!(anaQmf->flags & QMF_FLAG_LP)) { + qmfImagSlot = qmfImag[i]; + } + + qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, + pWorkBuffer); + + timeIn += no_channels * stride; + + } /* no_col loop i */ +} #endif /* QMF_PCM_H */ diff --git a/libFDK/include/scale.h b/libFDK/include/scale.h index fcfc116..0d8db9e 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_bitbuffer.cpp b/libFDK/src/FDK_bitbuffer.cpp index 98905ea..9b7f5b8 100644 --- a/libFDK/src/FDK_bitbuffer.cpp +++ b/libFDK/src/FDK_bitbuffer.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 @@ -368,7 +368,10 @@ void FDK_Feed(HANDLE_FDK_BITBUF hBitBuf, const UCHAR *RESTRICT inputBuffer, UINT bTotal = 0; - UINT bToRead = (hBitBuf->bufBits - hBitBuf->ValidBits) >> 3; + UINT bToRead = + fMin(hBitBuf->bufBits, + (UINT)fMax(0, ((INT)hBitBuf->bufBits - (INT)hBitBuf->ValidBits))) >> + 3; UINT noOfBytes = fMin(bToRead, *bytesValid); //(bToRead < *bytesValid) ? bToRead : *bytesValid ; @@ -384,7 +387,7 @@ void FDK_Feed(HANDLE_FDK_BITBUF hBitBuf, const UCHAR *RESTRICT inputBuffer, bToRead * sizeof(UCHAR)); /* add noOfBits to number of valid bits in buffer */ - hBitBuf->ValidBits += bToRead << 3; + hBitBuf->ValidBits = (UINT)((INT)hBitBuf->ValidBits + (INT)(bToRead << 3)); bTotal += bToRead; inputBuffer += bToRead; diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp index 75ea8a2..48db17e 100644 --- a/libFDK/src/FDK_core.cpp +++ b/libFDK/src/FDK_core.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 @@ -104,10 +104,10 @@ amm-info@iis.fraunhofer.de /* FDK tools library info */ #define FDK_TOOLS_LIB_VL0 3 -#define FDK_TOOLS_LIB_VL1 0 +#define FDK_TOOLS_LIB_VL1 1 #define FDK_TOOLS_LIB_VL2 0 #define FDK_TOOLS_LIB_TITLE "FDK Tools" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define FDK_TOOLS_LIB_BUILD_DATE "" #define FDK_TOOLS_LIB_BUILD_TIME "" #else 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/FDK_hybrid.cpp b/libFDK/src/FDK_hybrid.cpp index b661f82..08d32a8 100644 --- a/libFDK/src/FDK_hybrid.cpp +++ b/libFDK/src/FDK_hybrid.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 @@ -142,11 +142,12 @@ amm-info@iis.fraunhofer.de } /* How to arrange the packed values. */ struct FDK_HYBRID_SETUP { - UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ - UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ - SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ - UCHAR protoLen; /*!< Prototype filter length. */ - UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ + UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ + UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ + UCHAR synHybScale[3]; /*!< Headroom needed in hybrid synthesis filterbank. */ + SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ + UCHAR protoLen; /*!< Prototype filter length. */ + UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ const INT *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */ }; @@ -156,12 +157,12 @@ static const INT ringbuffIdxTab[2 * 13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; -static const FDK_HYBRID_SETUP setup_3_16 = {3, {8, 4, 4}, {8, 4, 4}, - 13, (13 - 1) / 2, ringbuffIdxTab}; -static const FDK_HYBRID_SETUP setup_3_12 = {3, {8, 2, 2}, {8, 2, 2}, - 13, (13 - 1) / 2, ringbuffIdxTab}; -static const FDK_HYBRID_SETUP setup_3_10 = {3, {6, 2, 2}, {-8, -2, 2}, - 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_16 = { + 3, {8, 4, 4}, {4, 3, 3}, {8, 4, 4}, 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_12 = { + 3, {8, 2, 2}, {4, 2, 2}, {8, 2, 2}, 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_10 = { + 3, {6, 2, 2}, {3, 2, 2}, {-8, -2, 2}, 13, (13 - 1) / 2, ringbuffIdxTab}; static const FIXP_HTP HybFilterCoef8[] = { HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), @@ -477,17 +478,18 @@ void FDKhybridSynthesisApply(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, */ for (k = 0; k < nrQmfBandsLF; k++) { const int nHybBands = hSynthesisHybFilter->pSetup->nHybBands[k]; + const int scale = hSynthesisHybFilter->pSetup->synHybScale[k]; FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); /* Perform hybrid filtering. */ for (n = 0; n < nHybBands; n++) { - accu1 += pHybridReal[hybOffset + n]; - accu2 += pHybridImag[hybOffset + n]; + accu1 += pHybridReal[hybOffset + n] >> scale; + accu2 += pHybridImag[hybOffset + n] >> scale; } - pQmfReal[k] = accu1; - pQmfImag[k] = accu2; + pQmfReal[k] = SATURATE_LEFT_SHIFT(accu1, scale, DFRACT_BITS); + pQmfImag[k] = SATURATE_LEFT_SHIFT(accu2, scale, DFRACT_BITS); hybOffset += nHybBands; } diff --git a/libFDK/src/FDK_qmf_domain.cpp b/libFDK/src/FDK_qmf_domain.cpp index 3245deb..77c5ca2 100644 --- a/libFDK/src/FDK_qmf_domain.cpp +++ b/libFDK/src/FDK_qmf_domain.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,35 +106,31 @@ amm-info@iis.fraunhofer.de #include "common_fix.h" #define WORKBUFFER1_TAG 0 -#define WORKBUFFER2_TAG 1 - #define WORKBUFFER3_TAG 4 #define WORKBUFFER4_TAG 5 -#define WORKBUFFER5_TAG 6 #define WORKBUFFER6_TAG 7 +#define WORKBUFFER7_TAG 8 C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL, QMF_WB_SECTION_SIZE, SECT_DATA_L1, WORKBUFFER1_TAG) -C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore2, FIXP_DBL, QMF_WB_SECTION_SIZE, - SECT_DATA_L2, WORKBUFFER2_TAG) C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL, QMF_WB_SECTION_SIZE, SECT_DATA_L2, WORKBUFFER3_TAG) C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL, QMF_WB_SECTION_SIZE, SECT_DATA_L2, WORKBUFFER4_TAG) -C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore5, FIXP_DBL, QMF_WB_SECTION_SIZE, - SECT_DATA_L2, WORKBUFFER5_TAG) C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL, QMF_WB_SECTION_SIZE, SECT_DATA_L2, WORKBUFFER6_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore7, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER7_TAG) /*! Analysis states buffer. <br> Dimension: #((8) + (1)) */ -C_ALLOC_MEM2(AnaQmfStates, FIXP_QAS, 10 * QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS, - ((8) + (1))) +C_AALLOC_MEM2(AnaQmfStates, FIXP_DBL, 10 * QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS, + ((8) + (1))) /*! Synthesis states buffer. <br> Dimension: #((8) + (1)) */ -C_ALLOC_MEM2(SynQmfStates, FIXP_QSS, 9 * QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS, - ((8) + (1))) +C_AALLOC_MEM2(SynQmfStates, FIXP_QSS, 9 * QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS, + ((8) + (1))) /*! Pointer to real qmf data for each time slot. <br> Dimension: #((8) + (1)) */ @@ -156,18 +152,17 @@ C_AALLOC_MEM2(QmfOverlapBuffer, FIXP_DBL, /*! Analysis states buffer. <br> Dimension: #((8) + (1)) */ -C_ALLOC_MEM2(AnaQmfStates16, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_16, - ((8) + (1))) - +C_AALLOC_MEM2(AnaQmfStates16, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_16, + ((8) + (1))) /*! Analysis states buffer. <br> Dimension: #((8) + (1)) */ -C_ALLOC_MEM2(AnaQmfStates24, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_24, - ((8) + (1))) +C_AALLOC_MEM2(AnaQmfStates24, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_24, + ((8) + (1))) /*! Analysis states buffer. <br> Dimension: #((8) + (1)) */ -C_ALLOC_MEM2(AnaQmfStates32, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_32, - ((8) + (1))) +C_AALLOC_MEM2(AnaQmfStates32, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_32, + ((8) + (1))) /*! Pointer to real qmf data for each time slot. <br> Dimension: #((8) + (1)) */ @@ -642,10 +637,10 @@ void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, if (pQmfOutImag == NULL) { for (; b < fMin(lsb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], lb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf); } for (; b < fMin(usb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], hb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf); } for (; b < stop_band; b++) { pQmfOutReal[b] = (FIXP_DBL)0; @@ -653,12 +648,12 @@ void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, } else { FDK_ASSERT(imag != NULL); for (; b < fMin(lsb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], lb_sf); - pQmfOutImag[b] = scaleValue(imag[b], lb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], lb_sf); + pQmfOutImag[b] = scaleValueSaturate(imag[b], lb_sf); } for (; b < fMin(usb, stop_band); b++) { - pQmfOutReal[b] = scaleValue(real[b], hb_sf); - pQmfOutImag[b] = scaleValue(imag[b], hb_sf); + pQmfOutReal[b] = scaleValueSaturate(real[b], hb_sf); + pQmfOutImag[b] = scaleValueSaturate(imag[b], hb_sf); } for (; b < stop_band; b++) { pQmfOutReal[b] = (FIXP_DBL)0; @@ -950,7 +945,7 @@ QMF_DOMAIN_ERROR FDK_QmfDomain_Configure(HANDLE_FDK_QMF_DOMAIN hqd) { if ((size > 4 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[4] == NULL)) { /* get work buffer of size QMF_WB_SECTION_SIZE */ - pWorkBuffer[4] = GetQmfWorkBufferCore5(); + pWorkBuffer[4] = GetQmfWorkBufferCore7(); } /* 8. distribute workbuffer over processing channels */ @@ -996,7 +991,7 @@ static void FDK_QmfDomain_FreeWorkBuffer(HANDLE_FDK_QMF_DOMAIN hqd) { if (pWorkBuffer[1]) FreeQmfWorkBufferCore1(&pWorkBuffer[1]); if (pWorkBuffer[2]) FreeQmfWorkBufferCore3(&pWorkBuffer[2]); if (pWorkBuffer[3]) FreeQmfWorkBufferCore4(&pWorkBuffer[3]); - if (pWorkBuffer[4]) FreeQmfWorkBufferCore5(&pWorkBuffer[4]); + if (pWorkBuffer[4]) FreeQmfWorkBufferCore7(&pWorkBuffer[4]); } void FDK_QmfDomain_FreeMem(HANDLE_FDK_QMF_DOMAIN hqd) { 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/fixpoint_math.cpp b/libFDK/src/fixpoint_math.cpp index 6c656fa..1e26420 100644 --- a/libFDK/src/fixpoint_math.cpp +++ b/libFDK/src/fixpoint_math.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 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. All rights reserved. 1. INTRODUCTION @@ -650,6 +650,12 @@ FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, INT ans_lg2_e, baselg2_e; FIXP_DBL base_lg2, ans_lg2, result; + if (base_m <= (FIXP_DBL)0) { + result = (FIXP_DBL)0; + *result_e = 0; + return result; + } + /* Calc log2 of base */ base_lg2 = fLog2(base_m, base_e, &baselg2_e); diff --git a/libFDK/src/mdct.cpp b/libFDK/src/mdct.cpp index d697cfb..0062b27 100644 --- a/libFDK/src/mdct.cpp +++ b/libFDK/src/mdct.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 @@ -569,7 +569,7 @@ INT imlt_block(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *spectrum, */ for (i = 0; i < hMdct->prev_nr; i++) { FIXP_DBL x = -(*pOvl--); - *pOut0 = IMDCT_SCALE_DBL(x + hMdct->pFacZir[i]); + *pOut0 = fAddSaturate(x, IMDCT_SCALE_DBL(hMdct->pFacZir[i])); pOut0++; } hMdct->pFacZir = NULL; @@ -678,7 +678,7 @@ INT imlt_block(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *spectrum, FIXP_DBL *pOut = pOut0 - fl / 2; FDK_ASSERT(fl / 2 <= 128); for (i = 0; i < fl / 2; i++) { - pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); + pOut[i] = fAddSaturate(pOut[i], IMDCT_SCALE_DBL(hMdct->pFacZir[i])); } hMdct->pFacZir = NULL; } diff --git a/libFDK/src/qmf.cpp b/libFDK/src/qmf.cpp index 6fca043..440bec2 100644 --- a/libFDK/src/qmf.cpp +++ b/libFDK/src/qmf.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 @@ -147,88 +147,6 @@ amm-info@iis.fraunhofer.de /* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot_NonSymmetric */ /* moved to qmf_pcm.h: -> qmfSynthesisFilteringSlot */ -#ifndef FUNCTION_qmfAnaPrototypeFirSlot -/*! - \brief Perform Analysis Prototype Filtering on a single slot of input data. -*/ -static void qmfAnaPrototypeFirSlot( - FIXP_DBL *analysisBuffer, - INT no_channels, /*!< Number channels of analysis filter */ - const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */ - FIXP_QAS *RESTRICT pFilterStates) { - INT k; - - FIXP_DBL accu; - const FIXP_PFT *RESTRICT p_flt = p_filter; - FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1; - FIXP_DBL *RESTRICT pData_1 = analysisBuffer; - - FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; - FIXP_QAS *RESTRICT sta_1 = - (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1; - INT pfltStep = QMF_NO_POLY * (p_stride); - INT staStep1 = no_channels << 1; - INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */ - - /* FIR filters 127..64 0..63 */ - for (k = 0; k < no_channels; k++) { - accu = fMultDiv2(p_flt[0], *sta_1); - sta_1 -= staStep1; - accu += fMultDiv2(p_flt[1], *sta_1); - sta_1 -= staStep1; - accu += fMultDiv2(p_flt[2], *sta_1); - sta_1 -= staStep1; - accu += fMultDiv2(p_flt[3], *sta_1); - sta_1 -= staStep1; - accu += fMultDiv2(p_flt[4], *sta_1); - *pData_1++ = (accu << 1); - sta_1 += staStep2; - - p_flt += pfltStep; - accu = fMultDiv2(p_flt[0], *sta_0); - sta_0 += staStep1; - accu += fMultDiv2(p_flt[1], *sta_0); - sta_0 += staStep1; - accu += fMultDiv2(p_flt[2], *sta_0); - sta_0 += staStep1; - accu += fMultDiv2(p_flt[3], *sta_0); - sta_0 += staStep1; - accu += fMultDiv2(p_flt[4], *sta_0); - *pData_0-- = (accu << 1); - sta_0 -= staStep2; - } -} -#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */ - -#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric -/*! - \brief Perform Analysis Prototype Filtering on a single slot of input data. -*/ -static void qmfAnaPrototypeFirSlot_NonSymmetric( - FIXP_DBL *analysisBuffer, - int no_channels, /*!< Number channels of analysis filter */ - const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */ - FIXP_QAS *RESTRICT pFilterStates) { - const FIXP_PFT *RESTRICT p_flt = p_filter; - int p, k; - - for (k = 0; k < 2 * no_channels; k++) { - FIXP_DBL accu = (FIXP_DBL)0; - - p_flt += QMF_NO_POLY * (p_stride - 1); - - /* - Perform FIR-Filter - */ - for (p = 0; p < QMF_NO_POLY; p++) { - accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]); - } - analysisBuffer[2 * no_channels - 1 - k] = (accu << 1); - pFilterStates++; - } -} -#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */ - /*! * * \brief Perform real-valued forward modulation of the time domain @@ -244,7 +162,7 @@ static void qmfForwardModulationLP_even( int i; int L = anaQmf->no_channels; int M = L >> 1; - int scale; + int scale = 0; FIXP_DBL accu; const FIXP_DBL *timeInTmp1 = (FIXP_DBL *)&timeIn[3 * M]; @@ -381,211 +299,6 @@ static void qmfForwardModulationHQ( } #endif /* FUNCTION_qmfForwardModulationHQ */ -/* - * \brief Perform one QMF slot analysis of the time domain data of timeIn - * with specified stride and stores the real part of the subband - * samples in rSubband, and the imaginary part in iSubband - * - * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case - * of implicit resampling (USAC with reduced 3/4 core frame length). - */ -#if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS) -void qmfAnalysisFilteringSlot( - HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ - FIXP_DBL *qmfReal, /*!< Low and High band, real */ - FIXP_DBL *qmfImag, /*!< Low and High band, imag */ - const LONG *RESTRICT timeIn, /*!< Pointer to input */ - const int stride, /*!< stride factor of input */ - FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ -) { - int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); - /* - Feed time signal into oldest anaQmf->no_channels states - */ - { - FIXP_DBL *FilterStatesAnaTmp = ((FIXP_DBL *)anaQmf->FilterStates) + offset; - - /* Feed and scale actual time in slot */ - for (int i = anaQmf->no_channels >> 1; i != 0; i--) { - /* Place INT_PCM value left aligned in scaledTimeIn */ - - *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; - timeIn += stride; - *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; - timeIn += stride; - } - } - - if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { - qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, - anaQmf->p_filter, anaQmf->p_stride, - (FIXP_QAS *)anaQmf->FilterStates); - } else { - qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, - anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); - } - - if (anaQmf->flags & QMF_FLAG_LP) { - if (anaQmf->flags & QMF_FLAG_CLDFB) - qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); - else - qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); - - } else { - qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); - } - /* - Shift filter states - - Should be realized with modulo adressing on a DSP instead of a true buffer - shift - */ - FDKmemmove(anaQmf->FilterStates, - (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, - offset * sizeof(FIXP_QAS)); -} -#endif - -void qmfAnalysisFilteringSlot( - HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ - FIXP_DBL *qmfReal, /*!< Low and High band, real */ - FIXP_DBL *qmfImag, /*!< Low and High band, imag */ - const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */ - const int stride, /*!< stride factor of input */ - FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ -) { - int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); - /* - Feed time signal into oldest anaQmf->no_channels states - */ - { - FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset; - - /* Feed and scale actual time in slot */ - for (int i = anaQmf->no_channels >> 1; i != 0; i--) { - /* Place INT_PCM value left aligned in scaledTimeIn */ -#if (QAS_BITS == SAMPLE_BITS) - *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; - timeIn += stride; - *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; - timeIn += stride; -#elif (QAS_BITS > SAMPLE_BITS) - *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS); - timeIn += stride; - *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS); - timeIn += stride; -#else - *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS)); - timeIn += stride; - *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS)); - timeIn += stride; -#endif - } - } - - if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { - qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, - anaQmf->p_filter, anaQmf->p_stride, - (FIXP_QAS *)anaQmf->FilterStates); - } else { - qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, - anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); - } - - if (anaQmf->flags & QMF_FLAG_LP) { - if (anaQmf->flags & QMF_FLAG_CLDFB) - qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); - else - qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); - - } else { - qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); - } - /* - Shift filter states - - Should be realized with modulo adressing on a DSP instead of a true buffer - shift - */ - FDKmemmove(anaQmf->FilterStates, - (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, - offset * sizeof(FIXP_QAS)); -} - -/*! - * - * \brief Perform complex-valued subband filtering of the time domain - * data of timeIn and stores the real part of the subband - * samples in rAnalysis, and the imaginary part in iAnalysis - * The qmf coefficient table is symmetric. The symmetry is expoited by - * shrinking the coefficient table to half the size. The addressing mode - * takes care of the symmetries. - * - * - * \sa PolyphaseFiltering - */ -#if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS) -void qmfAnalysisFiltering( - HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ - FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ - FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ - QMF_SCALE_FACTOR *scaleFactor, const LONG *timeIn, /*!< Time signal */ - const int timeIn_e, const int stride, - FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ -) { - int i; - int no_channels = anaQmf->no_channels; - - scaleFactor->lb_scale = - -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; - scaleFactor->lb_scale -= anaQmf->filterScale; - - for (i = 0; i < anaQmf->no_col; i++) { - FIXP_DBL *qmfImagSlot = NULL; - - if (!(anaQmf->flags & QMF_FLAG_LP)) { - qmfImagSlot = qmfImag[i]; - } - - qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, - pWorkBuffer); - - timeIn += no_channels * stride; - - } /* no_col loop i */ -} -#endif - -void qmfAnalysisFiltering( - HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ - FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ - FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ - QMF_SCALE_FACTOR *scaleFactor, const INT_PCM *timeIn, /*!< Time signal */ - const int timeIn_e, const int stride, - FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ -) { - int i; - int no_channels = anaQmf->no_channels; - - scaleFactor->lb_scale = - -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; - scaleFactor->lb_scale -= anaQmf->filterScale; - - for (i = 0; i < anaQmf->no_col; i++) { - FIXP_DBL *qmfImagSlot = NULL; - - if (!(anaQmf->flags & QMF_FLAG_LP)) { - qmfImagSlot = qmfImag[i]; - } - - qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, - pWorkBuffer); - - timeIn += no_channels * stride; - - } /* no_col loop i */ -} - /*! * * \brief Perform low power inverse modulation of the subband @@ -603,15 +316,15 @@ inline static void qmfInverseModulationLP_even( int i; int L = synQmf->no_channels; int M = L >> 1; - int scale; + int scale = 0; FIXP_DBL tmp; FIXP_DBL *RESTRICT tReal = pTimeOut; 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 +375,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 +411,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], @@ -1004,35 +718,6 @@ static inline void qmfAdaptFilterStates( * \return 0 if succesful * */ -int qmfInitAnalysisFilterBank( - HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ - FIXP_QAS *pFilterStates, /*!< Handle to filter states */ - int noCols, /*!< Number of timeslots per frame */ - int lsb, /*!< lower end of QMF */ - int usb, /*!< upper end of QMF */ - int no_channels, /*!< Number of channels (bands) */ - int flags) /*!< Low Power flag */ -{ - int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, - no_channels, flags, 0); - if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) { - FDKmemclear(h_Qmf->FilterStates, - (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS)); - } - - FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); - - return err; -} - -/*! - * - * \brief Create QMF filter bank instance - * - * - * \return 0 if succesful - * - */ int qmfInitSynthesisFilterBank( HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ FIXP_QSS *pFilterStates, /*!< Handle to filter states */ @@ -1128,8 +813,21 @@ void qmfChangeOutGain( synQmf->outGain_e = outputGainScale; } -/* When QMF_16IN_32OUT is set, synthesis functions for 16 and 32 bit parallel - * output is compiled */ #define INT_PCM_QMFOUT INT_PCM #define SAMPLE_BITS_QMFOUT SAMPLE_BITS #include "qmf_pcm.h" +#if SAMPLE_BITS == 16 + /* also create a 32 bit output version */ +#undef INT_PCM_QMFOUT +#undef SAMPLE_BITS_QMFOUT +#undef QMF_PCM_H +#undef FIXP_QAS +#undef QAS_BITS +#undef INT_PCM_QMFIN +#define INT_PCM_QMFOUT LONG +#define SAMPLE_BITS_QMFOUT 32 +#define FIXP_QAS FIXP_DBL +#define QAS_BITS 32 +#define INT_PCM_QMFIN LONG +#include "qmf_pcm.h" +#endif 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; |