mirror of https://github.com/mstorsjo/fdk-aac.git
Restructure QMF implementation and provide 16/32 bit implementation in parallel.
Bug: 149514474 Test: atest DecoderTestXheAac DecoderTestAacDrc Change-Id: I2c6b332a0b5c4966a3f680d7a4d562d9bf18752c
This commit is contained in:
parent
443d38963e
commit
5482443193
|
@ -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
|
||||
|
|
|
@ -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,16 +202,25 @@ struct QMF_FILTER_BANK {
|
|||
|
||||
typedef struct QMF_FILTER_BANK *HANDLE_QMF_FILTER_BANK;
|
||||
|
||||
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 timeIn_e, /*!< Exponent of audio data */
|
||||
const int stride, /*!< Stride factor of audio data */
|
||||
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 */
|
||||
#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 */
|
||||
|
@ -222,6 +232,48 @@ void qmfAnalysisFiltering(
|
|||
const int stride, /*!< Stride factor of audio data */
|
||||
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 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 temporary working buffer */
|
||||
);
|
||||
#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 *timeIn, /*!< Pointer to input */
|
||||
const int stride, /*!< stride factor of input */
|
||||
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 LONG *timeIn, /*!< Pointer to input */
|
||||
const int stride, /*!< stride factor of input */
|
||||
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 */
|
||||
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 */
|
||||
|
||||
void qmfSynthesisFiltering(
|
||||
HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */
|
||||
|
@ -234,41 +286,19 @@ void qmfSynthesisFiltering(
|
|||
FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer. It must be
|
||||
aligned */
|
||||
);
|
||||
#if SAMPLE_BITS == 16
|
||||
|
||||
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 */
|
||||
|
||||
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 stride, /*!< stride factor of input */
|
||||
FIXP_DBL *pWorkBuffer /*!< pointer to temporary 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 */
|
||||
LONG *timeOut, /*!< Time signal */
|
||||
const int timeOut_e, /*!< Target exponent for timeOut */
|
||||
FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */
|
||||
);
|
||||
|
||||
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 int stride, /*!< stride factor of input */
|
||||
FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */
|
||||
);
|
||||
int qmfInitSynthesisFilterBank(
|
||||
HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */
|
||||
FIXP_QSS *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 qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf,
|
||||
const FIXP_DBL *realSlot,
|
||||
|
@ -276,6 +306,15 @@ void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf,
|
|||
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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_AALLOC_MEM2(AnaQmfStates24, FIXP_DBL, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_24,
|
||||
((8) + (1)))
|
||||
|
||||
/*! Analysis states buffer. <br>
|
||||
Dimension: #((8) + (1)) */
|
||||
C_ALLOC_MEM2(AnaQmfStates24, FIXP_QAS, 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)) */
|
||||
|
|
|
@ -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
|
||||
|
@ -997,35 +710,6 @@ static inline void qmfAdaptFilterStates(
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
*
|
||||
* \brief Create QMF filter bank instance
|
||||
*
|
||||
*
|
||||
* \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
|
||||
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue