Mercurial > hg > audiostuff
comparison intercom/ilbc/enhancer.c @ 2:13be24d74cd2
import intercom-0.4.1
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Fri, 25 Jun 2010 09:57:52 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:9cadc470e3da | 2:13be24d74cd2 |
|---|---|
| 1 | |
| 2 /****************************************************************** | |
| 3 | |
| 4 iLBC Speech Coder ANSI-C Source Code | |
| 5 | |
| 6 enhancer.c | |
| 7 | |
| 8 Copyright (C) The Internet Society (2004). | |
| 9 All Rights Reserved. | |
| 10 | |
| 11 ******************************************************************/ | |
| 12 | |
| 13 #include <math.h> | |
| 14 #include <string.h> | |
| 15 #include "iLBC_define.h" | |
| 16 #include "constants.h" | |
| 17 #include "filter.h" | |
| 18 | |
| 19 /*----------------------------------------------------------------* | |
| 20 * Find index in array such that the array element with said | |
| 21 * index is the element of said array closest to "value" | |
| 22 * according to the squared-error criterion | |
| 23 *---------------------------------------------------------------*/ | |
| 24 | |
| 25 void NearestNeighbor(int *index, /* (o) index of array element closest | |
| 26 to value */ | |
| 27 float *array, /* (i) data array */ | |
| 28 float value, /* (i) value */ | |
| 29 int arlength /* (i) dimension of data array */ | |
| 30 ) | |
| 31 { | |
| 32 int i; | |
| 33 float bestcrit, crit; | |
| 34 | |
| 35 crit = array[0] - value; | |
| 36 bestcrit = crit * crit; | |
| 37 *index = 0; | |
| 38 for (i = 1; i < arlength; i++) { | |
| 39 crit = array[i] - value; | |
| 40 crit = crit * crit; | |
| 41 | |
| 42 if (crit < bestcrit) { | |
| 43 bestcrit = crit; | |
| 44 *index = i; | |
| 45 } | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 /*----------------------------------------------------------------* | |
| 50 * compute cross correlation between sequences | |
| 51 *---------------------------------------------------------------*/ | |
| 52 | |
| 53 void mycorr1(float *corr, /* (o) correlation of seq1 and seq2 */ | |
| 54 float *seq1, /* (i) first sequence */ | |
| 55 int dim1, /* (i) dimension first seq1 */ | |
| 56 const float *seq2, /* (i) second sequence */ | |
| 57 int dim2 /* (i) dimension seq2 */ | |
| 58 ) | |
| 59 { | |
| 60 int i, j; | |
| 61 | |
| 62 for (i = 0; i <= dim1 - dim2; i++) { | |
| 63 corr[i] = 0.0; | |
| 64 for (j = 0; j < dim2; j++) { | |
| 65 corr[i] += seq1[i + j] * seq2[j]; | |
| 66 } | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 /*----------------------------------------------------------------* | |
| 71 * upsample finite array assuming zeros outside bounds | |
| 72 *---------------------------------------------------------------*/ | |
| 73 | |
| 74 | |
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 void enh_upsample(float *useq1, /* (o) upsampled output sequence */ | |
| 80 float *seq1, /* (i) unupsampled sequence */ | |
| 81 int dim1, /* (i) dimension seq1 */ | |
| 82 int hfl /* (i) polyphase filter length=2*hfl+1 */ | |
| 83 ) | |
| 84 { | |
| 85 float *pu, *ps; | |
| 86 int i, j, k, q, filterlength, hfl2; | |
| 87 const float *polyp[ENH_UPS0]; /* pointers to | |
| 88 polyphase columns */ | |
| 89 const float *pp; | |
| 90 | |
| 91 /* define pointers for filter */ | |
| 92 | |
| 93 filterlength = 2 * hfl + 1; | |
| 94 | |
| 95 if (filterlength > dim1) { | |
| 96 hfl2 = (int) (dim1 / 2); | |
| 97 for (j = 0; j < ENH_UPS0; j++) { | |
| 98 polyp[j] = polyphaserTbl + j * filterlength + hfl - hfl2; | |
| 99 } | |
| 100 hfl = hfl2; | |
| 101 filterlength = 2 * hfl + 1; | |
| 102 } else { | |
| 103 for (j = 0; j < ENH_UPS0; j++) { | |
| 104 polyp[j] = polyphaserTbl + j * filterlength; | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 /* filtering: filter overhangs left side of sequence */ | |
| 109 | |
| 110 pu = useq1; | |
| 111 for (i = hfl; i < filterlength; i++) { | |
| 112 for (j = 0; j < ENH_UPS0; j++) { | |
| 113 *pu = 0.0; | |
| 114 pp = polyp[j]; | |
| 115 ps = seq1 + i; | |
| 116 for (k = 0; k <= i; k++) { | |
| 117 *pu += *ps-- * *pp++; | |
| 118 } | |
| 119 pu++; | |
| 120 } | |
| 121 } | |
| 122 | |
| 123 /* filtering: simple convolution=inner products */ | |
| 124 | |
| 125 for (i = filterlength; i < dim1; i++) { | |
| 126 | |
| 127 | |
| 128 | |
| 129 | |
| 130 | |
| 131 for (j = 0; j < ENH_UPS0; j++) { | |
| 132 *pu = 0.0; | |
| 133 pp = polyp[j]; | |
| 134 ps = seq1 + i; | |
| 135 for (k = 0; k < filterlength; k++) { | |
| 136 *pu += *ps-- * *pp++; | |
| 137 } | |
| 138 pu++; | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 /* filtering: filter overhangs right side of sequence */ | |
| 143 | |
| 144 for (q = 1; q <= hfl; q++) { | |
| 145 for (j = 0; j < ENH_UPS0; j++) { | |
| 146 *pu = 0.0; | |
| 147 pp = polyp[j] + q; | |
| 148 ps = seq1 + dim1 - 1; | |
| 149 for (k = 0; k < filterlength - q; k++) { | |
| 150 *pu += *ps-- * *pp++; | |
| 151 } | |
| 152 pu++; | |
| 153 } | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 | |
| 158 /*----------------------------------------------------------------* | |
| 159 * find segment starting near idata+estSegPos that has highest | |
| 160 * correlation with idata+centerStartPos through | |
| 161 * idata+centerStartPos+ENH_BLOCKL-1 segment is found at a | |
| 162 * resolution of ENH_UPSO times the original of the original | |
| 163 * sampling rate | |
| 164 *---------------------------------------------------------------*/ | |
| 165 | |
| 166 void refiner(float *seg, /* (o) segment array */ | |
| 167 float *updStartPos, /* (o) updated start point */ | |
| 168 float *idata, /* (i) original data buffer */ | |
| 169 int idatal, /* (i) dimension of idata */ | |
| 170 int centerStartPos, /* (i) beginning center segment */ | |
| 171 float estSegPos, /* (i) estimated beginning other segment */ | |
| 172 float period /* (i) estimated pitch period */ | |
| 173 ) | |
| 174 { | |
| 175 int estSegPosRounded, searchSegStartPos, searchSegEndPos, corrdim; | |
| 176 int tloc, tloc2, i, st, en, fraction; | |
| 177 float vect[ENH_VECTL], corrVec[ENH_CORRDIM], maxv; | |
| 178 float corrVecUps[ENH_CORRDIM * ENH_UPS0]; | |
| 179 | |
| 180 | |
| 181 | |
| 182 | |
| 183 | |
| 184 /* defining array bounds */ | |
| 185 | |
| 186 estSegPosRounded = (int) (estSegPos - 0.5); | |
| 187 | |
| 188 searchSegStartPos = estSegPosRounded - ENH_SLOP; | |
| 189 | |
| 190 if (searchSegStartPos < 0) { | |
| 191 searchSegStartPos = 0; | |
| 192 } | |
| 193 searchSegEndPos = estSegPosRounded + ENH_SLOP; | |
| 194 | |
| 195 if (searchSegEndPos + ENH_BLOCKL >= idatal) { | |
| 196 searchSegEndPos = idatal - ENH_BLOCKL - 1; | |
| 197 } | |
| 198 corrdim = searchSegEndPos - searchSegStartPos + 1; | |
| 199 | |
| 200 /* compute upsampled correlation (corr33) and find | |
| 201 location of max */ | |
| 202 | |
| 203 mycorr1(corrVec, idata + searchSegStartPos, | |
| 204 corrdim + ENH_BLOCKL - 1, idata + centerStartPos, ENH_BLOCKL); | |
| 205 enh_upsample(corrVecUps, corrVec, corrdim, ENH_FL0); | |
| 206 tloc = 0; | |
| 207 maxv = corrVecUps[0]; | |
| 208 for (i = 1; i < ENH_UPS0 * corrdim; i++) { | |
| 209 | |
| 210 if (corrVecUps[i] > maxv) { | |
| 211 tloc = i; | |
| 212 maxv = corrVecUps[i]; | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 /* make vector can be upsampled without ever running outside | |
| 217 bounds */ | |
| 218 | |
| 219 *updStartPos = (float) searchSegStartPos + | |
| 220 (float) tloc / (float) ENH_UPS0 + (float) 1.0; | |
| 221 tloc2 = (int) (tloc / ENH_UPS0); | |
| 222 | |
| 223 if (tloc > tloc2 * ENH_UPS0) { | |
| 224 tloc2++; | |
| 225 } | |
| 226 st = searchSegStartPos + tloc2 - ENH_FL0; | |
| 227 | |
| 228 if (st < 0) { | |
| 229 memset(vect, 0, -st * sizeof(float)); | |
| 230 memcpy(&vect[-st], idata, (ENH_VECTL + st) * sizeof(float)); | |
| 231 } else { | |
| 232 | |
| 233 | |
| 234 | |
| 235 | |
| 236 | |
| 237 en = st + ENH_VECTL; | |
| 238 | |
| 239 if (en > idatal) { | |
| 240 memcpy(vect, &idata[st], | |
| 241 (ENH_VECTL - (en - idatal)) * sizeof(float)); | |
| 242 memset(&vect[ENH_VECTL - (en - idatal)], 0, | |
| 243 (en - idatal) * sizeof(float)); | |
| 244 } else { | |
| 245 memcpy(vect, &idata[st], ENH_VECTL * sizeof(float)); | |
| 246 } | |
| 247 } | |
| 248 fraction = tloc2 * ENH_UPS0 - tloc; | |
| 249 | |
| 250 /* compute the segment (this is actually a convolution) */ | |
| 251 | |
| 252 mycorr1(seg, vect, ENH_VECTL, | |
| 253 polyphaserTbl + (2 * ENH_FL0 + 1) * fraction, 2 * ENH_FL0 + 1); | |
| 254 } | |
| 255 | |
| 256 /*----------------------------------------------------------------* | |
| 257 * find the smoothed output data | |
| 258 *---------------------------------------------------------------*/ | |
| 259 | |
| 260 void smath(float *odata, /* (o) smoothed output */ | |
| 261 float *sseq, /* (i) said second sequence of waveforms */ | |
| 262 int hl, /* (i) 2*hl+1 is sseq dimension */ | |
| 263 float alpha0 /* (i) max smoothing energy fraction */ | |
| 264 ) | |
| 265 { | |
| 266 int i, k; | |
| 267 float w00, w10, w11, A, B, C, *psseq, err, errs; | |
| 268 float surround[BLOCKL_MAX]; /* shape contributed by other than | |
| 269 current */ | |
| 270 float wt[2 * ENH_HL + 1]; /* waveform weighting to get | |
| 271 surround shape */ | |
| 272 float denom; | |
| 273 | |
| 274 /* create shape of contribution from all waveforms except the | |
| 275 current one */ | |
| 276 | |
| 277 for (i = 1; i <= 2 * hl + 1; i++) { | |
| 278 wt[i - 1] = | |
| 279 (float) 0.5 *(1 - (float) cos(2 * PI * i / (2 * hl + 2))); | |
| 280 } | |
| 281 wt[hl] = 0.0; /* for clarity, not used */ | |
| 282 for (i = 0; i < ENH_BLOCKL; i++) { | |
| 283 surround[i] = sseq[i] * wt[0]; | |
| 284 } | |
| 285 | |
| 286 | |
| 287 | |
| 288 | |
| 289 | |
| 290 for (k = 1; k < hl; k++) { | |
| 291 psseq = sseq + k * ENH_BLOCKL; | |
| 292 for (i = 0; i < ENH_BLOCKL; i++) { | |
| 293 surround[i] += psseq[i] * wt[k]; | |
| 294 } | |
| 295 } | |
| 296 for (k = hl + 1; k <= 2 * hl; k++) { | |
| 297 psseq = sseq + k * ENH_BLOCKL; | |
| 298 for (i = 0; i < ENH_BLOCKL; i++) { | |
| 299 surround[i] += psseq[i] * wt[k]; | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 /* compute some inner products */ | |
| 304 | |
| 305 w00 = w10 = w11 = 0.0; | |
| 306 psseq = sseq + hl * ENH_BLOCKL; /* current block */ | |
| 307 for (i = 0; i < ENH_BLOCKL; i++) { | |
| 308 w00 += psseq[i] * psseq[i]; | |
| 309 w11 += surround[i] * surround[i]; | |
| 310 w10 += surround[i] * psseq[i]; | |
| 311 } | |
| 312 | |
| 313 if (fabs(w11) < 1.0) { | |
| 314 w11 = 1.0; | |
| 315 } | |
| 316 C = (float) sqrt(w00 / w11); | |
| 317 | |
| 318 /* first try enhancement without power-constraint */ | |
| 319 | |
| 320 errs = 0.0; | |
| 321 psseq = sseq + hl * ENH_BLOCKL; | |
| 322 for (i = 0; i < ENH_BLOCKL; i++) { | |
| 323 odata[i] = C * surround[i]; | |
| 324 err = psseq[i] - odata[i]; | |
| 325 errs += err * err; | |
| 326 } | |
| 327 | |
| 328 /* if constraint violated by first try, add constraint */ | |
| 329 | |
| 330 if (errs > alpha0 * w00) { | |
| 331 if (w00 < 1) { | |
| 332 w00 = 1; | |
| 333 } | |
| 334 denom = (w11 * w00 - w10 * w10) / (w00 * w00); | |
| 335 | |
| 336 if (denom > 0.0001) { /* eliminates numerical problems | |
| 337 for if smooth */ | |
| 338 | |
| 339 | |
| 340 | |
| 341 | |
| 342 | |
| 343 A = (float) sqrt((alpha0 - alpha0 * alpha0 / 4) / denom); | |
| 344 B = -alpha0 / 2 - A * w10 / w00; | |
| 345 B = B + 1; | |
| 346 } else { /* essentially no difference between cycles; | |
| 347 smoothing not needed */ | |
| 348 A = 0.0; | |
| 349 B = 1.0; | |
| 350 } | |
| 351 | |
| 352 /* create smoothed sequence */ | |
| 353 | |
| 354 psseq = sseq + hl * ENH_BLOCKL; | |
| 355 for (i = 0; i < ENH_BLOCKL; i++) { | |
| 356 odata[i] = A * surround[i] + B * psseq[i]; | |
| 357 } | |
| 358 } | |
| 359 } | |
| 360 | |
| 361 /*----------------------------------------------------------------* | |
| 362 * get the pitch-synchronous sample sequence | |
| 363 *---------------------------------------------------------------*/ | |
| 364 | |
| 365 void getsseq(float *sseq, /* (o) the pitch-synchronous sequence */ | |
| 366 float *idata, /* (i) original data */ | |
| 367 int idatal, /* (i) dimension of data */ | |
| 368 int centerStartPos, /* (i) where current block starts */ | |
| 369 float *period, /* (i) rough-pitch-period array */ | |
| 370 float *plocs, /* (i) where periods of period array | |
| 371 are taken */ | |
| 372 int periodl, /* (i) dimension period array */ | |
| 373 int hl /* (i) 2*hl+1 is the number of sequences */ | |
| 374 ) | |
| 375 { | |
| 376 int i, centerEndPos, q; | |
| 377 float blockStartPos[2 * ENH_HL + 1]; | |
| 378 int lagBlock[2 * ENH_HL + 1]; | |
| 379 float plocs2[ENH_PLOCSL]; | |
| 380 float *psseq; | |
| 381 | |
| 382 centerEndPos = centerStartPos + ENH_BLOCKL - 1; | |
| 383 | |
| 384 /* present */ | |
| 385 | |
| 386 NearestNeighbor(lagBlock + hl, plocs, | |
| 387 (float) 0.5 * (centerStartPos + centerEndPos), periodl); | |
| 388 | |
| 389 blockStartPos[hl] = (float) centerStartPos; | |
| 390 | |
| 391 | |
| 392 | |
| 393 | |
| 394 | |
| 395 psseq = sseq + ENH_BLOCKL * hl; | |
| 396 memcpy(psseq, idata + centerStartPos, ENH_BLOCKL * sizeof(float)); | |
| 397 | |
| 398 /* past */ | |
| 399 | |
| 400 for (q = hl - 1; q >= 0; q--) { | |
| 401 blockStartPos[q] = blockStartPos[q + 1] - period[lagBlock[q + 1]]; | |
| 402 NearestNeighbor(lagBlock + q, plocs, | |
| 403 blockStartPos[q] + | |
| 404 ENH_BLOCKL_HALF - period[lagBlock[q + 1]], periodl); | |
| 405 | |
| 406 | |
| 407 if (blockStartPos[q] - ENH_OVERHANG >= 0) { | |
| 408 refiner(sseq + q * ENH_BLOCKL, blockStartPos + q, idata, | |
| 409 idatal, centerStartPos, blockStartPos[q], | |
| 410 period[lagBlock[q + 1]]); | |
| 411 } else { | |
| 412 psseq = sseq + q * ENH_BLOCKL; | |
| 413 memset(psseq, 0, ENH_BLOCKL * sizeof(float)); | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 /* future */ | |
| 418 | |
| 419 for (i = 0; i < periodl; i++) { | |
| 420 plocs2[i] = plocs[i] - period[i]; | |
| 421 } | |
| 422 for (q = hl + 1; q <= 2 * hl; q++) { | |
| 423 NearestNeighbor(lagBlock + q, plocs2, | |
| 424 blockStartPos[q - 1] + ENH_BLOCKL_HALF, periodl); | |
| 425 | |
| 426 blockStartPos[q] = blockStartPos[q - 1] + period[lagBlock[q]]; | |
| 427 if (blockStartPos[q] + ENH_BLOCKL + ENH_OVERHANG < idatal) { | |
| 428 refiner(sseq + ENH_BLOCKL * q, blockStartPos + q, idata, | |
| 429 idatal, centerStartPos, blockStartPos[q], period[lagBlock[q]]); | |
| 430 } else { | |
| 431 psseq = sseq + q * ENH_BLOCKL; | |
| 432 memset(psseq, 0, ENH_BLOCKL * sizeof(float)); | |
| 433 } | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 /*----------------------------------------------------------------* | |
| 438 * perform enhancement on idata+centerStartPos through | |
| 439 * idata+centerStartPos+ENH_BLOCKL-1 | |
| 440 *---------------------------------------------------------------*/ | |
| 441 | |
| 442 | |
| 443 | |
| 444 | |
| 445 | |
| 446 void enhancer(float *odata, /* (o) smoothed block, dimension blockl */ | |
| 447 float *idata, /* (i) data buffer used for enhancing */ | |
| 448 int idatal, /* (i) dimension idata */ | |
| 449 int centerStartPos, /* (i) first sample current block | |
| 450 within idata */ | |
| 451 float alpha0, /* (i) max correction-energy-fraction | |
| 452 (in [0,1]) */ | |
| 453 float *period, /* (i) pitch period array */ | |
| 454 float *plocs, /* (i) locations where period array | |
| 455 values valid */ | |
| 456 int periodl /* (i) dimension of period and plocs */ | |
| 457 ) | |
| 458 { | |
| 459 float sseq[(2 * ENH_HL + 1) * ENH_BLOCKL]; | |
| 460 | |
| 461 /* get said second sequence of segments */ | |
| 462 | |
| 463 getsseq(sseq, idata, idatal, centerStartPos, period, | |
| 464 plocs, periodl, ENH_HL); | |
| 465 | |
| 466 /* compute the smoothed output from said second sequence */ | |
| 467 | |
| 468 smath(odata, sseq, ENH_HL, alpha0); | |
| 469 | |
| 470 } | |
| 471 | |
| 472 /*----------------------------------------------------------------* | |
| 473 * cross correlation | |
| 474 *---------------------------------------------------------------*/ | |
| 475 | |
| 476 float xCorrCoef(float *target, /* (i) first array */ | |
| 477 float *regressor, /* (i) second array */ | |
| 478 int subl /* (i) dimension arrays */ | |
| 479 ) | |
| 480 { | |
| 481 int i; | |
| 482 float ftmp1, ftmp2; | |
| 483 | |
| 484 ftmp1 = 0.0; | |
| 485 ftmp2 = 0.0; | |
| 486 for (i = 0; i < subl; i++) { | |
| 487 ftmp1 += target[i] * regressor[i]; | |
| 488 ftmp2 += regressor[i] * regressor[i]; | |
| 489 } | |
| 490 | |
| 491 if (ftmp1 > 0.0) { | |
| 492 return (float) (ftmp1 * ftmp1 / ftmp2); | |
| 493 } | |
| 494 | |
| 495 | |
| 496 | |
| 497 | |
| 498 | |
| 499 else { | |
| 500 return (float) 0.0; | |
| 501 } | |
| 502 } | |
| 503 | |
| 504 /*----------------------------------------------------------------* | |
| 505 * interface for enhancer | |
| 506 *---------------------------------------------------------------*/ | |
| 507 | |
| 508 int enhancerInterface(float *out, /* (o) enhanced signal */ | |
| 509 float *in, /* (i) unenhanced signal */ | |
| 510 iLBC_Dec_Inst_t * iLBCdec_inst /* (i) buffers etc */ | |
| 511 ) | |
| 512 { | |
| 513 float *enh_buf, *enh_period; | |
| 514 int iblock, isample; | |
| 515 int lag = 0, ilag, i, ioffset; | |
| 516 float cc, maxcc; | |
| 517 float ftmp1, ftmp2; | |
| 518 float *inPtr, *enh_bufPtr1, *enh_bufPtr2; | |
| 519 float plc_pred[ENH_BLOCKL]; | |
| 520 | |
| 521 float lpState[6], downsampled[(ENH_NBLOCKS * ENH_BLOCKL + 120) / 2]; | |
| 522 int inLen = ENH_NBLOCKS * ENH_BLOCKL + 120; | |
| 523 int start, plc_blockl, inlag; | |
| 524 | |
| 525 enh_buf = iLBCdec_inst->enh_buf; | |
| 526 enh_period = iLBCdec_inst->enh_period; | |
| 527 | |
| 528 memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl], | |
| 529 (ENH_BUFL - iLBCdec_inst->blockl) * sizeof(float)); | |
| 530 | |
| 531 memcpy(&enh_buf[ENH_BUFL - iLBCdec_inst->blockl], in, | |
| 532 iLBCdec_inst->blockl * sizeof(float)); | |
| 533 | |
| 534 if (iLBCdec_inst->mode == 30) | |
| 535 plc_blockl = ENH_BLOCKL; | |
| 536 else | |
| 537 plc_blockl = 40; | |
| 538 | |
| 539 /* when 20 ms frame, move processing one block */ | |
| 540 ioffset = 0; | |
| 541 if (iLBCdec_inst->mode == 20) | |
| 542 ioffset = 1; | |
| 543 | |
| 544 i = 3 - ioffset; | |
| 545 memmove(enh_period, &enh_period[i], | |
| 546 (ENH_NBLOCKS_TOT - i) * sizeof(float)); | |
| 547 | |
| 548 | |
| 549 | |
| 550 | |
| 551 | |
| 552 | |
| 553 /* Set state information to the 6 samples right before | |
| 554 the samples to be downsampled. */ | |
| 555 | |
| 556 memcpy(lpState, | |
| 557 enh_buf + (ENH_NBLOCKS_EXTRA + ioffset) * ENH_BLOCKL - 126, | |
| 558 6 * sizeof(float)); | |
| 559 | |
| 560 /* Down sample a factor 2 to save computations */ | |
| 561 | |
| 562 DownSample(enh_buf + (ENH_NBLOCKS_EXTRA + ioffset) * ENH_BLOCKL - 120, | |
| 563 lpFilt_coefsTbl, inLen - ioffset * ENH_BLOCKL, | |
| 564 lpState, downsampled); | |
| 565 | |
| 566 /* Estimate the pitch in the down sampled domain. */ | |
| 567 for (iblock = 0; iblock < ENH_NBLOCKS - ioffset; iblock++) { | |
| 568 | |
| 569 lag = 10; | |
| 570 maxcc = xCorrCoef(downsampled + 60 + iblock * | |
| 571 ENH_BLOCKL_HALF, downsampled + 60 + iblock * | |
| 572 ENH_BLOCKL_HALF - lag, ENH_BLOCKL_HALF); | |
| 573 for (ilag = 11; ilag < 60; ilag++) { | |
| 574 cc = xCorrCoef(downsampled + 60 + iblock * | |
| 575 ENH_BLOCKL_HALF, downsampled + 60 + iblock * | |
| 576 ENH_BLOCKL_HALF - ilag, ENH_BLOCKL_HALF); | |
| 577 | |
| 578 if (cc > maxcc) { | |
| 579 maxcc = cc; | |
| 580 lag = ilag; | |
| 581 } | |
| 582 } | |
| 583 | |
| 584 /* Store the estimated lag in the non-downsampled domain */ | |
| 585 enh_period[iblock + ENH_NBLOCKS_EXTRA + ioffset] = (float) lag *2; | |
| 586 | |
| 587 | |
| 588 } | |
| 589 | |
| 590 | |
| 591 /* PLC was performed on the previous packet */ | |
| 592 if (iLBCdec_inst->prev_enh_pl == 1) { | |
| 593 | |
| 594 inlag = (int) enh_period[ENH_NBLOCKS_EXTRA + ioffset]; | |
| 595 | |
| 596 lag = inlag - 1; | |
| 597 maxcc = xCorrCoef(in, in + lag, plc_blockl); | |
| 598 for (ilag = inlag; ilag <= inlag + 1; ilag++) { | |
| 599 cc = xCorrCoef(in, in + ilag, plc_blockl); | |
| 600 | |
| 601 | |
| 602 | |
| 603 | |
| 604 | |
| 605 | |
| 606 if (cc > maxcc) { | |
| 607 maxcc = cc; | |
| 608 lag = ilag; | |
| 609 } | |
| 610 } | |
| 611 | |
| 612 enh_period[ENH_NBLOCKS_EXTRA + ioffset - 1] = (float) lag; | |
| 613 | |
| 614 /* compute new concealed residual for the old lookahead, | |
| 615 mix the forward PLC with a backward PLC from | |
| 616 the new frame */ | |
| 617 | |
| 618 inPtr = &in[lag - 1]; | |
| 619 | |
| 620 enh_bufPtr1 = &plc_pred[plc_blockl - 1]; | |
| 621 | |
| 622 if (lag > plc_blockl) { | |
| 623 start = plc_blockl; | |
| 624 } else { | |
| 625 start = lag; | |
| 626 } | |
| 627 | |
| 628 for (isample = start; isample > 0; isample--) { | |
| 629 *enh_bufPtr1-- = *inPtr--; | |
| 630 } | |
| 631 | |
| 632 enh_bufPtr2 = &enh_buf[ENH_BUFL - 1 - iLBCdec_inst->blockl]; | |
| 633 for (isample = (plc_blockl - 1 - lag); isample >= 0; isample--) { | |
| 634 *enh_bufPtr1-- = *enh_bufPtr2--; | |
| 635 } | |
| 636 | |
| 637 /* limit energy change */ | |
| 638 ftmp2 = 0.0; | |
| 639 ftmp1 = 0.0; | |
| 640 for (i = 0; i < plc_blockl; i++) { | |
| 641 ftmp2 += enh_buf[ENH_BUFL - 1 - iLBCdec_inst->blockl - i] * | |
| 642 enh_buf[ENH_BUFL - 1 - iLBCdec_inst->blockl - i]; | |
| 643 ftmp1 += plc_pred[i] * plc_pred[i]; | |
| 644 } | |
| 645 ftmp1 = (float) sqrt(ftmp1 / (float) plc_blockl); | |
| 646 ftmp2 = (float) sqrt(ftmp2 / (float) plc_blockl); | |
| 647 if (ftmp1 > (float) 2.0 * ftmp2 && ftmp1 > 0.0) { | |
| 648 for (i = 0; i < plc_blockl - 10; i++) { | |
| 649 plc_pred[i] *= (float) 2.0 *ftmp2 / ftmp1; | |
| 650 } | |
| 651 for (i = plc_blockl - 10; i < plc_blockl; i++) { | |
| 652 plc_pred[i] *= (float) (i - plc_blockl + 10) * | |
| 653 ((float) 1.0 - (float) 2.0 * ftmp2 / ftmp1) / (float) (10) + | |
| 654 (float) 2.0 *ftmp2 / ftmp1; | |
| 655 } | |
| 656 } | |
| 657 | |
| 658 enh_bufPtr1 = &enh_buf[ENH_BUFL - 1 - iLBCdec_inst->blockl]; | |
| 659 for (i = 0; i < plc_blockl; i++) { | |
| 660 ftmp1 = (float) (i + 1) / (float) (plc_blockl + 1); | |
| 661 *enh_bufPtr1 *= ftmp1; | |
| 662 *enh_bufPtr1 += ((float) 1.0 - ftmp1) * | |
| 663 plc_pred[plc_blockl - 1 - i]; | |
| 664 enh_bufPtr1--; | |
| 665 } | |
| 666 } | |
| 667 | |
| 668 if (iLBCdec_inst->mode == 20) { | |
| 669 /* Enhancer with 40 samples delay */ | |
| 670 for (iblock = 0; iblock < 2; iblock++) { | |
| 671 enhancer(out + iblock * ENH_BLOCKL, enh_buf, | |
| 672 ENH_BUFL, (5 + iblock) * ENH_BLOCKL + 40, | |
| 673 ENH_ALPHA0, enh_period, enh_plocsTbl, ENH_NBLOCKS_TOT); | |
| 674 } | |
| 675 } else if (iLBCdec_inst->mode == 30) { | |
| 676 /* Enhancer with 80 samples delay */ | |
| 677 for (iblock = 0; iblock < 3; iblock++) { | |
| 678 enhancer(out + iblock * ENH_BLOCKL, enh_buf, | |
| 679 ENH_BUFL, (4 + iblock) * ENH_BLOCKL, | |
| 680 ENH_ALPHA0, enh_period, enh_plocsTbl, ENH_NBLOCKS_TOT); | |
| 681 } | |
| 682 } | |
| 683 | |
| 684 return (lag * 2); | |
| 685 } |
