blob: f6d2e4e363881ef3873743cae01d29d92349505e [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 Valin30f7f812009-10-17 14:35:13 -0400122 celt_int16 *eBands;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400123 int i, res, min_width, lin, low, high, nBark, offset=0;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400124
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400125 frame_size /= nbShortMdcts;
126 nbShortMdcts = 1;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100127 res = (Fs+frame_size)/(2*frame_size);
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400128 min_width = res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100129
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400130 /* Find the number of critical bands supported by our sampling rate */
131 for (nBark=1;nBark<BARK_BANDS;nBark++)
132 if (bark_freq[nBark+1]*2 >= Fs)
133 break;
134
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100135 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400136 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100137 if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
138 break;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400139
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400140 low = (bark_freq[lin]+res/2)/res;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400141 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100142 *nbEBands = low+high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400143 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100144
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400145 if (eBands==NULL)
146 return NULL;
147
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100148 /* Linear spacing (min_width) */
149 for (i=0;i<low;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400150 eBands[i] = i;
Jean-Marc Valinbe8d1252010-04-21 18:09:07 -0400151 if (low>0)
152 offset = eBands[low-1]*res - bark_freq[lin-1];
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100153 /* Spacing follows critical bands */
154 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400155 {
156 int target = bark_freq[lin+i];
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400157 eBands[i+low] = (target+(offset+res)/2)/res;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400158 offset = eBands[i+low]*res - target;
159 }
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 Valin65ee67a2010-04-26 07:08:44 -0400162 if (eBands[i] < i)
163 eBands[i] = i;
164 eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res;
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 {
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400172 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400173 }
174 }
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400175 /*for (i=0;i<=*nbEBands+1;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400176 printf ("%d ", eBands[i]);
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400177 printf ("\n");
178 exit(1);*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100179 /* FIXME: Remove last band if too small */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100180 return eBands;
181}
182
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400183static void compute_allocation_table(CELTMode *mode, int res, int M)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100184{
Gregory Maxwellec836da2009-05-04 14:55:40 -0400185 int i, j, nBark;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400186 celt_int16 *allocVectors;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400187
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400188 /* Find the number of critical bands supported by our sampling rate */
189 for (nBark=1;nBark<BARK_BANDS;nBark++)
190 if (bark_freq[nBark+1]*2 >= mode->Fs)
191 break;
192
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100193 mode->nbAllocVectors = BITALLOC_SIZE;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400194 allocVectors = celt_alloc(sizeof(celt_int16)*(BITALLOC_SIZE*mode->nbEBands));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400195 if (allocVectors==NULL)
196 return;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400197 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100198 for (i=0;i<BITALLOC_SIZE;i++)
199 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400200 celt_int32 current = 0;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400201 int eband = 0;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400202 for (j=0;j<nBark;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100203 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400204 int edge, low, high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400205 celt_int32 alloc;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400206
Jean-Marc Valin6a978022009-10-13 20:35:21 -0400207 alloc = mode->mdctSize*band_allocation[i*BARK_BANDS+j];
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400208 low = bark_freq[j];
209 high = bark_freq[j+1];
210
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400211 edge = M*mode->eBands[eband+1]*res;
Jean-Marc Valin3ff5e4c2010-04-14 18:02:09 -0400212 while (edge <= high && eband < mode->nbEBands)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100213 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400214 celt_int32 num;
215 int den, bits;
216 num = alloc * (edge-low);
217 den = high-low;
218 /* Divide with rounding */
219 bits = (2*num+den)/(2*den);
220 allocVectors[i*mode->nbEBands+eband] = (current+bits+128)>>8;
221
222 /* Remove the part of the band we just allocated */
223 low = edge;
224 alloc -= bits;
225
226 /* Move to next eband */
227 current = 0;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100228 eband++;
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400229 edge = M*mode->eBands[eband+1]*res;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400230 }
231 current += alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100232 }
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400233 if (eband < mode->nbEBands)
234 allocVectors[i*mode->nbEBands+eband] = (current+128)>>8;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100235 }
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400236 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000237}
238
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400239#endif /* STATIC_MODES */
240
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400241CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100242{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000243 int i;
244#ifdef STDIN_TUNING
245 scanf("%d ", &MIN_BINS);
246 scanf("%d ", &BITALLOC_SIZE);
247 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
248 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
249 {
250 scanf("%d ", band_allocation+i);
251 }
252#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100253#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100254 const CELTMode *m = NULL;
255 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000256 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400257#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
258 if (global_stack==NULL)
259 {
260 celt_free(global_stack);
261 goto failure;
262 }
263#endif
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100264 for (i=0;i<TOTAL_MODES;i++)
265 {
266 if (Fs == static_mode_list[i]->Fs &&
Jean-Marc Valin60d08372008-10-03 07:30:08 -0400267 frame_size == static_mode_list[i]->mdctSize)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100268 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100269 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100270 break;
271 }
272 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100273 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100274 {
275 celt_warning("Mode not included as part of the static modes");
276 if (error)
277 *error = CELT_BAD_ARG;
278 return NULL;
279 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100280 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400281 if (mode==NULL)
282 goto failure;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100283 CELT_COPY(mode, m, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400284 mode->marker_start = MODEPARTIAL;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100285#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100286 int res;
Gregory Maxwell84966952009-06-30 01:06:04 -0400287 CELTMode *mode=NULL;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400288 celt_word16 *window;
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400289 celt_int16 *logN;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000290 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400291#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
292 if (global_stack==NULL)
293 {
294 celt_free(global_stack);
295 goto failure;
296 }
297#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100298
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100299 /* The good thing here is that permutation of the arguments will automatically be invalid */
300
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500301 if (Fs < 32000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100302 {
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500303 celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100304 if (error)
305 *error = CELT_BAD_ARG;
306 return NULL;
307 }
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400308 if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100309 {
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400310 celt_warning("Only even frame sizes from 64 to 1024 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100311 if (error)
312 *error = CELT_BAD_ARG;
313 return NULL;
314 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100315 res = (Fs+frame_size)/(2*frame_size);
316
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100317 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400318 if (mode==NULL)
319 goto failure;
320 mode->marker_start = MODEPARTIAL;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100321 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100322 mode->mdctSize = frame_size;
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100323 mode->ePredCoef = QCONST16(.8f,15);
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400324
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400325 if (frame_size > 640 && (frame_size%16)==0)
326 {
327 mode->nbShortMdcts = 8;
328 } else if (frame_size > 384 && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000329 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400330 mode->nbShortMdcts = 4;
331 } else if (frame_size > 384 && (frame_size%10)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000332 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400333 mode->nbShortMdcts = 5;
334 } else if (frame_size > 256 && (frame_size%6)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000335 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400336 mode->nbShortMdcts = 3;
337 } else if (frame_size > 256 && (frame_size%8)==0)
338 {
339 mode->nbShortMdcts = 4;
340 } else if (frame_size > 64 && (frame_size%4)==0)
341 {
342 mode->nbShortMdcts = 2;
343 } else if (frame_size > 128 && (frame_size%6)==0)
344 {
345 mode->nbShortMdcts = 3;
346 } else
347 {
348 mode->nbShortMdcts = 1;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000349 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400350
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400351 mode->eBands = compute_ebands(Fs, frame_size, mode->nbShortMdcts, &mode->nbEBands);
352 if (mode->eBands==NULL)
353 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400354
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400355 mode->pitchEnd = 4000*(celt_int32)frame_size/Fs;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400356
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400357 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000358 if (mode->nbShortMdcts > 1)
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400359 mode->overlap = ((frame_size/mode->nbShortMdcts)>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000360 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400361 mode->overlap = (frame_size>>3)<<2;
362
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400363 compute_allocation_table(mode, res, mode->nbShortMdcts);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400364 if (mode->allocVectors==NULL)
365 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100366
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400367 window = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400368 if (window==NULL)
369 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100370
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100371#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100372 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100373 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 +1100374#else
375 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin8974f002010-03-20 00:41:39 -0400376 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 +1100377#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100378 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100379
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400380 mode->bits = (const celt_int16 **)compute_alloc_cache(mode, 1, mode->nbShortMdcts);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400381 if (mode->bits==NULL)
382 goto failure;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100383
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400384 logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
385 if (logN==NULL)
386 goto failure;
387
388 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400389 logN[i] = log2_frac(mode->nbShortMdcts*(mode->eBands[i+1]-mode->eBands[i]), BITRES);
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400390 mode->logN = logN;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100391#endif /* !STATIC_MODES */
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400392
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500393 clt_mdct_init(&mode->mdct, 2*mode->mdctSize);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +1000394
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000395 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500396 clt_mdct_init(&mode->shortMdct, 2*mode->shortMdctSize);
Jean-Marc Valin5f633542010-04-29 09:58:05 -0400397
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000398 mode->prob = quant_prob_alloc(mode);
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400399 if ((mode->mdct.trig==NULL) || (mode->shortMdct.trig==NULL)
400#ifndef ENABLE_TI_DSPLIB55
Jean-Marc Valin9319e3e2009-11-09 13:51:54 +0900401 || (mode->mdct.kfft==NULL) || (mode->shortMdct.kfft==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400402#endif
403 || (mode->prob==NULL))
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400404 goto failure;
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000405
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400406 mode->marker_start = MODEVALID;
407 mode->marker_end = MODEVALID;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100408 if (error)
409 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100410 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400411failure:
412 if (error)
413 *error = CELT_INVALID_MODE;
414 if (mode!=NULL)
415 celt_mode_destroy(mode);
416 return NULL;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100417}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100418
Peter Kirk19f9dc92008-06-06 14:38:38 +0200419void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100420{
Jean-Marc Valinf43488c2009-06-05 11:07:31 -0400421 int i;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400422 const celt_int16 *prevPtr = NULL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400423 if (mode == NULL)
424 {
425 celt_warning("NULL passed to celt_mode_destroy");
426 return;
427 }
428
429 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
430 {
431 celt_warning("Freeing a mode which has already been freed");
432 return;
433 }
434
435 if (mode->marker_start != MODEVALID && mode->marker_start != MODEPARTIAL)
436 {
437 celt_warning("This is not a valid CELT mode structure");
438 return;
439 }
440 mode->marker_start = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100441#ifndef STATIC_MODES
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400442 if (mode->bits!=NULL)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100443 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400444 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100445 {
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400446 if (mode->bits[i] != prevPtr)
447 {
448 prevPtr = mode->bits[i];
449 celt_free((int*)mode->bits[i]);
450 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100451 }
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400452 }
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400453 celt_free((celt_int16**)mode->bits);
454 celt_free((celt_int16*)mode->eBands);
455 celt_free((celt_int16*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400456
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400457 celt_free((celt_word16*)mode->window);
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400458 celt_free((celt_int16*)mode->logN);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100459
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000460#endif
Jean-Marc Valin6d584ac2009-11-21 21:57:44 -0500461 clt_mdct_clear(&mode->mdct);
462 clt_mdct_clear(&mode->shortMdct);
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000463 quant_prob_free(mode->prob);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400464 mode->marker_end = MODEFREED;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100465 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100466}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100467
468int check_mode(const CELTMode *mode)
469{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400470 if (mode==NULL)
471 return CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100472 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
473 return CELT_OK;
474 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
475 celt_warning("Using a mode that has already been freed");
476 else
477 celt_warning("This is not a valid CELT mode");
478 return CELT_INVALID_MODE;
479}