static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ int useLdTimeAlign ) { UINT synQmfFlags = hSbrDec->SynthesisQMF.flags; UINT anaQmfFlags = hSbrDec->AnalysiscQMF.flags; int resetSynQmf = 0; int resetAnaQmf = 0; /* assign qmf type */ if (useLdTimeAlign) { if (synQmfFlags & QMF_FLAG_CLDFB) { /* change the type to MPSLD */ synQmfFlags &= ~QMF_FLAG_CLDFB; synQmfFlags |= QMF_FLAG_MPSLDFB; resetSynQmf = 1; } if (anaQmfFlags & QMF_FLAG_CLDFB) { /* change the type to MPSLD */ anaQmfFlags &= ~QMF_FLAG_CLDFB; anaQmfFlags |= QMF_FLAG_MPSLDFB; resetAnaQmf = 1; } } else { if (synQmfFlags & QMF_FLAG_MPSLDFB) { /* change the type to CLDFB */ synQmfFlags &= ~QMF_FLAG_MPSLDFB; synQmfFlags |= QMF_FLAG_CLDFB; resetSynQmf = 1; } if (anaQmfFlags & QMF_FLAG_MPSLDFB) { /* change the type to CLDFB */ anaQmfFlags &= ~QMF_FLAG_MPSLDFB; anaQmfFlags |= QMF_FLAG_CLDFB; resetAnaQmf = 1; } } if (resetAnaQmf) { int qmfErr = qmfInitAnalysisFilterBank ( &hSbrDec->AnalysiscQMF, hSbrDec->anaQmfStates, hSbrDec->AnalysiscQMF.no_col, hSbrDec->AnalysiscQMF.lsb, hSbrDec->AnalysiscQMF.usb, hSbrDec->AnalysiscQMF.no_channels, anaQmfFlags | QMF_FLAG_KEEP_STATES ); if (qmfErr != 0) { FDK_ASSERT(0); } } if (resetSynQmf) { int qmfErr = qmfInitSynthesisFilterBank ( &hSbrDec->SynthesisQMF, hSbrDec->pSynQmfStates, hSbrDec->SynthesisQMF.no_col, hSbrDec->SynthesisQMF.lsb, hSbrDec->SynthesisQMF.usb, hSbrDec->SynthesisQMF.no_channels, synQmfFlags | QMF_FLAG_KEEP_STATES ); if (qmfErr != 0) { FDK_ASSERT(0); } } }
/*! \brief Creates sbr decoder structure \return errorCode, 0 if successful */ SBR_ERROR createSbrDec (SBR_CHANNEL * hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ TRANSPOSER_SETTINGS *pSettings, const int downsampleFac, /*!< Downsampling factor */ const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ const UINT flags, const int overlap, int chan) /*!< Channel for which to assign buffers etc. */ { SBR_ERROR err = SBRDEC_OK; int timeSlots = hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ int noCols = timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec); /* Initialize scale factors */ hs->sbrScaleFactor.ov_lb_scale = 0; hs->sbrScaleFactor.ov_hb_scale = 0; hs->sbrScaleFactor.hb_scale = 0; /* create envelope calculator */ err = createSbrEnvelopeCalc (&hs->SbrCalculateEnvelope, hHeaderData, chan, flags); if (err != SBRDEC_OK) { return err; } /* create QMF filter banks */ { int qmfErr; qmfErr = qmfInitAnalysisFilterBank ( &hs->AnalysiscQMF, hs->anaQmfStates, noCols, hHeaderData->freqBandData.lowSubband, hHeaderData->freqBandData.highSubband, hHeaderData->numberOfAnalysisBands, qmfFlags & (~QMF_FLAG_KEEP_STATES) ); if (qmfErr != 0) { return SBRDEC_UNSUPPORTED_CONFIG; } } if (hs->pSynQmfStates == NULL) { hs->pSynQmfStates = GetRam_sbr_QmfStatesSynthesis(chan); if (hs->pSynQmfStates == NULL) return SBRDEC_MEM_ALLOC_FAILED; } { int qmfErr; qmfErr = qmfInitSynthesisFilterBank ( &hs->SynthesisQMF, hs->pSynQmfStates, noCols, hHeaderData->freqBandData.lowSubband, hHeaderData->freqBandData.highSubband, (64) / downsampleFac, qmfFlags & (~QMF_FLAG_KEEP_STATES) ); if (qmfErr != 0) { return SBRDEC_UNSUPPORTED_CONFIG; } } initSbrPrevFrameData (&hSbrChannel->prevFrameData, timeSlots); /* create transposer */ err = createLppTransposer (&hs->LppTrans, pSettings, hHeaderData->freqBandData.lowSubband, hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, hs->SynthesisQMF.usb, timeSlots, hs->AnalysiscQMF.no_col, hHeaderData->freqBandData.freqBandTableNoise, hHeaderData->freqBandData.nNfb, hHeaderData->sbrProcSmplRate, chan, overlap ); if (err != SBRDEC_OK) { return err; } /* The CLDFB does not have overlap */ if ((qmfFlags & QMF_FLAG_CLDFB) == 0) { if (hs->pSbrOverlapBuffer == NULL) { hs->pSbrOverlapBuffer = GetRam_sbr_OverlapBuffer(chan); if (hs->pSbrOverlapBuffer == NULL) { return SBRDEC_MEM_ALLOC_FAILED; } } else { /* Clear overlap buffer */ FDKmemclear( hs->pSbrOverlapBuffer, sizeof(FIXP_DBL) * 2 * (6) * (64) ); } } /* assign qmf time slots */ assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP); return err; }
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; }