/*! \brief Initialize DRC information \self Handle of DRC info \return none */ void aacDecoder_drcInit ( HANDLE_AAC_DRC self ) { CDrcParams *pParams; if (self == NULL) { return; } /* init control fields */ self->enable = 0; self->numThreads = 0; self->digitalNorm = 0; /* init params */ pParams = &self->params; pParams->bsDelayEnable = 0; pParams->cut = FL2FXCONST_DBL(0.0f); pParams->boost = FL2FXCONST_DBL(0.0f); pParams->targetRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL; pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES; /* initial program ref level = target ref level */ self->progRefLevel = pParams->targetRefLevel; }
DRC_ERROR initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize, const int sampleRate) { int i, j, k; if (frameSize < 1) { return DE_NOT_OK; } hGainDec->frameSize = frameSize; if (hGainDec->frameSize * 1000 < sampleRate) { return DE_NOT_OK; } hGainDec->deltaTminDefault = getDeltaTmin(sampleRate); if (hGainDec->deltaTminDefault > hGainDec->frameSize) { return DE_NOT_OK; } for (i = 0; i < MAX_ACTIVE_DRCS; i++) { for (j = 0; j < 8; j++) { /* use startup node at the beginning */ hGainDec->activeDrc[i].lnbIndexForChannel[j][0] = 0; for (k = 1; k < NUM_LNB_FRAMES; k++) { hGainDec->activeDrc[i].lnbIndexForChannel[j][k] = -1; } } } for (j = 0; j < 8; j++) { hGainDec->channelGain[j] = FL2FXCONST_DBL(1.0f / (float)(1 << 8)); } for (i = 0; i < 4 * 1024 / 256; i++) { hGainDec->dummySubbandGains[i] = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); } hGainDec->status = 0; /* startup */ return DE_OK; }
SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) { SACDEC_ERROR err = MPS_OK; int ch; for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) { self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE)); self->oldWetEnerLD64[ch] = FL2FXCONST_DBL(0.34375f); /* 32768.0*32768.0/2^(44-26-10) */ } for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) { self->oldDryEnerLD64[ch] = FL2FXCONST_DBL(0.1875f); /* 32768.0*32768.0/2^(44-26) */ } self->BP = BP__FDK; self->BP_GF = BP_GF__FDK; self->update_old_ener = 0; return err; }
SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self, INT ch, UINT numBands, FIXP_DBL *pNextFact_mag, INT nextFact_exp, SHORT drcInterpolationScheme, UCHAR winSequence, USHORT *pBandTop ) { SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; int band, isValidData = 0; if (self == NULL) { return SBRDEC_NOT_INITIALIZED; } if (ch > (8) || pNextFact_mag == NULL) { return SBRDEC_SET_PARAM_FAIL; } /* Search for gain values different to 1.0f */ for (band = 0; band < numBands; band += 1) { if ( !((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) && (nextFact_exp == 1)) && !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) && (nextFact_exp == 0)) ) { isValidData = 1; break; } } /* Find the right SBR channel */ pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch ); if ( pSbrDrcChannelData != NULL ) { if ( pSbrDrcChannelData->enable || isValidData ) { /* Activate processing only with real and valid data */ int i; pSbrDrcChannelData->enable = 1; pSbrDrcChannelData->numBandsNext = numBands; pSbrDrcChannelData->winSequenceNext = winSequence; pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme; pSbrDrcChannelData->nextFact_exp = nextFact_exp; for (i = 0; i < (int)numBands; i++) { pSbrDrcChannelData->bandTopNext[i] = pBandTop[i]; pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i]; } } } return SBRDEC_OK; }
void imdct_gain(FIXP_DBL *pGain_m, int *pGain_e, int tl) { FIXP_DBL gain_m = *pGain_m; int gain_e = *pGain_e; int log2_tl; log2_tl = DFRACT_BITS-1-fNormz((FIXP_DBL)tl); gain_e += -MDCT_OUTPUT_GAIN - log2_tl - MDCT_OUT_HEADROOM + 1; /* Detect non-radix 2 transform length and add amplitude compensation factor which cannot be included into the exponent above */ switch ( (tl) >> (log2_tl - 2) ) { case 0x7: /* 10 ms, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * 0.53333333333333333333) */ if (gain_m == (FIXP_DBL)0) { gain_m = FL2FXCONST_DBL(0.53333333333333333333f); } else { gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f)); } break; case 0x6: /* 3/4 of radix 2, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * 2.0/3.0) */ if (gain_m == (FIXP_DBL)0) { gain_m = FL2FXCONST_DBL(2.0/3.0f); } else { gain_m = fMult(gain_m, FL2FXCONST_DBL(2.0/3.0f)); } break; case 0x4: /* radix 2, nothing to do. */ break; default: /* unsupported */ FDK_ASSERT(0); break; } *pGain_m = gain_m; *pGain_e = gain_e; }
void initDrcGainBuffers(const int frameSize, DRC_GAIN_BUFFERS* drcGainBuffers) { int i, c, j; /* prepare 12 instances of node buffers */ for (i = 0; i < 12; i++) { for (j = 0; j < NUM_LNB_FRAMES; j++) { drcGainBuffers->linearNodeBuffer[i].nNodes[j] = 1; drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); if (j == 0) { drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].time = 0; /* initialize last node with startup node */ } else { drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].time = frameSize - 1; } } } /* prepare dummyLnb, a linearNodeBuffer containing a constant gain of 0 dB, * for the "no DRC processing" case */ drcGainBuffers->dummyLnb.gainInterpolationType = GIT_LINEAR; for (i = 0; i < NUM_LNB_FRAMES; i++) { drcGainBuffers->dummyLnb.nNodes[i] = 1; drcGainBuffers->dummyLnb.linearNode[i][0].gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); drcGainBuffers->dummyLnb.linearNode[i][0].time = frameSize - 1; } /* prepare channelGain delay line */ for (c = 0; c < 8; c++) { for (i = 0; i < NUM_LNB_FRAMES; i++) { drcGainBuffers->channelGain[c][i] = FL2FXCONST_DBL(1.0f / (float)(1 << 8)); } } drcGainBuffers->lnbPointer = 0; }
/*! \brief FDKaacEnc_CalcAutoCorrValue Calculate autocorellation value for one lag \param pointer to spectrum \param start line \param stop line \param lag to be calculated \param scaling of the lag ****************************************************************************/ static inline FIXP_DBL FDKaacEnc_CalcAutoCorrValue( const FIXP_DBL *spectrum, const INT startLine, const INT stopLine, const INT lag, const INT scale ) { int i; FIXP_DBL result = FL2FXCONST_DBL(0.f); if (lag==0) { for (i=startLine; i<stopLine; i++) { result += (fPow2(spectrum[i])>>scale); } } else { for (i=startLine; i<(stopLine-lag); i++) {
/*! \brief FDKaacEnc_ScaleUpSpectrum Scales up spectrum lines in a given frequency section \param scaled spectrum \param original spectrum \param frequency line to start scaling \param frequency line to enc scaling \return scale factor ****************************************************************************/ static inline INT FDKaacEnc_ScaleUpSpectrum( FIXP_DBL *dest, const FIXP_DBL *src, const INT startLine, const INT stopLine ) { INT i, scale; FIXP_DBL maxVal = FL2FXCONST_DBL(0.f); /* Get highest value in given spectrum */ for (i=startLine; i<stopLine; i++) { maxVal = fixMax(maxVal,fixp_abs(src[i])); } scale = CountLeadingBits(maxVal); /* Scale spectrum according to highest value */ for (i=startLine; i<stopLine; i++) { dest[i] = src[i]<<scale; } return scale; }
static inline INT_PCM AdvanceFilter(LP_FILTER *downFilter, /*!< pointer to iir filter instance */ INT_PCM *pInput, /*!< input of filter */ int downRatio, int inStride) { INT_PCM output; int i, n; #ifdef RS_BIQUAD_SCATTERGAIN #define BIQUAD_SCALE 3 #else #define BIQUAD_SCALE 12 #endif FIXP_DBL y = FL2FXCONST_DBL(0.0f); FIXP_DBL input; for (n=0; n<downRatio; n++) { FIXP_BQS (*states)[2] = downFilter->states; const FIXP_SGL *coeff = downFilter->coeffa; int s1,s2; s1 = downFilter->ptr; s2 = s1 ^ 1; #if (SAMPLE_BITS == 16) input = ((FIXP_DBL)pInput[n*inStride]) << (DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE); #elif (SAMPLE_BITS == 32) input = pInput[n*inStride] >> BIQUAD_SCALE; #else #error NOT IMPLEMENTED #endif #ifndef RS_BIQUAD_SCATTERGAIN /* Merged Direct form I */ FIXP_BQS state1, state2, state1b, state2b; state1 = states[0][s1]; state2 = states[0][s2]; /* Loop over sections */ for (i=0; i<downFilter->noCoeffs; i++) { FIXP_DBL state0; /* Load merged states (from next section) */ state1b = states[i+1][s1]; state2b = states[i+1][s2]; state0 = input + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); y = state0 - fMult(state1b, coeff[A1]) - fMult(state2b, coeff[A2]); /* Store new feed forward merge state */ states[i+1][s2] = y<<1; /* Store new feed backward state */ states[i][s2] = input<<1; /* Feedback output to next section. */ input = y; /* Transfer merged states */ state1 = state1b; state2 = state2b; /* Step to next coef set */ coeff += BIQUAD_COEFSTEP; } downFilter->ptr ^= 1; } /* Apply global gain */ y = fMult(y, downFilter->gain); #else /* Direct form II */ /* Loop over sections */ for (i=0; i<downFilter->noCoeffs; i++) { FIXP_BQS state1, state2; FIXP_DBL state0; /* Load states */ state1 = states[i][s1]; state2 = states[i][s2]; state0 = input - fMult(state1, coeff[A1]) - fMult(state2, coeff[A2]); y = state0 + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); /* Apply scattered gain */ y = fMult(y, downFilter->gain); /* Store new state in normalized form */ #ifdef RS_BIQUAD_STATES16 /* Do not saturate any state value ! The result would be unacceptable. Rounding makes SNR around 10dB better. */ states[i][s2] = (FIXP_BQS)(LONG)((state0 + (FIXP_DBL)(1<<(DFRACT_BITS-FRACT_BITS-2))) >> (DFRACT_BITS-FRACT_BITS-1)); #else states[i][s2] = state0<<1; #endif /* Feedback output to next section. */ input=y; /* Step to next coef set */ coeff += BIQUAD_COEFSTEP; } downFilter->ptr ^= 1; }
/******************************************************************************* Functionname: subbandTPApply ******************************************************************************/ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) { FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS]; FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS]; FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS]; FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS]; FIXP_DBL DryEner[MAX_INPUT_CHANNELS]; FIXP_DBL scale[MAX_OUTPUT_CHANNELS]; FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS]; FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS]; FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f); FIXP_DBL WetEnerX, damp, tmp; FIXP_DBL dmxReal0, dmxImag0; int skipChannels[MAX_OUTPUT_CHANNELS]; int n, ch, cplxBands, cplxHybBands; int dry_scale_dmx, wet_scale_dmx; int i_LF, i_RF; HANDLE_STP_DEC hStpDec; const FIXP_CFG *pBP; int nrgScale = (2 * self->clipProtectGainSF__FDK); hStpDec = self->hStpDec; /* set scalefactor and loop counter */ FDK_ASSERT(SF_DRY >= 1); { cplxBands = BP_GF_SIZE; cplxHybBands = self->hybridBands; dry_scale_dmx = (2 * SF_DRY) - 2; wet_scale_dmx = 2; } /* setup pointer for forming the direct downmix signal */ for (ch = 0; ch < self->numOutputChannels; ch++) { qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7]; qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7]; qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7]; qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7]; } /* clear skipping flag for all output channels */ FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int)); /* set scale values to zero */ FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL)); /* update normalisation energy with latest smoothed energy */ if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) { hStpDec->update_old_ener = 1; for (ch = 0; ch < self->numInputChannels; ch++) { hStpDec->oldDryEnerLD64[ch] = CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK); } for (ch = 0; ch < self->numOutputChannels; ch++) { hStpDec->oldWetEnerLD64[ch] = CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK); } } else { hStpDec->update_old_ener++; } /* get channel configuration */ switch (self->treeConfig) { case TREE_212: i_LF = 0; i_RF = 1; break; default: return MPS_WRONG_TREECONFIG; } /* form the 'direct' downmix signal */ pBP = hStpDec->BP_GF - BP_GF_START; switch (self->treeConfig) { case TREE_212: for (n = BP_GF_START; n < cplxBands; n++) { dmxReal0 = qmfOutputRealDry[i_LF][n] + qmfOutputRealDry[i_RF][n]; dmxImag0 = qmfOutputImagDry[i_LF][n] + qmfOutputImagDry[i_RF][n]; DRY_ENER_SUM_CPLX(DryEner0, dmxReal0, dmxImag0, n); } DRY_ENER_WEIGHT(DryEner0); break; default:; } DryEner[0] = DryEner0; /* normalise the 'direct' signals */ for (ch = 0; ch < self->numInputChannels; ch++) { DryEner[ch] = DryEner[ch] << (nrgScale); hStpDec->runDryEner[ch] = fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) + fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]); if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) { DryEnerLD64[ch] = fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]), FL2FXCONST_DBL(-0.484375f)); } else { DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); } } if (self->treeConfig == TREE_212) { for (; ch < MAX_INPUT_CHANNELS; ch++) { DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); } } /* normalise the 'diffuse' signals */ pBP = hStpDec->BP_GF - BP_GF_START; for (ch = 0; ch < self->numOutputChannels; ch++) { if (skipChannels[ch]) { continue; } WetEnerX = FL2FXCONST_DBL(0.0f); for (n = BP_GF_START; n < cplxBands; n++) { tmp = fPow2Div2(qmfOutputRealWet[ch][n] << SF_WET); tmp += fPow2Div2(qmfOutputImagWet[ch][n] << SF_WET); WetEnerX += fMultDiv2(tmp, pBP[n]); } WET_ENER_WEIGHT(WetEnerX); WetEnerX = WetEnerX << (nrgScale); hStpDec->runWetEner[ch] = fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) + fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX); if (WetEnerX == FL2FXCONST_DBL(0.0f)) { WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); } else { WetEnerLD64[ch] = fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]), FL2FXCONST_DBL(-0.484375f)); } } /* compute scale factor for the 'diffuse' signals */ switch (self->treeConfig) { case TREE_212: if (DryEner[0] != FL2FXCONST_DBL(0.0f)) { CALC_WET_SCALE(0, i_LF); CALC_WET_SCALE(0, i_RF); } break; default:; } damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE)); for (ch = 0; ch < self->numOutputChannels; ch++) { /* damp the scaling factor */ scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]); /* limiting the scale factor */ if (scale[ch] > STP_SCALE_LIMIT__FDK) { scale[ch] = STP_SCALE_LIMIT__FDK; } if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) { scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK; } /* low pass filter the scaling factor */ scale[ch] = fMult(STP_LPF_COEFF2__FDK, scale[ch]) + fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]); hStpDec->prev_tp_scale[ch] = scale[ch]; } /* combine 'direct' and scaled 'diffuse' signal */ FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS); const SCHAR *channlIndex = row2channelSTP[self->treeConfig]; for (ch = 0; ch < self->numOutputChannels; ch++) { int no_scaling; no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]]; if (no_scaling) { combineSignalCplx( &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder], &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder], &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder], &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder], cplxHybBands - self->tp_hybBandBorder); } else { FIXP_DBL scaleX; scaleX = scale[ch]; pBP = hStpDec->BP - self->tp_hybBandBorder; /* Band[HP_SIZE-3+10-1] needs not to be processed in combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */ combineSignalCplxScale1( &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder], &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder], &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder], &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder], &pBP[self->tp_hybBandBorder], scaleX, (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder); { combineSignalCplxScale2( &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1], &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1], &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1], &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX, cplxHybBands - (HP_SIZE - 3 + 10 - 1)); } } } return (SACDEC_ERROR)MPS_OK; ; }
{ 52000, 60000, 22050, 2, 9,11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ { 60000, 76000, 22050, 2, 10,12,10,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ { 76000, 82000, 22050, 2, 12,12,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ { 82000,128001, 22050, 2, 13,12,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ /* 24/48 kHz dual rate */ { 32000, 36000, 24000, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ { 36000, 44000, 24000, 2, 4, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ { 44000, 52000, 24000, 2, 6,10, 8, 8, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ { 52000, 60000, 24000, 2, 9,11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ { 60000, 76000, 24000, 2, 11,12,10,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ { 76000, 88000, 24000, 2, 12,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ { 88000,128001, 24000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 92 kbit/s */ }; const psTuningTable_t psTuningTable[4] = { { 8000, 22000, PSENC_STEREO_BANDS_10, PSENC_NENV_1, FL2FXCONST_DBL(3.0f/4.0f) }, { 22000, 28000, PSENC_STEREO_BANDS_20, PSENC_NENV_1, FL2FXCONST_DBL(2.0f/4.0f) }, { 28000, 36000, PSENC_STEREO_BANDS_20, PSENC_NENV_2, FL2FXCONST_DBL(1.5f/4.0f) }, { 36000, 160001, PSENC_STEREO_BANDS_20, PSENC_NENV_4, FL2FXCONST_DBL(1.1f/4.0f) }, }; //@}
/** * \brief Generate a vector of noise of given length. The noise values are * scaled in order to yield a noise energy of 1.0 * \param spec pointer to were the noise values will be written to. * \param size amount of noise values to be generated. * \param pRandomState pointer to the state of the random generator being used. * \return exponent of generated noise vector. */ static int GenerateRandomVector (FIXP_DBL *RESTRICT spec, int size, int *pRandomState) { int i, invNrg_e = 0, nrg_e = 0; FIXP_DBL invNrg_m, nrg_m = FL2FXCONST_DBL(0.0f) ; FIXP_DBL *RESTRICT ptr = spec; int randomState = *pRandomState; #define GEN_NOISE_NRG_SCALE 7 /* Generate noise and calculate energy. */ for (i=0; i<size; i++) { randomState = (1664525L * randomState) + 1013904223L; // Numerical Recipes nrg_m = fPow2AddDiv2(nrg_m, (FIXP_DBL)randomState>>GEN_NOISE_NRG_SCALE); *ptr++ = (FIXP_DBL)randomState; } nrg_e = GEN_NOISE_NRG_SCALE*2 + 1; /* weight noise with = 1 / sqrt_nrg; */
static void calculateDetectorValues(FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the original. */ SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ FIXP_DBL *nrgVector, /*!< Energy vector. */ DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */ INT startChannel, /*!< Start channel. */ INT stopChannel, /*!< Stop channel. */ INT startIndex, /*!< Start index. */ INT stopIndex, /*!< Stop index. */ INT numberOfStrongest /*!< The number of sorted tonal components to be considered. */ ) { INT i,temp, j; const FIXP_DBL* filter = *fir_table[INVF_SMOOTHING_LENGTH]; FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest; FIXP_DBL origQuota, sbrQuota; FIXP_DBL invIndex, invChannel, invTemp; FIXP_DBL quotaVecOrig[64], quotaVecSbr[64]; FDKmemclear(quotaVecOrig,64*sizeof(FIXP_DBL)); FDKmemclear(quotaVecSbr,64*sizeof(FIXP_DBL)); invIndex = GetInvInt(stopIndex-startIndex); invChannel = GetInvInt(stopChannel-startChannel); /* Calculate the mean value, over the current time segment, for the original, the HFR and the difference, over all channels in the current frequency range. NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION). */ /* The original, the sbr signal and the total energy */ detectorValues->avgNrg = FL2FXCONST_DBL(0.0f); for(j=startIndex; j<stopIndex; j++) { for(i=startChannel; i<stopChannel; i++) { quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex); if(indexVector[i] != -1) quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex); } detectorValues->avgNrg += fMult(nrgVector[j], invIndex); } /* Calculate the mean value, over the current frequency range, for the original, the HFR and the difference. Also calculate the same mean values for the three vectors, but only includeing the x strongest copmponents. */ origQuota = FL2FXCONST_DBL(0.0f); sbrQuota = FL2FXCONST_DBL(0.0f); for(i=startChannel; i<stopChannel; i++) { origQuota += fMultDiv2(quotaVecOrig[i], invChannel); sbrQuota += fMultDiv2(quotaVecSbr[i], invChannel); } /* Calculate the mean value for the x strongest components */ FDKsbrEnc_Shellsort_fract(quotaVecOrig+startChannel,stopChannel-startChannel); FDKsbrEnc_Shellsort_fract(quotaVecSbr+startChannel,stopChannel-startChannel); origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); sbrQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); temp = min(stopChannel - startChannel, numberOfStrongest); invTemp = GetInvInt(temp); for(i=0; i<temp; i++) { origQuotaMeanStrongest += fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp); sbrQuotaMeanStrongest += fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp); } /* The value for the strongest component */ detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1]; detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1]; /* Buffer values */ FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); FDKmemmove(detectorValues->origQuotaMeanStrongest, detectorValues->origQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); FDKmemmove(detectorValues->sbrQuotaMeanStrongest, detectorValues->sbrQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota<<1; detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota<<1; detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = origQuotaMeanStrongest<<1; detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = sbrQuotaMeanStrongest<<1; /* Filter values */ detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f); detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f); detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); for(i=0;i<INVF_SMOOTHING_LENGTH+1;i++) { detectorValues->origQuotaMeanFilt += fMult(detectorValues->origQuotaMean[i], filter[i]); detectorValues->sbrQuotaMeanFilt += fMult(detectorValues->sbrQuotaMean[i], filter[i]); detectorValues->origQuotaMeanStrongestFilt += fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]); detectorValues->sbrQuotaMeanStrongestFilt += fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]); } }
static INVF_MODE decisionAlgorithm(const DETECTOR_PARAMETERS *detectorParams, /*!< Struct with the detector parameters. */ DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */ INT transientFlag, /*!< Flag indicating if there is a transient present.*/ INT* prevRegionSbr, /*!< The previous region in which the Sbr value was. */ INT* prevRegionOrig /*!< The previous region in which the Orig value was. */ ) { INT invFiltLevel, regionSbr, regionOrig, regionNrg; /* Current thresholds. */ const FIXP_DBL *quantStepsSbr = detectorParams->quantStepsSbr; const FIXP_DBL *quantStepsOrig = detectorParams->quantStepsOrig; const FIXP_DBL *nrgBorders = detectorParams->nrgBorders; const INT numRegionsSbr = detectorParams->numRegionsSbr; const INT numRegionsOrig = detectorParams->numRegionsOrig; const INT numRegionsNrg = detectorParams->numRegionsNrg; FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS]; FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS]; /* Current detector values. */ FIXP_DBL origQuotaMeanFilt; FIXP_DBL sbrQuotaMeanFilt; FIXP_DBL nrg; /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = log(16)/64.0; 0.6875 = 44/64.0 */ origQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0; /* scaled by 1/2^9 */ sbrQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0; /* scaled by 1/2^9 */ /* If energy is zero then we will get different results for different word lengths. */ nrg = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(detectorValues->avgNrg+(FIXP_DBL)1) + FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */ FDKmemcpy(quantStepsSbrTmp,quantStepsSbr,numRegionsSbr*sizeof(FIXP_DBL)); FDKmemcpy(quantStepsOrigTmp,quantStepsOrig,numRegionsOrig*sizeof(FIXP_DBL)); if(*prevRegionSbr < numRegionsSbr) quantStepsSbrTmp[*prevRegionSbr] = quantStepsSbr[*prevRegionSbr] + hysteresis; if(*prevRegionSbr > 0) quantStepsSbrTmp[*prevRegionSbr - 1] = quantStepsSbr[*prevRegionSbr - 1] - hysteresis; if(*prevRegionOrig < numRegionsOrig) quantStepsOrigTmp[*prevRegionOrig] = quantStepsOrig[*prevRegionOrig] + hysteresis; if(*prevRegionOrig > 0) quantStepsOrigTmp[*prevRegionOrig - 1] = quantStepsOrig[*prevRegionOrig - 1] - hysteresis; regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr); regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig); regionNrg = findRegion(nrg,nrgBorders,numRegionsNrg); *prevRegionSbr = regionSbr; *prevRegionOrig = regionOrig; /* Use different settings if a transient is present*/ invFiltLevel = (transientFlag == 1) ? detectorParams->regionSpaceTransient[regionSbr][regionOrig] : detectorParams->regionSpace[regionSbr][regionOrig]; /* Compensate for low energy.*/ invFiltLevel = max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg],0); return (INVF_MODE) (invFiltLevel); }
#include "sf_estim.h" #include "aacEnc_rom.h" #include "quantize.h" #include "bit_cnt.h" #define AS_PE_FAC_SHIFT 7 #define DIST_FAC_SHIFT 3 #define AS_PE_FAC_FLOAT (float)(1 << AS_PE_FAC_SHIFT) static const INT MAX_SCF_DELTA = 60; static const FIXP_DBL PE_C1 = FL2FXCONST_DBL(3.0f/AS_PE_FAC_FLOAT); /* (log(8.0)/log(2)) >> AS_PE_FAC_SHIFT */ static const FIXP_DBL PE_C2 = FL2FXCONST_DBL(1.3219281f/AS_PE_FAC_FLOAT); /* (log(2.5)/log(2)) >> AS_PE_FAC_SHIFT */ static const FIXP_DBL PE_C3 = FL2FXCONST_DBL(0.5593573f); /* 1-C2/C1 */ /* Function; FDKaacEnc_FDKaacEnc_CalcFormFactorChannel Description: Calculates the formfactor sf: scale factor of the mdct spectrum sfbFormFactorLdData is scaled with the factor 1/(((2^sf)^0.5) * (2^FORM_FAC_SHIFT)) */ static void FDKaacEnc_FDKaacEnc_CalcFormFactorChannel(FIXP_DBL *RESTRICT sfbFormFactorLdData, PSY_OUT_CHANNEL *RESTRICT psyOutChan)
FL2FXCONST_SGL(0.0f / (float)(1 << 2)), FL2FXCONST_SGL(0.005f / (float)(1 << 2)), FL2FXCONST_SGL(0.0312f / (float)(1 << 2)), FL2FXCONST_SGL(0.0781f / (float)(1 << 2)), FL2FXCONST_SGL(0.1953f / (float)(1 << 2)), FL2FXCONST_SGL(0.4883f / (float)(1 << 2)), FL2FXCONST_SGL(1.2207f / (float)(1 << 2)), FL2FXCONST_SGL(3.0518f / (float)(1 << 2))}; const SCHAR slopeSteepness_huffman[14][2] = { {1, -57}, {-58, 2}, {3, 4}, {5, 6}, {7, -56}, {8, -60}, {-61, -55}, {9, -59}, {10, -54}, {-64, 11}, {-51, 12}, {-62, -50}, {-63, 13}, {-52, -53}}; const FIXP_DBL downmixCoeff[] = { FL2FXCONST_DBL(1.0000000000 / (float)(1 << 2)), FL2FXCONST_DBL(0.9440608763 / (float)(1 << 2)), FL2FXCONST_DBL(0.8912509381 / (float)(1 << 2)), FL2FXCONST_DBL(0.8413951416 / (float)(1 << 2)), FL2FXCONST_DBL(0.7943282347 / (float)(1 << 2)), FL2FXCONST_DBL(0.7498942093 / (float)(1 << 2)), FL2FXCONST_DBL(0.7079457844 / (float)(1 << 2)), FL2FXCONST_DBL(0.6683439176 / (float)(1 << 2)), FL2FXCONST_DBL(0.6309573445 / (float)(1 << 2)), FL2FXCONST_DBL(0.5956621435 / (float)(1 << 2)), FL2FXCONST_DBL(0.5623413252 / (float)(1 << 2)), FL2FXCONST_DBL(0.5308844442 / (float)(1 << 2)), FL2FXCONST_DBL(0.5011872336 / (float)(1 << 2)), FL2FXCONST_DBL(0.4216965034 / (float)(1 << 2)), FL2FXCONST_DBL(0.3548133892 / (float)(1 << 2)), FL2FXCONST_DBL(0.0000000000 / (float)(1 << 2))};
/* 48/96 kHz dual rate */ {CODEC_AACLD, 60000, 80000, 48000, 2, 7, 7, 10, 10, 2, 0, -3, SBR_SWITCH_LRC, 2}, {CODEC_AACLD, 80000, 112000, 48000, 2, 9, 9, 10, 10, 3, 0, -3, SBR_LEFT_RIGHT, 1}, {CODEC_AACLD, 112000, 144000, 48000, 2, 11, 11, 11, 11, 3, 0, -3, SBR_LEFT_RIGHT, 1}, {CODEC_AACLD, 144000, 176000, 48000, 2, 12, 12, 11, 11, 3, 0, -3, SBR_LEFT_RIGHT, 1}, {CODEC_AACLD, 176000, 256001, 48000, 2, 13, 13, 11, 11, 3, 0, -3, SBR_LEFT_RIGHT, 1}, }; const int sbrTuningTableSize = sizeof(sbrTuningTable) / sizeof(sbrTuningTable[0]); const psTuningTable_t psTuningTable[4] = { {8000, 22000, PSENC_STEREO_BANDS_10, PSENC_NENV_1, FL2FXCONST_DBL(3.0f / 4.0f)}, {22000, 28000, PSENC_STEREO_BANDS_20, PSENC_NENV_1, FL2FXCONST_DBL(2.0f / 4.0f)}, {28000, 36000, PSENC_STEREO_BANDS_20, PSENC_NENV_2, FL2FXCONST_DBL(1.5f / 4.0f)}, {36000, 160001, PSENC_STEREO_BANDS_20, PSENC_NENV_4, FL2FXCONST_DBL(1.1f / 4.0f)}, }; //@}
void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData, PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **qmfSlotReal, FIXP_DBL **qmfSlotImag, const int qmfExponent, const int pvcBorder0, const int timeSlotNumber, FIXP_DBL predictedEsgSlot[], int *predictedEsg_exp) { int i, band, ksg, ksg_start = 0; int RATE = pPvcDynamicData->RATE; int Esg_index = pPvcStaticData->Esg_slot_index; const SCHAR *sg_borders = pPvcDynamicData->sg_offset_low; FIXP_DBL *pEsg = pPvcStaticData->Esg[Esg_index]; FIXP_DBL E[PVC_NBLOW] = {0}; /* Subband grouping in QMF subbands below SBR range */ /* Within one timeslot ( i = [0...(RATE-1)] QMF subsamples) calculate energy E(ib,t) and group them to Esg(ksg,t). Then transfer values to logarithmical domain and store them for time domain smoothing. (7.5.6.3 Subband grouping in QMF subbands below SBR range) */ for (ksg = 0; sg_borders[ksg] < 0; ksg++) { pEsg[ksg] = FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ ksg_start++; } for (i = 0; i < RATE; i++) { FIXP_DBL *qmfR, *qmfI; qmfR = qmfSlotReal[i]; qmfI = qmfSlotImag[i]; for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { for (band = sg_borders[ksg]; band < sg_borders[ksg + 1]; band++) { /* The division by 8 == (RATE*lbw) is required algorithmically */ E[ksg] += (fPow2Div2(qmfR[band]) + fPow2Div2(qmfI[band])) >> 2; } } } for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { if (E[ksg] > (FIXP_DBL)0) { /* 10/log2(10) = 0.752574989159953 * 2^2 */ int exp_log; FIXP_DBL nrg = CalcLog2(E[ksg], 2 * qmfExponent, &exp_log); nrg = fMult(nrg, FL2FXCONST_SGL(LOG10FAC)); nrg = scaleValue(nrg, exp_log - PVC_ESG_EXP + 2); pEsg[ksg] = fMax(nrg, FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP))); } else { pEsg[ksg] = FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ } } /* Time domain smoothing of subband-grouped energy */ { int idx = pPvcStaticData->Esg_slot_index; FIXP_DBL *pEsg_filt; FIXP_SGL SCcoeff; E[0] = E[1] = E[2] = (FIXP_DBL)0; for (i = 0; i < pPvcDynamicData->ns; i++) { SCcoeff = pPvcDynamicData->pSCcoeffs[i]; pEsg_filt = pPvcStaticData->Esg[idx]; /* Div2 is compensated by scaling of coeff table */ E[0] = fMultAddDiv2(E[0], pEsg_filt[0], SCcoeff); E[1] = fMultAddDiv2(E[1], pEsg_filt[1], SCcoeff); E[2] = fMultAddDiv2(E[2], pEsg_filt[2], SCcoeff); if (i >= pPvcDynamicData->pastEsgSlotsAvail) { /* if past Esg values are not available use the ones from the last valid * slot */ continue; } if (idx > 0) { idx--; } else { idx += PVC_NS_MAX - 1; } } } /* SBR envelope scalefactor prediction */ { int E_high_exp[PVC_NBHIGH_MAX]; int E_high_exp_max = 0; int pvcTab1ID; int pvcTab2ID = (int)pPvcDynamicData->pPvcID[timeSlotNumber]; const UCHAR *pTab1, *pTab2; if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[0]) { pvcTab1ID = 0; } else if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[1]) { pvcTab1ID = 1; } else { pvcTab1ID = 2; } pTab1 = &(pPvcDynamicData ->pPVCTab1[pvcTab1ID * PVC_NBLOW * pPvcDynamicData->nbHigh]); pTab2 = &(pPvcDynamicData->pPVCTab2[pvcTab2ID * pPvcDynamicData->nbHigh]); for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { FIXP_SGL predCoeff; FIXP_DBL accu; int predCoeff_exp, kb; E_high_exp[ksg] = 0; /* residual part */ accu = ((LONG)(SCHAR)*pTab2++) << (DFRACT_BITS - 8 - PVC_ESG_EXP + pPvcDynamicData->pScalingCoef[3]); /* linear combination of lower grouped energies part */ for (kb = 0; kb < PVC_NBLOW; kb++) { predCoeff = (FIXP_SGL)( (SHORT)(SCHAR)pTab1[kb * pPvcDynamicData->nbHigh + ksg] << 8); predCoeff_exp = pPvcDynamicData->pScalingCoef[kb] + 1; /* +1 to compensate for Div2 */ accu += fMultDiv2(E[kb], predCoeff) << predCoeff_exp; } /* convert back to linear domain */ accu = fMult(accu, FL2FXCONST_SGL(LOG10FAC_INV)); accu = f2Pow( accu, PVC_ESG_EXP - 1, &predCoeff_exp); /* -1 compensates for exponent of LOG10FAC_INV */ predictedEsgSlot[ksg] = accu; E_high_exp[ksg] = predCoeff_exp; if (predCoeff_exp > E_high_exp_max) { E_high_exp_max = predCoeff_exp; } } /* rescale output vector according to largest exponent */ for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { int scale = E_high_exp[ksg] - E_high_exp_max; predictedEsgSlot[ksg] = scaleValue(predictedEsgSlot[ksg], scale); } *predictedEsg_exp = E_high_exp_max; } pPvcStaticData->Esg_slot_index = (pPvcStaticData->Esg_slot_index + 1) & (PVC_NS_MAX - 1); pPvcDynamicData->pastEsgSlotsAvail = fMin(pPvcDynamicData->pastEsgSlotsAvail + 1, PVC_NS_MAX - 1); return; }
BQC(1.55727745512726), BQC(1.00000011737815), BQC(0.712515423588351), BQC( 0.268752723900498), BQC(1.33407591943643), BQC(0.999999795953228), BQC(0.625059117330989), BQC( 0.316194685288965), BQC(1.10689898412458), BQC(1.00000035057114), BQC(0.52803514366398), BQC( 0.370517843224669), BQC(0.89060371078454), BQC(0.999999343962822), BQC(0.426920462165257), BQC( 0.429608200207746), BQC(0.694438261209433), BQC( 1.0000008629792), BQC(0.326530699561716), BQC( 0.491714450654174), BQC(0.523237800935322), BQC(1.00000101349782), BQC(0.230829556274851), BQC( 0.555559034843281), BQC(0.378631165929563), BQC(0.99998986482665), BQC(0.142906422036095), BQC( 0.620338874442411), BQC(0.260786911308437), BQC(1.00003261460178), BQC(0.0651008576256505), BQC( 0.685759923926262), BQC(0.168409429188098), BQC(0.999933049695828), BQC(-0.000790067789975562), BQC( 0.751905896602325), BQC(0.100724533818628), BQC(1.00009472669872), BQC(-0.0533772830257041), BQC( 0.81930744384525), BQC(0.0561434357867363), BQC(0.999911636304276), BQC(-0.0913550299236405), BQC( 0.88883625875915), BQC(0.0341680678662057), BQC(1.00003667508676), BQC(-0.113405185536697), BQC( 0.961756638268446) }; #ifdef RS_BIQUAD_SCATTERGAIN static const FIXP_DBL g48 = FL2FXCONST_DBL(0.67436532061161992682404480717671 - 0.001); #else static const FIXP_DBL g48 = FL2FXCONST_DBL(0.002712866530047) - (FIXP_DBL)0x8000; #endif static const struct FILTER_PARAM param_set48 = { sos48, g48, 480, 15, 4 /* LF 2 */ }; /** *\brief Low Pass Wc = 0,5, order 24, Stop Band -96dB. Wc criteria is "almost 0dB passband", not the usual -3db gain point.
/***************************************************************************** functionname: FDKaacEnc_PnsDetect description: do decision, if PNS shall used or not returns: input: pns config structure pns data structure (modified), lastWindowSequence (long or short blocks) sfbActive pointer to Sfb Energy, Threshold, Offset pointer to mdct Spectrum length of each group pointer to tonality calculated in chaosmeasure tns order and prediction gain calculated noiseNrg at active PNS output: pnsFlag in pns data structure *****************************************************************************/ void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT lastWindowSequence, const INT sfbActive, const INT maxSfbPerGroup, FIXP_DBL *sfbThresholdLdData, const INT *sfbOffset, FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality, INT tnsOrder, INT tnsPredictionGain, INT tnsActive, FIXP_DBL *sfbEnergyLdData, INT *noiseNrg ) { int sfb; int startNoiseSfb; if (pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) { if ( (!pnsConf->usePns) || /* pns enabled? */ (lastWindowSequence == SHORT_WINDOW) ) /* currently only long blocks */ { FDKmemclear(pnsData->pnsFlag, MAX_GROUPED_SFB*sizeof(INT)); /* clear all pnsFlags */ for (sfb=0; sfb<MAX_GROUPED_SFB; sfb++) { noiseNrg[sfb] = NO_NOISE_PNS; /* clear nrg's of previous frame */ } return; } } else { if(!pnsConf->usePns) return; /* PNS only for long Windows */ if (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) { if(lastWindowSequence != LONG_WINDOW) { for (sfb = 0; sfb < sfbActive; sfb++) { pnsData->pnsFlag[sfb] = 0; /* clear all pnsFlags */ } return; } } } /* call noise detection */ FDKaacEnc_FDKaacEnc_noiseDetection( pnsConf, pnsData, sfbActive, sfbOffset, tnsOrder, tnsPredictionGain, tnsActive, mdctSpectrum, sfbMaxScaleSpec, sfbtonality ); /* set startNoiseSfb (long) */ startNoiseSfb = pnsConf->np.startSfb; /* Set noise substitution status */ for(sfb = 0; sfb < sfbActive; sfb++) { /* No PNS below startNoiseSfb */ if(sfb < startNoiseSfb){ pnsData->pnsFlag[sfb] = 0; continue; } /* do noise substitution if fuzzy measure is high enough sfb freq > minimum sfb freq signal in coder band is not masked */ if((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) && ( (sfbThresholdLdData[sfb] + FL2FXCONST_DBL(0.5849625f/64.0f)) /* thr * 1.5 = thrLd +ld(1.5)/64 */ < sfbEnergyLdData[sfb] ) ) { /* mark in psyout flag array that we will code this band with PNS */ pnsData->pnsFlag[sfb] = 1; /* PNS_ON */ } else{ pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */ } /* no PNS if LTP is active */ } /* avoid PNS holes */ if((pnsData->noiseFuzzyMeasure[0]>FL2FXCONST_SGL(0.5f)) && (pnsData->pnsFlag[1])) { pnsData->pnsFlag[0] = 1; } for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) { if((pnsData->noiseFuzzyMeasure[sfb]>pnsConf->np.gapFillThr) && (pnsData->pnsFlag[sfb-1]) && (pnsData->pnsFlag[sfb+1])) { pnsData->pnsFlag[sfb] = 1; } } if(maxSfbPerGroup>0) { /* avoid PNS hole */ if((pnsData->noiseFuzzyMeasure[maxSfbPerGroup-1]>pnsConf->np.gapFillThr) && (pnsData->pnsFlag[maxSfbPerGroup-2])) { pnsData->pnsFlag[maxSfbPerGroup-1] = 1; } /* avoid single PNS band */ if(pnsData->pnsFlag[maxSfbPerGroup-2]==0) { pnsData->pnsFlag[maxSfbPerGroup-1] = 0; } } /* avoid single PNS bands */ if(pnsData->pnsFlag[1]==0) { pnsData->pnsFlag[0] = 0; } for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) { if((pnsData->pnsFlag[sfb-1]==0)&&(pnsData->pnsFlag[sfb+1]==0)) { pnsData->pnsFlag[sfb] = 0; } } /* calculate noiseNrg's */ FDKaacEnc_CalcNoiseNrgs( sfbActive, pnsData->pnsFlag, sfbEnergyLdData, noiseNrg ); }
Initial author: M. Lohwasser contents/description: pns.c ******************************************************************************/ #include "aacenc_pns.h" #include "psy_data.h" #include "pnsparam.h" #include "noisedet.h" #include "bit_cnt.h" #include "interface.h" /* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */ static const FIXP_DBL minCorrelationEnergy = FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */ /* noiseCorrelationThresh = 0.6^2 */ static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36); static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT sfbActive, const INT *sfbOffset, INT tnsOrder, INT tnsPredictionGain, INT tnsActive, FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality ); static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive,
void FDKaacEnc_CalculateFullTonality(FIXP_DBL *RESTRICT spectrum, INT *RESTRICT sfbMaxScaleSpec, FIXP_DBL *RESTRICT sfbEnergyLD64, FIXP_SGL *RESTRICT sfbTonality, INT sfbCnt, const INT *sfbOffset, INT usePns) { INT j; #if defined(ARCH_PREFER_MULT_32x16) FIXP_SGL alpha_0 = FL2FXCONST_SGL(0.25f); /* used in smooth ChaosMeasure */ FIXP_SGL alpha_1 = FL2FXCONST_SGL(1.0f-0.25f); /* used in smooth ChaosMeasure */ #else FIXP_DBL alpha_0 = FL2FXCONST_DBL(0.25f); /* used in smooth ChaosMeasure */ FIXP_DBL alpha_1 = FL2FXCONST_DBL(1.0f-0.25f); /* used in smooth ChaosMeasure */ #endif INT numberOfLines = sfbOffset[sfbCnt]; if (!usePns) return; C_ALLOC_SCRATCH_START(chaosMeasurePerLine, FIXP_DBL, (1024)); /* calculate chaos measure */ FDKaacEnc_CalculateChaosMeasure(spectrum, numberOfLines, chaosMeasurePerLine); /* smooth ChaosMeasure */ for (j=1;j<numberOfLines;j++) {
static void CTns_Filter (FIXP_DBL *spec, int size, int inc, FIXP_TCC coeff [], int order) { // - Simple all-pole filter of order "order" defined by // y(n) = x(n) - a(2)*y(n-1) - ... - a(order+1)*y(n-order) // // - The state variables of the filter are initialized to zero every time // // - The output data is written over the input data ("in-place operation") // // - An input vector of "size" samples is processed and the index increment // to the next data sample is given by "inc" int i,j,N; FIXP_DBL *pSpec; FIXP_DBL maxVal=FL2FXCONST_DBL(0.0); INT s; FDK_ASSERT(order <= TNS_MAXIMUM_ORDER); C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER); FDKmemclear(state, order*sizeof(FIXP_DBL)); for (i=0; i<size; i++) { maxVal = fixMax(maxVal,fixp_abs(spec[i])); } if ( maxVal > FL2FXCONST_DBL(0.03125*0.70710678118) ) s = fixMax(CntLeadingZeros(maxVal)-6,0); else s = fixMax(CntLeadingZeros(maxVal)-5,0); s = fixMin(s,2); s = s-1; if (inc == -1) pSpec = &spec[size - 1]; else pSpec = &spec[0]; FIXP_TCC *pCoeff; #define FIRST_PART_FLTR \ FIXP_DBL x, *pState = state; \ pCoeff = coeff; \ \ if (s < 0) \ x = (pSpec [0]>>1) + fMultDiv2 (*pCoeff++, pState [0]) ; \ else \ x = (pSpec [0]<<s) + fMultDiv2 (*pCoeff++, pState [0]) ; #define INNER_FLTR_INLINE \ x = fMultAddDiv2 (x, *pCoeff, pState [1]); \ pState [0] = pState [1] - (fMultDiv2 (*pCoeff++, x) <<2) ; \ pState++; #define LAST_PART_FLTR \ if (s < 0) \ *pSpec = x << 1; \ else \ *pSpec = x >> s; \ *pState =(-x) << 1; \ pSpec += inc ; if (order>8) { N = (order-1)&7; for (i = size ; i != 0 ; i--) { FIRST_PART_FLTR for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE } INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE LAST_PART_FLTR } } else if (order>4) {