blob: 6b9af9773924343400e742562788913e127382ed [file] [log] [blame]
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +11001/* (C) 2007-2008 Jean-Marc Valin, CSIRO
Jean-Marc Valinecb36a32007-12-05 01:31:49 +11002*/
3/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 - Neither the name of the Xiph.org Foundation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*/
31
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110032#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
Jean-Marc Valin65d57e62008-02-18 15:49:37 +110036#include "celt.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110037#include "modes.h"
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110038#include "rate.h"
Jean-Marc Valin81a82952008-02-17 22:41:29 +110039#include "os_support.h"
Jean-Marc Valinf7cec832008-04-18 17:29:56 +100040#include "stack_alloc.h"
Jean-Marc Valin4ce92052008-04-23 13:42:10 +100041#include "quant_bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110042
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110043#ifdef STATIC_MODES
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +100044#include "static_modes.c"
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110045#endif
46
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110047#define MODEVALID 0xa110ca7e
48#define MODEFREED 0xb10cf8ee
49
Jean-Marc Valind748cd52008-03-01 07:27:03 +110050#ifndef M_PI
51#define M_PI 3.141592653
52#endif
53
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110054
Jean-Marc Valin7f389062008-03-12 17:46:04 +110055int EXPORT celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110056{
57 switch (request)
58 {
59 case CELT_GET_FRAME_SIZE:
60 *value = mode->mdctSize;
61 break;
62 case CELT_GET_LOOKAHEAD:
63 *value = mode->overlap;
64 break;
Jean-Marc Valin4c6bc882008-01-31 17:34:27 +110065 case CELT_GET_NB_CHANNELS:
66 *value = mode->nbChannels;
67 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110068 default:
69 return CELT_BAD_ARG;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110070 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110071 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110072}
73
Jean-Marc Valin5588d522008-03-10 15:07:58 +110074#ifndef STATIC_MODES
75
Jean-Marc Valin134492a2008-02-18 16:46:22 +110076#define PBANDS 8
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100077
78#ifdef STDIN_TUNING
79int MIN_BINS;
80#else
Jean-Marc Valin52824c72008-05-06 18:01:17 +100081#define MIN_BINS 3
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100082#endif
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 Valin25358cd2008-02-19 12:21:32 +110087static const celt_int16_t 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 Valin25358cd2008-02-19 12:21:32 +110095static const celt_int16_t pitch_freq[PBANDS+1] ={0, 345, 689, 1034, 1378, 2067, 3273, 5340, 6374};
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +110096
Jean-Marc Valin75e9c862008-02-18 17:04:15 +110097/* This allocation table is per critical band. When creating a mode, the bits get added together
98 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100099
100#ifdef STDIN_TUNING
101int BITALLOC_SIZE;
102int *band_allocation;
103#else
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100104#define BITALLOC_SIZE 10
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100105static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100106 { 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,
Jean-Marc Valin52824c72008-05-06 18:01:17 +1000107 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 4, 5, 7, 7, 7, 5, 4, 0, 0, 0, 0, 0, 0,
108 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 3, 5, 6, 8, 8, 8, 6, 5, 4, 0, 0, 0, 0, 0,
109 3, 2, 2, 2, 3, 3, 2, 3, 2, 3, 4, 4, 6, 7, 9, 9, 9, 7, 6, 5, 5, 5, 0, 0, 0,
110 3, 3, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 7, 9, 10, 10, 10, 9, 6, 5, 5, 5, 5, 1, 0,
111 4, 4, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 9, 10, 10, 10, 9, 9, 8, 11, 10, 10, 1, 1,
112 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 10, 12, 13, 13, 13, 12, 12, 12, 18, 18, 16, 10, 1,
113 7, 7, 6, 6, 7, 7, 7, 7, 8, 9, 10, 11, 13, 18, 20, 22, 25, 22, 25, 30, 30, 35, 35, 35, 15,
114 9, 9, 9, 9, 10, 10, 10, 10, 11, 12, 18, 22, 25, 24, 23, 27, 29, 27, 35, 40, 42, 50, 59, 54, 31,
115 16, 16, 16, 16, 16, 18, 20, 22, 24, 28, 30, 32, 35, 34, 33, 37, 39, 40, 45, 50, 52, 60, 60, 60, 60,
116};
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000117#endif
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100118
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100119static celt_int16_t *compute_ebands(celt_int32_t Fs, int frame_size, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100120{
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100121 celt_int16_t *eBands;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100122 int i, res, min_width, lin, low, high;
123 res = (Fs+frame_size)/(2*frame_size);
124 min_width = MIN_BINS*res;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100125 /*printf ("min_width = %d\n", min_width);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100126
127 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
128 for (lin=0;lin<BARK_BANDS;lin++)
129 if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
130 break;
131
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100132 /*printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100133 low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
134 high = BARK_BANDS-lin;
135 *nbEBands = low+high;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100136 eBands = celt_alloc(sizeof(celt_int16_t)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100137
138 /* Linear spacing (min_width) */
139 for (i=0;i<low;i++)
140 eBands[i] = MIN_BINS*i;
141 /* Spacing follows critical bands */
142 for (i=0;i<high;i++)
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100143 eBands[i+low] = (bark_freq[lin+i]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100144 /* Enforce the minimum spacing at the boundary */
145 for (i=0;i<*nbEBands;i++)
146 if (eBands[i] < MIN_BINS*i)
147 eBands[i] = MIN_BINS*i;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100148 eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100149 eBands[*nbEBands+1] = frame_size;
150 if (eBands[*nbEBands] > eBands[*nbEBands+1])
151 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100152
153 /* FIXME: Remove last band if too small */
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100154 /*for (i=0;i<*nbEBands+2;i++)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100155 printf("%d ", eBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100156 printf ("\n");*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100157 return eBands;
158}
159
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100160static void compute_pbands(CELTMode *mode, int res)
161{
162 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100163 celt_int16_t *pBands;
164 pBands=celt_alloc(sizeof(celt_int16_t)*(PBANDS+2));
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100165 mode->nbPBands = PBANDS;
166 for (i=0;i<PBANDS+1;i++)
167 {
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100168 pBands[i] = (pitch_freq[i]+res/2)/res;
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100169 if (pBands[i] < mode->eBands[i])
170 pBands[i] = mode->eBands[i];
171 }
172 pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100173 for (i=1;i<mode->nbPBands+1;i++)
174 {
175 int j;
176 for (j=0;j<mode->nbEBands;j++)
177 if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
178 break;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100179 /*printf ("%d %d\n", i, j);*/
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100180 if (mode->eBands[j] != pBands[i])
181 {
182 if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] &&
183 mode->eBands[j] != pBands[i-1])
184 pBands[i] = mode->eBands[j];
185 else
186 pBands[i] = mode->eBands[j+1];
187 }
188 }
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100189 /*for (i=0;i<mode->nbPBands+2;i++)
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100190 printf("%d ", pBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100191 printf ("\n");*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100192 mode->pBands = pBands;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100193 mode->pitchEnd = pBands[PBANDS];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100194}
195
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100196static void compute_allocation_table(CELTMode *mode, int res)
197{
198 int i, j, eband;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100199 celt_int16_t *allocVectors;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100200
201 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100202 allocVectors = celt_alloc(sizeof(celt_int16_t)*(BITALLOC_SIZE*mode->nbEBands));
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100203 for (i=0;i<BITALLOC_SIZE;i++)
204 {
205 eband = 0;
206 for (j=0;j<BARK_BANDS;j++)
207 {
208 int edge, low;
209 edge = mode->eBands[eband+1]*res;
210 if (edge < bark_freq[j+1])
211 {
212 int num, den;
213 num = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j]);
214 den = bark_freq[j+1]-bark_freq[j];
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100215 low = (num+den/2)/den;
216 allocVectors[i*mode->nbEBands+eband] += low;
217 eband++;
218 allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]-low;
219 } else {
220 allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j];
221 }
222 }
223 }
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100224 /*for (i=0;i<BITALLOC_SIZE;i++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100225 {
226 for (j=0;j<mode->nbEBands;j++)
227 printf ("%2d ", allocVectors[i*mode->nbEBands+j]);
228 printf ("\n");
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100229 }*/
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100230 mode->allocVectors = allocVectors;
231}
232
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100233#endif /* STATIC_MODES */
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100234
Jean-Marc Valinad637192008-05-07 13:44:39 +1000235static void compute_energy_allocation_table(CELTMode *mode)
236{
237 int i, j;
238 celt_int16_t *alloc;
239
240 alloc = celt_alloc(sizeof(celt_int16_t)*(mode->nbAllocVectors*(mode->nbEBands+1)));
241 for (i=0;i<mode->nbAllocVectors;i++)
242 {
243 int sum = 0;
244 int min_bits = 1;
245 if (mode->allocVectors[i*mode->nbEBands]>12)
246 min_bits = 2;
247 if (mode->allocVectors[i*mode->nbEBands]>24)
248 min_bits = 3;
249 for (j=0;j<mode->nbEBands;j++)
250 {
251 alloc[i*(mode->nbEBands+1)+j] = mode->allocVectors[i*mode->nbEBands+j]
252 / (mode->eBands[j+1]-mode->eBands[j]-1);
253 if (alloc[i*(mode->nbEBands+1)+j]<min_bits)
254 alloc[i*(mode->nbEBands+1)+j] = min_bits;
255 if (alloc[i*(mode->nbEBands+1)+j]>7)
256 alloc[i*(mode->nbEBands+1)+j] = 7;
257 sum += alloc[i*(mode->nbEBands+1)+j];
258 /*printf ("%d ", alloc[i*(mode->nbEBands+1)+j]);*/
259 /*printf ("%f ", mode->allocVectors[i*mode->nbEBands+j]*1.f/(mode->eBands[j+1]-mode->eBands[j]-1));*/
260 }
261 alloc[i*(mode->nbEBands+1)+mode->nbEBands] = sum;
262 /*printf ("\n");*/
263 }
264 mode->energy_alloc = alloc;
265}
266
Jean-Marc Valin7f389062008-03-12 17:46:04 +1100267CELTMode EXPORT *celt_mode_create(celt_int32_t Fs, int channels, int frame_size, int lookahead, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100268{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000269 int i;
270#ifdef STDIN_TUNING
271 scanf("%d ", &MIN_BINS);
272 scanf("%d ", &BITALLOC_SIZE);
273 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
274 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
275 {
276 scanf("%d ", band_allocation+i);
277 }
278#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100279#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100280 const CELTMode *m = NULL;
281 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000282 ALLOC_STACK;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100283 for (i=0;i<TOTAL_MODES;i++)
284 {
285 if (Fs == static_mode_list[i]->Fs &&
286 channels == static_mode_list[i]->nbChannels &&
287 frame_size == static_mode_list[i]->mdctSize &&
288 lookahead == static_mode_list[i]->overlap)
289 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100290 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100291 break;
292 }
293 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100294 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100295 {
296 celt_warning("Mode not included as part of the static modes");
297 if (error)
298 *error = CELT_BAD_ARG;
299 return NULL;
300 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100301 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
302 CELT_COPY(mode, m, 1);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100303#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100304 int res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100305 CELTMode *mode;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100306 celt_word16_t *window;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000307 ALLOC_STACK;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100308
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100309 /* The good thing here is that permutation of the arguments will automatically be invalid */
310
311 if (Fs < 32000 || Fs > 64000)
312 {
313 celt_warning("Sampling rate must be between 32 kHz and 64 kHz");
314 if (error)
315 *error = CELT_BAD_ARG;
316 return NULL;
317 }
318 if (channels < 0 || channels > 2)
319 {
320 celt_warning("Only mono and stereo supported");
321 if (error)
322 *error = CELT_BAD_ARG;
323 return NULL;
324 }
325 if (frame_size < 64 || frame_size > 256 || frame_size%2!=0)
326 {
327 celt_warning("Only even frame sizes between 64 and 256 are supported");
328 if (error)
329 *error = CELT_BAD_ARG;
330 return NULL;
331 }
332 if (lookahead < 32 || lookahead > frame_size)
333 {
334 celt_warning("The overlap must be between 32 and the frame size");
335 if (error)
336 *error = CELT_BAD_ARG;
337 return NULL;
338 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100339 res = (Fs+frame_size)/(2*frame_size);
340
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100341 mode = celt_alloc(sizeof(CELTMode));
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100342 mode->Fs = Fs;
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100343 mode->overlap = lookahead;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100344 mode->mdctSize = frame_size;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100345 mode->nbChannels = channels;
346 mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100347 compute_pbands(mode, res);
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100348 mode->ePredCoef = QCONST16(.8f,15);
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100349
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100350 compute_allocation_table(mode, res);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100351 /*printf ("%d bands\n", mode->nbEBands);*/
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100352
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100353 window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100354
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100355#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100356 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100357 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 +1100358#else
359 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100360 window[i] = MIN32(32767,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 +1100361#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100362 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100363
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100364 compute_alloc_cache(mode);
365
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000366#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100367 psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs);
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000368#endif
369
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100370 mode->marker_start = MODEVALID;
371 mode->marker_end = MODEVALID;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100372#endif /* !STATIC_MODES */
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100373 mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000374 mode->fft = pitch_state_alloc(MAX_PERIOD);
375
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000376 mode->prob = quant_prob_alloc(mode);
Jean-Marc Valinad637192008-05-07 13:44:39 +1000377 compute_energy_allocation_table(mode);
378
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100379 if (error)
380 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100381 return mode;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100382}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100383
Jean-Marc Valin7f389062008-03-12 17:46:04 +1100384void EXPORT celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100385{
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100386#ifndef STATIC_MODES
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100387 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100388 const celt_int16_t *prevPtr = NULL;
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100389 for (i=0;i<mode->nbEBands;i++)
390 {
391 if (mode->bits[i] != prevPtr)
392 {
393 prevPtr = mode->bits[i];
394 celt_free((int*)mode->bits[i]);
395 }
396 }
397 celt_free((int**)mode->bits);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100398 if (check_mode(mode) != CELT_OK)
399 return;
400 celt_free((int*)mode->eBands);
401 celt_free((int*)mode->pBands);
402 celt_free((int*)mode->allocVectors);
403
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100404 celt_free((celt_word16_t*)mode->window);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100405
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100406 mode->marker_start = MODEFREED;
407 mode->marker_end = MODEFREED;
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000408#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100409 psydecay_clear(&mode->psy);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100410#endif
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000411#endif
Jean-Marc Valin9656ca02008-04-11 17:23:01 +1000412 mdct_clear(&mode->mdct);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000413 pitch_state_free(mode->fft);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000414 quant_prob_free(mode->prob);
Jean-Marc Valinad637192008-05-07 13:44:39 +1000415 celt_free((celt_int16_t *)mode->energy_alloc);
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100416 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100417}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100418
419int check_mode(const CELTMode *mode)
420{
421 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
422 return CELT_OK;
423 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
424 celt_warning("Using a mode that has already been freed");
425 else
426 celt_warning("This is not a valid CELT mode");
427 return CELT_INVALID_MODE;
428}