blob: ab94404ecba30b4c412bb985907921578b103971 [file] [log] [blame]
Gregory Maxwell54547f12009-02-16 18:56:44 -05001/* (C) 2007-2009 Jean-Marc Valin, CSIRO
Gregory Maxwellfea148f2009-02-03 20:46:53 -05002 (C) 2008 Gregory Maxwell */
Jean-Marc Valinecb36a32007-12-05 01:31:49 +11003/*
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
Gregory Maxwelldc67fa92009-06-04 17:17:35 -040047#define MODEVALID 0xa110ca7e
48#define MODEPARTIAL 0x7eca10a1
49#define MODEFREED 0xb10cf8ee
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110050
Jean-Marc Valind748cd52008-03-01 07:27:03 +110051#ifndef M_PI
52#define M_PI 3.141592653
53#endif
54
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110055
Peter Kirk19f9dc92008-06-06 14:38:38 +020056int celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110057{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -040058 if (check_mode(mode) != CELT_OK)
59 return CELT_INVALID_MODE;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110060 switch (request)
61 {
62 case CELT_GET_FRAME_SIZE:
63 *value = mode->mdctSize;
64 break;
65 case CELT_GET_LOOKAHEAD:
66 *value = mode->overlap;
67 break;
Jean-Marc Valin4c6bc882008-01-31 17:34:27 +110068 case CELT_GET_NB_CHANNELS:
69 *value = mode->nbChannels;
70 break;
Jean-Marc Valin59093c02008-05-15 21:53:27 +100071 case CELT_GET_BITSTREAM_VERSION:
72 *value = CELT_BITSTREAM_VERSION;
73 break;
Gregory Maxwelld9458cd2009-05-30 17:04:02 -040074 case CELT_GET_SAMPLE_RATE:
75 *value = mode->Fs;
76 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110077 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040078 return CELT_UNIMPLEMENTED;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110079 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110080 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110081}
82
Jean-Marc Valin5588d522008-03-10 15:07:58 +110083#ifndef STATIC_MODES
84
Jean-Marc Valin134492a2008-02-18 16:46:22 +110085#define PBANDS 8
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100086
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] =
Christopher Montgomery8e511a82009-07-03 02:10:17 -0400109 /* 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 */
110 { 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*/
111 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*/
112 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*/
113 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*/
114 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*/
115 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*/
116 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*/
117 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*/
118 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*/
119 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*/
120 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*/
121 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 -0400122 };
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000123#endif
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100124
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400125static celt_int16_t *compute_ebands(celt_int32_t Fs, int frame_size, int nbShortMdcts, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100126{
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400127 int min_bins = 2;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100128 celt_int16_t *eBands;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400129 int i, res, min_width, lin, low, high, nBark;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400130
131 if (min_bins < nbShortMdcts)
132 min_bins = nbShortMdcts;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100133 res = (Fs+frame_size)/(2*frame_size);
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400134 min_width = min_bins*res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100135
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400136 /* Find the number of critical bands supported by our sampling rate */
137 for (nBark=1;nBark<BARK_BANDS;nBark++)
138 if (bark_freq[nBark+1]*2 >= Fs)
139 break;
140
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100141 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400142 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100143 if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
144 break;
145
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400146 low = ((bark_freq[lin]/res)+(min_bins-1))/min_bins;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400147 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100148 *nbEBands = low+high;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100149 eBands = celt_alloc(sizeof(celt_int16_t)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100150
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400151 if (eBands==NULL)
152 return NULL;
153
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100154 /* Linear spacing (min_width) */
155 for (i=0;i<low;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400156 eBands[i] = min_bins*i;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100157 /* Spacing follows critical bands */
158 for (i=0;i<high;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400159 eBands[i+low] = (bark_freq[lin+i]+res/2)/res/nbShortMdcts*nbShortMdcts;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100160 /* Enforce the minimum spacing at the boundary */
161 for (i=0;i<*nbEBands;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400162 if (eBands[i] < min_bins*i)
163 eBands[i] = min_bins*i;
164 eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res/nbShortMdcts*nbShortMdcts;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100165 eBands[*nbEBands+1] = frame_size;
166 if (eBands[*nbEBands] > eBands[*nbEBands+1])
167 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400168 for (i=1;i<*nbEBands-1;i++)
169 {
170 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
171 {
172 eBands[i] -= min_bins;
173 }
174 }
175 /*for (i=0;i<*nbEBands+1;i++)
176 printf ("%d ", eBands[i]);
177 printf ("\n");*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100178 /* FIXME: Remove last band if too small */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100179 return eBands;
180}
181
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100182static void compute_pbands(CELTMode *mode, int res)
183{
184 int i;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100185 celt_int16_t *pBands;
186 pBands=celt_alloc(sizeof(celt_int16_t)*(PBANDS+2));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400187 mode->pBands = pBands;
188 if (pBands==NULL)
189 return;
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100190 mode->nbPBands = PBANDS;
191 for (i=0;i<PBANDS+1;i++)
192 {
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100193 pBands[i] = (pitch_freq[i]+res/2)/res;
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100194 if (pBands[i] < mode->eBands[i])
195 pBands[i] = mode->eBands[i];
196 }
197 pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100198 for (i=1;i<mode->nbPBands+1;i++)
199 {
200 int j;
201 for (j=0;j<mode->nbEBands;j++)
202 if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
203 break;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100204 if (mode->eBands[j] != pBands[i])
205 {
206 if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] &&
207 mode->eBands[j] != pBands[i-1])
208 pBands[i] = mode->eBands[j];
209 else
210 pBands[i] = mode->eBands[j+1];
211 }
212 }
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100213 mode->pitchEnd = pBands[PBANDS];
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100214}
215
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100216static void compute_allocation_table(CELTMode *mode, int res)
217{
Gregory Maxwellec836da2009-05-04 14:55:40 -0400218 int i, j, nBark;
Jean-Marc Valin18c1c222009-05-30 09:50:47 -0400219 celt_int16_t *allocVectors;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400220 const int C = CHANNELS(mode);
221
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400222 /* Find the number of critical bands supported by our sampling rate */
223 for (nBark=1;nBark<BARK_BANDS;nBark++)
224 if (bark_freq[nBark+1]*2 >= mode->Fs)
225 break;
226
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100227 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valindb0141e2008-03-10 16:37:37 +1100228 allocVectors = celt_alloc(sizeof(celt_int16_t)*(BITALLOC_SIZE*mode->nbEBands));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400229 if (allocVectors==NULL)
230 return;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400231 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100232 for (i=0;i<BITALLOC_SIZE;i++)
233 {
Gregory Maxwellec836da2009-05-04 14:55:40 -0400234 celt_int32_t current = 0;
235 int eband = 0;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400236 for (j=0;j<nBark;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100237 {
Jean-Marc Valin5c0d4862008-07-24 08:49:34 -0400238 int edge, low;
239 celt_int32_t alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100240 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin13294b52008-05-30 16:07:06 +1000241 alloc = band_allocation[i*BARK_BANDS+j];
Gregory Maxwellec836da2009-05-04 14:55:40 -0400242 alloc = alloc*C*mode->mdctSize;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100243 if (edge < bark_freq[j+1])
244 {
245 int num, den;
Jean-Marc Valin13294b52008-05-30 16:07:06 +1000246 num = alloc * (edge-bark_freq[j]);
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100247 den = bark_freq[j+1]-bark_freq[j];
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100248 low = (num+den/2)/den;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400249 allocVectors[i*mode->nbEBands+eband] = (current+low+128)/256;
250 current=0;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100251 eband++;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400252 current += alloc-low;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100253 } else {
Gregory Maxwellec836da2009-05-04 14:55:40 -0400254 current += alloc;
255 }
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100256 }
Gregory Maxwellec836da2009-05-04 14:55:40 -0400257 allocVectors[i*mode->nbEBands+eband] = (current+128)/256;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100258 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400259 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000260}
261
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400262#endif /* STATIC_MODES */
263
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000264CELTMode *celt_mode_create(celt_int32_t Fs, int channels, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100265{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000266 int i;
267#ifdef STDIN_TUNING
268 scanf("%d ", &MIN_BINS);
269 scanf("%d ", &BITALLOC_SIZE);
270 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
271 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
272 {
273 scanf("%d ", band_allocation+i);
274 }
275#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100276#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100277 const CELTMode *m = NULL;
278 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000279 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400280#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
281 if (global_stack==NULL)
282 {
283 celt_free(global_stack);
284 goto failure;
285 }
286#endif
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100287 for (i=0;i<TOTAL_MODES;i++)
288 {
289 if (Fs == static_mode_list[i]->Fs &&
290 channels == static_mode_list[i]->nbChannels &&
Jean-Marc Valin60d08372008-10-03 07:30:08 -0400291 frame_size == static_mode_list[i]->mdctSize)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100292 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100293 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100294 break;
295 }
296 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100297 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100298 {
299 celt_warning("Mode not included as part of the static modes");
300 if (error)
301 *error = CELT_BAD_ARG;
302 return NULL;
303 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100304 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400305 if (mode==NULL)
306 goto failure;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100307 CELT_COPY(mode, m, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400308 mode->marker_start = MODEPARTIAL;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100309#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100310 int res;
Gregory Maxwell84966952009-06-30 01:06:04 -0400311 CELTMode *mode=NULL;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100312 celt_word16_t *window;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000313 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400314#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
315 if (global_stack==NULL)
316 {
317 celt_free(global_stack);
318 goto failure;
319 }
320#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100321
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100322 /* The good thing here is that permutation of the arguments will automatically be invalid */
323
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500324 if (Fs < 32000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100325 {
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500326 celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100327 if (error)
328 *error = CELT_BAD_ARG;
329 return NULL;
330 }
331 if (channels < 0 || channels > 2)
332 {
333 celt_warning("Only mono and stereo supported");
334 if (error)
335 *error = CELT_BAD_ARG;
336 return NULL;
337 }
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400338 if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100339 {
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400340 celt_warning("Only even frame sizes from 64 to 1024 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100341 if (error)
342 *error = CELT_BAD_ARG;
343 return NULL;
344 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100345 res = (Fs+frame_size)/(2*frame_size);
346
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100347 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400348 if (mode==NULL)
349 goto failure;
350 mode->marker_start = MODEPARTIAL;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100351 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100352 mode->mdctSize = frame_size;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100353 mode->nbChannels = channels;
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100354 mode->ePredCoef = QCONST16(.8f,15);
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400355
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400356 if (frame_size > 640 && (frame_size%16)==0)
357 {
358 mode->nbShortMdcts = 8;
359 } else if (frame_size > 384 && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000360 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400361 mode->nbShortMdcts = 4;
362 } else if (frame_size > 384 && (frame_size%10)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000363 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400364 mode->nbShortMdcts = 5;
365 } else if (frame_size > 256 && (frame_size%6)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000366 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400367 mode->nbShortMdcts = 3;
368 } else if (frame_size > 256 && (frame_size%8)==0)
369 {
370 mode->nbShortMdcts = 4;
371 } else if (frame_size > 64 && (frame_size%4)==0)
372 {
373 mode->nbShortMdcts = 2;
374 } else if (frame_size > 128 && (frame_size%6)==0)
375 {
376 mode->nbShortMdcts = 3;
377 } else
378 {
379 mode->nbShortMdcts = 1;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000380 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400381
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400382 mode->eBands = compute_ebands(Fs, frame_size, mode->nbShortMdcts, &mode->nbEBands);
383 if (mode->eBands==NULL)
384 goto failure;
385 compute_pbands(mode, res);
386 if (mode->pBands==NULL)
387 goto failure;
388
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400389 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000390 if (mode->nbShortMdcts > 1)
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400391 mode->overlap = ((frame_size/mode->nbShortMdcts)>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000392 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400393 mode->overlap = (frame_size>>3)<<2;
394
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100395 compute_allocation_table(mode, res);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400396 if (mode->allocVectors==NULL)
397 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100398
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100399 window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400400 if (window==NULL)
401 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100402
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100403#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100404 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100405 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 +1100406#else
407 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100408 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 +1100409#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100410 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100411
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000412 mode->bits = (const celt_int16_t **)compute_alloc_cache(mode, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400413 if (mode->bits==NULL)
414 goto failure;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100415
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000416#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100417 psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400418 if (mode->psy.decayR==NULL)
419 goto failure;
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000420#endif
421
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100422#endif /* !STATIC_MODES */
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400423
424#ifdef DISABLE_STEREO
425 if (channels > 1)
426 {
427 celt_warning("Stereo support was disable from this build");
428 if (error)
429 *error = CELT_BAD_ARG;
430 return NULL;
431 }
432#endif
433
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100434 mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000435 mode->fft = pitch_state_alloc(MAX_PERIOD);
436
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000437 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
438 mdct_init(&mode->shortMdct, 2*mode->shortMdctSize);
439 mode->shortWindow = mode->window;
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000440 mode->prob = quant_prob_alloc(mode);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400441 if ((mode->mdct.trig==NULL) || (mode->mdct.kfft==NULL) || (mode->fft==NULL) ||
442 (mode->shortMdct.trig==NULL) || (mode->shortMdct.kfft==NULL) || (mode->prob==NULL))
443 goto failure;
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000444
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400445 mode->marker_start = MODEVALID;
446 mode->marker_end = MODEVALID;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100447 if (error)
448 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100449 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400450failure:
451 if (error)
452 *error = CELT_INVALID_MODE;
453 if (mode!=NULL)
454 celt_mode_destroy(mode);
455 return NULL;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100456}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100457
Peter Kirk19f9dc92008-06-06 14:38:38 +0200458void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100459{
Jean-Marc Valinf43488c2009-06-05 11:07:31 -0400460 int i;
461 const celt_int16_t *prevPtr = NULL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400462 if (mode == NULL)
463 {
464 celt_warning("NULL passed to celt_mode_destroy");
465 return;
466 }
467
468 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
469 {
470 celt_warning("Freeing a mode which has already been freed");
471 return;
472 }
473
474 if (mode->marker_start != MODEVALID && mode->marker_start != MODEPARTIAL)
475 {
476 celt_warning("This is not a valid CELT mode structure");
477 return;
478 }
479 mode->marker_start = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100480#ifndef STATIC_MODES
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400481 if (mode->bits!=NULL)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100482 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400483 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100484 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400485 if (mode->bits[i] != prevPtr)
486 {
487 prevPtr = mode->bits[i];
488 celt_free((int*)mode->bits[i]);
489 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100490 }
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400491 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100492 celt_free((int**)mode->bits);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100493 celt_free((int*)mode->eBands);
494 celt_free((int*)mode->pBands);
495 celt_free((int*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400496
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100497 celt_free((celt_word16_t*)mode->window);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100498
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000499#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100500 psydecay_clear(&mode->psy);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100501#endif
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000502#endif
Jean-Marc Valin9656ca02008-04-11 17:23:01 +1000503 mdct_clear(&mode->mdct);
Jean-Marc Valinc9943942008-08-30 00:55:07 -0400504 mdct_clear(&mode->shortMdct);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000505 pitch_state_free(mode->fft);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000506 quant_prob_free(mode->prob);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400507 mode->marker_end = MODEFREED;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100508 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100509}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100510
511int check_mode(const CELTMode *mode)
512{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400513 if (mode==NULL)
514 return CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100515 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
516 return CELT_OK;
517 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
518 celt_warning("Using a mode that has already been freed");
519 else
520 celt_warning("This is not a valid CELT mode");
521 return CELT_INVALID_MODE;
522}