Add per-user preferences support.
[chromium-blink-merge.git] / third_party / speex / libspeex / nb_celp.c
blob9dd726a0cf3912b64fbb44a069e3fceadfb3e057
1 /* Copyright (C) 2002-2006 Jean-Marc Valin
2 File: nb_celp.c
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
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.
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.
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.
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <math.h>
37 #include "nb_celp.h"
38 #include "lpc.h"
39 #include "lsp.h"
40 #include "ltp.h"
41 #include "quant_lsp.h"
42 #include "cb_search.h"
43 #include "filters.h"
44 #include "stack_alloc.h"
45 #include "vq.h"
46 #include <speex/speex_bits.h>
47 #include "vbr.h"
48 #include "arch.h"
49 #include "math_approx.h"
50 #include "os_support.h"
51 #include <speex/speex_callbacks.h>
53 #ifdef VORBIS_PSYCHO
54 #include "vorbis_psy.h"
55 #endif
57 #ifndef M_PI
58 #define M_PI 3.14159265358979323846 /* pi */
59 #endif
61 #ifndef NULL
62 #define NULL 0
63 #endif
65 #define SUBMODE(x) st->submodes[st->submodeID]->x
67 /* Default size for the encoder and decoder stack (can be changed at compile time).
68 This does not apply when using variable-size arrays or alloca. */
69 #ifndef NB_ENC_STACK
70 #define NB_ENC_STACK (8000*sizeof(spx_sig_t))
71 #endif
73 #ifndef NB_DEC_STACK
74 #define NB_DEC_STACK (4000*sizeof(spx_sig_t))
75 #endif
78 #ifdef FIXED_POINT
79 const spx_word32_t ol_gain_table[32]={18900, 25150, 33468, 44536, 59265, 78865, 104946, 139653, 185838, 247297, 329081, 437913, 582736, 775454, 1031906, 1373169, 1827293, 2431601, 3235761, 4305867, 5729870, 7624808, 10146425, 13501971, 17967238, 23909222, 31816294, 42338330, 56340132, 74972501, 99766822, 132760927};
80 const spx_word16_t exc_gain_quant_scal3_bound[7]={1841, 3883, 6051, 8062, 10444, 13580, 18560};
81 const spx_word16_t exc_gain_quant_scal3[8]={1002, 2680, 5086, 7016, 9108, 11781, 15380, 21740};
82 const spx_word16_t exc_gain_quant_scal1_bound[1]={14385};
83 const spx_word16_t exc_gain_quant_scal1[2]={11546, 17224};
85 #define LSP_MARGIN 16
86 #define LSP_DELTA1 6553
87 #define LSP_DELTA2 1638
89 #else
91 const float exc_gain_quant_scal3_bound[7]={0.112338f, 0.236980f, 0.369316f, 0.492054f, 0.637471f, 0.828874f, 1.132784f};
92 const float exc_gain_quant_scal3[8]={0.061130f, 0.163546f, 0.310413f, 0.428220f, 0.555887f, 0.719055f, 0.938694f, 1.326874f};
93 const float exc_gain_quant_scal1_bound[1]={0.87798f};
94 const float exc_gain_quant_scal1[2]={0.70469f, 1.05127f};
96 #define LSP_MARGIN .002f
97 #define LSP_DELTA1 .2f
98 #define LSP_DELTA2 .05f
100 #endif
102 #ifdef VORBIS_PSYCHO
103 #define EXTRA_BUFFER 100
104 #else
105 #define EXTRA_BUFFER 0
106 #endif
109 #define sqr(x) ((x)*(x))
111 extern const spx_word16_t lag_window[];
112 extern const spx_word16_t lpc_window[];
114 void *nb_encoder_init(const SpeexMode *m)
116 EncState *st;
117 const SpeexNBMode *mode;
118 int i;
120 mode=(const SpeexNBMode *)m->mode;
121 st = (EncState*)speex_alloc(sizeof(EncState));
122 if (!st)
123 return NULL;
124 #if defined(VAR_ARRAYS) || defined (USE_ALLOCA)
125 st->stack = NULL;
126 #else
127 st->stack = (char*)speex_alloc_scratch(NB_ENC_STACK);
128 #endif
130 st->mode=m;
132 st->frameSize = mode->frameSize;
133 st->nbSubframes=mode->frameSize/mode->subframeSize;
134 st->subframeSize=mode->subframeSize;
135 st->windowSize = st->frameSize+st->subframeSize;
136 st->lpcSize = mode->lpcSize;
137 st->gamma1=mode->gamma1;
138 st->gamma2=mode->gamma2;
139 st->min_pitch=mode->pitchStart;
140 st->max_pitch=mode->pitchEnd;
141 st->lpc_floor = mode->lpc_floor;
143 st->submodes=mode->submodes;
144 st->submodeID=st->submodeSelect=mode->defaultSubmode;
145 st->bounded_pitch = 1;
147 st->encode_submode = 1;
149 #ifdef VORBIS_PSYCHO
150 st->psy = vorbis_psy_init(8000, 256);
151 st->curve = (float*)speex_alloc(128*sizeof(float));
152 st->old_curve = (float*)speex_alloc(128*sizeof(float));
153 st->psy_window = (float*)speex_alloc(256*sizeof(float));
154 #endif
156 st->cumul_gain = 1024;
158 /* Allocating input buffer */
159 st->winBuf = (spx_word16_t*)speex_alloc((st->windowSize-st->frameSize)*sizeof(spx_word16_t));
160 /* Allocating excitation buffer */
161 st->excBuf = (spx_word16_t*)speex_alloc((mode->frameSize+mode->pitchEnd+2)*sizeof(spx_word16_t));
162 st->exc = st->excBuf + mode->pitchEnd + 2;
163 st->swBuf = (spx_word16_t*)speex_alloc((mode->frameSize+mode->pitchEnd+2)*sizeof(spx_word16_t));
164 st->sw = st->swBuf + mode->pitchEnd + 2;
166 st->window= lpc_window;
168 /* Create the window for autocorrelation (lag-windowing) */
169 st->lagWindow = lag_window;
171 st->old_lsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
172 st->old_qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t));
173 st->first = 1;
174 for (i=0;i<st->lpcSize;i++)
175 st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1);
177 st->mem_sp = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
178 st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
179 st->mem_sw_whole = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
180 st->mem_exc = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
181 st->mem_exc2 = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t));
183 st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t));
184 st->innov_rms_save = NULL;
186 st->pitch = (int*)speex_alloc((st->nbSubframes)*sizeof(int));
188 #ifndef DISABLE_VBR
189 st->vbr = (VBRState*)speex_alloc(sizeof(VBRState));
190 vbr_init(st->vbr);
191 st->vbr_quality = 8;
192 st->vbr_enabled = 0;
193 st->vbr_max = 0;
194 st->vad_enabled = 0;
195 st->dtx_enabled = 0;
196 st->dtx_count=0;
197 st->abr_enabled = 0;
198 st->abr_drift = 0;
199 st->abr_drift2 = 0;
200 #endif /* #ifndef DISABLE_VBR */
202 st->plc_tuning = 2;
203 st->complexity=2;
204 st->sampling_rate=8000;
205 st->isWideband = 0;
206 st->highpass_enabled = 1;
208 #ifdef ENABLE_VALGRIND
209 VALGRIND_MAKE_READABLE(st, NB_ENC_STACK);
210 #endif
211 return st;
214 void nb_encoder_destroy(void *state)
216 EncState *st=(EncState *)state;
217 /* Free all allocated memory */
218 #if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA))
219 speex_free_scratch(st->stack);
220 #endif
222 speex_free (st->winBuf);
223 speex_free (st->excBuf);
224 speex_free (st->old_qlsp);
225 speex_free (st->swBuf);
227 speex_free (st->old_lsp);
228 speex_free (st->mem_sp);
229 speex_free (st->mem_sw);
230 speex_free (st->mem_sw_whole);
231 speex_free (st->mem_exc);
232 speex_free (st->mem_exc2);
233 speex_free (st->pi_gain);
234 speex_free (st->pitch);
236 #ifndef DISABLE_VBR
237 vbr_destroy(st->vbr);
238 speex_free (st->vbr);
239 #endif /* #ifndef DISABLE_VBR */
241 #ifdef VORBIS_PSYCHO
242 vorbis_psy_destroy(st->psy);
243 speex_free (st->curve);
244 speex_free (st->old_curve);
245 speex_free (st->psy_window);
246 #endif
248 /*Free state memory... should be last*/
249 speex_free(st);
252 int nb_encode(void *state, void *vin, SpeexBits *bits)
254 EncState *st;
255 int i, sub, roots;
256 int ol_pitch;
257 spx_word16_t ol_pitch_coef;
258 spx_word32_t ol_gain;
259 VARDECL(spx_word16_t *ringing);
260 VARDECL(spx_word16_t *target);
261 VARDECL(spx_sig_t *innov);
262 VARDECL(spx_word32_t *exc32);
263 VARDECL(spx_mem_t *mem);
264 VARDECL(spx_coef_t *bw_lpc1);
265 VARDECL(spx_coef_t *bw_lpc2);
266 VARDECL(spx_coef_t *lpc);
267 VARDECL(spx_lsp_t *lsp);
268 VARDECL(spx_lsp_t *qlsp);
269 VARDECL(spx_lsp_t *interp_lsp);
270 VARDECL(spx_lsp_t *interp_qlsp);
271 VARDECL(spx_coef_t *interp_lpc);
272 VARDECL(spx_coef_t *interp_qlpc);
273 char *stack;
274 VARDECL(spx_word16_t *syn_resp);
275 VARDECL(spx_word16_t *real_exc);
277 spx_word32_t ener=0;
278 spx_word16_t fine_gain;
279 spx_word16_t *in = (spx_word16_t*)vin;
281 st=(EncState *)state;
282 stack=st->stack;
284 ALLOC(lpc, st->lpcSize, spx_coef_t);
285 ALLOC(bw_lpc1, st->lpcSize, spx_coef_t);
286 ALLOC(bw_lpc2, st->lpcSize, spx_coef_t);
287 ALLOC(lsp, st->lpcSize, spx_lsp_t);
288 ALLOC(qlsp, st->lpcSize, spx_lsp_t);
289 ALLOC(interp_lsp, st->lpcSize, spx_lsp_t);
290 ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t);
291 ALLOC(interp_lpc, st->lpcSize, spx_coef_t);
292 ALLOC(interp_qlpc, st->lpcSize, spx_coef_t);
294 /* Move signals 1 frame towards the past */
295 SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, st->max_pitch+2);
296 SPEEX_MOVE(st->swBuf, st->swBuf+st->frameSize, st->max_pitch+2);
298 if (st->highpass_enabled)
299 highpass(in, in, st->frameSize, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPASS_NARROWBAND)|HIGHPASS_INPUT, st->mem_hp);
302 VARDECL(spx_word16_t *w_sig);
303 VARDECL(spx_word16_t *autocorr);
304 ALLOC(w_sig, st->windowSize, spx_word16_t);
305 ALLOC(autocorr, st->lpcSize+1, spx_word16_t);
306 /* Window for analysis */
307 for (i=0;i<st->windowSize-st->frameSize;i++)
308 w_sig[i] = EXTRACT16(SHR32(MULT16_16(st->winBuf[i],st->window[i]),SIG_SHIFT));
309 for (;i<st->windowSize;i++)
310 w_sig[i] = EXTRACT16(SHR32(MULT16_16(in[i-st->windowSize+st->frameSize],st->window[i]),SIG_SHIFT));
311 /* Compute auto-correlation */
312 _spx_autocorr(w_sig, autocorr, st->lpcSize+1, st->windowSize);
313 autocorr[0] = ADD16(autocorr[0],MULT16_16_Q15(autocorr[0],st->lpc_floor)); /* Noise floor in auto-correlation domain */
315 /* Lag windowing: equivalent to filtering in the power-spectrum domain */
316 for (i=0;i<st->lpcSize+1;i++)
317 autocorr[i] = MULT16_16_Q14(autocorr[i],st->lagWindow[i]);
319 /* Levinson-Durbin */
320 _spx_lpc(lpc, autocorr, st->lpcSize);
321 /* LPC to LSPs (x-domain) transform */
322 roots=lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA1, stack);
323 /* Check if we found all the roots */
324 if (roots!=st->lpcSize)
326 /*If we can't find all LSP's, do some damage control and use previous filter*/
327 for (i=0;i<st->lpcSize;i++)
329 lsp[i]=st->old_lsp[i];
337 /* Whole frame analysis (open-loop estimation of pitch and excitation gain) */
339 int diff = st->windowSize-st->frameSize;
340 if (st->first)
341 for (i=0;i<st->lpcSize;i++)
342 interp_lsp[i] = lsp[i];
343 else
344 lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, st->nbSubframes, st->nbSubframes<<1);
346 lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN);
348 /* Compute interpolated LPCs (unquantized) for whole frame*/
349 lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack);
352 /*Open-loop pitch*/
353 if (!st->submodes[st->submodeID] || (st->complexity>2 && SUBMODE(have_subframe_gain)<3) || SUBMODE(forced_pitch_gain) || SUBMODE(lbr_pitch) != -1
354 #ifndef DISABLE_VBR
355 || st->vbr_enabled || st->vad_enabled
356 #endif
359 int nol_pitch[6];
360 spx_word16_t nol_pitch_coef[6];
362 bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize);
363 bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize);
365 SPEEX_COPY(st->sw, st->winBuf, diff);
366 SPEEX_COPY(st->sw+diff, in, st->frameSize-diff);
367 filter_mem16(st->sw, bw_lpc1, bw_lpc2, st->sw, st->frameSize, st->lpcSize, st->mem_sw_whole, stack);
369 open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSize,
370 nol_pitch, nol_pitch_coef, 6, stack);
371 ol_pitch=nol_pitch[0];
372 ol_pitch_coef = nol_pitch_coef[0];
373 /*Try to remove pitch multiples*/
374 for (i=1;i<6;i++)
376 #ifdef FIXED_POINT
377 if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],27853)) &&
378 #else
379 if ((nol_pitch_coef[i]>.85*nol_pitch_coef[0]) &&
380 #endif
381 (ABS(2*nol_pitch[i]-ol_pitch)<=2 || ABS(3*nol_pitch[i]-ol_pitch)<=3 ||
382 ABS(4*nol_pitch[i]-ol_pitch)<=4 || ABS(5*nol_pitch[i]-ol_pitch)<=5))
384 /*ol_pitch_coef=nol_pitch_coef[i];*/
385 ol_pitch = nol_pitch[i];
388 /*if (ol_pitch>50)
389 ol_pitch/=2;*/
390 /*ol_pitch_coef = sqrt(ol_pitch_coef);*/
392 } else {
393 ol_pitch=0;
394 ol_pitch_coef=0;
397 /*Compute "real" excitation*/
398 SPEEX_COPY(st->exc, st->winBuf, diff);
399 SPEEX_COPY(st->exc+diff, in, st->frameSize-diff);
400 fir_mem16(st->exc, interp_lpc, st->exc, st->frameSize, st->lpcSize, st->mem_exc, stack);
402 /* Compute open-loop excitation gain */
404 spx_word16_t g = compute_rms16(st->exc, st->frameSize);
405 if (st->submodeID!=1 && ol_pitch>0)
406 ol_gain = MULT16_16(g, MULT16_16_Q14(QCONST16(1.1,14),
407 spx_sqrt(QCONST32(1.,28)-MULT16_32_Q15(QCONST16(.8,15),SHL32(MULT16_16(ol_pitch_coef,ol_pitch_coef),16)))));
408 else
409 ol_gain = SHL32(EXTEND32(g),SIG_SHIFT);
413 #ifdef VORBIS_PSYCHO
414 SPEEX_MOVE(st->psy_window, st->psy_window+st->frameSize, 256-st->frameSize);
415 SPEEX_COPY(&st->psy_window[256-st->frameSize], in, st->frameSize);
416 compute_curve(st->psy, st->psy_window, st->curve);
417 /*print_vec(st->curve, 128, "curve");*/
418 if (st->first)
419 SPEEX_COPY(st->old_curve, st->curve, 128);
420 #endif
422 /*VBR stuff*/
423 #ifndef DISABLE_VBR
424 if (st->vbr && (st->vbr_enabled||st->vad_enabled))
426 float lsp_dist=0;
427 for (i=0;i<st->lpcSize;i++)
428 lsp_dist += (st->old_lsp[i] - lsp[i])*(st->old_lsp[i] - lsp[i]);
429 lsp_dist /= LSP_SCALING*LSP_SCALING;
431 if (st->abr_enabled)
433 float qual_change=0;
434 if (st->abr_drift2 * st->abr_drift > 0)
436 /* Only adapt if long-term and short-term drift are the same sign */
437 qual_change = -.00001*st->abr_drift/(1+st->abr_count);
438 if (qual_change>.05)
439 qual_change=.05;
440 if (qual_change<-.05)
441 qual_change=-.05;
443 st->vbr_quality += qual_change;
444 if (st->vbr_quality>10)
445 st->vbr_quality=10;
446 if (st->vbr_quality<0)
447 st->vbr_quality=0;
450 st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch, GAIN_SCALING_1*ol_pitch_coef);
451 /*if (delta_qual<0)*/
452 /* delta_qual*=.1*(3+st->vbr_quality);*/
453 if (st->vbr_enabled)
455 spx_int32_t mode;
456 int choice=0;
457 float min_diff=100;
458 mode = 8;
459 while (mode)
461 int v1;
462 float thresh;
463 v1=(int)floor(st->vbr_quality);
464 if (v1==10)
465 thresh = vbr_nb_thresh[mode][v1];
466 else
467 thresh = (st->vbr_quality-v1)*vbr_nb_thresh[mode][v1+1] + (1+v1-st->vbr_quality)*vbr_nb_thresh[mode][v1];
468 if (st->relative_quality > thresh &&
469 st->relative_quality-thresh<min_diff)
471 choice = mode;
472 min_diff = st->relative_quality-thresh;
474 mode--;
476 mode=choice;
477 if (mode==0)
479 if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20)
481 mode=1;
482 st->dtx_count=1;
483 } else {
484 mode=0;
485 st->dtx_count++;
487 } else {
488 st->dtx_count=0;
491 speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);
492 if (st->vbr_max>0)
494 spx_int32_t rate;
495 speex_encoder_ctl(state, SPEEX_GET_BITRATE, &rate);
496 if (rate > st->vbr_max)
498 rate = st->vbr_max;
499 speex_encoder_ctl(state, SPEEX_SET_BITRATE, &rate);
503 if (st->abr_enabled)
505 spx_int32_t bitrate;
506 speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate);
507 st->abr_drift+=(bitrate-st->abr_enabled);
508 st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled);
509 st->abr_count += 1.0;
512 } else {
513 /*VAD only case*/
514 int mode;
515 if (st->relative_quality<2)
517 if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_count>20)
519 st->dtx_count=1;
520 mode=1;
521 } else {
522 mode=0;
523 st->dtx_count++;
525 } else {
526 st->dtx_count = 0;
527 mode=st->submodeSelect;
529 /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/
530 st->submodeID=mode;
532 } else {
533 st->relative_quality = -1;
535 #endif /* #ifndef DISABLE_VBR */
537 if (st->encode_submode)
539 /* First, transmit a zero for narrowband */
540 speex_bits_pack(bits, 0, 1);
542 /* Transmit the sub-mode we use for this frame */
543 speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS);
547 /* If null mode (no transmission), just set a couple things to zero*/
548 if (st->submodes[st->submodeID] == NULL)
550 for (i=0;i<st->frameSize;i++)
551 st->exc[i]=st->sw[i]=VERY_SMALL;
553 for (i=0;i<st->lpcSize;i++)
554 st->mem_sw[i]=0;
555 st->first=1;
556 st->bounded_pitch = 1;
558 SPEEX_COPY(st->winBuf, in+2*st->frameSize-st->windowSize, st->windowSize-st->frameSize);
560 /* Clear memory (no need to really compute it) */
561 for (i=0;i<st->lpcSize;i++)
562 st->mem_sp[i] = 0;
563 return 0;
567 /* LSP Quantization */
568 if (st->first)
570 for (i=0;i<st->lpcSize;i++)
571 st->old_lsp[i] = lsp[i];
575 /*Quantize LSPs*/
576 #if 1 /*0 for unquantized*/
577 SUBMODE(lsp_quant)(lsp, qlsp, st->lpcSize, bits);
578 #else
579 for (i=0;i<st->lpcSize;i++)
580 qlsp[i]=lsp[i];
581 #endif
583 /*If we use low bit-rate pitch mode, transmit open-loop pitch*/
584 if (SUBMODE(lbr_pitch)!=-1)
586 speex_bits_pack(bits, ol_pitch-st->min_pitch, 7);
589 if (SUBMODE(forced_pitch_gain))
591 int quant;
592 /* This just damps the pitch a bit, because it tends to be too aggressive when forced */
593 ol_pitch_coef = MULT16_16_Q15(QCONST16(.9,15), ol_pitch_coef);
594 #ifdef FIXED_POINT
595 quant = PSHR16(MULT16_16_16(15, ol_pitch_coef),GAIN_SHIFT);
596 #else
597 quant = (int)floor(.5+15*ol_pitch_coef*GAIN_SCALING_1);
598 #endif
599 if (quant>15)
600 quant=15;
601 if (quant<0)
602 quant=0;
603 speex_bits_pack(bits, quant, 4);
604 ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT));
608 /*Quantize and transmit open-loop excitation gain*/
609 #ifdef FIXED_POINT
611 int qe = scal_quant32(ol_gain, ol_gain_table, 32);
612 /*ol_gain = exp(qe/3.5)*SIG_SCALING;*/
613 ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]);
614 speex_bits_pack(bits, qe, 5);
616 #else
618 int qe = (int)(floor(.5+3.5*log(ol_gain*1.0/SIG_SCALING)));
619 if (qe<0)
620 qe=0;
621 if (qe>31)
622 qe=31;
623 ol_gain = exp(qe/3.5)*SIG_SCALING;
624 speex_bits_pack(bits, qe, 5);
626 #endif
630 /* Special case for first frame */
631 if (st->first)
633 for (i=0;i<st->lpcSize;i++)
634 st->old_qlsp[i] = qlsp[i];
637 /* Target signal */
638 ALLOC(target, st->subframeSize, spx_word16_t);
639 ALLOC(innov, st->subframeSize, spx_sig_t);
640 ALLOC(exc32, st->subframeSize, spx_word32_t);
641 ALLOC(ringing, st->subframeSize, spx_word16_t);
642 ALLOC(syn_resp, st->subframeSize, spx_word16_t);
643 ALLOC(real_exc, st->subframeSize, spx_word16_t);
644 ALLOC(mem, st->lpcSize, spx_mem_t);
646 /* Loop on sub-frames */
647 for (sub=0;sub<st->nbSubframes;sub++)
649 int offset;
650 spx_word16_t *sw;
651 spx_word16_t *exc;
652 int pitch;
653 int response_bound = st->subframeSize;
655 /* Offset relative to start of frame */
656 offset = st->subframeSize*sub;
657 /* Excitation */
658 exc=st->exc+offset;
659 /* Weighted signal */
660 sw=st->sw+offset;
662 /* LSP interpolation (quantized and unquantized) */
663 lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, sub, st->nbSubframes);
664 lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes);
666 /* Make sure the filters are stable */
667 lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN);
668 lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN);
670 /* Compute interpolated LPCs (quantized and unquantized) */
671 lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack);
673 lsp_to_lpc(interp_qlsp, interp_qlpc, st->lpcSize, stack);
675 /* Compute analysis filter gain at w=pi (for use in SB-CELP) */
677 spx_word32_t pi_g=LPC_SCALING;
678 for (i=0;i<st->lpcSize;i+=2)
680 /*pi_g += -st->interp_qlpc[i] + st->interp_qlpc[i+1];*/
681 pi_g = ADD32(pi_g, SUB32(EXTEND32(interp_qlpc[i+1]),EXTEND32(interp_qlpc[i])));
683 st->pi_gain[sub] = pi_g;
686 #ifdef VORBIS_PSYCHO
688 float curr_curve[128];
689 float fact = ((float)sub+1.0f)/st->nbSubframes;
690 for (i=0;i<128;i++)
691 curr_curve[i] = (1.0f-fact)*st->old_curve[i] + fact*st->curve[i];
692 curve_to_lpc(st->psy, curr_curve, bw_lpc1, bw_lpc2, 10);
694 #else
695 /* Compute bandwidth-expanded (unquantized) LPCs for perceptual weighting */
696 bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize);
697 if (st->gamma2>=0)
698 bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize);
699 else
701 for (i=0;i<st->lpcSize;i++)
702 bw_lpc2[i]=0;
704 /*print_vec(st->bw_lpc1, 10, "bw_lpc");*/
705 #endif
707 /*FIXME: This will break if we change the window size */
708 speex_assert(st->windowSize-st->frameSize == st->subframeSize);
709 if (sub==0)
711 for (i=0;i<st->subframeSize;i++)
712 real_exc[i] = sw[i] = st->winBuf[i];
713 } else {
714 for (i=0;i<st->subframeSize;i++)
715 real_exc[i] = sw[i] = in[i+((sub-1)*st->subframeSize)];
717 fir_mem16(real_exc, interp_qlpc, real_exc, st->subframeSize, st->lpcSize, st->mem_exc2, stack);
719 if (st->complexity==0)
720 response_bound >>= 1;
721 compute_impulse_response(interp_qlpc, bw_lpc1, bw_lpc2, syn_resp, response_bound, st->lpcSize, stack);
722 for (i=response_bound;i<st->subframeSize;i++)
723 syn_resp[i]=VERY_SMALL;
725 /* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */
726 for (i=0;i<st->lpcSize;i++)
727 mem[i]=SHL32(st->mem_sp[i],1);
728 for (i=0;i<st->subframeSize;i++)
729 ringing[i] = VERY_SMALL;
730 #ifdef SHORTCUTS2
731 iir_mem16(ringing, interp_qlpc, ringing, response_bound, st->lpcSize, mem, stack);
732 for (i=0;i<st->lpcSize;i++)
733 mem[i]=SHL32(st->mem_sw[i],1);
734 filter_mem16(ringing, st->bw_lpc1, st->bw_lpc2, ringing, response_bound, st->lpcSize, mem, stack);
735 SPEEX_MEMSET(&ringing[response_bound], 0, st->subframeSize-response_bound);
736 #else
737 iir_mem16(ringing, interp_qlpc, ringing, st->subframeSize, st->lpcSize, mem, stack);
738 for (i=0;i<st->lpcSize;i++)
739 mem[i]=SHL32(st->mem_sw[i],1);
740 filter_mem16(ringing, bw_lpc1, bw_lpc2, ringing, st->subframeSize, st->lpcSize, mem, stack);
741 #endif
743 /* Compute weighted signal */
744 for (i=0;i<st->lpcSize;i++)
745 mem[i]=st->mem_sw[i];
746 filter_mem16(sw, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, mem, stack);
748 if (st->complexity==0)
749 for (i=0;i<st->lpcSize;i++)
750 st->mem_sw[i]=mem[i];
752 /* Compute target signal (saturation prevents overflows on clipped input speech) */
753 for (i=0;i<st->subframeSize;i++)
754 target[i]=EXTRACT16(SATURATE(SUB32(sw[i],PSHR32(ringing[i],1)),32767));
756 /* Reset excitation */
757 SPEEX_MEMSET(exc, 0, st->subframeSize);
759 /* If we have a long-term predictor (otherwise, something's wrong) */
760 speex_assert (SUBMODE(ltp_quant));
762 int pit_min, pit_max;
763 /* Long-term prediction */
764 if (SUBMODE(lbr_pitch) != -1)
766 /* Low bit-rate pitch handling */
767 int margin;
768 margin = SUBMODE(lbr_pitch);
769 if (margin)
771 if (ol_pitch < st->min_pitch+margin-1)
772 ol_pitch=st->min_pitch+margin-1;
773 if (ol_pitch > st->max_pitch-margin)
774 ol_pitch=st->max_pitch-margin;
775 pit_min = ol_pitch-margin+1;
776 pit_max = ol_pitch+margin;
777 } else {
778 pit_min=pit_max=ol_pitch;
780 } else {
781 pit_min = st->min_pitch;
782 pit_max = st->max_pitch;
785 /* Force pitch to use only the current frame if needed */
786 if (st->bounded_pitch && pit_max>offset)
787 pit_max=offset;
789 /* Perform pitch search */
790 pitch = SUBMODE(ltp_quant)(target, sw, interp_qlpc, bw_lpc1, bw_lpc2,
791 exc32, SUBMODE(ltp_params), pit_min, pit_max, ol_pitch_coef,
792 st->lpcSize, st->subframeSize, bits, stack,
793 exc, syn_resp, st->complexity, 0, st->plc_tuning, &st->cumul_gain);
795 st->pitch[sub]=pitch;
797 /* Quantization of innovation */
798 SPEEX_MEMSET(innov, 0, st->subframeSize);
800 /* FIXME: Make sure this is save from overflows (so far so good) */
801 for (i=0;i<st->subframeSize;i++)
802 real_exc[i] = EXTRACT16(SUB32(EXTEND32(real_exc[i]), PSHR32(exc32[i],SIG_SHIFT-1)));
804 ener = SHL32(EXTEND32(compute_rms16(real_exc, st->subframeSize)),SIG_SHIFT);
806 /*FIXME: Should use DIV32_16 and make sure result fits in 16 bits */
807 #ifdef FIXED_POINT
809 spx_word32_t f = PDIV32(ener,PSHR32(ol_gain,SIG_SHIFT));
810 if (f<=32767)
811 fine_gain = f;
812 else
813 fine_gain = 32767;
815 #else
816 fine_gain = PDIV32_16(ener,PSHR32(ol_gain,SIG_SHIFT));
817 #endif
818 /* Calculate gain correction for the sub-frame (if any) */
819 if (SUBMODE(have_subframe_gain))
821 int qe;
822 if (SUBMODE(have_subframe_gain)==3)
824 qe = scal_quant(fine_gain, exc_gain_quant_scal3_bound, 8);
825 speex_bits_pack(bits, qe, 3);
826 ener=MULT16_32_Q14(exc_gain_quant_scal3[qe],ol_gain);
827 } else {
828 qe = scal_quant(fine_gain, exc_gain_quant_scal1_bound, 2);
829 speex_bits_pack(bits, qe, 1);
830 ener=MULT16_32_Q14(exc_gain_quant_scal1[qe],ol_gain);
832 } else {
833 ener=ol_gain;
836 /*printf ("%f %f\n", ener, ol_gain);*/
838 /* Normalize innovation */
839 signal_div(target, target, ener, st->subframeSize);
841 /* Quantize innovation */
842 speex_assert (SUBMODE(innovation_quant));
844 /* Codebook search */
845 SUBMODE(innovation_quant)(target, interp_qlpc, bw_lpc1, bw_lpc2,
846 SUBMODE(innovation_params), st->lpcSize, st->subframeSize,
847 innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_codebook));
849 /* De-normalize innovation and update excitation */
850 signal_mul(innov, innov, ener, st->subframeSize);
852 for (i=0;i<st->subframeSize;i++)
853 exc[i] = EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i]),SIG_SHIFT),32767));
855 /* In some (rare) modes, we do a second search (more bits) to reduce noise even more */
856 if (SUBMODE(double_codebook)) {
857 char *tmp_stack=stack;
858 VARDECL(spx_sig_t *innov2);
859 ALLOC(innov2, st->subframeSize, spx_sig_t);
860 SPEEX_MEMSET(innov2, 0, st->subframeSize);
861 for (i=0;i<st->subframeSize;i++)
862 target[i]=MULT16_16_P13(QCONST16(2.2f,13), target[i]);
863 SUBMODE(innovation_quant)(target, interp_qlpc, bw_lpc1, bw_lpc2,
864 SUBMODE(innovation_params), st->lpcSize, st->subframeSize,
865 innov2, syn_resp, bits, stack, st->complexity, 0);
866 signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),ener), st->subframeSize);
867 for (i=0;i<st->subframeSize;i++)
868 innov[i] = ADD32(innov[i],innov2[i]);
869 stack = tmp_stack;
871 for (i=0;i<st->subframeSize;i++)
872 exc[i] = EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i]),SIG_SHIFT),32767));
873 if (st->innov_rms_save)
875 st->innov_rms_save[sub] = compute_rms(innov, st->subframeSize);
879 /* Final signal synthesis from excitation */
880 iir_mem16(exc, interp_qlpc, sw, st->subframeSize, st->lpcSize, st->mem_sp, stack);
882 /* Compute weighted signal again, from synthesized speech (not sure it's the right thing) */
883 if (st->complexity!=0)
884 filter_mem16(sw, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, st->mem_sw, stack);
888 /* Store the LSPs for interpolation in the next frame */
889 if (st->submodeID>=1)
891 for (i=0;i<st->lpcSize;i++)
892 st->old_lsp[i] = lsp[i];
893 for (i=0;i<st->lpcSize;i++)
894 st->old_qlsp[i] = qlsp[i];
897 #ifdef VORBIS_PSYCHO
898 if (st->submodeID>=1)
899 SPEEX_COPY(st->old_curve, st->curve, 128);
900 #endif
902 if (st->submodeID==1)
904 #ifndef DISABLE_VBR
905 if (st->dtx_count)
906 speex_bits_pack(bits, 15, 4);
907 else
908 #endif
909 speex_bits_pack(bits, 0, 4);
912 /* The next frame will not be the first (Duh!) */
913 st->first = 0;
914 SPEEX_COPY(st->winBuf, in+2*st->frameSize-st->windowSize, st->windowSize-st->frameSize);
916 if (SUBMODE(innovation_quant) == noise_codebook_quant || st->submodeID==0)
917 st->bounded_pitch = 1;
918 else
919 st->bounded_pitch = 0;
921 return 1;
924 void *nb_decoder_init(const SpeexMode *m)
926 DecState *st;
927 const SpeexNBMode *mode;
928 int i;
930 mode=(const SpeexNBMode*)m->mode;
931 st = (DecState *)speex_alloc(sizeof(DecState));
932 if (!st)
933 return NULL;
934 #if defined(VAR_ARRAYS) || defined (USE_ALLOCA)
935 st->stack = NULL;
936 #else
937 st->stack = (char*)speex_alloc_scratch(NB_DEC_STACK);
938 #endif
940 st->mode=m;
943 st->encode_submode = 1;
945 st->first=1;
946 /* Codec parameters, should eventually have several "modes"*/
947 st->frameSize = mode->frameSize;
948 st->nbSubframes=mode->frameSize/mode->subframeSize;
949 st->subframeSize=mode->subframeSize;
950 st->lpcSize = mode->lpcSize;
951 st->min_pitch=mode->pitchStart;
952 st->max_pitch=mode->pitchEnd;
954 st->submodes=mode->submodes;
955 st->submodeID=mode->defaultSubmode;
957 st->lpc_enh_enabled=1;
959 st->excBuf = (spx_word16_t*)speex_alloc((st->frameSize + 2*st->max_pitch + st->subframeSize + 12)*sizeof(spx_word16_t));
960 st->exc = st->excBuf + 2*st->max_pitch + st->subframeSize + 6;
961 SPEEX_MEMSET(st->excBuf, 0, st->frameSize + st->max_pitch);
963 st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t));
964 st->old_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t));
965 st->mem_sp = (spx_mem_t*)speex_alloc(st->lpcSize*sizeof(spx_mem_t));
966 st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_t));
967 st->last_pitch = 40;
968 st->count_lost=0;
969 st->pitch_gain_buf[0] = st->pitch_gain_buf[1] = st->pitch_gain_buf[2] = 0;
970 st->pitch_gain_buf_idx = 0;
971 st->seed = 1000;
973 st->sampling_rate=8000;
974 st->last_ol_gain = 0;
976 st->user_callback.func = &speex_default_user_handler;
977 st->user_callback.data = NULL;
978 for (i=0;i<16;i++)
979 st->speex_callbacks[i].func = NULL;
981 st->voc_m1=st->voc_m2=st->voc_mean=0;
982 st->voc_offset=0;
983 st->dtx_enabled=0;
984 st->isWideband = 0;
985 st->highpass_enabled = 1;
987 #ifdef ENABLE_VALGRIND
988 VALGRIND_MAKE_READABLE(st, NB_DEC_STACK);
989 #endif
990 return st;
993 void nb_decoder_destroy(void *state)
995 DecState *st;
996 st=(DecState*)state;
998 #if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA))
999 speex_free_scratch(st->stack);
1000 #endif
1002 speex_free (st->excBuf);
1003 speex_free (st->interp_qlpc);
1004 speex_free (st->old_qlsp);
1005 speex_free (st->mem_sp);
1006 speex_free (st->pi_gain);
1008 speex_free(state);
1011 #define median3(a, b, c) ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c) : (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a))))
1013 #ifdef FIXED_POINT
1014 const spx_word16_t attenuation[10] = {32767, 31483, 27923, 22861, 17278, 12055, 7764, 4616, 2533, 1283};
1015 #else
1016 const spx_word16_t attenuation[10] = {1., 0.961, 0.852, 0.698, 0.527, 0.368, 0.237, 0.141, 0.077, 0.039};
1018 #endif
1020 static void nb_decode_lost(DecState *st, spx_word16_t *out, char *stack)
1022 int i;
1023 int pitch_val;
1024 spx_word16_t pitch_gain;
1025 spx_word16_t fact;
1026 spx_word16_t gain_med;
1027 spx_word16_t innov_gain;
1028 spx_word16_t noise_gain;
1030 if (st->count_lost<10)
1031 fact = attenuation[st->count_lost];
1032 else
1033 fact = 0;
1035 gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], st->pitch_gain_buf[2]);
1036 if (gain_med < st->last_pitch_gain)
1037 st->last_pitch_gain = gain_med;
1039 #ifdef FIXED_POINT
1040 pitch_gain = st->last_pitch_gain;
1041 if (pitch_gain>54)
1042 pitch_gain = 54;
1043 pitch_gain = SHL16(pitch_gain, 9);
1044 #else
1045 pitch_gain = GAIN_SCALING_1*st->last_pitch_gain;
1046 if (pitch_gain>.85)
1047 pitch_gain=.85;
1048 #endif
1049 pitch_gain = MULT16_16_Q15(fact,pitch_gain) + VERY_SMALL;
1050 /* FIXME: This was rms of innovation (not exc) */
1051 innov_gain = compute_rms16(st->exc, st->frameSize);
1052 noise_gain = MULT16_16_Q15(innov_gain, MULT16_16_Q15(fact, SUB16(Q15ONE,MULT16_16_Q15(pitch_gain,pitch_gain))));
1053 /* Shift all buffers by one frame */
1054 SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, 2*st->max_pitch + st->subframeSize + 12);
1057 pitch_val = st->last_pitch + SHR32((spx_int32_t)speex_rand(1+st->count_lost, &st->seed),SIG_SHIFT);
1058 if (pitch_val > st->max_pitch)
1059 pitch_val = st->max_pitch;
1060 if (pitch_val < st->min_pitch)
1061 pitch_val = st->min_pitch;
1062 for (i=0;i<st->frameSize;i++)
1064 st->exc[i]= MULT16_16_Q15(pitch_gain, (st->exc[i-pitch_val]+VERY_SMALL)) +
1065 speex_rand(noise_gain, &st->seed);
1068 bw_lpc(QCONST16(.98,15), st->interp_qlpc, st->interp_qlpc, st->lpcSize);
1069 iir_mem16(&st->exc[-st->subframeSize], st->interp_qlpc, out, st->frameSize,
1070 st->lpcSize, st->mem_sp, stack);
1071 highpass(out, out, st->frameSize, HIGHPASS_NARROWBAND|HIGHPASS_OUTPUT, st->mem_hp);
1073 st->first = 0;
1074 st->count_lost++;
1075 st->pitch_gain_buf[st->pitch_gain_buf_idx++] = PSHR16(pitch_gain,9);
1076 if (st->pitch_gain_buf_idx > 2) /* rollover */
1077 st->pitch_gain_buf_idx = 0;
1080 /* Just so we don't need to carry the complete wideband mode information */
1081 static const int wb_skip_table[8] = {0, 36, 112, 192, 352, 0, 0, 0};
1083 int nb_decode(void *state, SpeexBits *bits, void *vout)
1085 DecState *st;
1086 int i, sub;
1087 int pitch;
1088 spx_word16_t pitch_gain[3];
1089 spx_word32_t ol_gain=0;
1090 int ol_pitch=0;
1091 spx_word16_t ol_pitch_coef=0;
1092 int best_pitch=40;
1093 spx_word16_t best_pitch_gain=0;
1094 int wideband;
1095 int m;
1096 char *stack;
1097 VARDECL(spx_sig_t *innov);
1098 VARDECL(spx_word32_t *exc32);
1099 VARDECL(spx_coef_t *ak);
1100 VARDECL(spx_lsp_t *qlsp);
1101 spx_word16_t pitch_average=0;
1103 spx_word16_t *out = (spx_word16_t*)vout;
1104 VARDECL(spx_lsp_t *interp_qlsp);
1106 st=(DecState*)state;
1107 stack=st->stack;
1109 /* Check if we're in DTX mode*/
1110 if (!bits && st->dtx_enabled)
1112 st->submodeID=0;
1113 } else
1115 /* If bits is NULL, consider the packet to be lost (what could we do anyway) */
1116 if (!bits)
1118 nb_decode_lost(st, out, stack);
1119 return 0;
1122 if (st->encode_submode)
1125 /* Search for next narrowband block (handle requests, skip wideband blocks) */
1126 do {
1127 if (speex_bits_remaining(bits)<5)
1128 return -1;
1129 wideband = speex_bits_unpack_unsigned(bits, 1);
1130 if (wideband) /* Skip wideband block (for compatibility) */
1132 int submode;
1133 int advance;
1134 advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS);
1135 /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);*/
1136 advance = wb_skip_table[submode];
1137 if (advance < 0)
1139 speex_notify("Invalid mode encountered. The stream is corrupted.");
1140 return -2;
1142 advance -= (SB_SUBMODE_BITS+1);
1143 speex_bits_advance(bits, advance);
1145 if (speex_bits_remaining(bits)<5)
1146 return -1;
1147 wideband = speex_bits_unpack_unsigned(bits, 1);
1148 if (wideband)
1150 advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS);
1151 /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);*/
1152 advance = wb_skip_table[submode];
1153 if (advance < 0)
1155 speex_notify("Invalid mode encountered. The stream is corrupted.");
1156 return -2;
1158 advance -= (SB_SUBMODE_BITS+1);
1159 speex_bits_advance(bits, advance);
1160 wideband = speex_bits_unpack_unsigned(bits, 1);
1161 if (wideband)
1163 speex_notify("More than two wideband layers found. The stream is corrupted.");
1164 return -2;
1169 if (speex_bits_remaining(bits)<4)
1170 return -1;
1171 /* FIXME: Check for overflow */
1172 m = speex_bits_unpack_unsigned(bits, 4);
1173 if (m==15) /* We found a terminator */
1175 return -1;
1176 } else if (m==14) /* Speex in-band request */
1178 int ret = speex_inband_handler(bits, st->speex_callbacks, state);
1179 if (ret)
1180 return ret;
1181 } else if (m==13) /* User in-band request */
1183 int ret = st->user_callback.func(bits, state, st->user_callback.data);
1184 if (ret)
1185 return ret;
1186 } else if (m>8) /* Invalid mode */
1188 speex_notify("Invalid mode encountered. The stream is corrupted.");
1189 return -2;
1192 } while (m>8);
1194 /* Get the sub-mode that was used */
1195 st->submodeID = m;
1200 /* Shift all buffers by one frame */
1201 SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, 2*st->max_pitch + st->subframeSize + 12);
1203 /* If null mode (no transmission), just set a couple things to zero*/
1204 if (st->submodes[st->submodeID] == NULL)
1206 VARDECL(spx_coef_t *lpc);
1207 ALLOC(lpc, st->lpcSize, spx_coef_t);
1208 bw_lpc(QCONST16(0.93f,15), st->interp_qlpc, lpc, st->lpcSize);
1210 spx_word16_t innov_gain=0;
1211 /* FIXME: This was innov, not exc */
1212 innov_gain = compute_rms16(st->exc, st->frameSize);
1213 for (i=0;i<st->frameSize;i++)
1214 st->exc[i]=speex_rand(innov_gain, &st->seed);
1218 st->first=1;
1220 /* Final signal synthesis from excitation */
1221 iir_mem16(st->exc, lpc, out, st->frameSize, st->lpcSize, st->mem_sp, stack);
1223 st->count_lost=0;
1224 return 0;
1227 ALLOC(qlsp, st->lpcSize, spx_lsp_t);
1229 /* Unquantize LSPs */
1230 SUBMODE(lsp_unquant)(qlsp, st->lpcSize, bits);
1232 /*Damp memory if a frame was lost and the LSP changed too much*/
1233 if (st->count_lost)
1235 spx_word16_t fact;
1236 spx_word32_t lsp_dist=0;
1237 for (i=0;i<st->lpcSize;i++)
1238 lsp_dist = ADD32(lsp_dist, EXTEND32(ABS(st->old_qlsp[i] - qlsp[i])));
1239 #ifdef FIXED_POINT
1240 fact = SHR16(19661,SHR32(lsp_dist,LSP_SHIFT+2));
1241 #else
1242 fact = .6*exp(-.2*lsp_dist);
1243 #endif
1244 for (i=0;i<st->lpcSize;i++)
1245 st->mem_sp[i] = MULT16_32_Q15(fact,st->mem_sp[i]);
1249 /* Handle first frame and lost-packet case */
1250 if (st->first || st->count_lost)
1252 for (i=0;i<st->lpcSize;i++)
1253 st->old_qlsp[i] = qlsp[i];
1256 /* Get open-loop pitch estimation for low bit-rate pitch coding */
1257 if (SUBMODE(lbr_pitch)!=-1)
1259 ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7);
1262 if (SUBMODE(forced_pitch_gain))
1264 int quant;
1265 quant = speex_bits_unpack_unsigned(bits, 4);
1266 ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT));
1269 /* Get global excitation gain */
1271 int qe;
1272 qe = speex_bits_unpack_unsigned(bits, 5);
1273 #ifdef FIXED_POINT
1274 /* FIXME: Perhaps we could slightly lower the gain here when the output is going to saturate? */
1275 ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]);
1276 #else
1277 ol_gain = SIG_SCALING*exp(qe/3.5);
1278 #endif
1281 ALLOC(ak, st->lpcSize, spx_coef_t);
1282 ALLOC(innov, st->subframeSize, spx_sig_t);
1283 ALLOC(exc32, st->subframeSize, spx_word32_t);
1285 if (st->submodeID==1)
1287 int extra;
1288 extra = speex_bits_unpack_unsigned(bits, 4);
1290 if (extra==15)
1291 st->dtx_enabled=1;
1292 else
1293 st->dtx_enabled=0;
1295 if (st->submodeID>1)
1296 st->dtx_enabled=0;
1298 /*Loop on subframes */
1299 for (sub=0;sub<st->nbSubframes;sub++)
1301 int offset;
1302 spx_word16_t *exc;
1303 spx_word16_t *sp;
1304 spx_word16_t *innov_save = NULL;
1305 spx_word16_t tmp;
1307 /* Offset relative to start of frame */
1308 offset = st->subframeSize*sub;
1309 /* Excitation */
1310 exc=st->exc+offset;
1311 /* Original signal */
1312 sp=out+offset;
1313 if (st->innov_save)
1314 innov_save = st->innov_save+offset;
1317 /* Reset excitation */
1318 SPEEX_MEMSET(exc, 0, st->subframeSize);
1320 /*Adaptive codebook contribution*/
1321 speex_assert (SUBMODE(ltp_unquant));
1323 int pit_min, pit_max;
1324 /* Handle pitch constraints if any */
1325 if (SUBMODE(lbr_pitch) != -1)
1327 int margin;
1328 margin = SUBMODE(lbr_pitch);
1329 if (margin)
1331 /* GT - need optimization?
1332 if (ol_pitch < st->min_pitch+margin-1)
1333 ol_pitch=st->min_pitch+margin-1;
1334 if (ol_pitch > st->max_pitch-margin)
1335 ol_pitch=st->max_pitch-margin;
1336 pit_min = ol_pitch-margin+1;
1337 pit_max = ol_pitch+margin;
1339 pit_min = ol_pitch-margin+1;
1340 if (pit_min < st->min_pitch)
1341 pit_min = st->min_pitch;
1342 pit_max = ol_pitch+margin;
1343 if (pit_max > st->max_pitch)
1344 pit_max = st->max_pitch;
1345 } else {
1346 pit_min = pit_max = ol_pitch;
1348 } else {
1349 pit_min = st->min_pitch;
1350 pit_max = st->max_pitch;
1355 SUBMODE(ltp_unquant)(exc, exc32, pit_min, pit_max, ol_pitch_coef, SUBMODE(ltp_params),
1356 st->subframeSize, &pitch, &pitch_gain[0], bits, stack,
1357 st->count_lost, offset, st->last_pitch_gain, 0);
1359 /* Ensuring that things aren't blowing up as would happen if e.g. an encoder is
1360 crafting packets to make us produce NaNs and slow down the decoder (vague DoS threat).
1361 We can probably be even more aggressive and limit to 15000 or so. */
1362 sanitize_values32(exc32, NEG32(QCONST32(32000,SIG_SHIFT-1)), QCONST32(32000,SIG_SHIFT-1), st->subframeSize);
1364 tmp = gain_3tap_to_1tap(pitch_gain);
1366 pitch_average += tmp;
1367 if ((tmp>best_pitch_gain&&ABS(2*best_pitch-pitch)>=3&&ABS(3*best_pitch-pitch)>=4&&ABS(4*best_pitch-pitch)>=5)
1368 || (tmp>MULT16_16_Q15(QCONST16(.6,15),best_pitch_gain)&&(ABS(best_pitch-2*pitch)<3||ABS(best_pitch-3*pitch)<4||ABS(best_pitch-4*pitch)<5))
1369 || (MULT16_16_Q15(QCONST16(.67,15),tmp)>best_pitch_gain&&(ABS(2*best_pitch-pitch)<3||ABS(3*best_pitch-pitch)<4||ABS(4*best_pitch-pitch)<5)) )
1371 best_pitch = pitch;
1372 if (tmp > best_pitch_gain)
1373 best_pitch_gain = tmp;
1377 /* Unquantize the innovation */
1379 int q_energy;
1380 spx_word32_t ener;
1382 SPEEX_MEMSET(innov, 0, st->subframeSize);
1384 /* Decode sub-frame gain correction */
1385 if (SUBMODE(have_subframe_gain)==3)
1387 q_energy = speex_bits_unpack_unsigned(bits, 3);
1388 ener = MULT16_32_Q14(exc_gain_quant_scal3[q_energy],ol_gain);
1389 } else if (SUBMODE(have_subframe_gain)==1)
1391 q_energy = speex_bits_unpack_unsigned(bits, 1);
1392 ener = MULT16_32_Q14(exc_gain_quant_scal1[q_energy],ol_gain);
1393 } else {
1394 ener = ol_gain;
1397 speex_assert (SUBMODE(innovation_unquant));
1399 /*Fixed codebook contribution*/
1400 SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), st->subframeSize, bits, stack, &st->seed);
1401 /* De-normalize innovation and update excitation */
1403 signal_mul(innov, innov, ener, st->subframeSize);
1405 /* Decode second codebook (only for some modes) */
1406 if (SUBMODE(double_codebook))
1408 char *tmp_stack=stack;
1409 VARDECL(spx_sig_t *innov2);
1410 ALLOC(innov2, st->subframeSize, spx_sig_t);
1411 SPEEX_MEMSET(innov2, 0, st->subframeSize);
1412 SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), st->subframeSize, bits, stack, &st->seed);
1413 signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),ener), st->subframeSize);
1414 for (i=0;i<st->subframeSize;i++)
1415 innov[i] = ADD32(innov[i], innov2[i]);
1416 stack = tmp_stack;
1418 for (i=0;i<st->subframeSize;i++)
1419 exc[i]=EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i]),SIG_SHIFT),32767));
1420 /*print_vec(exc, 40, "innov");*/
1421 if (innov_save)
1423 for (i=0;i<st->subframeSize;i++)
1424 innov_save[i] = EXTRACT16(PSHR32(innov[i], SIG_SHIFT));
1428 /*Vocoder mode*/
1429 if (st->submodeID==1)
1431 spx_word16_t g=ol_pitch_coef;
1432 g=MULT16_16_P14(QCONST16(1.5f,14),(g-QCONST16(.2f,6)));
1433 if (g<0)
1434 g=0;
1435 if (g>GAIN_SCALING)
1436 g=GAIN_SCALING;
1438 SPEEX_MEMSET(exc, 0, st->subframeSize);
1439 while (st->voc_offset<st->subframeSize)
1441 /* exc[st->voc_offset]= g*sqrt(2*ol_pitch)*ol_gain;
1442 Not quite sure why we need the factor of two in the sqrt */
1443 if (st->voc_offset>=0)
1444 exc[st->voc_offset]=MULT16_16(spx_sqrt(MULT16_16_16(2,ol_pitch)),EXTRACT16(PSHR32(MULT16_16(g,PSHR32(ol_gain,SIG_SHIFT)),6)));
1445 st->voc_offset+=ol_pitch;
1447 st->voc_offset -= st->subframeSize;
1449 for (i=0;i<st->subframeSize;i++)
1451 spx_word16_t exci=exc[i];
1452 exc[i]= ADD16(ADD16(MULT16_16_Q15(QCONST16(.7f,15),exc[i]) , MULT16_16_Q15(QCONST16(.3f,15),st->voc_m1)),
1453 SUB16(MULT16_16_Q15(Q15_ONE-MULT16_16_16(QCONST16(.85f,9),g),EXTRACT16(PSHR32(innov[i],SIG_SHIFT))),
1454 MULT16_16_Q15(MULT16_16_16(QCONST16(.15f,9),g),EXTRACT16(PSHR32(st->voc_m2,SIG_SHIFT)))
1456 st->voc_m1 = exci;
1457 st->voc_m2=innov[i];
1458 st->voc_mean = EXTRACT16(PSHR32(ADD32(MULT16_16(QCONST16(.8f,15),st->voc_mean), MULT16_16(QCONST16(.2f,15),exc[i])), 15));
1459 exc[i]-=st->voc_mean;
1466 ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t);
1468 if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0 && !st->count_lost)
1470 multicomb(st->exc-st->subframeSize, out, st->interp_qlpc, st->lpcSize, 2*st->subframeSize, best_pitch, 40, SUBMODE(comb_gain), stack);
1471 multicomb(st->exc+st->subframeSize, out+2*st->subframeSize, st->interp_qlpc, st->lpcSize, 2*st->subframeSize, best_pitch, 40, SUBMODE(comb_gain), stack);
1472 } else {
1473 SPEEX_COPY(out, &st->exc[-st->subframeSize], st->frameSize);
1476 /* If the last packet was lost, re-scale the excitation to obtain the same energy as encoded in ol_gain */
1477 if (st->count_lost)
1479 spx_word16_t exc_ener;
1480 spx_word32_t gain32;
1481 spx_word16_t gain;
1482 exc_ener = compute_rms16 (st->exc, st->frameSize);
1483 gain32 = PDIV32(ol_gain, ADD16(exc_ener,1));
1484 #ifdef FIXED_POINT
1485 if (gain32 > 32767)
1486 gain32 = 32767;
1487 gain = EXTRACT16(gain32);
1488 #else
1489 if (gain32 > 2)
1490 gain32=2;
1491 gain = gain32;
1492 #endif
1493 for (i=0;i<st->frameSize;i++)
1495 st->exc[i] = MULT16_16_Q14(gain, st->exc[i]);
1496 out[i]=st->exc[i-st->subframeSize];
1500 /*Loop on subframes */
1501 for (sub=0;sub<st->nbSubframes;sub++)
1503 int offset;
1504 spx_word16_t *sp;
1505 spx_word16_t *exc;
1506 /* Offset relative to start of frame */
1507 offset = st->subframeSize*sub;
1508 /* Original signal */
1509 sp=out+offset;
1510 /* Excitation */
1511 exc=st->exc+offset;
1513 /* LSP interpolation (quantized and unquantized) */
1514 lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbSubframes);
1516 /* Make sure the LSP's are stable */
1517 lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN);
1519 /* Compute interpolated LPCs (unquantized) */
1520 lsp_to_lpc(interp_qlsp, ak, st->lpcSize, stack);
1522 /* Compute analysis filter at w=pi */
1524 spx_word32_t pi_g=LPC_SCALING;
1525 for (i=0;i<st->lpcSize;i+=2)
1527 /*pi_g += -st->interp_qlpc[i] + st->interp_qlpc[i+1];*/
1528 pi_g = ADD32(pi_g, SUB32(EXTEND32(ak[i+1]),EXTEND32(ak[i])));
1530 st->pi_gain[sub] = pi_g;
1533 iir_mem16(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize,
1534 st->mem_sp, stack);
1536 for (i=0;i<st->lpcSize;i++)
1537 st->interp_qlpc[i] = ak[i];
1541 if (st->highpass_enabled)
1542 highpass(out, out, st->frameSize, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPASS_NARROWBAND)|HIGHPASS_OUTPUT, st->mem_hp);
1543 /*for (i=0;i<st->frameSize;i++)
1544 printf ("%d\n", (int)st->frame[i]);*/
1546 /* Tracking output level */
1547 st->level = 1+PSHR32(ol_gain,SIG_SHIFT);
1548 st->max_level = MAX16(MULT16_16_Q15(QCONST16(.99f,15), st->max_level), st->level);
1549 st->min_level = MIN16(ADD16(1,MULT16_16_Q14(QCONST16(1.01f,14), st->min_level)), st->level);
1550 if (st->max_level < st->min_level+1)
1551 st->max_level = st->min_level+1;
1552 /*printf ("%f %f %f %d\n", og, st->min_level, st->max_level, update);*/
1554 /* Store the LSPs for interpolation in the next frame */
1555 for (i=0;i<st->lpcSize;i++)
1556 st->old_qlsp[i] = qlsp[i];
1558 /* The next frame will not be the first (Duh!) */
1559 st->first = 0;
1560 st->count_lost=0;
1561 st->last_pitch = best_pitch;
1562 #ifdef FIXED_POINT
1563 st->last_pitch_gain = PSHR16(pitch_average,2);
1564 #else
1565 st->last_pitch_gain = .25*pitch_average;
1566 #endif
1567 st->pitch_gain_buf[st->pitch_gain_buf_idx++] = st->last_pitch_gain;
1568 if (st->pitch_gain_buf_idx > 2) /* rollover */
1569 st->pitch_gain_buf_idx = 0;
1571 st->last_ol_gain = ol_gain;
1573 return 0;
1576 int nb_encoder_ctl(void *state, int request, void *ptr)
1578 EncState *st;
1579 st=(EncState*)state;
1580 switch(request)
1582 case SPEEX_GET_FRAME_SIZE:
1583 (*(spx_int32_t*)ptr) = st->frameSize;
1584 break;
1585 case SPEEX_SET_LOW_MODE:
1586 case SPEEX_SET_MODE:
1587 st->submodeSelect = st->submodeID = (*(spx_int32_t*)ptr);
1588 break;
1589 case SPEEX_GET_LOW_MODE:
1590 case SPEEX_GET_MODE:
1591 (*(spx_int32_t*)ptr) = st->submodeID;
1592 break;
1593 #ifndef DISABLE_VBR
1594 case SPEEX_SET_VBR:
1595 st->vbr_enabled = (*(spx_int32_t*)ptr);
1596 break;
1597 case SPEEX_GET_VBR:
1598 (*(spx_int32_t*)ptr) = st->vbr_enabled;
1599 break;
1600 case SPEEX_SET_VAD:
1601 st->vad_enabled = (*(spx_int32_t*)ptr);
1602 break;
1603 case SPEEX_GET_VAD:
1604 (*(spx_int32_t*)ptr) = st->vad_enabled;
1605 break;
1606 case SPEEX_SET_DTX:
1607 st->dtx_enabled = (*(spx_int32_t*)ptr);
1608 break;
1609 case SPEEX_GET_DTX:
1610 (*(spx_int32_t*)ptr) = st->dtx_enabled;
1611 break;
1612 case SPEEX_SET_ABR:
1613 st->abr_enabled = (*(spx_int32_t*)ptr);
1614 st->vbr_enabled = st->abr_enabled!=0;
1615 if (st->vbr_enabled)
1617 spx_int32_t i=10;
1618 spx_int32_t rate, target;
1619 float vbr_qual;
1620 target = (*(spx_int32_t*)ptr);
1621 while (i>=0)
1623 speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i);
1624 speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate);
1625 if (rate <= target)
1626 break;
1627 i--;
1629 vbr_qual=i;
1630 if (vbr_qual<0)
1631 vbr_qual=0;
1632 speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual);
1633 st->abr_count=0;
1634 st->abr_drift=0;
1635 st->abr_drift2=0;
1638 break;
1639 case SPEEX_GET_ABR:
1640 (*(spx_int32_t*)ptr) = st->abr_enabled;
1641 break;
1642 #endif /* #ifndef DISABLE_VBR */
1643 #if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API)
1644 case SPEEX_SET_VBR_QUALITY:
1645 st->vbr_quality = (*(float*)ptr);
1646 break;
1647 case SPEEX_GET_VBR_QUALITY:
1648 (*(float*)ptr) = st->vbr_quality;
1649 break;
1650 #endif /* !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */
1651 case SPEEX_SET_QUALITY:
1653 int quality = (*(spx_int32_t*)ptr);
1654 if (quality < 0)
1655 quality = 0;
1656 if (quality > 10)
1657 quality = 10;
1658 st->submodeSelect = st->submodeID = ((const SpeexNBMode*)(st->mode->mode))->quality_map[quality];
1660 break;
1661 case SPEEX_SET_COMPLEXITY:
1662 st->complexity = (*(spx_int32_t*)ptr);
1663 if (st->complexity<0)
1664 st->complexity=0;
1665 break;
1666 case SPEEX_GET_COMPLEXITY:
1667 (*(spx_int32_t*)ptr) = st->complexity;
1668 break;
1669 case SPEEX_SET_BITRATE:
1671 spx_int32_t i=10;
1672 spx_int32_t rate, target;
1673 target = (*(spx_int32_t*)ptr);
1674 while (i>=0)
1676 speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i);
1677 speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate);
1678 if (rate <= target)
1679 break;
1680 i--;
1683 break;
1684 case SPEEX_GET_BITRATE:
1685 if (st->submodes[st->submodeID])
1686 (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize;
1687 else
1688 (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize;
1689 break;
1690 case SPEEX_SET_SAMPLING_RATE:
1691 st->sampling_rate = (*(spx_int32_t*)ptr);
1692 break;
1693 case SPEEX_GET_SAMPLING_RATE:
1694 (*(spx_int32_t*)ptr)=st->sampling_rate;
1695 break;
1696 case SPEEX_RESET_STATE:
1698 int i;
1699 st->bounded_pitch = 1;
1700 st->first = 1;
1701 for (i=0;i<st->lpcSize;i++)
1702 st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st->lpcSize+1);
1703 for (i=0;i<st->lpcSize;i++)
1704 st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0;
1705 for (i=0;i<st->frameSize+st->max_pitch+1;i++)
1706 st->excBuf[i]=st->swBuf[i]=0;
1707 for (i=0;i<st->windowSize-st->frameSize;i++)
1708 st->winBuf[i]=0;
1710 break;
1711 case SPEEX_SET_SUBMODE_ENCODING:
1712 st->encode_submode = (*(spx_int32_t*)ptr);
1713 break;
1714 case SPEEX_GET_SUBMODE_ENCODING:
1715 (*(spx_int32_t*)ptr) = st->encode_submode;
1716 break;
1717 case SPEEX_GET_LOOKAHEAD:
1718 (*(spx_int32_t*)ptr)=(st->windowSize-st->frameSize);
1719 break;
1720 case SPEEX_SET_PLC_TUNING:
1721 st->plc_tuning = (*(spx_int32_t*)ptr);
1722 if (st->plc_tuning>100)
1723 st->plc_tuning=100;
1724 break;
1725 case SPEEX_GET_PLC_TUNING:
1726 (*(spx_int32_t*)ptr)=(st->plc_tuning);
1727 break;
1728 #ifndef DISABLE_VBR
1729 case SPEEX_SET_VBR_MAX_BITRATE:
1730 st->vbr_max = (*(spx_int32_t*)ptr);
1731 break;
1732 case SPEEX_GET_VBR_MAX_BITRATE:
1733 (*(spx_int32_t*)ptr) = st->vbr_max;
1734 break;
1735 #endif /* #ifndef DISABLE_VBR */
1736 case SPEEX_SET_HIGHPASS:
1737 st->highpass_enabled = (*(spx_int32_t*)ptr);
1738 break;
1739 case SPEEX_GET_HIGHPASS:
1740 (*(spx_int32_t*)ptr) = st->highpass_enabled;
1741 break;
1743 /* This is all internal stuff past this point */
1744 case SPEEX_GET_PI_GAIN:
1746 int i;
1747 spx_word32_t *g = (spx_word32_t*)ptr;
1748 for (i=0;i<st->nbSubframes;i++)
1749 g[i]=st->pi_gain[i];
1751 break;
1752 case SPEEX_GET_EXC:
1754 int i;
1755 for (i=0;i<st->nbSubframes;i++)
1756 ((spx_word16_t*)ptr)[i] = compute_rms16(st->exc+i*st->subframeSize, st->subframeSize);
1758 break;
1759 #ifndef DISABLE_VBR
1760 case SPEEX_GET_RELATIVE_QUALITY:
1761 (*(float*)ptr)=st->relative_quality;
1762 break;
1763 #endif /* #ifndef DISABLE_VBR */
1764 case SPEEX_SET_INNOVATION_SAVE:
1765 st->innov_rms_save = (spx_word16_t*)ptr;
1766 break;
1767 case SPEEX_SET_WIDEBAND:
1768 st->isWideband = *((spx_int32_t*)ptr);
1769 break;
1770 case SPEEX_GET_STACK:
1771 *((char**)ptr) = st->stack;
1772 break;
1773 default:
1774 speex_warning_int("Unknown nb_ctl request: ", request);
1775 return -1;
1777 return 0;
1780 int nb_decoder_ctl(void *state, int request, void *ptr)
1782 DecState *st;
1783 st=(DecState*)state;
1784 switch(request)
1786 case SPEEX_SET_LOW_MODE:
1787 case SPEEX_SET_MODE:
1788 st->submodeID = (*(spx_int32_t*)ptr);
1789 break;
1790 case SPEEX_GET_LOW_MODE:
1791 case SPEEX_GET_MODE:
1792 (*(spx_int32_t*)ptr) = st->submodeID;
1793 break;
1794 case SPEEX_SET_ENH:
1795 st->lpc_enh_enabled = *((spx_int32_t*)ptr);
1796 break;
1797 case SPEEX_GET_ENH:
1798 *((spx_int32_t*)ptr) = st->lpc_enh_enabled;
1799 break;
1800 case SPEEX_GET_FRAME_SIZE:
1801 (*(spx_int32_t*)ptr) = st->frameSize;
1802 break;
1803 case SPEEX_GET_BITRATE:
1804 if (st->submodes[st->submodeID])
1805 (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->frameSize;
1806 else
1807 (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameSize;
1808 break;
1809 case SPEEX_SET_SAMPLING_RATE:
1810 st->sampling_rate = (*(spx_int32_t*)ptr);
1811 break;
1812 case SPEEX_GET_SAMPLING_RATE:
1813 (*(spx_int32_t*)ptr)=st->sampling_rate;
1814 break;
1815 case SPEEX_SET_HANDLER:
1817 SpeexCallback *c = (SpeexCallback*)ptr;
1818 st->speex_callbacks[c->callback_id].func=c->func;
1819 st->speex_callbacks[c->callback_id].data=c->data;
1820 st->speex_callbacks[c->callback_id].callback_id=c->callback_id;
1822 break;
1823 case SPEEX_SET_USER_HANDLER:
1825 SpeexCallback *c = (SpeexCallback*)ptr;
1826 st->user_callback.func=c->func;
1827 st->user_callback.data=c->data;
1828 st->user_callback.callback_id=c->callback_id;
1830 break;
1831 case SPEEX_RESET_STATE:
1833 int i;
1834 for (i=0;i<st->lpcSize;i++)
1835 st->mem_sp[i]=0;
1836 for (i=0;i<st->frameSize + st->max_pitch + 1;i++)
1837 st->excBuf[i]=0;
1839 break;
1840 case SPEEX_SET_SUBMODE_ENCODING:
1841 st->encode_submode = (*(spx_int32_t*)ptr);
1842 break;
1843 case SPEEX_GET_SUBMODE_ENCODING:
1844 (*(spx_int32_t*)ptr) = st->encode_submode;
1845 break;
1846 case SPEEX_GET_LOOKAHEAD:
1847 (*(spx_int32_t*)ptr)=st->subframeSize;
1848 break;
1849 case SPEEX_SET_HIGHPASS:
1850 st->highpass_enabled = (*(spx_int32_t*)ptr);
1851 break;
1852 case SPEEX_GET_HIGHPASS:
1853 (*(spx_int32_t*)ptr) = st->highpass_enabled;
1854 break;
1855 /* FIXME: Convert to fixed-point and re-enable even when float API is disabled */
1856 #ifndef DISABLE_FLOAT_API
1857 case SPEEX_GET_ACTIVITY:
1859 float ret;
1860 ret = log(st->level/st->min_level)/log(st->max_level/st->min_level);
1861 if (ret>1)
1862 ret = 1;
1863 /* Done in a strange way to catch NaNs as well */
1864 if (!(ret > 0))
1865 ret = 0;
1866 /*printf ("%f %f %f %f\n", st->level, st->min_level, st->max_level, ret);*/
1867 (*(spx_int32_t*)ptr) = (int)(100*ret);
1869 break;
1870 #endif
1871 case SPEEX_GET_PI_GAIN:
1873 int i;
1874 spx_word32_t *g = (spx_word32_t*)ptr;
1875 for (i=0;i<st->nbSubframes;i++)
1876 g[i]=st->pi_gain[i];
1878 break;
1879 case SPEEX_GET_EXC:
1881 int i;
1882 for (i=0;i<st->nbSubframes;i++)
1883 ((spx_word16_t*)ptr)[i] = compute_rms16(st->exc+i*st->subframeSize, st->subframeSize);
1885 break;
1886 case SPEEX_GET_DTX_STATUS:
1887 *((spx_int32_t*)ptr) = st->dtx_enabled;
1888 break;
1889 case SPEEX_SET_INNOVATION_SAVE:
1890 st->innov_save = (spx_word16_t*)ptr;
1891 break;
1892 case SPEEX_SET_WIDEBAND:
1893 st->isWideband = *((spx_int32_t*)ptr);
1894 break;
1895 case SPEEX_GET_STACK:
1896 *((char**)ptr) = st->stack;
1897 break;
1898 default:
1899 speex_warning_int("Unknown nb_ctl request: ", request);
1900 return -1;
1902 return 0;