blob: af0d6caca7151f8bdcf18af3015ac233a03cdadc [file] [log] [blame]
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04001/* Copyright (c) 2007-2008 CSIRO
2 Copyright (c) 2007-2009 Xiph.Org Foundation
3 Copyright (c) 2008 Gregory Maxwell
4 Written by Jean-Marc Valin and Gregory Maxwell */
Jean-Marc Valinecb36a32007-12-05 01:31:49 +11005/*
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12
13 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16
17 - Neither the name of the Xiph.org Foundation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110034#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
Jean-Marc Valin65d57e62008-02-18 15:49:37 +110038#include "celt.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110039#include "modes.h"
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110040#include "rate.h"
Jean-Marc Valin81a82952008-02-17 22:41:29 +110041#include "os_support.h"
Jean-Marc Valinf7cec832008-04-18 17:29:56 +100042#include "stack_alloc.h"
Jean-Marc Valin4ce92052008-04-23 13:42:10 +100043#include "quant_bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110044
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110045#ifdef STATIC_MODES
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +100046#include "static_modes.c"
Jean-Marc Valinf39e8692008-03-10 12:13:23 +110047#endif
48
Gregory Maxwelldc67fa92009-06-04 17:17:35 -040049#define MODEVALID 0xa110ca7e
50#define MODEPARTIAL 0x7eca10a1
51#define MODEFREED 0xb10cf8ee
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110052
Jean-Marc Valind748cd52008-03-01 07:27:03 +110053#ifndef M_PI
54#define M_PI 3.141592653
55#endif
56
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +110057
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040058int celt_mode_info(const CELTMode *mode, int request, celt_int32 *value)
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110059{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -040060 if (check_mode(mode) != CELT_OK)
61 return CELT_INVALID_MODE;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110062 switch (request)
63 {
64 case CELT_GET_FRAME_SIZE:
65 *value = mode->mdctSize;
66 break;
67 case CELT_GET_LOOKAHEAD:
68 *value = mode->overlap;
69 break;
Jean-Marc Valin59093c02008-05-15 21:53:27 +100070 case CELT_GET_BITSTREAM_VERSION:
71 *value = CELT_BITSTREAM_VERSION;
72 break;
Gregory Maxwelld9458cd2009-05-30 17:04:02 -040073 case CELT_GET_SAMPLE_RATE:
74 *value = mode->Fs;
75 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110076 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040077 return CELT_UNIMPLEMENTED;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110078 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110079 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110080}
81
Jean-Marc Valin5588d522008-03-10 15:07:58 +110082#ifndef STATIC_MODES
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 Valin30f7f812009-10-17 14:35:13 -040087static const celt_int16 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 Valin75e9c862008-02-18 17:04:15 +110095/* This allocation table is per critical band. When creating a mode, the bits get added together
96 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100097
98#ifdef STDIN_TUNING
99int BITALLOC_SIZE;
100int *band_allocation;
101#else
Jean-Marc Valin9c709062008-08-03 22:07:06 -0400102#define BITALLOC_SIZE 12
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100103static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Christopher Montgomery8e511a82009-07-03 02:10:17 -0400104 /* 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 */
105 { 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*/
106 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*/
107 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*/
108 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*/
109 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*/
110 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*/
111 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*/
112 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*/
113 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*/
114 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*/
115 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*/
116 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 -0400117 };
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000118#endif
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100119
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400120static celt_int16 *compute_ebands(celt_int32 Fs, int frame_size, int nbShortMdcts, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100121{
Jean-Marc Valin6db9e6e2009-09-29 23:16:26 -0400122 int min_bins = 3;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400123 celt_int16 *eBands;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400124 int i, res, min_width, lin, low, high, nBark, offset=0;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400125
Jean-Marc Valind5e54362009-09-30 20:50:41 -0400126 /*if (min_bins < nbShortMdcts)
127 min_bins = nbShortMdcts;*/
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100128 res = (Fs+frame_size)/(2*frame_size);
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400129 min_width = min_bins*res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100130
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400131 /* Find the number of critical bands supported by our sampling rate */
132 for (nBark=1;nBark<BARK_BANDS;nBark++)
133 if (bark_freq[nBark+1]*2 >= Fs)
134 break;
135
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100136 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400137 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100138 if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
139 break;
140
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400141 low = ((bark_freq[lin]/res)+(min_bins-1))/min_bins;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400142 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100143 *nbEBands = low+high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400144 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100145
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400146 if (eBands==NULL)
147 return NULL;
148
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100149 /* Linear spacing (min_width) */
150 for (i=0;i<low;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400151 eBands[i] = min_bins*i;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100152 /* Spacing follows critical bands */
153 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400154 {
155 int target = bark_freq[lin+i];
156 eBands[i+low] = (2*target+offset+res)/(2*res);
157 offset = eBands[i+low]*res - target;
158 }
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100159 /* Enforce the minimum spacing at the boundary */
160 for (i=0;i<*nbEBands;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400161 if (eBands[i] < min_bins*i)
162 eBands[i] = min_bins*i;
Jean-Marc Valin6db9e6e2009-09-29 23:16:26 -0400163 eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100164 eBands[*nbEBands+1] = frame_size;
165 if (eBands[*nbEBands] > eBands[*nbEBands+1])
166 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400167 for (i=1;i<*nbEBands-1;i++)
168 {
169 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
170 {
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400171 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1]+1)/2;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400172 }
173 }
174 /*for (i=0;i<*nbEBands+1;i++)
175 printf ("%d ", eBands[i]);
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400176 printf ("\n");
177 exit(1);*/
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 Valin9838fec2008-02-18 14:45:11 +1100182static void compute_allocation_table(CELTMode *mode, int res)
183{
Gregory Maxwellec836da2009-05-04 14:55:40 -0400184 int i, j, nBark;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400185 celt_int16 *allocVectors;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400186
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400187 /* Find the number of critical bands supported by our sampling rate */
188 for (nBark=1;nBark<BARK_BANDS;nBark++)
189 if (bark_freq[nBark+1]*2 >= mode->Fs)
190 break;
191
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100192 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400193 allocVectors = celt_alloc(sizeof(celt_int16)*(BITALLOC_SIZE*mode->nbEBands));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400194 if (allocVectors==NULL)
195 return;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400196 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100197 for (i=0;i<BITALLOC_SIZE;i++)
198 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400199 celt_int32 current = 0;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400200 int eband = 0;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400201 for (j=0;j<nBark;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100202 {
Jean-Marc Valin5c0d4862008-07-24 08:49:34 -0400203 int edge, low;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400204 celt_int32 alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100205 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin6a978022009-10-13 20:35:21 -0400206 alloc = mode->mdctSize*band_allocation[i*BARK_BANDS+j];
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100207 if (edge < bark_freq[j+1])
208 {
209 int num, den;
Jean-Marc Valin13294b52008-05-30 16:07:06 +1000210 num = alloc * (edge-bark_freq[j]);
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100211 den = bark_freq[j+1]-bark_freq[j];
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100212 low = (num+den/2)/den;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400213 allocVectors[i*mode->nbEBands+eband] = (current+low+128)/256;
214 current=0;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100215 eband++;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400216 current += alloc-low;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100217 } else {
Gregory Maxwellec836da2009-05-04 14:55:40 -0400218 current += alloc;
219 }
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100220 }
Gregory Maxwellec836da2009-05-04 14:55:40 -0400221 allocVectors[i*mode->nbEBands+eband] = (current+128)/256;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100222 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400223 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000224}
225
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400226#endif /* STATIC_MODES */
227
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400228CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100229{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000230 int i;
231#ifdef STDIN_TUNING
232 scanf("%d ", &MIN_BINS);
233 scanf("%d ", &BITALLOC_SIZE);
234 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
235 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
236 {
237 scanf("%d ", band_allocation+i);
238 }
239#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100240#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100241 const CELTMode *m = NULL;
242 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000243 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400244#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
245 if (global_stack==NULL)
246 {
247 celt_free(global_stack);
248 goto failure;
249 }
250#endif
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100251 for (i=0;i<TOTAL_MODES;i++)
252 {
253 if (Fs == static_mode_list[i]->Fs &&
Jean-Marc Valin60d08372008-10-03 07:30:08 -0400254 frame_size == static_mode_list[i]->mdctSize)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100255 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100256 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100257 break;
258 }
259 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100260 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100261 {
262 celt_warning("Mode not included as part of the static modes");
263 if (error)
264 *error = CELT_BAD_ARG;
265 return NULL;
266 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100267 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400268 if (mode==NULL)
269 goto failure;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100270 CELT_COPY(mode, m, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400271 mode->marker_start = MODEPARTIAL;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100272#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100273 int res;
Gregory Maxwell84966952009-06-30 01:06:04 -0400274 CELTMode *mode=NULL;
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100275 celt_word16_t *window;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000276 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400277#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
278 if (global_stack==NULL)
279 {
280 celt_free(global_stack);
281 goto failure;
282 }
283#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100284
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100285 /* The good thing here is that permutation of the arguments will automatically be invalid */
286
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500287 if (Fs < 32000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100288 {
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500289 celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100290 if (error)
291 *error = CELT_BAD_ARG;
292 return NULL;
293 }
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400294 if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100295 {
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400296 celt_warning("Only even frame sizes from 64 to 1024 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100297 if (error)
298 *error = CELT_BAD_ARG;
299 return NULL;
300 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100301 res = (Fs+frame_size)/(2*frame_size);
302
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100303 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400304 if (mode==NULL)
305 goto failure;
306 mode->marker_start = MODEPARTIAL;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100307 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100308 mode->mdctSize = frame_size;
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100309 mode->ePredCoef = QCONST16(.8f,15);
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400310
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400311 if (frame_size > 640 && (frame_size%16)==0)
312 {
313 mode->nbShortMdcts = 8;
314 } else if (frame_size > 384 && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000315 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400316 mode->nbShortMdcts = 4;
317 } else if (frame_size > 384 && (frame_size%10)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000318 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400319 mode->nbShortMdcts = 5;
320 } else if (frame_size > 256 && (frame_size%6)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000321 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400322 mode->nbShortMdcts = 3;
323 } else if (frame_size > 256 && (frame_size%8)==0)
324 {
325 mode->nbShortMdcts = 4;
326 } else if (frame_size > 64 && (frame_size%4)==0)
327 {
328 mode->nbShortMdcts = 2;
329 } else if (frame_size > 128 && (frame_size%6)==0)
330 {
331 mode->nbShortMdcts = 3;
332 } else
333 {
334 mode->nbShortMdcts = 1;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000335 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400336
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400337 mode->eBands = compute_ebands(Fs, frame_size, mode->nbShortMdcts, &mode->nbEBands);
338 if (mode->eBands==NULL)
339 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400340
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400341 mode->pitchEnd = 4000*(celt_int32)frame_size/Fs;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400342
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400343 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000344 if (mode->nbShortMdcts > 1)
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400345 mode->overlap = ((frame_size/mode->nbShortMdcts)>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000346 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400347 mode->overlap = (frame_size>>3)<<2;
348
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100349 compute_allocation_table(mode, res);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400350 if (mode->allocVectors==NULL)
351 goto failure;
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));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400354 if (window==NULL)
355 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100356
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100357#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100358 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100359 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 +1100360#else
361 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100362 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 +1100363#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100364 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100365
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400366 mode->bits = (const celt_int16 **)compute_alloc_cache(mode, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400367 if (mode->bits==NULL)
368 goto failure;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100369
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000370#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100371 psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400372 if (mode->psy.decayR==NULL)
373 goto failure;
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000374#endif
375
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100376#endif /* !STATIC_MODES */
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400377
378#ifdef DISABLE_STEREO
379 if (channels > 1)
380 {
381 celt_warning("Stereo support was disable from this build");
382 if (error)
383 *error = CELT_BAD_ARG;
384 return NULL;
385 }
386#endif
387
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100388 mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000389 mode->fft = pitch_state_alloc(MAX_PERIOD);
390
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000391 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
392 mdct_init(&mode->shortMdct, 2*mode->shortMdctSize);
393 mode->shortWindow = mode->window;
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000394 mode->prob = quant_prob_alloc(mode);
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400395 if ((mode->mdct.trig==NULL) || (mode->shortMdct.trig==NULL)
396#ifndef ENABLE_TI_DSPLIB55
397 || (mode->mdct.kfft==NULL) || (mode->fft==NULL) || (mode->shortMdct.kfft==NULL)
398#endif
399 || (mode->prob==NULL))
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400400 goto failure;
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000401
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400402 mode->marker_start = MODEVALID;
403 mode->marker_end = MODEVALID;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100404 if (error)
405 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100406 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400407failure:
408 if (error)
409 *error = CELT_INVALID_MODE;
410 if (mode!=NULL)
411 celt_mode_destroy(mode);
412 return NULL;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100413}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100414
Peter Kirk19f9dc92008-06-06 14:38:38 +0200415void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100416{
Jean-Marc Valinf43488c2009-06-05 11:07:31 -0400417 int i;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400418 const celt_int16 *prevPtr = NULL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400419 if (mode == NULL)
420 {
421 celt_warning("NULL passed to celt_mode_destroy");
422 return;
423 }
424
425 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
426 {
427 celt_warning("Freeing a mode which has already been freed");
428 return;
429 }
430
431 if (mode->marker_start != MODEVALID && mode->marker_start != MODEPARTIAL)
432 {
433 celt_warning("This is not a valid CELT mode structure");
434 return;
435 }
436 mode->marker_start = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100437#ifndef STATIC_MODES
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400438 if (mode->bits!=NULL)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100439 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400440 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100441 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400442 if (mode->bits[i] != prevPtr)
443 {
444 prevPtr = mode->bits[i];
445 celt_free((int*)mode->bits[i]);
446 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100447 }
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400448 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100449 celt_free((int**)mode->bits);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100450 celt_free((int*)mode->eBands);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100451 celt_free((int*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400452
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100453 celt_free((celt_word16_t*)mode->window);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100454
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000455#ifndef SHORTCUTS
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100456 psydecay_clear(&mode->psy);
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100457#endif
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000458#endif
Jean-Marc Valin9656ca02008-04-11 17:23:01 +1000459 mdct_clear(&mode->mdct);
Jean-Marc Valinc9943942008-08-30 00:55:07 -0400460 mdct_clear(&mode->shortMdct);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000461 pitch_state_free(mode->fft);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000462 quant_prob_free(mode->prob);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400463 mode->marker_end = MODEFREED;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100464 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100465}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100466
467int check_mode(const CELTMode *mode)
468{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400469 if (mode==NULL)
470 return CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100471 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
472 return CELT_OK;
473 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
474 celt_warning("Using a mode that has already been freed");
475 else
476 celt_warning("This is not a valid CELT mode");
477 return CELT_INVALID_MODE;
478}