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