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