da22d74eb2552b4d8214413c9e5b078c952915c6
[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
668   submodes = (const SpeexSubmode **)
669     speex_alloc (sizeof (SpeexSubmode *) * SB_SUBMODES);
670   if (submodes == NULL) return NULL;
671   memset (submodes, 0, sizeof (submodes));
672
673   if (!(submodes[1] = nb_submode1())) goto nb_1;
674   if (!(submodes[2] = nb_submode2())) goto nb_2;
675   if (!(submodes[3] = nb_submode3())) goto nb_3;
676   if (!(submodes[4] = nb_submode4())) goto nb_4;
677   if (!(submodes[5] = nb_submode5())) goto nb_5;
678   if (!(submodes[6] = nb_submode6())) goto nb_6;
679   if (!(submodes[7] = nb_submode7())) goto nb_7;
680   if (!(submodes[8] = nb_submode8())) goto nb_8;
681
682   ret = nb_mode_new (
683    160,    /*frameSize*/
684    40,     /*subframeSize*/
685    10,     /*lpcSize*/
686    640,    /*bufSize*/
687    17,     /*pitchStart*/
688    144,    /*pitchEnd*/
689 #ifdef FIXED_POINT
690    29491, 19661, /* gamma1, gamma2 */
691 #else
692    0.9, 0.6, /* gamma1, gamma2 */
693 #endif
694    .012,   /*lag_factor*/
695    1.0002, /*lpc_floor*/
696 #ifdef EPIC_48K
697    0,
698 #endif
699    submodes,
700    5,
701    quality_map
702    );
703
704   if (ret == NULL) goto nb_8;
705  
706   /* If nb_mode_new() was successful, the references to submodes have been
707    * copied into ret->submodes[], and it's safe to free submodes.
708    */
709   speex_free (submodes);
710
711   return ret;
712
713   /* Cleanup on memory allocation errors */
714  nb_8: speex_submode_free (submodes[8]);
715  nb_7: speex_submode_free (submodes[7]);
716  nb_6: speex_submode_free (submodes[6]);
717  nb_5: speex_submode_free (submodes[5]);
718  nb_4: speex_submode_free (submodes[4]);
719  nb_3: speex_submode_free (submodes[3]);
720  nb_2: speex_submode_free (submodes[2]);
721  nb_1: speex_submode_free (submodes[1]);
722
723   speex_free (submodes);
724
725   return NULL;
726 }
727
728
729 /* Default mode for narrowband */
730 const SpeexMode * speex_nb_mode_new (void)
731 {
732   const SpeexNBMode * _nb_mode;
733
734   _nb_mode = nb_mode();
735   if (_nb_mode == NULL) return NULL;
736
737   return speex_mode_new (
738    _nb_mode,
739    nb_mode_query,
740    "narrowband",
741    0,
742    4,
743    &nb_encoder_init,
744    &nb_encoder_destroy,
745    &nb_encode,
746    &nb_decoder_init,
747    &nb_decoder_destroy,
748    &nb_decode,
749    &nb_encoder_ctl,
750    &nb_decoder_ctl
751    );
752 }
753
754 void speex_nb_mode_free (const SpeexMode * mode)
755 {
756   nb_mode_free ((SpeexNBMode *)mode->mode);
757   speex_free ((void *)mode);
758 }
759
760 /* Wideband part */
761
762 static const SpeexSubmode * wb_submode1 (void)
763 {
764   return speex_submode_new (
765    0,
766    0,
767    1,
768    0,
769    /*LSP quantization*/
770    lsp_quant_high,
771    lsp_unquant_high,
772    /*Pitch quantization*/
773    NULL,
774    NULL,
775    NULL,
776    /*No innovation quantization*/
777    NULL,
778    NULL,
779    NULL,
780 #ifdef FIXED_POINT
781    24576, 24576, 0, -1,
782 #else
783    .75, .75, .0, -1,
784 #endif
785    36
786    );
787 }
788
789
790 static const SpeexSubmode * wb_submode2 (void)
791 {
792   return speex_submode_new (
793    0,
794    0,
795    1,
796    0,
797    /*LSP quantization*/
798    lsp_quant_high,
799    lsp_unquant_high,
800    /*Pitch quantization*/
801    NULL,
802    NULL,
803    NULL,
804    /*Innovation quantization*/
805    split_cb_search_shape_sign,
806    split_cb_shape_sign_unquant,
807    split_cb_high_lbr(),
808 #ifdef FIXED_POINT
809    27853, 19661, 8192, -1,
810 #else
811    .85, .6, .25, -1,
812 #endif
813    112
814    );
815 }
816
817
818 static const SpeexSubmode * wb_submode3 (void)
819 {
820   return speex_submode_new (
821    0,
822    0,
823    1,
824    0,
825    /*LSP quantization*/
826    lsp_quant_high,
827    lsp_unquant_high,
828    /*Pitch quantization*/
829    NULL,
830    NULL,
831    NULL,
832    /*Innovation quantization*/
833    split_cb_search_shape_sign,
834    split_cb_shape_sign_unquant,
835    split_cb_high(),
836
837 #ifdef FIXED_POINT
838    24576, 22938, 1638, -1,
839 #else
840    .75, .7, .05, -1,
841 #endif
842    192
843    );
844 }
845
846 static const SpeexSubmode * wb_submode4 (void)
847 {
848   return speex_submode_new (
849    0,
850    0,
851    1,
852    1,
853    /*LSP quantization*/
854    lsp_quant_high,
855    lsp_unquant_high,
856    /*Pitch quantization*/
857    NULL,
858    NULL,
859    NULL,
860    /*Innovation quantization*/
861    split_cb_search_shape_sign,
862    split_cb_shape_sign_unquant,
863    split_cb_high(),
864 #ifdef FIXED_POINT
865    24576, 24576, 0, -1,
866 #else
867    .75, .75, .0, -1,
868 #endif
869    352
870    );
871 }
872
873
874 /* Split-band wideband CELP mode*/
875 static const SpeexSBMode * sb_wb_mode (void)
876 {
877   const SpeexMode * nb_mode;
878   const SpeexSubmode ** submodes;
879   int low_quality_map[11] = {1, 8, 2, 3, 4, 5, 5, 6, 6, 7, 7};
880   int quality_map[11] = {1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4};
881   SpeexSBMode * ret;
882
883   nb_mode = speex_nb_mode_new ();
884   if (nb_mode == NULL) return NULL;
885
886   submodes = (const SpeexSubmode **)
887     speex_alloc (sizeof (SpeexSubmode *) * SB_SUBMODES);
888   if (submodes == NULL) return NULL;
889   memset (submodes, 0, sizeof (submodes));
890
891   if (!(submodes[1] = wb_submode1())) goto sb_1;
892   if (!(submodes[2] = wb_submode2())) goto sb_2;
893   if (!(submodes[3] = wb_submode3())) goto sb_3;
894   if (!(submodes[4] = wb_submode4())) goto sb_4;
895
896   ret = sb_mode_new (
897    nb_mode,
898    160,    /*frameSize*/
899    40,     /*subframeSize*/
900    8,     /*lpcSize*/
901    640,    /*bufSize*/
902 #ifdef FIXED_POINT
903    29491, 19661, /* gamma1, gamma2 */
904 #else
905    0.9, 0.6, /* gamma1, gamma2 */
906 #endif
907    .001,   /*lag_factor*/
908    1.0001, /*lpc_floor*/
909    0.9,
910    submodes,
911    3,
912    low_quality_map,
913    quality_map,
914    vbr_hb_thresh,
915    5
916    );
917
918   if (ret == NULL) goto sb_4;
919
920   /* If sb_mode_new() was successful, the references to submodes have been
921    * copied into ret->submodes[], and it's safe to free submodes.
922    */
923   speex_free (submodes);
924
925   return ret;
926
927   /* Cleanup on memory allocation errors */
928  sb_4: speex_submode_free (submodes[4]);
929  sb_3: speex_submode_free (submodes[3]);
930  sb_2: speex_submode_free (submodes[2]);
931  sb_1: speex_submode_free (submodes[1]);
932
933   speex_free (submodes);
934
935   return NULL;
936 }
937
938 static void
939 sb_wb_mode_free (const SpeexSBMode * mode)
940 {
941   speex_nb_mode_free (mode->nb_mode);
942 }
943
944 const SpeexMode * speex_wb_mode_new (void)
945 {
946   const SpeexSBMode * sb_mode;
947
948   sb_mode = sb_wb_mode ();
949   if (sb_mode == NULL) return NULL;
950
951   return speex_mode_new (
952    (const SpeexNBMode *)sb_mode,
953    wb_mode_query,
954    "wideband (sub-band CELP)",
955    1,
956    4,
957    &sb_encoder_init,
958    &sb_encoder_destroy,
959    &sb_encode,
960    &sb_decoder_init,
961    &sb_decoder_destroy,
962    &sb_decode,
963    &sb_encoder_ctl,
964    &sb_decoder_ctl
965    );
966 }
967
968 void speex_wb_mode_free (const SpeexMode * mode)
969 {
970   sb_wb_mode_free (mode->mode);
971   speex_free ((void *)mode);
972 }
973
974
975 /* "Ultra-wideband" mode stuff */
976
977
978
979 /* Split-band "ultra-wideband" (32 kbps) CELP mode*/
980 static const SpeexSBMode * sb_uwb_mode (void)
981 {
982   const SpeexSBMode * nb_mode;
983   const SpeexSubmode ** submodes;
984   int low_quality_map[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
985   int quality_map[11] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
986   SpeexSBMode * ret;
987
988   nb_mode = sb_wb_mode ();
989   if (nb_mode == NULL) return NULL;
990
991   submodes = (const SpeexSubmode **)
992     speex_alloc (sizeof (SpeexSubmode *) * SB_SUBMODES);
993   if (submodes == NULL) return NULL;
994   memset (submodes, 0, sizeof (submodes));
995
996   if (!(submodes[1] = wb_submode1())) goto uwb_1;
997
998   ret = sb_mode_new (
999    (const SpeexMode *)nb_mode,
1000    320,    /*frameSize*/
1001    80,     /*subframeSize*/
1002    8,     /*lpcSize*/
1003    1280,    /*bufSize*/
1004 #ifdef FIXED_POINT
1005    29491, 19661, /* gamma1, gamma2 */
1006 #else
1007    0.9, 0.6, /* gamma1, gamma2 */
1008 #endif
1009    .002,   /*lag_factor*/
1010    1.0001, /*lpc_floor*/
1011    0.7,
1012    submodes,
1013    1,
1014    low_quality_map,
1015    quality_map,
1016    vbr_uhb_thresh,
1017    2
1018    );
1019
1020   if (ret == NULL) goto uwb_1;
1021
1022   /* If sb_mode_new() was successful, the references to submodes have been
1023    * copied into ret->submodes[], and it's safe to free submodes.
1024    */
1025   speex_free (submodes);
1026
1027   return ret;
1028
1029  uwb_1: speex_submode_free (submodes[1]);
1030
1031   speex_free (submodes);
1032
1033   return NULL;
1034 }
1035
1036 void sb_uwb_mode_free (const SpeexSBMode * mode)
1037 {
1038   sb_wb_mode_free ((const SpeexSBMode *)mode->nb_mode);
1039   sb_mode_free (mode);
1040 }
1041
1042 const SpeexMode * speex_uwb_mode_new (void)
1043 {
1044   const SpeexSBMode * sb_mode;
1045
1046   sb_mode = sb_uwb_mode();
1047   if (sb_mode == NULL) return NULL;
1048
1049   return speex_mode_new (
1050    sb_mode,
1051    wb_mode_query,
1052    "ultra-wideband (sub-band CELP)",
1053    2,
1054    4,
1055    &sb_encoder_init,
1056    &sb_encoder_destroy,
1057    &sb_encode,
1058    &sb_decoder_init,
1059    &sb_decoder_destroy,
1060    &sb_decode,
1061    &sb_encoder_ctl,
1062    &sb_decoder_ctl
1063    );
1064 }
1065
1066 void speex_uwb_mode_free (const SpeexMode * mode)
1067 {
1068   sb_uwb_mode_free (mode->mode);
1069   speex_free ((void *)mode);
1070 }
1071
1072 const SpeexMode * speex_mode_new_byID (int id)
1073 {
1074   switch (id) {
1075   case 0: return speex_nb_mode_new(); break;
1076   case 1: return speex_wb_mode_new(); break;
1077   case 2: return speex_uwb_mode_new(); break;
1078   default: return NULL;
1079   }
1080 }
1081
1082 void speex_mode_free_byID (SpeexMode * mode, int id)
1083 {
1084   switch (id) {
1085   case 0: speex_nb_mode_free(mode); break;
1086   case 1: speex_wb_mode_free(mode); break;
1087   case 2:  speex_uwb_mode_free(mode); break;
1088   default: break;
1089   }
1090 }
1091
1092 /** XXX: This is just a dummy global mode, as used by nb_celp.c */
1093 const SpeexMode speex_wb_mode = {
1094    NULL,
1095    NULL,
1096    NULL,
1097    0,
1098    0,
1099    NULL,
1100    NULL,
1101    NULL,
1102    NULL,
1103    NULL,
1104    NULL,
1105    NULL,
1106    NULL
1107 };
1108
1109 int speex_mode_query(const SpeexMode *mode, int request, void *ptr)
1110 {
1111   if (mode == &speex_wb_mode && request == SPEEX_SUBMODE_BITS_PER_FRAME) {
1112     int * p = (int*)ptr;
1113
1114     switch (*p) {
1115     case 0: *p = SB_SUBMODE_BITS+1; break;
1116     case 1: *p = 36; break;
1117     case 2: *p = 112; break;
1118     case 3: *p = 192; break;
1119     case 4: *p = 352; break;
1120     default: *p = -1; break;
1121     }
1122
1123     return 0;
1124   }
1125   
1126   return mode->query(mode->mode, request, ptr);
1127 }