blob: dc28805846d8daa0f6f661bfaf1f65ad1e348c5b [file] [log] [blame]
Jean-Marc Valindba28a52008-02-18 23:40:43 +11001/* (C) 2007 Timothy B. Terriberry
2 (C) 2008 Jean-Marc Valin */
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +11003/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +11007
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +11008 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110010
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110011 - 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.
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110014
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110015 - 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.
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +110018
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110019 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*/
Jean-Marc Valindba28a52008-02-18 23:40:43 +110031
32/* Functions for encoding and decoding pulse vectors. For more details, see:
33 http://people.xiph.org/~tterribe/notes/cwrs.html
34*/
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110035
36#ifdef HAVE_CONFIG_H
37#include "config.h"
38#endif
39
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110040#include <stdlib.h>
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110041#include "cwrs.h"
42
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +110043/* Knowing ncwrs() for a fixed number of pulses m and for all vector sizes n,
44 compute ncwrs() for m+1, for all n. Could also be used when m and n are
45 swapped just by changing nc */
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110046static void next_ncwrs32(celt_uint32_t *nc, int len, int nc0)
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +110047{
48 int i;
49 celt_uint32_t mem;
50
51 mem = nc[0];
52 nc[0] = nc0;
53 for (i=1;i<len;i++)
54 {
55 celt_uint32_t tmp = nc[i]+nc[i-1]+mem;
56 mem = nc[i];
57 nc[i] = tmp;
58 }
59}
60
61/* Knowing ncwrs() for a fixed number of pulses m and for all vector sizes n,
62 compute ncwrs() for m-1, for all n. Could also be used when m and n are
63 swapped just by changing nc */
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110064static void prev_ncwrs32(celt_uint32_t *nc, int len, int nc0)
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +110065{
66 int i;
67 celt_uint32_t mem;
68
69 mem = nc[0];
70 nc[0] = nc0;
71 for (i=1;i<len;i++)
72 {
73 celt_uint32_t tmp = nc[i]-nc[i-1]-mem;
74 mem = nc[i];
75 nc[i] = tmp;
76 }
77}
78
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110079static void next_ncwrs64(celt_uint64_t *nc, int len, int nc0)
Jean-Marc Valin31348842008-02-14 11:55:01 +110080{
81 int i;
82 celt_uint64_t mem;
83
84 mem = nc[0];
85 nc[0] = nc0;
86 for (i=1;i<len;i++)
87 {
88 celt_uint64_t tmp = nc[i]+nc[i-1]+mem;
89 mem = nc[i];
90 nc[i] = tmp;
91 }
92}
93
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110094static void prev_ncwrs64(celt_uint64_t *nc, int len, int nc0)
Jean-Marc Valin31348842008-02-14 11:55:01 +110095{
96 int i;
97 celt_uint64_t mem;
98
99 mem = nc[0];
100 nc[0] = nc0;
101 for (i=1;i<len;i++)
102 {
103 celt_uint64_t tmp = nc[i]-nc[i-1]-mem;
104 mem = nc[i];
105 nc[i] = tmp;
106 }
107}
108
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100109/*Returns the numer of ways of choosing _m elements from a set of size _n with
110 replacement when a sign bit is needed for each unique element.*/
111celt_uint32_t ncwrs(int _n,int _m)
112{
113 int i;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100114 celt_uint32_t nc[_n+1];
115 for (i=0;i<_n+1;i++)
116 nc[i] = 1;
117 for (i=0;i<_m;i++)
118 next_ncwrs32(nc, _n+1, 0);
119 return nc[_n];
120}
121
122/*Returns the numer of ways of choosing _m elements from a set of size _n with
123 replacement when a sign bit is needed for each unique element.*/
124celt_uint64_t ncwrs64(int _n,int _m)
Jean-Marc Valin31348842008-02-14 11:55:01 +1100125{
126 int i;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100127 celt_uint64_t nc[_n+1];
128 for (i=0;i<_n+1;i++)
129 nc[i] = 1;
130 for (i=0;i<_m;i++)
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100131 next_ncwrs64(nc, _n+1, 0);
Jean-Marc Valin31348842008-02-14 11:55:01 +1100132 return nc[_n];
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100133}
Jean-Marc Valin31348842008-02-14 11:55:01 +1100134
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100135
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100136/*Returns the _i'th combination of _m elements chosen from a set of size _n
137 with associated sign bits.
138 _x: Returns the combination with elements sorted in ascending order.
139 _s: Returns the associated sign bits.*/
Jean-Marc Valinabe043f2008-01-31 14:26:29 +1100140void cwrsi(int _n,int _m,celt_uint32_t _i,int *_x,int *_s){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100141 int j;
142 int k;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100143 celt_uint32_t nc[_n+1];
144 for (j=0;j<_n+1;j++)
145 nc[j] = 1;
146 for (k=0;k<_m-1;k++)
147 next_ncwrs32(nc, _n+1, 0);
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100148 for(k=j=0;k<_m;k++){
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100149 celt_uint32_t pn, p, t;
150 /*p=ncwrs(_n-j,_m-k-1);
151 pn=ncwrs(_n-j-1,_m-k-1);*/
152 p=nc[_n-j];
153 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100154 p+=pn;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100155 if(k>0){
156 t=p>>1;
157 if(t<=_i||_s[k-1])_i+=t;
158 }
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100159 while(p<=_i){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100160 _i-=p;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100161 j++;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100162 p=pn;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100163 /*pn=ncwrs(_n-j-1,_m-k-1);*/
164 pn=nc[_n-j-1];
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100165 p+=pn;
166 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100167 t=p>>1;
168 _s[k]=_i>=t;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100169 _x[k]=j;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100170 if(_s[k])_i-=t;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100171 if (k<_m-2)
172 prev_ncwrs32(nc, _n+1, 0);
173 else
174 prev_ncwrs32(nc, _n+1, 1);
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100175 }
176}
177
178/*Returns the index of the given combination of _m elements chosen from a set
179 of size _n with associated sign bits.
180 _x: The combination with elements sorted in ascending order.
181 _s: The associated sign bits.*/
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100182celt_uint32_t icwrs(int _n,int _m,const int *_x,const int *_s, celt_uint32_t *bound){
Jean-Marc Valinabe043f2008-01-31 14:26:29 +1100183 celt_uint32_t i;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100184 int j;
185 int k;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100186 celt_uint32_t nc[_n+1];
187 for (j=0;j<_n+1;j++)
188 nc[j] = 1;
189 for (k=0;k<_m;k++)
190 next_ncwrs32(nc, _n+1, 0);
191 if (bound)
192 *bound = nc[_n];
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100193 i=0;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100194 for(k=j=0;k<_m;k++){
Jean-Marc Valinabe043f2008-01-31 14:26:29 +1100195 celt_uint32_t pn;
196 celt_uint32_t p;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100197 if (k<_m-1)
198 prev_ncwrs32(nc, _n+1, 0);
199 else
200 prev_ncwrs32(nc, _n+1, 1);
201 /*p=ncwrs(_n-j,_m-k-1);
202 pn=ncwrs(_n-j-1,_m-k-1);*/
203 p=nc[_n-j];
204 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100205 p+=pn;
206 if(k>0)p>>=1;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100207 while(j<_x[k]){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100208 i+=p;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100209 j++;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100210 p=pn;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100211 /*pn=ncwrs(_n-j-1,_m-k-1);*/
212 pn=nc[_n-j-1];
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100213 p+=pn;
214 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100215 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100216 }
217 return i;
218}
219
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100220/*Returns the _i'th combination of _m elements chosen from a set of size _n
221 with associated sign bits.
222 _x: Returns the combination with elements sorted in ascending order.
223 _s: Returns the associated sign bits.*/
224void cwrsi64(int _n,int _m,celt_uint64_t _i,int *_x,int *_s){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100225 int j;
226 int k;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100227 celt_uint64_t nc[_n+1];
228 for (j=0;j<_n+1;j++)
229 nc[j] = 1;
230 for (k=0;k<_m-1;k++)
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100231 next_ncwrs64(nc, _n+1, 0);
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100232 for(k=j=0;k<_m;k++){
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100233 celt_uint64_t pn, p, t;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100234 /*p=ncwrs64(_n-j,_m-k-1);
235 pn=ncwrs64(_n-j-1,_m-k-1);*/
236 p=nc[_n-j];
237 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100238 p+=pn;
239 if(k>0){
240 t=p>>1;
241 if(t<=_i||_s[k-1])_i+=t;
242 }
243 while(p<=_i){
244 _i-=p;
245 j++;
246 p=pn;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100247 /*pn=ncwrs64(_n-j-1,_m-k-1);*/
248 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100249 p+=pn;
250 }
251 t=p>>1;
252 _s[k]=_i>=t;
253 _x[k]=j;
254 if(_s[k])_i-=t;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100255 if (k<_m-2)
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100256 prev_ncwrs64(nc, _n+1, 0);
Jean-Marc Valin31348842008-02-14 11:55:01 +1100257 else
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100258 prev_ncwrs64(nc, _n+1, 1);
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100259 }
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100260}
261
262/*Returns the index of the given combination of _m elements chosen from a set
263 of size _n with associated sign bits.
264 _x: The combination with elements sorted in ascending order.
265 _s: The associated sign bits.*/
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100266celt_uint64_t icwrs64(int _n,int _m,const int *_x,const int *_s, celt_uint64_t *bound){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100267 celt_uint64_t i;
268 int j;
269 int k;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100270 celt_uint64_t nc[_n+1];
271 for (j=0;j<_n+1;j++)
272 nc[j] = 1;
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100273 for (k=0;k<_m;k++)
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100274 next_ncwrs64(nc, _n+1, 0);
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100275 if (bound)
276 *bound = nc[_n];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100277 i=0;
278 for(k=j=0;k<_m;k++){
279 celt_uint64_t pn;
280 celt_uint64_t p;
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100281 if (k<_m-1)
282 prev_ncwrs64(nc, _n+1, 0);
283 else
284 prev_ncwrs64(nc, _n+1, 1);
Jean-Marc Valin31348842008-02-14 11:55:01 +1100285 /*p=ncwrs64(_n-j,_m-k-1);
286 pn=ncwrs64(_n-j-1,_m-k-1);*/
287 p=nc[_n-j];
288 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100289 p+=pn;
290 if(k>0)p>>=1;
291 while(j<_x[k]){
292 i+=p;
293 j++;
294 p=pn;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100295 /*pn=ncwrs64(_n-j-1,_m-k-1);*/
296 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100297 p+=pn;
298 }
299 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
300 }
301 return i;
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100302}
303
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100304/*Converts a combination _x of _m unit pulses with associated sign bits _s into
305 a pulse vector _y of length _n.
306 _y: Returns the vector of pulses.
307 _x: The combination with elements sorted in ascending order.
308 _s: The associated sign bits.*/
309void comb2pulse(int _n,int _m,int *_y,const int *_x,const int *_s){
310 int j;
311 int k;
312 int n;
313 for(k=j=0;k<_m;k+=n){
314 for(n=1;k+n<_m&&_x[k+n]==_x[k];n++);
315 while(j<_x[k])_y[j++]=0;
316 _y[j++]=_s[k]?-n:n;
317 }
318 while(j<_n)_y[j++]=0;
319}
320
321/*Converts a pulse vector vector _y of length _n into a combination of _m unit
322 pulses with associated sign bits _s.
323 _x: Returns the combination with elements sorted in ascending order.
324 _s: Returns the associated sign bits.
325 _y: The vector of pulses, whose sum of absolute values must be _m.*/
326void pulse2comb(int _n,int _m,int *_x,int *_s,const int *_y){
327 int j;
328 int k;
329 for(k=j=0;j<_n;j++){
330 if(_y[j]){
331 int n;
332 int s;
333 n=abs(_y[j]);
334 s=_y[j]<0;
335 for(;n-->0;k++){
336 _x[k]=j;
337 _s[k]=s;
338 }
339 }
340 }
341}
342
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100343void encode_pulses(int *_y, int N, int K, ec_enc *enc)
344{
345 int comb[K];
346 int signs[K];
347 pulse2comb(N, K, comb, signs, _y);
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100348 /* Go with 32-bit path if we're sure we can */
349 if (N<=13 && K<=13)
350 {
351 celt_uint32_t bound, id;
352 id = icwrs(N, K, comb, signs, &bound);
353 ec_enc_uint(enc,id,bound);
354 } else {
355 celt_uint64_t bound, id;
356 id = icwrs64(N, K, comb, signs, &bound);
357 ec_enc_uint64(enc,id,bound);
358 }
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100359}
360
361void decode_pulses(int *_y, int N, int K, ec_dec *dec)
362{
363 int comb[K];
364 int signs[K];
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100365 if (N<=13 && K<=13)
366 {
367 cwrsi(N, K, ec_dec_uint(dec, ncwrs(N, K)), comb, signs);
368 comb2pulse(N, K, _y, comb, signs);
369 } else {
370 cwrsi64(N, K, ec_dec_uint64(dec, ncwrs64(N, K)), comb, signs);
371 comb2pulse(N, K, _y, comb, signs);
372 }
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100373}
374