Moved all the includes from /usr/include to /usr/include/speex
[speexdsp.git] / libspeex / nb_celp.c
1 /* Copyright (C) 2002 Jean-Marc Valin 
2    File: nb_celp.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 #include <math.h>
33 #include "nb_celp.h"
34 #include "lpc.h"
35 #include "lsp.h"
36 #include "ltp.h"
37 #include "quant_lsp.h"
38 #include "cb_search.h"
39 #include "filters.h"
40 #include "stack_alloc.h"
41 #include "vq.h"
42 #include <speex/speex_bits.h>
43 #include "vbr.h"
44 #include "misc.h"
45 #include <speex/speex_callbacks.h>
46
47 #include <stdio.h>
48
49 #ifndef M_PI
50 #define M_PI           3.14159265358979323846  /* pi */
51 #endif
52
53 #ifndef NULL
54 #define NULL 0
55 #endif
56
57 #define SUBMODE(x) st->submodes[st->submodeID]->x
58
59
60 #ifdef FIXED_POINT
61 const spx_word32_t ol_gain_table[32]={18900, 25150, 33468, 44536, 59265, 78865, 104946, 139653, 185838, 247297, 329081, 437913, 582736, 775454, 1031906, 1373169, 1827293, 2431601, 3235761, 4305867, 5729870, 7624808, 10146425, 13501971, 17967238, 23909222, 31816294, 42338330, 56340132, 74972501, 99766822, 132760927};
62 const spx_word16_t exc_gain_quant_scal3_bound[7]={1841, 3883, 6051, 8062, 10444, 13580, 18560};
63 const spx_word16_t exc_gain_quant_scal3[8]={1002, 2680, 5086, 7016, 9108, 11781, 15380, 21740};
64 const spx_word16_t exc_gain_quant_scal1_bound[1]={14385};
65 const spx_word16_t exc_gain_quant_scal1[2]={11546, 17224};
66
67 #define LSP_MARGIN 16
68 #define LSP_DELTA1 6553
69 #define LSP_DELTA2 1638
70
71 #else
72
73 const float exc_gain_quant_scal3_bound[7]={0.112338, 0.236980, 0.369316, 0.492054, 0.637471, 0.828874, 1.132784};
74 const float exc_gain_quant_scal3[8]={0.061130, 0.163546, 0.310413, 0.428220, 0.555887, 0.719055, 0.938694, 1.326874};
75 const float exc_gain_quant_scal1_bound[1]={0.87798};
76 const float exc_gain_quant_scal1[2]={0.70469, 1.05127};
77
78 #define LSP_MARGIN .002
79 #define LSP_DELTA1 .2
80 #define LSP_DELTA2 .05
81
82 #endif
83
84
85
86
87 #define sqr(x) ((x)*(x))
88
89 void *nb_encoder_init(const SpeexMode *m)
90 {
91    EncState *st;
92    const SpeexNBMode *mode;
93    int i;
94
95    mode=(SpeexNBMode *)m->mode;
96    st = (EncState*)speex_alloc(sizeof(EncState)+8000*sizeof(spx_sig_t));
97    if (!st)
98       return NULL;
99
100    st->stack = ((char*)st) + sizeof(EncState);
101    
102    st->mode=m;
103
104    st->frameSize = mode->frameSize;
105    st->windowSize = st->frameSize*3/2;
106    st->nbSubframes=mode->frameSize/mode->subframeSize;
107    st->subframeSize=mode->subframeSize;
108    st->lpcSize = mode->lpcSize;
109    st->bufSize = mode->bufSize;
110    st->gamma1=mode->gamma1;
111    st->gamma2=mode->gamma2;
112    st->min_pitch=mode->pitchStart;
113    st->max_pitch=mode->pitchEnd;
114    st->lag_factor=mode->lag_factor;
115    st->lpc_floor = mode->lpc_floor;
116   
117    st->submodes=mode->submodes;
118    st->submodeID=st->submodeSelect=mode->defaultSubmode;
119    st->bounded_pitch = 1;
120
121    st->encode_submode = 1;
122 #ifdef EPIC_48K
123    st->lbr_48k=mode->lbr48k;
124 #endif
125
126    /* Allocating input buffer */
127    st->inBuf = PUSH(st->stack, st->bufSize, spx_sig_t);
128    st->frame = st->inBuf + st->bufSize - st->windowSize;
129    /* Allocating excitation buffer */
130    st->excBuf = PUSH(st->stack, st->bufSize, spx_sig_t);
131    st->exc = st->excBuf + st->bufSize - st->windowSize;
132    st->swBuf = PUSH(st->stack, st->bufSize, spx_sig_t);
133    st->sw = st->swBuf + st->bufSize - st->windowSize;
134
135    st->exc2Buf = PUSH(st->stack, st->bufSize, spx_sig_t);
136    st->exc2 = st->exc2Buf + st->bufSize - st->windowSize;
137
138    st->innov = PUSH(st->stack, st->frameSize, spx_sig_t);
139
140    /* Asymmetric "pseudo-Hamming" window */
141    {
142       int part1, part2;
143       part1=st->frameSize - (st->subframeSize>>1);
144       part2=(st->frameSize>>1) + (st->subframeSize>>1);
145       st->window = PUSH(st->stack, st->windowSize, spx_word16_t);
146       for (i=0;i<part1;i++)
147          st->window[i]=(spx_word16_t)(SIG_SCALING*(.54-.46*cos(M_PI*i/part1)));
148       for (i=0;i<part2;i++)
149          st->window[part1+i]=(spx_word16_t)(SIG_SCALING*(.54+.46*cos(M_PI*i/part2)));
150    }
151    /* Create the window for autocorrelation (lag-windowing) */
152    st->lagWindow = PUSH(st->stack, st->lpcSize+1, spx_word16_t);
153    for (i=0;i<st->lpcSize+1;i++)
154       st->lagWindow[i]=16384*exp(-.5*sqr(2*M_PI*st->lag_factor*i));
155
156    st->autocorr = PUSH(st->stack, st->lpcSize+1, spx_word16_t);
157
158    st->buf2 = PUSH(st->stack, st->windowSize, spx_sig_t);
159
160    st->lpc = PUSH(st->stack, st->lpcSize+1, spx_coef_t);
161    st->interp_lpc = PUSH(st->stack, st->lpcSize+1, spx_coef_t);
162    st->interp_qlpc = PUSH(st->stack, st->lpcSize+1, spx_coef_t);
163    st->bw_lpc1 = PUSH(st->stack, st->lpcSize+1, spx_coef_t);
164    st->bw_lpc2 = PUSH(st->stack, st->lpcSize+1, spx_coef_t);
165
166    st->lsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
167    st->qlsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
168    st->old_lsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
169    st->old_qlsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
170    st->interp_lsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
171    st->interp_qlsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
172
173    st->first = 1;
174    for (i=0;i<st->lpcSize;i++)
175    {
176       st->lsp[i]=LSP_SCALING*(M_PI*((float)(i+1)))/(st->lpcSize+1);
177    }
178
179    st->mem_sp = PUSH(st->stack, st->lpcSize, spx_mem_t);
180    st->mem_sw = PUSH(st->stack, st->lpcSize, spx_mem_t);
181    st->mem_sw_whole = PUSH(st->stack, st->lpcSize, spx_mem_t);
182    st->mem_exc = PUSH(st->stack, st->lpcSize, spx_mem_t);
183
184    st->pi_gain = PUSH(st->stack, st->nbSubframes, spx_word32_t);
185
186    st->pitch = PUSH(st->stack, st->nbSubframes, int);
187
188    st->vbr = PUSHS(st->stack, VBRState);
189    vbr_init(st->vbr);
190    st->vbr_quality = 8;
191    st->vbr_enabled = 0;
192    st->vad_enabled = 0;
193    st->dtx_enabled = 0;
194    st->abr_enabled = 0;
195    st->abr_drift = 0;
196
197    st->complexity=2;
198    st->sampling_rate=8000;
199    st->dtx_count=0;
200
201 #ifdef ENABLE_VALGRIND
202    VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st));
203 #endif
204    return st;
205 }
206
207 void nb_encoder_destroy(void *state)
208 {
209    EncState *st=(EncState *)state;
210    /* Free all allocated memory */
211
212    vbr_destroy(st->vbr);
213
214    /*Free state memory... should be last*/
215    speex_free(st);
216 }
217
218 int nb_encode(void *state, void *vin, SpeexBits *bits)
219 {
220    EncState *st;
221    int i, sub, roots;
222    int ol_pitch;
223    spx_word16_t ol_pitch_coef;
224    spx_word32_t ol_gain;
225    spx_sig_t *res, *target;
226    spx_mem_t *mem;
227    char *stack;
228    spx_sig_t *syn_resp;
229    spx_sig_t *orig;
230 #ifdef EPIC_48K
231    int pitch_half[2];
232    int ol_pitch_id=0;
233 #endif
234    spx_word16_t *in = vin;
235
236    st=(EncState *)state;
237    stack=st->stack;
238
239    /* Copy new data in input buffer */
240    speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
241    for (i=0;i<st->frameSize;i++)
242       st->inBuf[st->bufSize-st->frameSize+i] = SHL((int)in[i], SIG_SHIFT);
243
244    /* Move signals 1 frame towards the past */
245    speex_move(st->exc2Buf, st->exc2Buf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
246    speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
247    speex_move(st->swBuf, st->swBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
248
249
250    {
251       spx_word16_t *w_sig;
252       w_sig = PUSH(stack, st->windowSize, spx_word16_t);
253       /* Window for analysis */
254       for (i=0;i<st->windowSize;i++)
255          w_sig[i] = SHR(MULT16_16(SHR((spx_word32_t)(st->frame[i]),SIG_SHIFT),st->window[i]),SIG_SHIFT);
256
257       /* Compute auto-correlation */
258       _spx_autocorr(w_sig, st->autocorr, st->lpcSize+1, st->windowSize);
259    }
260    st->autocorr[0] = (spx_word16_t) (st->autocorr[0]*st->lpc_floor); /* Noise floor in auto-correlation domain */
261
262    /* Lag windowing: equivalent to filtering in the power-spectrum domain */
263    for (i=0;i<st->lpcSize+1;i++)
264       st->autocorr[i] = MULT16_16_Q14(st->autocorr[i],st->lagWindow[i]);
265
266    /* Levinson-Durbin */
267    _spx_lpc(st->lpc+1, st->autocorr, st->lpcSize);
268    st->lpc[0]=(spx_coef_t)LPC_SCALING;
269
270    /* LPC to LSPs (x-domain) transform */
271    roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 15, LSP_DELTA1, stack);
272    /* Check if we found all the roots */
273    if (roots!=st->lpcSize)
274    {
275       /* Search again if we can afford it */
276       if (st->complexity>1)
277          roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, LSP_DELTA2, stack);
278       if (roots!=st->lpcSize) 
279       {
280          /*If we can't find all LSP's, do some damage control and use previous filter*/
281          for (i=0;i<st->lpcSize;i++)
282          {
283             st->lsp[i]=st->old_lsp[i];
284          }
285       }
286    }
287
288
289
290    /* Whole frame analysis (open-loop estimation of pitch and excitation gain) */
291    {
292       if (st->first)
293          for (i=0;i<st->lpcSize;i++)
294             st->interp_lsp[i] = st->lsp[i];
295       else
296          lsp_interpolate(st->old_lsp, st->lsp, st->interp_lsp, st->lpcSize, st->nbSubframes, st->nbSubframes<<1);
297
298       lsp_enforce_margin(st->interp_lsp, st->lpcSize, LSP_MARGIN);
299
300       /* Compute interpolated LPCs (unquantized) for whole frame*/
301       lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);
302
303
304       /*Open-loop pitch*/
305       if (!st->submodes[st->submodeID] || st->vbr_enabled || st->vad_enabled || SUBMODE(forced_pitch_gain) ||
306           SUBMODE(lbr_pitch) != -1)
307       {
308          int nol_pitch[6];
309          spx_word16_t nol_pitch_coef[6];
310          
311          bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
312          bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
313          
314          filter_mem2(st->frame, st->bw_lpc1, st->bw_lpc2, st->sw, st->frameSize, st->lpcSize, st->mem_sw_whole);
315
316          open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSize, 
317                                nol_pitch, nol_pitch_coef, 6, stack);
318          ol_pitch=nol_pitch[0];
319          ol_pitch_coef = nol_pitch_coef[0];
320          /*Try to remove pitch multiples*/
321          for (i=1;i<6;i++)
322          {
323 #ifdef FIXED_POINT
324             if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],27853)) && 
325 #else
326             if ((nol_pitch_coef[i]>.85*nol_pitch_coef[0]) && 
327 #endif
328                 (ABS(2*nol_pitch[i]-ol_pitch)<=2 || ABS(3*nol_pitch[i]-ol_pitch)<=3 || 
329                  ABS(4*nol_pitch[i]-ol_pitch)<=4 || ABS(5*nol_pitch[i]-ol_pitch)<=5))
330             {
331                /*ol_pitch_coef=nol_pitch_coef[i];*/
332                ol_pitch = nol_pitch[i];
333             }
334          }
335          /*if (ol_pitch>50)
336            ol_pitch/=2;*/
337          /*ol_pitch_coef = sqrt(ol_pitch_coef);*/
338
339 #ifdef EPIC_48K
340          if (st->lbr_48k)
341          {
342             if (ol_pitch < st->min_pitch+2)
343                ol_pitch = st->min_pitch+2;
344             if (ol_pitch > st->max_pitch-2)
345                ol_pitch = st->max_pitch-2;
346             open_loop_nbest_pitch(st->sw, ol_pitch-2, ol_pitch+2, st->frameSize>>1, 
347                                   &pitch_half[0], nol_pitch_coef, 1, stack);
348             open_loop_nbest_pitch(st->sw+(st->frameSize>>1), pitch_half[0]-1, pitch_half[0]+2, st->frameSize>>1, 
349                                   &pitch_half[1], nol_pitch_coef, 1, stack);
350          }
351 #endif
352       } else {
353          ol_pitch=0;
354          ol_pitch_coef=0;
355       }
356       /*Compute "real" excitation*/
357       fir_mem2(st->frame, st->interp_lpc, st->exc, st->frameSize, st->lpcSize, st->mem_exc);
358
359       /* Compute open-loop excitation gain */
360 #ifdef EPIC_48K
361       if (st->lbr_48k)
362       {
363          float ol1=0,ol2=0;
364          float ol_gain2;
365          ol1 = compute_rms(st->exc, st->frameSize>>1);
366          ol2 = compute_rms(st->exc+(st->frameSize>>1), st->frameSize>>1);
367          ol1 *= ol1*(st->frameSize>>1);
368          ol2 *= ol2*(st->frameSize>>1);
369
370          ol_gain2=ol1;
371          if (ol2>ol1)
372             ol_gain2=ol2;
373          ol_gain2 = sqrt(2*ol_gain2*(ol1+ol2))*1.3*(1-.5*GAIN_SCALING_1*GAIN_SCALING_1*ol_pitch_coef*ol_pitch_coef);
374       
375          ol_gain=SHR(sqrt(1+ol_gain2/st->frameSize),SIG_SHIFT);
376
377       } else {
378 #endif
379          ol_gain = SHL(compute_rms(st->exc, st->frameSize),SIG_SHIFT);
380 #ifdef EPIC_48K
381       }
382 #endif
383    }
384
385    /*VBR stuff*/
386    if (st->vbr && (st->vbr_enabled||st->vad_enabled))
387    {
388       float lsp_dist=0;
389       for (i=0;i<st->lpcSize;i++)
390          lsp_dist += (st->old_lsp[i] - st->lsp[i])*(st->old_lsp[i] - st->lsp[i]);
391       lsp_dist /= LSP_SCALING*LSP_SCALING;
392       
393       if (st->abr_enabled)
394       {
395          float qual_change=0;
396          if (st->abr_drift2 * st->abr_drift > 0)
397          {
398             /* Only adapt if long-term and short-term drift are the same sign */
399             qual_change = -.00001*st->abr_drift/(1+st->abr_count);
400             if (qual_change>.05)
401                qual_change=.05;
402             if (qual_change<-.05)
403                qual_change=-.05;
404          }
405          st->vbr_quality += qual_change;
406          if (st->vbr_quality>10)
407             st->vbr_quality=10;
408          if (st->vbr_quality<0)
409             st->vbr_quality=0;
410       }
411
412       st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch, GAIN_SCALING_1*ol_pitch_coef);
413       /*if (delta_qual<0)*/
414       /*  delta_qual*=.1*(3+st->vbr_quality);*/
415       if (st->vbr_enabled) 
416       {
417          int mode;
418          int choice=0;
419          float min_diff=100;
420          mode = 8;
421          while (mode)
422          {
423             int v1;
424             float thresh;
425             v1=(int)floor(st->vbr_quality);
426             if (v1==10)
427                thresh = vbr_nb_thresh[mode][v1];
428             else
429                thresh = (st->vbr_quality-v1)*vbr_nb_thresh[mode][v1+1] + (1+v1-st->vbr_quality)*vbr_nb_thresh[mode][v1];
430             if (st->relative_quality > thresh && 
431                 st->relative_quality-thresh<min_diff)
432             {
433                choice = mode;
434                min_diff = st->relative_quality-thresh;
435             }
436             mode--;
437          }
438          mode=choice;
439          if (mode==0)
440          {
441             if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20)
442             {
443                mode=1;
444                st->dtx_count=1;
445             } else {
446                mode=0;
447                st->dtx_count++;
448             }
449          } else {
450             st->dtx_count=0;
451          }
452
453          speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);
454
455          if (st->abr_enabled)
456          {
457             int bitrate;
458             speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate);
459             st->abr_drift+=(bitrate-st->abr_enabled);
460             st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled);
461             st->abr_count += 1.0;
462          }
463
464       } else {
465          /*VAD only case*/
466          int mode;
467          if (st->relative_quality<2)
468          {
469             if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20)
470             {
471                st->dtx_count=1;
472                mode=1;
473             } else {
474                mode=0;
475                st->dtx_count++;
476             }
477          } else {
478             st->dtx_count = 0;
479             mode=st->submodeSelect;
480          }
481          /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/
482          st->submodeID=mode;
483       } 
484    } else {
485       st->relative_quality = -1;
486    }
487
488    if (st->encode_submode)
489    {
490 #ifdef EPIC_48K
491    if (!st->lbr_48k) {
492 #endif
493
494    /* First, transmit a zero for narrowband */
495    speex_bits_pack(bits, 0, 1);
496
497    /* Transmit the sub-mode we use for this frame */
498    speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS);
499
500 #ifdef EPIC_48K
501    }
502 #endif
503    }
504
505    /* If null mode (no transmission), just set a couple things to zero*/
506    if (st->submodes[st->submodeID] == NULL)
507    {
508       for (i=0;i<st->frameSize;i++)
509          st->exc[i]=st->exc2[i]=st->sw[i]=VERY_SMALL;
510
511       for (i=0;i<st->lpcSize;i++)
512          st->mem_sw[i]=0;
513       st->first=1;
514       st->bounded_pitch = 1;
515
516       /* Final signal synthesis from excitation */
517       iir_mem2(st->exc, st->interp_qlpc, st->frame, st->frameSize, st->lpcSize, st->mem_sp);
518
519       for (i=0;i<st->frameSize;i++)
520          in[i]=st->frame[i];
521
522       return 0;
523
524    }
525
526    /* LSP Quantization */
527    if (st->first)
528    {
529       for (i=0;i<st->lpcSize;i++)
530          st->old_lsp[i] = st->lsp[i];
531    }
532
533
534    /*Quantize LSPs*/
535 #if 1 /*0 for unquantized*/
536    SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits);
537 #else
538    for (i=0;i<st->lpcSize;i++)
539      st->qlsp[i]=st->lsp[i];
540 #endif
541
542 #ifdef EPIC_48K
543    if (st->lbr_48k) {
544       speex_bits_pack(bits, pitch_half[0]-st->min_pitch, 7);
545       speex_bits_pack(bits, pitch_half[1]-pitch_half[0]+1, 2);
546       
547       {
548          int quant = (int)floor(.5+7.4*GAIN_SCALING_1*ol_pitch_coef);
549          if (quant>7)
550             quant=7;
551          if (quant<0)
552             quant=0;
553          ol_pitch_id=quant;
554          speex_bits_pack(bits, quant, 3);
555          ol_pitch_coef=GAIN_SCALING*0.13514*quant;
556          
557       }
558       {
559          int qe = (int)(floor(.5+2.1*log(ol_gain*1.0/SIG_SCALING)))-2;
560          if (qe<0)
561             qe=0;
562          if (qe>15)
563             qe=15;
564          ol_gain = exp((qe+2)/2.1)*SIG_SCALING;
565          speex_bits_pack(bits, qe, 4);
566       }
567
568    } else {
569 #endif
570
571    /*If we use low bit-rate pitch mode, transmit open-loop pitch*/
572    if (SUBMODE(lbr_pitch)!=-1)
573    {
574       speex_bits_pack(bits, ol_pitch-st->min_pitch, 7);
575    } 
576
577    if (SUBMODE(forced_pitch_gain))
578    {
579       int quant;
580       quant = (int)floor(.5+15*ol_pitch_coef*GAIN_SCALING_1);
581       if (quant>15)
582          quant=15;
583       if (quant<0)
584          quant=0;
585       speex_bits_pack(bits, quant, 4);
586       ol_pitch_coef=GAIN_SCALING*0.066667*quant;
587    }
588    
589    
590    /*Quantize and transmit open-loop excitation gain*/
591 #ifdef FIXED_POINT
592    {
593       int qe = scal_quant32(ol_gain, ol_gain_table, 32);
594       /*ol_gain = exp(qe/3.5)*SIG_SCALING;*/
595       ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]);
596       speex_bits_pack(bits, qe, 5);
597    }
598 #else
599    {
600       int qe = (int)(floor(.5+3.5*log(ol_gain*1.0/SIG_SCALING)));
601       if (qe<0)
602          qe=0;
603       if (qe>31)
604          qe=31;
605       ol_gain = exp(qe/3.5)*SIG_SCALING;
606       speex_bits_pack(bits, qe, 5);
607    }
608 #endif
609
610
611 #ifdef EPIC_48K
612    }
613 #endif
614
615
616    /* Special case for first frame */
617    if (st->first)
618    {
619       for (i=0;i<st->lpcSize;i++)
620          st->old_qlsp[i] = st->qlsp[i];
621    }
622
623    /* Filter response */
624    res = PUSH(stack, st->subframeSize, spx_sig_t);
625    /* Target signal */
626    target = PUSH(stack, st->subframeSize, spx_sig_t);
627    syn_resp = PUSH(stack, st->subframeSize, spx_sig_t);
628    mem = PUSH(stack, st->lpcSize, spx_mem_t);
629    orig = PUSH(stack, st->frameSize, spx_sig_t);
630    for (i=0;i<st->frameSize;i++)
631       orig[i]=st->frame[i];
632
633    /* Loop on sub-frames */
634    for (sub=0;sub<st->nbSubframes;sub++)
635    {
636       int   offset;
637       spx_sig_t *sp, *sw, *exc, *exc2;
638       int pitch;
639
640 #ifdef EPIC_48K
641       if (st->lbr_48k)
642       {
643          if (sub*2 < st->nbSubframes)
644             ol_pitch = pitch_half[0];
645          else
646             ol_pitch = pitch_half[1];
647       }
648 #endif
649
650       /* Offset relative to start of frame */
651       offset = st->subframeSize*sub;
652       /* Original signal */
653       sp=st->frame+offset;
654       /* Excitation */
655       exc=st->exc+offset;
656       /* Weighted signal */
657       sw=st->sw+offset;
658
659       exc2=st->exc2+offset;
660
661
662       /* LSP interpolation (quantized and unquantized) */
663       lsp_interpolate(st->old_lsp, st->lsp, st->interp_lsp, st->lpcSize, sub, st->nbSubframes);
664       lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, sub, st->nbSubframes);
665
666       /* Make sure the filters are stable */
667       lsp_enforce_margin(st->interp_lsp, st->lpcSize, LSP_MARGIN);
668       lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN);
669
670       /* Compute interpolated LPCs (quantized and unquantized) */
671       lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);
672
673       lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);
674
675       /* Compute analysis filter gain at w=pi (for use in SB-CELP) */
676       {
677          spx_word32_t pi_g=st->interp_qlpc[0];
678          for (i=1;i<=st->lpcSize;i+=2)
679          {
680             pi_g += -st->interp_qlpc[i] +  st->interp_qlpc[i+1];
681          }
682          st->pi_gain[sub] = pi_g;
683       }
684
685
686       /* Compute bandwidth-expanded (unquantized) LPCs for perceptual weighting */
687       bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
688       if (st->gamma2>=0)
689          bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
690       else
691       {
692          st->bw_lpc2[0]=1;
693          for (i=1;i<=st->lpcSize;i++)
694             st->bw_lpc2[i]=0;
695       }
696
697       /* Compute impulse response of A(z/g1) / ( A(z)*A(z/g2) )*/
698       for (i=0;i<st->subframeSize;i++)
699          exc[i]=VERY_SMALL;
700       exc[0]=SIG_SCALING;
701       syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack);
702
703       /* Reset excitation */
704       for (i=0;i<st->subframeSize;i++)
705          exc[i]=VERY_SMALL;
706       for (i=0;i<st->subframeSize;i++)
707          exc2[i]=VERY_SMALL;
708
709       /* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */
710       for (i=0;i<st->lpcSize;i++)
711          mem[i]=st->mem_sp[i];
712       iir_mem2(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem);
713       
714       for (i=0;i<st->lpcSize;i++)
715          mem[i]=st->mem_sw[i];
716       filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem);
717       
718       /* Compute weighted signal */
719       for (i=0;i<st->lpcSize;i++)
720          mem[i]=st->mem_sw[i];
721       filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem);
722       
723       /* Compute target signal */
724       for (i=0;i<st->subframeSize;i++)
725          target[i]=sw[i]-res[i];
726
727       for (i=0;i<st->subframeSize;i++)
728          exc[i]=exc2[i]=0;
729
730       /* If we have a long-term predictor (otherwise, something's wrong) */
731       if (SUBMODE(ltp_quant))
732       {
733          int pit_min, pit_max;
734          /* Long-term prediction */
735          if (SUBMODE(lbr_pitch) != -1)
736          {
737             /* Low bit-rate pitch handling */
738             int margin;
739             margin = SUBMODE(lbr_pitch);
740             if (margin)
741             {
742                if (ol_pitch < st->min_pitch+margin-1)
743                   ol_pitch=st->min_pitch+margin-1;
744                if (ol_pitch > st->max_pitch-margin)
745                   ol_pitch=st->max_pitch-margin;
746                pit_min = ol_pitch-margin+1;
747                pit_max = ol_pitch+margin;
748             } else {
749                pit_min=pit_max=ol_pitch;
750             }
751          } else {
752             pit_min = st->min_pitch;
753             pit_max = st->max_pitch;
754          }
755          
756          /* Force pitch to use only the current frame if needed */
757          if (st->bounded_pitch && pit_max>offset)
758             pit_max=offset;
759
760 #ifdef EPIC_48K
761          if (st->lbr_48k)
762          {
763             pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
764                                        exc, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef,
765                                        st->lpcSize, st->subframeSize, bits, stack, 
766                                        exc2, syn_resp, st->complexity, ol_pitch_id);
767          } else {
768 #endif
769
770          /* Perform pitch search */
771          pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
772                                     exc, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef,
773                                     st->lpcSize, st->subframeSize, bits, stack, 
774                                     exc2, syn_resp, st->complexity, 0);
775 #ifdef EPIC_48K
776          }
777 #endif
778
779          st->pitch[sub]=pitch;
780       } else {
781          speex_error ("No pitch prediction, what's wrong");
782       }
783
784       /* Update target for adaptive codebook contribution */
785       syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, stack);
786       for (i=0;i<st->subframeSize;i++)
787          target[i]=SATURATE(SUB32(target[i],res[i]),805306368);
788
789
790       /* Quantization of innovation */
791       {
792          spx_sig_t *innov;
793          spx_word32_t ener=0;
794          spx_word16_t fine_gain;
795
796          innov = st->innov+sub*st->subframeSize;
797          for (i=0;i<st->subframeSize;i++)
798             innov[i]=0;
799          
800          residue_percep_zero(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, st->buf2, st->subframeSize, st->lpcSize, stack);
801
802          ener = SHL(compute_rms(st->buf2, st->subframeSize),SIG_SHIFT);
803
804          /*for (i=0;i<st->subframeSize;i++)
805             printf ("%f\n", st->buf2[i]/ener);
806          */
807          
808          /*FIXME: Should use DIV32_16 and make sure result fits in 16 bits */
809 #ifdef FIXED_POINT
810          {
811             spx_word32_t f = DIV32(ener,PSHR(ol_gain,SIG_SHIFT));
812             if (f<32768)
813                fine_gain = f;
814             else
815                fine_gain = 32767;
816          }
817 #else
818          fine_gain = DIV32_16(ener,PSHR(ol_gain,SIG_SHIFT));
819 #endif
820          /* Calculate gain correction for the sub-frame (if any) */
821          if (SUBMODE(have_subframe_gain)) 
822          {
823             int qe;
824             if (SUBMODE(have_subframe_gain)==3)
825             {
826                qe = scal_quant(fine_gain, exc_gain_quant_scal3_bound, 8);
827                speex_bits_pack(bits, qe, 3);
828                ener=MULT16_32_Q14(exc_gain_quant_scal3[qe],ol_gain);
829             } else {
830                qe = scal_quant(fine_gain, exc_gain_quant_scal1_bound, 2);
831                speex_bits_pack(bits, qe, 1);
832                ener=MULT16_32_Q14(exc_gain_quant_scal1[qe],ol_gain);               
833             }
834          } else {
835             ener=ol_gain;
836          }
837
838          /*printf ("%f %f\n", ener, ol_gain);*/
839
840          /* Normalize innovation */
841          signal_div(target, target, ener, st->subframeSize);
842
843          /* Quantize innovation */
844          if (SUBMODE(innovation_quant))
845          {
846             /* Codebook search */
847             SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, 
848                                       SUBMODE(innovation_params), st->lpcSize, st->subframeSize, 
849                                       innov, syn_resp, bits, stack, st->complexity);
850             
851             /* De-normalize innovation and update excitation */
852             signal_mul(innov, innov, ener, st->subframeSize);
853
854             for (i=0;i<st->subframeSize;i++)
855                exc[i] += innov[i];
856          } else {
857             speex_error("No fixed codebook");
858          }
859
860          /* In some (rare) modes, we do a second search (more bits) to reduce noise even more */
861          if (SUBMODE(double_codebook)) {
862             char *tmp_stack=stack;
863             spx_sig_t *innov2 = PUSH(tmp_stack, st->subframeSize, spx_sig_t);
864             for (i=0;i<st->subframeSize;i++)
865                innov2[i]=0;
866             for (i=0;i<st->subframeSize;i++)
867                target[i]*=2.2;
868             SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, 
869                                       SUBMODE(innovation_params), st->lpcSize, st->subframeSize, 
870                                       innov2, syn_resp, bits, tmp_stack, st->complexity);
871             signal_mul(innov2, innov2, ener*(1/2.2), st->subframeSize);
872             for (i=0;i<st->subframeSize;i++)
873                exc[i] += innov2[i];
874          }
875
876          signal_mul(target, target, ener, st->subframeSize);
877       }
878
879       /*Keep the previous memory*/
880       for (i=0;i<st->lpcSize;i++)
881          mem[i]=st->mem_sp[i];
882       /* Final signal synthesis from excitation */
883       iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp);
884
885       /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */
886       filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw);
887       for (i=0;i<st->subframeSize;i++)
888          exc2[i]=exc[i];
889    }
890
891    /* Store the LSPs for interpolation in the next frame */
892    if (st->submodeID>=1)
893    {
894       for (i=0;i<st->lpcSize;i++)
895          st->old_lsp[i] = st->lsp[i];
896       for (i=0;i<st->lpcSize;i++)
897          st->old_qlsp[i] = st->qlsp[i];
898    }
899
900    if (st->submodeID==1)
901    {
902       if (st->dtx_count)
903          speex_bits_pack(bits, 15, 4);
904       else
905          speex_bits_pack(bits, 0, 4);
906    }
907
908    /* The next frame will not be the first (Duh!) */
909    st->first = 0;
910
911    if (0) {
912       float ener=0, err=0;
913       float snr;
914       for (i=0;i<st->frameSize;i++)
915       {
916          ener+=st->frame[i]*st->frame[i];
917          err += (st->frame[i]-orig[i])*(st->frame[i]-orig[i]);
918       }
919       snr = 10*log10((ener+1)/(err+1));
920       /*printf ("%f %f %f\n", snr, ener, err);*/
921    }
922
923    /* Replace input by synthesized speech */
924    for (i=0;i<st->frameSize;i++)
925    {
926       spx_word32_t sig = PSHR(st->frame[i],SIG_SHIFT);
927       if (sig>32767)
928          sig = 32767;
929       if (sig<-32767)
930          sig = -32767;
931      in[i]=sig;
932    }
933
934    if (SUBMODE(innovation_quant) == noise_codebook_quant || st->submodeID==0)
935       st->bounded_pitch = 1;
936    else
937       st->bounded_pitch = 0;
938
939    return 1;
940 }
941
942
943 void *nb_decoder_init(const SpeexMode *m)
944 {
945    DecState *st;
946    const SpeexNBMode *mode;
947    int i;
948
949    mode=(SpeexNBMode*)m->mode;
950    st = (DecState *)speex_alloc(sizeof(DecState)+4000*sizeof(spx_sig_t));
951    st->mode=m;
952
953    st->stack = ((char*)st) + sizeof(DecState);
954
955    st->encode_submode = 1;
956 #ifdef EPIC_48K
957    st->lbr_48k=mode->lbr48k;
958 #endif
959
960    st->first=1;
961    /* Codec parameters, should eventually have several "modes"*/
962    st->frameSize = mode->frameSize;
963    st->windowSize = st->frameSize*3/2;
964    st->nbSubframes=mode->frameSize/mode->subframeSize;
965    st->subframeSize=mode->subframeSize;
966    st->lpcSize = mode->lpcSize;
967    st->bufSize = mode->bufSize;
968    st->min_pitch=mode->pitchStart;
969    st->max_pitch=mode->pitchEnd;
970
971    st->submodes=mode->submodes;
972    st->submodeID=mode->defaultSubmode;
973
974    st->lpc_enh_enabled=0;
975
976
977    st->inBuf = PUSH(st->stack, st->bufSize, spx_sig_t);
978    st->frame = st->inBuf + st->bufSize - st->windowSize;
979    st->excBuf = PUSH(st->stack, st->bufSize, spx_sig_t);
980    st->exc = st->excBuf + st->bufSize - st->windowSize;
981    for (i=0;i<st->bufSize;i++)
982       st->inBuf[i]=0;
983    for (i=0;i<st->bufSize;i++)
984       st->excBuf[i]=0;
985    st->innov = PUSH(st->stack, st->frameSize, spx_sig_t);
986
987    st->interp_qlpc = PUSH(st->stack, st->lpcSize+1, spx_coef_t);
988    st->qlsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
989    st->old_qlsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
990    st->interp_qlsp = PUSH(st->stack, st->lpcSize, spx_lsp_t);
991    st->mem_sp = PUSH(st->stack, 5*st->lpcSize, spx_mem_t);
992    st->comb_mem = PUSHS(st->stack, CombFilterMem);
993    comb_filter_mem_init (st->comb_mem);
994
995    st->pi_gain = PUSH(st->stack, st->nbSubframes, spx_word32_t);
996    st->last_pitch = 40;
997    st->count_lost=0;
998    st->pitch_gain_buf[0] = st->pitch_gain_buf[1] = st->pitch_gain_buf[2] = 0;
999    st->pitch_gain_buf_idx = 0;
1000
1001    st->sampling_rate=8000;
1002    st->last_ol_gain = 0;
1003
1004    st->user_callback.func = &speex_default_user_handler;
1005    st->user_callback.data = NULL;
1006    for (i=0;i<16;i++)
1007       st->speex_callbacks[i].func = NULL;
1008
1009    st->voc_m1=st->voc_m2=st->voc_mean=0;
1010    st->voc_offset=0;
1011    st->dtx_enabled=0;
1012 #ifdef ENABLE_VALGRIND
1013    VALGRIND_MAKE_READABLE(st, (st->stack-(char*)st));
1014 #endif
1015    return st;
1016 }
1017
1018 void nb_decoder_destroy(void *state)
1019 {
1020    DecState *st;
1021    st=(DecState*)state;
1022    
1023    speex_free(state);
1024 }
1025
1026 #define median3(a, b, c)        ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a))))
1027
1028 static void nb_decode_lost(DecState *st, spx_word16_t *out, char *stack)
1029 {
1030    int i, sub;
1031    spx_coef_t *awk1, *awk2, *awk3;
1032    float pitch_gain, fact;
1033    spx_word16_t gain_med;
1034
1035    fact = exp(-.04*st->count_lost*st->count_lost);
1036    gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], st->pitch_gain_buf[2]);
1037    if (gain_med < st->last_pitch_gain)
1038       st->last_pitch_gain = gain_med;
1039    
1040    pitch_gain = GAIN_SCALING_1*st->last_pitch_gain;
1041    if (pitch_gain>.95)
1042       pitch_gain=.95;
1043
1044    pitch_gain *= fact;
1045
1046    /* Shift all buffers by one frame */
1047    speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
1048    speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
1049
1050    awk1=PUSH(stack, (st->lpcSize+1), spx_coef_t);
1051    awk2=PUSH(stack, (st->lpcSize+1), spx_coef_t);
1052    awk3=PUSH(stack, (st->lpcSize+1), spx_coef_t);
1053
1054    for (sub=0;sub<st->nbSubframes;sub++)
1055    {
1056       int offset;
1057       spx_sig_t *sp, *exc;
1058       /* Offset relative to start of frame */
1059       offset = st->subframeSize*sub;
1060       /* Original signal */
1061       sp=st->frame+offset;
1062       /* Excitation */
1063       exc=st->exc+offset;
1064       /* Excitation after post-filter*/
1065
1066       /* Calculate perceptually enhanced LPC filter */
1067       if (st->lpc_enh_enabled)
1068       {
1069          spx_word16_t k1,k2,k3;
1070          if (st->submodes[st->submodeID] != NULL)
1071          {
1072             k1=SUBMODE(lpc_enh_k1);
1073             k2=SUBMODE(lpc_enh_k2);
1074             k3=SUBMODE(lpc_enh_k3);
1075          } else {
1076             k1=k2=.7*GAMMA_SCALING;
1077             k3=.0;
1078          }
1079          bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize);
1080          bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize);
1081          bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize);
1082       }
1083         
1084       /* Make up a plausible excitation */
1085       /* FIXME: THIS CAN BE IMPROVED */
1086       /*if (pitch_gain>.95)
1087         pitch_gain=.95;*/
1088       {
1089          float innov_gain=0;
1090          for (i=0;i<st->frameSize;i++)
1091             innov_gain += 1.0*st->innov[i]*st->innov[i];
1092          innov_gain=sqrt(innov_gain/st->frameSize);
1093       for (i=0;i<st->subframeSize;i++)
1094       {
1095 #if 0
1096          exc[i] = pitch_gain * exc[i - st->last_pitch] + fact*sqrt(1-pitch_gain)*st->innov[i+offset];
1097          /*Just so it give the same lost packets as with if 0*/
1098          /*rand();*/
1099 #else
1100          /*exc[i]=pitch_gain*exc[i-st->last_pitch] +  fact*st->innov[i+offset];*/
1101          exc[i]=pitch_gain*exc[i-st->last_pitch] + 
1102          fact*sqrt(1-pitch_gain)*speex_rand(innov_gain);
1103 #endif
1104       }
1105       }
1106       for (i=0;i<st->subframeSize;i++)
1107          sp[i]=exc[i];
1108       
1109       /* Signal synthesis */
1110       if (st->lpc_enh_enabled)
1111       {
1112          filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize, 
1113                      st->mem_sp+st->lpcSize);
1114          filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, 
1115                      st->mem_sp);
1116       } else {
1117          for (i=0;i<st->lpcSize;i++)
1118             st->mem_sp[st->lpcSize+i] = 0;
1119          iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, 
1120                      st->mem_sp);
1121       }      
1122    }
1123
1124    for (i=0;i<st->frameSize;i++)
1125    {
1126       spx_word32_t sig = PSHR(st->frame[i],SIG_SHIFT);
1127       if (sig>32767)
1128          sig = 32767;
1129       if (sig<-32767)
1130          sig = -32767;
1131      out[i]=sig;
1132    }
1133    
1134    st->first = 0;
1135    st->count_lost++;
1136    st->pitch_gain_buf[st->pitch_gain_buf_idx++] = GAIN_SCALING*pitch_gain;
1137    if (st->pitch_gain_buf_idx > 2) /* rollover */
1138       st->pitch_gain_buf_idx = 0;
1139 }
1140
1141 int nb_decode(void *state, SpeexBits *bits, void *vout)
1142 {
1143    DecState *st;
1144    int i, sub;
1145    int pitch;
1146    spx_word16_t pitch_gain[3];
1147    spx_word32_t ol_gain=0;
1148    int ol_pitch=0;
1149    spx_word16_t ol_pitch_coef=0;
1150    int best_pitch=40;
1151    spx_word16_t best_pitch_gain=0;
1152    int wideband;
1153    int m;
1154    char *stack;
1155    spx_coef_t *awk1, *awk2, *awk3;
1156    spx_word16_t pitch_average=0;
1157 #ifdef EPIC_48K
1158    int pitch_half[2];
1159    int ol_pitch_id=0;
1160 #endif
1161    spx_word16_t *out = vout;
1162
1163    st=(DecState*)state;
1164    stack=st->stack;
1165
1166    if (st->encode_submode)
1167    {
1168 #ifdef EPIC_48K
1169    if (!st->lbr_48k) {
1170 #endif
1171
1172    /* Check if we're in DTX mode*/
1173    if (!bits && st->dtx_enabled)
1174    {
1175       st->submodeID=0;
1176    } else 
1177    {
1178       /* If bits is NULL, consider the packet to be lost (what could we do anyway) */
1179       if (!bits)
1180       {
1181          nb_decode_lost(st, out, stack);
1182          return 0;
1183       }
1184
1185       /* Search for next narrowband block (handle requests, skip wideband blocks) */
1186       do {
1187          if (speex_bits_remaining(bits)<5)
1188             return -1;
1189          wideband = speex_bits_unpack_unsigned(bits, 1);
1190          if (wideband) /* Skip wideband block (for compatibility) */
1191          {
1192             int submode;
1193             int advance;
1194             advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS);
1195             speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
1196             if (advance < 0)
1197             {
1198                speex_warning ("Invalid wideband mode encountered. Corrupted stream?");
1199                return -2;
1200             } 
1201             advance -= (SB_SUBMODE_BITS+1);
1202             speex_bits_advance(bits, advance);
1203             
1204             if (speex_bits_remaining(bits)<5)
1205                return -1;
1206             wideband = speex_bits_unpack_unsigned(bits, 1);
1207             if (wideband)
1208             {
1209                advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS);
1210                speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
1211                if (advance < 0)
1212                {
1213                   speex_warning ("Invalid wideband mode encountered: corrupted stream?");
1214                   return -2;
1215                } 
1216                advance -= (SB_SUBMODE_BITS+1);
1217                speex_bits_advance(bits, advance);
1218                wideband = speex_bits_unpack_unsigned(bits, 1);
1219                if (wideband)
1220                {
1221                   speex_warning ("More than two wideband layers found: corrupted stream?");
1222                   return -2;
1223                }
1224
1225             }
1226          }
1227          if (speex_bits_remaining(bits)<4)
1228             return -1;
1229          /* FIXME: Check for overflow */
1230          m = speex_bits_unpack_unsigned(bits, 4);
1231          if (m==15) /* We found a terminator */
1232          {
1233             return -1;
1234          } else if (m==14) /* Speex in-band request */
1235          {
1236             int ret = speex_inband_handler(bits, st->speex_callbacks, state);
1237             if (ret)
1238                return ret;
1239          } else if (m==13) /* User in-band request */
1240          {
1241             int ret = st->user_callback.func(bits, state, st->user_callback.data);
1242             if (ret)
1243                return ret;
1244          } else if (m>8) /* Invalid mode */
1245          {
1246             speex_warning("Invalid mode encountered: corrupted stream?");
1247             return -2;
1248          }
1249       
1250       } while (m>8);
1251
1252       /* Get the sub-mode that was used */
1253       st->submodeID = m;
1254
1255    }
1256 #ifdef EPIC_48K
1257    }
1258 #endif
1259    }
1260
1261    /* Shift all buffers by one frame */
1262    speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
1263    speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(spx_sig_t));
1264
1265    /* If null mode (no transmission), just set a couple things to zero*/
1266    if (st->submodes[st->submodeID] == NULL)
1267    {
1268       spx_coef_t *lpc;
1269       lpc = PUSH(stack,11, spx_coef_t);
1270       bw_lpc(GAMMA_SCALING*.93, st->interp_qlpc, lpc, 10);
1271       /*for (i=0;i<st->frameSize;i++)
1272         st->exc[i]=0;*/
1273       {
1274          float innov_gain=0;
1275          float pgain=GAIN_SCALING_1*st->last_pitch_gain;
1276          if (pgain>.6)
1277             pgain=.6;
1278          for (i=0;i<st->frameSize;i++)
1279             innov_gain += st->innov[i]*st->innov[i];
1280          innov_gain=sqrt(innov_gain/st->frameSize);
1281          for (i=0;i<st->frameSize;i++)
1282             st->exc[i]=0;
1283          speex_rand_vec(innov_gain, st->exc, st->frameSize);
1284       }
1285
1286
1287       st->first=1;
1288
1289       /* Final signal synthesis from excitation */
1290       iir_mem2(st->exc, lpc, st->frame, st->frameSize, st->lpcSize, st->mem_sp);
1291
1292       for (i=0;i<st->frameSize;i++)
1293       {
1294          spx_word32_t sig = PSHR(st->frame[i],SIG_SHIFT);
1295          if (sig>32767)
1296             sig = 32767;
1297          if (sig<-32767)
1298             sig = -32767;
1299          out[i]=sig;
1300       }
1301
1302       st->count_lost=0;
1303       return 0;
1304    }
1305
1306    /* Unquantize LSPs */
1307    SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits);
1308
1309    /*Damp memory if a frame was lost and the LSP changed too much*/
1310    if (st->count_lost)
1311    {
1312       float lsp_dist=0, fact;
1313       for (i=0;i<st->lpcSize;i++)
1314          lsp_dist += fabs(st->old_qlsp[i] - st->qlsp[i]);
1315       lsp_dist /= LSP_SCALING*LSP_SCALING;
1316       fact = .6*exp(-.2*lsp_dist);
1317       for (i=0;i<2*st->lpcSize;i++)
1318          st->mem_sp[i] = (spx_mem_t)(st->mem_sp[i]*fact);
1319    }
1320
1321
1322    /* Handle first frame and lost-packet case */
1323    if (st->first || st->count_lost)
1324    {
1325       for (i=0;i<st->lpcSize;i++)
1326          st->old_qlsp[i] = st->qlsp[i];
1327    }
1328
1329 #ifdef EPIC_48K
1330    if (st->lbr_48k) {
1331       pitch_half[0] = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
1332       pitch_half[1] = pitch_half[0]+speex_bits_unpack_unsigned(bits, 2)-1;
1333
1334       ol_pitch_id = speex_bits_unpack_unsigned(bits, 3);
1335       ol_pitch_coef=GAIN_SCALING*0.13514*ol_pitch_id;
1336
1337       {
1338          int qe;
1339          qe = speex_bits_unpack_unsigned(bits, 4);
1340          ol_gain = SIG_SCALING*exp((qe+2)/2.1),SIG_SHIFT;
1341       }
1342
1343    } else {
1344 #endif
1345
1346    /* Get open-loop pitch estimation for low bit-rate pitch coding */
1347    if (SUBMODE(lbr_pitch)!=-1)
1348    {
1349       ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
1350    } 
1351    
1352    if (SUBMODE(forced_pitch_gain))
1353    {
1354       int quant;
1355       quant = speex_bits_unpack_unsigned(bits, 4);
1356       ol_pitch_coef=GAIN_SCALING*0.066667*quant;
1357    }
1358    
1359    /* Get global excitation gain */
1360    {
1361       int qe;
1362       qe = speex_bits_unpack_unsigned(bits, 5);
1363 #ifdef FIXED_POINT
1364       ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]);
1365 #else
1366       ol_gain = SIG_SCALING*exp(qe/3.5);
1367 #endif
1368    }
1369 #ifdef EPIC_48K
1370    }
1371 #endif
1372
1373    awk1=PUSH(stack, st->lpcSize+1, spx_coef_t);
1374    awk2=PUSH(stack, st->lpcSize+1, spx_coef_t);
1375    awk3=PUSH(stack, st->lpcSize+1, spx_coef_t);
1376
1377    if (st->submodeID==1)
1378    {
1379       int extra;
1380       extra = speex_bits_unpack_unsigned(bits, 4);
1381
1382       if (extra==15)
1383          st->dtx_enabled=1;
1384       else
1385          st->dtx_enabled=0;
1386    }
1387    if (st->submodeID>1)
1388       st->dtx_enabled=0;
1389
1390    /*Loop on subframes */
1391    for (sub=0;sub<st->nbSubframes;sub++)
1392    {
1393       int offset;
1394       spx_sig_t *sp, *exc;
1395       spx_word16_t tmp;
1396
1397 #ifdef EPIC_48K
1398       if (st->lbr_48k)
1399       {
1400          if (sub*2 < st->nbSubframes)
1401             ol_pitch = pitch_half[0];
1402          else
1403             ol_pitch = pitch_half[1];
1404       }
1405 #endif
1406
1407       /* Offset relative to start of frame */
1408       offset = st->subframeSize*sub;
1409       /* Original signal */
1410       sp=st->frame+offset;
1411       /* Excitation */
1412       exc=st->exc+offset;
1413       /* Excitation after post-filter*/
1414
1415       /* LSP interpolation (quantized and unquantized) */
1416       lsp_interpolate(st->old_qlsp, st->qlsp, st->interp_qlsp, st->lpcSize, sub, st->nbSubframes);
1417
1418       /* Make sure the LSP's are stable */
1419       lsp_enforce_margin(st->interp_qlsp, st->lpcSize, LSP_MARGIN);
1420
1421
1422       /* Compute interpolated LPCs (unquantized) */
1423       lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);
1424
1425       /* Compute enhanced synthesis filter */
1426       if (st->lpc_enh_enabled)
1427       {
1428          bw_lpc(SUBMODE(lpc_enh_k1), st->interp_qlpc, awk1, st->lpcSize);
1429          bw_lpc(SUBMODE(lpc_enh_k2), st->interp_qlpc, awk2, st->lpcSize);
1430          bw_lpc(SUBMODE(lpc_enh_k3), st->interp_qlpc, awk3, st->lpcSize);
1431       }
1432
1433       /* Compute analysis filter at w=pi */
1434       {
1435          spx_word32_t pi_g=st->interp_qlpc[0];
1436          for (i=1;i<=st->lpcSize;i+=2)
1437          {
1438             pi_g += -st->interp_qlpc[i] +  st->interp_qlpc[i+1];
1439          }
1440          st->pi_gain[sub] = pi_g;
1441       }
1442
1443       /* Reset excitation */
1444       for (i=0;i<st->subframeSize;i++)
1445          exc[i]=0;
1446
1447       /*Adaptive codebook contribution*/
1448       if (SUBMODE(ltp_unquant))
1449       {
1450          int pit_min, pit_max;
1451          /* Handle pitch constraints if any */
1452          if (SUBMODE(lbr_pitch) != -1)
1453          {
1454             int margin;
1455             margin = SUBMODE(lbr_pitch);
1456             if (margin)
1457             {
1458 /* GT - need optimization?
1459                if (ol_pitch < st->min_pitch+margin-1)
1460                   ol_pitch=st->min_pitch+margin-1;
1461                if (ol_pitch > st->max_pitch-margin)
1462                   ol_pitch=st->max_pitch-margin;
1463                pit_min = ol_pitch-margin+1;
1464                pit_max = ol_pitch+margin;
1465 */
1466                pit_min = ol_pitch-margin+1;
1467                if (pit_min < st->min_pitch)
1468                   pit_min = st->min_pitch;
1469                pit_max = ol_pitch+margin;
1470                if (pit_max > st->max_pitch)
1471                   pit_max = st->max_pitch;
1472             } else {
1473                pit_min = pit_max = ol_pitch;
1474             }
1475          } else {
1476             pit_min = st->min_pitch;
1477             pit_max = st->max_pitch;
1478          }
1479
1480
1481 #ifdef EPIC_48K
1482          if (st->lbr_48k)
1483          {
1484              SUBMODE(ltp_unquant)(exc, pit_min, pit_max, ol_pitch_coef, SUBMODE(ltp_params), 
1485                                   st->subframeSize, &pitch, &pitch_gain[0], bits, stack, 
1486                                   st->count_lost, offset, st->last_pitch_gain, ol_pitch_id);
1487          } else {
1488 #endif
1489
1490              SUBMODE(ltp_unquant)(exc, pit_min, pit_max, ol_pitch_coef, SUBMODE(ltp_params), 
1491                                   st->subframeSize, &pitch, &pitch_gain[0], bits, stack, 
1492                                   st->count_lost, offset, st->last_pitch_gain, 0);
1493
1494 #ifdef EPIC_48K
1495          }
1496 #endif
1497
1498          
1499          /* If we had lost frames, check energy of last received frame */
1500          if (st->count_lost && ol_gain < st->last_ol_gain)
1501          {
1502             float fact = (float)ol_gain/(st->last_ol_gain+1);
1503             for (i=0;i<st->subframeSize;i++)
1504                exc[i]*=fact;
1505          }
1506
1507          tmp = gain_3tap_to_1tap(pitch_gain);
1508
1509          pitch_average += tmp;
1510          if (tmp>best_pitch_gain)
1511          {
1512             best_pitch = pitch;
1513             best_pitch_gain = tmp;
1514          }
1515       } else {
1516          speex_error("No pitch prediction, what's wrong");
1517       }
1518       
1519       /* Unquantize the innovation */
1520       {
1521          int q_energy;
1522          spx_word32_t ener;
1523          spx_sig_t *innov;
1524          
1525          innov = st->innov+sub*st->subframeSize;
1526          for (i=0;i<st->subframeSize;i++)
1527             innov[i]=0;
1528
1529          /* Decode sub-frame gain correction */
1530          if (SUBMODE(have_subframe_gain)==3)
1531          {
1532             q_energy = speex_bits_unpack_unsigned(bits, 3);
1533             ener = MULT16_32_Q14(exc_gain_quant_scal3[q_energy],ol_gain);
1534          } else if (SUBMODE(have_subframe_gain)==1)
1535          {
1536             q_energy = speex_bits_unpack_unsigned(bits, 1);
1537             ener = MULT16_32_Q14(exc_gain_quant_scal1[q_energy],ol_gain);
1538          } else {
1539             ener = ol_gain;
1540          }
1541                   
1542          if (SUBMODE(innovation_unquant))
1543          {
1544             /*Fixed codebook contribution*/
1545             SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), st->subframeSize, bits, stack);
1546          } else {
1547             speex_error("No fixed codebook");
1548          }
1549
1550          /* De-normalize innovation and update excitation */
1551 #ifdef FIXED_POINT
1552          signal_mul(innov, innov, ener, st->subframeSize);
1553 #else
1554          signal_mul(innov, innov, ener, st->subframeSize);
1555 #endif
1556          /*Vocoder mode*/
1557          if (st->submodeID==1) 
1558          {
1559             float g=ol_pitch_coef*GAIN_SCALING_1;
1560
1561             
1562             for (i=0;i<st->subframeSize;i++)
1563                exc[i]=0;
1564             while (st->voc_offset<st->subframeSize)
1565             {
1566                if (st->voc_offset>=0)
1567                   exc[st->voc_offset]=SIG_SCALING*sqrt(1.0*ol_pitch);
1568                st->voc_offset+=ol_pitch;
1569             }
1570             st->voc_offset -= st->subframeSize;
1571
1572             g=.5+2*(g-.6);
1573             if (g<0)
1574                g=0;
1575             if (g>1)
1576                g=1;
1577             for (i=0;i<st->subframeSize;i++)
1578             {
1579                float exci=exc[i];
1580                exc[i]=.8*g*exc[i]*ol_gain/SIG_SCALING + .6*g*st->voc_m1*ol_gain/SIG_SCALING + .5*g*innov[i] - .5*g*st->voc_m2 + (1-g)*innov[i];
1581                st->voc_m1 = exci;
1582                st->voc_m2=innov[i];
1583                st->voc_mean = .95*st->voc_mean + .05*exc[i];
1584                exc[i]-=st->voc_mean;
1585             }
1586          } else {
1587             for (i=0;i<st->subframeSize;i++)
1588                exc[i]+=innov[i];
1589             /*print_vec(exc, 40, "innov");*/
1590          }
1591          /* Decode second codebook (only for some modes) */
1592          if (SUBMODE(double_codebook))
1593          {
1594             char *tmp_stack=stack;
1595             spx_sig_t *innov2 = PUSH(tmp_stack, st->subframeSize, spx_sig_t);
1596             for (i=0;i<st->subframeSize;i++)
1597                innov2[i]=0;
1598             SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, bits, tmp_stack);
1599             signal_mul(innov2, innov2, ener*(1/2.2), st->subframeSize);
1600             for (i=0;i<st->subframeSize;i++)
1601                exc[i] += innov2[i];
1602          }
1603
1604       }
1605
1606       for (i=0;i<st->subframeSize;i++)
1607          sp[i]=exc[i];
1608
1609       /* Signal synthesis */
1610       if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0)
1611          comb_filter(exc, sp, st->interp_qlpc, st->lpcSize, st->subframeSize,
1612                               pitch, pitch_gain, SUBMODE(comb_gain), st->comb_mem);
1613
1614       if (st->lpc_enh_enabled)
1615       {
1616          /* Use enhanced LPC filter */
1617          filter_mem2(sp, awk2, awk1, sp, st->subframeSize, st->lpcSize, 
1618                      st->mem_sp+st->lpcSize);
1619          filter_mem2(sp, awk3, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, 
1620                      st->mem_sp);
1621       } else {
1622          /* Use regular filter */
1623          for (i=0;i<st->lpcSize;i++)
1624             st->mem_sp[st->lpcSize+i] = 0;
1625          iir_mem2(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, 
1626                      st->mem_sp);
1627       }
1628    }
1629    
1630    /*Copy output signal*/   
1631    for (i=0;i<st->frameSize;i++)
1632    {
1633       spx_word32_t sig = PSHR(st->frame[i],SIG_SHIFT);
1634       if (sig>32767)
1635          sig = 32767;
1636       if (sig<-32767)
1637          sig = -32767;
1638      out[i]=sig;
1639    }
1640
1641    /*for (i=0;i<st->frameSize;i++)
1642      printf ("%d\n", (int)st->frame[i]);*/
1643
1644    /* Store the LSPs for interpolation in the next frame */
1645    for (i=0;i<st->lpcSize;i++)
1646       st->old_qlsp[i] = st->qlsp[i];
1647
1648    /* The next frame will not be the first (Duh!) */
1649    st->first = 0;
1650    st->count_lost=0;
1651    st->last_pitch = best_pitch;
1652 #ifdef FIXED_POINT
1653    st->last_pitch_gain = PSHR(pitch_average,2);
1654 #else
1655    st->last_pitch_gain = .25*pitch_average;   
1656 #endif
1657    st->pitch_gain_buf[st->pitch_gain_buf_idx++] = st->last_pitch_gain;
1658    if (st->pitch_gain_buf_idx > 2) /* rollover */
1659       st->pitch_gain_buf_idx = 0;
1660
1661    st->last_ol_gain = ol_gain;
1662
1663    return 0;
1664 }
1665
1666 int nb_encoder_ctl(void *state, int request, void *ptr)
1667 {
1668    EncState *st;
1669    st=(EncState*)state;     
1670    switch(request)
1671    {
1672    case SPEEX_GET_FRAME_SIZE:
1673       (*(int*)ptr) = st->frameSize;
1674       break;
1675    case SPEEX_SET_LOW_MODE:
1676    case SPEEX_SET_MODE:
1677       st->submodeSelect = st->submodeID = (*(int*)ptr);
1678       break;
1679    case SPEEX_GET_LOW_MODE:
1680    case SPEEX_GET_MODE:
1681       (*(int*)ptr) = st->submodeID;
1682       break;
1683    case SPEEX_SET_VBR:
1684       st->vbr_enabled = (*(int*)ptr);
1685       break;
1686    case SPEEX_GET_VBR:
1687       (*(int*)ptr) = st->vbr_enabled;
1688       break;
1689    case SPEEX_SET_VAD:
1690       st->vad_enabled = (*(int*)ptr);
1691       break;
1692    case SPEEX_GET_VAD:
1693       (*(int*)ptr) = st->vad_enabled;
1694       break;
1695    case SPEEX_SET_DTX:
1696       st->dtx_enabled = (*(int*)ptr);
1697       break;
1698    case SPEEX_GET_DTX:
1699       (*(int*)ptr) = st->dtx_enabled;
1700       break;
1701    case SPEEX_SET_ABR:
1702       st->abr_enabled = (*(int*)ptr);
1703       st->vbr_enabled = 1;
1704       {
1705          int i=10, rate, target;
1706          float vbr_qual;
1707          target = (*(int*)ptr);
1708          while (i>=0)
1709          {
1710             speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i);
1711             speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate);
1712             if (rate <= target)
1713                break;
1714             i--;
1715          }
1716          vbr_qual=i;
1717          if (vbr_qual<0)
1718             vbr_qual=0;
1719          speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual);
1720          st->abr_count=0;
1721          st->abr_drift=0;
1722          st->abr_drift2=0;
1723       }
1724       
1725       break;
1726    case SPEEX_GET_ABR:
1727       (*(int*)ptr) = st->abr_enabled;
1728       break;
1729    case SPEEX_SET_VBR_QUALITY:
1730       st->vbr_quality = (*(float*)ptr);
1731       break;
1732    case SPEEX_GET_VBR_QUALITY:
1733       (*(float*)ptr) = st->vbr_quality;
1734       break;
1735    case SPEEX_SET_QUALITY:
1736       {
1737          int quality = (*(int*)ptr);
1738          if (quality < 0)
1739             quality = 0;
1740          if (quality > 10)
1741             quality = 10;
1742          st->submodeSelect = st->submodeID = ((SpeexNBMode*)(st->mode->mode))->quality_map[quality];
1743       }
1744       break;
1745    case SPEEX_SET_COMPLEXITY:
1746       st->complexity = (*(int*)ptr);
1747       if (st->complexity<1)
1748          st->complexity=1;
1749       break;
1750    case SPEEX_GET_COMPLEXITY:
1751       (*(int*)ptr) = st->complexity;
1752       break;
1753    case SPEEX_SET_BITRATE:
1754       {
1755          int i=10, rate, target;
1756          target = (*(int*)ptr);
1757          while (i>=0)
1758          {
1759             speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i);
1760             speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate);
1761             if (rate <= target)
1762                break;
1763             i--;
1764          }
1765       }
1766       break;
1767    case SPEEX_GET_BITRATE:
1768       if (st->submodes[st->submodeID])
1769          (*(int*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize;
1770       else
1771          (*(int*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize;
1772       break;
1773    case SPEEX_SET_SAMPLING_RATE:
1774       st->sampling_rate = (*(int*)ptr);
1775       break;
1776    case SPEEX_GET_SAMPLING_RATE:
1777       (*(int*)ptr)=st->sampling_rate;
1778       break;
1779    case SPEEX_RESET_STATE:
1780       {
1781          int i;
1782          st->bounded_pitch = 1;
1783          st->first = 1;
1784          for (i=0;i<st->lpcSize;i++)
1785             st->lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1);
1786          for (i=0;i<st->lpcSize;i++)
1787             st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0;
1788          for (i=0;i<st->bufSize;i++)
1789             st->excBuf[i]=st->swBuf[i]=st->inBuf[i]=st->exc2Buf[i]=0;
1790       }
1791       break;
1792    case SPEEX_SET_SUBMODE_ENCODING:
1793       st->encode_submode = (*(int*)ptr);
1794       break;
1795    case SPEEX_GET_SUBMODE_ENCODING:
1796       (*(int*)ptr) = st->encode_submode;
1797       break;
1798    case SPEEX_GET_LOOKAHEAD:
1799       (*(int*)ptr)=(st->windowSize-st->frameSize);
1800       break;
1801    case SPEEX_GET_PI_GAIN:
1802       {
1803          int i;
1804          spx_word32_t *g = (spx_word32_t*)ptr;
1805          for (i=0;i<st->nbSubframes;i++)
1806             g[i]=st->pi_gain[i];
1807       }
1808       break;
1809    case SPEEX_GET_EXC:
1810       {
1811          int i;
1812          spx_sig_t *e = (spx_sig_t*)ptr;
1813          for (i=0;i<st->frameSize;i++)
1814             e[i]=st->exc[i];
1815       }
1816       break;
1817    case SPEEX_GET_INNOV:
1818       {
1819          int i;
1820          spx_sig_t *e = (spx_sig_t*)ptr;
1821          for (i=0;i<st->frameSize;i++)
1822             e[i]=st->innov[i];
1823       }
1824       break;
1825    case SPEEX_GET_RELATIVE_QUALITY:
1826       (*(float*)ptr)=st->relative_quality;
1827       break;
1828    default:
1829       speex_warning_int("Unknown nb_ctl request: ", request);
1830       return -1;
1831    }
1832    return 0;
1833 }
1834
1835 int nb_decoder_ctl(void *state, int request, void *ptr)
1836 {
1837    DecState *st;
1838    st=(DecState*)state;
1839    switch(request)
1840    {
1841    case SPEEX_SET_LOW_MODE:
1842    case SPEEX_SET_MODE:
1843       st->submodeID = (*(int*)ptr);
1844       break;
1845    case SPEEX_GET_LOW_MODE:
1846    case SPEEX_GET_MODE:
1847       (*(int*)ptr) = st->submodeID;
1848       break;
1849    case SPEEX_SET_ENH:
1850       st->lpc_enh_enabled = *((int*)ptr);
1851       break;
1852    case SPEEX_GET_ENH:
1853       *((int*)ptr) = st->lpc_enh_enabled;
1854       break;
1855    case SPEEX_GET_FRAME_SIZE:
1856       (*(int*)ptr) = st->frameSize;
1857       break;
1858    case SPEEX_GET_BITRATE:
1859       if (st->submodes[st->submodeID])
1860          (*(int*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize;
1861       else
1862          (*(int*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize;
1863       break;
1864    case SPEEX_SET_SAMPLING_RATE:
1865       st->sampling_rate = (*(int*)ptr);
1866       break;
1867    case SPEEX_GET_SAMPLING_RATE:
1868       (*(int*)ptr)=st->sampling_rate;
1869       break;
1870    case SPEEX_SET_HANDLER:
1871       {
1872          SpeexCallback *c = (SpeexCallback*)ptr;
1873          st->speex_callbacks[c->callback_id].func=c->func;
1874          st->speex_callbacks[c->callback_id].data=c->data;
1875          st->speex_callbacks[c->callback_id].callback_id=c->callback_id;
1876       }
1877       break;
1878    case SPEEX_SET_USER_HANDLER:
1879       {
1880          SpeexCallback *c = (SpeexCallback*)ptr;
1881          st->user_callback.func=c->func;
1882          st->user_callback.data=c->data;
1883          st->user_callback.callback_id=c->callback_id;
1884       }
1885       break;
1886    case SPEEX_RESET_STATE:
1887       {
1888          int i;
1889          for (i=0;i<2*st->lpcSize;i++)
1890             st->mem_sp[i]=0;
1891          for (i=0;i<st->bufSize;i++)
1892             st->excBuf[i]=st->inBuf[i]=0;
1893       }
1894       break;
1895    case SPEEX_SET_SUBMODE_ENCODING:
1896       st->encode_submode = (*(int*)ptr);
1897       break;
1898    case SPEEX_GET_SUBMODE_ENCODING:
1899       (*(int*)ptr) = st->encode_submode;
1900       break;
1901    case SPEEX_GET_PI_GAIN:
1902       {
1903          int i;
1904          spx_word32_t *g = (spx_word32_t*)ptr;
1905          for (i=0;i<st->nbSubframes;i++)
1906             g[i]=st->pi_gain[i];
1907       }
1908       break;
1909    case SPEEX_GET_EXC:
1910       {
1911          int i;
1912          spx_sig_t *e = (spx_sig_t*)ptr;
1913          for (i=0;i<st->frameSize;i++)
1914             e[i]=st->exc[i];
1915       }
1916       break;
1917    case SPEEX_GET_INNOV:
1918       {
1919          int i;
1920          spx_sig_t *e = (spx_sig_t*)ptr;
1921          for (i=0;i<st->frameSize;i++)
1922             e[i]=st->innov[i];
1923       }
1924       break;
1925    case SPEEX_GET_DTX_STATUS:
1926       *((int*)ptr) = st->dtx_enabled;
1927       break;
1928    default:
1929       speex_warning_int("Unknown nb_ctl request: ", request);
1930       return -1;
1931    }
1932    return 0;
1933 }