iCBSearch.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /******************************************************************
  2. iLBC Speech Coder ANSI-C Source Code
  3. iCBSearch.c
  4. Copyright (C) The Internet Society (2004).
  5. All Rights Reserved.
  6. ******************************************************************/
  7. #include <math.h>
  8. #include <string.h>
  9. #include "iLBC_define.h"
  10. #include "gainquant.h"
  11. #include "createCB.h"
  12. #include "filter.h"
  13. #include "constants.h"
  14. /*----------------------------------------------------------------*
  15. * Search routine for codebook encoding and gain quantization.
  16. *---------------------------------------------------------------*/
  17. void iCBSearch(
  18. iLBC_Enc_Inst_t *iLBCenc_inst,
  19. /* (i) the encoder state structure */
  20. int *index, /* (o) Codebook indices */
  21. int *gain_index,/* (o) Gain quantization indices */
  22. float *intarget,/* (i) Target vector for encoding */
  23. float *mem, /* (i) Buffer for codebook construction */
  24. int lMem, /* (i) Length of buffer */
  25. int lTarget, /* (i) Length of vector */
  26. int nStages, /* (i) Number of codebook stages */
  27. float *weightDenum, /* (i) weighting filter coefficients */
  28. float *weightState, /* (i) weighting filter state */
  29. int block /* (i) the sub-block number */
  30. ){
  31. int i, j, icount, stage, best_index, range, counter;
  32. float max_measure, gain, measure, crossDot, ftmp;
  33. float gains[CB_NSTAGES];
  34. float target[SUBL];
  35. int base_index, sInd, eInd, base_size;
  36. int sIndAug=0, eIndAug=0;
  37. float buf[CB_MEML+SUBL+2*LPC_FILTERORDER];
  38. float invenergy[CB_EXPAND*128], energy[CB_EXPAND*128];
  39. float *pp, *ppi=0, *ppo=0, *ppe=0;
  40. float cbvectors[CB_MEML];
  41. float tene, cene, cvec[SUBL];
  42. float aug_vec[SUBL];
  43. memset(cvec,0,SUBL*sizeof(float));
  44. /* Determine size of codebook sections */
  45. base_size=lMem-lTarget+1;
  46. if (lTarget==SUBL) {
  47. base_size=lMem-lTarget+1+lTarget/2;
  48. }
  49. /* setup buffer for weighting */
  50. memcpy(buf,weightState,sizeof(float)*LPC_FILTERORDER);
  51. memcpy(buf+LPC_FILTERORDER,mem,lMem*sizeof(float));
  52. memcpy(buf+LPC_FILTERORDER+lMem,intarget,lTarget*sizeof(float));
  53. /* weighting */
  54. AllPoleFilter(buf+LPC_FILTERORDER, weightDenum,
  55. lMem+lTarget, LPC_FILTERORDER);
  56. /* Construct the codebook and target needed */
  57. memcpy(target, buf+LPC_FILTERORDER+lMem, lTarget*sizeof(float));
  58. tene=0.0;
  59. for (i=0; i<lTarget; i++) {
  60. tene+=target[i]*target[i];
  61. }
  62. /* Prepare search over one more codebook section. This section
  63. is created by filtering the original buffer with a filter. */
  64. filteredCBvecs(cbvectors, buf+LPC_FILTERORDER, lMem);
  65. /* The Main Loop over stages */
  66. for (stage=0; stage<nStages; stage++) {
  67. range = search_rangeTbl[block][stage];
  68. /* initialize search measure */
  69. max_measure = (float)-10000000.0;
  70. gain = (float)0.0;
  71. best_index = 0;
  72. /* Compute cross dot product between the target
  73. and the CB memory */
  74. crossDot=0.0;
  75. pp=buf+LPC_FILTERORDER+lMem-lTarget;
  76. for (j=0; j<lTarget; j++) {
  77. crossDot += target[j]*(*pp++);
  78. }
  79. if (stage==0) {
  80. /* Calculate energy in the first block of
  81. 'lTarget' samples. */
  82. ppe = energy;
  83. ppi = buf+LPC_FILTERORDER+lMem-lTarget-1;
  84. ppo = buf+LPC_FILTERORDER+lMem-1;
  85. *ppe=0.0;
  86. pp=buf+LPC_FILTERORDER+lMem-lTarget;
  87. for (j=0; j<lTarget; j++) {
  88. *ppe+=(*pp)*(*pp);
  89. ++pp;
  90. }
  91. if (*ppe>0.0) {
  92. invenergy[0] = (float) 1.0 / (*ppe + EPS);
  93. } else {
  94. invenergy[0] = (float) 0.0;
  95. }
  96. ppe++;
  97. measure=(float)-10000000.0;
  98. if (crossDot > 0.0) {
  99. measure = crossDot*crossDot*invenergy[0];
  100. }
  101. }
  102. else {
  103. measure = crossDot*crossDot*invenergy[0];
  104. }
  105. /* check if measure is better */
  106. ftmp = crossDot*invenergy[0];
  107. if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
  108. best_index = 0;
  109. max_measure = measure;
  110. gain = ftmp;
  111. }
  112. /* loop over the main first codebook section,
  113. full search */
  114. for (icount=1; icount<range; icount++) {
  115. /* calculate measure */
  116. crossDot=0.0;
  117. pp = buf+LPC_FILTERORDER+lMem-lTarget-icount;
  118. for (j=0; j<lTarget; j++) {
  119. crossDot += target[j]*(*pp++);
  120. }
  121. if (stage==0) {
  122. *ppe++ = energy[icount-1] + (*ppi)*(*ppi) -
  123. (*ppo)*(*ppo);
  124. ppo--;
  125. ppi--;
  126. if (energy[icount]>0.0) {
  127. invenergy[icount] =
  128. (float)1.0/(energy[icount]+EPS);
  129. } else {
  130. invenergy[icount] = (float) 0.0;
  131. }
  132. measure=(float)-10000000.0;
  133. if (crossDot > 0.0) {
  134. measure = crossDot*crossDot*invenergy[icount];
  135. }
  136. }
  137. else {
  138. measure = crossDot*crossDot*invenergy[icount];
  139. }
  140. /* check if measure is better */
  141. ftmp = crossDot*invenergy[icount];
  142. if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
  143. best_index = icount;
  144. max_measure = measure;
  145. gain = ftmp;
  146. }
  147. }
  148. /* Loop over augmented part in the first codebook
  149. * section, full search.
  150. * The vectors are interpolated.
  151. */
  152. if (lTarget==SUBL) {
  153. /* Search for best possible cb vector and
  154. compute the CB-vectors' energy. */
  155. searchAugmentedCB(20, 39, stage, base_size-lTarget/2,
  156. target, buf+LPC_FILTERORDER+lMem,
  157. &max_measure, &best_index, &gain, energy,
  158. invenergy);
  159. }
  160. /* set search range for following codebook sections */
  161. base_index=best_index;
  162. /* unrestricted search */
  163. # if CB_RESRANGE == -1
  164. //if (CB_RESRANGE == -1) {
  165. sInd=0;
  166. eInd=range-1;
  167. sIndAug=20;
  168. eIndAug=39;
  169. //}
  170. # else
  171. /* restricted search around best index from first
  172. codebook section */
  173. //else {
  174. /* Initialize search indices */
  175. sIndAug=0;
  176. eIndAug=0;
  177. sInd=base_index-CB_RESRANGE/2;
  178. eInd=sInd+CB_RESRANGE;
  179. if (lTarget==SUBL) {
  180. if (sInd<0) {
  181. sIndAug = 40 + sInd;
  182. eIndAug = 39;
  183. sInd=0;
  184. } else if ( base_index < (base_size-20) ) {
  185. if (eInd > range) {
  186. sInd -= (eInd-range);
  187. eInd = range;
  188. }
  189. } else { /* base_index >= (base_size-20) */
  190. if (sInd < (base_size-20)) {
  191. sIndAug = 20;
  192. sInd = 0;
  193. eInd = 0;
  194. eIndAug = 19 + CB_RESRANGE;
  195. if(eIndAug > 39) {
  196. eInd = eIndAug-39;
  197. eIndAug = 39;
  198. }
  199. } else {
  200. sIndAug = 20 + sInd - (base_size-20);
  201. eIndAug = 39;
  202. sInd = 0;
  203. eInd = CB_RESRANGE - (eIndAug-sIndAug+1);
  204. }
  205. }
  206. } else { /* lTarget = 22 or 23 */
  207. if (sInd < 0) {
  208. eInd -= sInd;
  209. sInd = 0;
  210. }
  211. if(eInd > range) {
  212. sInd -= (eInd - range);
  213. eInd = range;
  214. }
  215. }
  216. //}
  217. # endif /* CB_RESRANGE == -1 */
  218. /* search of higher codebook section */
  219. /* index search range */
  220. counter = sInd;
  221. sInd += base_size;
  222. eInd += base_size;
  223. if (stage==0) {
  224. ppe = energy+base_size;
  225. *ppe=0.0;
  226. pp=cbvectors+lMem-lTarget;
  227. for (j=0; j<lTarget; j++) {
  228. *ppe+=(*pp)*(*pp);
  229. ++pp;
  230. }
  231. ppi = cbvectors + lMem - 1 - lTarget;
  232. ppo = cbvectors + lMem - 1;
  233. for (j=0; j<(range-1); j++) {
  234. *(ppe+1) = *ppe + (*ppi)*(*ppi) - (*ppo)*(*ppo);
  235. ppo--;
  236. ppi--;
  237. ppe++;
  238. }
  239. }
  240. /* loop over search range */
  241. for (icount=sInd; icount<eInd; icount++) {
  242. /* calculate measure */
  243. crossDot=0.0;
  244. pp=cbvectors + lMem - (counter++) - lTarget;
  245. for (j=0;j<lTarget;j++) {
  246. crossDot += target[j]*(*pp++);
  247. }
  248. if (energy[icount]>0.0) {
  249. invenergy[icount] =(float)1.0/(energy[icount]+EPS);
  250. } else {
  251. invenergy[icount] =(float)0.0;
  252. }
  253. if (stage==0) {
  254. measure=(float)-10000000.0;
  255. if (crossDot > 0.0) {
  256. measure = crossDot*crossDot*
  257. invenergy[icount];
  258. }
  259. }
  260. else {
  261. measure = crossDot*crossDot*invenergy[icount];
  262. }
  263. /* check if measure is better */
  264. ftmp = crossDot*invenergy[icount];
  265. if ((measure>max_measure) && (fabs(ftmp)<CB_MAXGAIN)) {
  266. best_index = icount;
  267. max_measure = measure;
  268. gain = ftmp;
  269. }
  270. }
  271. /* Search the augmented CB inside the limited range. */
  272. if ((lTarget==SUBL)&&(sIndAug!=0)) {
  273. searchAugmentedCB(sIndAug, eIndAug, stage,
  274. 2*base_size-20, target, cbvectors+lMem,
  275. &max_measure, &best_index, &gain, energy,
  276. invenergy);
  277. }
  278. /* record best index */
  279. index[stage] = best_index;
  280. /* gain quantization */
  281. if (stage==0){
  282. if (gain<0.0){
  283. gain = 0.0;
  284. }
  285. if (gain>CB_MAXGAIN) {
  286. gain = (float)CB_MAXGAIN;
  287. }
  288. gain = gainquant(gain, 1.0, 32, &gain_index[stage]);
  289. }
  290. else {
  291. if (stage==1) {
  292. gain = gainquant(gain, (float)fabs(gains[stage-1]),
  293. 16, &gain_index[stage]);
  294. } else {
  295. gain = gainquant(gain, (float)fabs(gains[stage-1]),
  296. 8, &gain_index[stage]);
  297. }
  298. }
  299. /* Extract the best (according to measure)
  300. codebook vector */
  301. if (lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
  302. if (index[stage]<base_size) {
  303. pp=buf+LPC_FILTERORDER+lMem-lTarget-index[stage];
  304. } else {
  305. pp=cbvectors+lMem-lTarget-
  306. index[stage]+base_size;
  307. }
  308. } else {
  309. if (index[stage]<base_size) {
  310. if (index[stage]<(base_size-20)) {
  311. pp=buf+LPC_FILTERORDER+lMem-
  312. lTarget-index[stage];
  313. } else {
  314. createAugmentedVec(index[stage]-base_size+40,
  315. buf+LPC_FILTERORDER+lMem,aug_vec);
  316. pp=aug_vec;
  317. }
  318. } else {
  319. int filterno, position;
  320. filterno=index[stage]/base_size;
  321. position=index[stage]-filterno*base_size;
  322. if (position<(base_size-20)) {
  323. pp=cbvectors+filterno*lMem-lTarget-
  324. index[stage]+filterno*base_size;
  325. } else {
  326. createAugmentedVec(
  327. index[stage]-(filterno+1)*base_size+40,
  328. cbvectors+filterno*lMem,aug_vec);
  329. pp=aug_vec;
  330. }
  331. }
  332. }
  333. /* Subtract the best codebook vector, according
  334. to measure, from the target vector */
  335. for (j=0;j<lTarget;j++) {
  336. cvec[j] += gain*(*pp);
  337. target[j] -= gain*(*pp++);
  338. }
  339. /* record quantized gain */
  340. gains[stage]=gain;
  341. }/* end of Main Loop. for (stage=0;... */
  342. /* Gain adjustment for energy matching */
  343. cene=0.0;
  344. for (i=0; i<lTarget; i++) {
  345. cene+=cvec[i]*cvec[i];
  346. }
  347. j=gain_index[0];
  348. for (i=gain_index[0]; i<32; i++) {
  349. ftmp=cene*gain_sq5Tbl[i]*gain_sq5Tbl[i];
  350. if ((ftmp<(tene*gains[0]*gains[0])) &&
  351. (gain_sq5Tbl[j]<(2.0*gains[0]))) {
  352. j=i;
  353. }
  354. }
  355. gain_index[0]=j;
  356. }