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