Line data Source code
1 : /****************************************************************************** 2 : * ETSI TS 103 634 V1.5.1 * 3 : * Low Complexity Communication Codec Plus (LC3plus) * 4 : * * 5 : * Copyright licence is solely granted through ETSI Intellectual Property * 6 : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, * 7 : * estoppel or otherwise. * 8 : ******************************************************************************/ 9 : 10 : #include "options.h" 11 : #include "wmc_auto.h" 12 : #include "defines.h" 13 : #include "functions.h" 14 : 15 0 : void plc_phEcu_rec_frame(Complex *X_in, 16 : LC3_INT32 L, 17 : LC3_INT32 Lecu, 18 : const LC3_FLOAT *whr, 19 : const LC3_FLOAT *winMDCT, 20 : LC3_INT32 Lprot, 21 : LC3_FLOAT *xfp, 22 : LC3_INT32 time_offs, 23 : LC3_FLOAT *x_out, 24 : Complex *full_spec_dbg, 25 : LC3_FLOAT* ifft_out_dbg, 26 : LC3_FLOAT* xsubst_dbg, 27 : LC3_INT32 LA_ZEROS, 28 : LC3_INT32 LA, 29 : Fft* PhEcu_ifft 30 : ) 31 : { 32 : 33 : LC3_INT32 i; 34 : 35 : LC3_FLOAT xrec[2*MAX_LEN]; 36 : LC3_FLOAT xsubst[2*MAX_LEN]; 37 : LC3_FLOAT xsubst_LL[2*MAX_LEN]; 38 : LC3_FLOAT *pXsubst_LL; 39 : 40 : LC3_INT32 fs_idx; 41 : 42 : LC3_FLOAT *pXfp, *pOlaXsubst, *pXOut; 43 : LC3_INT32 work_part, copy_part, ola_part; 44 : 45 : const LC3_FLOAT *hannOla; 46 : const LC3_FLOAT *pHannOla; 47 : 48 : UNUSED(time_offs); 49 : UNUSED(full_spec_dbg); 50 : UNUSED(ifft_out_dbg); 51 : UNUSED(xsubst_dbg); 52 : UNUSED(xsubst_LL); 53 : 54 0 : fs_idx = FRAME2FS_IDX_10MS(L); 55 0 : hannOla = hannOla_wins[fs_idx]; 56 : 57 0 : X_in[0].i = X_in[Lprot / 2].r; /* move fs/2 real to imag part of X_in[0]*/ 58 : 59 0 : real_fft_apply(PhEcu_ifft, (LC3_FLOAT*)X_in, xrec); 60 : 61 0 : move_float(xsubst, xrec, Lprot); 62 : 63 : 64 : 65 : 66 : { 67 0 : for (i = 0; i < Lprot; i++) { 68 : 69 0 : if (whr[i] != 0) { 70 0 : xsubst[i] = xsubst[i] / whr[i]; /* inverse stored in BASOP */ 71 : } 72 : 73 : } 74 : 75 : assert(xsubst_LL != NULL); 76 0 : zero_float(xsubst_LL, (Lecu-Lprot)/2); /* initial 2ms */ 77 0 : zero_float(&(xsubst_LL[ Lecu- (Lecu-Lprot)/2]), (Lecu-Lprot)/2); /* tail 2ms */ 78 : { 79 : /* position reconstruction properly */ 80 : /* pXsubst_LL = &xsubst_LL[Lecu - Lprot - (Lecu - Lprot) / 2]; */ 81 0 : pXsubst_LL = &xsubst_LL[(Lecu - Lprot) / 2]; 82 0 : for (i = 0; i < Lprot ; i++) { 83 0 : *pXsubst_LL++ = xsubst[i]; /* copy required 14.25 ms into center */ 84 : } 85 : } 86 : 87 : } 88 : 89 : 90 : 91 0 : work_part = LA_ZEROS + LA; 92 0 : copy_part = (Lecu - Lprot) / 2; 93 0 : ola_part = work_part - copy_part; 94 : 95 0 : pXfp = &xfp[Lprot - work_part]; 96 0 : for (i = 0; i < copy_part; i++) { 97 0 : xsubst_LL[i] = *pXfp++; 98 : } 99 : 100 : assert(xsubst_LL != NULL); 101 0 : pOlaXsubst = &(xsubst_LL[copy_part]); 102 0 : pHannOla = hannOla; 103 0 : for (i = 0; i < ola_part; i++) { 104 0 : *pOlaXsubst = *pOlaXsubst * *pHannOla++; 105 0 : pOlaXsubst++; 106 : } 107 : 108 0 : pOlaXsubst = &(xsubst_LL[copy_part]); 109 0 : for (i = 0; i < ola_part; i++) { 110 0 : *pOlaXsubst = *pOlaXsubst + *pXfp++ * *pHannOla--; 111 0 : pOlaXsubst++; 112 : } 113 : 114 : 115 : /* clear x_out to start with */ 116 0 : assert(x_out != NULL); 117 0 : zero_float(x_out, L); 118 : 119 : 120 0 : for (i = 0; i < (Lecu - LA_ZEROS); i++) { 121 : 122 0 : xsubst_LL[i] = xsubst_LL[i] * winMDCT[i]; /* xsubstLL windowing up to 16.25 ms i.e not last 3.75 ms */ 123 : 124 : } 125 0 : zero_float(&(xsubst_LL[Lecu - LA_ZEROS]), LA_ZEROS); /* tail 3.75ms always zero */ 126 : 127 : /* perform tda */ 128 : 129 : /* first half */ 130 0 : pXsubst_LL = &xsubst_LL[3 * Lecu / 4]; 131 0 : pXfp = &xsubst_LL[(3 * Lecu / 4) - 1]; 132 : 133 0 : pXOut = x_out; 134 0 : for (i = 0; i < Lecu / 4; i++) { 135 0 : *pXOut++ = -*pXsubst_LL++ - *pXfp--; /* 3.75 ms mults with 0 . may be skipped, see BASOP */ 136 : } 137 : 138 : /* second half */ 139 : /* */ 140 : 141 0 : pXsubst_LL = &(xsubst_LL[0]); 142 0 : pXfp = &xsubst_LL[(Lecu / 2) - 1]; 143 0 : for (i = 0; i < Lecu / 4; i++) { 144 0 : *pXOut++ = *pXsubst_LL++ - *pXfp--; 145 : } 146 0 : } 147 :