More cleanups, do something more intelligent with LPC->LSP
[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 <stdlib.h>
33 #include <stdio.h>
34 #include <math.h>
35 #include "nb_celp.h"
36 #include "lpc.h"
37 #include "lsp.h"
38 #include "ltp.h"
39 #include "quant_lsp.h"
40 #include "cb_search.h"
41 #include "filters.h"
42 #include "stack_alloc.h"
43 #include "vq.h"
44 #include "speex_bits.h"
45 #include "vbr.h"
46 #include "misc.h"
47 #include "speex_callbacks.h"
48
49 extern int training_weight;
50 #ifndef M_PI
51 #define M_PI           3.14159265358979323846  /* pi */
52 #endif
53
54 #define SUBMODE(x) st->submodes[st->submodeID]->x
55
56 float exc_gain_quant_scal3[8]={-2.794750, -1.810660, -1.169850, -0.848119, -0.587190, -0.329818, -0.063266, 0.282826};
57
58 float exc_gain_quant_scal1[2]={-0.35, 0.05};
59 /*float exc_gain_quant_scal1[2]={-0.35, 0.05};*/
60
61 #define sqr(x) ((x)*(x))
62 #define min(a,b) ((a) < (b) ? (a) : (b))
63
64 void *nb_encoder_init(SpeexMode *m)
65 {
66    EncState *st;
67    SpeexNBMode *mode;
68    int i;
69
70    mode=m->mode;
71    st = speex_alloc(sizeof(EncState));
72    st->mode=m;
73    /* Codec parameters, should eventually have several "modes"*/
74    st->frameSize = mode->frameSize;
75    st->windowSize = st->frameSize*3/2;
76    st->nbSubframes=mode->frameSize/mode->subframeSize;
77    st->subframeSize=mode->subframeSize;
78    st->lpcSize = mode->lpcSize;
79    st->bufSize = mode->bufSize;
80    st->gamma1=mode->gamma1;
81    st->gamma2=mode->gamma2;
82    st->min_pitch=mode->pitchStart;
83    st->max_pitch=mode->pitchEnd;
84    st->lag_factor=mode->lag_factor;
85    st->lpc_floor = mode->lpc_floor;
86    st->preemph = mode->preemph;
87   
88    st->submodes=mode->submodes;
89    st->submodeID=mode->defaultSubmode;
90    st->pre_mem=0;
91    st->pre_mem2=0;
92    st->bounded_pitch = 0;
93
94    /* Allocating input buffer */
95    st->inBuf = speex_alloc(st->bufSize*sizeof(float));
96    st->frame = st->inBuf + st->bufSize - st->windowSize;
97    /* Allocating excitation buffer */
98    st->excBuf = speex_alloc(st->bufSize*sizeof(float));
99    st->exc = st->excBuf + st->bufSize - st->windowSize;
100    st->swBuf = speex_alloc(st->bufSize*sizeof(float));
101    st->sw = st->swBuf + st->bufSize - st->windowSize;
102
103    st->exc2Buf = speex_alloc(st->bufSize*sizeof(float));
104    st->exc2 = st->exc2Buf + st->bufSize - st->windowSize;
105
106    st->innov = speex_alloc(st->frameSize*sizeof(float));
107
108    /* Asymetric "pseudo-Hamming" window */
109    {
110       int part1, part2;
111       part1 = st->subframeSize*7/2;
112       part2 = st->subframeSize*5/2;
113       st->window = speex_alloc(st->windowSize*sizeof(float));
114       for (i=0;i<part1;i++)
115          st->window[i]=.54-.46*cos(M_PI*i/part1);
116       for (i=0;i<part2;i++)
117          st->window[part1+i]=.54+.46*cos(M_PI*i/part2);
118    }
119    /* Create the window for autocorrelation (lag-windowing) */
120    st->lagWindow = speex_alloc((st->lpcSize+1)*sizeof(float));
121    for (i=0;i<st->lpcSize+1;i++)
122       st->lagWindow[i]=exp(-.5*sqr(2*M_PI*st->lag_factor*i));
123
124    st->autocorr = speex_alloc((st->lpcSize+1)*sizeof(float));
125
126    st->stack = speex_alloc(20000*sizeof(float));
127
128    st->buf2 = speex_alloc(st->windowSize*sizeof(float));
129
130    st->lpc = speex_alloc((st->lpcSize+1)*sizeof(float));
131    st->interp_lpc = speex_alloc((st->lpcSize+1)*sizeof(float));
132    st->interp_qlpc = speex_alloc((st->lpcSize+1)*sizeof(float));
133    st->bw_lpc1 = speex_alloc((st->lpcSize+1)*sizeof(float));
134    st->bw_lpc2 = speex_alloc((st->lpcSize+1)*sizeof(float));
135
136    st->lsp = speex_alloc(st->lpcSize*sizeof(float));
137    st->qlsp = speex_alloc(st->lpcSize*sizeof(float));
138    st->old_lsp = speex_alloc(st->lpcSize*sizeof(float));
139    st->old_qlsp = speex_alloc(st->lpcSize*sizeof(float));
140    st->interp_lsp = speex_alloc(st->lpcSize*sizeof(float));
141    st->interp_qlsp = speex_alloc(st->lpcSize*sizeof(float));
142    st->rc = speex_alloc(st->lpcSize*sizeof(float));
143    st->first = 1;
144    for (i=0;i<st->lpcSize;i++)
145    {
146       st->lsp[i]=(M_PI*((float)(i+1)))/(st->lpcSize+1);
147    }
148
149    st->mem_sp = speex_alloc(st->lpcSize*sizeof(float));
150    st->mem_sw = speex_alloc(st->lpcSize*sizeof(float));
151    st->mem_sw_whole = speex_alloc(st->lpcSize*sizeof(float));
152    st->mem_exc = speex_alloc(st->lpcSize*sizeof(float));
153
154    st->pi_gain = speex_alloc(st->nbSubframes*sizeof(float));
155
156    st->pitch = speex_alloc(st->nbSubframes*sizeof(int));
157
158    if (1) {
159       st->vbr = speex_alloc(sizeof(VBRState));
160       vbr_init(st->vbr);
161       st->vbr_quality = 8;
162       st->vbr_enabled = 0;
163    } else {
164       st->vbr = 0;
165    }
166    st->complexity=2;
167
168    return st;
169 }
170
171 void nb_encoder_destroy(void *state)
172 {
173    EncState *st=state;
174    /* Free all allocated memory */
175    speex_free(st->inBuf);
176    speex_free(st->excBuf);
177    speex_free(st->swBuf);
178    speex_free(st->exc2Buf);
179    speex_free(st->innov);
180    speex_free(st->stack);
181
182    speex_free(st->window);
183    speex_free(st->buf2);
184    speex_free(st->lpc);
185    speex_free(st->interp_lpc);
186    speex_free(st->interp_qlpc);
187    
188    speex_free(st->bw_lpc1);
189    speex_free(st->bw_lpc2);
190    speex_free(st->autocorr);
191    speex_free(st->lagWindow);
192    speex_free(st->lsp);
193    speex_free(st->qlsp);
194    speex_free(st->old_lsp);
195    speex_free(st->interp_lsp);
196    speex_free(st->old_qlsp);
197    speex_free(st->interp_qlsp);
198    speex_free(st->rc);
199
200    speex_free(st->mem_sp);
201    speex_free(st->mem_sw);
202    speex_free(st->mem_sw_whole);
203    speex_free(st->mem_exc);
204    speex_free(st->pi_gain);
205    speex_free(st->pitch);
206
207    vbr_destroy(st->vbr);
208    speex_free(st->vbr);
209
210    /*Free state memory... should be last*/
211    speex_free(st);
212 }
213
214 void nb_encode(void *state, float *in, SpeexBits *bits)
215 {
216    EncState *st;
217    int i, sub, roots;
218    int ol_pitch;
219    float ol_pitch_coef;
220    float ol_gain;
221    float delta_qual=0;
222    float *res, *target, *mem;
223    float *stack;
224    float *syn_resp;
225
226    st=state;
227    stack=st->stack;
228
229    /* Copy new data in input buffer */
230    speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
231    st->inBuf[st->bufSize-st->frameSize] = in[0] - st->preemph*st->pre_mem;
232    for (i=1;i<st->frameSize;i++)
233       st->inBuf[st->bufSize-st->frameSize+i] = in[i] - st->preemph*in[i-1];
234    st->pre_mem = in[st->frameSize-1];
235
236    /* Move signals 1 frame towards the past */
237    speex_move(st->exc2Buf, st->exc2Buf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
238    speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
239    speex_move(st->swBuf, st->swBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
240
241
242    /* Window for analysis */
243    for (i=0;i<st->windowSize;i++)
244       st->buf2[i] = st->frame[i] * st->window[i];
245
246    /* Compute auto-correlation */
247    autocorr(st->buf2, st->autocorr, st->lpcSize+1, st->windowSize);
248
249    st->autocorr[0] += 10;        /* prevents NANs */
250    st->autocorr[0] *= st->lpc_floor; /* Noise floor in auto-correlation domain */
251
252    /* Lag windowing: equivalent to filtering in the power-spectrum domain */
253    for (i=0;i<st->lpcSize+1;i++)
254       st->autocorr[i] *= st->lagWindow[i];
255
256    /* Levinson-Durbin */
257    wld(st->lpc+1, st->autocorr, st->rc, st->lpcSize);
258    st->lpc[0]=1;
259
260    /* LPC to LSPs (x-domain) transform */
261    roots=lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 15, 0.2, stack);
262    if (roots==st->lpcSize)
263    {
264       /* LSP x-domain to angle domain*/
265       for (i=0;i<st->lpcSize;i++)
266          st->lsp[i] = acos(st->lsp[i]);
267    } else {
268       if (st->complexity>1)
269          roots = lpc_to_lsp (st->lpc, st->lpcSize, st->lsp, 11, 0.05, stack);
270       if (roots==st->lpcSize) 
271       {
272          /* LSP x-domain to angle domain*/
273          for (i=0;i<st->lpcSize;i++)
274             st->lsp[i] = acos(st->lsp[i]);
275       } else {
276          /*If we can't find all LSP's, do some damage control and use previous filter*/
277          for (i=0;i<st->lpcSize;i++)
278          {
279             st->lsp[i]=st->old_lsp[i];
280          }
281       }
282    }
283
284    /* LSP Quantization */
285    if (st->first)
286    {
287       for (i=0;i<st->lpcSize;i++)
288          st->old_lsp[i] = st->lsp[i];
289    }
290
291    if (0) {
292       float dd=0;
293       for (i=0;i<st->lpcSize;i++)
294          dd += fabs(st->old_lsp[i] - st->lsp[i]);
295       printf ("lspdist = %f\n", dd);
296    }
297
298    /* Whole frame analysis (open-loop estimation of pitch and excitation gain) */
299    {
300       for (i=0;i<st->lpcSize;i++)
301          st->interp_lsp[i] = .5*st->old_lsp[i] + .5*st->lsp[i];
302
303       lsp_enforce_margin(st->interp_lsp, st->lpcSize, .002);
304
305       /* Compute interpolated LPCs (unquantized) for whole frame*/
306       for (i=0;i<st->lpcSize;i++)
307          st->interp_lsp[i] = cos(st->interp_lsp[i]);
308       lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);
309
310
311       /*Open-loop pitch*/
312       if (!st->submodes[st->submodeID] || st->vbr_enabled || SUBMODE(forced_pitch_gain) ||
313           SUBMODE(lbr_pitch) != -1)
314       {
315          int nol_pitch[4];
316          float nol_pitch_coef[4];
317          
318          bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
319          bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
320          
321          filter_mem2(st->frame, st->bw_lpc1, st->bw_lpc2, st->sw, st->frameSize, st->lpcSize, st->mem_sw_whole);
322
323          open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSize, 
324                                nol_pitch, nol_pitch_coef, 4, stack);
325          ol_pitch=nol_pitch[0];
326          ol_pitch_coef = nol_pitch_coef[0];
327          /*Try to remove pitch multiples*/
328          for (i=1;i<4;i++)
329          {
330             if ((nol_pitch_coef[i] > .85*ol_pitch_coef) && 
331                 (fabs(2*nol_pitch[i]-ol_pitch)<=2 || fabs(3*nol_pitch[i]-ol_pitch)<=4 || 
332                  fabs(4*nol_pitch[i]-ol_pitch)<=6 || fabs(5*nol_pitch[i]-ol_pitch)<=8))
333             {
334                /*ol_pitch_coef=nol_pitch_coef[i];*/
335                ol_pitch = nol_pitch[i];
336             }
337          }
338          /*ol_pitch_coef = sqrt(ol_pitch_coef);*/
339          /*printf ("ol_pitch: %d %f\n", ol_pitch, ol_pitch_coef);*/
340       } else {
341          ol_pitch=0;
342          ol_pitch_coef=0;
343       }
344       /*Compute "real" excitation*/
345       fir_mem2(st->frame, st->interp_lpc, st->exc, st->frameSize, st->lpcSize, st->mem_exc);
346
347       /* Compute open-loop excitation gain */
348       ol_gain=0;
349       for (i=0;i<st->frameSize;i++)
350          ol_gain += st->exc[i]*st->exc[i];
351       
352       ol_gain=sqrt(1+ol_gain/st->frameSize);
353    }
354
355    /*Experimental VBR stuff*/
356    if (st->vbr)
357    {
358       delta_qual = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch, ol_pitch_coef);
359       /*if (delta_qual<0)*/
360          delta_qual*=.1*(3+st->vbr_quality);
361       if (st->vbr_enabled) 
362       {
363          int qual = (int)floor(st->vbr_quality+delta_qual+.5);
364          if (qual<1 && delta_qual>-3.5)
365             qual=1;
366          if (qual<0)
367             qual=0;
368          if (qual>10)
369             qual=10;
370          if (qual==10 && st->vbr_quality<10)
371             qual=9;
372          speex_encoder_ctl(state, SPEEX_SET_QUALITY, &qual);
373       }
374    }
375    /*printf ("VBR quality = %f\n", vbr_qual);*/
376
377    /* First, transmit a zero for narrowband */
378    speex_bits_pack(bits, 0, 1);
379
380    /* Transmit the sub-mode we use for this frame */
381    speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS);
382
383
384    /* If null mode (no transmission), just set a couple things to zero*/
385    if (st->submodes[st->submodeID] == NULL)
386    {
387       for (i=0;i<st->frameSize;i++)
388          st->exc[i]=st->exc2[i]=st->sw[i]=0;
389
390       for (i=0;i<st->lpcSize;i++)
391          st->mem_sw[i]=0;
392       st->first=1;
393
394       /* Final signal synthesis from excitation */
395       iir_mem2(st->exc, st->interp_qlpc, st->frame, st->subframeSize, st->lpcSize, st->mem_sp);
396
397       in[0] = st->frame[0] + st->preemph*st->pre_mem2;
398       for (i=1;i<st->frameSize;i++)
399          in[i]=st->frame[i] + st->preemph*in[i-1];
400       st->pre_mem2=in[st->frameSize-1];
401
402       return;
403
404    }
405
406    /*Quantize LSPs*/
407 #if 1 /*0 for unquantized*/
408    SUBMODE(lsp_quant)(st->lsp, st->qlsp, st->lpcSize, bits);
409 #else
410    for (i=0;i<st->lpcSize;i++)
411      st->qlsp[i]=st->lsp[i];
412 #endif
413
414    /*If we use low bit-rate pitch mode, transmit open-loop pitch*/
415    if (SUBMODE(lbr_pitch)!=-1)
416    {
417       speex_bits_pack(bits, ol_pitch-st->min_pitch, 7);
418    } 
419    
420    if (SUBMODE(forced_pitch_gain))
421    {
422       int quant;
423       quant = (int)floor(.5+15*ol_pitch_coef);
424       if (quant>15)
425          quant=0;
426       if (quant<0)
427          quant=0;
428       speex_bits_pack(bits, quant, 4);
429       ol_pitch_coef=0.066667*quant;
430    }
431    
432    
433    /*Quantize and transmit open-loop excitation gain*/
434    {
435       int qe = (int)(floor(3.5*log(ol_gain)));
436       if (qe<0)
437          qe=0;
438       if (qe>31)
439          qe=31;
440       ol_gain = exp(qe/3.5);
441       speex_bits_pack(bits, qe, 5);
442    }
443
444    /* Special case for first frame */
445    if (st->first)
446    {
447       for (i=0;i<st->lpcSize;i++)
448          st->old_qlsp[i] = st->qlsp[i];
449    }
450
451    /* Filter response */
452    res = PUSH(stack, st->subframeSize);
453    /* Target signal */
454    target = PUSH(stack, st->subframeSize);
455    syn_resp = PUSH(stack, st->subframeSize);
456    mem = PUSH(stack, st->lpcSize);
457
458    /* Loop on sub-frames */
459    for (sub=0;sub<st->nbSubframes;sub++)
460    {
461       float tmp;
462       int   offset;
463       float *sp, *sw, *exc, *exc2;
464       int pitch;
465
466       /* Offset relative to start of frame */
467       offset = st->subframeSize*sub;
468       /* Original signal */
469       sp=st->frame+offset;
470       /* Excitation */
471       exc=st->exc+offset;
472       /* Weighted signal */
473       sw=st->sw+offset;
474
475       exc2=st->exc2+offset;
476
477
478       /* LSP interpolation (quantized and unquantized) */
479       tmp = (1.0 + sub)/st->nbSubframes;
480       for (i=0;i<st->lpcSize;i++)
481          st->interp_lsp[i] = (1-tmp)*st->old_lsp[i] + tmp*st->lsp[i];
482       for (i=0;i<st->lpcSize;i++)
483          st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i];
484
485       /* Make sure the filters are stable */
486       lsp_enforce_margin(st->interp_lsp, st->lpcSize, .002);
487       lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .002);
488
489       /* Compute interpolated LPCs (quantized and unquantized) */
490       for (i=0;i<st->lpcSize;i++)
491          st->interp_lsp[i] = cos(st->interp_lsp[i]);
492       lsp_to_lpc(st->interp_lsp, st->interp_lpc, st->lpcSize,stack);
493
494       for (i=0;i<st->lpcSize;i++)
495          st->interp_qlsp[i] = cos(st->interp_qlsp[i]);
496       lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);
497
498       /* Compute analysis filter gain at w=pi (for use in SB-CELP) */
499       tmp=1;
500       st->pi_gain[sub]=0;
501       for (i=0;i<=st->lpcSize;i++)
502       {
503          st->pi_gain[sub] += tmp*st->interp_qlpc[i];
504          tmp = -tmp;
505       }
506      
507
508       /* Compute bandwidth-expanded (unquantized) LPCs for perceptual weighting */
509       bw_lpc(st->gamma1, st->interp_lpc, st->bw_lpc1, st->lpcSize);
510       if (st->gamma2>=0)
511          bw_lpc(st->gamma2, st->interp_lpc, st->bw_lpc2, st->lpcSize);
512       else
513       {
514          st->bw_lpc2[0]=1;
515          st->bw_lpc2[1]=-st->preemph;
516          for (i=2;i<=st->lpcSize;i++)
517             st->bw_lpc2[i]=0;
518       }
519
520       for (i=0;i<st->subframeSize;i++)
521          exc[i]=0;
522       exc[0]=1;
523       syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, syn_resp, st->subframeSize, st->lpcSize, stack);
524
525       /* Reset excitation */
526       for (i=0;i<st->subframeSize;i++)
527          exc[i]=0;
528       for (i=0;i<st->subframeSize;i++)
529          exc2[i]=0;
530
531       /* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */
532       for (i=0;i<st->lpcSize;i++)
533          mem[i]=st->mem_sp[i];
534       iir_mem2(exc, st->interp_qlpc, exc, st->subframeSize, st->lpcSize, mem);
535       
536       for (i=0;i<st->lpcSize;i++)
537          mem[i]=st->mem_sw[i];
538       filter_mem2(exc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, mem);
539       
540       /* Compute weighted signal */
541       for (i=0;i<st->lpcSize;i++)
542          mem[i]=st->mem_sw[i];
543       filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, mem);
544       
545       /* Compute target signal */
546       for (i=0;i<st->subframeSize;i++)
547          target[i]=sw[i]-res[i];
548
549       for (i=0;i<st->subframeSize;i++)
550          exc[i]=exc2[i]=0;
551
552       /* If we have a long-term predictor (not all sub-modes have one) */
553       if (SUBMODE(ltp_quant))
554       {
555          int pit_min, pit_max;
556          /* Long-term prediction */
557          if (SUBMODE(lbr_pitch) != -1)
558          {
559             /* Low bit-rate pitch handling */
560             int margin;
561             margin = SUBMODE(lbr_pitch);
562             if (margin)
563             {
564                if (ol_pitch < st->min_pitch+margin-1)
565                   ol_pitch=st->min_pitch+margin-1;
566                if (ol_pitch > st->max_pitch-margin)
567                   ol_pitch=st->max_pitch-margin;
568                pit_min = ol_pitch-margin+1;
569                pit_max = ol_pitch+margin;
570             } else {
571                pit_min=pit_max=ol_pitch;
572             }
573          } else {
574             pit_min = st->min_pitch;
575             pit_max = st->max_pitch;
576          }
577          
578          if (st->bounded_pitch && pit_max>offset)
579             pit_max=offset;
580          pitch = SUBMODE(ltp_quant)(target, sw, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
581                                     exc, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef,
582                                     st->lpcSize, st->subframeSize, bits, stack, 
583                                     exc2, syn_resp, st->complexity);
584
585          /*printf ("cl_pitch: %d\n", pitch);*/
586          st->pitch[sub]=pitch;
587       } else {
588          fprintf (stderr, "No pitch prediction, what's wrong\n");
589       }
590
591       /* Update target for adaptive codebook contribution */
592       syn_percep_zero(exc, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, res, st->subframeSize, st->lpcSize, stack);
593       for (i=0;i<st->subframeSize;i++)
594         target[i]-=res[i];
595
596
597       /* Quantization of innovation */
598       {
599          float *innov;
600          float ener=0, ener_1;
601
602          innov = st->innov+sub*st->subframeSize;
603          for (i=0;i<st->subframeSize;i++)
604             innov[i]=0;
605          
606          residue_percep_zero(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, st->buf2, st->subframeSize, st->lpcSize, stack);
607          for (i=0;i<st->subframeSize;i++)
608             ener+=st->buf2[i]*st->buf2[i];
609          ener=sqrt(.1+ener/st->subframeSize);
610
611          
612          ener /= ol_gain;
613
614          if (0)
615             printf ("ener: %f %f %f\n", ener, ol_gain, ol_pitch_coef);
616
617          if (SUBMODE(have_subframe_gain)) 
618          {
619             int qe;
620             ener=log(ener);
621             if (SUBMODE(have_subframe_gain)==3)
622             {
623                qe = vq_index(&ener, exc_gain_quant_scal3, 1, 8);
624                speex_bits_pack(bits, qe, 3);
625                ener=exc_gain_quant_scal3[qe];
626             } else {
627                qe = vq_index(&ener, exc_gain_quant_scal1, 1, 2);
628                speex_bits_pack(bits, qe, 1);
629                ener=exc_gain_quant_scal1[qe];               
630             }
631             ener=exp(ener);
632             /*printf ("encode gain: %d %f\n", qe, ener);*/
633          } else {
634             ener=1;
635          }
636
637          ener*=ol_gain;
638          /*printf ("transmit gain: %f\n", ener);*/
639          ener_1 = 1/ener;
640
641          if (0) {
642             int start=rand()%35;
643             printf ("norm_exc: ");
644             for (i=start;i<start+5;i++)
645                printf ("%f ", ener_1*st->buf2[i]);
646             printf ("\n");
647          }
648          
649          for (i=0;i<st->subframeSize;i++)
650             target[i]*=ener_1;
651          
652          if (SUBMODE(innovation_quant))
653          {
654             /* Normal quantization */
655             SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, 
656                                       SUBMODE(innovation_params), st->lpcSize, st->subframeSize, 
657                                       innov, syn_resp, bits, stack, st->complexity);
658             for (i=0;i<st->subframeSize;i++)
659                innov[i]*=ener;
660             for (i=0;i<st->subframeSize;i++)
661                exc[i] += innov[i];
662          } else {
663             fprintf(stderr, "No fixed codebook\n");
664          }
665
666          if (SUBMODE(double_codebook)) {
667             float *tmp_stack=stack;
668             float *innov2 = PUSH(tmp_stack, st->subframeSize);
669             for (i=0;i<st->subframeSize;i++)
670                innov2[i]=0;
671             for (i=0;i<st->subframeSize;i++)
672                target[i]*=2.2;
673             SUBMODE(innovation_quant)(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2, 
674                                       SUBMODE(innovation_params), st->lpcSize, st->subframeSize, 
675                                       innov2, syn_resp, bits, tmp_stack, st->complexity);
676             for (i=0;i<st->subframeSize;i++)
677                innov2[i]*=ener*(1/2.2);
678             for (i=0;i<st->subframeSize;i++)
679                exc[i] += innov2[i];
680          }
681
682          for (i=0;i<st->subframeSize;i++)
683             target[i]*=ener;
684
685       }
686
687       /*Keep the previous memory*/
688       for (i=0;i<st->lpcSize;i++)
689          mem[i]=st->mem_sp[i];
690       /* Final signal synthesis from excitation */
691       iir_mem2(exc, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, st->mem_sp);
692
693       /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */
694       filter_mem2(sp, st->bw_lpc1, st->bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw);
695       for (i=0;i<st->subframeSize;i++)
696          exc2[i]=exc[i];
697    }
698
699    /* Store the LSPs for interpolation in the next frame */
700    for (i=0;i<st->lpcSize;i++)
701       st->old_lsp[i] = st->lsp[i];
702    for (i=0;i<st->lpcSize;i++)
703       st->old_qlsp[i] = st->qlsp[i];
704
705    /* The next frame will not be the first (Duh!) */
706    st->first = 0;
707
708    /* Replace input by synthesized speech */
709    in[0] = st->frame[0] + st->preemph*st->pre_mem2;
710    for (i=1;i<st->frameSize;i++)
711      in[i]=st->frame[i] + st->preemph*in[i-1];
712    st->pre_mem2=in[st->frameSize-1];
713
714    if (SUBMODE(innovation_quant) == noise_codebook_quant)
715       st->bounded_pitch = 1;
716    else
717       st->bounded_pitch = 0;
718 }
719
720
721 void *nb_decoder_init(SpeexMode *m)
722 {
723    DecState *st;
724    SpeexNBMode *mode;
725    int i;
726
727    mode=m->mode;
728    st = speex_alloc(sizeof(DecState));
729    st->mode=m;
730
731    st->first=1;
732    /* Codec parameters, should eventually have several "modes"*/
733    st->frameSize = mode->frameSize;
734    st->windowSize = st->frameSize*3/2;
735    st->nbSubframes=mode->frameSize/mode->subframeSize;
736    st->subframeSize=mode->subframeSize;
737    st->lpcSize = mode->lpcSize;
738    st->bufSize = mode->bufSize;
739    st->gamma1=mode->gamma1;
740    st->gamma2=mode->gamma2;
741    st->min_pitch=mode->pitchStart;
742    st->max_pitch=mode->pitchEnd;
743    st->preemph = mode->preemph;
744
745    st->submodes=mode->submodes;
746    st->submodeID=mode->defaultSubmode;
747
748    st->pre_mem=0;
749    st->lpc_enh_enabled=0;
750
751    st->stack = speex_alloc(20000*sizeof(float));
752
753    st->inBuf = speex_alloc(st->bufSize*sizeof(float));
754    st->frame = st->inBuf + st->bufSize - st->windowSize;
755    st->excBuf = speex_alloc(st->bufSize*sizeof(float));
756    st->exc = st->excBuf + st->bufSize - st->windowSize;
757    for (i=0;i<st->bufSize;i++)
758       st->inBuf[i]=0;
759    for (i=0;i<st->bufSize;i++)
760       st->excBuf[i]=0;
761    st->innov = speex_alloc(st->frameSize*sizeof(float));
762
763    st->interp_qlpc = speex_alloc((st->lpcSize+1)*sizeof(float));
764    st->qlsp = speex_alloc(st->lpcSize*sizeof(float));
765    st->old_qlsp = speex_alloc(st->lpcSize*sizeof(float));
766    st->interp_qlsp = speex_alloc(st->lpcSize*sizeof(float));
767    st->mem_sp = speex_alloc(5*st->lpcSize*sizeof(float));
768
769    st->pi_gain = speex_alloc(st->nbSubframes*sizeof(float));
770    st->last_pitch = 40;
771    st->count_lost=0;
772
773
774    st->user_callback.func = &speex_default_user_handler;
775    st->user_callback.data = NULL;
776    for (i=0;i<16;i++)
777       st->speex_callbacks[i].func = NULL;
778
779    return st;
780 }
781
782 void nb_decoder_destroy(void *state)
783 {
784    DecState *st;
785    st=state;
786    speex_free(st->inBuf);
787    speex_free(st->excBuf);
788    speex_free(st->innov);
789    speex_free(st->interp_qlpc);
790    speex_free(st->qlsp);
791    speex_free(st->old_qlsp);
792    speex_free(st->interp_qlsp);
793    speex_free(st->stack);
794    speex_free(st->mem_sp);
795    speex_free(st->pi_gain);
796    
797    speex_free(state);
798 }
799
800 static void nb_decode_lost(DecState *st, float *out, float *stack)
801 {
802    int i, sub;
803    float *awk1, *awk2, *awk3;
804    /*float exc_ener=0,g;*/
805    /* Shift all buffers by one frame */
806    speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
807    speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
808
809    awk1=PUSH(stack, (st->lpcSize+1));
810    awk2=PUSH(stack, (st->lpcSize+1));
811    awk3=PUSH(stack, (st->lpcSize+1));
812
813    for (sub=0;sub<st->nbSubframes;sub++)
814    {
815       int offset;
816       float *sp, *exc;
817       /* Offset relative to start of frame */
818       offset = st->subframeSize*sub;
819       /* Original signal */
820       sp=st->frame+offset;
821       /* Excitation */
822       exc=st->exc+offset;
823       /* Excitation after post-filter*/
824
825       {
826          float r=.9;
827          
828          float k1,k2,k3;
829          k1=SUBMODE(lpc_enh_k1);
830          k2=SUBMODE(lpc_enh_k2);
831          k3=(1-(1-r*k1)/(1-r*k2))/r;
832          if (!st->lpc_enh_enabled)
833          {
834             k1=k2;
835             k3=0;
836          }
837          bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize);
838          bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize);
839          bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize);
840          
841       }
842         
843       for (i=0;i<st->subframeSize;i++)
844       {
845          exc[i]=st->last_pitch_gain*exc[i-st->last_pitch] + 
846          .8*st->innov[i+offset];
847       }
848
849       for (i=0;i<st->subframeSize;i++)
850          sp[i]=exc[i];
851       
852       filter_mem2(sp, awk3, awk1, sp, st->subframeSize, st->lpcSize, 
853         st->mem_sp+st->lpcSize);
854       filter_mem2(sp, awk2, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, 
855         st->mem_sp);
856   
857    }
858
859    out[0] = st->frame[0] + st->preemph*st->pre_mem;
860    for (i=1;i<st->frameSize;i++)
861       out[i]=st->frame[i] + st->preemph*out[i-1];
862    st->pre_mem=out[st->frameSize-1];
863    
864    st->first = 0;
865    st->count_lost++;
866 }
867
868
869 int nb_decode(void *state, SpeexBits *bits, float *out)
870 {
871    DecState *st;
872    int i, sub;
873    int pitch;
874    float pitch_gain[3];
875    float ol_gain;
876    int ol_pitch=0;
877    float ol_pitch_coef=0;
878    int best_pitch=40;
879    float best_pitch_gain=-1;
880    int wideband;
881    int m;
882    float *stack;
883    float *awk1, *awk2, *awk3;
884    st=state;
885    stack=st->stack;
886
887    if (!bits)
888    {
889       nb_decode_lost(st, out, stack);
890       return 0;
891    }
892
893    do {
894       wideband = speex_bits_unpack_unsigned(bits, 1);
895       if (wideband)
896       {
897          int submode;
898          int advance;
899          submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS);
900          advance = submode;
901          speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
902          advance -= (SB_SUBMODE_BITS+1);
903          speex_bits_advance(bits, advance);
904          wideband = speex_bits_unpack_unsigned(bits, 1);
905          if (wideband)
906          {
907             fprintf (stderr, "Corrupted stream?\n");
908          }
909       }
910
911       m = speex_bits_unpack_unsigned(bits, 4);
912       if (m==15)
913       {
914          return -1;
915       } else if (m==14)
916       {
917          int ret = speex_inband_handler(bits, st->speex_callbacks, state);
918          if (ret)
919             return ret;
920       } else if (m==13)
921       {
922          int ret = st->user_callback.func(bits, state, st->user_callback.data);
923          if (ret)
924             return ret;
925       } else if (m>7)
926       {
927          return -2;
928       }
929       
930    } while (m>7);
931
932    /* Get the sub-mode that was used */
933    st->submodeID = m;
934
935    /* Shift all buffers by one frame */
936    speex_move(st->inBuf, st->inBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
937    speex_move(st->excBuf, st->excBuf+st->frameSize, (st->bufSize-st->frameSize)*sizeof(float));
938
939    /* If null mode (no transmission), just set a couple things to zero*/
940    if (st->submodes[st->submodeID] == NULL)
941    {
942       for (i=0;i<st->frameSize;i++)
943          st->exc[i]=0;
944       st->first=1;
945       
946       /* Final signal synthesis from excitation */
947       iir_mem2(st->exc, st->interp_qlpc, st->frame, st->subframeSize, st->lpcSize, st->mem_sp);
948
949       out[0] = st->frame[0] + st->preemph*st->pre_mem;
950       for (i=1;i<st->frameSize;i++)
951          out[i]=st->frame[i] + st->preemph*out[i-1];
952       st->pre_mem=out[st->frameSize-1];
953       st->count_lost=0;
954       return 0;
955    }
956
957    /* Unquantize LSPs */
958    SUBMODE(lsp_unquant)(st->qlsp, st->lpcSize, bits);
959
960    /* Handle first frame and lost-packet case */
961    if (st->first || st->count_lost)
962    {
963       for (i=0;i<st->lpcSize;i++)
964          st->old_qlsp[i] = st->qlsp[i];
965    }
966
967    /* Get open-loop pitch estimation for low bit-rate pitch coding */
968    if (SUBMODE(lbr_pitch)!=-1)
969    {
970       ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
971    } 
972    
973    if (SUBMODE(forced_pitch_gain))
974    {
975       int quant;
976       quant = speex_bits_unpack_unsigned(bits, 4);
977       ol_pitch_coef=0.066667*quant;
978       /*fprintf (stderr, "unquant pitch coef: %f\n", ol_pitch_coef);*/
979    }
980    
981    /* Get global excitation gain */
982    {
983       int qe;
984       qe = speex_bits_unpack_unsigned(bits, 5);
985       ol_gain = exp(qe/3.5);
986       /*printf ("decode_ol_gain: %f\n", ol_gain);*/
987    }
988
989    awk1=PUSH(stack, st->lpcSize+1);
990    awk2=PUSH(stack, st->lpcSize+1);
991    awk3=PUSH(stack, st->lpcSize+1);
992
993    /*Loop on subframes */
994    for (sub=0;sub<st->nbSubframes;sub++)
995    {
996       int offset;
997       float *sp, *exc, tmp;
998
999       /* Offset relative to start of frame */
1000       offset = st->subframeSize*sub;
1001       /* Original signal */
1002       sp=st->frame+offset;
1003       /* Excitation */
1004       exc=st->exc+offset;
1005       /* Excitation after post-filter*/
1006
1007       /* LSP interpolation (quantized and unquantized) */
1008       tmp = (1.0 + sub)/st->nbSubframes;
1009       for (i=0;i<st->lpcSize;i++)
1010          st->interp_qlsp[i] = (1-tmp)*st->old_qlsp[i] + tmp*st->qlsp[i];
1011
1012       lsp_enforce_margin(st->interp_qlsp, st->lpcSize, .002);
1013
1014
1015       /* Compute interpolated LPCs (unquantized) */
1016       for (i=0;i<st->lpcSize;i++)
1017          st->interp_qlsp[i] = cos(st->interp_qlsp[i]);
1018       lsp_to_lpc(st->interp_qlsp, st->interp_qlpc, st->lpcSize, stack);
1019
1020       /* Compute enhanced synthesis filter */
1021       {
1022          float r=.9;
1023          
1024          float k1,k2,k3;
1025          k1=SUBMODE(lpc_enh_k1);
1026          k2=SUBMODE(lpc_enh_k2);
1027          k3=(1-(1-r*k1)/(1-r*k2))/r;
1028          if (!st->lpc_enh_enabled)
1029          {
1030             k1=k2;
1031             k3=0;
1032          }
1033          bw_lpc(k1, st->interp_qlpc, awk1, st->lpcSize);
1034          bw_lpc(k2, st->interp_qlpc, awk2, st->lpcSize);
1035          bw_lpc(k3, st->interp_qlpc, awk3, st->lpcSize);
1036          
1037       }
1038
1039       /* Compute analysis filter at w=pi */
1040       tmp=1;
1041       st->pi_gain[sub]=0;
1042       for (i=0;i<=st->lpcSize;i++)
1043       {
1044          st->pi_gain[sub] += tmp*st->interp_qlpc[i];
1045          tmp = -tmp;
1046       }
1047
1048       /* Reset excitation */
1049       for (i=0;i<st->subframeSize;i++)
1050          exc[i]=0;
1051
1052       /*Adaptive codebook contribution*/
1053       if (SUBMODE(ltp_unquant))
1054       {
1055          int pit_min, pit_max;
1056          /* Handle pitch constraints if any */
1057          if (SUBMODE(lbr_pitch) != -1)
1058          {
1059             int margin;
1060             margin = SUBMODE(lbr_pitch);
1061             if (margin)
1062             {
1063                if (ol_pitch < st->min_pitch+margin-1)
1064                   ol_pitch=st->min_pitch+margin-1;
1065                if (ol_pitch > st->max_pitch-margin)
1066                   ol_pitch=st->max_pitch-margin;
1067                pit_min = ol_pitch-margin+1;
1068                pit_max = ol_pitch+margin;
1069             } else {
1070                pit_min=pit_max=ol_pitch;
1071             }
1072          } else {
1073             pit_min = st->min_pitch;
1074             pit_max = st->max_pitch;
1075          }
1076
1077          /* Pitch synthesis */
1078          SUBMODE(ltp_unquant)(exc, pit_min, pit_max, ol_pitch_coef, SUBMODE(ltp_params), 
1079                               st->subframeSize, &pitch, &pitch_gain[0], bits, stack, st->count_lost);
1080          
1081          tmp = (pitch_gain[0]+pitch_gain[1]+pitch_gain[2]);
1082          if (tmp>best_pitch_gain)
1083          {
1084             best_pitch = pitch;
1085             best_pitch_gain = tmp*.9;
1086             if (best_pitch_gain>.85)
1087                best_pitch_gain=.85;
1088          }
1089       } else {
1090          fprintf (stderr, "No pitch prediction, what's wrong\n");
1091       }
1092       
1093       /* Unquantize the innovation */
1094       {
1095          int q_energy;
1096          float ener;
1097          float *innov;
1098          
1099          innov = st->innov+sub*st->subframeSize;
1100          for (i=0;i<st->subframeSize;i++)
1101             innov[i]=0;
1102
1103          if (SUBMODE(have_subframe_gain)==3)
1104          {
1105             q_energy = speex_bits_unpack_unsigned(bits, 3);
1106             ener = ol_gain*exp(exc_gain_quant_scal3[q_energy]);
1107          } else if (SUBMODE(have_subframe_gain)==1)
1108          {
1109             q_energy = speex_bits_unpack_unsigned(bits, 1);
1110             ener = ol_gain*exp(exc_gain_quant_scal1[q_energy]);
1111          } else {
1112             ener = ol_gain;
1113          }
1114          
1115          /*printf ("unquant_energy: %d %f\n", q_energy, ener);*/
1116          
1117          if (SUBMODE(innovation_unquant))
1118          {
1119             /*Fixed codebook contribution*/
1120             SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), st->subframeSize, bits, stack);
1121          } else {
1122             fprintf(stderr, "No fixed codebook\n");
1123          }
1124
1125          for (i=0;i<st->subframeSize;i++)
1126             innov[i]*=ener;
1127          for (i=0;i<st->subframeSize;i++)
1128             exc[i]+=innov[i];
1129
1130          if (SUBMODE(double_codebook))
1131          {
1132             float *tmp_stack=stack;
1133             float *innov2 = PUSH(tmp_stack, st->subframeSize);
1134             for (i=0;i<st->subframeSize;i++)
1135                innov2[i]=0;
1136             SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, bits, tmp_stack);
1137             for (i=0;i<st->subframeSize;i++)
1138                innov2[i]*=ener*(1/2.2);
1139             for (i=0;i<st->subframeSize;i++)
1140                exc[i] += innov2[i];
1141          }
1142
1143       }
1144
1145       for (i=0;i<st->subframeSize;i++)
1146          sp[i]=exc[i];
1147
1148       if (st->lpc_enh_enabled && SUBMODE(comb_gain>0))
1149          comb_filter(exc, sp, st->interp_qlpc, st->lpcSize, st->subframeSize,
1150                               pitch, pitch_gain, .5);
1151       filter_mem2(sp, awk3, awk1, sp, st->subframeSize, st->lpcSize, 
1152         st->mem_sp+st->lpcSize);
1153       filter_mem2(sp, awk2, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, 
1154         st->mem_sp);
1155    }
1156    
1157    /*Copy output signal*/
1158    out[0] = st->frame[0] + st->preemph*st->pre_mem;
1159    for (i=1;i<st->frameSize;i++)
1160      out[i]=st->frame[i] + st->preemph*out[i-1];
1161    st->pre_mem=out[st->frameSize-1];
1162
1163
1164    /* Store the LSPs for interpolation in the next frame */
1165    for (i=0;i<st->lpcSize;i++)
1166       st->old_qlsp[i] = st->qlsp[i];
1167
1168    /* The next frame will not be the first (Duh!) */
1169    st->first = 0;
1170    st->count_lost=0;
1171    st->last_pitch = best_pitch;
1172    st->last_pitch_gain = best_pitch_gain;
1173
1174    return 0;
1175 }
1176
1177 void nb_encoder_ctl(void *state, int request, void *ptr)
1178 {
1179    EncState *st;
1180    st=state;     
1181    switch(request)
1182    {
1183    case SPEEX_GET_FRAME_SIZE:
1184       (*(int*)ptr) = st->frameSize;
1185       break;
1186    case SPEEX_SET_LOW_MODE:
1187    case SPEEX_SET_MODE:
1188       st->submodeID = (*(int*)ptr);
1189       break;
1190    case SPEEX_GET_LOW_MODE:
1191    case SPEEX_GET_MODE:
1192       (*(int*)ptr) = st->submodeID;
1193       break;
1194    case SPEEX_SET_VBR:
1195       st->vbr_enabled = (*(int*)ptr);
1196       break;
1197    case SPEEX_GET_VBR:
1198       (*(int*)ptr) = st->vbr_enabled;
1199       break;
1200    case SPEEX_SET_VBR_QUALITY:
1201       st->vbr_quality = (*(int*)ptr);
1202       break;
1203    case SPEEX_GET_VBR_QUALITY:
1204       (*(int*)ptr) = st->vbr_quality;
1205       break;
1206    case SPEEX_SET_QUALITY:
1207       {
1208          int quality = (*(int*)ptr);
1209          if (quality<=0)
1210             st->submodeID = 0;
1211          else if (quality<=1)
1212             st->submodeID = 1;
1213          else if (quality<=2)
1214             st->submodeID = 2;
1215          else if (quality<=4)
1216             st->submodeID = 3;
1217          else if (quality<=6)
1218             st->submodeID = 4;
1219          else if (quality<=8)
1220             st->submodeID = 5;
1221          else if (quality<=9)
1222             st->submodeID = 6;
1223          else if (quality<=10)
1224             st->submodeID = 7;
1225          else
1226             fprintf(stderr, "Unknown nb_ctl quality: %d\n", quality);
1227       }
1228       break;
1229    case SPEEX_SET_COMPLEXITY:
1230       st->complexity = (*(int*)ptr);
1231       if (st->complexity<1)
1232          st->complexity=1;
1233       break;
1234    case SPEEX_GET_COMPLEXITY:
1235       (*(int*)ptr) = st->complexity;
1236       break;
1237    case SPEEX_GET_BITRATE:
1238       if (st->submodes[st->submodeID])
1239          (*(int*)ptr) = 50*SUBMODE(bits_per_frame);
1240       else
1241          (*(int*)ptr) = 50*(NB_SUBMODE_BITS+1);
1242       break;
1243    default:
1244       fprintf(stderr, "Unknown nb_ctl request: %d\n", request);
1245    }
1246 }
1247
1248 void nb_decoder_ctl(void *state, int request, void *ptr)
1249 {
1250    DecState *st;
1251    st=state;
1252    switch(request)
1253    {
1254    case SPEEX_SET_ENH:
1255       st->lpc_enh_enabled = *((int*)ptr);
1256       break;
1257    case SPEEX_GET_ENH:
1258       *((int*)ptr) = st->lpc_enh_enabled;
1259       break;
1260    case SPEEX_GET_FRAME_SIZE:
1261       (*(int*)ptr) = st->frameSize;
1262       break;
1263    case SPEEX_GET_BITRATE:
1264       if (st->submodes[st->submodeID])
1265          (*(int*)ptr) = 50*SUBMODE(bits_per_frame);
1266       else
1267          (*(int*)ptr) = 50*(NB_SUBMODE_BITS+1);
1268       break;
1269    case SPEEX_SET_HANDLER:
1270       {
1271          SpeexCallback *c = ptr;
1272          st->speex_callbacks[c->callback_id].func=c->func;
1273          st->speex_callbacks[c->callback_id].data=c->data;
1274          st->speex_callbacks[c->callback_id].callback_id=c->callback_id;
1275       }
1276       break;
1277    case SPEEX_SET_USER_HANDLER:
1278       {
1279          SpeexCallback *c = ptr;
1280          st->user_callback.func=c->func;
1281          st->user_callback.data=c->data;
1282          st->user_callback.callback_id=c->callback_id;
1283       }
1284       break;
1285    default:
1286       fprintf(stderr, "Unknown nb_ctl request: %d\n", request);
1287    }
1288 }