aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libFDK/include/FDK_qmf_domain.h12
-rw-r--r--libFDK/include/qmf.h105
-rw-r--r--libFDK/include/qmf_pcm.h218
-rw-r--r--libFDK/src/FDK_qmf_domain.cpp23
-rw-r--r--libFDK/src/qmf.cpp333
5 files changed, 318 insertions, 373 deletions
diff --git a/libFDK/include/FDK_qmf_domain.h b/libFDK/include/FDK_qmf_domain.h
index 5c12682..d8bc8ce 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
@@ -145,15 +145,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 *)
@@ -244,7 +244,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/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/src/FDK_qmf_domain.cpp b/libFDK/src/FDK_qmf_domain.cpp
index 3245deb..5e1d35f 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
@@ -128,13 +128,13 @@ C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL, QMF_WB_SECTION_SIZE,
/*! 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 +156,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)) */
diff --git a/libFDK/src/qmf.cpp b/libFDK/src/qmf.cpp
index 19f1ea1..440bec2 100644
--- a/libFDK/src/qmf.cpp
+++ b/libFDK/src/qmf.cpp
@@ -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
@@ -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
@@ -1005,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 */
@@ -1129,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