blob: 7447a5c44ff9a2cd35152926594d2d685f9aa0f3 [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 Valin4fb95682010-04-20 23:30:22 -0400122 int min_bins = 2;
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 Valin4fb95682010-04-20 23:30:22 -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;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400140
141 low = (bark_freq[lin]+res*min_bins/2)/(res*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 Valinbe8d1252010-04-21 18:09:07 -0400152 if (low>0)
153 offset = eBands[low-1]*res - bark_freq[lin-1];
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100154 /* Spacing follows critical bands */
155 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400156 {
157 int target = bark_freq[lin+i];
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400158 eBands[i+low] = (target+(offset+res*nbShortMdcts)/2)/(res*nbShortMdcts)*nbShortMdcts;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400159 offset = eBands[i+low]*res - target;
160 }
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100161 /* Enforce the minimum spacing at the boundary */
162 for (i=0;i<*nbEBands;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400163 if (eBands[i] < min_bins*i)
164 eBands[i] = min_bins*i;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400165 eBands[*nbEBands] = (bark_freq[nBark]+res*nbShortMdcts/2)/(res*nbShortMdcts)*nbShortMdcts;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100166 eBands[*nbEBands+1] = frame_size;
167 if (eBands[*nbEBands] > eBands[*nbEBands+1])
168 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400169 for (i=1;i<*nbEBands-1;i++)
170 {
171 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
172 {
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400173 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1]+nbShortMdcts)/(2*nbShortMdcts)*nbShortMdcts;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400174 }
175 }
176 /*for (i=0;i<*nbEBands+1;i++)
177 printf ("%d ", eBands[i]);
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400178 printf ("\n");
179 exit(1);*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100180 /* FIXME: Remove last band if too small */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100181 return eBands;
182}
183
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100184static void compute_allocation_table(CELTMode *mode, int res)
185{
Gregory Maxwellec836da2009-05-04 14:55:40 -0400186 int i, j, nBark;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400187 celt_int16 *allocVectors;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400188
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400189 /* Find the number of critical bands supported by our sampling rate */
190 for (nBark=1;nBark<BARK_BANDS;nBark++)
191 if (bark_freq[nBark+1]*2 >= mode->Fs)
192 break;
193
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100194 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400195 allocVectors = celt_alloc(sizeof(celt_int16)*(BITALLOC_SIZE*mode->nbEBands));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400196 if (allocVectors==NULL)
197 return;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400198 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100199 for (i=0;i<BITALLOC_SIZE;i++)
200 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400201 celt_int32 current = 0;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400202 int eband = 0;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400203 for (j=0;j<nBark;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100204 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400205 int edge, low, high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400206 celt_int32 alloc;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400207
Jean-Marc Valin6a978022009-10-13 20:35:21 -0400208 alloc = mode->mdctSize*band_allocation[i*BARK_BANDS+j];
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400209 low = bark_freq[j];
210 high = bark_freq[j+1];
211
212 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin3ff5e4c2010-04-14 18:02:09 -0400213 while (edge <= high && eband < mode->nbEBands)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100214 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400215 celt_int32 num;
216 int den, bits;
217 num = alloc * (edge-low);
218 den = high-low;
219 /* Divide with rounding */
220 bits = (2*num+den)/(2*den);
221 allocVectors[i*mode->nbEBands+eband] = (current+bits+128)>>8;
222
223 /* Remove the part of the band we just allocated */
224 low = edge;
225 alloc -= bits;
226
227 /* Move to next eband */
228 current = 0;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100229 eband++;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400230 edge = mode->eBands[eband+1]*res;
231 }
232 current += alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100233 }
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400234 if (eband < mode->nbEBands)
235 allocVectors[i*mode->nbEBands+eband] = (current+128)>>8;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100236 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400237 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000238}
239
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400240#endif /* STATIC_MODES */
241
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400242CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100243{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000244 int i;
245#ifdef STDIN_TUNING
246 scanf("%d ", &MIN_BINS);
247 scanf("%d ", &BITALLOC_SIZE);
248 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
249 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
250 {
251 scanf("%d ", band_allocation+i);
252 }
253#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100254#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100255 const CELTMode *m = NULL;
256 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000257 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400258#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
259 if (global_stack==NULL)
260 {
261 celt_free(global_stack);
262 goto failure;
263 }
264#endif
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100265 for (i=0;i<TOTAL_MODES;i++)
266 {
267 if (Fs == static_mode_list[i]->Fs &&
Jean-Marc Valin60d08372008-10-03 07:30:08 -0400268 frame_size == static_mode_list[i]->mdctSize)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100269 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100270 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100271 break;
272 }
273 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100274 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100275 {
276 celt_warning("Mode not included as part of the static modes");
277 if (error)
278 *error = CELT_BAD_ARG;
279 return NULL;
280 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100281 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400282 if (mode==NULL)
283 goto failure;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100284 CELT_COPY(mode, m, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400285 mode->marker_start = MODEPARTIAL;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100286#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100287 int res;
Gregory Maxwell84966952009-06-30 01:06:04 -0400288 CELTMode *mode=NULL;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400289 celt_word16 *window;
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400290 celt_int16 *logN;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000291 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400292#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
293 if (global_stack==NULL)
294 {
295 celt_free(global_stack);
296 goto failure;
297 }
298#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100299
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100300 /* The good thing here is that permutation of the arguments will automatically be invalid */
301
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500302 if (Fs < 32000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100303 {
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500304 celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100305 if (error)
306 *error = CELT_BAD_ARG;
307 return NULL;
308 }
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400309 if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100310 {
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400311 celt_warning("Only even frame sizes from 64 to 1024 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100312 if (error)
313 *error = CELT_BAD_ARG;
314 return NULL;
315 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100316 res = (Fs+frame_size)/(2*frame_size);
317
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100318 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400319 if (mode==NULL)
320 goto failure;
321 mode->marker_start = MODEPARTIAL;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100322 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100323 mode->mdctSize = frame_size;
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100324 mode->ePredCoef = QCONST16(.8f,15);
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400325
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400326 if (frame_size > 640 && (frame_size%16)==0)
327 {
328 mode->nbShortMdcts = 8;
329 } else if (frame_size > 384 && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000330 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400331 mode->nbShortMdcts = 4;
332 } else if (frame_size > 384 && (frame_size%10)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000333 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400334 mode->nbShortMdcts = 5;
335 } else if (frame_size > 256 && (frame_size%6)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000336 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400337 mode->nbShortMdcts = 3;
338 } else if (frame_size > 256 && (frame_size%8)==0)
339 {
340 mode->nbShortMdcts = 4;
341 } else if (frame_size > 64 && (frame_size%4)==0)
342 {
343 mode->nbShortMdcts = 2;
344 } else if (frame_size > 128 && (frame_size%6)==0)
345 {
346 mode->nbShortMdcts = 3;
347 } else
348 {
349 mode->nbShortMdcts = 1;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000350 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400351
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400352 mode->eBands = compute_ebands(Fs, frame_size, mode->nbShortMdcts, &mode->nbEBands);
353 if (mode->eBands==NULL)
354 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400355
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400356 mode->pitchEnd = 4000*(celt_int32)frame_size/Fs;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400357
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400358 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000359 if (mode->nbShortMdcts > 1)
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400360 mode->overlap = ((frame_size/mode->nbShortMdcts)>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000361 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400362 mode->overlap = (frame_size>>3)<<2;
363
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100364 compute_allocation_table(mode, res);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400365 if (mode->allocVectors==NULL)
366 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100367
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400368 window = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400369 if (window==NULL)
370 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100371
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100372#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100373 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100374 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 +1100375#else
376 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin8974f002010-03-20 00:41:39 -0400377 window[i] = MIN32(32767,floor(.5+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 +1100378#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100379 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100380
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400381 mode->bits = (const celt_int16 **)compute_alloc_cache(mode, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400382 if (mode->bits==NULL)
383 goto failure;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100384
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400385 logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
386 if (logN==NULL)
387 goto failure;
388
389 for (i=0;i<mode->nbEBands;i++)
390 logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
391 mode->logN = logN;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100392#endif /* !STATIC_MODES */
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400393
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500394 clt_mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000395
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000396 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500397 clt_mdct_init(&mode->shortMdct, 2*mode->shortMdctSize);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000398 mode->shortWindow = mode->window;
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000399 mode->prob = quant_prob_alloc(mode);
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400400 if ((mode->mdct.trig==NULL) || (mode->shortMdct.trig==NULL)
401#ifndef ENABLE_TI_DSPLIB55
Jean-Marc Valin9319e3e2009-11-09 13:51:54 +0900402 || (mode->mdct.kfft==NULL) || (mode->shortMdct.kfft==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400403#endif
404 || (mode->prob==NULL))
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400405 goto failure;
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000406
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400407 mode->marker_start = MODEVALID;
408 mode->marker_end = MODEVALID;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100409 if (error)
410 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100411 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400412failure:
413 if (error)
414 *error = CELT_INVALID_MODE;
415 if (mode!=NULL)
416 celt_mode_destroy(mode);
417 return NULL;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100418}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100419
Peter Kirk19f9dc92008-06-06 14:38:38 +0200420void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100421{
Jean-Marc Valinf43488c2009-06-05 11:07:31 -0400422 int i;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400423 const celt_int16 *prevPtr = NULL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400424 if (mode == NULL)
425 {
426 celt_warning("NULL passed to celt_mode_destroy");
427 return;
428 }
429
430 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
431 {
432 celt_warning("Freeing a mode which has already been freed");
433 return;
434 }
435
436 if (mode->marker_start != MODEVALID && mode->marker_start != MODEPARTIAL)
437 {
438 celt_warning("This is not a valid CELT mode structure");
439 return;
440 }
441 mode->marker_start = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100442#ifndef STATIC_MODES
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400443 if (mode->bits!=NULL)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100444 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400445 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100446 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400447 if (mode->bits[i] != prevPtr)
448 {
449 prevPtr = mode->bits[i];
450 celt_free((int*)mode->bits[i]);
451 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100452 }
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400453 }
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400454 celt_free((celt_int16**)mode->bits);
455 celt_free((celt_int16*)mode->eBands);
456 celt_free((celt_int16*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400457
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400458 celt_free((celt_word16*)mode->window);
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400459 celt_free((celt_int16*)mode->logN);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100460
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000461#endif
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500462 clt_mdct_clear(&mode->mdct);
463 clt_mdct_clear(&mode->shortMdct);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000464 quant_prob_free(mode->prob);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400465 mode->marker_end = MODEFREED;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100466 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100467}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100468
469int check_mode(const CELTMode *mode)
470{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400471 if (mode==NULL)
472 return CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100473 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
474 return CELT_OK;
475 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
476 celt_warning("Using a mode that has already been freed");
477 else
478 celt_warning("This is not a valid CELT mode");
479 return CELT_INVALID_MODE;
480}