void sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ INT_PCM *timeIn, /*!< pointer to input time signal */ INT_PCM *timeOut, /*!< pointer to output time signal */ HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ INT_PCM *timeOutRight, /*!< pointer to output time signal */ const int strideIn, /*!< Time data traversal strideIn */ const int strideOut, /*!< Time data traversal strideOut */ HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ const int applyProcessing, /*!< Flag for SBR operation */ HANDLE_PS_DEC h_ps_d, const UINT flags ) { int i, slot, reserve; int saveLbScale; int ov_len; int lastSlotOffs; FIXP_DBL maxVal; /* 1+1/3 frames of spectral data: */ FIXP_DBL **QmfBufferReal = hSbrDec->QmfBufferReal; FIXP_DBL **QmfBufferImag = hSbrDec->QmfBufferImag; /* Number of QMF timeslots in the overlap buffer: */ ov_len = hSbrDec->LppTrans.pSettings->overlap; /* Number of QMF slots per frame */ int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; /* assign qmf time slots */ if ( ((flags & SBRDEC_LOW_POWER ) ? 1 : 0) != ((hSbrDec->SynthesisQMF.flags & QMF_FLAG_LP) ? 1 : 0) ) { assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, flags & SBRDEC_LOW_POWER); } if (flags & SBRDEC_ELD_GRID) { /* Choose the right low delay filter bank */ changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 ); } /* low band codec signal subband filtering */ { C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); qmfAnalysisFiltering( &hSbrDec->AnalysiscQMF, QmfBufferReal + ov_len, QmfBufferImag + ov_len, &hSbrDec->sbrScaleFactor, timeIn, strideIn, qmfTemp ); C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); } /* Clear upper half of spectrum */ { int nAnalysisBands = hHeaderData->numberOfAnalysisBands; if (! (flags & SBRDEC_LOW_POWER)) { for (slot = ov_len; slot < noCols+ov_len; slot++) { FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); FDKmemclear(&QmfBufferImag[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); } } else for (slot = ov_len; slot < noCols+ov_len; slot++) { FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); } } /* Shift spectral data left to gain accuracy in transposer and adjustor */ maxVal = maxSubbandSample( QmfBufferReal, (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, 0, hSbrDec->AnalysiscQMF.lsb, ov_len, noCols+ov_len ); reserve = fixMax(0,CntLeadingZeros(maxVal)-1) ; reserve = fixMin(reserve,DFRACT_BITS-1-hSbrDec->sbrScaleFactor.lb_scale); /* If all data is zero, lb_scale could become too large */ rescaleSubbandSamples( QmfBufferReal, (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, 0, hSbrDec->AnalysiscQMF.lsb, ov_len, noCols+ov_len, reserve); hSbrDec->sbrScaleFactor.lb_scale += reserve; /* save low band scale, wavecoding or parametric stereo may modify it */ saveLbScale = hSbrDec->sbrScaleFactor.lb_scale; if (applyProcessing) { UCHAR * borders = hFrameData->frameInfo.borders; lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - hHeaderData->numberTimeSlots; FIXP_DBL degreeAlias[(64)]; /* The transposer will override most values in degreeAlias[]. The array needs to be cleared at least from lowSubband to highSubband before. */ if (flags & SBRDEC_LOW_POWER) FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], (hHeaderData->freqBandData.highSubband-hHeaderData->freqBandData.lowSubband)*sizeof(FIXP_DBL)); /* Inverse filtering of lowband and transposition into the SBR-frequency range */ lppTransposer ( &hSbrDec->LppTrans, &hSbrDec->sbrScaleFactor, QmfBufferReal, degreeAlias, // only used if useLP = 1 QmfBufferImag, flags & SBRDEC_LOW_POWER, hHeaderData->timeStep, borders[0], lastSlotOffs, hHeaderData->freqBandData.nInvfBands, hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode ); /* Adjust envelope of current frame. */ calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, &hSbrDec->SbrCalculateEnvelope, hHeaderData, hFrameData, QmfBufferReal, QmfBufferImag, flags & SBRDEC_LOW_POWER, degreeAlias, flags, (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); /* Update hPrevFrameData (to be used in the next frame) */ for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i]; } hPrevFrameData->coupling = hFrameData->coupling; hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes]; hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame; } else { /* Reset hb_scale if no highband is present, because hb_scale is considered in the QMF-synthesis */ hSbrDec->sbrScaleFactor.hb_scale = saveLbScale; } for (i=0; i<LPC_ORDER; i++) { /* Store the unmodified qmf Slots values (required for LPC filtering) */ if (! (flags & SBRDEC_LOW_POWER)) { FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImag[i], QmfBufferImag[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); } else FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); } /* Synthesis subband filtering. */ if ( ! (flags & SBRDEC_PS_DECODED) ) { { int outScalefactor = 0; if (h_ps_d != NULL) { h_ps_d->procFrameBased = 1; /* we here do frame based processing */ } sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, QmfBufferReal, (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, hSbrDec->SynthesisQMF.no_col, &outScalefactor ); qmfChangeOutScalefactor(&hSbrDec->SynthesisQMF, outScalefactor ); { C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); qmfSynthesisFiltering( &hSbrDec->SynthesisQMF, QmfBufferReal, (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, &hSbrDec->sbrScaleFactor, hSbrDec->LppTrans.pSettings->overlap, timeOut, strideOut, qmfTemp); C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); } } } else { /* (flags & SBRDEC_PS_DECODED) */ INT i, sdiff, outScalefactor, scaleFactorLowBand, scaleFactorHighBand; SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->SynthesisQMF; HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->SynthesisQMF; /* adapt scaling */ sdiff = hSbrDec->sbrScaleFactor.lb_scale - reserve; /* Scaling difference */ scaleFactorHighBand = sdiff - hSbrDec->sbrScaleFactor.hb_scale; /* Scale of current high band */ scaleFactorLowBand_ov = sdiff - hSbrDec->sbrScaleFactor.ov_lb_scale; /* Scale of low band overlapping QMF data */ scaleFactorLowBand_no_ov = sdiff - hSbrDec->sbrScaleFactor.lb_scale; /* Scale of low band current QMF data */ outScalefactor = 0; /* Initial output scale */ if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing copy filter states */ { /* procFrameBased will be unset later */ /* copy filter states from left to right */ FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, ((640)-(64))*sizeof(FIXP_QSS)); } /* scale ALL qmf vales ( real and imag ) of mono / left channel to the same scale factor ( ov_lb_sf, lb_sf and hq_sf ) */ scalFilterBankValues( h_ps_d, /* parametric stereo decoder handle */ QmfBufferReal, /* qmf filterbank values */ QmfBufferImag, /* qmf filterbank values */ synQmf->lsb, /* sbr start subband */ hSbrDec->sbrScaleFactor.ov_lb_scale, hSbrDec->sbrScaleFactor.lb_scale, &scaleFactorLowBand_ov, /* adapt scaling values */ &scaleFactorLowBand_no_ov, /* adapt scaling values */ hSbrDec->sbrScaleFactor.hb_scale, /* current frame ( highband ) */ &scaleFactorHighBand, synQmf->no_col); /* use the same synthese qmf values for left and right channel */ synQmfRight->no_col = synQmf->no_col; synQmfRight->lsb = synQmf->lsb; synQmfRight->usb = synQmf->usb; int env=0; outScalefactor += (SCAL_HEADROOM+1); /* psDiffScale! */ { C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2*(64)); int maxShift = 0; if (hSbrDec->sbrDrcChannel.enable != 0) { if (hSbrDec->sbrDrcChannel.prevFact_exp > maxShift) { maxShift = hSbrDec->sbrDrcChannel.prevFact_exp; } if (hSbrDec->sbrDrcChannel.currFact_exp > maxShift) { maxShift = hSbrDec->sbrDrcChannel.currFact_exp; } if (hSbrDec->sbrDrcChannel.nextFact_exp > maxShift) { maxShift = hSbrDec->sbrDrcChannel.nextFact_exp; } } /* copy DRC data to right channel (with PS both channels use the same DRC gains) */ FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, sizeof(SBRDEC_DRC_CHANNEL)); for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ INT outScalefactorR, outScalefactorL; outScalefactorR = outScalefactorL = outScalefactor; /* qmf timeslot of right channel */ FIXP_DBL* rQmfReal = pWorkBuffer; FIXP_DBL* rQmfImag = pWorkBuffer + 64; { if ( i == h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env] ) { initSlotBasedRotation( h_ps_d, env, hHeaderData->freqBandData.highSubband ); env++; } ApplyPsSlot( h_ps_d, /* parametric stereo decoder handle */ (QmfBufferReal + i), /* one timeslot of left/mono channel */ (QmfBufferImag + i), /* one timeslot of left/mono channel */ rQmfReal, /* one timeslot or right channel */ rQmfImag); /* one timeslot or right channel */ } scaleFactorLowBand = (i<(6)) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; sbrDecoder_drcApplySlot ( /* right channel */ &hSbrDecRight->sbrDrcChannel, rQmfReal, rQmfImag, i, synQmfRight->no_col, maxShift ); outScalefactorR += maxShift; sbrDecoder_drcApplySlot ( /* left channel */ &hSbrDec->sbrDrcChannel, *(QmfBufferReal + i), *(QmfBufferImag + i), i, synQmf->no_col, maxShift ); outScalefactorL += maxShift; /* scale filter states for left and right channel */ qmfChangeOutScalefactor( synQmf, outScalefactorL ); qmfChangeOutScalefactor( synQmfRight, outScalefactorR ); { qmfSynthesisFilteringSlot( synQmfRight, rQmfReal, /* QMF real buffer */ rQmfImag, /* QMF imag buffer */ scaleFactorLowBand, scaleFactorHighBand, timeOutRight+(i*synQmf->no_channels*strideOut), strideOut, pWorkBuffer); qmfSynthesisFilteringSlot( synQmf, *(QmfBufferReal + i), /* QMF real buffer */ *(QmfBufferImag + i), /* QMF imag buffer */ scaleFactorLowBand, scaleFactorHighBand, timeOut+(i*synQmf->no_channels*strideOut), strideOut, pWorkBuffer); } } /* no_col loop i */ /* scale back (6) timeslots look ahead for hybrid filterbank to original value */ rescalFilterBankValues( h_ps_d, QmfBufferReal, QmfBufferImag, synQmf->lsb, synQmf->no_col ); C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2*(64)); } } sbrDecoder_drcUpdateChannel( &hSbrDec->sbrDrcChannel ); /* Update overlap buffer Even bands above usb are copied to avoid outdated spectral data in case the stop frequency raises. */ if (hSbrDec->LppTrans.pSettings->overlap > 0) { if (! (flags & SBRDEC_LOW_POWER)) { for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) { FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); FDKmemcpy(QmfBufferImag[i], QmfBufferImag[i+noCols], (64)*sizeof(FIXP_DBL)); } } else for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) { FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); } } hSbrDec->sbrScaleFactor.ov_lb_scale = saveLbScale; /* Save current frame status */ hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag; } // sbr_dec()
/* * * * \brief Perform complex-valued subband synthesis of the * low band and the high band and store the * time domain data in timeOut * */ void cplxSynthesisQmfFiltering( float **qmfReal, #ifndef LP_SBR_ONLY float **qmfImag, #endif float *timeOut, HANDLE_SBR_QMF_FILTER_BANK synQmf, int bUseLP, HANDLE_PS_DEC h_ps_dec, int active ) { int i, j; float *ptr_time_out; float *filterStates; float accu; int p; float qmfReal2[NO_ACTUAL_SYNTHESIS_CHANNELS]; float *imagSlot; int no_synthesis_channels; int qmf_filter_state_syn_size; float qmfRealTmp[NO_ACTUAL_SYNTHESIS_CHANNELS]; float qmfImagTmp[NO_ACTUAL_SYNTHESIS_CHANNELS]; int env; COUNT_sub_start("cplxSynthesisQmfFiltering"); MOVE(1); env = 0; FUNC(3); LOOP(1); PTR_INIT(1); MOVE(1); STORE(NO_ACTUAL_SYNTHESIS_CHANNELS); memset(qmfRealTmp,0,NO_ACTUAL_SYNTHESIS_CHANNELS*sizeof(float)); FUNC(3); LOOP(1); PTR_INIT(1); MOVE(1); STORE(NO_ACTUAL_SYNTHESIS_CHANNELS); memset(qmfImagTmp,0,NO_ACTUAL_SYNTHESIS_CHANNELS*sizeof(float)); INDIRECT(1); MOVE(1); no_synthesis_channels = synQmf->no_channels; INDIRECT(1); MOVE(1); qmf_filter_state_syn_size = synQmf->qmf_filter_state_size; INDIRECT(1); PTR_INIT(1); filterStates = synQmf->FilterStatesSyn; PTR_INIT(1); ptr_time_out = timeOut; INDIRECT(1); LOOP(1); for (i = 0; i < synQmf->no_col; i++) { const float *p_filter = synQmf->p_filter; INDIRECT(1); PTR_INIT(1); BRANCH(1); if (bUseLP) { PTR_INIT(1); imagSlot = qmfReal2; } #ifndef LP_SBR_ONLY else { PTR_INIT(1); imagSlot = *(qmfImag + i); } #endif #ifndef MONO_ONLY BRANCH(1); if(active){ ADD(1); INDIRECT(1); BRANCH(1); if(i == h_ps_dec-> aEnvStartStop[env]){ FUNC(3); INDIRECT(1); InitRotationEnvelope(h_ps_dec,env,synQmf->usb); env++; } FUNC(5); ApplyPsSlot(h_ps_dec, &qmfReal[i], &qmfImag[i], qmfRealTmp, qmfImagTmp); } #endif #ifndef LP_SBR_ONLY BRANCH(1); if(!bUseLP) { BRANCH(1); if(no_synthesis_channels == NO_SYNTHESIS_CHANNELS_DOWN_SAMPLED){ PTR_INIT(4); /* pointers for qmfReal[i][j], imagSlot[j], synQmf->cos_twiddle_ds[j], synQmf->sin_twiddle_ds[j] */ LOOP(1); for (j = 0; j < no_synthesis_channels; j++){ float temp; MOVE(1); temp = qmfReal[i][j]; MULT(1); MAC(1); STORE(1); qmfReal[i][j] = synQmf->t_cos[j] * qmfReal[i][j] + synQmf->t_sin[j] * imagSlot[j]; MULT(2); ADD(1); STORE(1); imagSlot[j] = synQmf->t_cos[j] * imagSlot[j] - synQmf->t_sin[j] * temp; } } PTR_INIT(2); /* pointers for qmfReal[i][j], imagSlot[j], */ INDIRECT(1); LOOP(1); for (j = 0; j < synQmf->usb; j++) { MULT(2); STORE(2); qmfReal[i][j] *= -1.0; imagSlot[j] *= -1.0; } } #endif BRANCH(1); if (bUseLP) { FUNC(3); inverseModulationLP (qmfReal[i], imagSlot, synQmf); } #ifndef LP_SBR_ONLY else { FUNC(3); inverseModulation (qmfReal[i], imagSlot, synQmf); } #endif BRANCH(1); if (bUseLP) { PTR_INIT(2); /* pointers for qmfReal[i][j], imagSlot[j], */ LOOP(1); for (j = 0; j < no_synthesis_channels; j++) { MULT(2); STORE(2); qmfReal[i][j] = qmfReal[i][j] * 0.0625f; imagSlot[j] = imagSlot[j] * 0.0625f; } } #ifndef LP_SBR_ONLY else { PTR_INIT(2); /* pointers for qmfReal[i][j], imagSlot[j], */ LOOP(1); for (j = 0; j < no_synthesis_channels; j++) { MULT(2); STORE(2); qmfReal[i][j] = qmfReal[i][j] * 0.03125f; imagSlot[j] = imagSlot[j] * 0.03125f; } } #endif COUNT_sub_start("SynthesisPolyphaseFiltering"); MULT(1); PTR_INIT(2); /* pointers for filterStates[p * 2*no_synthesis_channels + j], imagSlot[no_synthesis_channels -1 - j] */ LOOP(1); for (j = 0; j < no_synthesis_channels; j++){ float newSample; MOVE(1); newSample = imagSlot[no_synthesis_channels -1 - j]; if(no_synthesis_channels == 32){ p_filter += NO_POLY; } LOOP(1); for (p = 0; p < NO_POLY; p++) { MAC(1); STORE(1); accu = filterStates[p * 2*no_synthesis_channels + j] + (*p_filter++) * newSample; filterStates[p * 2*no_synthesis_channels + j] = accu; } } MULT(2); PTR_INIT(1); /* pointer for filterStates[p * 2*no_synthesis_channels + no_synthesis_channels + (no_synthesis_channels-1)] */ LOOP(1); for (p = 0; p < NO_POLY; p++) { MAC(1); STORE(1); accu = filterStates[p * 2*no_synthesis_channels + no_synthesis_channels + (no_synthesis_channels-1) ] + (*p_filter++) * qmfReal[i][0]; filterStates[p * 2*no_synthesis_channels + no_synthesis_channels + (no_synthesis_channels-1)] = accu; } MOVE(1); ptr_time_out[0] = accu; p_filter -= NO_POLY*2; MULT(2); PTR_INIT(2); /* pointers for filterStates[p * 2*no_synthesis_channels + no_synthesis_channels + j], qmfReal[no_synthesis_channels -1 - j] */ ADD(1); LOOP(1); for (j = 0; j < no_synthesis_channels-1; j++){ float newSample; MOVE(1); newSample = qmfReal[i][no_synthesis_channels -1 - j]; if(no_synthesis_channels == 32){ p_filter -= NO_POLY; } LOOP(1); for (p = 0; p < NO_POLY; p++) { MAC(1); STORE(1); accu = filterStates[p * 2*no_synthesis_channels + no_synthesis_channels + j] + (*--p_filter) * newSample; filterStates[p * 2*no_synthesis_channels + no_synthesis_channels + j] = accu; } MOVE(1); ptr_time_out[no_synthesis_channels - 1 - j] = accu; } ptr_time_out += no_synthesis_channels; /* Shift filter states Should be replaces by modulo operation if available */ /* FUNC(2); LOOP(1); PTR_INIT(2); MOVE(1); STORE((qmf_filter_state_syn_size - no_synthesis_channels)); */ memmove (filterStates + no_synthesis_channels, filterStates, (qmf_filter_state_syn_size - no_synthesis_channels) * sizeof (float)); /* FUNC(2); LOOP(1); PTR_INIT(1); MOVE(1); STORE(no_synthesis_channels); */ memset (filterStates, 0, no_synthesis_channels * sizeof (float)); BRANCH(1); if(active){ FUNC(2); LOOP(1); PTR_INIT(2); MOVE(1); STORE(no_synthesis_channels); memcpy(qmfReal[i],qmfRealTmp,sizeof(float)*no_synthesis_channels); #ifndef LP_SBR_ONLY FUNC(2); LOOP(1); PTR_INIT(2); MOVE(1); STORE(no_synthesis_channels); memcpy(qmfImag[i],qmfImagTmp,sizeof(float)*no_synthesis_channels); #endif } COUNT_sub_end(); } COUNT_sub_end(); }