summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libspeex/cb_search.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libspeex/cb_search.c')
-rw-r--r--lib/rbcodec/codecs/libspeex/cb_search.c621
1 files changed, 621 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libspeex/cb_search.c b/lib/rbcodec/codecs/libspeex/cb_search.c
new file mode 100644
index 0000000000..35fe3a2f67
--- /dev/null
+++ b/lib/rbcodec/codecs/libspeex/cb_search.c
@@ -0,0 +1,621 @@
1/* Copyright (C) 2002-2006 Jean-Marc Valin
2 File: cb_search.c
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 - Neither the name of the Xiph.org Foundation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*/
31
32#ifdef HAVE_CONFIG_H
33#include "config-speex.h"
34#endif
35
36#include "cb_search.h"
37#include "filters.h"
38#include "stack_alloc.h"
39#include "vq.h"
40#include "arch.h"
41#include "math_approx.h"
42#include "os_support.h"
43
44#ifdef _USE_SSE
45#include "cb_search_sse.h"
46#elif defined(ARM4_ASM) || defined(ARM5E_ASM)
47#include "cb_search_arm4.h"
48#elif defined(BFIN_ASM)
49#include "cb_search_bfin.h"
50#endif
51
52#ifndef SPEEX_DISABLE_ENCODER
53#ifndef OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK
54static void compute_weighted_codebook(const signed char *shape_cb, const spx_word16_t *r, spx_word16_t *resp, spx_word16_t *resp2, spx_word32_t *E, int shape_cb_size, int subvect_size, char *stack)
55{
56 int i, j, k;
57 VARDECL(spx_word16_t *shape);
58 ALLOC(shape, subvect_size, spx_word16_t);
59 for (i=0;i<shape_cb_size;i++)
60 {
61 spx_word16_t *res;
62
63 res = resp+i*subvect_size;
64 for (k=0;k<subvect_size;k++)
65 shape[k] = (spx_word16_t)shape_cb[i*subvect_size+k];
66 E[i]=0;
67
68 /* Compute codeword response using convolution with impulse response */
69 for(j=0;j<subvect_size;j++)
70 {
71 spx_word32_t resj=0;
72 spx_word16_t res16;
73 for (k=0;k<=j;k++)
74 resj = MAC16_16(resj,shape[k],r[j-k]);
75#ifdef FIXED_POINT
76 res16 = EXTRACT16(SHR32(resj, 13));
77#else
78 res16 = 0.03125f*resj;
79#endif
80 /* Compute codeword energy */
81 E[i]=MAC16_16(E[i],res16,res16);
82 res[j] = res16;
83 /*printf ("%d\n", (int)res[j]);*/
84 }
85 }
86
87}
88#endif
89
90#ifndef OVERRIDE_TARGET_UPDATE
91static inline void target_update(spx_word16_t *t, spx_word16_t g, spx_word16_t *r, int len)
92{
93 int n;
94 for (n=0;n<len;n++)
95 t[n] = SUB16(t[n],PSHR32(MULT16_16(g,r[n]),13));
96}
97#endif
98
99
100
101static void split_cb_search_shape_sign_N1(
102spx_word16_t target[], /* target vector */
103spx_coef_t ak[], /* LPCs for this subframe */
104spx_coef_t awk1[], /* Weighted LPCs for this subframe */
105spx_coef_t awk2[], /* Weighted LPCs for this subframe */
106const void *par, /* Codebook/search parameters*/
107int p, /* number of LPC coeffs */
108int nsf, /* number of samples in subframe */
109spx_sig_t *exc,
110spx_word16_t *r,
111SpeexBits *bits,
112char *stack,
113int update_target
114)
115{
116 int i,j,m,q;
117 VARDECL(spx_word16_t *resp);
118#ifdef _USE_SSE
119 VARDECL(__m128 *resp2);
120 VARDECL(__m128 *E);
121#else
122 spx_word16_t *resp2;
123 VARDECL(spx_word32_t *E);
124#endif
125 VARDECL(spx_word16_t *t);
126 VARDECL(spx_sig_t *e);
127 const signed char *shape_cb;
128 int shape_cb_size, subvect_size, nb_subvect;
129 const split_cb_params *params;
130 int best_index;
131 spx_word32_t best_dist;
132 int have_sign;
133
134 params = (const split_cb_params *) par;
135 subvect_size = params->subvect_size;
136 nb_subvect = params->nb_subvect;
137 shape_cb_size = 1<<params->shape_bits;
138 shape_cb = params->shape_cb;
139 have_sign = params->have_sign;
140 ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t);
141#ifdef _USE_SSE
142 ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128);
143 ALLOC(E, shape_cb_size>>2, __m128);
144#else
145 resp2 = resp;
146 ALLOC(E, shape_cb_size, spx_word32_t);
147#endif
148 ALLOC(t, nsf, spx_word16_t);
149 ALLOC(e, nsf, spx_sig_t);
150
151 /* FIXME: Do we still need to copy the target? */
152 SPEEX_COPY(t, target, nsf);
153
154 compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);
155
156 for (i=0;i<nb_subvect;i++)
157 {
158 spx_word16_t *x=t+subvect_size*i;
159 /*Find new n-best based on previous n-best j*/
160 if (have_sign)
161 vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack);
162 else
163 vq_nbest(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack);
164
165 speex_bits_pack(bits,best_index,params->shape_bits+have_sign);
166
167 {
168 int rind;
169 spx_word16_t *res;
170 spx_word16_t sign=1;
171 rind = best_index;
172 if (rind>=shape_cb_size)
173 {
174 sign=-1;
175 rind-=shape_cb_size;
176 }
177 res = resp+rind*subvect_size;
178 if (sign>0)
179 for (m=0;m<subvect_size;m++)
180 t[subvect_size*i+m] = SUB16(t[subvect_size*i+m], res[m]);
181 else
182 for (m=0;m<subvect_size;m++)
183 t[subvect_size*i+m] = ADD16(t[subvect_size*i+m], res[m]);
184
185#ifdef FIXED_POINT
186 if (sign==1)
187 {
188 for (j=0;j<subvect_size;j++)
189 e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5);
190 } else {
191 for (j=0;j<subvect_size;j++)
192 e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5));
193 }
194#else
195 for (j=0;j<subvect_size;j++)
196 e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j];
197#endif
198
199 }
200
201 for (m=0;m<subvect_size;m++)
202 {
203 spx_word16_t g;
204 int rind;
205 spx_word16_t sign=1;
206 rind = best_index;
207 if (rind>=shape_cb_size)
208 {
209 sign=-1;
210 rind-=shape_cb_size;
211 }
212
213 q=subvect_size-m;
214#ifdef FIXED_POINT
215 g=sign*shape_cb[rind*subvect_size+m];
216#else
217 g=sign*0.03125*shape_cb[rind*subvect_size+m];
218#endif
219 target_update(t+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
220 }
221 }
222
223 /* Update excitation */
224 /* FIXME: We could update the excitation directly above */
225 for (j=0;j<nsf;j++)
226 exc[j]=ADD32(exc[j],e[j]);
227
228 /* Update target: only update target if necessary */
229 if (update_target)
230 {
231 VARDECL(spx_word16_t *r2);
232 ALLOC(r2, nsf, spx_word16_t);
233 for (j=0;j<nsf;j++)
234 r2[j] = EXTRACT16(PSHR32(e[j] ,6));
235 syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack);
236 for (j=0;j<nsf;j++)
237 target[j]=SUB16(target[j],PSHR16(r2[j],2));
238 }
239}
240
241
242
243void split_cb_search_shape_sign(
244spx_word16_t target[], /* target vector */
245spx_coef_t ak[], /* LPCs for this subframe */
246spx_coef_t awk1[], /* Weighted LPCs for this subframe */
247spx_coef_t awk2[], /* Weighted LPCs for this subframe */
248const void *par, /* Codebook/search parameters*/
249int p, /* number of LPC coeffs */
250int nsf, /* number of samples in subframe */
251spx_sig_t *exc,
252spx_word16_t *r,
253SpeexBits *bits,
254char *stack,
255int complexity,
256int update_target
257)
258{
259 int i,j,k,m,n,q;
260 VARDECL(spx_word16_t *resp);
261#ifdef _USE_SSE
262 VARDECL(__m128 *resp2);
263 VARDECL(__m128 *E);
264#else
265 spx_word16_t *resp2;
266 VARDECL(spx_word32_t *E);
267#endif
268 VARDECL(spx_word16_t *t);
269 VARDECL(spx_sig_t *e);
270 VARDECL(spx_word16_t *tmp);
271 VARDECL(spx_word32_t *ndist);
272 VARDECL(spx_word32_t *odist);
273 VARDECL(int *itmp);
274 VARDECL(spx_word16_t **ot2);
275 VARDECL(spx_word16_t **nt2);
276 spx_word16_t **ot, **nt;
277 VARDECL(int **nind);
278 VARDECL(int **oind);
279 VARDECL(int *ind);
280 const signed char *shape_cb;
281 int shape_cb_size, subvect_size, nb_subvect;
282 const split_cb_params *params;
283 int N=2;
284 VARDECL(int *best_index);
285 VARDECL(spx_word32_t *best_dist);
286 VARDECL(int *best_nind);
287 VARDECL(int *best_ntarget);
288 int have_sign;
289 N=complexity;
290 if (N>10)
291 N=10;
292 /* Complexity isn't as important for the codebooks as it is for the pitch */
293 N=(2*N)/3;
294 if (N<1)
295 N=1;
296 if (N==1)
297 {
298 split_cb_search_shape_sign_N1(target,ak,awk1,awk2,par,p,nsf,exc,r,bits,stack,update_target);
299 return;
300 }
301 ALLOC(ot2, N, spx_word16_t*);
302 ALLOC(nt2, N, spx_word16_t*);
303 ALLOC(oind, N, int*);
304 ALLOC(nind, N, int*);
305
306 params = (const split_cb_params *) par;
307 subvect_size = params->subvect_size;
308 nb_subvect = params->nb_subvect;
309 shape_cb_size = 1<<params->shape_bits;
310 shape_cb = params->shape_cb;
311 have_sign = params->have_sign;
312 ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t);
313#ifdef _USE_SSE
314 ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128);
315 ALLOC(E, shape_cb_size>>2, __m128);
316#else
317 resp2 = resp;
318 ALLOC(E, shape_cb_size, spx_word32_t);
319#endif
320 ALLOC(t, nsf, spx_word16_t);
321 ALLOC(e, nsf, spx_sig_t);
322 ALLOC(ind, nb_subvect, int);
323
324 ALLOC(tmp, 2*N*nsf, spx_word16_t);
325 for (i=0;i<N;i++)
326 {
327 ot2[i]=tmp+2*i*nsf;
328 nt2[i]=tmp+(2*i+1)*nsf;
329 }
330 ot=ot2;
331 nt=nt2;
332 ALLOC(best_index, N, int);
333 ALLOC(best_dist, N, spx_word32_t);
334 ALLOC(best_nind, N, int);
335 ALLOC(best_ntarget, N, int);
336 ALLOC(ndist, N, spx_word32_t);
337 ALLOC(odist, N, spx_word32_t);
338
339 ALLOC(itmp, 2*N*nb_subvect, int);
340 for (i=0;i<N;i++)
341 {
342 nind[i]=itmp+2*i*nb_subvect;
343 oind[i]=itmp+(2*i+1)*nb_subvect;
344 }
345
346 SPEEX_COPY(t, target, nsf);
347
348 for (j=0;j<N;j++)
349 SPEEX_COPY(&ot[j][0], t, nsf);
350
351 /* Pre-compute codewords response and energy */
352 compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);
353
354 for (j=0;j<N;j++)
355 odist[j]=0;
356
357 /*For all subvectors*/
358 for (i=0;i<nb_subvect;i++)
359 {
360 /*"erase" nbest list*/
361 for (j=0;j<N;j++)
362 ndist[j]=VERY_LARGE32;
363 /* This is not strictly necessary, but it provides an additonal safety
364 to prevent crashes in case something goes wrong in the previous
365 steps (e.g. NaNs) */
366 for (j=0;j<N;j++)
367 best_nind[j] = best_ntarget[j] = 0;
368 /*For all n-bests of previous subvector*/
369 for (j=0;j<N;j++)
370 {
371 spx_word16_t *x=ot[j]+subvect_size*i;
372 spx_word32_t tener = 0;
373 for (m=0;m<subvect_size;m++)
374 tener = MAC16_16(tener, x[m],x[m]);
375#ifdef FIXED_POINT
376 tener = SHR32(tener,1);
377#else
378 tener *= .5;
379#endif
380 /*Find new n-best based on previous n-best j*/
381 if (have_sign)
382 vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack);
383 else
384 vq_nbest(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack);
385
386 /*For all new n-bests*/
387 for (k=0;k<N;k++)
388 {
389 /* Compute total distance (including previous sub-vectors */
390 spx_word32_t err = ADD32(ADD32(odist[j],best_dist[k]),tener);
391
392 /*update n-best list*/
393 if (err<ndist[N-1])
394 {
395 for (m=0;m<N;m++)
396 {
397 if (err < ndist[m])
398 {
399 for (n=N-1;n>m;n--)
400 {
401 ndist[n] = ndist[n-1];
402 best_nind[n] = best_nind[n-1];
403 best_ntarget[n] = best_ntarget[n-1];
404 }
405 /* n is equal to m here, so they're interchangeable */
406 ndist[m] = err;
407 best_nind[n] = best_index[k];
408 best_ntarget[n] = j;
409 break;
410 }
411 }
412 }
413 }
414 if (i==0)
415 break;
416 }
417 for (j=0;j<N;j++)
418 {
419 /*previous target (we don't care what happened before*/
420 for (m=(i+1)*subvect_size;m<nsf;m++)
421 nt[j][m]=ot[best_ntarget[j]][m];
422
423 /* New code: update the rest of the target only if it's worth it */
424 for (m=0;m<subvect_size;m++)
425 {
426 spx_word16_t g;
427 int rind;
428 spx_word16_t sign=1;
429 rind = best_nind[j];
430 if (rind>=shape_cb_size)
431 {
432 sign=-1;
433 rind-=shape_cb_size;
434 }
435
436 q=subvect_size-m;
437#ifdef FIXED_POINT
438 g=sign*shape_cb[rind*subvect_size+m];
439#else
440 g=sign*0.03125*shape_cb[rind*subvect_size+m];
441#endif
442 target_update(nt[j]+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
443 }
444
445 for (q=0;q<nb_subvect;q++)
446 nind[j][q]=oind[best_ntarget[j]][q];
447 nind[j][i]=best_nind[j];
448 }
449
450 /*update old-new data*/
451 /* just swap pointers instead of a long copy */
452 {
453 spx_word16_t **tmp2;
454 tmp2=ot;
455 ot=nt;
456 nt=tmp2;
457 }
458 for (j=0;j<N;j++)
459 for (m=0;m<nb_subvect;m++)
460 oind[j][m]=nind[j][m];
461 for (j=0;j<N;j++)
462 odist[j]=ndist[j];
463 }
464
465 /*save indices*/
466 for (i=0;i<nb_subvect;i++)
467 {
468 ind[i]=nind[0][i];
469 speex_bits_pack(bits,ind[i],params->shape_bits+have_sign);
470 }
471
472 /* Put everything back together */
473 for (i=0;i<nb_subvect;i++)
474 {
475 int rind;
476 spx_word16_t sign=1;
477 rind = ind[i];
478 if (rind>=shape_cb_size)
479 {
480 sign=-1;
481 rind-=shape_cb_size;
482 }
483#ifdef FIXED_POINT
484 if (sign==1)
485 {
486 for (j=0;j<subvect_size;j++)
487 e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5);
488 } else {
489 for (j=0;j<subvect_size;j++)
490 e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5));
491 }
492#else
493 for (j=0;j<subvect_size;j++)
494 e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j];
495#endif
496 }
497 /* Update excitation */
498 for (j=0;j<nsf;j++)
499 exc[j]=ADD32(exc[j],e[j]);
500
501 /* Update target: only update target if necessary */
502 if (update_target)
503 {
504 VARDECL(spx_word16_t *r2);
505 ALLOC(r2, nsf, spx_word16_t);
506 for (j=0;j<nsf;j++)
507 r2[j] = EXTRACT16(PSHR32(e[j] ,6));
508 syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack);
509 for (j=0;j<nsf;j++)
510 target[j]=SUB16(target[j],PSHR16(r2[j],2));
511 }
512}
513#endif /* SPEEX_DISABLE_ENCODER*/
514
515
516void split_cb_shape_sign_unquant(
517spx_sig_t *exc,
518const void *par, /* non-overlapping codebook */
519int nsf, /* number of samples in subframe */
520SpeexBits *bits,
521char *stack,
522spx_int32_t *seed
523)
524{
525 (void)nsf;
526 (void)stack;
527 (void)seed;
528 int i,j;
529 VARDECL(int *ind);
530 VARDECL(int *signs);
531 const signed char *shape_cb;
532 int subvect_size, nb_subvect;
533 const split_cb_params *params;
534 int have_sign;
535
536 params = (const split_cb_params *) par;
537 subvect_size = params->subvect_size;
538 nb_subvect = params->nb_subvect;
539 shape_cb = params->shape_cb;
540 have_sign = params->have_sign;
541
542 ALLOC(ind, nb_subvect, int);
543 ALLOC(signs, nb_subvect, int);
544
545 /* Decode codewords and gains */
546 for (i=0;i<nb_subvect;i++)
547 {
548 if (have_sign)
549 signs[i] = speex_bits_unpack_unsigned(bits, 1);
550 else
551 signs[i] = 0;
552 ind[i] = speex_bits_unpack_unsigned(bits, params->shape_bits);
553 }
554 /* Compute decoded excitation */
555 for (i=0;i<nb_subvect;i++)
556 {
557 spx_word16_t s=1;
558 if (signs[i])
559 s=-1;
560#ifdef FIXED_POINT
561 if (s==1)
562 {
563 for (j=0;j<subvect_size;j++)
564 exc[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5);
565 } else {
566 for (j=0;j<subvect_size;j++)
567 exc[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5));
568 }
569#else
570 for (j=0;j<subvect_size;j++)
571 exc[subvect_size*i+j]+=s*0.03125*shape_cb[ind[i]*subvect_size+j];
572#endif
573 }
574}
575
576#ifndef SPEEX_DISABLE_ENCODER
577void noise_codebook_quant(
578spx_word16_t target[], /* target vector */
579spx_coef_t ak[], /* LPCs for this subframe */
580spx_coef_t awk1[], /* Weighted LPCs for this subframe */
581spx_coef_t awk2[], /* Weighted LPCs for this subframe */
582const void *par, /* Codebook/search parameters*/
583int p, /* number of LPC coeffs */
584int nsf, /* number of samples in subframe */
585spx_sig_t *exc,
586spx_word16_t *r,
587SpeexBits *bits,
588char *stack,
589int complexity,
590int update_target
591)
592{
593 int i;
594 VARDECL(spx_word16_t *tmp);
595 ALLOC(tmp, nsf, spx_word16_t);
596 residue_percep_zero16(target, ak, awk1, awk2, tmp, nsf, p, stack);
597
598 for (i=0;i<nsf;i++)
599 exc[i]+=SHL32(EXTEND32(tmp[i]),8);
600 SPEEX_MEMSET(target, 0, nsf);
601}
602#endif /* SPEEX_DISABLE_ENCODER */
603
604
605void noise_codebook_unquant(
606spx_sig_t *exc,
607const void *par, /* non-overlapping codebook */
608int nsf, /* number of samples in subframe */
609SpeexBits *bits,
610char *stack,
611spx_int32_t *seed
612)
613{
614 (void)par;
615 (void)bits;
616 (void)stack;
617 int i;
618 /* FIXME: This is bad, but I don't think the function ever gets called anyway */
619 for (i=0;i<nsf;i++)
620 exc[i]=SHL32(EXTEND32(speex_rand(1, seed)),SIG_SHIFT);
621}