blob: e01de39c12ecec3925ebcaef9330867438e10875 [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 {
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110064 case CELT_GET_LOOKAHEAD:
65 *value = mode->overlap;
66 break;
Jean-Marc Valin59093c02008-05-15 21:53:27 +100067 case CELT_GET_BITSTREAM_VERSION:
68 *value = CELT_BITSTREAM_VERSION;
69 break;
Gregory Maxwelld9458cd2009-05-30 17:04:02 -040070 case CELT_GET_SAMPLE_RATE:
71 *value = mode->Fs;
72 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110073 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040074 return CELT_UNIMPLEMENTED;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110075 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110076 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110077}
78
Jean-Marc Valin5588d522008-03-10 15:07:58 +110079#ifndef STATIC_MODES
80
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110081/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
82 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +110083#define BARK_BANDS 25
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040084static const celt_int16 bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110085 0, 100, 200, 300, 400,
86 510, 630, 770, 920, 1080,
87 1270, 1480, 1720, 2000, 2320,
88 2700, 3150, 3700, 4400, 5300,
89 6400, 7700, 9500, 12000, 15500,
90 20000};
91
Jean-Marc Valin75e9c862008-02-18 17:04:15 +110092/* This allocation table is per critical band. When creating a mode, the bits get added together
93 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100094
95#ifdef STDIN_TUNING
96int BITALLOC_SIZE;
97int *band_allocation;
98#else
Jean-Marc Valin9c709062008-08-03 22:07:06 -040099#define BITALLOC_SIZE 12
Jean-Marc Valinc1ca5872010-05-15 23:47:09 -0400100static const unsigned char band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Christopher Montgomery8e511a82009-07-03 02:10:17 -0400101 /* 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 */
102 { 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*/
103 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*/
104 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*/
105 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*/
106 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*/
107 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*/
108 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*/
109 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*/
110 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*/
111 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*/
112 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*/
113 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 -0400114 };
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000115#endif
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100116
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400117static const celt_int16 eband5ms[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 20, 23, 27, 33, 40, 48, 60, 78, 100};
118
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400119static celt_int16 *compute_ebands(celt_int32 Fs, int frame_size, int res, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100120{
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400121 celt_int16 *eBands;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400122 int i, lin, low, high, nBark, offset=0;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100123
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400124 if (Fs == 400*(celt_int32)frame_size && Fs >= 40000)
125 {
126 *nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
127 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
128 for (i=0;i<*nbEBands+2;i++)
129 eBands[i] = eband5ms[i];
130 eBands[*nbEBands+1] = frame_size;
131 return eBands;
132 }
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400133 /* Find the number of critical bands supported by our sampling rate */
134 for (nBark=1;nBark<BARK_BANDS;nBark++)
135 if (bark_freq[nBark+1]*2 >= Fs)
136 break;
137
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100138 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400139 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400140 if (bark_freq[lin+1]-bark_freq[lin] >= res)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100141 break;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400142
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400143 low = (bark_freq[lin]+res/2)/res;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400144 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100145 *nbEBands = low+high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400146 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100147
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400148 if (eBands==NULL)
149 return NULL;
150
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100151 /* Linear spacing (min_width) */
152 for (i=0;i<low;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400153 eBands[i] = i;
Jean-Marc Valinbe8d1252010-04-21 18:09:07 -0400154 if (low>0)
155 offset = eBands[low-1]*res - bark_freq[lin-1];
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100156 /* Spacing follows critical bands */
157 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400158 {
159 int target = bark_freq[lin+i];
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400160 eBands[i+low] = (target+(offset+res)/2)/res;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400161 offset = eBands[i+low]*res - target;
162 }
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100163 /* Enforce the minimum spacing at the boundary */
164 for (i=0;i<*nbEBands;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400165 if (eBands[i] < i)
166 eBands[i] = i;
167 eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100168 eBands[*nbEBands+1] = frame_size;
169 if (eBands[*nbEBands] > eBands[*nbEBands+1])
170 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400171 for (i=1;i<*nbEBands-1;i++)
172 {
173 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
174 {
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400175 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400176 }
177 }
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400178 /*for (i=0;i<=*nbEBands+1;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400179 printf ("%d ", eBands[i]);
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400180 printf ("\n");
181 exit(1);*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100182 /* FIXME: Remove last band if too small */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100183 return eBands;
184}
185
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400186static void compute_allocation_table(CELTMode *mode, int res)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100187{
Gregory Maxwellec836da2009-05-04 14:55:40 -0400188 int i, j, nBark;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400189 celt_int16 *allocVectors;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400190
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400191 /* Find the number of critical bands supported by our sampling rate */
192 for (nBark=1;nBark<BARK_BANDS;nBark++)
193 if (bark_freq[nBark+1]*2 >= mode->Fs)
194 break;
195
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100196 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400197 allocVectors = celt_alloc(sizeof(celt_int16)*(BITALLOC_SIZE*mode->nbEBands));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400198 if (allocVectors==NULL)
199 return;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400200 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100201 for (i=0;i<BITALLOC_SIZE;i++)
202 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400203 celt_int32 current = 0;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400204 int eband = 0;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400205 for (j=0;j<nBark;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100206 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400207 int edge, low, high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400208 celt_int32 alloc;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400209
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400210 alloc = mode->shortMdctSize*band_allocation[i*BARK_BANDS+j];
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400211 low = bark_freq[j];
212 high = bark_freq[j+1];
213
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400214 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin3ff5e4c2010-04-14 18:02:09 -0400215 while (edge <= high && eband < mode->nbEBands)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100216 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400217 celt_int32 num;
218 int den, bits;
219 num = alloc * (edge-low);
220 den = high-low;
221 /* Divide with rounding */
222 bits = (2*num+den)/(2*den);
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400223 allocVectors[i*mode->nbEBands+eband] = (current+bits+128)>>(8-BITRES);
224 /* Remove one bit from every band -- FIXME: this is just a temporary hack*/
225 allocVectors[i*mode->nbEBands+eband] -= 1<<BITRES;
226 if (allocVectors[i*mode->nbEBands+eband]<0)
227 allocVectors[i*mode->nbEBands+eband]=0;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400228 /* Remove the part of the band we just allocated */
229 low = edge;
230 alloc -= bits;
231
232 /* Move to next eband */
233 current = 0;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100234 eband++;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400235 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400236 }
237 current += alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100238 }
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400239 if (eband < mode->nbEBands)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400240 {
241 allocVectors[i*mode->nbEBands+eband] = (current+128)>>(8-BITRES);
242 /* Same hack as above FIXME: again */
243 allocVectors[i*mode->nbEBands+eband] -= 1<<BITRES;
244 if (allocVectors[i*mode->nbEBands+eband]<0)
245 allocVectors[i*mode->nbEBands+eband]=0;
246 }
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100247 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400248 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000249}
250
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400251#endif /* STATIC_MODES */
252
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400253CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100254{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000255 int i;
256#ifdef STDIN_TUNING
257 scanf("%d ", &MIN_BINS);
258 scanf("%d ", &BITALLOC_SIZE);
259 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
260 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
261 {
262 scanf("%d ", band_allocation+i);
263 }
264#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100265#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100266 const CELTMode *m = NULL;
267 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000268 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400269#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
270 if (global_stack==NULL)
271 {
272 celt_free(global_stack);
273 goto failure;
274 }
275#endif
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100276 for (i=0;i<TOTAL_MODES;i++)
277 {
278 if (Fs == static_mode_list[i]->Fs &&
Jean-Marc Valin60d08372008-10-03 07:30:08 -0400279 frame_size == static_mode_list[i]->mdctSize)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100280 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100281 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100282 break;
283 }
284 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100285 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100286 {
287 celt_warning("Mode not included as part of the static modes");
288 if (error)
289 *error = CELT_BAD_ARG;
290 return NULL;
291 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100292 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400293 if (mode==NULL)
294 goto failure;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100295 CELT_COPY(mode, m, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400296 mode->marker_start = MODEPARTIAL;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100297#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100298 int res;
Gregory Maxwell84966952009-06-30 01:06:04 -0400299 CELTMode *mode=NULL;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400300 celt_word16 *window;
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400301 celt_int16 *logN;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000302 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400303#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
304 if (global_stack==NULL)
305 {
306 celt_free(global_stack);
307 goto failure;
308 }
309#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100310
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100311 /* The good thing here is that permutation of the arguments will automatically be invalid */
312
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500313 if (Fs < 32000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100314 {
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500315 celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100316 if (error)
317 *error = CELT_BAD_ARG;
318 return NULL;
319 }
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400320 if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100321 {
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400322 celt_warning("Only even frame sizes from 64 to 1024 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100323 if (error)
324 *error = CELT_BAD_ARG;
325 return NULL;
326 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100327
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100328 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400329 if (mode==NULL)
330 goto failure;
331 mode->marker_start = MODEPARTIAL;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100332 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100333 mode->mdctSize = frame_size;
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100334 mode->ePredCoef = QCONST16(.8f,15);
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400335
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400336 if (frame_size >= 640 && (frame_size%16)==0)
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400337 {
338 mode->nbShortMdcts = 8;
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400339 } else if (frame_size >= 320 && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000340 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400341 mode->nbShortMdcts = 4;
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400342 } else if (frame_size >= 120 && (frame_size%4)==0)
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400343 {
344 mode->nbShortMdcts = 2;
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400345 } else
346 {
347 mode->nbShortMdcts = 1;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000348 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400349
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400350 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
351 res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
352
353 mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400354 if (mode->eBands==NULL)
355 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400356
Jean-Marc Valine949b722010-05-07 07:48:07 -0400357 mode->pitchEnd = 4000*(celt_int32)mode->shortMdctSize/Fs;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400358
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400359 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000360 if (mode->nbShortMdcts > 1)
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400361 mode->overlap = (mode->shortMdctSize>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000362 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400363 mode->overlap = (frame_size>>3)<<2;
364
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400365
366 compute_allocation_table(mode, res);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400367 if (mode->allocVectors==NULL)
368 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100369
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400370 window = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400371 if (window==NULL)
372 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100373
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100374#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100375 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100376 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 +1100377#else
378 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin8974f002010-03-20 00:41:39 -0400379 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 +1100380#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100381 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100382
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400383 for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
Jean-Marc Valin811f21a2010-05-06 07:38:04 -0400384 mode->bits[i] = (const celt_int16 **)compute_alloc_cache(mode, 1, 1<<i);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400385 if (mode->bits==NULL)
386 goto failure;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100387
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400388 logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
389 if (logN==NULL)
390 goto failure;
391
392 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valinaead79b2010-05-11 07:34:24 -0400393 logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400394 mode->logN = logN;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100395#endif /* !STATIC_MODES */
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400396
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400397 for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
398 {
399 clt_mdct_init(&mode->mdct[i], 2*mode->shortMdctSize<<i);
400 if ((mode->mdct[i].trig==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400401#ifndef ENABLE_TI_DSPLIB55
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400402 || (mode->mdct[i].kfft==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400403#endif
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400404 )
405 goto failure;
406 }
407 mode->prob = quant_prob_alloc(mode);
408 if (mode->prob==NULL)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400409 goto failure;
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000410
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400411 mode->marker_start = MODEVALID;
412 mode->marker_end = MODEVALID;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100413 if (error)
414 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100415 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400416failure:
417 if (error)
418 *error = CELT_INVALID_MODE;
419 if (mode!=NULL)
420 celt_mode_destroy(mode);
421 return NULL;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100422}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100423
Peter Kirk19f9dc92008-06-06 14:38:38 +0200424void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100425{
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400426 int i, m;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400427 const celt_int16 *prevPtr = NULL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400428 if (mode == NULL)
429 {
430 celt_warning("NULL passed to celt_mode_destroy");
431 return;
432 }
433
434 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
435 {
436 celt_warning("Freeing a mode which has already been freed");
437 return;
438 }
439
440 if (mode->marker_start != MODEVALID && mode->marker_start != MODEPARTIAL)
441 {
442 celt_warning("This is not a valid CELT mode structure");
443 return;
444 }
445 mode->marker_start = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100446#ifndef STATIC_MODES
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400447 for (m=0;(1<<m)<=mode->nbShortMdcts;m++)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100448 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400449 if (mode->bits[m]!=NULL)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100450 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400451 for (i=0;i<mode->nbEBands;i++)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400452 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400453 if (mode->bits[m][i] != prevPtr)
454 {
455 prevPtr = mode->bits[m][i];
456 celt_free((int*)mode->bits[m][i]);
457 }
458 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100459 }
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400460 celt_free((celt_int16**)mode->bits[m]);
461 }
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400462 celt_free((celt_int16*)mode->eBands);
463 celt_free((celt_int16*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400464
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400465 celt_free((celt_word16*)mode->window);
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400466 celt_free((celt_int16*)mode->logN);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100467
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000468#endif
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400469 for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
470 clt_mdct_clear(&mode->mdct[i]);
471
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000472 quant_prob_free(mode->prob);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400473 mode->marker_end = MODEFREED;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100474 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100475}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100476
477int check_mode(const CELTMode *mode)
478{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400479 if (mode==NULL)
480 return CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100481 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
482 return CELT_OK;
483 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
484 celt_warning("Using a mode that has already been freed");
485 else
486 celt_warning("This is not a valid CELT mode");
487 return CELT_INVALID_MODE;
488}