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()
int FDK_QmfDomain_InitFilterBank(HANDLE_FDK_QMF_DOMAIN qd, UINT extra_flags) { FDK_ASSERT(qd != NULL); int err = 0; int ch, ts; HANDLE_FDK_QMF_DOMAIN_GC gc = &qd->globalConf; int noCols = gc->nQmfTimeSlots; int lsb = gc->nBandsAnalysis; int usb = fMin((INT)gc->nBandsSynthesis, 64); int nProcBands = gc->nQmfProcBands; FDK_ASSERT(nProcBands % ALIGNMENT_DEFAULT == 0); if (extra_flags & QMF_FLAG_MPSLDFB) { gc->flags &= ~QMF_FLAG_CLDFB; gc->flags |= QMF_FLAG_MPSLDFB; } for (ch = 0; ch < gc->nInputChannels; ch++) { /* distribute memory to slots array */ FIXP_DBL *ptrOv = qd->QmfDomainIn[ch].pOverlapBuffer; /* persistent memory for overlap */ if ((ptrOv == NULL) && (gc->nQmfOvTimeSlots != 0)) { err = 1; return err; } /* This assumes the workbuffer defined for ch0 is the big one being used to * hold one full frame of QMF data. */ FIXP_DBL **ptr = qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] .pWorkBuffer; /* non-persistent workbuffer */ USHORT workBufferOffset = qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] .workBufferOffset; USHORT workBufferSectSize = qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] .workBufferSectSize; if ((ptr == NULL) && (gc->nQmfTimeSlots != 0)) { err = 1; return err; } qd->QmfDomainIn[ch].pGlobalConf = gc; for (ts = 0; ts < gc->nQmfOvTimeSlots; ts++) { qd->QmfDomainIn[ch].hQmfSlotsReal[ts] = ptrOv; ptrOv += nProcBands; qd->QmfDomainIn[ch].hQmfSlotsImag[ts] = ptrOv; ptrOv += nProcBands; } for (; ts < (gc->nQmfOvTimeSlots + gc->nQmfTimeSlots); ts++) { qd->QmfDomainIn[ch].hQmfSlotsReal[ts] = FDK_getWorkBuffer( ptr, workBufferOffset, workBufferSectSize, nProcBands); workBufferOffset += nProcBands; qd->QmfDomainIn[ch].hQmfSlotsImag[ts] = FDK_getWorkBuffer( ptr, workBufferOffset, workBufferSectSize, nProcBands); workBufferOffset += nProcBands; } err |= qmfInitAnalysisFilterBank( &qd->QmfDomainIn[ch].fb, qd->QmfDomainIn[ch].pAnaQmfStates, noCols, (qd->QmfDomainIn[ch].fb.lsb == 0) ? lsb : qd->QmfDomainIn[ch].fb.lsb, (qd->QmfDomainIn[ch].fb.usb == 0) ? usb : qd->QmfDomainIn[ch].fb.usb, gc->nBandsAnalysis, gc->flags | extra_flags); } for (ch = 0; ch < gc->nOutputChannels; ch++) { FIXP_DBL outGain_m = qd->QmfDomainOut[ch].fb.outGain_m; int outGain_e = qd->QmfDomainOut[ch].fb.outGain_e; int outScale = qmfGetOutScalefactor(&qd->QmfDomainOut[ch].fb); err |= qmfInitSynthesisFilterBank( &qd->QmfDomainOut[ch].fb, qd->QmfDomainOut[ch].pSynQmfStates, noCols, (qd->QmfDomainOut[ch].fb.lsb == 0) ? lsb : qd->QmfDomainOut[ch].fb.lsb, (qd->QmfDomainOut[ch].fb.usb == 0) ? usb : qd->QmfDomainOut[ch].fb.usb, gc->nBandsSynthesis, gc->flags | extra_flags); if (outGain_m != (FIXP_DBL)0) { qmfChangeOutGain(&qd->QmfDomainOut[ch].fb, outGain_m, outGain_e); } if (outScale) { qmfChangeOutScalefactor(&qd->QmfDomainOut[ch].fb, outScale); } } return err; }