예제 #1
0
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(&degreeAlias[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()
예제 #2
0
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;
}