blob: 968bc2ff3b36c176f90e510d3e0e0382e3d871b0 [file] [log] [blame]
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04001/* Copyright (c) 2007-2008 CSIRO
2 Copyright (c) 2007-2009 Xiph.Org Foundation
3 Copyright (c) 2008 Gregory Maxwell
4 Written by Jean-Marc Valin and Gregory Maxwell */
Jean-Marc Valinecb36a32007-12-05 01:31:49 +11005/*
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
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110017 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
21 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110030#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
Jean-Marc Valin65d57e62008-02-18 15:49:37 +110034#include "celt.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110035#include "modes.h"
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110036#include "rate.h"
Jean-Marc Valin81a82952008-02-17 22:41:29 +110037#include "os_support.h"
Jean-Marc Valinf7cec832008-04-18 17:29:56 +100038#include "stack_alloc.h"
Jean-Marc Valin4ce92052008-04-23 13:42:10 +100039#include "quant_bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110040
Jean-Marc Valine0c25452010-09-03 11:52:38 -040041static const celt_int16 eband5ms[] = {
Jean-Marc Valin9cc56bf2011-02-01 22:03:26 -050042/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
Jean-Marc Valin8ccda882010-10-04 18:01:45 -040043 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100
Jean-Marc Valine0c25452010-09-03 11:52:38 -040044};
45
Jean-Marc Valin54d84c02010-11-19 11:45:37 -050046/* Alternate tuning (partially derived from Vorbis) */
Timothy B. Terriberryce6d0902011-02-01 17:41:12 -080047#define BITALLOC_SIZE 11
Jean-Marc Valin94491652010-10-21 17:10:24 -040048/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */
49static const unsigned char band_allocation[] = {
Jean-Marc Valin54d84c02010-11-19 11:45:37 -050050/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
Jean-Marc Valin94491652010-10-21 17:10:24 -040051 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Jean-Marc Valinc992a0d2010-11-19 14:06:10 -050052 90, 80, 75, 69, 63, 56, 49, 40, 34, 29, 20, 18, 10, 0, 0, 0, 0, 0, 0, 0, 0,
Jean-Marc Valin54d84c02010-11-19 11:45:37 -050053110,100, 90, 84, 78, 71, 65, 58, 51, 45, 39, 32, 26, 20, 12, 0, 0, 0, 0, 0, 0,
Jean-Marc Valinc992a0d2010-11-19 14:06:10 -050054118,110,103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15, 4, 0, 0, 0, 0,
55126,119,112,104, 95, 89, 83, 78, 72, 66, 60, 54, 47, 39, 32, 25, 17, 12, 1, 0, 0,
Jean-Marc Valin54d84c02010-11-19 11:45:37 -050056134,127,120,114,103, 97, 91, 85, 78, 72, 66, 60, 54, 47, 41, 35, 29, 23, 16, 10, 1,
Jean-Marc Valindd4bf632010-11-30 15:31:45 -050057144,137,130,124,113,107,101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15, 1,
58152,145,138,132,123,117,111,105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20, 1,
59162,155,148,142,133,127,121,115,108,102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30, 1,
60172,165,158,152,143,137,131,125,118,112,106,100, 94, 87, 81, 75, 69, 63, 56, 45, 20,
Timothy B. Terriberry89039a32011-01-30 22:27:13 -080061200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,129,104,
Jean-Marc Valin94491652010-10-21 17:10:24 -040062};
Jean-Marc Valin78ea9fd2010-09-24 08:27:28 -040063
Jean-Marc Valin665da0b2011-01-30 12:15:12 -050064#ifndef CUSTOM_MODES_ONLY
65 #ifdef FIXED_POINT
66 #include "static_modes_fixed.c"
67 #else
68 #include "static_modes_float.c"
69 #endif
70#endif /* CUSTOM_MODES_ONLY */
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110071
Jean-Marc Valind748cd52008-03-01 07:27:03 +110072#ifndef M_PI
73#define M_PI 3.141592653
74#endif
75
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110076
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -050077#ifdef CUSTOM_MODES
Jean-Marc Valin5588d522008-03-10 15:07:58 +110078
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110079/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
80 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +110081#define BARK_BANDS 25
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040082static const celt_int16 bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110083 0, 100, 200, 300, 400,
84 510, 630, 770, 920, 1080,
85 1270, 1480, 1720, 2000, 2320,
86 2700, 3150, 3700, 4400, 5300,
87 6400, 7700, 9500, 12000, 15500,
88 20000};
89
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -040090static celt_int16 *compute_ebands(celt_int32 Fs, int frame_size, int res, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +110091{
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040092 celt_int16 *eBands;
Timothy B. Terriberrycb8f3662011-02-01 12:32:34 -080093 int i, j, lin, low, high, nBark, offset=0;
Jean-Marc Valin81a82952008-02-17 22:41:29 +110094
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -040095 /* All modes that have 2.5 ms short blocks use the same definition */
96 if (Fs == 400*(celt_int32)frame_size)
Jean-Marc Valin20639c42010-05-19 16:10:12 -040097 {
98 *nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
Jean-Marc Valin8952c452010-07-16 21:48:44 -040099 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+1));
100 for (i=0;i<*nbEBands+1;i++)
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400101 eBands[i] = eband5ms[i];
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400102 return eBands;
103 }
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400104 /* Find the number of critical bands supported by our sampling rate */
105 for (nBark=1;nBark<BARK_BANDS;nBark++)
106 if (bark_freq[nBark+1]*2 >= Fs)
107 break;
108
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100109 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400110 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400111 if (bark_freq[lin+1]-bark_freq[lin] >= res)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100112 break;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400113
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400114 low = (bark_freq[lin]+res/2)/res;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400115 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100116 *nbEBands = low+high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400117 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100118
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400119 if (eBands==NULL)
120 return NULL;
121
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100122 /* Linear spacing (min_width) */
123 for (i=0;i<low;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400124 eBands[i] = i;
Jean-Marc Valinbe8d1252010-04-21 18:09:07 -0400125 if (low>0)
126 offset = eBands[low-1]*res - bark_freq[lin-1];
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100127 /* Spacing follows critical bands */
128 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400129 {
130 int target = bark_freq[lin+i];
Jean-Marc Valin44203902011-01-12 09:22:29 -0500131 /* Round to an even value */
132 eBands[i+low] = (target+offset/2+res)/(2*res)*2;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400133 offset = eBands[i+low]*res - target;
134 }
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100135 /* Enforce the minimum spacing at the boundary */
136 for (i=0;i<*nbEBands;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400137 if (eBands[i] < i)
138 eBands[i] = i;
Jean-Marc Valin44203902011-01-12 09:22:29 -0500139 /* Round to an even value */
140 eBands[*nbEBands] = (bark_freq[nBark]+res)/(2*res)*2;
Jean-Marc Valin8952c452010-07-16 21:48:44 -0400141 if (eBands[*nbEBands] > frame_size)
142 eBands[*nbEBands] = frame_size;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400143 for (i=1;i<*nbEBands-1;i++)
144 {
145 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
146 {
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400147 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400148 }
149 }
Timothy B. Terriberrycb8f3662011-02-01 12:32:34 -0800150 /* Remove any empty bands. */
151 for (i=j=0;i<*nbEBands;i++)
152 if(eBands[i+1]>eBands[j])
153 eBands[++j]=eBands[i+1];
154 *nbEBands=j;
155
Timothy B. Terriberry2799c292011-02-01 12:53:05 -0800156 for (i=1;i<*nbEBands;i++)
157 {
158 /* Every band must be smaller than the last band. */
159 celt_assert(eBands[i]-eBands[i-1]<=eBands[*nbEBands]-eBands[*nbEBands-1]);
160 /* Each band must be no larger than twice the size of the previous one. */
161 celt_assert(eBands[i+1]-eBands[i]<=2*(eBands[i]-eBands[i-1]));
162 }
163
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100164 return eBands;
165}
166
Jean-Marc Valine3e2c262011-01-26 13:09:53 -0500167static void compute_allocation_table(CELTMode *mode)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100168{
Jean-Marc Valin2f6c5fe2010-06-28 17:22:37 -0400169 int i, j;
Jean-Marc Valin01b54b92010-06-03 23:29:35 -0400170 unsigned char *allocVectors;
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400171 int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400172
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400173 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valin01b54b92010-06-03 23:29:35 -0400174 allocVectors = celt_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands));
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400175 if (allocVectors==NULL)
176 return;
177
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400178 /* Check for standard mode */
Jean-Marc Valin8e31ab32010-12-16 16:45:35 -0500179 if (mode->Fs == 400*(celt_int32)mode->shortMdctSize)
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400180 {
181 for (i=0;i<BITALLOC_SIZE*mode->nbEBands;i++)
Jean-Marc Valinffe50612010-06-04 00:13:19 -0400182 allocVectors[i] = band_allocation[i];
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400183 mode->allocVectors = allocVectors;
184 return;
185 }
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400186 /* If not the standard mode, interpolate */
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400187 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100188 for (i=0;i<BITALLOC_SIZE;i++)
189 {
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500190 for (j=0;j<mode->nbEBands;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100191 {
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500192 int k;
193 for (k=0;k<maxBands;k++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100194 {
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500195 if (400*(celt_int32)eband5ms[k] > mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize)
196 break;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400197 }
Jean-Marc Valinfa74ae22011-02-11 21:56:11 -0500198 if (k>maxBands-1)
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500199 allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1];
200 else {
201 celt_int32 a0, a1;
202 a1 = mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize - 400*(celt_int32)eband5ms[k-1];
203 a0 = 400*(celt_int32)eband5ms[k] - mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize;
204 allocVectors[i*mode->nbEBands+j] = (a0*band_allocation[i*maxBands+k-1]
205 + a1*band_allocation[i*maxBands+k])/(a0+a1);
206 }
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400207 }
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100208 }
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500209
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400210 /*printf ("\n");
211 for (i=0;i<BITALLOC_SIZE;i++)
Jean-Marc Valinbb8fa1f2010-06-03 00:33:42 -0400212 {
213 for (j=0;j<mode->nbEBands;j++)
214 printf ("%d ", allocVectors[i*mode->nbEBands+j]);
215 printf ("\n");
216 }
217 exit(0);*/
218
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400219 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000220}
221
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500222#endif /* CUSTOM_MODES */
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400223
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400224CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100225{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000226 int i;
Gregory Maxwell95becbe2011-02-03 21:06:43 -0500227#ifdef CUSTOM_MODES
Jean-Marc Valinff96b162011-03-21 11:32:50 -0400228 CELTMode *mode=NULL;
Gregory Maxwell95becbe2011-02-03 21:06:43 -0500229 int res;
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400230 celt_word16 *window;
231 celt_int16 *logN;
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400232 int LM;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000233 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400234#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
235 if (global_stack==NULL)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400236 goto failure;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400237#endif
Jean-Marc Valin7e983192011-02-01 18:00:29 -0500238#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100239
Jean-Marc Valin665da0b2011-01-30 12:15:12 -0500240#ifndef CUSTOM_MODES_ONLY
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500241 for (i=0;i<TOTAL_MODES;i++)
242 {
Jean-Marc Valinc97b2582011-01-28 23:07:32 -0500243 int j;
244 for (j=0;j<4;j++)
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500245 {
Jean-Marc Valinc97b2582011-01-28 23:07:32 -0500246 if (Fs == static_mode_list[i]->Fs &&
247 (frame_size<<j) == static_mode_list[i]->shortMdctSize*static_mode_list[i]->nbShortMdcts)
248 {
249 if (error)
250 *error = CELT_OK;
251 return (CELTMode*)static_mode_list[i];
252 }
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500253 }
254 }
Jean-Marc Valin665da0b2011-01-30 12:15:12 -0500255#endif /* CUSTOM_MODES_ONLY */
256
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500257#ifndef CUSTOM_MODES
258 if (error)
259 *error = CELT_BAD_ARG;
260 return NULL;
261#else
262
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100263 /* The good thing here is that permutation of the arguments will automatically be invalid */
264
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400265 if (Fs < 8000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100266 {
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100267 if (error)
268 *error = CELT_BAD_ARG;
269 return NULL;
270 }
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400271 if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100272 {
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100273 if (error)
274 *error = CELT_BAD_ARG;
275 return NULL;
276 }
Timothy B. Terriberryaa6fec62011-02-01 15:36:59 -0800277 /* Frames of less than 1ms are not supported. */
278 if ((celt_int32)frame_size*1000 < Fs)
279 {
280 if (error)
Jean-Marc Valinef20e392011-03-18 15:34:11 -0400281 *error = CELT_BAD_ARG;
Timothy B. Terriberryaa6fec62011-02-01 15:36:59 -0800282 return NULL;
283 }
284
285 if ((celt_int32)frame_size*75 >= Fs && (frame_size%16)==0)
286 {
287 LM = 3;
288 } else if ((celt_int32)frame_size*150 >= Fs && (frame_size%8)==0)
289 {
290 LM = 2;
291 } else if ((celt_int32)frame_size*300 >= Fs && (frame_size%4)==0)
292 {
293 LM = 1;
Timothy B. Terriberrycf5d3a82011-02-02 11:42:33 -0800294 } else
Timothy B. Terriberryaa6fec62011-02-01 15:36:59 -0800295 {
296 LM = 0;
297 }
Timothy B. Terriberrycf5d3a82011-02-02 11:42:33 -0800298
Timothy B. Terriberryaa6fec62011-02-01 15:36:59 -0800299 /* Shorts longer than 3.3ms are not supported. */
Timothy B. Terriberrycf5d3a82011-02-02 11:42:33 -0800300 if ((celt_int32)(frame_size>>LM)*300 > Fs)
Timothy B. Terriberryaa6fec62011-02-01 15:36:59 -0800301 {
302 if (error)
Jean-Marc Valinef20e392011-03-18 15:34:11 -0400303 *error = CELT_BAD_ARG;
Timothy B. Terriberryaa6fec62011-02-01 15:36:59 -0800304 return NULL;
305 }
306
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100307 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400308 if (mode==NULL)
309 goto failure;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100310 mode->Fs = Fs;
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400311
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400312 /* Pre/de-emphasis depends on sampling rate. The "standard" pre-emphasis
313 is defined as A(z) = 1 - 0.85*z^-1 at 48 kHz. Other rates should
314 approximate that. */
315 if(Fs < 12000) /* 8 kHz */
316 {
Jean-Marc Valin49f76802011-01-27 17:01:59 -0500317 mode->preemph[0] = QCONST16(0.3500061035f, 15);
318 mode->preemph[1] = -QCONST16(0.1799926758f, 15);
Jean-Marc Valin09213de2011-01-27 21:43:24 -0500319 mode->preemph[2] = QCONST16(0.2719968125f, SIG_SHIFT); /* exact 1/preemph[3] */
Jean-Marc Valin49f76802011-01-27 17:01:59 -0500320 mode->preemph[3] = QCONST16(3.6765136719f, 13);
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400321 } else if(Fs < 24000) /* 16 kHz */
322 {
Jean-Marc Valin49f76802011-01-27 17:01:59 -0500323 mode->preemph[0] = QCONST16(0.6000061035f, 15);
324 mode->preemph[1] = -QCONST16(0.1799926758f, 15);
Jean-Marc Valin09213de2011-01-27 21:43:24 -0500325 mode->preemph[2] = QCONST16(0.4424998650f, SIG_SHIFT); /* exact 1/preemph[3] */
326 mode->preemph[3] = QCONST16(2.2598876953f, 13);
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400327 } else if(Fs < 40000) /* 32 kHz */
328 {
Jean-Marc Valin49f76802011-01-27 17:01:59 -0500329 mode->preemph[0] = QCONST16(0.7799987793f, 15);
330 mode->preemph[1] = -QCONST16(0.1000061035f, 15);
Jean-Marc Valin09213de2011-01-27 21:43:24 -0500331 mode->preemph[2] = QCONST16(0.7499771125f, SIG_SHIFT); /* exact 1/preemph[3] */
Jean-Marc Valin49f76802011-01-27 17:01:59 -0500332 mode->preemph[3] = QCONST16(1.3333740234f, 13);
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400333 } else /* 48 kHz */
334 {
Jean-Marc Valin49f76802011-01-27 17:01:59 -0500335 mode->preemph[0] = QCONST16(0.8500061035f, 15);
336 mode->preemph[1] = QCONST16(0.0f, 15);
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400337 mode->preemph[2] = QCONST16(1.f, SIG_SHIFT);
338 mode->preemph[3] = QCONST16(1.f, 13);
339 }
340
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400341 mode->maxLM = LM;
342 mode->nbShortMdcts = 1<<LM;
Jean-Marc Valin60ff9992010-06-27 13:49:38 -0400343 mode->shortMdctSize = frame_size/mode->nbShortMdcts;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400344 res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
345
346 mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400347 if (mode->eBands==NULL)
348 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400349
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400350 mode->effEBands = mode->nbEBands;
351 while (mode->eBands[mode->effEBands] > mode->shortMdctSize)
352 mode->effEBands--;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400353
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400354 /* Overlap must be divisible by 4 */
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -0500355 mode->overlap = ((mode->shortMdctSize>>2)<<2);
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400356
Jean-Marc Valine3e2c262011-01-26 13:09:53 -0500357 compute_allocation_table(mode);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400358 if (mode->allocVectors==NULL)
359 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100360
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400361 window = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400362 if (window==NULL)
363 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100364
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100365#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100366 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100367 window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100368#else
369 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin8974f002010-03-20 00:41:39 -0400370 window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap))));
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100371#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100372 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100373
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400374 logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
375 if (logN==NULL)
376 goto failure;
377
378 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valinaead79b2010-05-11 07:34:24 -0400379 logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400380 mode->logN = logN;
Jean-Marc Valin3ad8db42010-08-25 13:11:09 -0400381
382 compute_pulse_cache(mode, mode->maxLM);
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400383
Jean-Marc Valin732ea382010-08-25 13:52:27 -0400384 clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts, mode->maxLM);
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400385 if ((mode->mdct.trig==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400386#ifndef ENABLE_TI_DSPLIB55
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400387 || (mode->mdct.kfft==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400388#endif
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400389 )
390 goto failure;
391
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100392 if (error)
393 *error = CELT_OK;
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400394
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100395 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400396failure:
397 if (error)
Jean-Marc Valinef20e392011-03-18 15:34:11 -0400398 *error = CELT_ALLOC_FAIL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400399 if (mode!=NULL)
400 celt_mode_destroy(mode);
401 return NULL;
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500402#endif /* !CUSTOM_MODES */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100403}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100404
Peter Kirk19f9dc92008-06-06 14:38:38 +0200405void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100406{
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500407#ifdef CUSTOM_MODES
408 int i;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400409 if (mode == NULL)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400410 return;
Jean-Marc Valin665da0b2011-01-30 12:15:12 -0500411#ifndef CUSTOM_MODES_ONLY
Jean-Marc Valin5ad35bf2011-01-28 22:42:09 -0500412 for (i=0;i<TOTAL_MODES;i++)
413 {
414 if (mode == static_mode_list[i])
415 {
416 return;
417 }
418 }
Jean-Marc Valin665da0b2011-01-30 12:15:12 -0500419#endif /* CUSTOM_MODES_ONLY */
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400420 celt_free((celt_int16*)mode->eBands);
421 celt_free((celt_int16*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400422
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400423 celt_free((celt_word16*)mode->window);
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400424 celt_free((celt_int16*)mode->logN);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100425
Jean-Marc Valin732ea382010-08-25 13:52:27 -0400426 celt_free((celt_int16*)mode->cache.index);
427 celt_free((unsigned char*)mode->cache.bits);
Timothy B. Terriberryc5643072011-01-29 12:57:18 -0800428 celt_free((unsigned char*)mode->cache.caps);
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400429 clt_mdct_clear(&mode->mdct);
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400430
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100431 celt_free((CELTMode *)mode);
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400432#endif
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100433}