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