blob: 6b128f9dd3bb9894d854d9043cd1b21a90de45ed [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 Valinf39e8692008-03-10 12:13:23 +110045#ifdef STATIC_MODES
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +100046#include "static_modes.c"
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110047#endif
48
Gregory Maxwelldc67fa92009-06-04 17:17:35 -040049#define MODEVALID 0xa110ca7e
50#define MODEPARTIAL 0x7eca10a1
51#define MODEFREED 0xb10cf8ee
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110052
Jean-Marc Valind748cd52008-03-01 07:27:03 +110053#ifndef M_PI
54#define M_PI 3.141592653
55#endif
56
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110057
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040058int celt_mode_info(const CELTMode *mode, int request, celt_int32 *value)
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110059{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -040060 if (check_mode(mode) != CELT_OK)
61 return CELT_INVALID_MODE;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110062 switch (request)
63 {
64 case CELT_GET_FRAME_SIZE:
65 *value = mode->mdctSize;
66 break;
67 case CELT_GET_LOOKAHEAD:
68 *value = mode->overlap;
69 break;
Jean-Marc Valin59093c02008-05-15 21:53:27 +100070 case CELT_GET_BITSTREAM_VERSION:
71 *value = CELT_BITSTREAM_VERSION;
72 break;
Gregory Maxwelld9458cd2009-05-30 17:04:02 -040073 case CELT_GET_SAMPLE_RATE:
74 *value = mode->Fs;
75 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110076 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040077 return CELT_UNIMPLEMENTED;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110078 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110079 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110080}
81
Jean-Marc Valin5588d522008-03-10 15:07:58 +110082#ifndef STATIC_MODES
83
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110084/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
85 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +110086#define BARK_BANDS 25
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040087static const celt_int16 bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110088 0, 100, 200, 300, 400,
89 510, 630, 770, 920, 1080,
90 1270, 1480, 1720, 2000, 2320,
91 2700, 3150, 3700, 4400, 5300,
92 6400, 7700, 9500, 12000, 15500,
93 20000};
94
Jean-Marc Valin75e9c862008-02-18 17:04:15 +110095/* This allocation table is per critical band. When creating a mode, the bits get added together
96 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100097
98#ifdef STDIN_TUNING
99int BITALLOC_SIZE;
100int *band_allocation;
101#else
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400102#define BITALLOC_SIZE 12
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100103static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Christopher Montgomery8e511a82009-07-03 02:10:17 -0400104 /* 0 100 200 300 400 510 630 770 920 1k 1.2 1.5 1.7 2k 2.3 2.7 3.1 3.7 4.4 5.3 6.4 7.7 9.5 12k 15k */
105 { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0*/
106 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*1*/
107 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 4, 5, 7, 7, 7, 5, 4, 0, 0, 0, 0, 0, 0, /*2*/
108 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 6, 8, 8, 8, 6, 5, 4, 0, 0, 0, 0, 0, /*3*/
109 3, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 6, 7, 9, 9, 9, 7, 6, 5, 5, 5, 0, 0, 0, /*4*/
110 3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 6, 7, 7, 9, 10, 10, 10, 9, 6, 5, 5, 5, 5, 1, 0, /*5*/
111 4, 3, 3, 4, 6, 7, 7, 7, 7, 7, 8, 9, 9, 9, 11, 10, 10, 9, 9, 8, 11, 10, 10, 1, 0, /*6*/
112 5, 5, 5, 6, 7, 7, 7, 7, 8, 8, 9, 10, 10, 12, 12, 11, 11, 17, 12, 15, 15, 20, 18, 10, 1, /*7*/
113 6, 7, 7, 7, 8, 8, 8, 8, 9, 10, 11, 12, 14, 17, 18, 21, 22, 27, 29, 39, 37, 38, 40, 35, 1, /*8*/
114 7, 7, 7, 8, 8, 8, 10, 10, 10, 13, 14, 18, 20, 24, 28, 32, 32, 35, 38, 38, 42, 50, 59, 54, 31, /*9*/
115 8, 8, 8, 8, 8, 9, 10, 12, 14, 20, 22, 25, 28, 30, 35, 42, 46, 50, 55, 60, 62, 62, 72, 82, 62, /*10*/
116 9, 9, 9, 10, 12, 13, 15, 18, 22, 30, 32, 35, 40, 45, 55, 62, 66, 70, 85, 90, 92, 92, 92,102, 92, /*11*/
Jean-Marc Valin9eba8232008-08-02 20:51:44 -0400117 };
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000118#endif
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100119
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400120static celt_int16 *compute_ebands(celt_int32 Fs, int frame_size, int res, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100121{
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400122 celt_int16 *eBands;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400123 int i, lin, low, high, nBark, offset=0;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100124
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400125 /* Find the number of critical bands supported by our sampling rate */
126 for (nBark=1;nBark<BARK_BANDS;nBark++)
127 if (bark_freq[nBark+1]*2 >= Fs)
128 break;
129
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100130 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400131 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400132 if (bark_freq[lin+1]-bark_freq[lin] >= res)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100133 break;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400134
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400135 low = (bark_freq[lin]+res/2)/res;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400136 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100137 *nbEBands = low+high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400138 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100139
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400140 if (eBands==NULL)
141 return NULL;
142
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100143 /* Linear spacing (min_width) */
144 for (i=0;i<low;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400145 eBands[i] = i;
Jean-Marc Valinbe8d1252010-04-21 18:09:07 -0400146 if (low>0)
147 offset = eBands[low-1]*res - bark_freq[lin-1];
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100148 /* Spacing follows critical bands */
149 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400150 {
151 int target = bark_freq[lin+i];
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400152 eBands[i+low] = (target+(offset+res)/2)/res;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400153 offset = eBands[i+low]*res - target;
154 }
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100155 /* Enforce the minimum spacing at the boundary */
156 for (i=0;i<*nbEBands;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400157 if (eBands[i] < i)
158 eBands[i] = i;
159 eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100160 eBands[*nbEBands+1] = frame_size;
161 if (eBands[*nbEBands] > eBands[*nbEBands+1])
162 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400163 for (i=1;i<*nbEBands-1;i++)
164 {
165 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
166 {
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400167 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400168 }
169 }
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400170 /*for (i=0;i<=*nbEBands+1;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400171 printf ("%d ", eBands[i]);
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400172 printf ("\n");
173 exit(1);*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100174 /* FIXME: Remove last band if too small */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100175 return eBands;
176}
177
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400178static void compute_allocation_table(CELTMode *mode, int res)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100179{
Gregory Maxwellec836da2009-05-04 14:55:40 -0400180 int i, j, nBark;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400181 celt_int16 *allocVectors;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400182
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400183 /* Find the number of critical bands supported by our sampling rate */
184 for (nBark=1;nBark<BARK_BANDS;nBark++)
185 if (bark_freq[nBark+1]*2 >= mode->Fs)
186 break;
187
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100188 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400189 allocVectors = celt_alloc(sizeof(celt_int16)*(BITALLOC_SIZE*mode->nbEBands));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400190 if (allocVectors==NULL)
191 return;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400192 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100193 for (i=0;i<BITALLOC_SIZE;i++)
194 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400195 celt_int32 current = 0;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400196 int eband = 0;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400197 for (j=0;j<nBark;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100198 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400199 int edge, low, high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400200 celt_int32 alloc;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400201
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400202 alloc = mode->shortMdctSize*band_allocation[i*BARK_BANDS+j];
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400203 low = bark_freq[j];
204 high = bark_freq[j+1];
205
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400206 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin3ff5e4c2010-04-14 18:02:09 -0400207 while (edge <= high && eband < mode->nbEBands)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100208 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400209 celt_int32 num;
210 int den, bits;
211 num = alloc * (edge-low);
212 den = high-low;
213 /* Divide with rounding */
214 bits = (2*num+den)/(2*den);
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400215 allocVectors[i*mode->nbEBands+eband] = (current+bits+128)>>(8-BITRES);
216 /* Remove one bit from every band -- FIXME: this is just a temporary hack*/
217 allocVectors[i*mode->nbEBands+eband] -= 1<<BITRES;
218 if (allocVectors[i*mode->nbEBands+eband]<0)
219 allocVectors[i*mode->nbEBands+eband]=0;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400220 /* Remove the part of the band we just allocated */
221 low = edge;
222 alloc -= bits;
223
224 /* Move to next eband */
225 current = 0;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100226 eband++;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400227 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400228 }
229 current += alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100230 }
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400231 if (eband < mode->nbEBands)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400232 {
233 allocVectors[i*mode->nbEBands+eband] = (current+128)>>(8-BITRES);
234 /* Same hack as above FIXME: again */
235 allocVectors[i*mode->nbEBands+eband] -= 1<<BITRES;
236 if (allocVectors[i*mode->nbEBands+eband]<0)
237 allocVectors[i*mode->nbEBands+eband]=0;
238 }
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100239 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400240 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000241}
242
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400243#endif /* STATIC_MODES */
244
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400245CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100246{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000247 int i;
248#ifdef STDIN_TUNING
249 scanf("%d ", &MIN_BINS);
250 scanf("%d ", &BITALLOC_SIZE);
251 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
252 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
253 {
254 scanf("%d ", band_allocation+i);
255 }
256#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100257#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100258 const CELTMode *m = NULL;
259 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000260 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400261#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
262 if (global_stack==NULL)
263 {
264 celt_free(global_stack);
265 goto failure;
266 }
267#endif
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100268 for (i=0;i<TOTAL_MODES;i++)
269 {
270 if (Fs == static_mode_list[i]->Fs &&
Jean-Marc Valin60d08372008-10-03 07:30:08 -0400271 frame_size == static_mode_list[i]->mdctSize)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100272 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100273 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100274 break;
275 }
276 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100277 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100278 {
279 celt_warning("Mode not included as part of the static modes");
280 if (error)
281 *error = CELT_BAD_ARG;
282 return NULL;
283 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100284 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400285 if (mode==NULL)
286 goto failure;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100287 CELT_COPY(mode, m, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400288 mode->marker_start = MODEPARTIAL;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100289#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100290 int res;
Gregory Maxwell84966952009-06-30 01:06:04 -0400291 CELTMode *mode=NULL;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400292 celt_word16 *window;
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400293 celt_int16 *logN;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000294 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400295#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
296 if (global_stack==NULL)
297 {
298 celt_free(global_stack);
299 goto failure;
300 }
301#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100302
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100303 /* The good thing here is that permutation of the arguments will automatically be invalid */
304
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500305 if (Fs < 32000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100306 {
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500307 celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100308 if (error)
309 *error = CELT_BAD_ARG;
310 return NULL;
311 }
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400312 if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100313 {
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400314 celt_warning("Only even frame sizes from 64 to 1024 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100315 if (error)
316 *error = CELT_BAD_ARG;
317 return NULL;
318 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100319
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100320 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400321 if (mode==NULL)
322 goto failure;
323 mode->marker_start = MODEPARTIAL;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100324 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100325 mode->mdctSize = frame_size;
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100326 mode->ePredCoef = QCONST16(.8f,15);
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400327
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400328 if (frame_size > 640 && (frame_size%16)==0)
329 {
330 mode->nbShortMdcts = 8;
331 } else if (frame_size > 384 && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000332 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400333 mode->nbShortMdcts = 4;
334 } else if (frame_size > 384 && (frame_size%10)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000335 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400336 mode->nbShortMdcts = 5;
337 } else if (frame_size > 256 && (frame_size%6)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000338 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400339 mode->nbShortMdcts = 3;
340 } else if (frame_size > 256 && (frame_size%8)==0)
341 {
342 mode->nbShortMdcts = 4;
343 } else if (frame_size > 64 && (frame_size%4)==0)
344 {
345 mode->nbShortMdcts = 2;
346 } else if (frame_size > 128 && (frame_size%6)==0)
347 {
348 mode->nbShortMdcts = 3;
349 } else
350 {
351 mode->nbShortMdcts = 1;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000352 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400353
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400354 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
355 res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
356
357 mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400358 if (mode->eBands==NULL)
359 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400360
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400361 mode->pitchEnd = 4000*(celt_int32)frame_size/Fs;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400362
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400363 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000364 if (mode->nbShortMdcts > 1)
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400365 mode->overlap = ((frame_size/mode->nbShortMdcts)>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000366 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400367 mode->overlap = (frame_size>>3)<<2;
368
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400369
370 compute_allocation_table(mode, res);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400371 if (mode->allocVectors==NULL)
372 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100373
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400374 window = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400375 if (window==NULL)
376 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100377
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100378#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100379 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100380 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 +1100381#else
382 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin8974f002010-03-20 00:41:39 -0400383 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 +1100384#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100385 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100386
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400387 mode->bits = (const celt_int16 **)compute_alloc_cache(mode, 1, mode->nbShortMdcts);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400388 if (mode->bits==NULL)
389 goto failure;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +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 Valin65ee67a2010-04-26 07:08:44 -0400396 logN[i] = log2_frac(mode->nbShortMdcts*(mode->eBands[i+1]-mode->eBands[i]), BITRES);
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400397 mode->logN = logN;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100398#endif /* !STATIC_MODES */
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400399
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500400 clt_mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000401
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500402 clt_mdct_init(&mode->shortMdct, 2*mode->shortMdctSize);
Jean-Marc Valin5f633542010-04-29 09:58:05 -0400403
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000404 mode->prob = quant_prob_alloc(mode);
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400405 if ((mode->mdct.trig==NULL) || (mode->shortMdct.trig==NULL)
406#ifndef ENABLE_TI_DSPLIB55
Jean-Marc Valin9319e3e2009-11-09 13:51:54 +0900407 || (mode->mdct.kfft==NULL) || (mode->shortMdct.kfft==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400408#endif
409 || (mode->prob==NULL))
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400410 goto failure;
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000411
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400412 mode->marker_start = MODEVALID;
413 mode->marker_end = MODEVALID;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100414 if (error)
415 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100416 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400417failure:
418 if (error)
419 *error = CELT_INVALID_MODE;
420 if (mode!=NULL)
421 celt_mode_destroy(mode);
422 return NULL;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100423}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100424
Peter Kirk19f9dc92008-06-06 14:38:38 +0200425void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100426{
Jean-Marc Valinf43488c2009-06-05 11:07:31 -0400427 int i;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400428 const celt_int16 *prevPtr = NULL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400429 if (mode == NULL)
430 {
431 celt_warning("NULL passed to celt_mode_destroy");
432 return;
433 }
434
435 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
436 {
437 celt_warning("Freeing a mode which has already been freed");
438 return;
439 }
440
441 if (mode->marker_start != MODEVALID && mode->marker_start != MODEPARTIAL)
442 {
443 celt_warning("This is not a valid CELT mode structure");
444 return;
445 }
446 mode->marker_start = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100447#ifndef STATIC_MODES
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400448 if (mode->bits!=NULL)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100449 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400450 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100451 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400452 if (mode->bits[i] != prevPtr)
453 {
454 prevPtr = mode->bits[i];
455 celt_free((int*)mode->bits[i]);
456 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100457 }
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400458 }
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400459 celt_free((celt_int16**)mode->bits);
460 celt_free((celt_int16*)mode->eBands);
461 celt_free((celt_int16*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400462
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400463 celt_free((celt_word16*)mode->window);
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400464 celt_free((celt_int16*)mode->logN);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100465
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000466#endif
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500467 clt_mdct_clear(&mode->mdct);
468 clt_mdct_clear(&mode->shortMdct);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000469 quant_prob_free(mode->prob);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400470 mode->marker_end = MODEFREED;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100471 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100472}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100473
474int check_mode(const CELTMode *mode)
475{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400476 if (mode==NULL)
477 return CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100478 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
479 return CELT_OK;
480 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
481 celt_warning("Using a mode that has already been freed");
482 else
483 celt_warning("This is not a valid CELT mode");
484 return CELT_INVALID_MODE;
485}