blob: 7d60016e9d2a7c6d4942aba752587dde47324a17 [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
Peter Kirk19f9dc92008-06-06 14:38:38 +020055int 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 Valin59093c02008-05-15 21:53:27 +100068 case CELT_GET_BITSTREAM_VERSION:
69 *value = CELT_BITSTREAM_VERSION;
70 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110071 default:
72 return CELT_BAD_ARG;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110073 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110074 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110075}
76
Jean-Marc Valin5588d522008-03-10 15:07:58 +110077#ifndef STATIC_MODES
78
Jean-Marc Valin134492a2008-02-18 16:46:22 +110079#define PBANDS 8
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100080
81#ifdef STDIN_TUNING
82int MIN_BINS;
83#else
Jean-Marc Valin52824c72008-05-06 18:01:17 +100084#define MIN_BINS 3
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100085#endif
86
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110087/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
88 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +110089#define BARK_BANDS 25
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110090static const celt_int16_t bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110091 0, 100, 200, 300, 400,
92 510, 630, 770, 920, 1080,
93 1270, 1480, 1720, 2000, 2320,
94 2700, 3150, 3700, 4400, 5300,
95 6400, 7700, 9500, 12000, 15500,
96 20000};
97
Jean-Marc Valin25358cd2008-02-19 12:21:32 +110098static 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 +110099
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100100/* This allocation table is per critical band. When creating a mode, the bits get added together
101 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000102
103#ifdef STDIN_TUNING
104int BITALLOC_SIZE;
105int *band_allocation;
106#else
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400107#define BITALLOC_SIZE 12
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100108static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400109 { 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,
110 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 +1000111 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,
112 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,
113 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,
114 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,
Jean-Marc Valin6855bf62008-05-07 16:44:29 +1000115 4, 3, 3, 3, 3, 3, 3, 3, 4, 4, 6, 7, 7, 9, 11, 10, 10, 9, 9, 8, 11, 10, 10, 1, 1,
116 5, 5, 4, 4, 5, 5, 5, 5, 6, 6, 8, 8, 10, 12, 15, 15, 13, 12, 12, 12, 18, 18, 16, 10, 1,
117 6, 6, 6, 6, 6, 6, 7, 7, 9, 9, 11, 12, 13, 18, 22, 23, 24, 25, 28, 30, 35, 35, 35, 35, 15,
118 7, 7, 7, 7, 7, 7, 10, 10, 10, 13, 14, 18, 20, 24, 28, 32, 32, 35, 38, 38, 42, 50, 59, 54, 31,
119 8, 8, 8, 8, 8, 9, 10, 12, 14, 20, 22, 25, 28, 30, 35, 42, 46, 50, 55, 60, 62, 62, 62, 62, 62,
Jean-Marc Valin9eba8232008-08-02 20:51:44 -0400120 12, 12, 12, 12, 12, 13, 15, 18, 22, 30, 32, 35, 40, 45, 55, 62, 66, 70, 85, 90, 92, 92, 92, 92, 92,
121 };
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000122#endif
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100123
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100124static celt_int16_t *compute_ebands(celt_int32_t Fs, int frame_size, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100125{
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100126 celt_int16_t *eBands;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100127 int i, res, min_width, lin, low, high;
128 res = (Fs+frame_size)/(2*frame_size);
129 min_width = MIN_BINS*res;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100130 /*printf ("min_width = %d\n", min_width);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100131
132 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
133 for (lin=0;lin<BARK_BANDS;lin++)
134 if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
135 break;
136
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100137 /*printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100138 low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
139 high = BARK_BANDS-lin;
140 *nbEBands = low+high;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100141 eBands = celt_alloc(sizeof(celt_int16_t)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100142
143 /* Linear spacing (min_width) */
144 for (i=0;i<low;i++)
145 eBands[i] = MIN_BINS*i;
146 /* Spacing follows critical bands */
147 for (i=0;i<high;i++)
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100148 eBands[i+low] = (bark_freq[lin+i]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100149 /* Enforce the minimum spacing at the boundary */
150 for (i=0;i<*nbEBands;i++)
151 if (eBands[i] < MIN_BINS*i)
152 eBands[i] = MIN_BINS*i;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100153 eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100154 eBands[*nbEBands+1] = frame_size;
155 if (eBands[*nbEBands] > eBands[*nbEBands+1])
156 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100157
158 /* FIXME: Remove last band if too small */
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100159 /*for (i=0;i<*nbEBands+2;i++)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100160 printf("%d ", eBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100161 printf ("\n");*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100162 return eBands;
163}
164
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100165static void compute_pbands(CELTMode *mode, int res)
166{
167 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100168 celt_int16_t *pBands;
169 pBands=celt_alloc(sizeof(celt_int16_t)*(PBANDS+2));
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100170 mode->nbPBands = PBANDS;
171 for (i=0;i<PBANDS+1;i++)
172 {
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100173 pBands[i] = (pitch_freq[i]+res/2)/res;
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100174 if (pBands[i] < mode->eBands[i])
175 pBands[i] = mode->eBands[i];
176 }
177 pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100178 for (i=1;i<mode->nbPBands+1;i++)
179 {
180 int j;
181 for (j=0;j<mode->nbEBands;j++)
182 if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
183 break;
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100184 /*printf ("%d %d\n", i, j);*/
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100185 if (mode->eBands[j] != pBands[i])
186 {
187 if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] &&
188 mode->eBands[j] != pBands[i-1])
189 pBands[i] = mode->eBands[j];
190 else
191 pBands[i] = mode->eBands[j+1];
192 }
193 }
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100194 /*for (i=0;i<mode->nbPBands+2;i++)
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100195 printf("%d ", pBands[i]);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100196 printf ("\n");*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100197 mode->pBands = pBands;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100198 mode->pitchEnd = pBands[PBANDS];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100199}
200
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100201static void compute_allocation_table(CELTMode *mode, int res)
202{
203 int i, j, eband;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400204 celt_int16_t *allocVectors, *allocEnergy;
205 const int C = CHANNELS(mode);
206
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100207 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100208 allocVectors = celt_alloc(sizeof(celt_int16_t)*(BITALLOC_SIZE*mode->nbEBands));
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400209 allocEnergy = celt_alloc(sizeof(celt_int16_t)*(mode->nbAllocVectors*(mode->nbEBands+1)));
210 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100211 for (i=0;i<BITALLOC_SIZE;i++)
212 {
213 eband = 0;
214 for (j=0;j<BARK_BANDS;j++)
215 {
Jean-Marc Valin5c0d4862008-07-24 08:49:34 -0400216 int edge, low;
217 celt_int32_t alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100218 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin13294b52008-05-30 16:07:06 +1000219 alloc = band_allocation[i*BARK_BANDS+j];
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400220 alloc = alloc*C*mode->mdctSize/256;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100221 if (edge < bark_freq[j+1])
222 {
223 int num, den;
Jean-Marc Valin13294b52008-05-30 16:07:06 +1000224 num = alloc * (edge-bark_freq[j]);
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100225 den = bark_freq[j+1]-bark_freq[j];
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100226 low = (num+den/2)/den;
227 allocVectors[i*mode->nbEBands+eband] += low;
228 eband++;
Jean-Marc Valin13294b52008-05-30 16:07:06 +1000229 allocVectors[i*mode->nbEBands+eband] += alloc-low;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100230 } else {
Jean-Marc Valin13294b52008-05-30 16:07:06 +1000231 allocVectors[i*mode->nbEBands+eband] += alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100232 }
233 }
234 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400235 /* Compute fine energy resolution and update the pulse allocation table to subtract that */
Jean-Marc Valinad637192008-05-07 13:44:39 +1000236 for (i=0;i<mode->nbAllocVectors;i++)
237 {
238 int sum = 0;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000239 for (j=0;j<mode->nbEBands;j++)
240 {
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400241 int ebits;
242 int min_bits=0;
Jean-Marc Valin504f8c22008-08-05 20:39:53 -0400243 if (allocVectors[i*mode->nbEBands+j] > 0)
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400244 min_bits = 1;
Jean-Marc Valin504f8c22008-08-05 20:39:53 -0400245 ebits = min_bits + allocVectors[i*mode->nbEBands+j] / (C*(mode->eBands[j+1]-mode->eBands[j]));
246 if (ebits>7)
247 ebits=7;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400248 /* The bits used for fine allocation can't be used for pulses */
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400249 /* However, we give two "free" bits to all modes to compensate for the fact that some energy
250 resolution is needed regardless of the frame size. */
251 if (ebits>1)
252 allocVectors[i*mode->nbEBands+j] -= C*(ebits-2);
Jean-Marc Valin504f8c22008-08-05 20:39:53 -0400253 if (allocVectors[i*mode->nbEBands+j] < 0)
254 allocVectors[i*mode->nbEBands+j] = 0;
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400255 sum += ebits;
256 allocEnergy[i*(mode->nbEBands+1)+j] = ebits;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000257 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400258 allocEnergy[i*(mode->nbEBands+1)+mode->nbEBands] = sum;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000259 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400260 mode->energy_alloc = allocEnergy;
261 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000262}
263
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400264#endif /* STATIC_MODES */
265
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000266CELTMode *celt_mode_create(celt_int32_t Fs, int channels, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100267{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000268 int i;
269#ifdef STDIN_TUNING
270 scanf("%d ", &MIN_BINS);
271 scanf("%d ", &BITALLOC_SIZE);
272 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
273 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
274 {
275 scanf("%d ", band_allocation+i);
276 }
277#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100278#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100279 const CELTMode *m = NULL;
280 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000281 ALLOC_STACK;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100282 for (i=0;i<TOTAL_MODES;i++)
283 {
284 if (Fs == static_mode_list[i]->Fs &&
285 channels == static_mode_list[i]->nbChannels &&
286 frame_size == static_mode_list[i]->mdctSize &&
287 lookahead == static_mode_list[i]->overlap)
288 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100289 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100290 break;
291 }
292 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100293 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100294 {
295 celt_warning("Mode not included as part of the static modes");
296 if (error)
297 *error = CELT_BAD_ARG;
298 return NULL;
299 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100300 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
301 CELT_COPY(mode, m, 1);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100302#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100303 int res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100304 CELTMode *mode;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100305 celt_word16_t *window;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000306 ALLOC_STACK;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100307
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100308 /* The good thing here is that permutation of the arguments will automatically be invalid */
309
310 if (Fs < 32000 || Fs > 64000)
311 {
312 celt_warning("Sampling rate must be between 32 kHz and 64 kHz");
313 if (error)
314 *error = CELT_BAD_ARG;
315 return NULL;
316 }
317 if (channels < 0 || channels > 2)
318 {
319 celt_warning("Only mono and stereo supported");
320 if (error)
321 *error = CELT_BAD_ARG;
322 return NULL;
323 }
Jean-Marc Valin96748cf2008-06-06 17:04:07 +1000324 if (frame_size < 64 || frame_size > 512 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100325 {
Jean-Marc Valin96748cf2008-06-06 17:04:07 +1000326 celt_warning("Only even frame sizes between 64 and 512 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100327 if (error)
328 *error = CELT_BAD_ARG;
329 return NULL;
330 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100331 res = (Fs+frame_size)/(2*frame_size);
332
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100333 mode = celt_alloc(sizeof(CELTMode));
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100334 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100335 mode->mdctSize = frame_size;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100336 mode->nbChannels = channels;
337 mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100338 compute_pbands(mode, res);
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100339 mode->ePredCoef = QCONST16(.8f,15);
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100340
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000341 if (frame_size <= 64)
342 {
343 mode->nbShortMdcts = 1;
344 } else if (frame_size <= 256)
345 {
346 mode->nbShortMdcts = 2;
347 } else if (frame_size <= 384)
348 {
349 mode->nbShortMdcts = 3;
350 } else {
351 mode->nbShortMdcts = 4;
352 }
353 if (mode->nbShortMdcts > 1)
354 mode->overlap = frame_size/mode->nbShortMdcts;
355 else
356 mode->overlap = frame_size/2;
357
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100358 compute_allocation_table(mode, res);
Jean-Marc Valina85657b2008-02-20 11:59:30 +1100359 /*printf ("%d bands\n", mode->nbEBands);*/
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100360
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100361 window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t));
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100362
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100363#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100364 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100365 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 +1100366#else
367 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100368 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 +1100369#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100370 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100371
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000372 mode->bits = (const celt_int16_t **)compute_alloc_cache(mode, 1);
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100373
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000374 mode->bits_stereo = NULL;
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000375#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100376 psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs);
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000377#endif
378
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100379 mode->marker_start = MODEVALID;
380 mode->marker_end = MODEVALID;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100381#endif /* !STATIC_MODES */
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100382 mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000383 mode->fft = pitch_state_alloc(MAX_PERIOD);
384
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000385 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
386 mdct_init(&mode->shortMdct, 2*mode->shortMdctSize);
387 mode->shortWindow = mode->window;
388
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000389 mode->prob = quant_prob_alloc(mode);
Jean-Marc Valinad637192008-05-07 13:44:39 +1000390
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000391 if (mode->nbChannels>=2)
392 mode->bits_stereo = (const celt_int16_t **)compute_alloc_cache(mode, mode->nbChannels);
393
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100394 if (error)
395 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100396 return mode;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100397}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100398
Peter Kirk19f9dc92008-06-06 14:38:38 +0200399void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100400{
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100401#ifndef STATIC_MODES
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100402 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100403 const celt_int16_t *prevPtr = NULL;
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100404 for (i=0;i<mode->nbEBands;i++)
405 {
406 if (mode->bits[i] != prevPtr)
407 {
408 prevPtr = mode->bits[i];
409 celt_free((int*)mode->bits[i]);
410 }
411 }
412 celt_free((int**)mode->bits);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100413 if (check_mode(mode) != CELT_OK)
414 return;
415 celt_free((int*)mode->eBands);
416 celt_free((int*)mode->pBands);
417 celt_free((int*)mode->allocVectors);
418
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100419 celt_free((celt_word16_t*)mode->window);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100420
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100421 mode->marker_start = MODEFREED;
422 mode->marker_end = MODEFREED;
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000423#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100424 psydecay_clear(&mode->psy);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100425#endif
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000426#endif
Jean-Marc Valin9656ca02008-04-11 17:23:01 +1000427 mdct_clear(&mode->mdct);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000428 pitch_state_free(mode->fft);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000429 quant_prob_free(mode->prob);
Jean-Marc Valinad637192008-05-07 13:44:39 +1000430 celt_free((celt_int16_t *)mode->energy_alloc);
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100431 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100432}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100433
434int check_mode(const CELTMode *mode)
435{
436 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
437 return CELT_OK;
438 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
439 celt_warning("Using a mode that has already been freed");
440 else
441 celt_warning("This is not a valid CELT mode");
442 return CELT_INVALID_MODE;
443}