1 /* 2 * Copyright (C) 2003 - 2016 Sony Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "ldac.h" 18 19 20 #define LDAC_Q_LOWENERGY 11 21 #define LDAC_Q_ADD_LOWENERGY 4 22 23 #define LDAC_TH_LOWENERGY_L (0x070bc28f>>LDAC_Q_ADD_LOWENERGY) /* Q15, _scalar(225.47)(Q19)>>4 */ 24 #define LDAC_TH_LOWENERGY_M (0x1c0ce148>>LDAC_Q_ADD_LOWENERGY) /* Q15, _scalar(897.61)(Q19)>>4 */ 25 #define LDAC_TH_LOWENERGY_H (0x6fab851f>>LDAC_Q_ADD_LOWENERGY) /* Q15, _scalar(3573.44)(Q19)>>4 */ 26 27 #define LDAC_TH_CENTROID 0x00168000 /* Q15, _scalar(45.0) */ 28 29 /*************************************************************************************************** 30 Lookup Table for Calculating Square Root Value 31 ***************************************************************************************************/ 32 static INT16 sa_sqrt_ldac[97] = { /* Q14 */ 33 0x2d41, 0x2df4, 0x2ea5, 0x2f54, 0x3000, 0x30a9, 0x3150, 0x31f5, 34 0x3298, 0x3339, 0x33d8, 0x3475, 0x3510, 0x35aa, 0x3642, 0x36d8, 35 0x376c, 0x3800, 0x3891, 0x3921, 0x39b0, 0x3a3d, 0x3ac9, 0x3b54, 36 0x3bdd, 0x3c66, 0x3ced, 0x3d72, 0x3df7, 0x3e7b, 0x3efd, 0x3f7f, 37 0x4000, 0x407f, 0x40fe, 0x417b, 0x41f8, 0x4273, 0x42ee, 0x4368, 38 0x43e1, 0x445a, 0x44d1, 0x4548, 0x45be, 0x4633, 0x46a7, 0x471b, 39 0x478d, 0x4800, 0x4871, 0x48e2, 0x4952, 0x49c1, 0x4a30, 0x4a9e, 40 0x4b0b, 0x4b78, 0x4be5, 0x4c50, 0x4cbb, 0x4d26, 0x4d90, 0x4df9, 41 0x4e62, 0x4eca, 0x4f32, 0x4f99, 0x5000, 0x5066, 0x50cb, 0x5130, 42 0x5195, 0x51f9, 0x525d, 0x52c0, 0x5323, 0x5385, 0x53e7, 0x5449, 43 0x54a9, 0x550a, 0x556a, 0x55ca, 0x5629, 0x5688, 0x56e6, 0x5745, 44 0x57a2, 0x5800, 0x585c, 0x58b9, 0x5915, 0x5971, 0x59cc, 0x5a27, 45 0x5a82, 46 }; 47 48 /*************************************************************************************************** 49 Subfunction: Multiply 50 ***************************************************************************************************/ mul_ldac(INT32 in1,INT32 in2)51 __inline static INT32 mul_ldac( 52 INT32 in1, 53 INT32 in2) 54 { 55 INT32 out; 56 INT64 acc; 57 58 /* Q30 <- Q30 * Q30 */ 59 acc = (INT64)in1 * in2; 60 acc >>= 30; 61 62 if (acc > LDAC_MAX_32BIT) { 63 out = LDAC_MAX_32BIT; 64 } 65 else if (acc < LDAC_MIN_32BIT) { 66 out = LDAC_MIN_32BIT; 67 } 68 else { 69 out = (INT32)acc; 70 } 71 72 return out; 73 } 74 75 /*************************************************************************************************** 76 Subfunction: Subtract 77 ***************************************************************************************************/ sub_ldac(INT32 in1,INT32 in2)78 __inline static INT32 sub_ldac( 79 INT32 in1, 80 INT32 in2) 81 { 82 INT32 out; 83 84 out = in1 - in2; 85 86 return out; 87 } 88 89 /*************************************************************************************************** 90 Subfunction: Add 91 ***************************************************************************************************/ add_ldac(INT32 in1,INT32 in2)92 __inline static INT32 add_ldac( 93 INT32 in1, 94 INT32 in2) 95 { 96 INT32 out; 97 98 out = in1 + in2; 99 100 return out; 101 } 102 103 /*************************************************************************************************** 104 Subfunction: Multiply and Add 105 ***************************************************************************************************/ mad_ldac(INT32 in1,INT32 in2,INT32 in3)106 __inline static INT32 mad_ldac( 107 INT32 in1, 108 INT32 in2, 109 INT32 in3) 110 { 111 INT32 out; 112 113 out = mul_ldac(in2, in3); 114 out = add_ldac(in1, out); 115 116 return out; 117 } 118 119 /*************************************************************************************************** 120 Subfunction: Normalize 121 ***************************************************************************************************/ norm_ldac(UINT32 val)122 __inline static INT16 norm_ldac( 123 UINT32 val) 124 { 125 INT16 len; 126 127 len = 0; 128 while (val > 0) { 129 val >>= 1; 130 len++; 131 } 132 133 return len; 134 } 135 136 /*************************************************************************************************** 137 Subfunction: Calculate Exponential 138 ***************************************************************************************************/ calc_exp_ldac(INT32 in_h,UINT32 in_l)139 __inline static INT16 calc_exp_ldac( 140 INT32 in_h, 141 UINT32 in_l) 142 { 143 INT16 e; 144 145 if (in_h) { 146 e = norm_ldac((UINT32)in_h) + 32; 147 } 148 else { 149 e = norm_ldac(in_l); 150 } 151 e = (63 - e) & 0xfffe; 152 153 return e; 154 } 155 156 /*************************************************************************************************** 157 Subfunction: Calculate Square Root 158 ***************************************************************************************************/ calc_sqrt_ldac(INT32 in,INT16 e)159 __inline static INT32 calc_sqrt_ldac( 160 INT32 in, 161 INT16 e) 162 { 163 INT16 i; 164 INT32 val, dif, a; 165 166 if (in <= 0) { 167 return 0; 168 } 169 170 i = (INT16)(in >> 24); 171 a = in & 0x00ffffffL; 172 173 i = i - 32; 174 val = sa_sqrt_ldac[i] << 16; /* Q30 <- Q14 << 16 */ 175 dif = sub_ldac(sa_sqrt_ldac[i+1]<<16, val); /* Q30 */ 176 a = (INT32)(((INT64)a << 30) >> 24); /* Q30 a = a / 0x1000000 */ 177 val = mad_ldac(val, dif, a); 178 val = val >> (e >> 1); 179 180 return val; 181 } 182 183 /*************************************************************************************************** 184 Calculate Pseudo Spectrum and Low Band Energy 185 ***************************************************************************************************/ calc_mdct_pseudo_spectrum_ldac(INT32 * p_spec,INT32 * p_psd,UINT32 nsp)186 static INT32 calc_mdct_pseudo_spectrum_ldac( 187 INT32 *p_spec, 188 INT32 *p_psd, 189 UINT32 nsp) 190 { 191 UINT32 isp; 192 INT16 e; 193 INT32 y0, y1, y2; 194 INT32 tmp; 195 INT64 low_energy; 196 INT64 acc1, acc2; 197 198 { 199 y1 = p_spec[0]; 200 y2 = p_spec[1]; 201 acc1 = (INT64)y1 * (INT64)y1; 202 acc2 = (INT64)y2 * (INT64)y2; 203 acc1 = acc1 + acc2; 204 low_energy = acc1 >> LDAC_Q_ADD_LOWENERGY; /* Q26 <- (Q15 * Q15) >> 4 */ 205 e = calc_exp_ldac((INT32)(acc1>>32), (UINT32)(acc1&0xffffffff)); 206 tmp = (INT32)((acc1 << e) >> 32); 207 *p_psd++ = calc_sqrt_ldac(tmp, e); 208 } 209 210 for (isp = 1; isp < LDAC_NSP_LOWENERGY; isp++) { 211 y0 = y1; 212 y1 = y2; 213 y2 = p_spec[isp+1]; 214 acc1 = (INT64)y1 * (INT64)y1; 215 acc2 = (INT64)(y0-y2) * (INT64)(y0-y2); 216 acc1 = acc1 + acc2; 217 low_energy += acc1 >> LDAC_Q_ADD_LOWENERGY; /* Q26 <- (Q15 * Q15) >> 4 */ 218 e = calc_exp_ldac((INT32)(acc1>>32), (UINT32)(acc1&0xffffffff)); 219 tmp = (INT32)((acc1 << e) >> 32); 220 *p_psd++ = calc_sqrt_ldac(tmp, e); 221 } 222 223 for (isp = LDAC_NSP_LOWENERGY; isp < nsp-1; isp++) { 224 y0 = y1; 225 y1 = y2; 226 y2 = p_spec[isp+1]; 227 acc1 = (INT64)y1 * (INT64)y1; 228 acc2 = (INT64)(y0-y2) * (INT64)(y0-y2); 229 acc1 = acc1 + acc2; 230 e = calc_exp_ldac((INT32)(acc1 >> 32), (UINT32)(acc1&0xffffffff)); 231 tmp = (INT32) ((acc1 << e) >> 32); 232 *p_psd++ = calc_sqrt_ldac(tmp, e); 233 } 234 235 { 236 acc1 = (INT64)y1 * (INT64)y1; 237 acc2 = (INT64)y2 * (INT64)y2; 238 acc1 = acc1 + acc2; 239 e = calc_exp_ldac((INT32)(acc1 >> 32), (UINT32)(acc1&0xffffffff)); 240 tmp = (INT32)((acc1 << e) >> 32); 241 *p_psd++ = calc_sqrt_ldac(tmp, e); 242 } 243 244 low_energy >>= LDAC_Q_LOWENERGY; /* Q15 <- Q26 >> 11 */ 245 if (low_energy > LDAC_MAX_32BIT) { 246 low_energy = LDAC_MAX_32BIT; 247 } 248 249 return (INT32)low_energy; 250 } 251 252 /*************************************************************************************************** 253 Calculate Pseudo Spectrum Centroid 254 ***************************************************************************************************/ calc_spectral_centroid_ldac(INT32 * p_spec,UINT32 nsp)255 static INT32 calc_spectral_centroid_ldac( 256 INT32 *p_spec, 257 UINT32 nsp) 258 { 259 UINT32 isp; 260 INT32 centroid = 0; 261 INT64 s1, s2; 262 263 s1 = s2 = 0; 264 for (isp = 0; isp < nsp; isp++) { 265 s1 += ((INT64)isp * (INT64)*p_spec); /* Q15 <- Q00 * Q15 */ 266 s2 += (INT64)*p_spec++; /* Q15 */ 267 } 268 269 if (s2 != 0) { 270 centroid = (INT32)((s1<<15) / s2); /* Q15 <- (Q15<<15) / Q15 */ 271 } 272 273 return centroid; 274 } 275 276 /*************************************************************************************************** 277 Calculate Number of Zero Cross 278 ***************************************************************************************************/ calc_zero_cross_number_ldac(INT32 * p_time,UINT32 n)279 static UINT32 calc_zero_cross_number_ldac( 280 INT32 *p_time, 281 UINT32 n) 282 { 283 UINT32 i; 284 UINT32 zero_cross = 0; 285 INT32 prev, tmp; 286 287 prev = 0; 288 for (i = 0; i < n; i++) { 289 if ((prev == 0) || (*p_time == 0)) { 290 tmp = 0; 291 } 292 else { 293 tmp = prev ^ (*p_time); 294 } 295 296 if (tmp < 0) { 297 zero_cross++; 298 } 299 prev = *p_time++; 300 } 301 302 return zero_cross; 303 } 304 305 /*************************************************************************************************** 306 Analyze Frame Status 307 ***************************************************************************************************/ ana_frame_status_ldac(SFINFO * p_sfinfo,int nlnn)308 DECLSPEC int ana_frame_status_ldac( 309 SFINFO *p_sfinfo, 310 int nlnn) 311 { 312 AC *p_ac; 313 int ich; 314 int nchs = p_sfinfo->cfg.ch; 315 int nsmpl = npow2_ldac(nlnn+1); 316 int cnt; 317 int a_status[LDAC_PRCNCH]; 318 UINT32 zero_cross; 319 INT32 low_energy, centroid; 320 INT32 a_psd_spec[LDAC_NSP_PSEUDOANA]; 321 322 323 for (ich = 0; ich < nchs; ich++) { 324 p_ac = p_sfinfo->ap_ac[ich]; 325 326 low_energy = calc_mdct_pseudo_spectrum_ldac(p_ac->p_acsub->a_spec, a_psd_spec, LDAC_NSP_PSEUDOANA); 327 328 centroid = calc_spectral_centroid_ldac(a_psd_spec, LDAC_NSP_PSEUDOANA); 329 330 zero_cross = calc_zero_cross_number_ldac(p_ac->p_acsub->a_time, nsmpl); 331 332 a_status[ich] = LDAC_FRMSTAT_LEV_0; 333 if (low_energy < LDAC_TH_LOWENERGY_L) { 334 a_status[ich] = LDAC_FRMSTAT_LEV_3; 335 } 336 else { 337 if (low_energy < LDAC_TH_LOWENERGY_M) { 338 a_status[ich] = LDAC_FRMSTAT_LEV_2; 339 } 340 else if (low_energy < LDAC_TH_LOWENERGY_H) { 341 a_status[ich] = LDAC_FRMSTAT_LEV_1; 342 } 343 344 cnt = p_ac->frmana_cnt; 345 if ((centroid > LDAC_TH_CENTROID) && (zero_cross >= LDAC_TH_ZCROSNUM)) { 346 cnt++; 347 348 if (cnt >= LDAC_MAXCNT_FRMANA) { 349 cnt = LDAC_MAXCNT_FRMANA; 350 a_status[ich] = LDAC_FRMSTAT_LEV_2; 351 } 352 else if (a_status[ich] <= LDAC_FRMSTAT_LEV_1) { 353 a_status[ich]++; 354 } 355 } 356 else { 357 cnt = 0; 358 } 359 p_ac->frmana_cnt = cnt; 360 } 361 } 362 363 if (nchs == LDAC_CHANNEL_1CH) { 364 return a_status[0]; 365 } else { 366 return min_ldac(a_status[0], a_status[1]); 367 } 368 } 369 370