| Jean-Marc Valin | 8b2a592 | 2008-02-29 00:32:51 +1100 | [diff] [blame] | 1 | /* (C) 2007-2008 Jean-Marc Valin, CSIRO | 
| Jean-Marc Valin | ecb36a3 | 2007-12-05 01:31:49 +1100 | [diff] [blame] | 2 | */ | 
|  | 3 | /* | 
|  | 4 | Redistribution and use in source and binary forms, with or without | 
|  | 5 | modification, are permitted provided that the following conditions | 
|  | 6 | are met: | 
|  | 7 |  | 
|  | 8 | - Redistributions of source code must retain the above copyright | 
|  | 9 | notice, this list of conditions and the following disclaimer. | 
|  | 10 |  | 
|  | 11 | - Redistributions in binary form must reproduce the above copyright | 
|  | 12 | notice, this list of conditions and the following disclaimer in the | 
|  | 13 | documentation and/or other materials provided with the distribution. | 
|  | 14 |  | 
|  | 15 | - Neither the name of the Xiph.org Foundation nor the names of its | 
|  | 16 | contributors may be used to endorse or promote products derived from | 
|  | 17 | this software without specific prior written permission. | 
|  | 18 |  | 
|  | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | 20 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  | 22 | A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR | 
|  | 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
|  | 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
|  | 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
|  | 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
|  | 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|  | 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|  | 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | 30 | */ | 
|  | 31 |  | 
| Jean-Marc Valin | 02fa913 | 2008-02-20 12:09:29 +1100 | [diff] [blame] | 32 | #ifdef HAVE_CONFIG_H | 
|  | 33 | #include "config.h" | 
|  | 34 | #endif | 
|  | 35 |  | 
| Jean-Marc Valin | 65d57e6 | 2008-02-18 15:49:37 +1100 | [diff] [blame] | 36 | #include "celt.h" | 
| Jean-Marc Valin | ecb36a3 | 2007-12-05 01:31:49 +1100 | [diff] [blame] | 37 | #include "modes.h" | 
| Jean-Marc Valin | 472a5f0 | 2008-02-19 13:12:32 +1100 | [diff] [blame] | 38 | #include "rate.h" | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 39 | #include "os_support.h" | 
| Jean-Marc Valin | ecb36a3 | 2007-12-05 01:31:49 +1100 | [diff] [blame] | 40 |  | 
| Jean-Marc Valin | f39e869 | 2008-03-10 12:13:23 +1100 | [diff] [blame] | 41 | #ifdef STATIC_MODES | 
|  | 42 | #include "static_modes.h" | 
|  | 43 | #endif | 
|  | 44 |  | 
| Jean-Marc Valin | 44ffd5a | 2008-02-22 00:39:25 +1100 | [diff] [blame] | 45 | #define MODEVALID 0xa110ca7e | 
|  | 46 | #define MODEFREED 0xb10cf8ee | 
|  | 47 |  | 
| Jean-Marc Valin | d748cd5 | 2008-03-01 07:27:03 +1100 | [diff] [blame] | 48 | #ifndef M_PI | 
|  | 49 | #define M_PI 3.141592653 | 
|  | 50 | #endif | 
|  | 51 |  | 
| Jean-Marc Valin | 44ffd5a | 2008-02-22 00:39:25 +1100 | [diff] [blame] | 52 |  | 
| Jean-Marc Valin | f997ad5 | 2008-01-31 16:47:16 +1100 | [diff] [blame] | 53 | int celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value) | 
|  | 54 | { | 
|  | 55 | switch (request) | 
|  | 56 | { | 
|  | 57 | case CELT_GET_FRAME_SIZE: | 
|  | 58 | *value = mode->mdctSize; | 
|  | 59 | break; | 
|  | 60 | case CELT_GET_LOOKAHEAD: | 
|  | 61 | *value = mode->overlap; | 
|  | 62 | break; | 
| Jean-Marc Valin | 4c6bc88 | 2008-01-31 17:34:27 +1100 | [diff] [blame] | 63 | case CELT_GET_NB_CHANNELS: | 
|  | 64 | *value = mode->nbChannels; | 
|  | 65 | break; | 
| Jean-Marc Valin | cb7a2a3 | 2008-02-11 16:44:48 +1100 | [diff] [blame] | 66 | default: | 
|  | 67 | return CELT_BAD_ARG; | 
| Jean-Marc Valin | f997ad5 | 2008-01-31 16:47:16 +1100 | [diff] [blame] | 68 | } | 
| Jean-Marc Valin | cb7a2a3 | 2008-02-11 16:44:48 +1100 | [diff] [blame] | 69 | return CELT_OK; | 
| Jean-Marc Valin | f997ad5 | 2008-01-31 16:47:16 +1100 | [diff] [blame] | 70 | } | 
|  | 71 |  | 
| Jean-Marc Valin | 5588d52 | 2008-03-10 15:07:58 +1100 | [diff] [blame^] | 72 | #ifndef STATIC_MODES | 
|  | 73 |  | 
| Jean-Marc Valin | 134492a | 2008-02-18 16:46:22 +1100 | [diff] [blame] | 74 | #define PBANDS 8 | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 75 | #define MIN_BINS 4 | 
| Jean-Marc Valin | 17683eb | 2008-02-18 21:45:19 +1100 | [diff] [blame] | 76 | /* Defining 25 critical bands for the full 0-20 kHz audio bandwidth | 
|  | 77 | Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */ | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 78 | #define BARK_BANDS 25 | 
| Jean-Marc Valin | 25358cd | 2008-02-19 12:21:32 +1100 | [diff] [blame] | 79 | static const celt_int16_t bark_freq[BARK_BANDS+1] = { | 
| Jean-Marc Valin | 17683eb | 2008-02-18 21:45:19 +1100 | [diff] [blame] | 80 | 0,   100,   200,   300,   400, | 
|  | 81 | 510,   630,   770,   920,  1080, | 
|  | 82 | 1270,  1480,  1720,  2000,  2320, | 
|  | 83 | 2700,  3150,  3700,  4400,  5300, | 
|  | 84 | 6400,  7700,  9500, 12000, 15500, | 
|  | 85 | 20000}; | 
|  | 86 |  | 
| Jean-Marc Valin | 25358cd | 2008-02-19 12:21:32 +1100 | [diff] [blame] | 87 | static const celt_int16_t pitch_freq[PBANDS+1] ={0, 345, 689, 1034, 1378, 2067, 3273, 5340, 6374}; | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 88 |  | 
| Jean-Marc Valin | 75e9c86 | 2008-02-18 17:04:15 +1100 | [diff] [blame] | 89 | /* This allocation table is per critical band. When creating a mode, the bits get added together | 
|  | 90 | into the codec bands, which are sometimes larger than one critical band at low frequency */ | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 91 | #define BITALLOC_SIZE 10 | 
| Jean-Marc Valin | 25358cd | 2008-02-19 12:21:32 +1100 | [diff] [blame] | 92 | static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] = | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 93 | {  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, | 
| Jean-Marc Valin | 5a4bbde | 2008-02-19 14:32:08 +1100 | [diff] [blame] | 94 | 2,  2,  2,  1,  2,  2,  2,  2,  2,  1,  2,  2,  5,  5,  7,  7,  7,  5,  4,  0,  0,  0,  0,  0,  0, | 
|  | 95 | 2,  2,  2,  2,  3,  2,  2,  2,  2,  2,  3,  2,  6,  6,  8,  8,  8,  6,  5,  4,  0,  0,  0,  0,  0, | 
|  | 96 | 3,  2,  2,  2,  3,  3,  2,  3,  2,  2,  4,  3,  7,  7,  9,  9,  9,  7,  6,  5,  5,  5,  0,  0,  0, | 
|  | 97 | 3,  3,  2,  2,  3,  3,  3,  3,  3,  2,  4,  4,  9,  9, 10, 10, 10,  9,  6,  5,  5,  5,  5,  0,  0, | 
|  | 98 | 3,  3,  2,  2,  3,  3,  3,  3,  3,  3,  4,  4, 10, 10, 12, 12, 12, 10, 10, 10, 11, 10, 10,  5,  5, | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 99 | 4,  4,  4,  4,  5,  5,  5,  5,  5,  4,  7,  7, 14, 13, 13, 13, 13, 13, 15, 16, 17, 18, 20, 18, 11, | 
|  | 100 | 7,  7,  6,  6,  9,  8,  8,  8,  8,  8, 11, 11, 20, 18, 19, 19, 25, 22, 25, 30, 30, 35, 35, 35, 35, | 
|  | 101 | 8,  8,  8,  8, 10, 10, 10, 10,  9,  9, 19, 18, 25, 24, 23, 21, 29, 27, 35, 40, 42, 50, 59, 54, 51, | 
|  | 102 | 11, 11, 10, 10, 14, 13, 13, 13, 13, 12, 19, 18, 35, 34, 33, 31, 39, 37, 45, 50, 52, 60, 60, 60, 60, | 
|  | 103 | }; | 
|  | 104 |  | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 105 |  | 
| Jean-Marc Valin | 5588d52 | 2008-03-10 15:07:58 +1100 | [diff] [blame^] | 106 | static int *compute_ebands(celt_int32_t Fs, int frame_size, int *nbEBands) | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 107 | { | 
|  | 108 | int *eBands; | 
|  | 109 | int i, res, min_width, lin, low, high; | 
|  | 110 | res = (Fs+frame_size)/(2*frame_size); | 
|  | 111 | min_width = MIN_BINS*res; | 
| Jean-Marc Valin | a85657b | 2008-02-20 11:59:30 +1100 | [diff] [blame] | 112 | /*printf ("min_width = %d\n", min_width);*/ | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 113 |  | 
|  | 114 | /* Find where the linear part ends (i.e. where the spacing is more than min_width */ | 
|  | 115 | for (lin=0;lin<BARK_BANDS;lin++) | 
|  | 116 | if (bark_freq[lin+1]-bark_freq[lin] >= min_width) | 
|  | 117 | break; | 
|  | 118 |  | 
| Jean-Marc Valin | a85657b | 2008-02-20 11:59:30 +1100 | [diff] [blame] | 119 | /*printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);*/ | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 120 | low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS; | 
|  | 121 | high = BARK_BANDS-lin; | 
|  | 122 | *nbEBands = low+high; | 
|  | 123 | eBands = celt_alloc(sizeof(int)*(*nbEBands+2)); | 
|  | 124 |  | 
|  | 125 | /* Linear spacing (min_width) */ | 
|  | 126 | for (i=0;i<low;i++) | 
|  | 127 | eBands[i] = MIN_BINS*i; | 
|  | 128 | /* Spacing follows critical bands */ | 
|  | 129 | for (i=0;i<high;i++) | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 130 | eBands[i+low] = (bark_freq[lin+i]+res/2)/res; | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 131 | /* Enforce the minimum spacing at the boundary */ | 
|  | 132 | for (i=0;i<*nbEBands;i++) | 
|  | 133 | if (eBands[i] < MIN_BINS*i) | 
|  | 134 | eBands[i] = MIN_BINS*i; | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 135 | eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res; | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 136 | eBands[*nbEBands+1] = frame_size; | 
|  | 137 | if (eBands[*nbEBands] > eBands[*nbEBands+1]) | 
|  | 138 | eBands[*nbEBands] = eBands[*nbEBands+1]; | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 139 |  | 
|  | 140 | /* FIXME: Remove last band if too small */ | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 141 | /*for (i=0;i<*nbEBands+2;i++) | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 142 | printf("%d ", eBands[i]); | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 143 | printf ("\n");*/ | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 144 | return eBands; | 
|  | 145 | } | 
|  | 146 |  | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 147 | static void compute_pbands(CELTMode *mode, int res) | 
|  | 148 | { | 
|  | 149 | int i; | 
|  | 150 | int *pBands; | 
|  | 151 | pBands=celt_alloc(sizeof(int)*(PBANDS+2)); | 
|  | 152 | mode->nbPBands = PBANDS; | 
|  | 153 | for (i=0;i<PBANDS+1;i++) | 
|  | 154 | { | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 155 | pBands[i] = (pitch_freq[i]+res/2)/res; | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 156 | if (pBands[i] < mode->eBands[i]) | 
|  | 157 | pBands[i] = mode->eBands[i]; | 
|  | 158 | } | 
|  | 159 | pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1]; | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 160 | for (i=1;i<mode->nbPBands+1;i++) | 
|  | 161 | { | 
|  | 162 | int j; | 
|  | 163 | for (j=0;j<mode->nbEBands;j++) | 
|  | 164 | if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i]) | 
|  | 165 | break; | 
| Jean-Marc Valin | a85657b | 2008-02-20 11:59:30 +1100 | [diff] [blame] | 166 | /*printf ("%d %d\n", i, j);*/ | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 167 | if (mode->eBands[j] != pBands[i]) | 
|  | 168 | { | 
|  | 169 | if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] && | 
|  | 170 | mode->eBands[j] != pBands[i-1]) | 
|  | 171 | pBands[i] = mode->eBands[j]; | 
|  | 172 | else | 
|  | 173 | pBands[i] = mode->eBands[j+1]; | 
|  | 174 | } | 
|  | 175 | } | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 176 | /*for (i=0;i<mode->nbPBands+2;i++) | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 177 | printf("%d ", pBands[i]); | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 178 | printf ("\n");*/ | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 179 | mode->pBands = pBands; | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 180 | mode->pitchEnd = pBands[PBANDS]; | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 181 | } | 
|  | 182 |  | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 183 | static void compute_allocation_table(CELTMode *mode, int res) | 
|  | 184 | { | 
|  | 185 | int i, j, eband; | 
|  | 186 | int *allocVectors; | 
|  | 187 |  | 
|  | 188 | mode->nbAllocVectors = BITALLOC_SIZE; | 
|  | 189 | allocVectors = celt_alloc(sizeof(int)*(BITALLOC_SIZE*mode->nbEBands)); | 
|  | 190 | for (i=0;i<BITALLOC_SIZE;i++) | 
|  | 191 | { | 
|  | 192 | eband = 0; | 
|  | 193 | for (j=0;j<BARK_BANDS;j++) | 
|  | 194 | { | 
|  | 195 | int edge, low; | 
|  | 196 | edge = mode->eBands[eband+1]*res; | 
|  | 197 | if (edge < bark_freq[j+1]) | 
|  | 198 | { | 
|  | 199 | int num, den; | 
|  | 200 | num = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j]); | 
|  | 201 | den = bark_freq[j+1]-bark_freq[j]; | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 202 | low = (num+den/2)/den; | 
|  | 203 | allocVectors[i*mode->nbEBands+eband] += low; | 
|  | 204 | eband++; | 
|  | 205 | allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]-low; | 
|  | 206 | } else { | 
|  | 207 | allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]; | 
|  | 208 | } | 
|  | 209 | } | 
|  | 210 | } | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 211 | /*for (i=0;i<BITALLOC_SIZE;i++) | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 212 | { | 
|  | 213 | for (j=0;j<mode->nbEBands;j++) | 
|  | 214 | printf ("%2d ", allocVectors[i*mode->nbEBands+j]); | 
|  | 215 | printf ("\n"); | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 216 | }*/ | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 217 | mode->allocVectors = allocVectors; | 
|  | 218 | } | 
|  | 219 |  | 
| Jean-Marc Valin | 5588d52 | 2008-03-10 15:07:58 +1100 | [diff] [blame^] | 220 | #endif /* STATIC_MODES */ | 
| Jean-Marc Valin | 25358cd | 2008-02-19 12:21:32 +1100 | [diff] [blame] | 221 |  | 
| Jean-Marc Valin | d0f5787 | 2008-03-08 07:39:47 +1100 | [diff] [blame] | 222 | CELTMode *celt_mode_create(celt_int32_t Fs, int channels, int frame_size, int lookahead, int *error) | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 223 | { | 
| Jean-Marc Valin | f39e869 | 2008-03-10 12:13:23 +1100 | [diff] [blame] | 224 | #ifdef STATIC_MODES | 
| Jean-Marc Valin | 680a9ec | 2008-03-10 14:52:18 +1100 | [diff] [blame] | 225 | CELTMode *mode = NULL; | 
|  | 226 | int i; | 
|  | 227 | for (i=0;i<TOTAL_MODES;i++) | 
|  | 228 | { | 
|  | 229 | if (Fs == static_mode_list[i]->Fs && | 
|  | 230 | channels == static_mode_list[i]->nbChannels && | 
|  | 231 | frame_size == static_mode_list[i]->mdctSize && | 
|  | 232 | lookahead == static_mode_list[i]->overlap) | 
|  | 233 | { | 
|  | 234 | mode = static_mode_list[i]; | 
|  | 235 | break; | 
|  | 236 | } | 
|  | 237 | } | 
|  | 238 | if (mode == NULL) | 
|  | 239 | { | 
|  | 240 | celt_warning("Mode not included as part of the static modes"); | 
|  | 241 | if (error) | 
|  | 242 | *error = CELT_BAD_ARG; | 
|  | 243 | return NULL; | 
|  | 244 | } | 
| Jean-Marc Valin | f39e869 | 2008-03-10 12:13:23 +1100 | [diff] [blame] | 245 | #else | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 246 | int res; | 
| Jean-Marc Valin | f39e869 | 2008-03-10 12:13:23 +1100 | [diff] [blame] | 247 | int i; | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 248 | CELTMode *mode; | 
| Jean-Marc Valin | 3dbc1d0 | 2008-03-08 15:21:24 +1100 | [diff] [blame] | 249 | celt_word16_t *window; | 
|  | 250 |  | 
| Jean-Marc Valin | 75e9c86 | 2008-02-18 17:04:15 +1100 | [diff] [blame] | 251 | /* The good thing here is that permutation of the arguments will automatically be invalid */ | 
|  | 252 |  | 
|  | 253 | if (Fs < 32000 || Fs > 64000) | 
|  | 254 | { | 
|  | 255 | celt_warning("Sampling rate must be between 32 kHz and 64 kHz"); | 
|  | 256 | if (error) | 
|  | 257 | *error = CELT_BAD_ARG; | 
|  | 258 | return NULL; | 
|  | 259 | } | 
|  | 260 | if (channels < 0 || channels > 2) | 
|  | 261 | { | 
|  | 262 | celt_warning("Only mono and stereo supported"); | 
|  | 263 | if (error) | 
|  | 264 | *error = CELT_BAD_ARG; | 
|  | 265 | return NULL; | 
|  | 266 | } | 
|  | 267 | if (frame_size < 64 || frame_size > 256 || frame_size%2!=0) | 
|  | 268 | { | 
|  | 269 | celt_warning("Only even frame sizes between 64 and 256 are supported"); | 
|  | 270 | if (error) | 
|  | 271 | *error = CELT_BAD_ARG; | 
|  | 272 | return NULL; | 
|  | 273 | } | 
|  | 274 | if (lookahead < 32 || lookahead > frame_size) | 
|  | 275 | { | 
|  | 276 | celt_warning("The overlap must be between 32 and the frame size"); | 
|  | 277 | if (error) | 
|  | 278 | *error = CELT_BAD_ARG; | 
|  | 279 | return NULL; | 
|  | 280 | } | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 281 | res = (Fs+frame_size)/(2*frame_size); | 
|  | 282 |  | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 283 | mode = celt_alloc(sizeof(CELTMode)); | 
| Jean-Marc Valin | e6b7465 | 2008-02-20 18:01:08 +1100 | [diff] [blame] | 284 | mode->Fs = Fs; | 
| Jean-Marc Valin | 75e9c86 | 2008-02-18 17:04:15 +1100 | [diff] [blame] | 285 | mode->overlap = lookahead; | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 286 | mode->mdctSize = frame_size; | 
|  | 287 | mode->nbMdctBlocks = 1; | 
|  | 288 | mode->nbChannels = channels; | 
|  | 289 | mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands); | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 290 | compute_pbands(mode, res); | 
| Jean-Marc Valin | 8b2a592 | 2008-02-29 00:32:51 +1100 | [diff] [blame] | 291 | mode->ePredCoef = QCONST16(.8f,15); | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 292 |  | 
| Jean-Marc Valin | 9838fec | 2008-02-18 14:45:11 +1100 | [diff] [blame] | 293 | compute_allocation_table(mode, res); | 
| Jean-Marc Valin | a85657b | 2008-02-20 11:59:30 +1100 | [diff] [blame] | 294 | /*printf ("%d bands\n", mode->nbEBands);*/ | 
| Jean-Marc Valin | 81b38c2 | 2008-02-29 21:08:49 +1100 | [diff] [blame] | 295 |  | 
| Jean-Marc Valin | 3dbc1d0 | 2008-03-08 15:21:24 +1100 | [diff] [blame] | 296 | window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t)); | 
| Jean-Marc Valin | 81b38c2 | 2008-02-29 21:08:49 +1100 | [diff] [blame] | 297 |  | 
| Jean-Marc Valin | f28062f | 2008-03-03 13:24:01 +1100 | [diff] [blame] | 298 | #ifndef FIXED_POINT | 
| Jean-Marc Valin | 81b38c2 | 2008-02-29 21:08:49 +1100 | [diff] [blame] | 299 | for (i=0;i<mode->overlap;i++) | 
| Jean-Marc Valin | 3dbc1d0 | 2008-03-08 15:21:24 +1100 | [diff] [blame] | 300 | 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 Valin | f28062f | 2008-03-03 13:24:01 +1100 | [diff] [blame] | 301 | #else | 
|  | 302 | for (i=0;i<mode->overlap;i++) | 
| Jean-Marc Valin | 3dbc1d0 | 2008-03-08 15:21:24 +1100 | [diff] [blame] | 303 | 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 Valin | f28062f | 2008-03-03 13:24:01 +1100 | [diff] [blame] | 304 | #endif | 
| Jean-Marc Valin | 3dbc1d0 | 2008-03-08 15:21:24 +1100 | [diff] [blame] | 305 | mode->window = window; | 
| Jean-Marc Valin | 81b38c2 | 2008-02-29 21:08:49 +1100 | [diff] [blame] | 306 |  | 
| Jean-Marc Valin | 5588d52 | 2008-03-10 15:07:58 +1100 | [diff] [blame^] | 307 | psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs); | 
|  | 308 |  | 
| Jean-Marc Valin | 44ffd5a | 2008-02-22 00:39:25 +1100 | [diff] [blame] | 309 | mode->marker_start = MODEVALID; | 
|  | 310 | mode->marker_end = MODEVALID; | 
| Jean-Marc Valin | f39e869 | 2008-03-10 12:13:23 +1100 | [diff] [blame] | 311 | #endif | 
|  | 312 | mdct_init(&mode->mdct, 2*mode->mdctSize); | 
|  | 313 | compute_alloc_cache(mode); | 
| Jean-Marc Valin | 680a9ec | 2008-03-10 14:52:18 +1100 | [diff] [blame] | 314 | if (error) | 
|  | 315 | *error = CELT_OK; | 
| Jean-Marc Valin | 4991a56 | 2008-02-18 13:37:40 +1100 | [diff] [blame] | 316 | return mode; | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 317 | } | 
| Jean-Marc Valin | 2a8c371 | 2008-02-18 12:16:41 +1100 | [diff] [blame] | 318 |  | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 319 | void celt_mode_destroy(CELTMode *mode) | 
| Jean-Marc Valin | 81a8295 | 2008-02-17 22:41:29 +1100 | [diff] [blame] | 320 | { | 
| Jean-Marc Valin | 5588d52 | 2008-03-10 15:07:58 +1100 | [diff] [blame^] | 321 | #ifndef STATIC_MODES | 
| Jean-Marc Valin | 25358cd | 2008-02-19 12:21:32 +1100 | [diff] [blame] | 322 | int i; | 
|  | 323 | const int *prevPtr = NULL; | 
| Jean-Marc Valin | 25358cd | 2008-02-19 12:21:32 +1100 | [diff] [blame] | 324 | for (i=0;i<mode->nbEBands;i++) | 
|  | 325 | { | 
|  | 326 | if (mode->bits[i] != prevPtr) | 
|  | 327 | { | 
|  | 328 | prevPtr = mode->bits[i]; | 
|  | 329 | celt_free((int*)mode->bits[i]); | 
|  | 330 | } | 
|  | 331 | } | 
|  | 332 | celt_free((int**)mode->bits); | 
| Jean-Marc Valin | 81b38c2 | 2008-02-29 21:08:49 +1100 | [diff] [blame] | 333 | mdct_clear(&mode->mdct); | 
| Jean-Marc Valin | f39e869 | 2008-03-10 12:13:23 +1100 | [diff] [blame] | 334 | if (check_mode(mode) != CELT_OK) | 
|  | 335 | return; | 
|  | 336 | celt_free((int*)mode->eBands); | 
|  | 337 | celt_free((int*)mode->pBands); | 
|  | 338 | celt_free((int*)mode->allocVectors); | 
|  | 339 |  | 
| Jean-Marc Valin | 3dbc1d0 | 2008-03-08 15:21:24 +1100 | [diff] [blame] | 340 | celt_free((celt_word16_t*)mode->window); | 
| Jean-Marc Valin | 81b38c2 | 2008-02-29 21:08:49 +1100 | [diff] [blame] | 341 |  | 
| Jean-Marc Valin | 44ffd5a | 2008-02-22 00:39:25 +1100 | [diff] [blame] | 342 | mode->marker_start = MODEFREED; | 
|  | 343 | mode->marker_end = MODEFREED; | 
| Jean-Marc Valin | 75e9c86 | 2008-02-18 17:04:15 +1100 | [diff] [blame] | 344 | celt_free((CELTMode *)mode); | 
| Jean-Marc Valin | 5588d52 | 2008-03-10 15:07:58 +1100 | [diff] [blame^] | 345 | psydecay_clear(&mode->psy); | 
| Jean-Marc Valin | f39e869 | 2008-03-10 12:13:23 +1100 | [diff] [blame] | 346 | #endif | 
| Jean-Marc Valin | 2ca8fc3 | 2008-02-18 16:27:49 +1100 | [diff] [blame] | 347 | } | 
| Jean-Marc Valin | 44ffd5a | 2008-02-22 00:39:25 +1100 | [diff] [blame] | 348 |  | 
|  | 349 | int check_mode(const CELTMode *mode) | 
|  | 350 | { | 
|  | 351 | if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID) | 
|  | 352 | return CELT_OK; | 
|  | 353 | if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED) | 
|  | 354 | celt_warning("Using a mode that has already been freed"); | 
|  | 355 | else | 
|  | 356 | celt_warning("This is not a valid CELT mode"); | 
|  | 357 | return CELT_INVALID_MODE; | 
|  | 358 | } |