Mercurial > hg > audiostuff
comparison intercom/ilbc/iCBSearch.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 iCBSearch.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 | |
| 16 #include "iLBC_define.h" | |
| 17 #include "gainquant.h" | |
| 18 #include "createCB.h" | |
| 19 #include "filter.h" | |
| 20 #include "constants.h" | |
| 21 | |
| 22 /*----------------------------------------------------------------* | |
| 23 * Search routine for codebook encoding and gain quantization. | |
| 24 *---------------------------------------------------------------*/ | |
| 25 | |
| 26 void iCBSearch(iLBC_Enc_Inst_t * iLBCenc_inst, | |
| 27 /* (i) the encoder state structure */ | |
| 28 int *index, /* (o) Codebook indices */ | |
| 29 int *gain_index, /* (o) Gain quantization indices */ | |
| 30 float *intarget, /* (i) Target vector for encoding */ | |
| 31 float *mem, /* (i) Buffer for codebook construction */ | |
| 32 int lMem, /* (i) Length of buffer */ | |
| 33 int lTarget, /* (i) Length of vector */ | |
| 34 int nStages, /* (i) Number of codebook stages */ | |
| 35 float *weightDenum, /* (i) weighting filter coefficients */ | |
| 36 float *weightState, /* (i) weighting filter state */ | |
| 37 int block /* (i) the sub-block number */ | |
| 38 ) | |
| 39 { | |
| 40 int i, j, icount, stage, best_index, range, counter; | |
| 41 float max_measure, gain, measure, crossDot, ftmp; | |
| 42 float gains[CB_NSTAGES]; | |
| 43 float target[SUBL]; | |
| 44 int base_index, sInd, eInd, base_size; | |
| 45 int sIndAug = 0, eIndAug = 0; | |
| 46 float buf[CB_MEML + SUBL + 2 * LPC_FILTERORDER]; | |
| 47 float invenergy[CB_EXPAND * 128], energy[CB_EXPAND * 128]; | |
| 48 float *pp, *ppi = 0, *ppo = 0, *ppe = 0; | |
| 49 float cbvectors[CB_MEML]; | |
| 50 float tene, cene, cvec[SUBL]; | |
| 51 float aug_vec[SUBL]; | |
| 52 | |
| 53 memset(cvec, 0, SUBL * sizeof(float)); | |
| 54 | |
| 55 /* Determine size of codebook sections */ | |
| 56 | |
| 57 base_size = lMem - lTarget + 1; | |
| 58 | |
| 59 if (lTarget == SUBL) { | |
| 60 base_size = lMem - lTarget + 1 + lTarget / 2; | |
| 61 } | |
| 62 | |
| 63 /* setup buffer for weighting */ | |
| 64 | |
| 65 memcpy(buf, weightState, sizeof(float) * LPC_FILTERORDER); | |
| 66 memcpy(buf + LPC_FILTERORDER, mem, lMem * sizeof(float)); | |
| 67 memcpy(buf + LPC_FILTERORDER + lMem, intarget, | |
| 68 lTarget * sizeof(float)); | |
| 69 | |
| 70 /* weighting */ | |
| 71 | |
| 72 AllPoleFilter(buf + LPC_FILTERORDER, weightDenum, | |
| 73 lMem + lTarget, LPC_FILTERORDER); | |
| 74 | |
| 75 /* Construct the codebook and target needed */ | |
| 76 | |
| 77 memcpy(target, buf + LPC_FILTERORDER + lMem, lTarget * sizeof(float)); | |
| 78 | |
| 79 tene = 0.0; | |
| 80 | |
| 81 | |
| 82 | |
| 83 | |
| 84 | |
| 85 for (i = 0; i < lTarget; i++) { | |
| 86 tene += target[i] * target[i]; | |
| 87 } | |
| 88 | |
| 89 /* Prepare search over one more codebook section. This section | |
| 90 is created by filtering the original buffer with a filter. */ | |
| 91 | |
| 92 filteredCBvecs(cbvectors, buf + LPC_FILTERORDER, lMem); | |
| 93 | |
| 94 /* The Main Loop over stages */ | |
| 95 | |
| 96 for (stage = 0; stage < nStages; stage++) { | |
| 97 | |
| 98 range = search_rangeTbl[block][stage]; | |
| 99 | |
| 100 /* initialize search measure */ | |
| 101 | |
| 102 max_measure = (float) -10000000.0; | |
| 103 gain = (float) 0.0; | |
| 104 best_index = 0; | |
| 105 | |
| 106 /* Compute cross dot product between the target | |
| 107 and the CB memory */ | |
| 108 | |
| 109 crossDot = 0.0; | |
| 110 pp = buf + LPC_FILTERORDER + lMem - lTarget; | |
| 111 for (j = 0; j < lTarget; j++) { | |
| 112 crossDot += target[j] * (*pp++); | |
| 113 } | |
| 114 | |
| 115 if (stage == 0) { | |
| 116 | |
| 117 /* Calculate energy in the first block of | |
| 118 'lTarget' samples. */ | |
| 119 ppe = energy; | |
| 120 ppi = buf + LPC_FILTERORDER + lMem - lTarget - 1; | |
| 121 ppo = buf + LPC_FILTERORDER + lMem - 1; | |
| 122 | |
| 123 *ppe = 0.0; | |
| 124 pp = buf + LPC_FILTERORDER + lMem - lTarget; | |
| 125 for (j = 0; j < lTarget; j++, pp++) { | |
| 126 *ppe += (*pp) * (*pp); | |
| 127 } | |
| 128 | |
| 129 if (*ppe > 0.0) { | |
| 130 invenergy[0] = (float) 1.0 / (*ppe + EPS); | |
| 131 } else { | |
| 132 invenergy[0] = (float) 0.0; | |
| 133 | |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 } | |
| 139 ppe++; | |
| 140 | |
| 141 measure = (float) -10000000.0; | |
| 142 | |
| 143 if (crossDot > 0.0) { | |
| 144 measure = crossDot * crossDot * invenergy[0]; | |
| 145 } | |
| 146 } else { | |
| 147 measure = crossDot * crossDot * invenergy[0]; | |
| 148 } | |
| 149 | |
| 150 /* check if measure is better */ | |
| 151 ftmp = crossDot * invenergy[0]; | |
| 152 | |
| 153 if ((measure > max_measure) && (fabs(ftmp) < CB_MAXGAIN)) { | |
| 154 best_index = 0; | |
| 155 max_measure = measure; | |
| 156 gain = ftmp; | |
| 157 } | |
| 158 | |
| 159 /* loop over the main first codebook section, | |
| 160 full search */ | |
| 161 | |
| 162 for (icount = 1; icount < range; icount++) { | |
| 163 | |
| 164 /* calculate measure */ | |
| 165 | |
| 166 crossDot = 0.0; | |
| 167 pp = buf + LPC_FILTERORDER + lMem - lTarget - icount; | |
| 168 | |
| 169 for (j = 0; j < lTarget; j++) { | |
| 170 crossDot += target[j] * (*pp++); | |
| 171 } | |
| 172 | |
| 173 if (stage == 0) { | |
| 174 *ppe++ = energy[icount - 1] + (*ppi) * (*ppi) - (*ppo) * (*ppo); | |
| 175 ppo--; | |
| 176 ppi--; | |
| 177 | |
| 178 if (energy[icount] > 0.0) { | |
| 179 invenergy[icount] = (float) 1.0 / (energy[icount] + EPS); | |
| 180 } else { | |
| 181 invenergy[icount] = (float) 0.0; | |
| 182 } | |
| 183 | |
| 184 | |
| 185 | |
| 186 | |
| 187 | |
| 188 measure = (float) -10000000.0; | |
| 189 | |
| 190 if (crossDot > 0.0) { | |
| 191 measure = crossDot * crossDot * invenergy[icount]; | |
| 192 } | |
| 193 } else { | |
| 194 measure = crossDot * crossDot * invenergy[icount]; | |
| 195 } | |
| 196 | |
| 197 /* check if measure is better */ | |
| 198 ftmp = crossDot * invenergy[icount]; | |
| 199 | |
| 200 if ((measure > max_measure) && (fabs(ftmp) < CB_MAXGAIN)) { | |
| 201 best_index = icount; | |
| 202 max_measure = measure; | |
| 203 gain = ftmp; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 /* Loop over augmented part in the first codebook | |
| 208 * section, full search. | |
| 209 * The vectors are interpolated. | |
| 210 */ | |
| 211 | |
| 212 if (lTarget == SUBL) { | |
| 213 | |
| 214 /* Search for best possible cb vector and | |
| 215 compute the CB-vectors' energy. */ | |
| 216 searchAugmentedCB(20, 39, stage, base_size - lTarget / 2, | |
| 217 target, buf + LPC_FILTERORDER + lMem, | |
| 218 &max_measure, &best_index, &gain, energy, invenergy); | |
| 219 } | |
| 220 | |
| 221 /* set search range for following codebook sections */ | |
| 222 | |
| 223 base_index = best_index; | |
| 224 | |
| 225 /* unrestricted search */ | |
| 226 | |
| 227 if (CB_RESRANGE == -1) { | |
| 228 sInd = 0; | |
| 229 eInd = range - 1; | |
| 230 sIndAug = 20; | |
| 231 eIndAug = 39; | |
| 232 } | |
| 233 | |
| 234 | |
| 235 | |
| 236 | |
| 237 | |
| 238 | |
| 239 /* restricted search around best index from first | |
| 240 codebook section */ | |
| 241 | |
| 242 else { | |
| 243 /* Initialize search indices */ | |
| 244 sIndAug = 0; | |
| 245 eIndAug = 0; | |
| 246 sInd = base_index - CB_RESRANGE / 2; | |
| 247 eInd = sInd + CB_RESRANGE; | |
| 248 | |
| 249 if (lTarget == SUBL) { | |
| 250 | |
| 251 if (sInd < 0) { | |
| 252 | |
| 253 sIndAug = 40 + sInd; | |
| 254 eIndAug = 39; | |
| 255 sInd = 0; | |
| 256 | |
| 257 } else if (base_index < (base_size - 20)) { | |
| 258 | |
| 259 if (eInd > range) { | |
| 260 sInd -= (eInd - range); | |
| 261 eInd = range; | |
| 262 } | |
| 263 } else { /* base_index >= (base_size-20) */ | |
| 264 | |
| 265 if (sInd < (base_size - 20)) { | |
| 266 sIndAug = 20; | |
| 267 sInd = 0; | |
| 268 eInd = 0; | |
| 269 eIndAug = 19 + CB_RESRANGE; | |
| 270 | |
| 271 if (eIndAug > 39) { | |
| 272 eInd = eIndAug - 39; | |
| 273 eIndAug = 39; | |
| 274 } | |
| 275 } else { | |
| 276 sIndAug = 20 + sInd - (base_size - 20); | |
| 277 eIndAug = 39; | |
| 278 sInd = 0; | |
| 279 eInd = CB_RESRANGE - (eIndAug - sIndAug + 1); | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 } else { /* lTarget = 22 or 23 */ | |
| 284 | |
| 285 if (sInd < 0) { | |
| 286 eInd -= sInd; | |
| 287 | |
| 288 | |
| 289 | |
| 290 | |
| 291 | |
| 292 sInd = 0; | |
| 293 } | |
| 294 | |
| 295 if (eInd > range) { | |
| 296 sInd -= (eInd - range); | |
| 297 eInd = range; | |
| 298 } | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 /* search of higher codebook section */ | |
| 303 | |
| 304 /* index search range */ | |
| 305 counter = sInd; | |
| 306 sInd += base_size; | |
| 307 eInd += base_size; | |
| 308 | |
| 309 | |
| 310 if (stage == 0) { | |
| 311 ppe = energy + base_size; | |
| 312 *ppe = 0.0; | |
| 313 | |
| 314 pp = cbvectors + lMem - lTarget; | |
| 315 for (j = 0; j < lTarget; j++, pp++) { | |
| 316 *ppe += (*pp) * (*pp); | |
| 317 } | |
| 318 | |
| 319 ppi = cbvectors + lMem - 1 - lTarget; | |
| 320 ppo = cbvectors + lMem - 1; | |
| 321 | |
| 322 for (j = 0; j < (range - 1); j++) { | |
| 323 *(ppe + 1) = *ppe + (*ppi) * (*ppi) - (*ppo) * (*ppo); | |
| 324 ppo--; | |
| 325 ppi--; | |
| 326 ppe++; | |
| 327 } | |
| 328 } | |
| 329 | |
| 330 /* loop over search range */ | |
| 331 | |
| 332 for (icount = sInd; icount < eInd; icount++) { | |
| 333 | |
| 334 /* calculate measure */ | |
| 335 | |
| 336 crossDot = 0.0; | |
| 337 pp = cbvectors + lMem - (counter++) - lTarget; | |
| 338 | |
| 339 for (j = 0; j < lTarget; j++) { | |
| 340 | |
| 341 | |
| 342 | |
| 343 | |
| 344 | |
| 345 crossDot += target[j] * (*pp++); | |
| 346 } | |
| 347 | |
| 348 if (energy[icount] > 0.0) { | |
| 349 invenergy[icount] = (float) 1.0 / (energy[icount] + EPS); | |
| 350 } else { | |
| 351 invenergy[icount] = (float) 0.0; | |
| 352 } | |
| 353 | |
| 354 if (stage == 0) { | |
| 355 | |
| 356 measure = (float) -10000000.0; | |
| 357 | |
| 358 if (crossDot > 0.0) { | |
| 359 measure = crossDot * crossDot * invenergy[icount]; | |
| 360 } | |
| 361 } else { | |
| 362 measure = crossDot * crossDot * invenergy[icount]; | |
| 363 } | |
| 364 | |
| 365 /* check if measure is better */ | |
| 366 ftmp = crossDot * invenergy[icount]; | |
| 367 | |
| 368 if ((measure > max_measure) && (fabs(ftmp) < CB_MAXGAIN)) { | |
| 369 best_index = icount; | |
| 370 max_measure = measure; | |
| 371 gain = ftmp; | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 /* Search the augmented CB inside the limited range. */ | |
| 376 | |
| 377 if ((lTarget == SUBL) && (sIndAug != 0)) { | |
| 378 searchAugmentedCB(sIndAug, eIndAug, stage, | |
| 379 2 * base_size - 20, target, cbvectors + lMem, | |
| 380 &max_measure, &best_index, &gain, energy, invenergy); | |
| 381 } | |
| 382 | |
| 383 /* record best index */ | |
| 384 | |
| 385 index[stage] = best_index; | |
| 386 | |
| 387 /* gain quantization */ | |
| 388 | |
| 389 if (stage == 0) { | |
| 390 | |
| 391 | |
| 392 | |
| 393 | |
| 394 | |
| 395 | |
| 396 if (gain < 0.0) { | |
| 397 gain = 0.0; | |
| 398 } | |
| 399 | |
| 400 if (gain > CB_MAXGAIN) { | |
| 401 gain = (float) CB_MAXGAIN; | |
| 402 } | |
| 403 gain = gainquant(gain, 1.0, 32, &gain_index[stage]); | |
| 404 } else { | |
| 405 if (stage == 1) { | |
| 406 gain = gainquant(gain, (float) fabs(gains[stage - 1]), | |
| 407 16, &gain_index[stage]); | |
| 408 } else { | |
| 409 gain = gainquant(gain, (float) fabs(gains[stage - 1]), | |
| 410 8, &gain_index[stage]); | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 /* Extract the best (according to measure) | |
| 415 codebook vector */ | |
| 416 | |
| 417 if (lTarget == (STATE_LEN - iLBCenc_inst->state_short_len)) { | |
| 418 | |
| 419 if (index[stage] < base_size) { | |
| 420 pp = buf + LPC_FILTERORDER + lMem - lTarget - index[stage]; | |
| 421 } else { | |
| 422 pp = cbvectors + lMem - lTarget - index[stage] + base_size; | |
| 423 } | |
| 424 } else { | |
| 425 | |
| 426 if (index[stage] < base_size) { | |
| 427 if (index[stage] < (base_size - 20)) { | |
| 428 pp = buf + LPC_FILTERORDER + lMem - lTarget - index[stage]; | |
| 429 } else { | |
| 430 createAugmentedVec(index[stage] - base_size + 40, | |
| 431 buf + LPC_FILTERORDER + lMem, aug_vec); | |
| 432 pp = aug_vec; | |
| 433 } | |
| 434 } else { | |
| 435 int filterno, position; | |
| 436 | |
| 437 filterno = index[stage] / base_size; | |
| 438 position = index[stage] - filterno * base_size; | |
| 439 | |
| 440 | |
| 441 | |
| 442 | |
| 443 | |
| 444 | |
| 445 | |
| 446 if (position < (base_size - 20)) { | |
| 447 pp = cbvectors + filterno * lMem - lTarget - | |
| 448 index[stage] + filterno * base_size; | |
| 449 } else { | |
| 450 createAugmentedVec(index[stage] - (filterno + 1) * base_size + | |
| 451 40, cbvectors + filterno * lMem, aug_vec); | |
| 452 pp = aug_vec; | |
| 453 } | |
| 454 } | |
| 455 } | |
| 456 | |
| 457 /* Subtract the best codebook vector, according | |
| 458 to measure, from the target vector */ | |
| 459 | |
| 460 for (j = 0; j < lTarget; j++) { | |
| 461 cvec[j] += gain * (*pp); | |
| 462 target[j] -= gain * (*pp++); | |
| 463 } | |
| 464 | |
| 465 /* record quantized gain */ | |
| 466 | |
| 467 gains[stage] = gain; | |
| 468 | |
| 469 } /* end of Main Loop. for (stage=0;... */ | |
| 470 | |
| 471 /* Gain adjustment for energy matching */ | |
| 472 cene = 0.0; | |
| 473 for (i = 0; i < lTarget; i++) { | |
| 474 cene += cvec[i] * cvec[i]; | |
| 475 } | |
| 476 j = gain_index[0]; | |
| 477 | |
| 478 for (i = gain_index[0]; i < 32; i++) { | |
| 479 ftmp = cene * gain_sq5Tbl[i] * gain_sq5Tbl[i]; | |
| 480 | |
| 481 if ((ftmp < (tene * gains[0] * gains[0])) && | |
| 482 (gain_sq5Tbl[j] < (2.0 * gains[0]))) { | |
| 483 j = i; | |
| 484 } | |
| 485 } | |
| 486 gain_index[0] = j; | |
| 487 } |
