1 /* (C) 2007-2008 Timothy B. Terriberry
2 (C) 2008 Jean-Marc Valin */
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
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.
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.
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.
32 /* Functions for encoding and decoding pulse vectors.
33 These are based on the function
34 U(n,m) = U(n-1,m) + U(n,m-1) + U(n-1,m-1),
36 which counts the number of ways of placing m pulses in n dimensions, where
37 at least one pulse lies in dimension 0.
38 For more details, see: http://people.xiph.org/~tterribe/notes/cwrs.html
45 #include "os_support.h"
53 int log2_frac(ec_uint32 val, int frac)
56 /* EC_ILOG() actually returns log2()+1, go figure */
57 int L = EC_ILOG(val)-1;
58 /*printf ("in: %d %d ", val, L);*/
64 /*printf ("%d\n", val);*/
67 val = (val*val) >> 15;
68 /*printf ("%d\n", val);*/
78 int log2_frac64(ec_uint64 val, int frac)
81 /* EC_ILOG64() actually returns log2()+1, go figure */
82 int L = EC_ILOG64(val)-1;
83 /*printf ("in: %d %d ", val, L);*/
89 /*printf ("%d\n", val);*/
92 val = (val*val) >> 15;
93 /*printf ("%d\n", val);*/
102 int fits_in32(int _n, int _m)
104 static const celt_int16_t maxN[15] = {
105 255, 255, 255, 255, 255, 109, 60, 40,
106 29, 24, 20, 18, 16, 14, 13};
107 static const celt_int16_t maxM[15] = {
108 255, 255, 255, 255, 255, 238, 95, 53,
109 36, 27, 22, 18, 16, 15, 13};
115 return _n <= maxN[_m];
117 return _m <= maxM[_n];
120 int fits_in64(int _n, int _m)
122 static const celt_int16_t maxN[28] = {
123 255, 255, 255, 255, 255, 255, 255, 255,
124 255, 255, 178, 129, 100, 81, 68, 58,
125 51, 46, 42, 38, 36, 33, 31, 30,
127 static const celt_int16_t maxM[28] = {
128 255, 255, 255, 255, 255, 255, 255, 255,
129 255, 255, 245, 166, 122, 94, 77, 64,
130 56, 49, 44, 40, 37, 34, 32, 30,
137 return _n <= maxN[_m];
139 return _m <= maxM[_n];
143 /*Computes the next row/column of any recurrence that obeys the relation
144 u[i][j]=u[i-1][j]+u[i][j-1]+u[i-1][j-1].
145 _ui0 is the base case for the new row/column.*/
146 static inline void unext32(celt_uint32_t *_ui,int _len,celt_uint32_t _ui0){
149 /* doing a do-while would overrun the array if we had less than 2 samples */
151 ui1=UADD32(UADD32(_ui[j],_ui[j-1]),_ui0);
158 static inline void unext64(celt_uint64_t *_ui,int _len,celt_uint64_t _ui0){
161 /* doing a do-while would overrun the array if we had less than 2 samples */
163 ui1=_ui[j]+_ui[j-1]+_ui0;
170 /*Computes the previous row/column of any recurrence that obeys the relation
171 u[i-1][j]=u[i][j]-u[i][j-1]-u[i-1][j-1].
172 _ui0 is the base case for the new row/column.*/
173 static inline void uprev32(celt_uint32_t *_ui,int _n,celt_uint32_t _ui0){
176 /* doing a do-while would overrun the array if we had less than 2 samples */
178 ui1=USUB32(USUB32(_ui[j],_ui[j-1]),_ui0);
185 static inline void uprev64(celt_uint64_t *_ui,int _n,celt_uint64_t _ui0){
188 /* doing a do-while would overrun the array if we had less than 2 samples */
190 ui1=_ui[j]-_ui[j-1]-_ui0;
197 /*Returns the number of ways of choosing _m elements from a set of size _n with
198 replacement when a sign bit is needed for each unique element.
199 On input, _u should be initialized to column (_m-1) of U(n,m).
200 On exit, _u will be initialized to column _m of U(n,m).*/
201 celt_uint32_t ncwrs_unext32(int _n,celt_uint32_t *_ui){
209 ui1=_ui[j]+_ui[j-1]+ui0;
218 celt_uint64_t ncwrs_unext64(int _n,celt_uint64_t *_ui){
226 ui1=_ui[j]+_ui[j-1]+ui0;
235 /*Returns the number of ways of choosing _m elements from a set of size _n with
236 replacement when a sign bit is needed for each unique element.
237 On exit, _u will be initialized to column _m of U(n,m).*/
238 celt_uint32_t ncwrs_u32(int _n,int _m,celt_uint32_t *_u){
240 CELT_MEMSET(_u,0,_n);
243 for(k=1;k<_m;k++)unext32(_u,_n,2);
244 return ncwrs_unext32(_n,_u);
247 celt_uint64_t ncwrs_u64(int _n,int _m,celt_uint64_t *_u){
249 CELT_MEMSET(_u,0,_n);
252 for(k=1;k<_m;k++)unext64(_u,_n,2);
253 return ncwrs_unext64(_n,_u);
256 /*Returns the _i'th combination of _m elements chosen from a set of size _n
257 with associated sign bits.
258 _x: Returns the combination with elements sorted in ascending order.
259 _s: Returns the associated sign bits.
260 _u: Temporary storage already initialized to column _m of U(n,m).
261 Its contents will be overwritten.*/
262 void cwrsi32(int _n,int _m,celt_uint32_t _i,int *_x,int *_s,celt_uint32_t *_u){
271 if(t<=_i||_s[k-1])_i+=t;
286 void cwrsi64(int _n,int _m,celt_uint64_t _i,int *_x,int *_s,celt_uint64_t *_u){
295 if(t<=_i||_s[k-1])_i+=t;
310 /*Returns the index of the given combination of _m elements chosen from a set
311 of size _n with associated sign bits.
312 _x: The combination with elements sorted in ascending order.
313 _s: The associated sign bits.
314 _u: Temporary storage already initialized to column _m of U(n,m).
315 Its contents will be overwritten.*/
316 celt_uint32_t icwrs32(int _n,int _m,const int *_x,const int *_s,
331 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
337 celt_uint64_t icwrs64(int _n,int _m,const int *_x,const int *_s,
352 if((k==0||_x[k]!=_x[k-1])&&_s[k])i+=p>>1;
358 /*Converts a combination _x of _m unit pulses with associated sign bits _s into
359 a pulse vector _y of length _n.
360 _y: Returns the vector of pulses.
361 _x: The combination with elements sorted in ascending order. _x[_m] = -1
362 _s: The associated sign bits.*/
363 void comb2pulse(int _n,int _m,int * restrict _y,const int *_x,const int *_s){
365 const int signs[2]={1,-1};
366 CELT_MEMSET(_y, 0, _n);
368 _y[_x[k]]+=signs[_s[k]];
372 /*Converts a pulse vector vector _y of length _n into a combination of _m unit
373 pulses with associated sign bits _s.
374 _x: Returns the combination with elements sorted in ascending order.
375 _s: Returns the associated sign bits.
376 _y: The vector of pulses, whose sum of absolute values must be _m.*/
377 void pulse2comb(int _n,int _m,int *_x,int *_s,const int *_y){
395 static inline void encode_comb32(int _n,int _m,const int *_x,const int *_s,
397 VARDECL(celt_uint32_t,u);
401 ALLOC(u,_n,celt_uint32_t);
402 nc=ncwrs_u32(_n,_m,u);
403 i=icwrs32(_n,_m,_x,_s,u);
404 ec_enc_uint(_enc,i,nc);
408 static inline void encode_comb64(int _n,int _m,const int *_x,const int *_s,
410 VARDECL(celt_uint64_t,u);
414 ALLOC(u,_n,celt_uint64_t);
415 nc=ncwrs_u64(_n,_m,u);
416 i=icwrs64(_n,_m,_x,_s,u);
417 ec_enc_uint64(_enc,i,nc);
421 int get_required_bits(int N, int K, int frac)
426 VARDECL(celt_uint64_t,u);
428 ALLOC(u,N,celt_uint64_t);
429 nbits = log2_frac64(ncwrs_u64(N,K,u), frac);
432 nbits = log2_frac64(N, frac);
433 nbits += get_required_bits(N/2+1, (K+1)/2, frac);
434 nbits += get_required_bits(N/2+1, K/2, frac);
440 void encode_pulses(int *_y, int N, int K, ec_enc *enc)
447 ALLOC(signs, K, int);
449 pulse2comb(N, K, comb, signs, _y);
453 ec_enc_bits(enc, _y[0]<0, 1);
454 } else if(fits_in32(N,K))
456 encode_comb32(N, K, comb, signs, enc);
457 } else if(fits_in64(N,K)) {
458 encode_comb64(N, K, comb, signs, enc);
464 for (i=0;i<split;i++)
466 ec_enc_uint(enc,count,K+1);
467 encode_pulses(_y, split, count, enc);
468 encode_pulses(_y+split, N-split, K-count, enc);
473 static inline void decode_comb32(int _n,int _m,int *_x,int *_s,ec_dec *_dec){
474 VARDECL(celt_uint32_t,u);
476 ALLOC(u,_n,celt_uint32_t);
477 cwrsi32(_n,_m,ec_dec_uint(_dec,ncwrs_u32(_n,_m,u)),_x,_s,u);
481 static inline void decode_comb64(int _n,int _m,int *_x,int *_s,ec_dec *_dec){
482 VARDECL(celt_uint64_t,u);
484 ALLOC(u,_n,celt_uint64_t);
485 cwrsi64(_n,_m,ec_dec_uint64(_dec,ncwrs_u64(_n,_m,u)),_x,_s,u);
489 void decode_pulses(int *_y, int N, int K, ec_dec *dec)
496 ALLOC(signs, K, int);
503 int s = ec_dec_bits(dec, 1);
508 } else if(fits_in32(N,K))
510 decode_comb32(N, K, comb, signs, dec);
511 comb2pulse(N, K, _y, comb, signs);
512 } else if(fits_in64(N,K)) {
513 decode_comb64(N, K, comb, signs, dec);
514 comb2pulse(N, K, _y, comb, signs);
517 int count = ec_dec_uint(dec,K+1);
519 decode_pulses(_y, split, count, dec);
520 decode_pulses(_y+split, N-split, K-count, dec);