blob: e8665fad194f40689f5df3a6f37321d139e2b20b [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
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
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110034#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
Jean-Marc Valin65d57e62008-02-18 15:49:37 +110038#include "celt.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110039#include "modes.h"
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110040#include "rate.h"
Jean-Marc Valin81a82952008-02-17 22:41:29 +110041#include "os_support.h"
Jean-Marc Valinf7cec832008-04-18 17:29:56 +100042#include "stack_alloc.h"
Jean-Marc Valin4ce92052008-04-23 13:42:10 +100043#include "quant_bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110044
Jean-Marc Valine0c25452010-09-03 11:52:38 -040045static const celt_int16 eband5ms[] = {
Jean-Marc Valin8ccda882010-10-04 18:01:45 -040046 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 -040047};
48
Jean-Marc Valinc992a0d2010-11-19 14:06:10 -050049#if 0
Jean-Marc Valin78ea9fd2010-09-24 08:27:28 -040050
Jean-Marc Valine0c25452010-09-03 11:52:38 -040051#define BITALLOC_SIZE 9
52/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */
53static const unsigned char band_allocation[] = {
54/*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 */
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Jean-Marc Valin35095c62010-11-04 13:24:44 -040056 95, 90, 80, 75, 65, 60, 55, 50, 44, 40, 35, 30, 15, 1, 0, 0, 0, 0, 0, 0, 0,
57100, 95, 90, 88, 85, 82, 78, 74, 70, 65, 60, 54, 45, 35, 25, 15, 1, 0, 0, 0, 0,
Jean-Marc Valine0c25452010-09-03 11:52:38 -040058120,110,110,110,100, 96, 90, 88, 84, 76, 70, 65, 60, 45, 35, 25, 20, 1, 1, 0, 0,
59135,125,125,125,115,112,104,104,100, 96, 83, 78, 70, 55, 46, 36, 32, 28, 20, 8, 0,
Jean-Marc Valin8ccda882010-10-04 18:01:45 -040060170,165,157,155,149,145,143,138,138,138,129,124,108, 96, 88, 83, 72, 56, 44, 28, 2,
61192,192,160,160,160,160,160,160,160,160,150,140,120,110,100, 90, 80, 70, 60, 50, 20,
62224,224,192,192,192,192,192,192,192,160,160,160,160,160,160,160,160,120, 80, 64, 40,
63255,255,224,224,224,224,224,224,224,192,192,192,192,192,192,192,192,192,192,192,120,
Jean-Marc Valine0c25452010-09-03 11:52:38 -040064};
65
Jean-Marc Valin78ea9fd2010-09-24 08:27:28 -040066#else
Jean-Marc Valin94491652010-10-21 17:10:24 -040067
Jean-Marc Valin54d84c02010-11-19 11:45:37 -050068/* Alternate tuning (partially derived from Vorbis) */
Jean-Marc Valindd4bf632010-11-30 15:31:45 -050069#define BITALLOC_SIZE 11
Jean-Marc Valin94491652010-10-21 17:10:24 -040070/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */
71static const unsigned char band_allocation[] = {
Jean-Marc Valin54d84c02010-11-19 11:45:37 -050072/*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 -040073 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 -050074 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 -050075110,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 -050076118,110,103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15, 4, 0, 0, 0, 0,
77126,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 -050078134,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 -050079144,137,130,124,113,107,101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15, 1,
80152,145,138,132,123,117,111,105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20, 1,
81162,155,148,142,133,127,121,115,108,102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30, 1,
82172,165,158,152,143,137,131,125,118,112,106,100, 94, 87, 81, 75, 69, 63, 56, 45, 20,
Jean-Marc Valine6d7c082010-11-19 14:43:05 -050083200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,143,120,
Jean-Marc Valin94491652010-10-21 17:10:24 -040084};
Jean-Marc Valin78ea9fd2010-09-24 08:27:28 -040085#endif
86
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110087#ifdef STATIC_MODES
Jean-Marc Valin8f6d12b2010-11-06 12:11:18 -040088#ifdef FIXED_POINT
89#include "static_modes_fixed.c"
90#else
91#include "static_modes_float.c"
92#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110093#endif
94
Jean-Marc Valind748cd52008-03-01 07:27:03 +110095#ifndef M_PI
96#define M_PI 3.141592653
97#endif
98
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110099
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400100int celt_mode_info(const CELTMode *mode, int request, celt_int32 *value)
Jean-Marc Valinf997ad52008-01-31 16:47:16 +1100101{
102 switch (request)
103 {
Jean-Marc Valinf997ad52008-01-31 16:47:16 +1100104 case CELT_GET_LOOKAHEAD:
105 *value = mode->overlap;
106 break;
Jean-Marc Valin59093c02008-05-15 21:53:27 +1000107 case CELT_GET_BITSTREAM_VERSION:
108 *value = CELT_BITSTREAM_VERSION;
109 break;
Gregory Maxwelld9458cd2009-05-30 17:04:02 -0400110 case CELT_GET_SAMPLE_RATE:
111 *value = mode->Fs;
112 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100113 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -0400114 return CELT_UNIMPLEMENTED;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +1100115 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +1100116 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +1100117}
118
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100119#ifndef STATIC_MODES
120
Jean-Marc Valin17683eb2008-02-18 21:45:19 +1100121/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
122 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100123#define BARK_BANDS 25
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400124static const celt_int16 bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +1100125 0, 100, 200, 300, 400,
126 510, 630, 770, 920, 1080,
127 1270, 1480, 1720, 2000, 2320,
128 2700, 3150, 3700, 4400, 5300,
129 6400, 7700, 9500, 12000, 15500,
130 20000};
131
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400132static celt_int16 *compute_ebands(celt_int32 Fs, int frame_size, int res, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100133{
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400134 celt_int16 *eBands;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400135 int i, lin, low, high, nBark, offset=0;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100136
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -0400137 /* All modes that have 2.5 ms short blocks use the same definition */
138 if (Fs == 400*(celt_int32)frame_size)
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400139 {
140 *nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
Jean-Marc Valin8952c452010-07-16 21:48:44 -0400141 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+1));
142 for (i=0;i<*nbEBands+1;i++)
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400143 eBands[i] = eband5ms[i];
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400144 return eBands;
145 }
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400146 /* Find the number of critical bands supported by our sampling rate */
147 for (nBark=1;nBark<BARK_BANDS;nBark++)
148 if (bark_freq[nBark+1]*2 >= Fs)
149 break;
150
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100151 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400152 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400153 if (bark_freq[lin+1]-bark_freq[lin] >= res)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100154 break;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400155
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400156 low = (bark_freq[lin]+res/2)/res;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400157 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100158 *nbEBands = low+high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400159 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100160
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400161 if (eBands==NULL)
162 return NULL;
163
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100164 /* Linear spacing (min_width) */
165 for (i=0;i<low;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400166 eBands[i] = i;
Jean-Marc Valinbe8d1252010-04-21 18:09:07 -0400167 if (low>0)
168 offset = eBands[low-1]*res - bark_freq[lin-1];
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100169 /* Spacing follows critical bands */
170 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400171 {
172 int target = bark_freq[lin+i];
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400173 eBands[i+low] = (target+(offset+res)/2)/res;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400174 offset = eBands[i+low]*res - target;
175 }
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100176 /* Enforce the minimum spacing at the boundary */
177 for (i=0;i<*nbEBands;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400178 if (eBands[i] < i)
179 eBands[i] = i;
180 eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res;
Jean-Marc Valin8952c452010-07-16 21:48:44 -0400181 if (eBands[*nbEBands] > frame_size)
182 eBands[*nbEBands] = frame_size;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400183 for (i=1;i<*nbEBands-1;i++)
184 {
185 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
186 {
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400187 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400188 }
189 }
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400190 /*for (i=0;i<=*nbEBands+1;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400191 printf ("%d ", eBands[i]);
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400192 printf ("\n");
193 exit(1);*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100194 /* FIXME: Remove last band if too small */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100195 return eBands;
196}
197
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400198static void compute_allocation_table(CELTMode *mode, int res)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100199{
Jean-Marc Valin2f6c5fe2010-06-28 17:22:37 -0400200 int i, j;
Jean-Marc Valin01b54b92010-06-03 23:29:35 -0400201 unsigned char *allocVectors;
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400202 int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400203
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400204 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valin01b54b92010-06-03 23:29:35 -0400205 allocVectors = celt_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands));
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400206 if (allocVectors==NULL)
207 return;
208
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400209 /* Check for standard mode */
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400210 if (mode->Fs == 400*(celt_int32)mode->shortMdctSize && mode->Fs >= 40000)
211 {
212 for (i=0;i<BITALLOC_SIZE*mode->nbEBands;i++)
Jean-Marc Valinffe50612010-06-04 00:13:19 -0400213 allocVectors[i] = band_allocation[i];
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400214 mode->allocVectors = allocVectors;
215 return;
216 }
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400217 /* If not the standard mode, interpolate */
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400218 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100219 for (i=0;i<BITALLOC_SIZE;i++)
220 {
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500221 for (j=0;j<mode->nbEBands;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100222 {
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500223 int k;
224 for (k=0;k<maxBands;k++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100225 {
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500226 if (400*(celt_int32)eband5ms[k] > mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize)
227 break;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400228 }
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500229 if (k>mode->nbEBands-1)
230 allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1];
231 else {
232 celt_int32 a0, a1;
233 a1 = mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize - 400*(celt_int32)eband5ms[k-1];
234 a0 = 400*(celt_int32)eband5ms[k] - mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize;
235 allocVectors[i*mode->nbEBands+j] = (a0*band_allocation[i*maxBands+k-1]
236 + a1*band_allocation[i*maxBands+k])/(a0+a1);
237 }
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400238 }
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100239 }
Jean-Marc Valin1bfa18c2010-12-01 16:11:38 -0500240
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400241 /*printf ("\n");
242 for (i=0;i<BITALLOC_SIZE;i++)
Jean-Marc Valinbb8fa1f2010-06-03 00:33:42 -0400243 {
244 for (j=0;j<mode->nbEBands;j++)
245 printf ("%d ", allocVectors[i*mode->nbEBands+j]);
246 printf ("\n");
247 }
248 exit(0);*/
249
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400250 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000251}
252
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400253#endif /* STATIC_MODES */
254
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400255CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100256{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000257 int i;
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400258#ifdef STATIC_MODES
259 for (i=0;i<TOTAL_MODES;i++)
260 {
261 if (Fs == static_mode_list[i]->Fs &&
262 frame_size == static_mode_list[i]->shortMdctSize*static_mode_list[i]->nbShortMdcts)
263 {
264 return (CELTMode*)static_mode_list[i];
265 }
266 }
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400267 if (error)
268 *error = CELT_BAD_ARG;
269 return NULL;
270#else
271 int res;
272 CELTMode *mode=NULL;
273 celt_word16 *window;
274 celt_int16 *logN;
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400275 int LM;
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000276#ifdef STDIN_TUNING
277 scanf("%d ", &MIN_BINS);
278 scanf("%d ", &BITALLOC_SIZE);
279 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
280 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
281 {
282 scanf("%d ", band_allocation+i);
283 }
284#endif
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000285 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400286#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
287 if (global_stack==NULL)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400288 goto failure;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400289#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100290
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100291 /* The good thing here is that permutation of the arguments will automatically be invalid */
292
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400293 if (Fs < 8000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100294 {
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100295 if (error)
296 *error = CELT_BAD_ARG;
297 return NULL;
298 }
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400299 if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100300 {
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100301 if (error)
302 *error = CELT_BAD_ARG;
303 return NULL;
304 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100305
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100306 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400307 if (mode==NULL)
308 goto failure;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100309 mode->Fs = Fs;
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400310
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400311 /* Pre/de-emphasis depends on sampling rate. The "standard" pre-emphasis
312 is defined as A(z) = 1 - 0.85*z^-1 at 48 kHz. Other rates should
313 approximate that. */
314 if(Fs < 12000) /* 8 kHz */
315 {
316 mode->preemph[0] = QCONST16(.35f, 15);
317 mode->preemph[1] = -QCONST16(.18f, 15);
318 mode->preemph[2] = QCONST16(.272f, SIG_SHIFT);
319 mode->preemph[3] = QCONST16(3.6765f, 13);
320 } else if(Fs < 24000) /* 16 kHz */
321 {
322 mode->preemph[0] = QCONST16(.6f, 15);
323 mode->preemph[1] = -QCONST16(.18f, 15);
324 mode->preemph[2] = QCONST16(.4425f, SIG_SHIFT);
325 mode->preemph[3] = QCONST16(2.259887f, 13);
326 } else if(Fs < 40000) /* 32 kHz */
327 {
328 mode->preemph[0] = QCONST16(.78f, 15);
329 mode->preemph[1] = -QCONST16(.1f, 15);
330 mode->preemph[2] = QCONST16(.75f, SIG_SHIFT);
331 mode->preemph[3] = QCONST16(1.33333333f, 13);
332 } else /* 48 kHz */
333 {
334 mode->preemph[0] = QCONST16(.85f, 15);
335 mode->preemph[1] = QCONST16(.0f, 15);
336 mode->preemph[2] = QCONST16(1.f, SIG_SHIFT);
337 mode->preemph[3] = QCONST16(1.f, 13);
338 }
339
Jean-Marc Valina2546bb2010-07-16 12:00:00 -0400340 if ((celt_int32)frame_size*75 >= Fs && (frame_size%16)==0)
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400341 {
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400342 LM = 3;
Jean-Marc Valina2546bb2010-07-16 12:00:00 -0400343 } else if ((celt_int32)frame_size*150 >= Fs && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000344 {
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400345 LM = 2;
Jean-Marc Valina2546bb2010-07-16 12:00:00 -0400346 } else if ((celt_int32)frame_size*300 >= Fs && (frame_size%4)==0)
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400347 {
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400348 LM = 1;
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400349 } else
350 {
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400351 LM = 0;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000352 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400353
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400354 mode->maxLM = LM;
355 mode->nbShortMdcts = 1<<LM;
Jean-Marc Valin60ff9992010-06-27 13:49:38 -0400356 mode->shortMdctSize = frame_size/mode->nbShortMdcts;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400357 res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
358
359 mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400360 if (mode->eBands==NULL)
361 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400362
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400363 mode->effEBands = mode->nbEBands;
364 while (mode->eBands[mode->effEBands] > mode->shortMdctSize)
365 mode->effEBands--;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400366
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400367 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000368 if (mode->nbShortMdcts > 1)
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400369 mode->overlap = (mode->shortMdctSize>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000370 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400371 mode->overlap = (frame_size>>3)<<2;
372
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400373
374 compute_allocation_table(mode, res);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400375 if (mode->allocVectors==NULL)
376 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100377
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400378 window = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400379 if (window==NULL)
380 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100381
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100382#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100383 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100384 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 +1100385#else
386 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin8974f002010-03-20 00:41:39 -0400387 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 +1100388#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100389 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100390
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400391 logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
392 if (logN==NULL)
393 goto failure;
394
395 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valinaead79b2010-05-11 07:34:24 -0400396 logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400397 mode->logN = logN;
Jean-Marc Valin3ad8db42010-08-25 13:11:09 -0400398
399 compute_pulse_cache(mode, mode->maxLM);
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400400
Jean-Marc Valin732ea382010-08-25 13:52:27 -0400401 clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts, mode->maxLM);
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400402 if ((mode->mdct.trig==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400403#ifndef ENABLE_TI_DSPLIB55
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400404 || (mode->mdct.kfft==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400405#endif
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400406 )
407 goto failure;
408
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100409 if (error)
410 *error = CELT_OK;
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400411
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100412 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400413failure:
414 if (error)
415 *error = CELT_INVALID_MODE;
416 if (mode!=NULL)
417 celt_mode_destroy(mode);
418 return NULL;
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400419#endif /* !STATIC_MODES */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100420}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100421
Peter Kirk19f9dc92008-06-06 14:38:38 +0200422void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100423{
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400424#ifndef STATIC_MODES
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400425 if (mode == NULL)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400426 return;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400427
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400428 celt_free((celt_int16*)mode->eBands);
429 celt_free((celt_int16*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400430
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400431 celt_free((celt_word16*)mode->window);
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400432 celt_free((celt_int16*)mode->logN);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100433
Jean-Marc Valin732ea382010-08-25 13:52:27 -0400434 celt_free((celt_int16*)mode->cache.index);
435 celt_free((unsigned char*)mode->cache.bits);
Jean-Marc Valin72513f32010-07-07 21:26:38 -0400436 clt_mdct_clear(&mode->mdct);
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400437
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100438 celt_free((CELTMode *)mode);
Jean-Marc Valin40603b22010-08-25 23:02:49 -0400439#endif
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100440}