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