aboutsummaryrefslogtreecommitdiffstats
path: root/libFDK/src/qmf.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2021-06-01 14:25:25 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2021-06-01 14:25:25 +0200
commite778887e4e5589528b06b04404ce4c71aaae267a (patch)
treefcce7bfb237a99ac174e16611f39bf363f6b280c /libFDK/src/qmf.cpp
parent97182034e8829014bdfc0449c2116d629196f1d4 (diff)
parent801f67f671929311e0c9952c5f92d6e147c7b003 (diff)
downloadfdk-aac-e778887e4e5589528b06b04404ce4c71aaae267a.tar.gz
fdk-aac-e778887e4e5589528b06b04404ce4c71aaae267a.tar.bz2
fdk-aac-e778887e4e5589528b06b04404ce4c71aaae267a.zip
Merge v2.0.2 into dabplus2
Diffstat (limited to 'libFDK/src/qmf.cpp')
-rw-r--r--libFDK/src/qmf.cpp384
1 files changed, 41 insertions, 343 deletions
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