minor fixes to modes_noglobals.c
[speexdsp.git] / libspeex / modes_noglobals.c
1 /* Copyright (C) 2002 Jean-Marc Valin 
2    File: modes_noglobals.c
3
4    Describes the different modes of the codec
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9    
10    - Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12    
13    - Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16    
17    - Neither the name of the Xiph.org Foundation nor the names of its
18    contributors may be used to endorse or promote products derived from
19    this software without specific prior written permission.
20    
21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
25    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 */
34
35 #include "modes.h"
36 #include "ltp.h"
37 #include "quant_lsp.h"
38 #include "cb_search.h"
39 #include "sb_celp.h"
40 #include "nb_celp.h"
41 #include "vbr.h"
42 #include "misc.h"
43 #include <math.h>
44
45 #ifndef NULL
46 #define NULL 0
47 #endif
48
49 /* Extern declarations for all codebooks we use here */
50 extern const signed char gain_cdbk_nb[];
51 extern const signed char gain_cdbk_lbr[];
52 extern const signed char hexc_table[];
53 extern const signed char exc_5_256_table[];
54 extern const signed char exc_5_64_table[];
55 extern const signed char exc_8_128_table[];
56 extern const signed char exc_10_32_table[];
57 extern const signed char exc_10_16_table[];
58 extern const signed char exc_20_32_table[];
59 extern const signed char hexc_10_32_table[];
60
61 static const ltp_params *
62 speex_ltp_params_new (const signed char * gain_cdbk, int gain_bits,
63                       int pitch_bits)
64 {
65   ltp_params * params;
66
67   params = (ltp_params *) speex_alloc (sizeof (ltp_params));
68   if (params == NULL) return NULL;
69
70   params->gain_cdbk = gain_cdbk;
71   params->gain_bits = gain_bits;
72   params->pitch_bits = pitch_bits;
73
74   return params;
75 }
76
77 static void
78 speex_ltp_params_free (ltp_params * params)
79 {
80   speex_free (params);
81 }
82
83 static const split_cb_params *
84 speex_split_cb_params_new (int subvect_size, int nb_subvect,
85                            const signed char * shape_cb, int shape_bits,
86                            int have_sign)
87 {
88   split_cb_params * params;
89
90   params = (split_cb_params *) speex_alloc (sizeof (split_cb_params));
91   if (params == NULL) return NULL;
92
93   params->subvect_size = subvect_size;
94   params->nb_subvect = nb_subvect;
95   params->shape_cb = shape_cb;
96   params->shape_bits = shape_bits;
97   params->have_sign = have_sign;
98
99   return params;
100 }
101
102 static void
103 speex_split_cb_params_free (split_cb_params * params)
104 {
105   speex_free (params);
106 }
107
108 static SpeexSubmode *
109 speex_submode_new (int lbr_pitch, int forced_pitch_gain,
110                    int have_subframe_gain, int double_codebook,
111
112                    lsp_quant_func lsp_quant, lsp_unquant_func lsp_unquant,
113                    ltp_quant_func ltp_quant, ltp_unquant_func ltp_unquant,
114                    const void * ltp_params,
115
116                    innovation_quant_func innovation_quant,
117                    innovation_unquant_func innovation_unquant,
118                    const void * innovation_params,
119
120                    /*Synthesis filter enhancement*/
121                    spx_word16_t      lpc_enh_k1, /**< Enhancer constant */
122                    spx_word16_t      lpc_enh_k2, /**< Enhancer constant */
123                    spx_word16_t      lpc_enh_k3, /**< Enhancer constant */
124                    spx_word16_t      comb_gain,  /**< Gain of enhancer comb filter */
125                    
126                    int               bits_per_frame /**< Number of bits per frame after encoding*/
127
128                    )
129 {
130   SpeexSubmode * submode;
131
132   submode = (SpeexSubmode *) speex_alloc (sizeof (SpeexSubmode));
133   if (submode == NULL) return NULL;
134
135   submode->lbr_pitch = lbr_pitch;
136   submode->forced_pitch_gain = forced_pitch_gain;
137   submode->have_subframe_gain = have_subframe_gain;
138   submode->double_codebook = double_codebook;
139   submode->lsp_quant = lsp_quant;
140   submode->lsp_unquant = lsp_unquant;
141   submode->ltp_quant = ltp_quant;
142   submode->ltp_unquant = ltp_unquant;
143   submode->ltp_params = ltp_params;
144   submode->innovation_quant = innovation_quant;
145   submode->innovation_unquant = innovation_unquant;
146   submode->innovation_params = innovation_params;
147   submode->lpc_enh_k1 = lpc_enh_k1;
148   submode->lpc_enh_k2 = lpc_enh_k2;
149   submode->lpc_enh_k3 = lpc_enh_k3;
150   submode->comb_gain = comb_gain;
151   submode->bits_per_frame = bits_per_frame;
152
153   return submode;
154 }
155
156 static void
157 speex_submode_free (const SpeexSubmode * submode)
158 {
159   speex_free ((void *)submode);
160 }
161
162 static SpeexNBMode *
163 nb_mode_new (int frameSize, int subframeSize, int lpcSize, int bufSize,
164              int pitchStart, int pitchEnd, spx_word16_t gamma1,
165              spx_word16_t gamma2, float lag_factor, float lpc_floor,
166 #ifdef EPIC_48K
167              int lbr48k,
168 #endif
169              const SpeexSubmode * submodes[], int defaultSubmode,
170              int quality_map[])
171 {
172   SpeexNBMode * nb_mode;
173
174   nb_mode = (SpeexNBMode *) speex_alloc (sizeof (SpeexNBMode));
175   if (nb_mode == NULL) return NULL;
176
177   nb_mode->frameSize = frameSize;
178   nb_mode->subframeSize = subframeSize;
179   nb_mode->lpcSize = lpcSize;
180   nb_mode->bufSize = bufSize;
181   nb_mode->pitchStart = pitchStart;
182   nb_mode->pitchEnd = pitchEnd;
183   nb_mode->gamma1 = gamma1;
184   nb_mode->gamma2 = gamma2;
185   nb_mode->lag_factor = lag_factor;
186   nb_mode->lpc_floor = lpc_floor;
187 #ifdef EPIC_48K
188   nb_mode->lbr48k = lbr48k;
189 #endif
190   memcpy (nb_mode->submodes, submodes, sizeof (nb_mode->submodes));
191   nb_mode->defaultSubmode = defaultSubmode;
192   memcpy (nb_mode->quality_map, quality_map, sizeof (nb_mode->quality_map));
193
194   return nb_mode;
195 }
196
197 static void
198 nb_mode_free (const SpeexNBMode * nb_mode)
199 {
200   speex_free ((void *)nb_mode);
201 }
202
203 static SpeexSBMode *
204 sb_mode_new (
205    const SpeexMode *nb_mode,    /**< Embedded narrowband mode */
206    int     frameSize,     /**< Size of frames used for encoding */
207    int     subframeSize,  /**< Size of sub-frames used for encoding */
208    int     lpcSize,       /**< Order of LPC filter */
209    int     bufSize,       /**< Signal buffer size in encoder */
210    spx_word16_t gamma1,   /**< Perceptual filter parameter #1 */
211    spx_word16_t gamma2,   /**< Perceptual filter parameter #1 */
212    float   lag_factor,    /**< Lag-windowing parameter */
213    float   lpc_floor,     /**< Noise floor for LPC analysis */
214    float   folding_gain,
215
216    const SpeexSubmode *submodes[], /**< Sub-mode data for the mode */
217    int     defaultSubmode, /**< Default sub-mode to use when encoding */
218    int     low_quality_map[], /**< Mode corresponding to each quality setting */
219    int     quality_map[], /**< Mode corresponding to each quality setting */
220    float   (*vbr_thresh)[11],
221    int     nb_modes
222                    )
223 {
224   SpeexSBMode * sb_mode;
225
226   sb_mode = (SpeexSBMode *) speex_alloc (sizeof (SpeexSBMode));
227   if (sb_mode == NULL) return NULL;
228
229   sb_mode->nb_mode = nb_mode;
230   sb_mode->frameSize = frameSize;
231   sb_mode->subframeSize = subframeSize;
232   sb_mode->lpcSize = lpcSize;
233   sb_mode->bufSize = bufSize;
234   sb_mode->gamma1 = gamma1;
235   sb_mode->gamma2 = gamma2;
236   sb_mode->lag_factor = lag_factor;
237   sb_mode->lpc_floor = lpc_floor;
238   sb_mode->folding_gain = folding_gain;
239
240   memcpy (sb_mode->submodes, submodes, sizeof (sb_mode->submodes));
241   sb_mode->defaultSubmode = defaultSubmode;
242   memcpy (sb_mode->low_quality_map, low_quality_map, sizeof (sb_mode->low_quality_map));
243   memcpy (sb_mode->quality_map, quality_map, sizeof (sb_mode->quality_map));
244   sb_mode->vbr_thresh = vbr_thresh;
245   sb_mode->nb_modes = nb_modes;
246
247   return sb_mode;
248 }
249
250 static void
251 sb_mode_free (const SpeexSBMode * sb_mode)
252 {
253   int i;
254
255   for (i = 0; i < SB_SUBMODES; i++)
256     if (sb_mode->submodes[i]) speex_submode_free (sb_mode->submodes[i]);
257
258   speex_free ((void *)sb_mode);
259 }
260
261 static SpeexMode *
262 speex_mode_new (const void * b_mode, mode_query_func query, char * modeName,
263                 int modeID, int bitstream_version, encoder_init_func enc_init,
264                 encoder_destroy_func enc_destroy, encode_func enc,
265                 decoder_init_func dec_init, decoder_destroy_func dec_destroy,
266                 decode_func dec, encoder_ctl_func enc_ctl,
267                 decoder_ctl_func dec_ctl)
268 {
269   SpeexMode * mode;
270
271   mode = (SpeexMode *) speex_alloc (sizeof (SpeexMode));
272   if (mode == NULL) return NULL;
273
274   mode->mode = b_mode;
275   mode->query = query;
276   mode->modeName = modeName;
277   mode->modeID = modeID;
278   mode->bitstream_version = bitstream_version;
279   mode->enc_init = enc_init;
280   mode->enc_destroy = enc_destroy;
281   mode->enc = enc;
282   mode->dec_init = dec_init;
283   mode->dec_destroy = dec_destroy;
284   mode->dec = dec;
285   mode->enc_ctl = enc_ctl;
286   mode->dec_ctl = dec_ctl;
287
288   return mode;
289 }
290
291 /* Freeing each kind of created (SpeexMode *) is done separately below */
292
293 /* Parameters for Long-Term Prediction (LTP)*/
294 static const ltp_params * ltp_params_nb (void)
295 {
296   return speex_ltp_params_new (
297    gain_cdbk_nb,
298    7,
299    7
300    );
301 };
302
303 /* Parameters for Long-Term Prediction (LTP)*/
304 static const ltp_params * ltp_params_vlbr (void)
305 {
306   return speex_ltp_params_new (
307    gain_cdbk_lbr,
308    5,
309    0
310    );
311 };
312
313 /* Parameters for Long-Term Prediction (LTP)*/
314 static const ltp_params * ltp_params_lbr (void)
315 {
316   return speex_ltp_params_new (
317    gain_cdbk_lbr,
318    5,
319    7
320    );
321 };
322
323 /* Parameters for Long-Term Prediction (LTP)*/
324 static const ltp_params * ltp_params_med (void)
325 {
326   return speex_ltp_params_new (
327    gain_cdbk_lbr,
328    5,
329    7
330    );
331 };
332
333 /* Split-VQ innovation parameters for very low bit-rate narrowband */
334 static const split_cb_params * split_cb_nb_vlbr (void)
335 {
336   return speex_split_cb_params_new (
337    10,               /*subvect_size*/
338    4,               /*nb_subvect*/
339    exc_10_16_table, /*shape_cb*/
340    4,               /*shape_bits*/
341    0
342    );
343 };
344
345 /* Split-VQ innovation parameters for very low bit-rate narrowband */
346 static const split_cb_params * split_cb_nb_ulbr (void)
347 {
348   return speex_split_cb_params_new (
349    20,               /*subvect_size*/
350    2,               /*nb_subvect*/
351    exc_20_32_table, /*shape_cb*/
352    5,               /*shape_bits*/
353    0
354    );
355 };
356
357 /* Split-VQ innovation parameters for low bit-rate narrowband */
358 static const split_cb_params * split_cb_nb_lbr (void)
359 {
360   return speex_split_cb_params_new (
361    10,              /*subvect_size*/
362    4,               /*nb_subvect*/
363    exc_10_32_table, /*shape_cb*/
364    5,               /*shape_bits*/
365    0
366    );
367 };
368
369
370 /* Split-VQ innovation parameters narrowband */
371 static const split_cb_params * split_cb_nb (void)
372 {
373   return speex_split_cb_params_new (
374    5,               /*subvect_size*/
375    8,               /*nb_subvect*/
376    exc_5_64_table, /*shape_cb*/
377    6,               /*shape_bits*/
378    0
379    );
380 };
381
382 /* Split-VQ innovation parameters narrowband */
383 static const split_cb_params * split_cb_nb_med (void)
384 {
385   return speex_split_cb_params_new (
386    8,               /*subvect_size*/
387    5,               /*nb_subvect*/
388    exc_8_128_table, /*shape_cb*/
389    7,               /*shape_bits*/
390    0
391    );
392 };
393
394 /* Split-VQ innovation for low-band wideband */
395 static const split_cb_params * split_cb_sb (void)
396 {
397   return speex_split_cb_params_new (
398    5,               /*subvect_size*/
399    8,              /*nb_subvect*/
400    exc_5_256_table,    /*shape_cb*/
401    8,               /*shape_bits*/
402    0
403    );
404 };
405
406 /* Split-VQ innovation for high-band wideband */
407 static const split_cb_params * split_cb_high (void)
408 {
409   return speex_split_cb_params_new (
410    8,               /*subvect_size*/
411    5,               /*nb_subvect*/
412    hexc_table,       /*shape_cb*/
413    7,               /*shape_bits*/
414    1
415    );
416 };
417
418
419 /* Split-VQ innovation for high-band wideband */
420 static const split_cb_params * split_cb_high_lbr (void)
421 {
422   return speex_split_cb_params_new (
423    10,               /*subvect_size*/
424    4,               /*nb_subvect*/
425    hexc_10_32_table,       /*shape_cb*/
426    5,               /*shape_bits*/
427    0
428    );
429 };
430
431 /* 2150 bps "vocoder-like" mode for comfort noise */
432 static const SpeexSubmode * nb_submode1 (void)
433 {
434   return speex_submode_new (
435    0,
436    1,
437    0,
438    0,
439    /* LSP quantization */
440    lsp_quant_lbr,
441    lsp_unquant_lbr,
442    /* No pitch quantization */
443    forced_pitch_quant,
444    forced_pitch_unquant,
445    NULL,
446    /* No innovation quantization (noise only) */
447    noise_codebook_quant,
448    noise_codebook_unquant,
449    NULL,
450 #ifdef FIXED_POINT
451    22938, 22938, 0, -1,
452 #else
453    .7, .7, 0, -1,
454 #endif
455    43
456    );
457 };
458
459 /* 3.95 kbps very low bit-rate mode */
460 static const SpeexSubmode * nb_submode8 (void)
461 {
462   const split_cb_params * params;
463
464   params = split_cb_nb_ulbr();
465   if (params == NULL) return NULL;
466
467   return speex_submode_new (
468    0,
469    1,
470    0,
471    0,
472    /*LSP quantization*/
473    lsp_quant_lbr,
474    lsp_unquant_lbr,
475    /*No pitch quantization*/
476    forced_pitch_quant,
477    forced_pitch_unquant,
478    NULL,
479    /*Innovation quantization*/
480    split_cb_search_shape_sign,
481    split_cb_shape_sign_unquant,
482    params,
483 #ifdef FIXED_POINT
484    22938, 16384, 11796, 21299,
485 #else
486    0.7, 0.5, .36, .65,
487 #endif
488    79
489    );
490 };
491
492 /* 5.95 kbps very low bit-rate mode */
493 static const SpeexSubmode * nb_submode2 (void)
494 {
495   return speex_submode_new (
496    0,
497    0,
498    0,
499    0,
500    /*LSP quantization*/
501    lsp_quant_lbr,
502    lsp_unquant_lbr,
503    /*No pitch quantization*/
504    pitch_search_3tap,
505    pitch_unquant_3tap,
506    &ltp_params_vlbr,
507    /*Innovation quantization*/
508    split_cb_search_shape_sign,
509    split_cb_shape_sign_unquant,
510    split_cb_nb_vlbr(),
511 #ifdef FIXED_POINT
512    22938, 16384, 11796, 18022,
513 #else
514    0.7, 0.5, .36, .55,
515 #endif
516    119
517    );
518 };
519
520 /* 8 kbps low bit-rate mode */
521 static const SpeexSubmode * nb_submode3 (void)
522 {
523   return speex_submode_new (
524    -1,
525    0,
526    1,
527    0,
528    /*LSP quantization*/
529    lsp_quant_lbr,
530    lsp_unquant_lbr,
531    /*Pitch quantization*/
532    pitch_search_3tap,
533    pitch_unquant_3tap,
534    ltp_params_lbr(),
535    /*Innovation quantization*/
536    split_cb_search_shape_sign,
537    split_cb_shape_sign_unquant,
538    split_cb_nb_lbr(),
539 #ifdef FIXED_POINT
540    22938, 18022, 9830, 14746,
541 #else
542    0.7, 0.55, .30, .45,
543 #endif
544    160
545    );
546 };
547
548 /* 11 kbps medium bit-rate mode */
549 static const SpeexSubmode * nb_submode4 (void)
550 {
551   return speex_submode_new (
552    -1,
553    0,
554    1,
555    0,
556    /*LSP quantization*/
557    lsp_quant_lbr,
558    lsp_unquant_lbr,
559    /*Pitch quantization*/
560    pitch_search_3tap,
561    pitch_unquant_3tap,
562    ltp_params_med(),
563    /*Innovation quantization*/
564    split_cb_search_shape_sign,
565    split_cb_shape_sign_unquant,
566    split_cb_nb_med(),
567 #ifdef FIXED_POINT
568    22938, 20644, 5243, 11469,
569 #else
570    0.7, 0.63, .16, .35,
571 #endif
572    220
573    );
574 };
575
576 /* 15 kbps high bit-rate mode */
577 static const SpeexSubmode * nb_submode5 (void)
578 {
579   return speex_submode_new (
580    -1,
581    0,
582    3,
583    0,
584    /*LSP quantization*/
585    lsp_quant_nb,
586    lsp_unquant_nb,
587    /*Pitch quantization*/
588    pitch_search_3tap,
589    pitch_unquant_3tap,
590    ltp_params_nb(),
591    /*Innovation quantization*/
592    split_cb_search_shape_sign,
593    split_cb_shape_sign_unquant,
594    split_cb_nb(),
595 #ifdef FIXED_POINT
596    22938, 21299, 3932, 8192,
597 #else
598    0.7, 0.65, .12, .25,
599 #endif
600    300
601    );
602 };
603
604 /* 18.2 high bit-rate mode */
605 static const SpeexSubmode * nb_submode6 (void)
606 {
607   return speex_submode_new (
608    -1,
609    0,
610    3,
611    0,
612    /*LSP quantization*/
613    lsp_quant_nb,
614    lsp_unquant_nb,
615    /*Pitch quantization*/
616    pitch_search_3tap,
617    pitch_unquant_3tap,
618    ltp_params_nb(),
619    /*Innovation quantization*/
620    split_cb_search_shape_sign,
621    split_cb_shape_sign_unquant,
622    split_cb_sb(),
623 #ifdef FIXED_POINT
624    22282, 21299, 2294, 3277,
625 #else
626    0.68, 0.65, .07, .1,
627 #endif
628    364
629    );
630 };
631
632 /* 24.6 kbps high bit-rate mode */
633 static const SpeexSubmode * nb_submode7 (void)
634 {
635   return speex_submode_new (
636    -1,
637    0,
638    3,
639    1,
640    /*LSP quantization*/
641    lsp_quant_nb,
642    lsp_unquant_nb,
643    /*Pitch quantization*/
644    pitch_search_3tap,
645    pitch_unquant_3tap,
646    ltp_params_nb(),
647    /*Innovation quantization*/
648    split_cb_search_shape_sign,
649    split_cb_shape_sign_unquant,
650    split_cb_nb(),
651 #ifdef FIXED_POINT
652    21299, 21299, 0, -1,
653 #else
654    0.65, 0.65, .0, -1,
655 #endif
656    492
657    );
658 };
659
660
661 /* Default mode for narrowband */
662 static const SpeexNBMode * nb_mode (void)
663 {
664   const SpeexSubmode ** submodes;
665   int quality_map[11] = {1, 8, 2, 3, 3, 4, 4, 5, 5, 6, 7};
666   const SpeexNBMode * ret;
667   int i;
668
669   submodes = (const SpeexSubmode **)
670     speex_alloc (sizeof (SpeexSubmode *) * SB_SUBMODES);
671   if (submodes == NULL) return NULL;
672   memset (submodes, 0, sizeof (submodes));
673
674   if (!(submodes[1] = nb_submode1())) goto nb_1;
675   if (!(submodes[2] = nb_submode2())) goto nb_2;
676   if (!(submodes[3] = nb_submode3())) goto nb_3;
677   if (!(submodes[4] = nb_submode4())) goto nb_4;
678   if (!(submodes[5] = nb_submode5())) goto nb_5;
679   if (!(submodes[6] = nb_submode6())) goto nb_6;
680   if (!(submodes[7] = nb_submode7())) goto nb_7;
681   if (!(submodes[8] = nb_submode8())) goto nb_8;
682
683   ret = nb_mode_new (
684    160,    /*frameSize*/
685    40,     /*subframeSize*/
686    10,     /*lpcSize*/
687    640,    /*bufSize*/
688    17,     /*pitchStart*/
689    144,    /*pitchEnd*/
690 #ifdef FIXED_POINT
691    29491, 19661, /* gamma1, gamma2 */
692 #else
693    0.9, 0.6, /* gamma1, gamma2 */
694 #endif
695    .012,   /*lag_factor*/
696    1.0002, /*lpc_floor*/
697 #ifdef EPIC_48K
698    0,
699 #endif
700    submodes,
701    5,
702    quality_map
703    );
704
705   if (ret == NULL) goto nb_8;
706  
707   /* If nb_mode_new() was successful, the references to submodes have been
708    * copied into ret->submodes[], and it's safe to free submodes.
709    */
710   speex_free (submodes);
711
712   return ret;
713
714   /* Cleanup on memory allocation errors */
715  nb_8: speex_submode_free (submodes[8]);
716  nb_7: speex_submode_free (submodes[7]);
717  nb_6: speex_submode_free (submodes[6]);
718  nb_5: speex_submode_free (submodes[5]);
719  nb_4: speex_submode_free (submodes[4]);
720  nb_3: speex_submode_free (submodes[3]);
721  nb_2: speex_submode_free (submodes[2]);
722  nb_1: speex_submode_free (submodes[1]);
723
724   speex_free (submodes);
725
726   return NULL;
727 };
728
729
730 /* Default mode for narrowband */
731 const SpeexMode * speex_nb_mode_new (void)
732 {
733   const SpeexNBMode * _nb_mode;
734
735   _nb_mode = nb_mode();
736   if (_nb_mode == NULL) return NULL;
737
738   return speex_mode_new (
739    _nb_mode,
740    nb_mode_query,
741    "narrowband",
742    0,
743    4,
744    &nb_encoder_init,
745    &nb_encoder_destroy,
746    &nb_encode,
747    &nb_decoder_init,
748    &nb_decoder_destroy,
749    &nb_decode,
750    &nb_encoder_ctl,
751    &nb_decoder_ctl
752    );
753 };
754
755 void speex_nb_mode_free (const SpeexMode * mode)
756 {
757   nb_mode_free ((SpeexNBMode *)mode->mode);
758   speex_free ((void *)mode);
759 }
760
761 /* Wideband part */
762
763 static const SpeexSubmode * wb_submode1 (void)
764 {
765   return speex_submode_new (
766    0,
767    0,
768    1,
769    0,
770    /*LSP quantization*/
771    lsp_quant_high,
772    lsp_unquant_high,
773    /*Pitch quantization*/
774    NULL,
775    NULL,
776    NULL,
777    /*No innovation quantization*/
778    NULL,
779    NULL,
780    NULL,
781 #ifdef FIXED_POINT
782    24576, 24576, 0, -1,
783 #else
784    .75, .75, .0, -1,
785 #endif
786    36
787    );
788 };
789
790
791 static const SpeexSubmode * wb_submode2 (void)
792 {
793   return speex_submode_new (
794    0,
795    0,
796    1,
797    0,
798    /*LSP quantization*/
799    lsp_quant_high,
800    lsp_unquant_high,
801    /*Pitch quantization*/
802    NULL,
803    NULL,
804    NULL,
805    /*Innovation quantization*/
806    split_cb_search_shape_sign,
807    split_cb_shape_sign_unquant,
808    split_cb_high_lbr(),
809 #ifdef FIXED_POINT
810    27853, 19661, 8192, -1,
811 #else
812    .85, .6, .25, -1,
813 #endif
814    112
815    );
816 };
817
818
819 static const SpeexSubmode * wb_submode3 (void)
820 {
821   return speex_submode_new (
822    0,
823    0,
824    1,
825    0,
826    /*LSP quantization*/
827    lsp_quant_high,
828    lsp_unquant_high,
829    /*Pitch quantization*/
830    NULL,
831    NULL,
832    NULL,
833    /*Innovation quantization*/
834    split_cb_search_shape_sign,
835    split_cb_shape_sign_unquant,
836    split_cb_high(),
837
838 #ifdef FIXED_POINT
839    24576, 22938, 1638, -1,
840 #else
841    .75, .7, .05, -1,
842 #endif
843    192
844    );
845 };
846
847 static const SpeexSubmode * wb_submode4 (void)
848 {
849   return speex_submode_new (
850    0,
851    0,
852    1,
853    1,
854    /*LSP quantization*/
855    lsp_quant_high,
856    lsp_unquant_high,
857    /*Pitch quantization*/
858    NULL,
859    NULL,
860    NULL,
861    /*Innovation quantization*/
862    split_cb_search_shape_sign,
863    split_cb_shape_sign_unquant,
864    split_cb_high(),
865 #ifdef FIXED_POINT
866    24576, 24576, 0, -1,
867 #else
868    .75, .75, .0, -1,
869 #endif
870    352
871    );
872 };
873
874
875 /* Split-band wideband CELP mode*/
876 static const SpeexSBMode * sb_wb_mode (void)
877 {
878   const SpeexMode * nb_mode;
879   const SpeexSubmode ** submodes;
880   int low_quality_map[11] = {1, 8, 2, 3, 4, 5, 5, 6, 6, 7, 7};
881   int quality_map[11] = {1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4};
882   SpeexSBMode * ret;
883
884   nb_mode = speex_nb_mode_new ();
885   if (nb_mode == NULL) return NULL;
886
887   submodes = (const SpeexSubmode **)
888     speex_alloc (sizeof (SpeexSubmode *) * SB_SUBMODES);
889   if (submodes == NULL) return NULL;
890   memset (submodes, 0, sizeof (submodes));
891
892   if (!(submodes[1] = wb_submode1())) goto sb_1;
893   if (!(submodes[2] = wb_submode2())) goto sb_2;
894   if (!(submodes[3] = wb_submode3())) goto sb_3;
895   if (!(submodes[4] = wb_submode4())) goto sb_4;
896
897   ret = sb_mode_new (
898    nb_mode,
899    160,    /*frameSize*/
900    40,     /*subframeSize*/
901    8,     /*lpcSize*/
902    640,    /*bufSize*/
903 #ifdef FIXED_POINT
904    29491, 19661, /* gamma1, gamma2 */
905 #else
906    0.9, 0.6, /* gamma1, gamma2 */
907 #endif
908    .001,   /*lag_factor*/
909    1.0001, /*lpc_floor*/
910    0.9,
911    submodes,
912    3,
913    low_quality_map,
914    quality_map,
915    vbr_hb_thresh,
916    5
917    );
918
919   if (ret == NULL) goto sb_4;
920
921   /* If sb_mode_new() was successful, the references to submodes have been
922    * copied into ret->submodes[], and it's safe to free submodes.
923    */
924   speex_free (submodes);
925
926   return ret;
927
928   /* Cleanup on memory allocation errors */
929  sb_4: speex_submode_free (submodes[4]);
930  sb_3: speex_submode_free (submodes[3]);
931  sb_2: speex_submode_free (submodes[2]);
932  sb_1: speex_submode_free (submodes[1]);
933
934   speex_free (submodes);
935
936   return NULL;
937 };
938
939 static void
940 sb_wb_mode_free (const SpeexSBMode * mode)
941 {
942   speex_nb_mode_free (mode->nb_mode);
943 }
944
945 const SpeexMode * speex_wb_mode_new (void)
946 {
947   const SpeexSBMode * sb_mode;
948
949   sb_mode = sb_wb_mode ();
950   if (sb_mode == NULL) return NULL;
951
952   return speex_mode_new (
953    (const SpeexNBMode *)sb_mode,
954    wb_mode_query,
955    "wideband (sub-band CELP)",
956    1,
957    4,
958    &sb_encoder_init,
959    &sb_encoder_destroy,
960    &sb_encode,
961    &sb_decoder_init,
962    &sb_decoder_destroy,
963    &sb_decode,
964    &sb_encoder_ctl,
965    &sb_decoder_ctl
966    );
967 };
968
969 void speex_wb_mode_free (const SpeexMode * mode)
970 {
971   sb_wb_mode_free (mode->mode);
972   speex_free ((void *)mode);
973 }
974
975
976 /* "Ultra-wideband" mode stuff */
977
978
979
980 /* Split-band "ultra-wideband" (32 kbps) CELP mode*/
981 static const SpeexSBMode * sb_uwb_mode (void)
982 {
983   const SpeexSBMode * nb_mode;
984   const SpeexSubmode ** submodes;
985   int low_quality_map[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
986   int quality_map[11] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
987   SpeexSBMode * ret;
988
989   nb_mode = sb_wb_mode ();
990   if (nb_mode == NULL) return NULL;
991
992   submodes = (const SpeexSubmode **)
993     speex_alloc (sizeof (SpeexSubmode *) * SB_SUBMODES);
994   if (submodes == NULL) return NULL;
995   memset (submodes, 0, sizeof (submodes));
996
997   if (!(submodes[1] = wb_submode1())) goto uwb_1;
998
999   ret = sb_mode_new (
1000    (const SpeexMode *)nb_mode,
1001    320,    /*frameSize*/
1002    80,     /*subframeSize*/
1003    8,     /*lpcSize*/
1004    1280,    /*bufSize*/
1005 #ifdef FIXED_POINT
1006    29491, 19661, /* gamma1, gamma2 */
1007 #else
1008    0.9, 0.6, /* gamma1, gamma2 */
1009 #endif
1010    .002,   /*lag_factor*/
1011    1.0001, /*lpc_floor*/
1012    0.7,
1013    submodes,
1014    1,
1015    low_quality_map,
1016    quality_map,
1017    vbr_uhb_thresh,
1018    2
1019    );
1020
1021   if (ret == NULL) goto uwb_1;
1022
1023   /* If sb_mode_new() was successful, the references to submodes have been
1024    * copied into ret->submodes[], and it's safe to free submodes.
1025    */
1026   speex_free (submodes);
1027
1028   return ret;
1029
1030  uwb_1: speex_submode_free (submodes[1]);
1031
1032   speex_free (submodes);
1033
1034   return NULL;
1035 };
1036
1037 void sb_uwb_mode_free (const SpeexSBMode * mode)
1038 {
1039   sb_wb_mode_free ((const SpeexSBMode *)mode->nb_mode);
1040   sb_mode_free (mode);
1041 }
1042
1043 const SpeexMode * speex_uwb_mode_new (void)
1044 {
1045   const SpeexSBMode * sb_mode;
1046
1047   sb_mode = sb_uwb_mode();
1048   if (sb_mode == NULL) return NULL;
1049
1050   return speex_mode_new (
1051    sb_mode,
1052    wb_mode_query,
1053    "ultra-wideband (sub-band CELP)",
1054    2,
1055    4,
1056    &sb_encoder_init,
1057    &sb_encoder_destroy,
1058    &sb_encode,
1059    &sb_decoder_init,
1060    &sb_decoder_destroy,
1061    &sb_decode,
1062    &sb_encoder_ctl,
1063    &sb_decoder_ctl
1064    );
1065 };
1066
1067 void speex_uwb_mode_free (const SpeexMode * mode)
1068 {
1069   sb_uwb_mode_free (mode->mode);
1070   speex_free ((void *)mode);
1071 }
1072
1073 const SpeexMode * speex_mode_new_byID (int id)
1074 {
1075   switch (id) {
1076   case 0: return speex_nb_mode_new(); break;
1077   case 1: return speex_wb_mode_new(); break;
1078   case 2: return speex_uwb_mode_new(); break;
1079   default: return NULL;
1080   }
1081 }
1082
1083 void speex_mode_free_byID (SpeexMode * mode, int id)
1084 {
1085   switch (id) {
1086   case 0: speex_nb_mode_free(mode); break;
1087   case 1: speex_wb_mode_free(mode); break;
1088   case 2:  speex_uwb_mode_free(mode); break;
1089   default: break;
1090   }
1091 }
1092
1093 /** XXX: This is just a dummy global mode, as used by nb_celp.c */
1094 const SpeexMode speex_wb_mode = {
1095    NULL,
1096    NULL,
1097    NULL,
1098    0,
1099    0,
1100    NULL,
1101    NULL,
1102    NULL,
1103    NULL,
1104    NULL,
1105    NULL,
1106    NULL,
1107    NULL
1108 };
1109
1110 int speex_mode_query(const SpeexMode *mode, int request, void *ptr)
1111 {
1112   if (mode == &speex_wb_mode && request == SPEEX_SUBMODE_BITS_PER_FRAME) {
1113     int * p = (int*)ptr;
1114
1115     switch (*p) {
1116     case 0: *p = SB_SUBMODE_BITS+1; break;
1117     case 1: *p = 36; break;
1118     case 2: *p = 112; break;
1119     case 3: *p = 192; break;
1120     case 4: *p = 352; break;
1121     default: *p = -1; break;
1122     }
1123
1124     return 0;
1125   }
1126   
1127   return mode->query(mode->mode, request, ptr);
1128 }