Some error reporting in the mode generation code. More cleanup
[opus.git] / libcelt / modes.c
1 /* (C) 2007 Jean-Marc Valin, CSIRO
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
32 #include "celt.h"
33 #include "modes.h"
34 #include "os_support.h"
35
36 int celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
37 {
38    switch (request)
39    {
40       case CELT_GET_FRAME_SIZE:
41          *value = mode->mdctSize;
42          break;
43       case CELT_GET_LOOKAHEAD:
44          *value = mode->overlap;
45          break;
46       case CELT_GET_NB_CHANNELS:
47          *value = mode->nbChannels;
48          break;
49       default:
50          return CELT_BAD_ARG;
51    }
52    return CELT_OK;
53 }
54
55 #define PBANDS 8
56 #define MIN_BINS 4
57 /* Defining 25 critical bands for the full 0-20 kHz audio bandwidth */
58 #define BARK_BANDS 25
59 const celt_int16_t bark_freq[BARK_BANDS+1] = {
60       0,   101,   200,   301,   405,
61     516,   635,   766,   912,  1077,
62    1263,  1476,  1720,  2003,  2333,
63    2721,  3184,  3742,  4428,  5285,
64    6376,  7791,  9662, 12181, 15624,
65    20397};
66    
67 const celt_int16_t pitch_freq[PBANDS+1] ={0, 345, 689, 1034, 1378, 2067, 3273, 5340, 6374};
68
69 /* This allocation table is per critical band. When creating a mode, the bits get added together 
70    into the codec bands, which are sometimes larger than one critical band at low frequency */
71 #define BITALLOC_SIZE 10
72 int band_allocation[BARK_BANDS*BITALLOC_SIZE] = 
73    {  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,
74       2,  2,  2,  1,  2,  2,  2,  2,  2,  1,  2,  2,  3,  3,  3,  3,  3,  3,  3,  0,  0,  0,  0,  0,  0,
75       2,  2,  2,  2,  3,  2,  2,  2,  2,  2,  3,  2,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0,
76       3,  2,  2,  2,  3,  3,  2,  3,  2,  2,  4,  3,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  0,  0,  0,
77       3,  3,  2,  2,  3,  3,  3,  3,  3,  2,  4,  4,  7,  7,  5,  5,  5,  5,  5,  5,  5,  5,  5,  0,  0,
78       3,  3,  2,  2,  3,  3,  3,  3,  3,  3,  4,  4,  8,  8,  8,  8,  8,  8,  9, 10, 11, 10, 10,  5,  5,
79       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,
80       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,
81       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,
82      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,
83    };
84
85
86 static int *compute_ebands(int Fs, int frame_size, int *nbEBands)
87 {
88    int *eBands;
89    int i, res, min_width, lin, low, high;
90    res = (Fs+frame_size)/(2*frame_size);
91    min_width = MIN_BINS*res;
92    //printf ("min_width = %d\n", min_width);
93
94    /* Find where the linear part ends (i.e. where the spacing is more than min_width */
95    for (lin=0;lin<BARK_BANDS;lin++)
96       if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
97          break;
98    
99    //printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);
100    low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
101    high = BARK_BANDS-lin;
102    *nbEBands = low+high;
103    eBands = celt_alloc(sizeof(int)*(*nbEBands+2));
104    
105    /* Linear spacing (min_width) */
106    for (i=0;i<low;i++)
107       eBands[i] = MIN_BINS*i;
108    /* Spacing follows critical bands */
109    for (i=0;i<high;i++)
110       eBands[i+low] = (bark_freq[lin+i]+res/2)/res;
111    /* Enforce the minimum spacing at the boundary */
112    for (i=0;i<*nbEBands;i++)
113       if (eBands[i] < MIN_BINS*i)
114          eBands[i] = MIN_BINS*i;
115    eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res;
116    eBands[*nbEBands+1] = frame_size;
117    if (eBands[*nbEBands] > eBands[*nbEBands+1])
118       eBands[*nbEBands] = eBands[*nbEBands+1];
119    
120    /* FIXME: Remove last band if too small */
121    /*for (i=0;i<*nbEBands+2;i++)
122       printf("%d ", eBands[i]);
123    printf ("\n");*/
124    return eBands;
125 }
126
127 static void compute_pbands(CELTMode *mode, int res)
128 {
129    int i;
130    int *pBands;
131    pBands=celt_alloc(sizeof(int)*(PBANDS+2));
132    mode->nbPBands = PBANDS;
133    for (i=0;i<PBANDS+1;i++)
134    {
135       pBands[i] = (pitch_freq[i]+res/2)/res;
136       if (pBands[i] < mode->eBands[i])
137          pBands[i] = mode->eBands[i];
138    }
139    pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
140    for (i=1;i<mode->nbPBands+1;i++)
141    {
142       int j;
143       for (j=0;j<mode->nbEBands;j++)
144          if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
145             break;
146       //printf ("%d %d\n", i, j);
147       if (mode->eBands[j] != pBands[i])
148       {
149          if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] && 
150              mode->eBands[j] != pBands[i-1])
151             pBands[i] = mode->eBands[j];
152          else
153             pBands[i] = mode->eBands[j+1];
154       }
155    }
156    /*for (i=0;i<mode->nbPBands+2;i++)
157       printf("%d ", pBands[i]);
158    printf ("\n");*/
159    mode->pBands = pBands;
160    mode->pitchEnd = pBands[PBANDS];
161 }
162
163 static void compute_allocation_table(CELTMode *mode, int res)
164 {
165    int i, j, eband;
166    int *allocVectors;
167    
168    mode->nbAllocVectors = BITALLOC_SIZE;
169    allocVectors = celt_alloc(sizeof(int)*(BITALLOC_SIZE*mode->nbEBands));
170    for (i=0;i<BITALLOC_SIZE;i++)
171    {
172       eband = 0;
173       for (j=0;j<BARK_BANDS;j++)
174       {
175          int edge, low;
176          edge = mode->eBands[eband+1]*res;
177          if (edge < bark_freq[j+1])
178          {
179             int num, den;
180             num = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j]);
181             den = bark_freq[j+1]-bark_freq[j];
182             //low = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j])/(bark_freq[j+1]-bark_freq[j]);
183             low = (num+den/2)/den;
184             allocVectors[i*mode->nbEBands+eband] += low;
185             eband++;
186             allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]-low;
187          } else {
188             allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j];
189          }
190       }
191    }
192    /*for (i=0;i<BITALLOC_SIZE;i++)
193    {
194       for (j=0;j<mode->nbEBands;j++)
195          printf ("%2d ", allocVectors[i*mode->nbEBands+j]);
196       printf ("\n");
197    }*/
198    mode->allocVectors = allocVectors;
199 }
200
201 CELTMode *celt_mode_create(int Fs, int channels, int frame_size, int lookahead, int *error)
202 {
203    int res;
204    CELTMode *mode;
205    
206    /* The good thing here is that permutation of the arguments will automatically be invalid */
207    
208    if (Fs < 32000 || Fs > 64000)
209    {
210       celt_warning("Sampling rate must be between 32 kHz and 64 kHz");
211       if (error)
212          *error = CELT_BAD_ARG;
213       return NULL;
214    }
215    if (channels < 0 || channels > 2)
216    {
217       celt_warning("Only mono and stereo supported");
218       if (error)
219          *error = CELT_BAD_ARG;
220       return NULL;
221    }
222    if (frame_size < 64 || frame_size > 256 || frame_size%2!=0)
223    {
224       celt_warning("Only even frame sizes between 64 and 256 are supported");
225       if (error)
226          *error = CELT_BAD_ARG;
227       return NULL;
228    }
229    if (lookahead < 32 || lookahead > frame_size)
230    {
231       celt_warning("The overlap must be between 32 and the frame size");
232       if (error)
233          *error = CELT_BAD_ARG;
234       return NULL;
235    }
236    res = (Fs+frame_size)/(2*frame_size);
237    
238    mode = celt_alloc(sizeof(CELTMode));
239    mode->overlap = lookahead;
240    mode->mdctSize = frame_size;
241    mode->nbMdctBlocks = 1;
242    mode->nbChannels = channels;
243    mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
244    compute_pbands(mode, res);
245    mode->ePredCoef = .8;
246    
247    compute_allocation_table(mode, res);
248    
249    //printf ("%d bands\n", mode->nbEBands);
250    return mode;
251 }
252
253 void celt_mode_destroy(CELTMode *mode)
254 {
255    celt_free((int*)mode->eBands);
256    celt_free((int*)mode->pBands);
257    celt_free((int*)mode->allocVectors);
258    celt_free((CELTMode *)mode);
259 }