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