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 : LC3_FLOAT plc_phEcu_imax2_jacobsen_mag(const Complex *y, LC3_FLOAT *c_jacobPtr) { 16 : 17 : LC3_FLOAT posi; 18 : const Complex *pY; 19 : Complex y_m1, y_0, y_p1; 20 : Complex N; 21 : Complex D; 22 : LC3_FLOAT numer, denom; 23 : 24 : /* Jacobsen estimates peak offset relative y_0 using 25 : * X_m1 - X_p1 26 : * d = REAL ( ------------------- ) * c_jacob 27 : * 2*X_0 - X_m1 -Xp1 28 : * 29 : * Where c_jacob is a window dependent constant 30 : */ 31 : 32 : /* Get the parameters into variables */ 33 0 : pY = y; 34 0 : y_m1 = *pY++; 35 0 : y_0 = *pY++; 36 0 : y_p1 = *pY++; 37 : 38 : /* prepare numerator real and imaginary parts*/ 39 0 : N = csub(y_m1, y_p1); 40 : 41 : /* prepare denominator real and imaginary parts */ 42 0 : D = cmul(cmplx(2.0, 0.0), y_0); 43 0 : D = csub(D, y_m1); 44 0 : D = csub(D, y_p1); 45 : 46 : /* REAL part of complex division */ 47 0 : numer = N.r*D.r + N.i*D.i; 48 0 : denom = D.r*D.r + D.i*D.i; 49 : 50 0 : if (numer != 0 && denom != 0) { 51 0 : posi = numer / denom * (*c_jacobPtr); 52 : } else { 53 0 : posi = 0.0; /* flat top, division is not possible choose center freq */ 54 : } 55 : 56 : 57 0 : posi = fclampf(-1.0, posi, 1.0); 58 0 : return posi; 59 : } 60 : 61 : /*-------------------------------------------------------------------* 62 : * imax() 63 : * 64 : * Get interpolated maximum position 65 : *-------------------------------------------------------------------*/ 66 : 67 0 : LC3_FLOAT plc_phEcu_interp_max(const LC3_FLOAT *y, LC3_INT32 y_len) { 68 : LC3_FLOAT posi, y1, y2, y3, y3_y1, y2i; 69 : LC3_FLOAT ftmp_den1, ftmp_den2; 70 : 71 : /* Seek the extrema of the parabola P(x) defined by 3 consecutive points so that P([-1 0 1]) = [y1 y2 y3] */ 72 0 : y1 = y[0]; 73 0 : y2 = y[1]; 74 : 75 : /* If interp between two values only */ 76 0 : if (y_len == 2) { 77 0 : if (y1 < y2) { 78 0 : return 1.0; 79 : } else { 80 0 : return 0.0; 81 : } 82 : } 83 : 84 0 : y3 = y[2]; 85 0 : y3_y1 = y3-y1; 86 0 : ftmp_den1 = (y1+y3-2*y2); 87 0 : ftmp_den2 = (4*y2 - 2*y1 - 2*y3); 88 : 89 0 : if(ftmp_den2 == 0.0 || ftmp_den1 == 0.0) { 90 0 : return 0.0; /* early exit with left-most value */ 91 : } 92 : 93 0 : y2i = ((LC3_FLOAT)-0.125) * sqrf(y3_y1) /(ftmp_den1) + y2; 94 : /* their corresponding normalized locations */ 95 0 : posi = y3_y1/(ftmp_den2); 96 : /* Interpolated maxima if locations are not within [-1,1], calculated extrema are ignored */ 97 0 : if (posi >= (LC3_FLOAT)1.0 || posi <= (LC3_FLOAT)-1.0) { 98 0 : posi = y3 > y1 ? (LC3_FLOAT)1.0 : (LC3_FLOAT)-1.0; 99 : } else { 100 0 : if (y1 >= y2i) { 101 0 : posi = (y1 > y3) ? (LC3_FLOAT)-1.0 :(LC3_FLOAT) 1.0; 102 0 : } else if (y3 >= y2i) { 103 0 : posi = (LC3_FLOAT)1.0; 104 : } 105 : } 106 : 107 0 : return posi + (LC3_FLOAT)1.0; 108 : } 109 : 110 : /*----------------------------------------------------------------------------- 111 : * fft_spec2_sqrt_approx_ () 112 : * 113 : * Approximation of sqrt(Square magnitude) of fft spectrum 114 : * if min_abs <= 0.4142135*max_abs 115 : * abs = 0.99 max_abs + 0.197*min_abs 116 : * else 117 : * abs = 0.84 max_abs + 0.561*min_abs 118 : * end 119 : * 120 : 121 : *----------------------------------------------------------------------------*/ 122 : 123 0 : void plc_phEcu_fft_spec2_sqrt_approx(const Complex* x, LC3_INT32 x_len, LC3_FLOAT* x_abs) { 124 : LC3_INT32 i; 125 : LC3_FLOAT max_abs, min_abs, re, im; 126 : 127 0 : for (i = 0; i < x_len; i++) { 128 0 : re = LC3_FABS(x[i].r); 129 0 : im = LC3_FABS(x[i].i); 130 0 : max_abs = MAX(re, im); 131 0 : min_abs = MIN(re, im); 132 : 133 0 : if (min_abs <= (LC3_FLOAT)0.4142135 * max_abs) { 134 0 : x_abs[i] = (LC3_FLOAT)0.99*max_abs + (LC3_FLOAT)0.197*min_abs; 135 : } else { 136 0 : x_abs[i] = (LC3_FLOAT)0.84*max_abs + (LC3_FLOAT)0.561*min_abs; 137 : } 138 : } 139 : 140 0 : return; 141 : } 142 : 143 0 : LC3_INT32 plc_phEcu_pitch_in_plocs(LC3_INT32* plocs, LC3_INT32 n_plocs) { 144 : 145 : LC3_INT32 i; 146 : LC3_INT32 p_in_plocs; 147 : 148 0 : p_in_plocs = 0; 149 : 150 0 : for (i = 0; i < n_plocs; i++) { 151 0 : if (plocs[i] > 0 && plocs[i] < 7) { 152 0 : p_in_plocs++; 153 : } 154 : } 155 : 156 0 : return p_in_plocs; 157 : } 158 :