blob: f33be53b0ba0bd8fe759f0f487866c4c0608228f [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 Valinecb36a32007-12-05 01:31:49 +110041
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110042#ifdef STATIC_MODES
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +100043#include "static_modes.c"
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110044#endif
45
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110046#define MODEVALID 0xa110ca7e
47#define MODEFREED 0xb10cf8ee
48
Jean-Marc Valind748cd52008-03-01 07:27:03 +110049#ifndef M_PI
50#define M_PI 3.141592653
51#endif
52
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110053
Jean-Marc Valin7f389062008-03-12 17:46:04 +110054int EXPORT celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110055{
56 switch (request)
57 {
58 case CELT_GET_FRAME_SIZE:
59 *value = mode->mdctSize;
60 break;
61 case CELT_GET_LOOKAHEAD:
62 *value = mode->overlap;
63 break;
Jean-Marc Valin4c6bc882008-01-31 17:34:27 +110064 case CELT_GET_NB_CHANNELS:
65 *value = mode->nbChannels;
66 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110067 default:
68 return CELT_BAD_ARG;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110069 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110070 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110071}
72
Jean-Marc Valin5588d522008-03-10 15:07:58 +110073#ifndef STATIC_MODES
74
Jean-Marc Valin134492a2008-02-18 16:46:22 +110075#define PBANDS 8
Jean-Marc Valin81a82952008-02-17 22:41:29 +110076#define MIN_BINS 4
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110077/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
78 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +110079#define BARK_BANDS 25
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110080static const celt_int16_t bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110081 0, 100, 200, 300, 400,
82 510, 630, 770, 920, 1080,
83 1270, 1480, 1720, 2000, 2320,
84 2700, 3150, 3700, 4400, 5300,
85 6400, 7700, 9500, 12000, 15500,
86 20000};
87
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110088static 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 +110089
Jean-Marc Valin75e9c862008-02-18 17:04:15 +110090/* This allocation table is per critical band. When creating a mode, the bits get added together
91 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +110092#define BITALLOC_SIZE 10
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110093static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Jean-Marc Valin9838fec2008-02-18 14:45:11 +110094 { 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 +110095 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,
96 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,
97 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,
98 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,
99 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 +1100100 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,
101 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,
102 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,
103 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,
104 };
105
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100106
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100107static celt_int16_t *compute_ebands(celt_int32_t Fs, int frame_size, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100108{
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100109 celt_int16_t *eBands;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100110 int i, res, min_width, lin, low, high;
111 res = (Fs+frame_size)/(2*frame_size);
112 min_width = MIN_BINS*res;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100113 /*printf ("min_width = %d\n", min_width);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100114
115 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
116 for (lin=0;lin<BARK_BANDS;lin++)
117 if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
118 break;
119
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100120 /*printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100121 low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
122 high = BARK_BANDS-lin;
123 *nbEBands = low+high;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100124 eBands = celt_alloc(sizeof(celt_int16_t)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100125
126 /* Linear spacing (min_width) */
127 for (i=0;i<low;i++)
128 eBands[i] = MIN_BINS*i;
129 /* Spacing follows critical bands */
130 for (i=0;i<high;i++)
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100131 eBands[i+low] = (bark_freq[lin+i]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100132 /* Enforce the minimum spacing at the boundary */
133 for (i=0;i<*nbEBands;i++)
134 if (eBands[i] < MIN_BINS*i)
135 eBands[i] = MIN_BINS*i;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100136 eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100137 eBands[*nbEBands+1] = frame_size;
138 if (eBands[*nbEBands] > eBands[*nbEBands+1])
139 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100140
141 /* FIXME: Remove last band if too small */
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100142 /*for (i=0;i<*nbEBands+2;i++)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100143 printf("%d ", eBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100144 printf ("\n");*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100145 return eBands;
146}
147
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100148static void compute_pbands(CELTMode *mode, int res)
149{
150 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100151 celt_int16_t *pBands;
152 pBands=celt_alloc(sizeof(celt_int16_t)*(PBANDS+2));
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100153 mode->nbPBands = PBANDS;
154 for (i=0;i<PBANDS+1;i++)
155 {
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100156 pBands[i] = (pitch_freq[i]+res/2)/res;
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100157 if (pBands[i] < mode->eBands[i])
158 pBands[i] = mode->eBands[i];
159 }
160 pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100161 for (i=1;i<mode->nbPBands+1;i++)
162 {
163 int j;
164 for (j=0;j<mode->nbEBands;j++)
165 if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
166 break;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100167 /*printf ("%d %d\n", i, j);*/
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100168 if (mode->eBands[j] != pBands[i])
169 {
170 if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] &&
171 mode->eBands[j] != pBands[i-1])
172 pBands[i] = mode->eBands[j];
173 else
174 pBands[i] = mode->eBands[j+1];
175 }
176 }
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100177 /*for (i=0;i<mode->nbPBands+2;i++)
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100178 printf("%d ", pBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100179 printf ("\n");*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100180 mode->pBands = pBands;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100181 mode->pitchEnd = pBands[PBANDS];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100182}
183
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100184static void compute_allocation_table(CELTMode *mode, int res)
185{
186 int i, j, eband;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100187 celt_int16_t *allocVectors;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100188
189 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100190 allocVectors = celt_alloc(sizeof(celt_int16_t)*(BITALLOC_SIZE*mode->nbEBands));
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100191 for (i=0;i<BITALLOC_SIZE;i++)
192 {
193 eband = 0;
194 for (j=0;j<BARK_BANDS;j++)
195 {
196 int edge, low;
197 edge = mode->eBands[eband+1]*res;
198 if (edge < bark_freq[j+1])
199 {
200 int num, den;
201 num = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j]);
202 den = bark_freq[j+1]-bark_freq[j];
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100203 low = (num+den/2)/den;
204 allocVectors[i*mode->nbEBands+eband] += low;
205 eband++;
206 allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]-low;
207 } else {
208 allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j];
209 }
210 }
211 }
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100212 /*for (i=0;i<BITALLOC_SIZE;i++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100213 {
214 for (j=0;j<mode->nbEBands;j++)
215 printf ("%2d ", allocVectors[i*mode->nbEBands+j]);
216 printf ("\n");
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100217 }*/
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100218 mode->allocVectors = allocVectors;
219}
220
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100221#endif /* STATIC_MODES */
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100222
Jean-Marc Valin7f389062008-03-12 17:46:04 +1100223CELTMode 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 +1100224{
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100225#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100226 const CELTMode *m = NULL;
227 CELTMode *mode=NULL;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100228 int i;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000229 ALLOC_STACK;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100230 for (i=0;i<TOTAL_MODES;i++)
231 {
232 if (Fs == static_mode_list[i]->Fs &&
233 channels == static_mode_list[i]->nbChannels &&
234 frame_size == static_mode_list[i]->mdctSize &&
235 lookahead == static_mode_list[i]->overlap)
236 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100237 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100238 break;
239 }
240 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100241 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100242 {
243 celt_warning("Mode not included as part of the static modes");
244 if (error)
245 *error = CELT_BAD_ARG;
246 return NULL;
247 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100248 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
249 CELT_COPY(mode, m, 1);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100250#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100251 int res;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100252 int i;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100253 CELTMode *mode;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100254 celt_word16_t *window;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000255 ALLOC_STACK;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100256
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100257 /* The good thing here is that permutation of the arguments will automatically be invalid */
258
259 if (Fs < 32000 || Fs > 64000)
260 {
261 celt_warning("Sampling rate must be between 32 kHz and 64 kHz");
262 if (error)
263 *error = CELT_BAD_ARG;
264 return NULL;
265 }
266 if (channels < 0 || channels > 2)
267 {
268 celt_warning("Only mono and stereo supported");
269 if (error)
270 *error = CELT_BAD_ARG;
271 return NULL;
272 }
273 if (frame_size < 64 || frame_size > 256 || frame_size%2!=0)
274 {
275 celt_warning("Only even frame sizes between 64 and 256 are supported");
276 if (error)
277 *error = CELT_BAD_ARG;
278 return NULL;
279 }
280 if (lookahead < 32 || lookahead > frame_size)
281 {
282 celt_warning("The overlap must be between 32 and the frame size");
283 if (error)
284 *error = CELT_BAD_ARG;
285 return NULL;
286 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100287 res = (Fs+frame_size)/(2*frame_size);
288
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100289 mode = celt_alloc(sizeof(CELTMode));
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100290 mode->Fs = Fs;
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100291 mode->overlap = lookahead;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100292 mode->mdctSize = frame_size;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100293 mode->nbChannels = channels;
294 mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100295 compute_pbands(mode, res);
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100296 mode->ePredCoef = QCONST16(.8f,15);
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100297
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100298 compute_allocation_table(mode, res);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100299 /*printf ("%d bands\n", mode->nbEBands);*/
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100300
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100301 window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100302
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100303#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100304 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100305 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 +1100306#else
307 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100308 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 +1100309#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100310 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100311
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100312 compute_alloc_cache(mode);
313
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100314 psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs);
315
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100316 mode->marker_start = MODEVALID;
317 mode->marker_end = MODEVALID;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100318#endif /* !STATIC_MODES */
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100319 mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100320 if (error)
321 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100322 return mode;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100323}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100324
Jean-Marc Valin7f389062008-03-12 17:46:04 +1100325void EXPORT celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100326{
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100327#ifndef STATIC_MODES
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100328 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100329 const celt_int16_t *prevPtr = NULL;
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100330 for (i=0;i<mode->nbEBands;i++)
331 {
332 if (mode->bits[i] != prevPtr)
333 {
334 prevPtr = mode->bits[i];
335 celt_free((int*)mode->bits[i]);
336 }
337 }
338 celt_free((int**)mode->bits);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100339 if (check_mode(mode) != CELT_OK)
340 return;
341 celt_free((int*)mode->eBands);
342 celt_free((int*)mode->pBands);
343 celt_free((int*)mode->allocVectors);
344
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100345 celt_free((celt_word16_t*)mode->window);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100346
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100347 mode->marker_start = MODEFREED;
348 mode->marker_end = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100349 psydecay_clear(&mode->psy);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100350#endif
Jean-Marc Valin9656ca02008-04-11 17:23:01 +1000351 mdct_clear(&mode->mdct);
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100352 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100353}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100354
355int check_mode(const CELTMode *mode)
356{
357 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
358 return CELT_OK;
359 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
360 celt_warning("Using a mode that has already been freed");
361 else
362 celt_warning("This is not a valid CELT mode");
363 return CELT_INVALID_MODE;
364}