blob: af20945c2917b95914c1597007ed4ffb7c592f6e [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*/
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110035#include <stdlib.h>
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +110036#include "cwrs.h"
37
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +110038/* Knowing ncwrs() for a fixed number of pulses m and for all vector sizes n,
39 compute ncwrs() for m+1, for all n. Could also be used when m and n are
40 swapped just by changing nc */
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110041static void next_ncwrs32(celt_uint32_t *nc, int len, int nc0)
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +110042{
43 int i;
44 celt_uint32_t mem;
45
46 mem = nc[0];
47 nc[0] = nc0;
48 for (i=1;i<len;i++)
49 {
50 celt_uint32_t tmp = nc[i]+nc[i-1]+mem;
51 mem = nc[i];
52 nc[i] = tmp;
53 }
54}
55
56/* Knowing ncwrs() for a fixed number of pulses m and for all vector sizes n,
57 compute ncwrs() for m-1, for all n. Could also be used when m and n are
58 swapped just by changing nc */
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110059static void prev_ncwrs32(celt_uint32_t *nc, int len, int nc0)
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +110060{
61 int i;
62 celt_uint32_t mem;
63
64 mem = nc[0];
65 nc[0] = nc0;
66 for (i=1;i<len;i++)
67 {
68 celt_uint32_t tmp = nc[i]-nc[i-1]-mem;
69 mem = nc[i];
70 nc[i] = tmp;
71 }
72}
73
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110074static void next_ncwrs64(celt_uint64_t *nc, int len, int nc0)
Jean-Marc Valin31348842008-02-14 11:55:01 +110075{
76 int i;
77 celt_uint64_t mem;
78
79 mem = nc[0];
80 nc[0] = nc0;
81 for (i=1;i<len;i++)
82 {
83 celt_uint64_t tmp = nc[i]+nc[i-1]+mem;
84 mem = nc[i];
85 nc[i] = tmp;
86 }
87}
88
Jean-Marc Valin472a5f02008-02-19 13:12:32 +110089static void prev_ncwrs64(celt_uint64_t *nc, int len, int nc0)
Jean-Marc Valin31348842008-02-14 11:55:01 +110090{
91 int i;
92 celt_uint64_t mem;
93
94 mem = nc[0];
95 nc[0] = nc0;
96 for (i=1;i<len;i++)
97 {
98 celt_uint64_t tmp = nc[i]-nc[i-1]-mem;
99 mem = nc[i];
100 nc[i] = tmp;
101 }
102}
103
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100104/*Returns the numer of ways of choosing _m elements from a set of size _n with
105 replacement when a sign bit is needed for each unique element.*/
106celt_uint32_t ncwrs(int _n,int _m)
107{
108 int i;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100109 celt_uint32_t nc[_n+1];
110 for (i=0;i<_n+1;i++)
111 nc[i] = 1;
112 for (i=0;i<_m;i++)
113 next_ncwrs32(nc, _n+1, 0);
114 return nc[_n];
115}
116
117/*Returns the numer of ways of choosing _m elements from a set of size _n with
118 replacement when a sign bit is needed for each unique element.*/
119celt_uint64_t ncwrs64(int _n,int _m)
Jean-Marc Valin31348842008-02-14 11:55:01 +1100120{
121 int i;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100122 celt_uint64_t nc[_n+1];
123 for (i=0;i<_n+1;i++)
124 nc[i] = 1;
125 for (i=0;i<_m;i++)
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100126 next_ncwrs64(nc, _n+1, 0);
Jean-Marc Valin31348842008-02-14 11:55:01 +1100127 return nc[_n];
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100128}
Jean-Marc Valin31348842008-02-14 11:55:01 +1100129
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100130
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100131/*Returns the _i'th combination of _m elements chosen from a set of size _n
132 with associated sign bits.
133 _x: Returns the combination with elements sorted in ascending order.
134 _s: Returns the associated sign bits.*/
Jean-Marc Valinabe043f2008-01-31 14:26:29 +1100135void cwrsi(int _n,int _m,celt_uint32_t _i,int *_x,int *_s){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100136 int j;
137 int k;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100138 celt_uint32_t nc[_n+1];
139 for (j=0;j<_n+1;j++)
140 nc[j] = 1;
141 for (k=0;k<_m-1;k++)
142 next_ncwrs32(nc, _n+1, 0);
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100143 for(k=j=0;k<_m;k++){
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100144 celt_uint32_t pn, p, t;
145 /*p=ncwrs(_n-j,_m-k-1);
146 pn=ncwrs(_n-j-1,_m-k-1);*/
147 p=nc[_n-j];
148 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100149 p+=pn;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100150 if(k>0){
151 t=p>>1;
152 if(t<=_i||_s[k-1])_i+=t;
153 }
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100154 while(p<=_i){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100155 _i-=p;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100156 j++;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100157 p=pn;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100158 /*pn=ncwrs(_n-j-1,_m-k-1);*/
159 pn=nc[_n-j-1];
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100160 p+=pn;
161 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100162 t=p>>1;
163 _s[k]=_i>=t;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100164 _x[k]=j;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100165 if(_s[k])_i-=t;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100166 if (k<_m-2)
167 prev_ncwrs32(nc, _n+1, 0);
168 else
169 prev_ncwrs32(nc, _n+1, 1);
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100170 }
171}
172
173/*Returns the index of the given combination of _m elements chosen from a set
174 of size _n with associated sign bits.
175 _x: The combination with elements sorted in ascending order.
176 _s: The associated sign bits.*/
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100177celt_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 +1100178 celt_uint32_t i;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100179 int j;
180 int k;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100181 celt_uint32_t nc[_n+1];
182 for (j=0;j<_n+1;j++)
183 nc[j] = 1;
184 for (k=0;k<_m;k++)
185 next_ncwrs32(nc, _n+1, 0);
186 if (bound)
187 *bound = nc[_n];
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100188 i=0;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100189 for(k=j=0;k<_m;k++){
Jean-Marc Valinabe043f2008-01-31 14:26:29 +1100190 celt_uint32_t pn;
191 celt_uint32_t p;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100192 if (k<_m-1)
193 prev_ncwrs32(nc, _n+1, 0);
194 else
195 prev_ncwrs32(nc, _n+1, 1);
196 /*p=ncwrs(_n-j,_m-k-1);
197 pn=ncwrs(_n-j-1,_m-k-1);*/
198 p=nc[_n-j];
199 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100200 p+=pn;
201 if(k>0)p>>=1;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100202 while(j<_x[k]){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100203 i+=p;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100204 j++;
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100205 p=pn;
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100206 /*pn=ncwrs(_n-j-1,_m-k-1);*/
207 pn=nc[_n-j-1];
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100208 p+=pn;
209 }
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100210 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100211 }
212 return i;
213}
214
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100215/*Returns the _i'th combination of _m elements chosen from a set of size _n
216 with associated sign bits.
217 _x: Returns the combination with elements sorted in ascending order.
218 _s: Returns the associated sign bits.*/
219void cwrsi64(int _n,int _m,celt_uint64_t _i,int *_x,int *_s){
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100220 int j;
221 int k;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100222 celt_uint64_t nc[_n+1];
223 for (j=0;j<_n+1;j++)
224 nc[j] = 1;
225 for (k=0;k<_m-1;k++)
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100226 next_ncwrs64(nc, _n+1, 0);
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100227 for(k=j=0;k<_m;k++){
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100228 celt_uint64_t pn, p, t;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100229 /*p=ncwrs64(_n-j,_m-k-1);
230 pn=ncwrs64(_n-j-1,_m-k-1);*/
231 p=nc[_n-j];
232 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100233 p+=pn;
234 if(k>0){
235 t=p>>1;
236 if(t<=_i||_s[k-1])_i+=t;
237 }
238 while(p<=_i){
239 _i-=p;
240 j++;
241 p=pn;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100242 /*pn=ncwrs64(_n-j-1,_m-k-1);*/
243 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100244 p+=pn;
245 }
246 t=p>>1;
247 _s[k]=_i>=t;
248 _x[k]=j;
249 if(_s[k])_i-=t;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100250 if (k<_m-2)
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100251 prev_ncwrs64(nc, _n+1, 0);
Jean-Marc Valin31348842008-02-14 11:55:01 +1100252 else
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100253 prev_ncwrs64(nc, _n+1, 1);
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100254 }
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100255}
256
257/*Returns the index of the given combination of _m elements chosen from a set
258 of size _n with associated sign bits.
259 _x: The combination with elements sorted in ascending order.
260 _s: The associated sign bits.*/
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100261celt_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 +1100262 celt_uint64_t i;
263 int j;
264 int k;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100265 celt_uint64_t nc[_n+1];
266 for (j=0;j<_n+1;j++)
267 nc[j] = 1;
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100268 for (k=0;k<_m;k++)
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100269 next_ncwrs64(nc, _n+1, 0);
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100270 if (bound)
271 *bound = nc[_n];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100272 i=0;
273 for(k=j=0;k<_m;k++){
274 celt_uint64_t pn;
275 celt_uint64_t p;
Jean-Marc Valinbf17da62008-02-14 14:18:19 +1100276 if (k<_m-1)
277 prev_ncwrs64(nc, _n+1, 0);
278 else
279 prev_ncwrs64(nc, _n+1, 1);
Jean-Marc Valin31348842008-02-14 11:55:01 +1100280 /*p=ncwrs64(_n-j,_m-k-1);
281 pn=ncwrs64(_n-j-1,_m-k-1);*/
282 p=nc[_n-j];
283 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100284 p+=pn;
285 if(k>0)p>>=1;
286 while(j<_x[k]){
287 i+=p;
288 j++;
289 p=pn;
Jean-Marc Valin31348842008-02-14 11:55:01 +1100290 /*pn=ncwrs64(_n-j-1,_m-k-1);*/
291 pn=nc[_n-j-1];
Timothy B. Terriberry71c9bbf2008-01-01 07:18:06 +1100292 p+=pn;
293 }
294 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
295 }
296 return i;
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100297}
298
Timothy B. Terriberryc4541ae2007-12-03 11:51:29 +1100299/*Converts a combination _x of _m unit pulses with associated sign bits _s into
300 a pulse vector _y of length _n.
301 _y: Returns the vector of pulses.
302 _x: The combination with elements sorted in ascending order.
303 _s: The associated sign bits.*/
304void comb2pulse(int _n,int _m,int *_y,const int *_x,const int *_s){
305 int j;
306 int k;
307 int n;
308 for(k=j=0;k<_m;k+=n){
309 for(n=1;k+n<_m&&_x[k+n]==_x[k];n++);
310 while(j<_x[k])_y[j++]=0;
311 _y[j++]=_s[k]?-n:n;
312 }
313 while(j<_n)_y[j++]=0;
314}
315
316/*Converts a pulse vector vector _y of length _n into a combination of _m unit
317 pulses with associated sign bits _s.
318 _x: Returns the combination with elements sorted in ascending order.
319 _s: Returns the associated sign bits.
320 _y: The vector of pulses, whose sum of absolute values must be _m.*/
321void pulse2comb(int _n,int _m,int *_x,int *_s,const int *_y){
322 int j;
323 int k;
324 for(k=j=0;j<_n;j++){
325 if(_y[j]){
326 int n;
327 int s;
328 n=abs(_y[j]);
329 s=_y[j]<0;
330 for(;n-->0;k++){
331 _x[k]=j;
332 _s[k]=s;
333 }
334 }
335 }
336}
337
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100338void encode_pulses(int *_y, int N, int K, ec_enc *enc)
339{
340 int comb[K];
341 int signs[K];
342 pulse2comb(N, K, comb, signs, _y);
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100343 /* Go with 32-bit path if we're sure we can */
344 if (N<=13 && K<=13)
345 {
346 celt_uint32_t bound, id;
347 id = icwrs(N, K, comb, signs, &bound);
348 ec_enc_uint(enc,id,bound);
349 } else {
350 celt_uint64_t bound, id;
351 id = icwrs64(N, K, comb, signs, &bound);
352 ec_enc_uint64(enc,id,bound);
353 }
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100354}
355
356void decode_pulses(int *_y, int N, int K, ec_dec *dec)
357{
358 int comb[K];
359 int signs[K];
Jean-Marc Valin0d28aa92008-02-14 15:02:04 +1100360 if (N<=13 && K<=13)
361 {
362 cwrsi(N, K, ec_dec_uint(dec, ncwrs(N, K)), comb, signs);
363 comb2pulse(N, K, _y, comb, signs);
364 } else {
365 cwrsi64(N, K, ec_dec_uint64(dec, ncwrs64(N, K)), comb, signs);
366 comb2pulse(N, K, _y, comb, signs);
367 }
Jean-Marc Valin5fa59952008-02-14 13:50:44 +1100368}
369