Removed all hard-coded modes
[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 #define BARK_BANDS 25
58 const celt_int16_t bark_freq[BARK_BANDS+1] = {
59       0,   101,   200,   301,   405,
60     516,   635,   766,   912,  1077,
61    1263,  1476,  1720,  2003,  2333,
62    2721,  3184,  3742,  4428,  5285,
63    6376,  7791,  9662, 12181, 15624,
64    20397};
65    
66 const celt_int16_t pitch_freq[PBANDS+1] ={0, 345, 689, 1034, 1378, 2067, 3273, 5340, 6374};
67
68 #define BITALLOC_SIZE 10
69 int band_allocation[BARK_BANDS*BITALLOC_SIZE] = 
70    {  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,
71       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,
72       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,
73       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,
74       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,
75       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,
76       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,
77       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,
78       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,
79      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,
80    };
81
82
83 static int *compute_ebands(int Fs, int frame_size, int *nbEBands)
84 {
85    int *eBands;
86    int i, res, min_width, lin, low, high;
87    res = (Fs+frame_size)/(2*frame_size);
88    min_width = MIN_BINS*res;
89    //printf ("min_width = %d\n", min_width);
90
91    /* Find where the linear part ends (i.e. where the spacing is more than min_width */
92    for (lin=0;lin<BARK_BANDS;lin++)
93       if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
94          break;
95    
96    //printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);
97    low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
98    high = BARK_BANDS-lin;
99    *nbEBands = low+high;
100    eBands = celt_alloc(sizeof(int)*(*nbEBands+2));
101    
102    /* Linear spacing (min_width) */
103    for (i=0;i<low;i++)
104       eBands[i] = MIN_BINS*i;
105    /* Spacing follows critical bands */
106    for (i=0;i<high;i++)
107       eBands[i+low] = (bark_freq[lin+i]+res/2)/res;
108    /* Enforce the minimum spacing at the boundary */
109    for (i=0;i<*nbEBands;i++)
110       if (eBands[i] < MIN_BINS*i)
111          eBands[i] = MIN_BINS*i;
112    eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res;
113    eBands[*nbEBands+1] = frame_size;
114    if (eBands[*nbEBands] > eBands[*nbEBands+1])
115       eBands[*nbEBands] = eBands[*nbEBands+1];
116    
117    /* FIXME: Remove last band if too small */
118    /*for (i=0;i<*nbEBands+2;i++)
119       printf("%d ", eBands[i]);
120    printf ("\n");*/
121    return eBands;
122 }
123
124 static void compute_pbands(CELTMode *mode, int res)
125 {
126    int i;
127    int *pBands;
128    pBands=celt_alloc(sizeof(int)*(PBANDS+2));
129    mode->nbPBands = PBANDS;
130    for (i=0;i<PBANDS+1;i++)
131    {
132       pBands[i] = (pitch_freq[i]+res/2)/res;
133       if (pBands[i] < mode->eBands[i])
134          pBands[i] = mode->eBands[i];
135    }
136    pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
137    for (i=1;i<mode->nbPBands+1;i++)
138    {
139       int j;
140       for (j=0;j<mode->nbEBands;j++)
141          if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
142             break;
143       //printf ("%d %d\n", i, j);
144       if (mode->eBands[j] != pBands[i])
145       {
146          if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] && 
147              mode->eBands[j] != pBands[i-1])
148             pBands[i] = mode->eBands[j];
149          else
150             pBands[i] = mode->eBands[j+1];
151       }
152    }
153    /*for (i=0;i<mode->nbPBands+2;i++)
154       printf("%d ", pBands[i]);
155    printf ("\n");*/
156    mode->pBands = pBands;
157    mode->pitchEnd = pBands[PBANDS];
158 }
159
160 static void compute_allocation_table(CELTMode *mode, int res)
161 {
162    int i, j, eband;
163    int *allocVectors;
164    
165    mode->nbAllocVectors = BITALLOC_SIZE;
166    allocVectors = celt_alloc(sizeof(int)*(BITALLOC_SIZE*mode->nbEBands));
167    for (i=0;i<BITALLOC_SIZE;i++)
168    {
169       eband = 0;
170       for (j=0;j<BARK_BANDS;j++)
171       {
172          int edge, low;
173          edge = mode->eBands[eband+1]*res;
174          if (edge < bark_freq[j+1])
175          {
176             int num, den;
177             num = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j]);
178             den = bark_freq[j+1]-bark_freq[j];
179             //low = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j])/(bark_freq[j+1]-bark_freq[j]);
180             low = (num+den/2)/den;
181             allocVectors[i*mode->nbEBands+eband] += low;
182             eband++;
183             allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]-low;
184          } else {
185             allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j];
186          }
187       }
188    }
189    /*for (i=0;i<BITALLOC_SIZE;i++)
190    {
191       for (j=0;j<mode->nbEBands;j++)
192          printf ("%2d ", allocVectors[i*mode->nbEBands+j]);
193       printf ("\n");
194    }*/
195    mode->allocVectors = allocVectors;
196 }
197
198 CELTMode *celt_mode_create(int Fs, int channels, int frame_size, int overlap)
199 {
200    int res;
201    CELTMode *mode;
202    
203    res = (Fs+frame_size)/(2*frame_size);
204    
205    mode = celt_alloc(sizeof(CELTMode));
206    mode->overlap = overlap;
207    mode->mdctSize = frame_size;
208    mode->nbMdctBlocks = 1;
209    mode->nbChannels = channels;
210    mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
211    compute_pbands(mode, res);
212    mode->ePredCoef = .8;
213    
214    compute_allocation_table(mode, res);
215    
216    //printf ("%d bands\n", mode->nbEBands);
217    return mode;
218 }
219
220 void celt_mode_destroy(CELTMode *mode)
221 {
222    celt_free((int*)mode->eBands);
223    celt_free((int*)mode->pBands);
224    celt_free((int*)mode->allocVectors);
225 }