/* ------------------------------------------------------------------ * Copyright (C) 1998-2009 PacketVideo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. * See the License for the specific language governing permissions * and limitations under the License. * ------------------------------------------------------------------- */ /* Filename: ps_pwr_transient_detection.c ------------------------------------------------------------------------------ REVISION HISTORY Who: Date: MM/DD/YYYY Description: ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS ------------------------------------------------------------------------------ FUNCTION DESCRIPTION Decorrelation Decorrelation is achieved by means of all-pass filtering and delaying Sub-band samples s_k(n) are converted into de-correlated sub-bands samples d_k(n). k index for frequency, n time index _______ ________ | | _______ | | ->|Hybrid | LF ---- | |->| Hybrid |--> | Anal. | | | | | Synth | QMF -> L ------- o----------------------->| | -------- Synth QMF | s_k(n) |Stereo |--------------> Anal. -------------------------->| | _______ | | | | ________ | | HF --o | ----------- |Process| | | ->| Delay | | ->| |-------->| |->| Hybrid |--> ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R ---->| |-------->| | -------- Synth ----------- |_______|--------------> To handle transients and other fast time-envelopes, the output of the all pass filters has to be attenuated at those signals. ------------------------------------------------------------------------------ REQUIREMENTS ------------------------------------------------------------------------------ REFERENCES SC 29 Software Copyright Licencing Disclaimer: This software module was originally developed by Coding Technologies and edited by - in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards for reference purposes and its performance may not have been optimized. This software module is an implementation of one or more tools as specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards. ISO/IEC gives users free license to this software module or modifications thereof for use in products claiming conformance to audiovisual and image-coding related ITU Recommendations and/or ISO/IEC International Standards. ISO/IEC gives users the same free license to this software module or modifications thereof for research purposes and further ISO/IEC standardisation. Those intending to use this software module in products are advised that its use may infringe existing patents. ISO/IEC have no liability for use of this software module or modifications thereof. Copyright is not released for products that do not conform to audiovisual and image-coding related ITU Recommendations and/or ISO/IEC International Standards. The original developer retains full right to modify and use the code for its own purpose, assign or donate the code to a third party and to inhibit third parties from using the code for products that do not conform to audiovisual and image-coding related ITU Recommendations and/or ISO/IEC International Standards. This copyright notice must be included in all copies or derivative works. Copyright (c) ISO/IEC 2003. ------------------------------------------------------------------------------ PSEUDO-CODE ------------------------------------------------------------------------------ */ /*---------------------------------------------------------------------------- ; INCLUDES ----------------------------------------------------------------------------*/ #ifdef AAC_PLUS #ifdef PARAMETRICSTEREO #include "pv_audio_type_defs.h" #include "s_ps_dec.h" #include "aac_mem_funcs.h" #include "ps_all_pass_filter_coeff.h" #include "ps_pwr_transient_detection.h" #include "fxp_mul32.h" #include "pv_div.h" /*---------------------------------------------------------------------------- ; MACROS ; Define module specific macros here ----------------------------------------------------------------------------*/ #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) #endif /*---------------------------------------------------------------------------- ; DEFINES ; Include all pre-processor statements here. Include conditional ; compile variables also. ----------------------------------------------------------------------------*/ #define R_SHIFT 29 #define Q29_fmt(x) (Int32)(x*((Int32)1<=0?0.5F:-0.5F)) #define Qfmt31(a) (Int32)(-a*((Int32)1<<31) - 1 + (a>=0?0.5F:-0.5F)) /*---------------------------------------------------------------------------- ; LOCAL FUNCTION DEFINITIONS ; Function Prototype declaration ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; LOCAL STORE/BUFFER/POINTER DEFINITIONS ; Variable declaration - defined here and used outside this module ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; EXTERNAL FUNCTION REFERENCES ; Declare functions defined elsewhere and referenced in this module ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES ; Declare variables used in this module but defined elsewhere ----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void ps_pwr_transient_detection(STRUCT_PS_DEC *h_ps_dec, Int32 *rIntBufferLeft, Int32 *iIntBufferLeft, Int32 aTransRatio[]) { Int32 sb; Int32 maxsb; Int32 gr; Int32 bin; Int32 *aLeftReal; Int32 *aLeftImag; Int32 temp_r; Int32 temp_i; Int32 accu; Int32 *aPower = aTransRatio; Quotient result; Int32 nrg; Int32 *ptr_aPrevNrg; Int32 peakDiff; Int32 *ptr_PrevPeakDiff; aLeftReal = rIntBufferLeft; aLeftImag = iIntBufferLeft; /* * Input Power Matrix * 2 * Power(i,n) = SUM | s_k(n)| * i */ for (gr = SUBQMF_GROUPS; gr < NO_IID_GROUPS; gr++) /* 10 to 22 */ { maxsb = min(h_ps_dec->usb, groupBorders[ gr+1]); accu = 0; for (sb = groupBorders[gr]; sb < maxsb; sb++) { temp_r = aLeftReal[sb]; temp_i = aLeftImag[sb]; accu = fxp_mac32_Q31(accu, temp_r, temp_r); accu = fxp_mac32_Q31(accu, temp_i, temp_i); } /* sb */ aPower[gr - 2] = accu >> 1; } /* gr */ aLeftReal = h_ps_dec->mHybridRealLeft; aLeftImag = h_ps_dec->mHybridImagLeft; temp_r = aLeftReal[0]; temp_i = aLeftImag[0]; accu = fxp_mul32_Q31(temp_r, temp_r); accu = fxp_mac32_Q31(accu, temp_i, temp_i); temp_r = aLeftReal[5]; temp_i = aLeftImag[5]; accu = fxp_mac32_Q31(accu, temp_r, temp_r); aPower[0] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; temp_r = aLeftReal[1]; temp_i = aLeftImag[1]; accu = fxp_mul32_Q31(temp_r, temp_r); accu = fxp_mac32_Q31(accu, temp_i, temp_i); temp_r = aLeftReal[4]; temp_i = aLeftImag[4]; accu = fxp_mac32_Q31(accu, temp_r, temp_r); aPower[1] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; temp_r = aLeftReal[2]; temp_i = aLeftImag[2]; accu = fxp_mul32_Q31(temp_r, temp_r); aPower[2] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; temp_r = aLeftReal[3]; temp_i = aLeftImag[3]; accu = fxp_mul32_Q31(temp_r, temp_r); aPower[3] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; temp_r = aLeftReal[6]; temp_i = aLeftImag[6]; accu = fxp_mul32_Q31(temp_r, temp_r); aPower[5] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; temp_r = aLeftReal[7]; temp_i = aLeftImag[7]; accu = fxp_mul32_Q31(temp_r, temp_r); aPower[4] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; temp_r = aLeftReal[8]; temp_i = aLeftImag[8]; accu = fxp_mul32_Q31(temp_r, temp_r); aPower[6] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; temp_r = aLeftReal[9]; temp_i = aLeftImag[9]; accu = fxp_mul32_Q31(temp_r, temp_r); aPower[7] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1; /* * Power transient detection */ ptr_aPrevNrg = h_ps_dec->aPrevNrg; ptr_PrevPeakDiff = h_ps_dec->aPrevPeakDiff; for (bin = 0; bin < NO_BINS; bin++) /* NO_BINS = 20 */ { peakDiff = *ptr_PrevPeakDiff; /* PEAK_DECAY_FACTOR 0.765928338364649f @ 48 KHz for Fs > 32 Khz */ accu = h_ps_dec->aPeakDecayFast[bin]; peakDiff -= peakDiff >> 2; accu = fxp_mul32_Q31(accu, Qfmt31(0.765928338364649f)) << 1; if (accu < *aPower) { accu = *aPower; } else { peakDiff += ((accu - *aPower) >> 2); } h_ps_dec->aPeakDecayFast[bin] = accu; *(ptr_PrevPeakDiff++) = peakDiff; nrg = *ptr_aPrevNrg + ((*aPower - *ptr_aPrevNrg) >> 2); *(ptr_aPrevNrg++) = nrg; peakDiff += peakDiff >> 1; /* transient impact factor == 1.5 */ if (peakDiff <= nrg) { *(aPower++) = 0x7FFFFFFF; /* in Q31 */ } else { pv_div(nrg, peakDiff, &result); *(aPower++) = (result.quotient >> (result.shift_factor)) << 1; /* in Q31 */ } } /* bin */ } #endif #endif