aboutsummaryrefslogtreecommitdiffstats
path: root/libSBRdec/src/psdec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libSBRdec/src/psdec.cpp')
-rw-r--r--libSBRdec/src/psdec.cpp1556
1 files changed, 428 insertions, 1128 deletions
diff --git a/libSBRdec/src/psdec.cpp b/libSBRdec/src/psdec.cpp
index 965917a..13a21bf 100644
--- a/libSBRdec/src/psdec.cpp
+++ b/libSBRdec/src/psdec.cpp
@@ -1,74 +1,85 @@
-
-/* -----------------------------------------------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
- All rights reserved.
+© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+Forschung e.V. All rights reserved.
1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
-the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
-This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
-audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
-independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
-of the MPEG specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
-may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
-individually for the purpose of encoding or decoding bit streams in products that are compliant with
-the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
-these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
-software may already be covered under those patent licenses when it is used for those licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
-are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
-applications information and documentation.
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
+that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
+scheme for digital audio. This FDK AAC Codec software is intended to be used on
+a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
+general perceptual audio codecs. AAC-ELD is considered the best-performing
+full-bandwidth communications codec by independent studies and is widely
+deployed. AAC has been standardized by ISO and IEC as part of the MPEG
+specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including
+those of Fraunhofer) may be obtained through Via Licensing
+(www.vialicensing.com) or through the respective patent owners individually for
+the purpose of encoding or decoding bit streams in products that are compliant
+with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
+Android devices already license these patent claims through Via Licensing or
+directly from the patent owners, and therefore FDK AAC Codec software may
+already be covered under those patent licenses when it is used for those
+licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions
+with enhanced sound quality, are also available from Fraunhofer. Users are
+encouraged to check the Fraunhofer website for additional applications
+information and documentation.
2. COPYRIGHT LICENSE
-Redistribution and use in source and binary forms, with or without modification, are permitted without
-payment of copyright license fees provided that you satisfy the following conditions:
+Redistribution and use in source and binary forms, with or without modification,
+are permitted without payment of copyright license fees provided that you
+satisfy the following conditions:
-You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
-your modifications thereto in source code form.
+You must retain the complete text of this software license in redistributions of
+the FDK AAC Codec or your modifications thereto in source code form.
-You must retain the complete text of this software license in the documentation and/or other materials
-provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
-You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+You must retain the complete text of this software license in the documentation
+and/or other materials provided with redistributions of the FDK AAC Codec or
+your modifications thereto in binary form. You must make available free of
+charge copies of the complete source code of the FDK AAC Codec and your
modifications thereto to recipients of copies in binary form.
-The name of Fraunhofer may not be used to endorse or promote products derived from this library without
-prior written permission.
+The name of Fraunhofer may not be used to endorse or promote products derived
+from this library without prior written permission.
-You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
-software or your modifications thereto.
+You may not charge copyright license fees for anyone to use, copy or distribute
+the FDK AAC Codec software or your modifications thereto.
-Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
-and the date of any change. For modified versions of the FDK AAC Codec, the term
-"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
-"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+Your modified versions of the FDK AAC Codec must carry prominent notices stating
+that you changed the software and the date of any change. For modified versions
+of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
+must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
+AAC Codec Library for Android."
3. NO PATENT LICENSE
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
-ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
-respect to this software.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
+limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
+Fraunhofer provides no warranty of patent non-infringement with respect to this
+software.
-You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
-by appropriate patent licenses.
+You may use this FDK AAC Codec software or modifications thereto only for
+purposes that are authorized by appropriate patent licenses.
4. DISCLAIMER
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
-"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
-of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
-including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
-or business interruption, however caused and on any theory of liability, whether in contract, strict
-liability, or tort (including negligence), arising in any way out of the use of this software, even if
-advised of the possibility of such damage.
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
+holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+including but not limited to the implied warranties of merchantability and
+fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
+or consequential damages, including but not limited to procurement of substitute
+goods or services; loss of use, data, or profits, or business interruption,
+however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of
+this software, even if advised of the possibility of such damage.
5. CONTACT INFORMATION
@@ -79,19 +90,24 @@ Am Wolfsmantel 33
www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
+----------------------------------------------------------------------------- */
+
+/**************************** SBR decoder library ******************************
+
+ Author(s):
+
+ Description:
+
+*******************************************************************************/
/*!
\file
- \brief parametric stereo decoder
+ \brief parametric stereo decoder
*/
#include "psdec.h"
-
-
#include "FDK_bitbuffer.h"
-#include "psdec_hybrid.h"
#include "sbr_rom.h"
#include "sbr_ram.h"
@@ -102,30 +118,17 @@ amm-info@iis.fraunhofer.de
#include "FDK_trigFcts.h"
-
/********************************************************************/
/* MLQUAL DEFINES */
/********************************************************************/
- #define FRACT_ZERO FRACT_BITS-1
+#define FRACT_ZERO FRACT_BITS - 1
/********************************************************************/
-SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d );
-
-void ResetPsDeCor( HANDLE_PS_DEC h_ps_d );
-
+SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d);
/***** HELPERS *****/
-static void assignTimeSlotsPS (FIXP_DBL *bufAdr, FIXP_DBL **bufPtr, const int numSlots, const int numChan);
-
-
-
-/*******************/
-
-#define DIV3 FL2FXCONST_DBL(1.f/3.f) /* division 3.0 */
-#define DIV1_5 FL2FXCONST_DBL(2.f/3.f) /* division 1.5 */
-
/***************************************************************************/
/*!
\brief Creates one instance of the PS_DEC struct
@@ -133,20 +136,16 @@ static void assignTimeSlotsPS (FIXP_DBL *bufAdr, FIXP_DBL **bufPtr, const int nu
\return Error info
****************************************************************************/
-int
-CreatePsDec( HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */
- int aacSamplesPerFrame
- )
-{
+int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */
+ int aacSamplesPerFrame) {
SBR_ERROR errorInfo = SBRDEC_OK;
- HANDLE_PS_DEC h_ps_d;
+ HANDLE_PS_DEC h_ps_d;
int i;
if (*h_PS_DEC == NULL) {
/* Get ps dec ram */
h_ps_d = GetRam_ps_dec();
if (h_ps_d == NULL) {
- errorInfo = SBRDEC_MEM_ALLOC_FAILED;
goto bail;
}
} else {
@@ -154,52 +153,61 @@ CreatePsDec( HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */
h_ps_d = *h_PS_DEC;
}
- /* initialisation */
- switch (aacSamplesPerFrame) {
- case 960:
- h_ps_d->noSubSamples = 30; /* col */
- break;
- case 1024:
- h_ps_d->noSubSamples = 32; /* col */
- break;
- default:
- h_ps_d->noSubSamples = -1;
- break;
- }
+ /*
+ * Create Analysis Hybrid filterbank.
+ */
+ FDKhybridAnalysisOpen(&h_ps_d->specificTo.mpeg.hybridAnalysis,
+ h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx,
+ sizeof(h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx),
+ NULL, 0);
- if (h_ps_d->noSubSamples > MAX_NUM_COL
- || h_ps_d->noSubSamples <= 0)
- {
+ /* initialisation */
+ switch (aacSamplesPerFrame) {
+ case 960:
+ h_ps_d->noSubSamples = 30; /* col */
+ break;
+ case 1024:
+ h_ps_d->noSubSamples = 32; /* col */
+ break;
+ default:
+ h_ps_d->noSubSamples = -1;
+ break;
+ }
+
+ if (h_ps_d->noSubSamples > MAX_NUM_COL || h_ps_d->noSubSamples <= 0) {
goto bail;
}
- h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */
+ h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */
- h_ps_d->psDecodedPrv = 0;
+ h_ps_d->psDecodedPrv = 0;
h_ps_d->procFrameBased = -1;
- for (i = 0; i < (1)+1; i++) {
- h_ps_d->bPsDataAvail[i] = ppt_none;
+ for (i = 0; i < (1) + 1; i++) {
+ h_ps_d->bPsDataAvail[i] = ppt_none;
+ }
+ {
+ int error;
+ error = FDKdecorrelateOpen(&(h_ps_d->specificTo.mpeg.apDecor),
+ h_ps_d->specificTo.mpeg.decorrBufferCplx,
+ (2 * ((825) + (373))));
+ if (error) goto bail;
}
-
- for (i = 0; i < (1)+1; i++) {
+ for (i = 0; i < (1) + 1; i++) {
FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA));
}
- errorInfo = ResetPsDec( h_ps_d );
+ errorInfo = ResetPsDec(h_ps_d);
- if ( errorInfo != SBRDEC_OK )
- goto bail;
-
- ResetPsDeCor( h_ps_d );
+ if (errorInfo != SBRDEC_OK) goto bail;
*h_PS_DEC = h_ps_d;
-
-
return 0;
bail:
- DeletePsDec(&h_ps_d);
+ if (h_ps_d != NULL) {
+ DeletePsDec(&h_ps_d);
+ }
return -1;
} /*END CreatePsDec */
@@ -211,17 +219,19 @@ bail:
\return Error info
****************************************************************************/
-int
-DeletePsDec( HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */
+int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */
{
if (*h_PS_DEC == NULL) {
return -1;
}
+ {
+ HANDLE_PS_DEC h_ps_d = *h_PS_DEC;
+ FDKdecorrelateClose(&(h_ps_d->specificTo.mpeg.apDecor));
+ }
FreeRam_ps_dec(h_PS_DEC);
-
return 0;
} /*END DeletePsDec */
@@ -232,825 +242,179 @@ DeletePsDec( HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */
\return
****************************************************************************/
-SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */
+SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d) /*!< pointer to the module state */
{
SBR_ERROR errorInfo = SBRDEC_OK;
INT i;
- const UCHAR noQmfBandsInHybrid20 = 3;
- /* const UCHAR noQmfBandsInHybrid34 = 5; */
-
- const UCHAR aHybridResolution20[] = { HYBRID_8_CPLX,
- HYBRID_2_REAL,
- HYBRID_2_REAL };
-
- h_ps_d->specificTo.mpeg.delayBufIndex = 0;
+ /* explicitly init state variables to safe values (until first ps header
+ * arrives) */
- /* explicitly init state variables to safe values (until first ps header arrives) */
+ h_ps_d->specificTo.mpeg.lastUsb = 0;
- h_ps_d->specificTo.mpeg.lastUsb = 0;
+ /*
+ * Initialize Analysis Hybrid filterbank.
+ */
+ FDKhybridAnalysisInit(&h_ps_d->specificTo.mpeg.hybridAnalysis, THREE_TO_TEN,
+ NO_QMF_BANDS_HYBRID20, NO_QMF_BANDS_HYBRID20, 1);
- h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = -(DFRACT_BITS-1);
-
- FDKmemclear(h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf, (NO_QMF_CHANNELS-FIRST_DELAY_SB)*sizeof(UCHAR));
- h_ps_d->specificTo.mpeg.noSampleDelay = delayIndexQmf[0];
-
- for (i=0 ; i < NO_SERIAL_ALLPASS_LINKS; i++) {
- h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[i] = 0;
+ /*
+ * Initialize Synthesis Hybrid filterbank.
+ */
+ for (i = 0; i < 2; i++) {
+ FDKhybridSynthesisInit(&h_ps_d->specificTo.mpeg.hybridSynthesis[i],
+ THREE_TO_TEN, NO_QMF_CHANNELS, NO_QMF_CHANNELS);
}
-
- h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufReal;
-
- assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB),
- &h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[1],
- h_ps_d->specificTo.mpeg.noSampleDelay-1,
- (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB));
-
- h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufImag;
-
- assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB),
- &h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[1],
- h_ps_d->specificTo.mpeg.noSampleDelay-1,
- (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB));
-
- /* Hybrid Filter Bank 1 creation. */
- errorInfo = InitHybridFilterBank ( &h_ps_d->specificTo.mpeg.hybrid,
- h_ps_d->noSubSamples,
- noQmfBandsInHybrid20,
- aHybridResolution20 );
-
- for ( i = 0; i < NO_IID_GROUPS; i++ )
{
+ INT error;
+ error = FDKdecorrelateInit(&h_ps_d->specificTo.mpeg.apDecor, 71, DECORR_PS,
+ DUCKER_AUTOMATIC, 0, 0, 0, 0, 1, /* isLegacyPS */
+ 1);
+ if (error) return SBRDEC_NOT_INITIALIZED;
+ }
+
+ for (i = 0; i < NO_IID_GROUPS; i++) {
h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f);
h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f);
}
- FDKmemclear( h_ps_d->specificTo.mpeg.h21rPrev, sizeof( h_ps_d->specificTo.mpeg.h21rPrev ) );
- FDKmemclear( h_ps_d->specificTo.mpeg.h22rPrev, sizeof( h_ps_d->specificTo.mpeg.h22rPrev ) );
+ FDKmemclear(h_ps_d->specificTo.mpeg.h21rPrev,
+ sizeof(h_ps_d->specificTo.mpeg.h21rPrev));
+ FDKmemclear(h_ps_d->specificTo.mpeg.h22rPrev,
+ sizeof(h_ps_d->specificTo.mpeg.h22rPrev));
return errorInfo;
}
/***************************************************************************/
/*!
- \brief clear some buffers used in decorrelation process
-
- \return
-
-****************************************************************************/
-void ResetPsDeCor( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */
-{
- INT i;
-
- FDKmemclear(h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS*sizeof(FIXP_DBL));
- FDKmemclear(h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS*sizeof(FIXP_DBL));
- FDKmemclear(h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS*sizeof(FIXP_DBL));
- FDKmemclear(h_ps_d->specificTo.mpeg.aPowerPrevScal, NO_MID_RES_BINS*sizeof(SCHAR));
-
- for (i=0 ; i < FIRST_DELAY_SB ; i++) {
- FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
- FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
- }
- for (i=0 ; i < NO_SUB_QMF_CHANNELS ; i++) {
- FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
- FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
- }
-
-}
-
-/*******************************************************************************/
-
-/* slot based funcion prototypes */
-
-static void deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d,
-
- FIXP_DBL *mHybridRealLeft,
- FIXP_DBL *mHybridImagLeft,
- SCHAR sf_mHybridLeft,
-
- FIXP_DBL *rIntBufferLeft,
- FIXP_DBL *iIntBufferLeft,
- SCHAR sf_IntBuffer,
-
- FIXP_DBL *mHybridRealRight,
- FIXP_DBL *mHybridImagRight,
-
- FIXP_DBL *rIntBufferRight,
- FIXP_DBL *iIntBufferRight );
-
-static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d,
-
- FIXP_DBL *mHybridRealLeft,
- FIXP_DBL *mHybridImagLeft,
-
- FIXP_DBL *QmfLeftReal,
- FIXP_DBL *QmfLeftImag,
-
- FIXP_DBL *mHybridRealRight,
- FIXP_DBL *mHybridImagRight,
-
- FIXP_DBL *QmfRightReal,
- FIXP_DBL *QmfRightImag
- );
-
-
-/***************************************************************************/
-/*!
- \brief Get scale factor for all ps delay buffer.
-
- \return
-
-****************************************************************************/
-static
-int getScaleFactorPsStatesBuffer(HANDLE_PS_DEC h_ps_d)
-{
- INT i;
- int scale = DFRACT_BITS-1;
-
- for (i=0; i<NO_QMF_BANDS_HYBRID20; i++) {
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS));
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS));
- }
-
- for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB));
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB));
- }
-
- for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS));
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS));
- }
-
- for (i=0; i<FIRST_DELAY_SB; i++) {
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS));
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS));
- }
-
- for (i=0; i<NO_SUB_QMF_CHANNELS; i++) {
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS));
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS));
- }
-
- for (i=0; i<MAX_DELAY_BUFFER_SIZE; i++)
- {
- INT len;
- if (i==0)
- len = NO_QMF_CHANNELS-FIRST_DELAY_SB;
- else
- len = NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB;
-
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[i], len));
- scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len));
- }
-
- return (scale);
-}
-
-/***************************************************************************/
-/*!
- \brief Rescale all ps delay buffer.
-
+ \brief Feed delaylines when parametric stereo is switched on.
\return
-
****************************************************************************/
-static
-void scalePsStatesBuffer(HANDLE_PS_DEC h_ps_d,
- int scale)
-{
- INT i;
-
- if (scale < 0)
- scale = fixMax((INT)scale,(INT)-(DFRACT_BITS-1));
- else
- scale = fixMin((INT)scale,(INT)DFRACT_BITS-1);
-
- for (i=0; i<NO_QMF_BANDS_HYBRID20; i++) {
- scaleValues( h_ps_d->specificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS, scale );
- scaleValues( h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS, scale );
- }
-
- for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
- scaleValues( h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB, scale );
- scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB, scale );
- }
-
- for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) {
- scaleValues( h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale );
- scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale );
- }
-
- for (i=0; i<FIRST_DELAY_SB; i++) {
- scaleValues( h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
- scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
- }
-
- for (i=0; i<NO_SUB_QMF_CHANNELS; i++) {
- scaleValues( h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
- scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale );
- }
-
- for (i=0; i<MAX_DELAY_BUFFER_SIZE; i++) {
- INT len;
- if (i==0)
- len = NO_QMF_CHANNELS-FIRST_DELAY_SB;
- else
- len = NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB;
-
- scaleValues( h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[i], len, scale );
- scaleValues( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len, scale );
- }
-
- scale <<= 1;
-
- scaleValues( h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS, scale );
- scaleValues( h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS, scale );
- scaleValues( h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS, scale );
-}
-
-/***************************************************************************/
-/*!
- \brief Scale input channel to the same scalefactor and rescale hybrid
- filterbank values
-
- \return
-
-****************************************************************************/
-
-void scalFilterBankValues( HANDLE_PS_DEC h_ps_d,
- FIXP_DBL **fixpQmfReal,
- FIXP_DBL **fixpQmfImag,
- int lsb,
- int scaleFactorLowBandSplitLow,
- int scaleFactorLowBandSplitHigh,
- SCHAR *scaleFactorLowBand_lb,
- SCHAR *scaleFactorLowBand_hb,
- int scaleFactorHighBands,
- INT *scaleFactorHighBand,
- INT noCols
- )
-{
- INT maxScal;
-
- INT i;
-
- scaleFactorHighBands = -scaleFactorHighBands;
- scaleFactorLowBandSplitLow = -scaleFactorLowBandSplitLow;
- scaleFactorLowBandSplitHigh = -scaleFactorLowBandSplitHigh;
-
- /* get max scale factor */
- maxScal = fixMax(scaleFactorHighBands,fixMax(scaleFactorLowBandSplitLow, scaleFactorLowBandSplitHigh ));
-
- {
- int headroom = getScaleFactorPsStatesBuffer(h_ps_d);
- maxScal = fixMax(maxScal,(INT)(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-headroom));
- maxScal += 1;
- }
-
- /* scale whole left channel to the same scale factor */
-
- /* low band ( overlap buffer ) */
- if ( maxScal != scaleFactorLowBandSplitLow ) {
- INT scale = scaleFactorLowBandSplitLow - maxScal;
- for ( i=0; i<(6); i++ ) {
- scaleValues( fixpQmfReal[i], lsb, scale );
- scaleValues( fixpQmfImag[i], lsb, scale );
- }
- }
- /* low band ( current frame ) */
- if ( maxScal != scaleFactorLowBandSplitHigh ) {
- INT scale = scaleFactorLowBandSplitHigh - maxScal;
- /* for ( i=(6); i<(6)+MAX_NUM_COL; i++ ) { */
- for ( i=(6); i<(6)+noCols; i++ ) {
- scaleValues( fixpQmfReal[i], lsb, scale );
- scaleValues( fixpQmfImag[i], lsb, scale );
- }
- }
- /* high band */
- if ( maxScal != scaleFactorHighBands ) {
- INT scale = scaleFactorHighBands - maxScal;
- /* for ( i=0; i<MAX_NUM_COL; i++ ) { */
- for ( i=0; i<noCols; i++ ) {
- scaleValues( &fixpQmfReal[i][lsb], (64)-lsb, scale );
- scaleValues( &fixpQmfImag[i][lsb], (64)-lsb, scale );
- }
- }
-
- if ( maxScal != h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer )
- scalePsStatesBuffer(h_ps_d,(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-maxScal));
-
- h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer = maxScal;
- h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = maxScal;
-
- *scaleFactorHighBand += maxScal - scaleFactorHighBands;
-
- h_ps_d->rescal = maxScal - scaleFactorLowBandSplitHigh;
- h_ps_d->sf_IntBuffer = maxScal;
-
- *scaleFactorLowBand_lb += maxScal - scaleFactorLowBandSplitLow;
- *scaleFactorLowBand_hb += maxScal - scaleFactorLowBandSplitHigh;
-}
-
-void rescalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */
- FIXP_DBL **QmfBufferReal, /* qmf filterbank values */
- FIXP_DBL **QmfBufferImag, /* qmf filterbank values */
- int lsb, /* sbr start subband */
- INT noCols)
-{
- int i;
- /* scale back 6 timeslots look ahead for hybrid filterbank to original value */
- for ( i=noCols; i<noCols + (6); i++ ) {
- scaleValues( QmfBufferReal[i], lsb, h_ps_d->rescal );
- scaleValues( QmfBufferImag[i], lsb, h_ps_d->rescal );
- }
-}
-
-/***************************************************************************/
-/*!
- \brief Generate decorrelated side channel using allpass/delay
-
- \return
-
-****************************************************************************/
-static void
-deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
-
- FIXP_DBL *mHybridRealLeft, /*!< left (mono) hybrid values real */
- FIXP_DBL *mHybridImagLeft, /*!< left (mono) hybrid values imag */
- SCHAR sf_mHybridLeft, /*!< scalefactor for left (mono) hybrid bands */
-
- FIXP_DBL *rIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */
- FIXP_DBL *iIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */
- SCHAR sf_IntBuffer, /*!< scalefactor for all left and right qmf bands */
-
- FIXP_DBL *mHybridRealRight, /*!< right (decorrelated) hybrid values real */
- FIXP_DBL *mHybridImagRight, /*!< right (decorrelated) hybrid values imag */
-
- FIXP_DBL *rIntBufferRight, /*!< real qmf bands right (decorrelated) (38x64) */
- FIXP_DBL *iIntBufferRight ) /*!< real qmf bands right (decorrelated) (38x64) */
-{
-
- INT i, m, sb, gr, bin;
-
- FIXP_DBL peakDiff, nrg, transRatio;
-
- FIXP_DBL *RESTRICT aaLeftReal;
- FIXP_DBL *RESTRICT aaLeftImag;
-
- FIXP_DBL *RESTRICT aaRightReal;
- FIXP_DBL *RESTRICT aaRightImag;
-
- FIXP_DBL *RESTRICT pRealDelayBuffer;
- FIXP_DBL *RESTRICT pImagDelayBuffer;
-
- C_ALLOC_SCRATCH_START(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS);
- C_ALLOC_SCRATCH_START(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS);
-
-/*!
-<pre>
- parameter index qmf bands hybrid bands
- ----------------------------------------------------------------------------
- 0 0 0,7
- 1 0 1,6
- 2 0 2
- 3 0 3 HYBRID BANDS
- 4 1 9
- 5 1 8
- 6 2 10
- 7 2 11
- ----------------------------------------------------------------------------
- 8 3
- 9 4
- 10 5
- 11 6
- 12 7
- 13 8
- 14 9,10 (2 ) QMF BANDS
- 15 11 - 13 (3 )
- 16 14 - 17 (4 )
- 17 18 - 22 (5 )
- 18 23 - 34 (12)
- 19 35 - 63 (29)
- ----------------------------------------------------------------------------
-</pre>
-*/
-
- #define FLTR_SCALE 3
-
- /* hybrid bands (parameter index 0 - 7) */
- aaLeftReal = mHybridRealLeft;
- aaLeftImag = mHybridImagLeft;
-
- aaPowerSlot[0] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[0], aaLeftReal[0]), aaLeftImag[0], aaLeftImag[0] ) >> FLTR_SCALE ) +
- ( fMultAddDiv2( fMultDiv2(aaLeftReal[7], aaLeftReal[7]), aaLeftImag[7], aaLeftImag[7] ) >> FLTR_SCALE );
-
- aaPowerSlot[1] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[1], aaLeftReal[1]), aaLeftImag[1], aaLeftImag[1] ) >> FLTR_SCALE ) +
- ( fMultAddDiv2( fMultDiv2(aaLeftReal[6], aaLeftReal[6]), aaLeftImag[6], aaLeftImag[6] ) >> FLTR_SCALE );
-
- aaPowerSlot[2] = fMultAddDiv2( fMultDiv2(aaLeftReal[2], aaLeftReal[2]), aaLeftImag[2], aaLeftImag[2] ) >> FLTR_SCALE;
- aaPowerSlot[3] = fMultAddDiv2( fMultDiv2(aaLeftReal[3], aaLeftReal[3]), aaLeftImag[3], aaLeftImag[3] ) >> FLTR_SCALE;
-
- aaPowerSlot[4] = fMultAddDiv2( fMultDiv2(aaLeftReal[9], aaLeftReal[9]), aaLeftImag[9], aaLeftImag[9] ) >> FLTR_SCALE;
- aaPowerSlot[5] = fMultAddDiv2( fMultDiv2(aaLeftReal[8], aaLeftReal[8]), aaLeftImag[8], aaLeftImag[8] ) >> FLTR_SCALE;
-
- aaPowerSlot[6] = fMultAddDiv2( fMultDiv2(aaLeftReal[10], aaLeftReal[10]), aaLeftImag[10], aaLeftImag[10] ) >> FLTR_SCALE;
- aaPowerSlot[7] = fMultAddDiv2( fMultDiv2(aaLeftReal[11], aaLeftReal[11]), aaLeftImag[11], aaLeftImag[11] ) >> FLTR_SCALE;
-
- /* qmf bands (parameter index 8 - 19) */
- for ( bin = 8; bin < NO_MID_RES_BINS; bin++ ) {
- FIXP_DBL slotNrg = FL2FXCONST_DBL(0.f);
-
- for ( i = groupBorders20[bin+2]; i < groupBorders20[bin+3]; i++ ) { /* max loops: 29 */
- slotNrg += fMultAddDiv2 ( fMultDiv2(rIntBufferLeft[i], rIntBufferLeft[i]), iIntBufferLeft[i], iIntBufferLeft[i]) >> FLTR_SCALE;
- }
- aaPowerSlot[bin] = slotNrg;
-
- }
-
-
- /* calculation of transient ratio */
- for (bin=0; bin < NO_MID_RES_BINS; bin++) { /* noBins = 20 ( BASELINE_PS ) */
-
- h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = fMult( h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin], PEAK_DECAY_FACTOR );
-
- if (h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] < aaPowerSlot[bin]) {
- h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = aaPowerSlot[bin];
- }
-
- /* calculate PSmoothPeakDecayDiffNrg */
- peakDiff = fMultAdd ( (h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]>>1),
- INT_FILTER_COEFF, h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] - aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]);
-
- /* save peakDiff for the next frame */
- h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin] = peakDiff;
-
- nrg = h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] + fMult( INT_FILTER_COEFF, aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] );
-
- /* Negative energies don't exist. But sometimes they appear due to rounding. */
-
- nrg = fixMax(nrg,FL2FXCONST_DBL(0.f));
-
- /* save nrg for the next frame */
- h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] = nrg;
-
- nrg = fMult( nrg, TRANSIENT_IMPACT_FACTOR );
-
- /* save transient impact factor */
- if ( peakDiff <= nrg || peakDiff == FL2FXCONST_DBL(0.0) ) {
- aaTransRatioSlot[bin] = (FIXP_DBL)MAXVAL_DBL /* FL2FXCONST_DBL(1.0f)*/;
- }
- else if ( nrg <= FL2FXCONST_DBL(0.0f) ) {
- aaTransRatioSlot[bin] = FL2FXCONST_DBL(0.f);
+void PreparePsProcessing(HANDLE_PS_DEC h_ps_d,
+ const FIXP_DBL *const *const rIntBufferLeft,
+ const FIXP_DBL *const *const iIntBufferLeft,
+ const int scaleFactorLowBand) {
+ if (h_ps_d->procFrameBased ==
+ 1) /* If we have switched from frame to slot based processing */
+ { /* fill hybrid delay buffer. */
+ int i, j;
+
+ for (i = 0; i < HYBRID_FILTER_DELAY; i++) {
+ FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20];
+ FIXP_DBL hybridOutputData[2][NO_SUB_QMF_CHANNELS];
+
+ for (j = 0; j < NO_QMF_BANDS_HYBRID20; j++) {
+ qmfInputData[0][j] =
+ scaleValue(rIntBufferLeft[i][j], scaleFactorLowBand);
+ qmfInputData[1][j] =
+ scaleValue(iIntBufferLeft[i][j], scaleFactorLowBand);
}
- else {
- /* scale to denominator */
- INT scale_left = fixMax(0, CntLeadingZeros(peakDiff) - 1);
- aaTransRatioSlot[bin] = schur_div( nrg<<scale_left, peakDiff<<scale_left, 16);
- }
- } /* bin */
-
-
-
-
- #define DELAY_GROUP_OFFSET 20
- #define NR_OF_DELAY_GROUPS 2
-
- FIXP_DBL rTmp, iTmp, rTmp0, iTmp0, rR0, iR0;
-
- INT TempDelay = h_ps_d->specificTo.mpeg.delayBufIndex; /* set delay indices */
-
- pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[TempDelay];
- pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[TempDelay];
-
- aaLeftReal = mHybridRealLeft;
- aaLeftImag = mHybridImagLeft;
- aaRightReal = mHybridRealRight;
- aaRightImag = mHybridImagRight;
-
- /************************/
- /* ICC groups : 0 - 9 */
- /************************/
-
- /* gr = ICC groups */
- for (gr=0; gr < SUBQMF_GROUPS; gr++) {
-
- transRatio = aaTransRatioSlot[bins2groupMap20[gr]];
-
- /* sb = subQMF/QMF subband */
- sb = groupBorders20[gr];
-
- /* Update delay buffers, sample delay allpass = 2 */
- rTmp0 = pRealDelayBuffer[sb];
- iTmp0 = pImagDelayBuffer[sb];
-
- pRealDelayBuffer[sb] = aaLeftReal[sb];
- pImagDelayBuffer[sb] = aaLeftImag[sb];
-
- /* delay by fraction */
- cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReSubQmf20[sb], aaFractDelayPhaseFactorImSubQmf20[sb]);
- rR0<<=1;
- iR0<<=1;
-
- FIXP_DBL *pAaaRealDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[sb];
- FIXP_DBL *pAaaImagDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[sb];
-
- for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) {
-
- INT tmpDelayRSer = h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m];
-
- /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */
- rTmp0 = pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer];
- iTmp0 = pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer];
-
- /* delay by fraction */
- cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReSubQmf20[sb][m], aaFractDelayPhaseFactorSerImSubQmf20[sb][m]);
-
- rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], rR0)) << 1;
- iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], iR0)) << 1;
-
- pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], rTmp);
- pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], iTmp);
-
- rR0 = rTmp;
- iR0 = iTmp;
-
- pAaaRealDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m];
- pAaaImagDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m];
-
- } /* m */
-
- /* duck if a past transient is found */
- aaRightReal[sb] = fMult(transRatio, rR0);
- aaRightImag[sb] = fMult(transRatio, iR0);
-
- } /* gr */
-
-
- scaleValues( mHybridRealLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
- scaleValues( mHybridImagLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
- scaleValues( mHybridRealRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
- scaleValues( mHybridImagRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM );
-
-
- /************************/
-
- aaLeftReal = rIntBufferLeft;
- aaLeftImag = iIntBufferLeft;
- aaRightReal = rIntBufferRight;
- aaRightImag = iIntBufferRight;
- pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[TempDelay];
- pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[TempDelay];
-
- /************************/
- /* ICC groups : 10 - 19 */
- /************************/
-
-
- /* gr = ICC groups */
- for (gr=SUBQMF_GROUPS; gr < NO_IID_GROUPS - NR_OF_DELAY_GROUPS; gr++) {
-
- transRatio = aaTransRatioSlot[bins2groupMap20[gr]];
-
- /* sb = subQMF/QMF subband */
- for (sb = groupBorders20[gr]; sb < groupBorders20[gr+1]; sb++) {
- FIXP_DBL resR, resI;
-
- /* decayScaleFactor = 1.0f + decay_cutoff * DECAY_SLOPE - DECAY_SLOPE * sb; DECAY_SLOPE = 0.05 */
- FIXP_DBL decayScaleFactor = decayScaleFactTable[sb];
-
- /* Update delay buffers, sample delay allpass = 2 */
- rTmp0 = pRealDelayBuffer[sb];
- iTmp0 = pImagDelayBuffer[sb];
-
- pRealDelayBuffer[sb] = aaLeftReal[sb];
- pImagDelayBuffer[sb] = aaLeftImag[sb];
-
- /* delay by fraction */
- cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReQmf[sb], aaFractDelayPhaseFactorImQmf[sb]);
- rR0<<=1;
- iR0<<=1;
-
- resR = fMult(decayScaleFactor, rR0);
- resI = fMult(decayScaleFactor, iR0);
-
- FIXP_DBL *pAaaRealDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[sb];
- FIXP_DBL *pAaaImagDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[sb];
-
- for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) {
-
- INT tmpDelayRSer = h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m];
-
- /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */
- rTmp0 = pAaaRealDelayRBufferSerQmf[tmpDelayRSer];
- iTmp0 = pAaaImagDelayRBufferSerQmf[tmpDelayRSer];
-
- /* delay by fraction */
- cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReQmf[sb][m], aaFractDelayPhaseFactorSerImQmf[sb][m]);
-
- rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], resR))<<1;
- iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], resI))<<1;
-
- resR = fMult(decayScaleFactor, rTmp);
- resI = fMult(decayScaleFactor, iTmp);
-
- pAaaRealDelayRBufferSerQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], resR);
- pAaaImagDelayRBufferSerQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], resI);
-
- rR0 = rTmp;
- iR0 = iTmp;
-
- pAaaRealDelayRBufferSerQmf += aAllpassLinkDelaySer[m];
- pAaaImagDelayRBufferSerQmf += aAllpassLinkDelaySer[m];
-
- } /* m */
-
- /* duck if a past transient is found */
- aaRightReal[sb] = fMult(transRatio, rR0);
- aaRightImag[sb] = fMult(transRatio, iR0);
-
- } /* sb */
- } /* gr */
-
- /************************/
- /* ICC groups : 20, 21 */
- /************************/
-
-
- /* gr = ICC groups */
- for (gr=DELAY_GROUP_OFFSET; gr < NO_IID_GROUPS; gr++) {
-
- INT sbStart = groupBorders20[gr];
- INT sbStop = groupBorders20[gr+1];
-
- UCHAR *pDelayBufIdx = &h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf[sbStart-FIRST_DELAY_SB];
-
- transRatio = aaTransRatioSlot[bins2groupMap20[gr]];
-
- /* sb = subQMF/QMF subband */
- for (sb = sbStart; sb < sbStop; sb++) {
-
- /* Update delay buffers */
- rR0 = h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB];
- iR0 = h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB];
-
- h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftReal[sb];
- h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftImag[sb];
-
- /* duck if a past transient is found */
- aaRightReal[sb] = fMult(transRatio, rR0);
- aaRightImag[sb] = fMult(transRatio, iR0);
-
- if (++(*pDelayBufIdx) >= delayIndexQmf[sb]) {
- *pDelayBufIdx = 0;
- }
- pDelayBufIdx++;
-
- } /* sb */
- } /* gr */
-
-
- /* Update delay buffer index */
- if (++h_ps_d->specificTo.mpeg.delayBufIndex >= NO_SAMPLE_DELAY_ALLPASS)
- h_ps_d->specificTo.mpeg.delayBufIndex = 0;
-
- for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) {
- if (++h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m] >= aAllpassLinkDelaySer[m])
- h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m] = 0;
- }
-
-
- scaleValues( &rIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
- scaleValues( &iIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
- scaleValues( &rIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
- scaleValues( &iIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM );
+ FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis,
+ qmfInputData[0], qmfInputData[1],
+ hybridOutputData[0], hybridOutputData[1]);
+ }
+ h_ps_d->procFrameBased = 0; /* switch to slot based processing. */
- /* free memory on scratch */
- C_ALLOC_SCRATCH_END(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS);
- C_ALLOC_SCRATCH_END(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS);
+ } /* procFrameBased==1 */
}
+void initSlotBasedRotation(
+ HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
+ int env, int usb) {
+ INT group = 0;
+ INT bin = 0;
+ INT noIidSteps;
-void initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
- int env,
- int usb
- ) {
-
- INT group = 0;
- INT bin = 0;
- INT noIidSteps;
-
-/* const UCHAR *pQuantizedIIDs;*/
-
- FIXP_SGL invL;
- FIXP_DBL ScaleL, ScaleR;
- FIXP_DBL Alpha, Beta;
- FIXP_DBL h11r, h12r, h21r, h22r;
+ FIXP_SGL invL;
+ FIXP_DBL ScaleL, ScaleR;
+ FIXP_DBL Alpha, Beta;
+ FIXP_DBL h11r, h12r, h21r, h22r;
- const FIXP_DBL *PScaleFactors;
+ const FIXP_DBL *PScaleFactors;
- /* Overwrite old values in delay buffers when upper subband is higher than in last frame */
- if (env == 0) {
-
- if ((usb > h_ps_d->specificTo.mpeg.lastUsb) && h_ps_d->specificTo.mpeg.lastUsb) {
-
- INT i,k,length;
-
- for (i=h_ps_d->specificTo.mpeg.lastUsb ; i < FIRST_DELAY_SB; i++) {
- FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
- FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL));
- }
-
- for (k=0 ; k<NO_SAMPLE_DELAY_ALLPASS; k++) {
- FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[k], FIRST_DELAY_SB*sizeof(FIXP_DBL));
- }
- length = (usb-FIRST_DELAY_SB)*sizeof(FIXP_DBL);
- if(length>0) {
- FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0], length);
- FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0], length);
- }
- length = (fixMin(NO_DELAY_BUFFER_BANDS,(INT)usb)-FIRST_DELAY_SB)*sizeof(FIXP_DBL);
- if(length>0) {
- for (k=1 ; k < h_ps_d->specificTo.mpeg.noSampleDelay; k++) {
- FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[k], length);
- FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[k], length);
- }
- }
- }
- h_ps_d->specificTo.mpeg.lastUsb = usb;
- } /* env == 0 */
-
- if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ)
- {
+ if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) {
PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */
noIidSteps = NO_IID_STEPS_FINE;
- /*pQuantizedIIDs = quantizedIIDsFine;*/
- }
-
- else
- {
+ } else {
PScaleFactors = ScaleFactors; /* values are shiftet right by one */
noIidSteps = NO_IID_STEPS;
- /*pQuantizedIIDs = quantizedIIDs;*/
}
-
/* dequantize and decode */
- for ( group = 0; group < NO_IID_GROUPS; group++ ) {
-
+ for (group = 0; group < NO_IID_GROUPS; group++) {
bin = bins2groupMap20[group];
/*!
<h3> type 'A' rotation </h3>
mixing procedure R_a, used in baseline version<br>
- Scale-factor vectors c1 and c2 are precalculated in initPsTables () and stored in
- scaleFactors[] and scaleFactorsFine[] = pScaleFactors [].
- From the linearized IID parameters (intensity differences), two scale factors are
+ Scale-factor vectors c1 and c2 are precalculated in initPsTables () and
+ stored in scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. From the
+ linearized IID parameters (intensity differences), two scale factors are
calculated. They are used to obtain the coefficients h11... h22.
*/
/* ScaleR and ScaleL are scaled by 1 shift right */
- ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]];
- ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]];
+ ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.pCoef
+ ->aaIidIndexMapped[env][bin]];
+ ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.pCoef
+ ->aaIidIndexMapped[env][bin]];
- Beta = fMult (fMult( Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]], ( ScaleR - ScaleL )), FIXP_SQRT05);
- Alpha = Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]]>>1;
+ Beta = fMult(
+ fMult(Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]],
+ (ScaleR - ScaleL)),
+ FIXP_SQRT05);
+ Alpha =
+ Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]] >> 1;
/* Alpha and Beta are now both scaled by 2 shifts right */
- /* calculate the coefficients h11... h22 from scale-factors and ICC parameters */
+ /* calculate the coefficients h11... h22 from scale-factors and ICC
+ * parameters */
/* h values are scaled by 1 shift right */
{
FIXP_DBL trigData[4];
inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData);
- h11r = fMult( ScaleL, trigData[0]);
- h12r = fMult( ScaleR, trigData[2]);
- h21r = fMult( ScaleL, trigData[1]);
- h22r = fMult( ScaleR, trigData[3]);
+ h11r = fMult(ScaleL, trigData[0]);
+ h12r = fMult(ScaleR, trigData[2]);
+ h21r = fMult(ScaleL, trigData[1]);
+ h22r = fMult(ScaleR, trigData[3]);
}
/*****************************************************************************************/
- /* Interpolation of the matrices H11... H22: */
+ /* Interpolation of the matrices H11... H22: */
/* */
- /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / (n[e+1] - n[e]) */
- /* ... */
+ /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) /
+ * (n[e+1] - n[e]) */
+ /* ... */
/*****************************************************************************************/
/* invL = 1/(length of envelope) */
- invL = FX_DBL2FX_SGL(GetInvInt(h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]));
-
- h_ps_d->specificTo.mpeg.coef.H11r[group] = h_ps_d->specificTo.mpeg.h11rPrev[group];
- h_ps_d->specificTo.mpeg.coef.H12r[group] = h_ps_d->specificTo.mpeg.h12rPrev[group];
- h_ps_d->specificTo.mpeg.coef.H21r[group] = h_ps_d->specificTo.mpeg.h21rPrev[group];
- h_ps_d->specificTo.mpeg.coef.H22r[group] = h_ps_d->specificTo.mpeg.h22rPrev[group];
-
- h_ps_d->specificTo.mpeg.coef.DeltaH11r[group] = fMult ( h11r - h_ps_d->specificTo.mpeg.coef.H11r[group], invL );
- h_ps_d->specificTo.mpeg.coef.DeltaH12r[group] = fMult ( h12r - h_ps_d->specificTo.mpeg.coef.H12r[group], invL );
- h_ps_d->specificTo.mpeg.coef.DeltaH21r[group] = fMult ( h21r - h_ps_d->specificTo.mpeg.coef.H21r[group], invL );
- h_ps_d->specificTo.mpeg.coef.DeltaH22r[group] = fMult ( h22r - h_ps_d->specificTo.mpeg.coef.H22r[group], invL );
+ invL = FX_DBL2FX_SGL(GetInvInt(
+ h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] -
+ h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]));
+
+ h_ps_d->specificTo.mpeg.pCoef->H11r[group] =
+ h_ps_d->specificTo.mpeg.h11rPrev[group];
+ h_ps_d->specificTo.mpeg.pCoef->H12r[group] =
+ h_ps_d->specificTo.mpeg.h12rPrev[group];
+ h_ps_d->specificTo.mpeg.pCoef->H21r[group] =
+ h_ps_d->specificTo.mpeg.h21rPrev[group];
+ h_ps_d->specificTo.mpeg.pCoef->H22r[group] =
+ h_ps_d->specificTo.mpeg.h22rPrev[group];
+
+ h_ps_d->specificTo.mpeg.pCoef->DeltaH11r[group] =
+ fMult(h11r - h_ps_d->specificTo.mpeg.pCoef->H11r[group], invL);
+ h_ps_d->specificTo.mpeg.pCoef->DeltaH12r[group] =
+ fMult(h12r - h_ps_d->specificTo.mpeg.pCoef->H12r[group], invL);
+ h_ps_d->specificTo.mpeg.pCoef->DeltaH21r[group] =
+ fMult(h21r - h_ps_d->specificTo.mpeg.pCoef->H21r[group], invL);
+ h_ps_d->specificTo.mpeg.pCoef->DeltaH22r[group] =
+ fMult(h22r - h_ps_d->specificTo.mpeg.pCoef->H22r[group], invL);
/* update prev coefficients for interpolation in next envelope */
@@ -1062,79 +426,67 @@ void initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module sta
} /* group loop */
}
+static const UCHAR groupTable[NO_IID_GROUPS + 1] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71};
-static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
-
- FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */
- FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */
-
- FIXP_DBL *QmfLeftReal, /*!< real bands left qmf channel */
- FIXP_DBL *QmfLeftImag, /*!< imag bands left qmf channel */
-
- FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */
- FIXP_DBL *mHybridImagRight, /*!< hybrid values imag right */
-
- FIXP_DBL *QmfRightReal, /*!< real bands right qmf channel */
- FIXP_DBL *QmfRightImag /*!< imag bands right qmf channel */
- )
-{
- INT group;
- INT subband;
-
- FIXP_DBL *RESTRICT HybrLeftReal;
- FIXP_DBL *RESTRICT HybrLeftImag;
- FIXP_DBL *RESTRICT HybrRightReal;
- FIXP_DBL *RESTRICT HybrRightImag;
+static void applySlotBasedRotation(
+ HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */
- FIXP_DBL tmpLeft, tmpRight;
+ FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */
+ FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */
+ FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */
+ FIXP_DBL *mHybridImagRight /*!< hybrid values imag right */
+) {
+ INT group;
+ INT subband;
/**********************************************************************************************/
/*!
<h2> Mapping </h2>
- The number of stereo bands that is actually used depends on the number of availble
- parameters for IID and ICC:
- <pre>
- nr. of IID para.| nr. of ICC para. | nr. of Stereo bands
+ The number of stereo bands that is actually used depends on the number of
+ availble parameters for IID and ICC: <pre> nr. of IID para.| nr. of ICC para.
+ | nr. of Stereo bands
----------------|------------------|-------------------
10,20 | 10,20 | 20
10,20 | 34 | 34
34 | 10,20 | 34
34 | 34 | 34
</pre>
- In the case the number of parameters for IIS and ICC differs from the number of stereo
- bands, a mapping from the lower number to the higher number of parameters is applied.
- Index mapping of IID and ICC parameters is already done in psbitdec.cpp. Further mapping is
- not needed here in baseline version.
+ In the case the number of parameters for IIS and ICC differs from the number
+ of stereo bands, a mapping from the lower number to the higher number of
+ parameters is applied. Index mapping of IID and ICC parameters is already done
+ in psbitdec.cpp. Further mapping is not needed here in baseline version.
**********************************************************************************************/
/************************************************************************************************/
/*!
<h2> Mixing </h2>
- To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, n_[e+1] the
- parameters at position n[e] and n[e+1] are required as well as the subband domain signals
- s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] represents the start position for
- envelope e. The border positions n[e] are handled in DecodePS().
+ To generate the QMF subband signals for the subband samples n = n[e]+1 ,,,
+ n_[e+1] the parameters at position n[e] and n[e+1] are required as well as the
+ subband domain signals s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e]
+ represents the start position for envelope e. The border positions n[e] are
+ handled in DecodePS().
The stereo sub subband signals are constructed as:
<pre>
l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n)
r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n)
</pre>
- In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... h22(b) need to
- be calculated first (b: parameter index). Depending on ICC mode either mixing procedure R_a
- or R_b is used for that. For both procedures, the parameters for parameter position n[e+1]
- is used.
+ In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)...
+ h22(b) need to be calculated first (b: parameter index). Depending on ICC mode
+ either mixing procedure R_a or R_b is used for that. For both procedures, the
+ parameters for parameter position n[e+1] is used.
************************************************************************************************/
-
/************************************************************************************************/
/*!
<h2>Phase parameters </h2>
- With disabled phase parameters (which is the case in baseline version), the H-matrices are
- just calculated by:
+ With disabled phase parameters (which is the case in baseline version), the
+ H-matrices are just calculated by:
<pre>
H11(k,n[e+1] = h11(b(k))
@@ -1146,69 +498,44 @@ static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to
this loop includes the interpolation of the coefficients Hxx
************************************************************************************************/
-
- /* loop thru all groups ... */
- HybrLeftReal = mHybridRealLeft;
- HybrLeftImag = mHybridImagLeft;
- HybrRightReal = mHybridRealRight;
- HybrRightImag = mHybridImagRight;
-
/******************************************************/
/* construct stereo sub subband signals according to: */
/* */
/* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) */
/* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n) */
/******************************************************/
- for ( group = 0; group < SUBQMF_GROUPS; group++ ) {
-
- h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group];
- h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group];
- h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group];
- h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group];
-
- subband = groupBorders20[group];
-
- tmpLeft = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]);
- tmpRight = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]);
- HybrLeftReal [subband] = tmpLeft<<1;
- HybrRightReal[subband] = tmpRight<<1;
-
- tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]);
- tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]);
- HybrLeftImag [subband] = tmpLeft;
- HybrRightImag[subband] = tmpRight;
- }
-
- /* continue in the qmf buffers */
- HybrLeftReal = QmfLeftReal;
- HybrLeftImag = QmfLeftImag;
- HybrRightReal = QmfRightReal;
- HybrRightImag = QmfRightImag;
-
- for (; group < NO_IID_GROUPS; group++ ) {
-
- h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group];
- h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group];
- h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group];
- h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group];
-
- for ( subband = groupBorders20[group]; subband < groupBorders20[group + 1]; subband++ )
- {
- tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]);
- tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]);
- HybrLeftReal [subband] = tmpLeft;
- HybrRightReal[subband] = tmpRight;
-
- tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]);
- tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]);
- HybrLeftImag [subband] = tmpLeft;
- HybrRightImag[subband] = tmpRight;
-
+ PS_DEC_COEFFICIENTS *pCoef = h_ps_d->specificTo.mpeg.pCoef;
+
+ for (group = 0; group < NO_IID_GROUPS; group++) {
+ pCoef->H11r[group] += pCoef->DeltaH11r[group];
+ pCoef->H12r[group] += pCoef->DeltaH12r[group];
+ pCoef->H21r[group] += pCoef->DeltaH21r[group];
+ pCoef->H22r[group] += pCoef->DeltaH22r[group];
+
+ const int start = groupTable[group];
+ const int stop = groupTable[group + 1];
+ for (subband = start; subband < stop; subband++) {
+ FIXP_DBL tmpLeft =
+ fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridRealLeft[subband]),
+ pCoef->H21r[group], mHybridRealRight[subband]);
+ FIXP_DBL tmpRight =
+ fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridRealLeft[subband]),
+ pCoef->H22r[group], mHybridRealRight[subband]);
+ mHybridRealLeft[subband] = tmpLeft;
+ mHybridRealRight[subband] = tmpRight;
+
+ tmpLeft =
+ fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridImagLeft[subband]),
+ pCoef->H21r[group], mHybridImagRight[subband]);
+ tmpRight =
+ fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridImagLeft[subband]),
+ pCoef->H22r[group], mHybridImagRight[subband]);
+ mHybridImagLeft[subband] = tmpLeft;
+ mHybridImagRight[subband] = tmpRight;
} /* subband */
}
}
-
/***************************************************************************/
/*!
\brief Applies IID, ICC, IPD and OPD parameters to the current frame.
@@ -1216,199 +543,172 @@ static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to
\return none
****************************************************************************/
-void
-ApplyPsSlot( HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/
- FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */
- FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */
- FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */
- FIXP_DBL *iIntBufferRight /*!< imag bands right qmf channel (38x64) */
- )
-{
-
- /*!
- The 64-band QMF representation of the monaural signal generated by the SBR tool
- is used as input of the PS tool. After the PS processing, the outputs of the left
- and right hybrid synthesis filterbanks are used to generate the stereo output
- signal.
-
- <pre>
-
- ------------- ---------- -------------
- | Hybrid | M_n[k,m] | | L_n[k,m] | Hybrid | l[n]
- m[n] --->| analysis |--------->| |--------->| synthesis |----->
- | filter bank | | | | filter bank |
- ------------- | Stereo | -------------
- | | recon- |
- | | stuction |
- \|/ | |
- ------------- | |
- | De- | D_n[k,m] | |
- | correlation |--------->| |
- ------------- | | -------------
- | | R_n[k,m] | Hybrid | r[n]
- | |--------->| synthesis |----->
- IID, ICC ------------------------>| | | filter bank |
- (IPD, OPD) ---------- -------------
-
- m[n]: QMF represantation of the mono input
- M_n[k,m]: (sub-)sub-band domain signals of the mono input
- D_n[k,m]: decorrelated (sub-)sub-band domain signals
- L_n[k,m]: (sub-)sub-band domain signals of the left output
- R_n[k,m]: (sub-)sub-band domain signals of the right output
- l[n],r[n]: left/right output signals
-
- </pre>
- */
+void ApplyPsSlot(
+ HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/
+ FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */
+ FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */
+ FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */
+ FIXP_DBL *iIntBufferRight, /*!< imag bands right qmf channel (38x64) */
+ const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand,
+ const int scaleFactorHighBand, const int lsb, const int usb) {
+/*!
+The 64-band QMF representation of the monaural signal generated by the SBR tool
+is used as input of the PS tool. After the PS processing, the outputs of the
+left and right hybrid synthesis filterbanks are used to generate the stereo
+output signal.
- /* get temporary hybrid qmf values of one timeslot */
- C_ALLOC_SCRATCH_START(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
- C_ALLOC_SCRATCH_START(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
- C_ALLOC_SCRATCH_START(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
- C_ALLOC_SCRATCH_START(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
+<pre>
- SCHAR sf_IntBuffer = h_ps_d->sf_IntBuffer;
+ ------------- ---------- -------------
+ | Hybrid | M_n[k,m] | | L_n[k,m] | Hybrid | l[n]
+ m[n] --->| analysis |--------->| |--------->| synthesis |----->
+ ------------- | Stereo | -------------
+ | | recon- |
+ | | stuction |
+ \|/ | |
+ ------------- | |
+ | De- | D_n[k,m] | |
+ | correlation |--------->| |
+ ------------- | | -------------
+ | | R_n[k,m] | Hybrid | r[n]
+ | |--------->| synthesis |----->
+ IID, ICC ------------------------>| | | filter bank |
+(IPD, OPD) ---------- -------------
+
+m[n]: QMF represantation of the mono input
+M_n[k,m]: (sub-)sub-band domain signals of the mono input
+D_n[k,m]: decorrelated (sub-)sub-band domain signals
+L_n[k,m]: (sub-)sub-band domain signals of the left output
+R_n[k,m]: (sub-)sub-band domain signals of the right output
+l[n],r[n]: left/right output signals
- /* clear workbuffer */
- FDKmemclear(hybridRealLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
- FDKmemclear(hybridImagLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
- FDKmemclear(hybridRealRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
- FDKmemclear(hybridImagRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL));
+</pre>
+*/
+#define NO_HYBRID_DATA_BANDS (71)
+ int i;
+ FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20];
+ FIXP_DBL *hybridData[2][2];
+ C_ALLOC_SCRATCH_START(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS);
+
+ hybridData[0][0] =
+ pHybridData + 0 * NO_HYBRID_DATA_BANDS; /* left real hybrid data */
+ hybridData[0][1] =
+ pHybridData + 1 * NO_HYBRID_DATA_BANDS; /* left imag hybrid data */
+ hybridData[1][0] =
+ pHybridData + 2 * NO_HYBRID_DATA_BANDS; /* right real hybrid data */
+ hybridData[1][1] =
+ pHybridData + 3 * NO_HYBRID_DATA_BANDS; /* right imag hybrid data */
/*!
Hybrid analysis filterbank:
- The lower 3 (5) of the 64 QMF subbands are further split to provide better frequency resolution.
- for PS processing.
- For the 10 and 20 stereo bands configuration, the QMF band H_0(w) is split
- up into 8 (sub-) sub-bands and the QMF bands H_1(w) and H_2(w) are spit into 2 (sub-)
- 4th. (See figures 8.20 and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) )
+ The lower 3 (5) of the 64 QMF subbands are further split to provide better
+ frequency resolution. for PS processing. For the 10 and 20 stereo bands
+ configuration, the QMF band H_0(w) is split up into 8 (sub-) sub-bands and the
+ QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) 4th. (See figures 8.20
+ and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) )
*/
-
- if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing */
- { /* fill hybrid delay buffer. */
- h_ps_d->procFrameBased = 0;
-
- fillHybridDelayLine( rIntBufferLeft,
- iIntBufferLeft,
- hybridRealLeft,
- hybridImagLeft,
- hybridRealRight,
- hybridImagRight,
- &h_ps_d->specificTo.mpeg.hybrid );
- }
-
- slotBasedHybridAnalysis ( rIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */
- iIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */
- hybridRealLeft, /* hybrid filterbank values */
- hybridImagLeft, /* hybrid filterbank values */
- &h_ps_d->specificTo.mpeg.hybrid); /* hybrid filterbank handle */
-
-
- SCHAR hybridScal = h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer;
-
+ /*
+ * Hybrid analysis.
+ */
+
+ /* Get qmf input data and apply descaling */
+ for (i = 0; i < NO_QMF_BANDS_HYBRID20; i++) {
+ qmfInputData[0][i] = scaleValue(rIntBufferLeft[HYBRID_FILTER_DELAY][i],
+ scaleFactorLowBand_no_ov);
+ qmfInputData[1][i] = scaleValue(iIntBufferLeft[HYBRID_FILTER_DELAY][i],
+ scaleFactorLowBand_no_ov);
+ }
+
+ /* LF - part */
+ FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis,
+ qmfInputData[0], qmfInputData[1], hybridData[0][0],
+ hybridData[0][1]);
+
+ /* HF - part */
+ /* bands up to lsb */
+ scaleValues(&hybridData[0][0][NO_SUB_QMF_CHANNELS - 2],
+ &rIntBufferLeft[0][NO_QMF_BANDS_HYBRID20],
+ lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand);
+ scaleValues(&hybridData[0][1][NO_SUB_QMF_CHANNELS - 2],
+ &iIntBufferLeft[0][NO_QMF_BANDS_HYBRID20],
+ lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand);
+
+ /* bands from lsb to usb */
+ scaleValues(&hybridData[0][0][lsb + (NO_SUB_QMF_CHANNELS - 2 -
+ NO_QMF_BANDS_HYBRID20)],
+ &rIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand);
+ scaleValues(&hybridData[0][1][lsb + (NO_SUB_QMF_CHANNELS - 2 -
+ NO_QMF_BANDS_HYBRID20)],
+ &iIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand);
+
+ /* bands from usb to NO_SUB_QMF_CHANNELS which should be zero for non-overlap
+ slots but can be non-zero for overlap slots */
+ FDKmemcpy(
+ &hybridData[0][0]
+ [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)],
+ &rIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb));
+ FDKmemcpy(
+ &hybridData[0][1]
+ [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)],
+ &iIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb));
/*!
Decorrelation:
- By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) are
- converted into de-correlated (sub-)sub-band samples d_k(n).
+ By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n)
+ are converted into de-correlated (sub-)sub-band samples d_k(n).
- k: frequency in hybrid spectrum
- n: time index
*/
- deCorrelateSlotBased( h_ps_d, /* parametric stereo decoder handle */
- hybridRealLeft, /* left hybrid time slot */
- hybridImagLeft,
- hybridScal, /* scale factor of left hybrid time slot */
- rIntBufferLeft[0], /* left qmf time slot */
- iIntBufferLeft[0],
- sf_IntBuffer, /* scale factor of left and right qmf time slot */
- hybridRealRight, /* right hybrid time slot */
- hybridImagRight,
- rIntBufferRight, /* right qmf time slot */
- iIntBufferRight );
-
-
+ FDKdecorrelateApply(&h_ps_d->specificTo.mpeg.apDecor,
+ &hybridData[0][0][0], /* left real hybrid data */
+ &hybridData[0][1][0], /* left imag hybrid data */
+ &hybridData[1][0][0], /* right real hybrid data */
+ &hybridData[1][1][0], /* right imag hybrid data */
+ 0 /* startHybBand */
+ );
/*!
Stereo Processing:
- The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according to
- the stereo cues which are defined per stereo band.
+ The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according
+ to the stereo cues which are defined per stereo band.
*/
-
- applySlotBasedRotation( h_ps_d, /* parametric stereo decoder handle */
- hybridRealLeft, /* left hybrid time slot */
- hybridImagLeft,
- rIntBufferLeft[0], /* left qmf time slot */
- iIntBufferLeft[0],
- hybridRealRight, /* right hybrid time slot */
- hybridImagRight,
- rIntBufferRight, /* right qmf time slot */
- iIntBufferRight );
-
-
-
+ applySlotBasedRotation(h_ps_d,
+ &hybridData[0][0][0], /* left real hybrid data */
+ &hybridData[0][1][0], /* left imag hybrid data */
+ &hybridData[1][0][0], /* right real hybrid data */
+ &hybridData[1][1][0] /* right imag hybrid data */
+ );
/*!
Hybrid synthesis filterbank:
- The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the hybrid synthesis
- filterbanks which are identical to the 64 complex synthesis filterbank of the SBR tool. The
- input to the filterbank are slots of 64 QMF samples. For each slot the filterbank outputs one
- block of 64 samples of one reconstructed stereo channel. The hybrid synthesis filterbank is
- computed seperatly for the left and right channel.
+ The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the
+ hybrid synthesis filterbanks which are identical to the 64 complex synthesis
+ filterbank of the SBR tool. The input to the filterbank are slots of 64 QMF
+ samples. For each slot the filterbank outputs one block of 64 samples of one
+ reconstructed stereo channel. The hybrid synthesis filterbank is computed
+ seperatly for the left and right channel.
*/
-
- /* left channel */
- slotBasedHybridSynthesis ( hybridRealLeft, /* one timeslot of hybrid filterbank values */
- hybridImagLeft,
- rIntBufferLeft[0], /* one timeslot of qmf filterbank values */
- iIntBufferLeft[0],
- &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */
-
- /* right channel */
- slotBasedHybridSynthesis ( hybridRealRight, /* one timeslot of hybrid filterbank values */
- hybridImagRight,
- rIntBufferRight, /* one timeslot of qmf filterbank values */
- iIntBufferRight,
- &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */
-
-
-
-
-
-
+ /*
+ * Hybrid synthesis.
+ */
+ for (i = 0; i < 2; i++) {
+ FDKhybridSynthesisApply(
+ &h_ps_d->specificTo.mpeg.hybridSynthesis[i],
+ hybridData[i][0], /* real hybrid data */
+ hybridData[i][1], /* imag hybrid data */
+ (i == 0) ? rIntBufferLeft[0]
+ : rIntBufferRight, /* output real qmf buffer */
+ (i == 0) ? iIntBufferLeft[0]
+ : iIntBufferRight /* output imag qmf buffer */
+ );
+ }
/* free temporary hybrid qmf values of one timeslot */
- C_ALLOC_SCRATCH_END(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
- C_ALLOC_SCRATCH_END(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS);
- C_ALLOC_SCRATCH_END(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
- C_ALLOC_SCRATCH_END(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS);
-
-}/* END ApplyPsSlot */
-
-
-/***************************************************************************/
-/*!
-
- \brief assigns timeslots to an array
-
- \return
-
-****************************************************************************/
-
-static void assignTimeSlotsPS (FIXP_DBL *bufAdr,
- FIXP_DBL **bufPtr,
- const int numSlots,
- const int numChan)
-{
- FIXP_DBL *ptr;
- int slot;
- ptr = bufAdr;
- for(slot=0; slot < numSlots; slot++) {
- bufPtr [slot] = ptr;
- ptr += numChan;
- }
-}
+ C_ALLOC_SCRATCH_END(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS);
+} /* END ApplyPsSlot */