blob: 533dc74120ed7ccfed40929e5aaafe09583b36d1 [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 Valin81a82952008-02-17 22:41:29 +110077#define MIN_BINS 4
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110078/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
79 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +110080#define BARK_BANDS 25
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110081static const celt_int16_t bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110082 0, 100, 200, 300, 400,
83 510, 630, 770, 920, 1080,
84 1270, 1480, 1720, 2000, 2320,
85 2700, 3150, 3700, 4400, 5300,
86 6400, 7700, 9500, 12000, 15500,
87 20000};
88
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110089static 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 +110090
Jean-Marc Valin75e9c862008-02-18 17:04:15 +110091/* This allocation table is per critical band. When creating a mode, the bits get added together
92 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +110093#define BITALLOC_SIZE 10
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110094static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Jean-Marc Valin9838fec2008-02-18 14:45:11 +110095 { 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 Valin5a4bbde2008-02-19 14:32:08 +110096 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 5, 5, 7, 7, 7, 5, 4, 0, 0, 0, 0, 0, 0,
97 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 6, 6, 8, 8, 8, 6, 5, 4, 0, 0, 0, 0, 0,
98 3, 2, 2, 2, 3, 3, 2, 3, 2, 2, 4, 3, 7, 7, 9, 9, 9, 7, 6, 5, 5, 5, 0, 0, 0,
99 3, 3, 2, 2, 3, 3, 3, 3, 3, 2, 4, 4, 9, 9, 10, 10, 10, 9, 6, 5, 5, 5, 5, 0, 0,
100 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 10, 10, 12, 12, 12, 10, 10, 10, 11, 10, 10, 5, 5,
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100101 4, 4, 4, 4, 5, 5, 5, 5, 5, 4, 7, 7, 14, 13, 13, 13, 13, 13, 15, 16, 17, 18, 20, 18, 11,
102 7, 7, 6, 6, 9, 8, 8, 8, 8, 8, 11, 11, 20, 18, 19, 19, 25, 22, 25, 30, 30, 35, 35, 35, 35,
103 8, 8, 8, 8, 10, 10, 10, 10, 9, 9, 19, 18, 25, 24, 23, 21, 29, 27, 35, 40, 42, 50, 59, 54, 51,
104 11, 11, 10, 10, 14, 13, 13, 13, 13, 12, 19, 18, 35, 34, 33, 31, 39, 37, 45, 50, 52, 60, 60, 60, 60,
105 };
106
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100107
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100108static celt_int16_t *compute_ebands(celt_int32_t Fs, int frame_size, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100109{
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100110 celt_int16_t *eBands;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100111 int i, res, min_width, lin, low, high;
112 res = (Fs+frame_size)/(2*frame_size);
113 min_width = MIN_BINS*res;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100114 /*printf ("min_width = %d\n", min_width);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100115
116 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
117 for (lin=0;lin<BARK_BANDS;lin++)
118 if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
119 break;
120
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100121 /*printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100122 low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
123 high = BARK_BANDS-lin;
124 *nbEBands = low+high;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100125 eBands = celt_alloc(sizeof(celt_int16_t)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100126
127 /* Linear spacing (min_width) */
128 for (i=0;i<low;i++)
129 eBands[i] = MIN_BINS*i;
130 /* Spacing follows critical bands */
131 for (i=0;i<high;i++)
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100132 eBands[i+low] = (bark_freq[lin+i]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100133 /* Enforce the minimum spacing at the boundary */
134 for (i=0;i<*nbEBands;i++)
135 if (eBands[i] < MIN_BINS*i)
136 eBands[i] = MIN_BINS*i;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100137 eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100138 eBands[*nbEBands+1] = frame_size;
139 if (eBands[*nbEBands] > eBands[*nbEBands+1])
140 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100141
142 /* FIXME: Remove last band if too small */
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100143 /*for (i=0;i<*nbEBands+2;i++)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100144 printf("%d ", eBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100145 printf ("\n");*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100146 return eBands;
147}
148
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100149static void compute_pbands(CELTMode *mode, int res)
150{
151 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100152 celt_int16_t *pBands;
153 pBands=celt_alloc(sizeof(celt_int16_t)*(PBANDS+2));
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100154 mode->nbPBands = PBANDS;
155 for (i=0;i<PBANDS+1;i++)
156 {
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100157 pBands[i] = (pitch_freq[i]+res/2)/res;
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100158 if (pBands[i] < mode->eBands[i])
159 pBands[i] = mode->eBands[i];
160 }
161 pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100162 for (i=1;i<mode->nbPBands+1;i++)
163 {
164 int j;
165 for (j=0;j<mode->nbEBands;j++)
166 if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
167 break;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100168 /*printf ("%d %d\n", i, j);*/
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100169 if (mode->eBands[j] != pBands[i])
170 {
171 if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] &&
172 mode->eBands[j] != pBands[i-1])
173 pBands[i] = mode->eBands[j];
174 else
175 pBands[i] = mode->eBands[j+1];
176 }
177 }
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100178 /*for (i=0;i<mode->nbPBands+2;i++)
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100179 printf("%d ", pBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100180 printf ("\n");*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100181 mode->pBands = pBands;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100182 mode->pitchEnd = pBands[PBANDS];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100183}
184
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100185static void compute_allocation_table(CELTMode *mode, int res)
186{
187 int i, j, eband;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100188 celt_int16_t *allocVectors;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100189
190 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100191 allocVectors = celt_alloc(sizeof(celt_int16_t)*(BITALLOC_SIZE*mode->nbEBands));
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100192 for (i=0;i<BITALLOC_SIZE;i++)
193 {
194 eband = 0;
195 for (j=0;j<BARK_BANDS;j++)
196 {
197 int edge, low;
198 edge = mode->eBands[eband+1]*res;
199 if (edge < bark_freq[j+1])
200 {
201 int num, den;
202 num = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j]);
203 den = bark_freq[j+1]-bark_freq[j];
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100204 low = (num+den/2)/den;
205 allocVectors[i*mode->nbEBands+eband] += low;
206 eband++;
207 allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]-low;
208 } else {
209 allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j];
210 }
211 }
212 }
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100213 /*for (i=0;i<BITALLOC_SIZE;i++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100214 {
215 for (j=0;j<mode->nbEBands;j++)
216 printf ("%2d ", allocVectors[i*mode->nbEBands+j]);
217 printf ("\n");
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100218 }*/
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100219 mode->allocVectors = allocVectors;
220}
221
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100222#endif /* STATIC_MODES */
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100223
Jean-Marc Valin7f389062008-03-12 17:46:04 +1100224CELTMode 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 +1100225{
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100226#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100227 const CELTMode *m = NULL;
228 CELTMode *mode=NULL;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100229 int i;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000230 ALLOC_STACK;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100231 for (i=0;i<TOTAL_MODES;i++)
232 {
233 if (Fs == static_mode_list[i]->Fs &&
234 channels == static_mode_list[i]->nbChannels &&
235 frame_size == static_mode_list[i]->mdctSize &&
236 lookahead == static_mode_list[i]->overlap)
237 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100238 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100239 break;
240 }
241 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100242 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100243 {
244 celt_warning("Mode not included as part of the static modes");
245 if (error)
246 *error = CELT_BAD_ARG;
247 return NULL;
248 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100249 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
250 CELT_COPY(mode, m, 1);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100251#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100252 int res;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100253 int i;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100254 CELTMode *mode;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100255 celt_word16_t *window;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000256 ALLOC_STACK;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100257
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100258 /* The good thing here is that permutation of the arguments will automatically be invalid */
259
260 if (Fs < 32000 || Fs > 64000)
261 {
262 celt_warning("Sampling rate must be between 32 kHz and 64 kHz");
263 if (error)
264 *error = CELT_BAD_ARG;
265 return NULL;
266 }
267 if (channels < 0 || channels > 2)
268 {
269 celt_warning("Only mono and stereo supported");
270 if (error)
271 *error = CELT_BAD_ARG;
272 return NULL;
273 }
274 if (frame_size < 64 || frame_size > 256 || frame_size%2!=0)
275 {
276 celt_warning("Only even frame sizes between 64 and 256 are supported");
277 if (error)
278 *error = CELT_BAD_ARG;
279 return NULL;
280 }
281 if (lookahead < 32 || lookahead > frame_size)
282 {
283 celt_warning("The overlap must be between 32 and the frame size");
284 if (error)
285 *error = CELT_BAD_ARG;
286 return NULL;
287 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100288 res = (Fs+frame_size)/(2*frame_size);
289
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100290 mode = celt_alloc(sizeof(CELTMode));
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100291 mode->Fs = Fs;
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100292 mode->overlap = lookahead;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100293 mode->mdctSize = frame_size;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100294 mode->nbChannels = channels;
295 mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100296 compute_pbands(mode, res);
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100297 mode->ePredCoef = QCONST16(.8f,15);
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100298
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100299 compute_allocation_table(mode, res);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100300 /*printf ("%d bands\n", mode->nbEBands);*/
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100301
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100302 window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100303
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100304#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100305 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100306 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 +1100307#else
308 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100309 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 +1100310#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100311 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100312
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100313 compute_alloc_cache(mode);
314
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000315#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100316 psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs);
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000317#endif
318
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100319 mode->marker_start = MODEVALID;
320 mode->marker_end = MODEVALID;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100321#endif /* !STATIC_MODES */
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100322 mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000323 mode->prob = quant_prob_alloc(mode);
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100324 if (error)
325 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100326 return mode;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100327}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100328
Jean-Marc Valin7f389062008-03-12 17:46:04 +1100329void EXPORT celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100330{
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100331#ifndef STATIC_MODES
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100332 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100333 const celt_int16_t *prevPtr = NULL;
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100334 for (i=0;i<mode->nbEBands;i++)
335 {
336 if (mode->bits[i] != prevPtr)
337 {
338 prevPtr = mode->bits[i];
339 celt_free((int*)mode->bits[i]);
340 }
341 }
342 celt_free((int**)mode->bits);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100343 if (check_mode(mode) != CELT_OK)
344 return;
345 celt_free((int*)mode->eBands);
346 celt_free((int*)mode->pBands);
347 celt_free((int*)mode->allocVectors);
348
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100349 celt_free((celt_word16_t*)mode->window);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100350
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100351 mode->marker_start = MODEFREED;
352 mode->marker_end = MODEFREED;
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000353#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100354 psydecay_clear(&mode->psy);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100355#endif
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000356#endif
Jean-Marc Valin9656ca02008-04-11 17:23:01 +1000357 mdct_clear(&mode->mdct);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000358 quant_prob_free(mode->prob);
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100359 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100360}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100361
362int check_mode(const CELTMode *mode)
363{
364 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
365 return CELT_OK;
366 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
367 celt_warning("Using a mode that has already been freed");
368 else
369 celt_warning("This is not a valid CELT mode");
370 return CELT_INVALID_MODE;
371}