blob: 32abe7e6ff221ef1268975484d47710bf3c6f611 [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 {
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110064 case CELT_GET_LOOKAHEAD:
65 *value = mode->overlap;
66 break;
Jean-Marc Valin59093c02008-05-15 21:53:27 +100067 case CELT_GET_BITSTREAM_VERSION:
68 *value = CELT_BITSTREAM_VERSION;
69 break;
Gregory Maxwelld9458cd2009-05-30 17:04:02 -040070 case CELT_GET_SAMPLE_RATE:
71 *value = mode->Fs;
72 break;
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110073 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040074 return CELT_UNIMPLEMENTED;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110075 }
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +110076 return CELT_OK;
Jean-Marc Valinf997ad52008-01-31 16:47:16 +110077}
78
Jean-Marc Valin5588d522008-03-10 15:07:58 +110079#ifndef STATIC_MODES
80
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110081/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
82 Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
Jean-Marc Valin81a82952008-02-17 22:41:29 +110083#define BARK_BANDS 25
Jean-Marc Valin30f7f812009-10-17 14:35:13 -040084static const celt_int16 bark_freq[BARK_BANDS+1] = {
Jean-Marc Valin17683eb2008-02-18 21:45:19 +110085 0, 100, 200, 300, 400,
86 510, 630, 770, 920, 1080,
87 1270, 1480, 1720, 2000, 2320,
88 2700, 3150, 3700, 4400, 5300,
89 6400, 7700, 9500, 12000, 15500,
90 20000};
91
Jean-Marc Valin75e9c862008-02-18 17:04:15 +110092/* This allocation table is per critical band. When creating a mode, the bits get added together
93 into the codec bands, which are sometimes larger than one critical band at low frequency */
Jean-Marc Valin47c248a2008-04-26 08:16:12 +100094
95#ifdef STDIN_TUNING
96int BITALLOC_SIZE;
97int *band_allocation;
98#else
Jean-Marc Valin9c709062008-08-03 22:07:06 -040099#define BITALLOC_SIZE 12
Jean-Marc Valinc1ca5872010-05-15 23:47:09 -0400100static const unsigned char band_allocation[BARK_BANDS*BITALLOC_SIZE] =
Christopher Montgomery8e511a82009-07-03 02:10:17 -0400101 /* 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 */
102 { 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*/
103 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*/
104 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*/
105 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*/
106 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*/
107 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*/
108 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*/
109 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*/
110 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*/
111 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*/
112 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*/
113 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 -0400114 };
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000115#endif
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100116
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400117static const celt_int16 eband5ms[] = {
118 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100
119};
120
121static const celt_int16 alloc_5ms[] = {
122 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123 10, 3, 8, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124 10, 6, 8, 6, 5, 4, 3, 2, 7, 10, 11, 9, 7, 3, 1, 0, 0, 0, 0, 0, 0,
125 10, 10, 14, 11, 10, 8, 6, 5, 10, 12, 13, 11, 8, 4, 2, 1, 0, 0, 0, 0, 0,
126 13, 10, 17, 16, 14, 12, 10, 8, 12, 14, 14, 12, 9, 5, 3, 2, 2, 1, 0, 0, 0,
127 17, 21, 23, 26, 24, 20, 17, 16, 17, 18, 16, 14, 11, 6, 3, 2, 2, 1, 1, 0, 0,
128 21, 21, 36, 32, 28, 24, 23, 23, 22, 18, 18, 14, 11, 7, 5, 5, 5, 3, 3, 0, 0,
129 31, 35, 40, 32, 30, 28, 26, 26, 25, 24, 19, 15, 15, 13, 9, 9, 8, 7, 5, 2, 0,
130 42, 46, 46, 37, 35, 34, 33, 32, 34, 35, 32, 31, 27, 24, 23, 23, 18, 14, 11, 7, 0,
131 46, 49, 46, 46, 42, 43, 44, 47, 50, 52, 51, 48, 39, 32, 27, 24, 22, 19, 17, 11, 5,
132 53, 53, 49, 48, 55, 66, 71, 71, 71, 65, 64, 64, 56, 47, 41, 37, 31, 24, 20, 16, 10,
133 60, 64, 74, 74, 87,103,106,102,101,100,101, 95, 80, 69, 63, 55, 47, 36, 26, 21, 15,
134};
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400135
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400136static celt_int16 *compute_ebands(celt_int32 Fs, int frame_size, int res, int *nbEBands)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100137{
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400138 celt_int16 *eBands;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400139 int i, lin, low, high, nBark, offset=0;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100140
Jean-Marc Valin20639c42010-05-19 16:10:12 -0400141 if (Fs == 400*(celt_int32)frame_size && Fs >= 40000)
142 {
143 *nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
144 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
145 for (i=0;i<*nbEBands+2;i++)
146 eBands[i] = eband5ms[i];
147 eBands[*nbEBands+1] = frame_size;
148 return eBands;
149 }
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400150 /* Find the number of critical bands supported by our sampling rate */
151 for (nBark=1;nBark<BARK_BANDS;nBark++)
152 if (bark_freq[nBark+1]*2 >= Fs)
153 break;
154
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100155 /* Find where the linear part ends (i.e. where the spacing is more than min_width */
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400156 for (lin=0;lin<nBark;lin++)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400157 if (bark_freq[lin+1]-bark_freq[lin] >= res)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100158 break;
Jean-Marc Valin4fb95682010-04-20 23:30:22 -0400159
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400160 low = (bark_freq[lin]+res/2)/res;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400161 high = nBark-lin;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100162 *nbEBands = low+high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400163 eBands = celt_alloc(sizeof(celt_int16)*(*nbEBands+2));
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100164
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400165 if (eBands==NULL)
166 return NULL;
167
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100168 /* Linear spacing (min_width) */
169 for (i=0;i<low;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400170 eBands[i] = i;
Jean-Marc Valinbe8d1252010-04-21 18:09:07 -0400171 if (low>0)
172 offset = eBands[low-1]*res - bark_freq[lin-1];
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100173 /* Spacing follows critical bands */
174 for (i=0;i<high;i++)
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400175 {
176 int target = bark_freq[lin+i];
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400177 eBands[i+low] = (target+(offset+res)/2)/res;
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400178 offset = eBands[i+low]*res - target;
179 }
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100180 /* Enforce the minimum spacing at the boundary */
181 for (i=0;i<*nbEBands;i++)
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400182 if (eBands[i] < i)
183 eBands[i] = i;
184 eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100185 eBands[*nbEBands+1] = frame_size;
186 if (eBands[*nbEBands] > eBands[*nbEBands+1])
187 eBands[*nbEBands] = eBands[*nbEBands+1];
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400188 for (i=1;i<*nbEBands-1;i++)
189 {
190 if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
191 {
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400192 eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400193 }
194 }
Jean-Marc Valin65ee67a2010-04-26 07:08:44 -0400195 /*for (i=0;i<=*nbEBands+1;i++)
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400196 printf ("%d ", eBands[i]);
Jean-Marc Valin39f68ac2009-10-03 23:27:52 -0400197 printf ("\n");
198 exit(1);*/
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100199 /* FIXME: Remove last band if too small */
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100200 return eBands;
201}
202
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400203static void compute_allocation_table(CELTMode *mode, int res)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100204{
Gregory Maxwellec836da2009-05-04 14:55:40 -0400205 int i, j, nBark;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400206 celt_int16 *allocVectors;
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400207 int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400208
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400209 mode->nbAllocVectors = BITALLOC_SIZE;
210 allocVectors = celt_alloc(sizeof(celt_int16)*(BITALLOC_SIZE*mode->nbEBands));
211 if (allocVectors==NULL)
212 return;
213
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400214 /* Check for standard mode */
Jean-Marc Valin12e851d2010-06-03 08:12:11 -0400215 if (mode->Fs == 400*(celt_int32)mode->shortMdctSize && mode->Fs >= 40000)
216 {
217 for (i=0;i<BITALLOC_SIZE*mode->nbEBands;i++)
218 allocVectors[i] = alloc_5ms[i];
219 mode->allocVectors = allocVectors;
220 return;
221 }
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400222
223 /* If not the standard mode, interpolate */
224
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400225 /* Find the number of critical bands supported by our sampling rate */
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400226 for (nBark=1;nBark<maxBands;nBark++)
227 if (eband5ms[j+1]*400 >= mode->Fs)
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400228 break;
229
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400230 /* Compute per-codec-band allocation from per-critical-band matrix */
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100231 for (i=0;i<BITALLOC_SIZE;i++)
232 {
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400233 celt_int32 current = 0;
Gregory Maxwellec836da2009-05-04 14:55:40 -0400234 int eband = 0;
Gregory Maxwellcbaf67e2008-09-28 04:19:19 -0400235 for (j=0;j<nBark;j++)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100236 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400237 int edge, low, high;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400238 celt_int32 alloc;
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400239 alloc = alloc_5ms[i*maxBands + j]*(mode->eBands[eband+1]-mode->eBands[eband])<<4;
240 low = eband5ms[j]*200;
241 high = eband5ms[j+1]*200;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400242 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin3ff5e4c2010-04-14 18:02:09 -0400243 while (edge <= high && eband < mode->nbEBands)
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100244 {
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400245 celt_int32 num;
246 int den, bits;
Jean-Marc Valinbb8fa1f2010-06-03 00:33:42 -0400247 int N = (mode->eBands[eband+1]-mode->eBands[eband]);
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400248 num = alloc * (edge-low);
249 den = high-low;
250 /* Divide with rounding */
251 bits = (2*num+den)/(2*den);
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400252 allocVectors[i*mode->nbEBands+eband] = (2*(current+bits)+(N<<4))/(2*N<<4);
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400253 /* Remove the part of the band we just allocated */
254 low = edge;
255 alloc -= bits;
256
257 /* Move to next eband */
258 current = 0;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100259 eband++;
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400260 edge = mode->eBands[eband+1]*res;
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400261 }
262 current += alloc;
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100263 }
Jean-Marc Valin137f3362010-04-14 17:42:22 -0400264 if (eband < mode->nbEBands)
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400265 {
Jean-Marc Valinbb8fa1f2010-06-03 00:33:42 -0400266 int N = (mode->eBands[eband+1]-mode->eBands[eband]);
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400267 allocVectors[i*mode->nbEBands+eband] = (2*current+(N<<4))/(2*N<<4);
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400268 }
Jean-Marc Valin9838fec2008-02-18 14:45:11 +1100269 }
Jean-Marc Valinc51e98b2010-06-03 22:11:41 -0400270 /*printf ("\n");
271 for (i=0;i<BITALLOC_SIZE;i++)
Jean-Marc Valinbb8fa1f2010-06-03 00:33:42 -0400272 {
273 for (j=0;j<mode->nbEBands;j++)
274 printf ("%d ", allocVectors[i*mode->nbEBands+j]);
275 printf ("\n");
276 }
277 exit(0);*/
278
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400279 mode->allocVectors = allocVectors;
Jean-Marc Valinad637192008-05-07 13:44:39 +1000280}
281
Jean-Marc Valin36e6e012008-08-02 22:25:19 -0400282#endif /* STATIC_MODES */
283
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400284CELTMode *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100285{
Jean-Marc Valin47c248a2008-04-26 08:16:12 +1000286 int i;
287#ifdef STDIN_TUNING
288 scanf("%d ", &MIN_BINS);
289 scanf("%d ", &BITALLOC_SIZE);
290 band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
291 for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
292 {
293 scanf("%d ", band_allocation+i);
294 }
295#endif
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100296#ifdef STATIC_MODES
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100297 const CELTMode *m = NULL;
298 CELTMode *mode=NULL;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000299 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400300#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
301 if (global_stack==NULL)
302 {
303 celt_free(global_stack);
304 goto failure;
305 }
306#endif
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100307 for (i=0;i<TOTAL_MODES;i++)
308 {
309 if (Fs == static_mode_list[i]->Fs &&
Jean-Marc Valin60d08372008-10-03 07:30:08 -0400310 frame_size == static_mode_list[i]->mdctSize)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100311 {
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100312 m = static_mode_list[i];
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100313 break;
314 }
315 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100316 if (m == NULL)
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100317 {
318 celt_warning("Mode not included as part of the static modes");
319 if (error)
320 *error = CELT_BAD_ARG;
321 return NULL;
322 }
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100323 mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400324 if (mode==NULL)
325 goto failure;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100326 CELT_COPY(mode, m, 1);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400327 mode->marker_start = MODEPARTIAL;
Jean-Marc Valinf39e8692008-03-10 12:13:23 +1100328#else
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100329 int res;
Gregory Maxwell84966952009-06-30 01:06:04 -0400330 CELTMode *mode=NULL;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400331 celt_word16 *window;
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400332 celt_int16 *logN;
Jean-Marc Valinf7cec832008-04-18 17:29:56 +1000333 ALLOC_STACK;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400334#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
335 if (global_stack==NULL)
336 {
337 celt_free(global_stack);
338 goto failure;
339 }
340#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100341
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100342 /* The good thing here is that permutation of the arguments will automatically be invalid */
343
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500344 if (Fs < 32000 || Fs > 96000)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100345 {
Gregory Maxwell8ed86582008-12-02 12:06:14 -0500346 celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100347 if (error)
348 *error = CELT_BAD_ARG;
349 return NULL;
350 }
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400351 if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100352 {
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400353 celt_warning("Only even frame sizes from 64 to 1024 are supported");
Jean-Marc Valin75e9c862008-02-18 17:04:15 +1100354 if (error)
355 *error = CELT_BAD_ARG;
356 return NULL;
357 }
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100358
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100359 mode = celt_alloc(sizeof(CELTMode));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400360 if (mode==NULL)
361 goto failure;
362 mode->marker_start = MODEPARTIAL;
Jean-Marc Valine6b74652008-02-20 18:01:08 +1100363 mode->Fs = Fs;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100364 mode->mdctSize = frame_size;
Jean-Marc Valin8b2a5922008-02-29 00:32:51 +1100365 mode->ePredCoef = QCONST16(.8f,15);
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400366
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400367 if (frame_size >= 640 && (frame_size%16)==0)
Jean-Marc Valine6d832a2009-07-08 22:21:31 -0400368 {
369 mode->nbShortMdcts = 8;
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400370 } else if (frame_size >= 320 && (frame_size%8)==0)
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000371 {
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400372 mode->nbShortMdcts = 4;
Jean-Marc Valinc5d00a02010-05-26 11:27:32 -0400373 } else if (frame_size >= 160 && (frame_size%4)==0)
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400374 {
375 mode->nbShortMdcts = 2;
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400376 } else
377 {
378 mode->nbShortMdcts = 1;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000379 }
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400380
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400381 mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
382 res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
383
384 mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400385 if (mode->eBands==NULL)
386 goto failure;
Jean-Marc Valinfbfddf72009-07-19 21:07:12 -0400387
Jean-Marc Valine949b722010-05-07 07:48:07 -0400388 mode->pitchEnd = 4000*(celt_int32)mode->shortMdctSize/Fs;
Jean-Marc Valin4834c922009-09-28 19:17:34 -0400389
Jean-Marc Valin08192e32009-07-02 13:28:55 -0400390 /* Overlap must be divisible by 4 */
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000391 if (mode->nbShortMdcts > 1)
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400392 mode->overlap = (mode->shortMdctSize>>2)<<2;
Jean-Marc Valin16ca18b2008-06-18 23:44:48 +1000393 else
Gregory Maxwell23e654f2008-09-27 16:20:03 -0400394 mode->overlap = (frame_size>>3)<<2;
395
Jean-Marc Valin7f1c9422010-04-29 11:24:11 -0400396
397 compute_allocation_table(mode, res);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400398 if (mode->allocVectors==NULL)
399 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100400
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400401 window = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400402 if (window==NULL)
403 goto failure;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100404
Jean-Marc Valinf28062f2008-03-03 13:24:01 +1100405#ifndef FIXED_POINT
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100406 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100407 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 +1100408#else
409 for (i=0;i<mode->overlap;i++)
Jean-Marc Valin8974f002010-03-20 00:41:39 -0400410 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 +1100411#endif
Jean-Marc Valin3dbc1d02008-03-08 15:21:24 +1100412 mode->window = window;
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100413
Jean-Marc Valincae30df2010-05-21 00:26:03 -0400414 mode->bits = mode->_bits+1;
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400415 for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
Jean-Marc Valincae30df2010-05-21 00:26:03 -0400416 {
417 mode->bits[i] = (const celt_int16 **)compute_alloc_cache(mode, 1<<i);
418 if (mode->bits[i]==NULL)
419 goto failure;
420 }
421 mode->bits[-1] = (const celt_int16 **)compute_alloc_cache(mode, 0);
422 if (mode->bits[-1]==NULL)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400423 goto failure;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100424
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400425 logN = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_int16));
426 if (logN==NULL)
427 goto failure;
428
429 for (i=0;i<mode->nbEBands;i++)
Jean-Marc Valinaead79b2010-05-11 07:34:24 -0400430 logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
Jean-Marc Valinf400a3c2010-04-05 23:58:44 -0400431 mode->logN = logN;
Jean-Marc Valinb76ee702008-03-10 15:42:35 +1100432#endif /* !STATIC_MODES */
Jean-Marc Valin640f7fd2009-06-21 09:47:51 -0400433
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400434 for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
435 {
436 clt_mdct_init(&mode->mdct[i], 2*mode->shortMdctSize<<i);
437 if ((mode->mdct[i].trig==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400438#ifndef ENABLE_TI_DSPLIB55
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400439 || (mode->mdct[i].kfft==NULL)
Jean-Marc Valin9714f662009-08-12 20:29:57 -0400440#endif
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400441 )
442 goto failure;
443 }
444 mode->prob = quant_prob_alloc(mode);
445 if (mode->prob==NULL)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400446 goto failure;
Jean-Marc Valinbf2d6482008-05-23 16:57:34 +1000447
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400448 mode->marker_start = MODEVALID;
449 mode->marker_end = MODEVALID;
Jean-Marc Valin680a9ec2008-03-10 14:52:18 +1100450 if (error)
451 *error = CELT_OK;
Jean-Marc Valin4991a562008-02-18 13:37:40 +1100452 return mode;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400453failure:
454 if (error)
455 *error = CELT_INVALID_MODE;
456 if (mode!=NULL)
457 celt_mode_destroy(mode);
458 return NULL;
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100459}
Jean-Marc Valin2a8c3712008-02-18 12:16:41 +1100460
Peter Kirk19f9dc92008-06-06 14:38:38 +0200461void celt_mode_destroy(CELTMode *mode)
Jean-Marc Valin81a82952008-02-17 22:41:29 +1100462{
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400463 int i, m;
Jean-Marc Valin30f7f812009-10-17 14:35:13 -0400464 const celt_int16 *prevPtr = NULL;
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400465 if (mode == NULL)
466 {
467 celt_warning("NULL passed to celt_mode_destroy");
468 return;
469 }
470
471 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
472 {
473 celt_warning("Freeing a mode which has already been freed");
474 return;
475 }
476
477 if (mode->marker_start != MODEVALID && mode->marker_start != MODEPARTIAL)
478 {
479 celt_warning("This is not a valid CELT mode structure");
480 return;
481 }
482 mode->marker_start = MODEFREED;
Jean-Marc Valin5588d522008-03-10 15:07:58 +1100483#ifndef STATIC_MODES
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400484 for (m=0;(1<<m)<=mode->nbShortMdcts;m++)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100485 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400486 if (mode->bits[m]!=NULL)
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100487 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400488 for (i=0;i<mode->nbEBands;i++)
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400489 {
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400490 if (mode->bits[m][i] != prevPtr)
491 {
492 prevPtr = mode->bits[m][i];
493 celt_free((int*)mode->bits[m][i]);
494 }
495 }
Jean-Marc Valin25358cd2008-02-19 12:21:32 +1100496 }
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400497 celt_free((celt_int16**)mode->bits[m]);
498 }
Jean-Marc Valincae30df2010-05-21 00:26:03 -0400499 if (mode->bits[-1]!=NULL)
500 {
501 for (i=0;i<mode->nbEBands;i++)
502 {
503 if (mode->bits[-1][i] != prevPtr)
504 {
505 prevPtr = mode->bits[-1][i];
506 celt_free((int*)mode->bits[-1][i]);
507 }
508 }
509 }
510 celt_free((celt_int16**)mode->bits[-1]);
511
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400512 celt_free((celt_int16*)mode->eBands);
513 celt_free((celt_int16*)mode->allocVectors);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400514
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400515 celt_free((celt_word16*)mode->window);
Jean-Marc Valin31bec962010-04-07 18:30:28 -0400516 celt_free((celt_int16*)mode->logN);
Jean-Marc Valin81b38c22008-02-29 21:08:49 +1100517
Jean-Marc Valin70720a32008-04-19 21:39:26 +1000518#endif
Jean-Marc Valin073d0bc2010-05-05 21:37:53 -0400519 for (i=0;(1<<i)<=mode->nbShortMdcts;i++)
520 clt_mdct_clear(&mode->mdct[i]);
521
Jean-Marc Valin4ce92052008-04-23 13:42:10 +1000522 quant_prob_free(mode->prob);
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400523 mode->marker_end = MODEFREED;
Jean-Marc Valin949902f2008-03-11 10:43:06 +1100524 celt_free((CELTMode *)mode);
Jean-Marc Valin2ca8fc32008-02-18 16:27:49 +1100525}
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100526
527int check_mode(const CELTMode *mode)
528{
Gregory Maxwelldc67fa92009-06-04 17:17:35 -0400529 if (mode==NULL)
530 return CELT_INVALID_MODE;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100531 if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
532 return CELT_OK;
533 if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
534 celt_warning("Using a mode that has already been freed");
535 else
536 celt_warning("This is not a valid CELT mode");
537 return CELT_INVALID_MODE;
538}