INT imdct_copy_ov_and_nr( H_MDCT hMdct, FIXP_DBL * pTimeData, INT nrSamples ) { FIXP_DBL *pOvl; int nt, nf, i; nt = fMin(hMdct->ov_offset, nrSamples); nrSamples -= nt; nf = fMin(hMdct->prev_nr, nrSamples); nrSamples -= nf; FDKmemcpy(pTimeData, hMdct->overlap.time, nt*sizeof(FIXP_DBL)); pTimeData += nt; pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; for (i=0; i<nf; i++) { FIXP_DBL x = - (*pOvl--); *pTimeData = IMDCT_SCALE_DBL(x); pTimeData ++; } return (nt+nf); }
INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec, const SHORT spec_scale[], const int nSpec, FIXP_DBL *pFac, const int fac_scale, const INT fac_length, INT noOutSamples, const INT tl, const FIXP_WTP *wrs, const INT fr, FIXP_LPC A[16], INT A_exp, CAcelpStaticMem *acelp_mem, const FIXP_DBL gain, const int last_frame_lost, const int isFdFac, const UCHAR last_lpd_mode, const int k, int currAliasingSymmetry) { FIXP_DBL *pCurr, *pOvl, *pSpec; const FIXP_WTP *pWindow; const FIXP_WTB *FacWindowZir_conceal; UCHAR doFacZirConceal = 0; int doDeemph = 1; const FIXP_WTB *FacWindowZir, *FacWindowSynth; FIXP_DBL *pOut0 = output, *pOut1; int w, i, fl, nl, nr, f_len, nrSamples = 0, s = 0, scale, total_gain_e; FIXP_DBL *pF, *pFAC_and_FAC_ZIR = NULL; FIXP_DBL total_gain = gain; FDK_ASSERT(fac_length <= 1024 / (4 * 2)); switch (fac_length) { /* coreCoderFrameLength = 1024 */ case 128: pWindow = SineWindow256; FacWindowZir = FacWindowZir128; FacWindowSynth = FacWindowSynth128; break; case 64: pWindow = SineWindow128; FacWindowZir = FacWindowZir64; FacWindowSynth = FacWindowSynth64; break; case 32: pWindow = SineWindow64; FacWindowZir = FacWindowZir32; FacWindowSynth = FacWindowSynth32; break; /* coreCoderFrameLength = 768 */ case 96: pWindow = SineWindow192; FacWindowZir = FacWindowZir96; FacWindowSynth = FacWindowSynth96; break; case 48: pWindow = SineWindow96; FacWindowZir = FacWindowZir48; FacWindowSynth = FacWindowSynth48; break; default: FDK_ASSERT(0); return 0; } FacWindowZir_conceal = FacWindowSynth; /* Derive NR and NL */ fl = fac_length * 2; nl = (tl - fl) >> 1; nr = (tl - fr) >> 1; if (noOutSamples > nrSamples) { /* Purge buffered output. */ FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); nrSamples = hMdct->ov_offset; hMdct->ov_offset = 0; } if (nrSamples >= noOutSamples) { pOut1 = hMdct->overlap.time + hMdct->ov_offset; if (hMdct->ov_offset < fac_length) { pOut0 = output + nrSamples; } else { pOut0 = pOut1; } hMdct->ov_offset += fac_length + nl; } else { pOut1 = output + nrSamples; pOut0 = output + nrSamples; } { pFAC_and_FAC_ZIR = CLpd_ACELP_GetFreeExcMem(acelp_mem, 2 * fac_length); { const FIXP_DBL *pTmp1, *pTmp2; doFacZirConceal |= ((last_frame_lost != 0) && (k == 0)); doDeemph &= (last_lpd_mode != 4); if (doFacZirConceal) { /* ACELP contribution in concealment case: Use ZIR with a modified ZIR window to preserve some more energy. Dont use FAC, which contains wrong information for concealed frame Dont use last ACELP samples, but double ZIR, instead (afterwards) */ FDKmemclear(pFAC_and_FAC_ZIR, 2 * fac_length * sizeof(FIXP_DBL)); FacWindowSynth = (FIXP_WTB *)pFAC_and_FAC_ZIR; FacWindowZir = FacWindowZir_conceal; } else { CFac_CalcFacSignal(pFAC_and_FAC_ZIR, pFac, fac_scale + s, fac_length, A, A_exp, 1, isFdFac); } /* 6) Get windowed past ACELP samples and ACELP ZIR signal */ /* * Get ACELP ZIR (pFac[]) and ACELP past samples (pOut0[]) and add them * to the FAC synth signal contribution on pOut1[]. */ { { CLpd_Acelp_Zir(A, A_exp, acelp_mem, fac_length, pFac, doDeemph); pTmp1 = pOut0; pTmp2 = pFac; } for (i = 0, w = 0; i < fac_length; i++) { FIXP_DBL x; /* Div2 is compensated by table scaling */ x = fMultDiv2(pTmp2[i], FacWindowZir[w]); x += fMultDiv2(pTmp1[-i - 1], FacWindowSynth[w]); x += pFAC_and_FAC_ZIR[i]; pOut1[i] = x; w++; } } if (doFacZirConceal) { /* ZIR is the only ACELP contribution, so double it */ scaleValues(pOut1, fac_length, 1); } } } if (nrSamples < noOutSamples) { nrSamples += fac_length + nl; } /* Obtain transform gain */ total_gain = gain; total_gain_e = 0; imdct_gain(&total_gain, &total_gain_e, tl); /* IMDCT overlap add */ scale = total_gain_e; pSpec = _pSpec; /* Note:when comming from an LPD frame (TCX/ACELP) the previous alisaing * symmetry must always be 0 */ if (currAliasingSymmetry == 0) { dct_IV(pSpec, tl, &scale); } else { FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); dst_III(pSpec, tmp, tl, &scale); C_ALLOC_ALIGNED_UNREGISTER(tmp); } /* Optional scaling of time domain - no yet windowed - of current spectrum */ if (total_gain != (FIXP_DBL)0) { for (i = 0; i < tl; i++) { pSpec[i] = fMult(pSpec[i], total_gain); } } int loc_scale = fixmin_I(spec_scale[0] + scale, (INT)DFRACT_BITS - 1); scaleValuesSaturate(pSpec, tl, loc_scale); pOut1 += fl / 2 - 1; pCurr = pSpec + tl - fl / 2; for (i = 0; i < fl / 2; i++) { FIXP_DBL x1; /* FAC signal is already on pOut1, because of that the += operator. */ x1 = fMult(*pCurr++, pWindow[i].v.re); FDK_ASSERT((pOut1 >= hMdct->overlap.time && pOut1 < hMdct->overlap.time + hMdct->ov_size) || (pOut1 >= output && pOut1 < output + 1024)); *pOut1 += IMDCT_SCALE_DBL(-x1); pOut1--; } /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ pOut1 += (fl / 2) + 1; pFAC_and_FAC_ZIR += fac_length; /* set pointer to beginning of FAC ZIR */ if (nl == 0) { /* save pointer to write FAC ZIR data later */ hMdct->pFacZir = pFAC_and_FAC_ZIR; } else { FDK_ASSERT(nl >= fac_length); /* FAC ZIR will be added now ... */ hMdct->pFacZir = NULL; } pF = pFAC_and_FAC_ZIR; f_len = fac_length; pCurr = pSpec + tl - fl / 2 - 1; for (i = 0; i < nl; i++) { FIXP_DBL x = -(*pCurr--); /* 5) (item 4) Synthesis filter Zir component, FAC ZIR (another one). */ if (i < f_len) { x += *pF++; } FDK_ASSERT((pOut1 >= hMdct->overlap.time && pOut1 < hMdct->overlap.time + hMdct->ov_size) || (pOut1 >= output && pOut1 < output + 1024)); *pOut1 = IMDCT_SCALE_DBL(x); pOut1++; } hMdct->prev_nr = nr; hMdct->prev_fr = fr; hMdct->prev_wrs = wrs; hMdct->prev_tl = tl; hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; hMdct->prevAliasSymmetry = currAliasingSymmetry; fl = fr; nl = nr; pOvl = pSpec + tl / 2 - 1; pOut0 = pOut1; for (w = 1; w < nSpec; w++) /* for ACELP -> FD short */ { const FIXP_WTP *pWindow_prev; /* Setup window pointers */ pWindow_prev = hMdct->prev_wrs; /* Current spectrum */ pSpec = _pSpec + w * tl; scale = total_gain_e; /* For the second, third, etc. short frames the alisaing symmetry is equal, * either (0,0) or (1,1) */ if (currAliasingSymmetry == 0) { /* DCT IV of current spectrum */ dct_IV(pSpec, tl, &scale); } else { dst_IV(pSpec, tl, &scale); } /* Optional scaling of time domain - no yet windowed - of current spectrum */ /* and de-scale current spectrum signal (time domain, no yet windowed) */ if (total_gain != (FIXP_DBL)0) { for (i = 0; i < tl; i++) { pSpec[i] = fMult(pSpec[i], total_gain); } } loc_scale = fixmin_I(spec_scale[w] + scale, (INT)DFRACT_BITS - 1); scaleValuesSaturate(pSpec, tl, loc_scale); if (noOutSamples <= nrSamples) { /* Divert output first half to overlap buffer if we already got enough * output samples. */ pOut0 = hMdct->overlap.time + hMdct->ov_offset; hMdct->ov_offset += hMdct->prev_nr + fl / 2; } else { /* Account output samples */ nrSamples += hMdct->prev_nr + fl / 2; } /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */ for (i = 0; i < hMdct->prev_nr; i++) { FIXP_DBL x = -(*pOvl--); *pOut0 = IMDCT_SCALE_DBL(x); pOut0++; } if (noOutSamples <= nrSamples) { /* Divert output second half to overlap buffer if we already got enough * output samples. */ pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1; hMdct->ov_offset += fl / 2 + nl; } else { pOut1 = pOut0 + (fl - 1); nrSamples += fl / 2 + nl; } /* output samples before window crossing point NR .. TL/2. * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */ /* output samples after window crossing point TL/2 .. TL/2+FL/2. * -overlap[0..FL/2] - current[TL/2..FL/2] */ pCurr = pSpec + tl - fl / 2; if (currAliasingSymmetry == 0) { for (i = 0; i < fl / 2; i++) { FIXP_DBL x0, x1; cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); *pOut0 = IMDCT_SCALE_DBL(x0); *pOut1 = IMDCT_SCALE_DBL(-x1); pOut0++; pOut1--; } } else { if (hMdct->prevPrevAliasSymmetry == 0) { /* Jump DST II -> DST IV for the second window */ for (i = 0; i < fl / 2; i++) { FIXP_DBL x0, x1; cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); *pOut0 = IMDCT_SCALE_DBL(x0); *pOut1 = IMDCT_SCALE_DBL(x1); pOut0++; pOut1--; } } else { /* Jump DST IV -> DST IV from the second window on */ for (i = 0; i < fl / 2; i++) { FIXP_DBL x0, x1; cplxMult(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]); *pOut0 = IMDCT_SCALE_DBL(x0); *pOut1 = IMDCT_SCALE_DBL(x1); pOut0++; pOut1--; } } } if (hMdct->pFacZir != 0) { /* add FAC ZIR of previous ACELP -> mdct transition */ FIXP_DBL *pOut = pOut0 - fl / 2; FDK_ASSERT(fl / 2 <= 128); for (i = 0; i < fl / 2; i++) { pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); } hMdct->pFacZir = NULL; } pOut0 += (fl / 2); /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ pOut1 += (fl / 2) + 1; pCurr = pSpec + tl - fl / 2 - 1; for (i = 0; i < nl; i++) { FIXP_DBL x = -(*pCurr--); *pOut1 = IMDCT_SCALE_DBL(x); pOut1++; } /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */ pOvl = pSpec + tl / 2 - 1; /* Previous window values. */ hMdct->prev_nr = nr; hMdct->prev_fr = fr; hMdct->prev_tl = tl; hMdct->prev_wrs = pWindow_prev; hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; hMdct->prevAliasSymmetry = currAliasingSymmetry; } /* Save overlap */ pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2; FDK_ASSERT(pOvl >= hMdct->overlap.time + hMdct->ov_offset); FDK_ASSERT(tl / 2 <= hMdct->ov_size); for (i = 0; i < tl / 2; i++) { pOvl[i] = _pSpec[i + (w - 1) * tl]; } return nrSamples; }
INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac, const int fac_scale, FIXP_LPC *A, INT A_exp, INT nrOutSamples, const INT fac_length, const INT isFdFac, UCHAR prevWindowShape) { FIXP_DBL *pOvl; FIXP_DBL *pOut0; const FIXP_WTP *pWindow; int i, fl, nrSamples = 0; FDK_ASSERT(fac_length <= 1024 / (4 * 2)); fl = fac_length * 2; pWindow = FDKgetWindowSlope(fl, prevWindowShape); /* Adapt window slope length in case of frame loss. */ if (hMdct->prev_fr != fl) { int nl = 0; imdct_adapt_parameters(hMdct, &fl, &nl, fac_length, pWindow, nrOutSamples); FDK_ASSERT(nl == 0); } if (nrSamples < nrOutSamples) { pOut0 = output; nrSamples += hMdct->ov_offset; /* Purge buffered output. */ FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); hMdct->ov_offset = 0; } pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; if (nrSamples >= nrOutSamples) { pOut0 = hMdct->overlap.time + hMdct->ov_offset; hMdct->ov_offset += hMdct->prev_nr + fl / 2; } else { pOut0 = output + nrSamples; nrSamples += hMdct->prev_nr + fl / 2; } if (hMdct->prevPrevAliasSymmetry == 0) { for (i = 0; i < hMdct->prev_nr; i++) { FIXP_DBL x = -(*pOvl--); *pOut0 = IMDCT_SCALE_DBL(x); pOut0++; } } else { for (i = 0; i < hMdct->prev_nr; i++) { FIXP_DBL x = (*pOvl--); *pOut0 = IMDCT_SCALE_DBL(x); pOut0++; } } hMdct->prev_nr = 0; { if (pFac != NULL) { /* Note: The FAC gain might have been applied directly after bit stream * parse in this case. */ CFac_CalcFacSignal(pOut0, pFac, fac_scale, fac_length, A, A_exp, 0, isFdFac); } else { /* Clear buffer because of the overlap and ADD! */ FDKmemclear(pOut0, fac_length * sizeof(FIXP_DBL)); } } i = 0; if (hMdct->prevPrevAliasSymmetry == 0) { for (; i < fl / 2; i++) { FIXP_DBL x0; /* Overlap Add */ x0 = -fMult(*pOvl--, pWindow[i].v.re); *pOut0 += IMDCT_SCALE_DBL(x0); pOut0++; } } else { for (; i < fl / 2; i++) { FIXP_DBL x0; /* Overlap Add */ x0 = fMult(*pOvl--, pWindow[i].v.re); *pOut0 += IMDCT_SCALE_DBL(x0); pOut0++; } } if (hMdct->pFacZir != 0) { /* this should only happen for ACELP -> TCX20 -> ACELP transition */ FIXP_DBL *pOut = pOut0 - fl / 2; /* fl/2 == fac_length */ for (i = 0; i < fl / 2; i++) { pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); } hMdct->pFacZir = NULL; } hMdct->prev_fr = 0; hMdct->prev_nr = 0; hMdct->prev_tl = 0; hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; return nrSamples; }