• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.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 OVERRIDE_COMPUTE_WEIGHTED_CODEBOOK
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)53  static 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)
54  {
55     int i, j, k;
56     VARDECL(spx_word16_t *shape);
57     ALLOC(shape, subvect_size, spx_word16_t);
58     for (i=0;i<shape_cb_size;i++)
59     {
60        spx_word16_t *res;
61  
62        res = resp+i*subvect_size;
63        for (k=0;k<subvect_size;k++)
64           shape[k] = (spx_word16_t)shape_cb[i*subvect_size+k];
65        E[i]=0;
66  
67        /* Compute codeword response using convolution with impulse response */
68        for(j=0;j<subvect_size;j++)
69        {
70           spx_word32_t resj=0;
71           spx_word16_t res16;
72           for (k=0;k<=j;k++)
73              resj = MAC16_16(resj,shape[k],r[j-k]);
74  #ifdef FIXED_POINT
75           res16 = EXTRACT16(SHR32(resj, 13));
76  #else
77           res16 = 0.03125f*resj;
78  #endif
79           /* Compute codeword energy */
80           E[i]=MAC16_16(E[i],res16,res16);
81           res[j] = res16;
82           /*printf ("%d\n", (int)res[j]);*/
83        }
84     }
85  
86  }
87  #endif
88  
89  #ifndef OVERRIDE_TARGET_UPDATE
target_update(spx_word16_t * t,spx_word16_t g,spx_word16_t * r,int len)90  static inline void target_update(spx_word16_t *t, spx_word16_t g, spx_word16_t *r, int len)
91  {
92     int n;
93     for (n=0;n<len;n++)
94        t[n] = SUB16(t[n],PSHR32(MULT16_16(g,r[n]),13));
95  }
96  #endif
97  
98  
99  
split_cb_search_shape_sign_N1(spx_word16_t target[],spx_coef_t ak[],spx_coef_t awk1[],spx_coef_t awk2[],const void * par,int p,int nsf,spx_sig_t * exc,spx_word16_t * r,SpeexBits * bits,char * stack,int update_target)100  static void split_cb_search_shape_sign_N1(
101  spx_word16_t target[],			/* target vector */
102  spx_coef_t ak[],			/* LPCs for this subframe */
103  spx_coef_t awk1[],			/* Weighted LPCs for this subframe */
104  spx_coef_t awk2[],			/* Weighted LPCs for this subframe */
105  const void *par,                      /* Codebook/search parameters*/
106  int   p,                        /* number of LPC coeffs */
107  int   nsf,                      /* number of samples in subframe */
108  spx_sig_t *exc,
109  spx_word16_t *r,
110  SpeexBits *bits,
111  char *stack,
112  int   update_target
113  )
114  {
115     int i,j,m,q;
116     VARDECL(spx_word16_t *resp);
117  #ifdef _USE_SSE
118     VARDECL(__m128 *resp2);
119     VARDECL(__m128 *E);
120  #else
121     spx_word16_t *resp2;
122     VARDECL(spx_word32_t *E);
123  #endif
124     VARDECL(spx_word16_t *t);
125     VARDECL(spx_sig_t *e);
126     const signed char *shape_cb;
127     int shape_cb_size, subvect_size, nb_subvect;
128     const split_cb_params *params;
129     int best_index;
130     spx_word32_t best_dist;
131     int have_sign;
132  
133     params = (const split_cb_params *) par;
134     subvect_size = params->subvect_size;
135     nb_subvect = params->nb_subvect;
136     shape_cb_size = 1<<params->shape_bits;
137     shape_cb = params->shape_cb;
138     have_sign = params->have_sign;
139     ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t);
140  #ifdef _USE_SSE
141     ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128);
142     ALLOC(E, shape_cb_size>>2, __m128);
143  #else
144     resp2 = resp;
145     ALLOC(E, shape_cb_size, spx_word32_t);
146  #endif
147     ALLOC(t, nsf, spx_word16_t);
148     ALLOC(e, nsf, spx_sig_t);
149  
150     /* FIXME: Do we still need to copy the target? */
151     SPEEX_COPY(t, target, nsf);
152  
153     compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);
154  
155     for (i=0;i<nb_subvect;i++)
156     {
157        spx_word16_t *x=t+subvect_size*i;
158        /*Find new n-best based on previous n-best j*/
159        if (have_sign)
160           vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack);
161        else
162           vq_nbest(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack);
163  
164        speex_bits_pack(bits,best_index,params->shape_bits+have_sign);
165  
166        {
167           int rind;
168           spx_word16_t *res;
169           spx_word16_t sign=1;
170           rind = best_index;
171           if (rind>=shape_cb_size)
172           {
173              sign=-1;
174              rind-=shape_cb_size;
175           }
176           res = resp+rind*subvect_size;
177           if (sign>0)
178              for (m=0;m<subvect_size;m++)
179                 t[subvect_size*i+m] = SUB16(t[subvect_size*i+m], res[m]);
180           else
181              for (m=0;m<subvect_size;m++)
182                 t[subvect_size*i+m] = ADD16(t[subvect_size*i+m], res[m]);
183  
184  #ifdef FIXED_POINT
185           if (sign==1)
186           {
187              for (j=0;j<subvect_size;j++)
188                 e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5);
189           } else {
190              for (j=0;j<subvect_size;j++)
191                 e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5));
192           }
193  #else
194           for (j=0;j<subvect_size;j++)
195              e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j];
196  #endif
197  
198        }
199  
200        for (m=0;m<subvect_size;m++)
201        {
202           spx_word16_t g;
203           int rind;
204           spx_word16_t sign=1;
205           rind = best_index;
206           if (rind>=shape_cb_size)
207           {
208              sign=-1;
209              rind-=shape_cb_size;
210           }
211  
212           q=subvect_size-m;
213  #ifdef FIXED_POINT
214           g=sign*shape_cb[rind*subvect_size+m];
215  #else
216           g=sign*0.03125*shape_cb[rind*subvect_size+m];
217  #endif
218           target_update(t+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
219        }
220     }
221  
222     /* Update excitation */
223     /* FIXME: We could update the excitation directly above */
224     for (j=0;j<nsf;j++)
225        exc[j]=ADD32(exc[j],e[j]);
226  
227     /* Update target: only update target if necessary */
228     if (update_target)
229     {
230        VARDECL(spx_word16_t *r2);
231        ALLOC(r2, nsf, spx_word16_t);
232        for (j=0;j<nsf;j++)
233           r2[j] = EXTRACT16(PSHR32(e[j] ,6));
234        syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack);
235        for (j=0;j<nsf;j++)
236           target[j]=SUB16(target[j],PSHR16(r2[j],2));
237     }
238  }
239  
240  
241  
split_cb_search_shape_sign(spx_word16_t target[],spx_coef_t ak[],spx_coef_t awk1[],spx_coef_t awk2[],const void * par,int p,int nsf,spx_sig_t * exc,spx_word16_t * r,SpeexBits * bits,char * stack,int complexity,int update_target)242  void split_cb_search_shape_sign(
243  spx_word16_t target[],			/* target vector */
244  spx_coef_t ak[],			/* LPCs for this subframe */
245  spx_coef_t awk1[],			/* Weighted LPCs for this subframe */
246  spx_coef_t awk2[],			/* Weighted LPCs for this subframe */
247  const void *par,                      /* Codebook/search parameters*/
248  int   p,                        /* number of LPC coeffs */
249  int   nsf,                      /* number of samples in subframe */
250  spx_sig_t *exc,
251  spx_word16_t *r,
252  SpeexBits *bits,
253  char *stack,
254  int   complexity,
255  int   update_target
256  )
257  {
258     int i,j,k,m,n,q;
259     VARDECL(spx_word16_t *resp);
260  #ifdef _USE_SSE
261     VARDECL(__m128 *resp2);
262     VARDECL(__m128 *E);
263  #else
264     spx_word16_t *resp2;
265     VARDECL(spx_word32_t *E);
266  #endif
267     VARDECL(spx_word16_t *t);
268     VARDECL(spx_sig_t *e);
269     VARDECL(spx_word16_t *tmp);
270     VARDECL(spx_word32_t *ndist);
271     VARDECL(spx_word32_t *odist);
272     VARDECL(int *itmp);
273     VARDECL(spx_word16_t **ot2);
274     VARDECL(spx_word16_t **nt2);
275     spx_word16_t **ot, **nt;
276     VARDECL(int **nind);
277     VARDECL(int **oind);
278     VARDECL(int *ind);
279     const signed char *shape_cb;
280     int shape_cb_size, subvect_size, nb_subvect;
281     const split_cb_params *params;
282     int N=2;
283     VARDECL(int *best_index);
284     VARDECL(spx_word32_t *best_dist);
285     VARDECL(int *best_nind);
286     VARDECL(int *best_ntarget);
287     int have_sign;
288     N=complexity;
289     if (N>10)
290        N=10;
291     /* Complexity isn't as important for the codebooks as it is for the pitch */
292     N=(2*N)/3;
293     if (N<1)
294        N=1;
295     if (N==1)
296     {
297        split_cb_search_shape_sign_N1(target,ak,awk1,awk2,par,p,nsf,exc,r,bits,stack,update_target);
298        return;
299     }
300     ALLOC(ot2, N, spx_word16_t*);
301     ALLOC(nt2, N, spx_word16_t*);
302     ALLOC(oind, N, int*);
303     ALLOC(nind, N, int*);
304  
305     params = (const split_cb_params *) par;
306     subvect_size = params->subvect_size;
307     nb_subvect = params->nb_subvect;
308     shape_cb_size = 1<<params->shape_bits;
309     shape_cb = params->shape_cb;
310     have_sign = params->have_sign;
311     ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t);
312  #ifdef _USE_SSE
313     ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128);
314     ALLOC(E, shape_cb_size>>2, __m128);
315  #else
316     resp2 = resp;
317     ALLOC(E, shape_cb_size, spx_word32_t);
318  #endif
319     ALLOC(t, nsf, spx_word16_t);
320     ALLOC(e, nsf, spx_sig_t);
321     ALLOC(ind, nb_subvect, int);
322  
323     ALLOC(tmp, 2*N*nsf, spx_word16_t);
324     for (i=0;i<N;i++)
325     {
326        ot2[i]=tmp+2*i*nsf;
327        nt2[i]=tmp+(2*i+1)*nsf;
328     }
329     ot=ot2;
330     nt=nt2;
331     ALLOC(best_index, N, int);
332     ALLOC(best_dist, N, spx_word32_t);
333     ALLOC(best_nind, N, int);
334     ALLOC(best_ntarget, N, int);
335     ALLOC(ndist, N, spx_word32_t);
336     ALLOC(odist, N, spx_word32_t);
337  
338     ALLOC(itmp, 2*N*nb_subvect, int);
339     for (i=0;i<N;i++)
340     {
341        nind[i]=itmp+2*i*nb_subvect;
342        oind[i]=itmp+(2*i+1)*nb_subvect;
343     }
344  
345     SPEEX_COPY(t, target, nsf);
346  
347     for (j=0;j<N;j++)
348        SPEEX_COPY(&ot[j][0], t, nsf);
349  
350     /* Pre-compute codewords response and energy */
351     compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);
352  
353     for (j=0;j<N;j++)
354        odist[j]=0;
355  
356     /*For all subvectors*/
357     for (i=0;i<nb_subvect;i++)
358     {
359        /*"erase" nbest list*/
360        for (j=0;j<N;j++)
361           ndist[j]=VERY_LARGE32;
362        /* This is not strictly necessary, but it provides an additonal safety
363           to prevent crashes in case something goes wrong in the previous
364           steps (e.g. NaNs) */
365        for (j=0;j<N;j++)
366           best_nind[j] = best_ntarget[j] = 0;
367        /*For all n-bests of previous subvector*/
368        for (j=0;j<N;j++)
369        {
370           spx_word16_t *x=ot[j]+subvect_size*i;
371           spx_word32_t tener = 0;
372           for (m=0;m<subvect_size;m++)
373              tener = MAC16_16(tener, x[m],x[m]);
374  #ifdef FIXED_POINT
375           tener = SHR32(tener,1);
376  #else
377           tener *= .5;
378  #endif
379           /*Find new n-best based on previous n-best j*/
380           if (have_sign)
381              vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack);
382           else
383              vq_nbest(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack);
384  
385           /*For all new n-bests*/
386           for (k=0;k<N;k++)
387           {
388              /* Compute total distance (including previous sub-vectors */
389              spx_word32_t err = ADD32(ADD32(odist[j],best_dist[k]),tener);
390  
391              /*update n-best list*/
392              if (err<ndist[N-1])
393              {
394                 for (m=0;m<N;m++)
395                 {
396                    if (err < ndist[m])
397                    {
398                       for (n=N-1;n>m;n--)
399                       {
400                          ndist[n] = ndist[n-1];
401                          best_nind[n] = best_nind[n-1];
402                          best_ntarget[n] = best_ntarget[n-1];
403                       }
404                       /* n is equal to m here, so they're interchangeable */
405                       ndist[m] = err;
406                       best_nind[n] = best_index[k];
407                       best_ntarget[n] = j;
408                       break;
409                    }
410                 }
411              }
412           }
413           if (i==0)
414              break;
415        }
416        for (j=0;j<N;j++)
417        {
418           /*previous target (we don't care what happened before*/
419           for (m=(i+1)*subvect_size;m<nsf;m++)
420              nt[j][m]=ot[best_ntarget[j]][m];
421  
422           /* New code: update the rest of the target only if it's worth it */
423           for (m=0;m<subvect_size;m++)
424           {
425              spx_word16_t g;
426              int rind;
427              spx_word16_t sign=1;
428              rind = best_nind[j];
429              if (rind>=shape_cb_size)
430              {
431                 sign=-1;
432                 rind-=shape_cb_size;
433              }
434  
435              q=subvect_size-m;
436  #ifdef FIXED_POINT
437              g=sign*shape_cb[rind*subvect_size+m];
438  #else
439              g=sign*0.03125*shape_cb[rind*subvect_size+m];
440  #endif
441              target_update(nt[j]+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
442           }
443  
444           for (q=0;q<nb_subvect;q++)
445              nind[j][q]=oind[best_ntarget[j]][q];
446           nind[j][i]=best_nind[j];
447        }
448  
449        /*update old-new data*/
450        /* just swap pointers instead of a long copy */
451        {
452           spx_word16_t **tmp2;
453           tmp2=ot;
454           ot=nt;
455           nt=tmp2;
456        }
457        for (j=0;j<N;j++)
458           for (m=0;m<nb_subvect;m++)
459              oind[j][m]=nind[j][m];
460        for (j=0;j<N;j++)
461           odist[j]=ndist[j];
462     }
463  
464     /*save indices*/
465     for (i=0;i<nb_subvect;i++)
466     {
467        ind[i]=nind[0][i];
468        speex_bits_pack(bits,ind[i],params->shape_bits+have_sign);
469     }
470  
471     /* Put everything back together */
472     for (i=0;i<nb_subvect;i++)
473     {
474        int rind;
475        spx_word16_t sign=1;
476        rind = ind[i];
477        if (rind>=shape_cb_size)
478        {
479           sign=-1;
480           rind-=shape_cb_size;
481        }
482  #ifdef FIXED_POINT
483        if (sign==1)
484        {
485           for (j=0;j<subvect_size;j++)
486              e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5);
487        } else {
488           for (j=0;j<subvect_size;j++)
489              e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5));
490        }
491  #else
492        for (j=0;j<subvect_size;j++)
493           e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j];
494  #endif
495     }
496     /* Update excitation */
497     for (j=0;j<nsf;j++)
498        exc[j]=ADD32(exc[j],e[j]);
499  
500     /* Update target: only update target if necessary */
501     if (update_target)
502     {
503        VARDECL(spx_word16_t *r2);
504        ALLOC(r2, nsf, spx_word16_t);
505        for (j=0;j<nsf;j++)
506           r2[j] = EXTRACT16(PSHR32(e[j] ,6));
507        syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack);
508        for (j=0;j<nsf;j++)
509           target[j]=SUB16(target[j],PSHR16(r2[j],2));
510     }
511  }
512  
513  
split_cb_shape_sign_unquant(spx_sig_t * exc,const void * par,int nsf,SpeexBits * bits,char * stack,spx_int32_t * seed)514  void split_cb_shape_sign_unquant(
515  spx_sig_t *exc,
516  const void *par,                      /* non-overlapping codebook */
517  int   nsf,                      /* number of samples in subframe */
518  SpeexBits *bits,
519  char *stack,
520  spx_int32_t *seed
521  )
522  {
523     int i,j;
524     VARDECL(int *ind);
525     VARDECL(int *signs);
526     const signed char *shape_cb;
527     int shape_cb_size, subvect_size, nb_subvect;
528     const split_cb_params *params;
529     int have_sign;
530  
531     params = (const split_cb_params *) par;
532     subvect_size = params->subvect_size;
533     nb_subvect = params->nb_subvect;
534     shape_cb_size = 1<<params->shape_bits;
535     shape_cb = params->shape_cb;
536     have_sign = params->have_sign;
537  
538     ALLOC(ind, nb_subvect, int);
539     ALLOC(signs, nb_subvect, int);
540  
541     /* Decode codewords and gains */
542     for (i=0;i<nb_subvect;i++)
543     {
544        if (have_sign)
545           signs[i] = speex_bits_unpack_unsigned(bits, 1);
546        else
547           signs[i] = 0;
548        ind[i] = speex_bits_unpack_unsigned(bits, params->shape_bits);
549     }
550     /* Compute decoded excitation */
551     for (i=0;i<nb_subvect;i++)
552     {
553        spx_word16_t s=1;
554        if (signs[i])
555           s=-1;
556  #ifdef FIXED_POINT
557        if (s==1)
558        {
559           for (j=0;j<subvect_size;j++)
560              exc[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5);
561        } else {
562           for (j=0;j<subvect_size;j++)
563              exc[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5));
564        }
565  #else
566        for (j=0;j<subvect_size;j++)
567           exc[subvect_size*i+j]+=s*0.03125*shape_cb[ind[i]*subvect_size+j];
568  #endif
569     }
570  }
571  
noise_codebook_quant(spx_word16_t target[],spx_coef_t ak[],spx_coef_t awk1[],spx_coef_t awk2[],const void * par,int p,int nsf,spx_sig_t * exc,spx_word16_t * r,SpeexBits * bits,char * stack,int complexity,int update_target)572  void noise_codebook_quant(
573  spx_word16_t target[],			/* target vector */
574  spx_coef_t ak[],			/* LPCs for this subframe */
575  spx_coef_t awk1[],			/* Weighted LPCs for this subframe */
576  spx_coef_t awk2[],			/* Weighted LPCs for this subframe */
577  const void *par,                      /* Codebook/search parameters*/
578  int   p,                        /* number of LPC coeffs */
579  int   nsf,                      /* number of samples in subframe */
580  spx_sig_t *exc,
581  spx_word16_t *r,
582  SpeexBits *bits,
583  char *stack,
584  int   complexity,
585  int   update_target
586  )
587  {
588     int i;
589     VARDECL(spx_word16_t *tmp);
590     ALLOC(tmp, nsf, spx_word16_t);
591     residue_percep_zero16(target, ak, awk1, awk2, tmp, nsf, p, stack);
592  
593     for (i=0;i<nsf;i++)
594        exc[i]+=SHL32(EXTEND32(tmp[i]),8);
595     SPEEX_MEMSET(target, 0, nsf);
596  }
597  
598  
noise_codebook_unquant(spx_sig_t * exc,const void * par,int nsf,SpeexBits * bits,char * stack,spx_int32_t * seed)599  void noise_codebook_unquant(
600  spx_sig_t *exc,
601  const void *par,                      /* non-overlapping codebook */
602  int   nsf,                      /* number of samples in subframe */
603  SpeexBits *bits,
604  char *stack,
605  spx_int32_t *seed
606  )
607  {
608     int i;
609     /* FIXME: This is bad, but I don't think the function ever gets called anyway */
610     for (i=0;i<nsf;i++)
611        exc[i]=SHL32(EXTEND32(speex_rand(1, seed)),SIG_SHIFT);
612  }
613