xref: /aosp_15_r20/external/tremolo/Tremolo/codebook.c (revision bda690e46497e1f65c5077173b9c548e6e0cd5a1)
1*bda690e4SXin Li /************************************************************************
2*bda690e4SXin Li  * Copyright (C) 2002-2009, Xiph.org Foundation
3*bda690e4SXin Li  * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4*bda690e4SXin Li  * All rights reserved.
5*bda690e4SXin Li  *
6*bda690e4SXin Li  * Redistribution and use in source and binary forms, with or without
7*bda690e4SXin Li  * modification, are permitted provided that the following conditions
8*bda690e4SXin Li  * are met:
9*bda690e4SXin Li  *
10*bda690e4SXin Li  *     * Redistributions of source code must retain the above copyright
11*bda690e4SXin Li  * notice, this list of conditions and the following disclaimer.
12*bda690e4SXin Li  *     * Redistributions in binary form must reproduce the above
13*bda690e4SXin Li  * copyright notice, this list of conditions and the following disclaimer
14*bda690e4SXin Li  * in the documentation and/or other materials provided with the
15*bda690e4SXin Li  * distribution.
16*bda690e4SXin Li  *     * Neither the names of the Xiph.org Foundation nor Pinknoise
17*bda690e4SXin Li  * Productions Ltd nor the names of its contributors may be used to
18*bda690e4SXin Li  * endorse or promote products derived from this software without
19*bda690e4SXin Li  * specific prior written permission.
20*bda690e4SXin Li  *
21*bda690e4SXin Li  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*bda690e4SXin Li  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*bda690e4SXin Li  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*bda690e4SXin Li  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25*bda690e4SXin Li  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*bda690e4SXin Li  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27*bda690e4SXin Li  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*bda690e4SXin Li  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29*bda690e4SXin Li  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30*bda690e4SXin Li  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*bda690e4SXin Li  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*bda690e4SXin Li  ************************************************************************
33*bda690e4SXin Li 
34*bda690e4SXin Li  function: basic codebook pack/unpack/code/decode operations
35*bda690e4SXin Li 
36*bda690e4SXin Li  ************************************************************************/
37*bda690e4SXin Li 
38*bda690e4SXin Li #include <stdlib.h>
39*bda690e4SXin Li #include <string.h>
40*bda690e4SXin Li #include <math.h>
41*bda690e4SXin Li #include <limits.h>
42*bda690e4SXin Li #include <log/log.h>
43*bda690e4SXin Li #include "ogg.h"
44*bda690e4SXin Li #include "ivorbiscodec.h"
45*bda690e4SXin Li #include "codebook.h"
46*bda690e4SXin Li #include "misc.h"
47*bda690e4SXin Li #include "os.h"
48*bda690e4SXin Li 
49*bda690e4SXin Li #define MARKER_SIZE 33
50*bda690e4SXin Li 
51*bda690e4SXin Li /**** pack/unpack helpers ******************************************/
_ilog(unsigned int v)52*bda690e4SXin Li int _ilog(unsigned int v){
53*bda690e4SXin Li   int ret=0;
54*bda690e4SXin Li   while(v){
55*bda690e4SXin Li     ret++;
56*bda690e4SXin Li     v>>=1;
57*bda690e4SXin Li   }
58*bda690e4SXin Li   return(ret);
59*bda690e4SXin Li }
60*bda690e4SXin Li 
decpack(long entry,long used_entry,long quantvals,codebook * b,oggpack_buffer * opb,int maptype)61*bda690e4SXin Li static ogg_uint32_t decpack(long entry,long used_entry,long quantvals,
62*bda690e4SXin Li                             codebook *b,oggpack_buffer *opb,int maptype){
63*bda690e4SXin Li   ogg_uint32_t ret=0;
64*bda690e4SXin Li   int j;
65*bda690e4SXin Li 
66*bda690e4SXin Li   switch(b->dec_type){
67*bda690e4SXin Li 
68*bda690e4SXin Li   case 0:
69*bda690e4SXin Li     return (ogg_uint32_t)entry;
70*bda690e4SXin Li 
71*bda690e4SXin Li   case 1:
72*bda690e4SXin Li     if(maptype==1){
73*bda690e4SXin Li       /* vals are already read into temporary column vector here */
74*bda690e4SXin Li       for(j=0;j<b->dim;j++){
75*bda690e4SXin Li         ogg_uint32_t off=entry%quantvals;
76*bda690e4SXin Li         entry/=quantvals;
77*bda690e4SXin Li         ret|=((ogg_uint16_t *)(b->q_val))[off]<<(b->q_bits*j);
78*bda690e4SXin Li       }
79*bda690e4SXin Li     }else{
80*bda690e4SXin Li       for(j=0;j<b->dim;j++)
81*bda690e4SXin Li         ret|=oggpack_read(opb,b->q_bits)<<(b->q_bits*j);
82*bda690e4SXin Li     }
83*bda690e4SXin Li     return ret;
84*bda690e4SXin Li 
85*bda690e4SXin Li   case 2:
86*bda690e4SXin Li     for(j=0;j<b->dim;j++){
87*bda690e4SXin Li       ogg_uint32_t off=entry%quantvals;
88*bda690e4SXin Li       entry/=quantvals;
89*bda690e4SXin Li       ret|=off<<(b->q_pack*j);
90*bda690e4SXin Li     }
91*bda690e4SXin Li     return ret;
92*bda690e4SXin Li 
93*bda690e4SXin Li   case 3:
94*bda690e4SXin Li     return (ogg_uint32_t)used_entry;
95*bda690e4SXin Li 
96*bda690e4SXin Li   }
97*bda690e4SXin Li   return 0; /* silence compiler */
98*bda690e4SXin Li }
99*bda690e4SXin Li 
100*bda690e4SXin Li /* 32 bit float (not IEEE; nonnormalized mantissa +
101*bda690e4SXin Li    biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm
102*bda690e4SXin Li    Why not IEEE?  It's just not that important here. */
103*bda690e4SXin Li 
_float32_unpack(long val,int * point)104*bda690e4SXin Li static ogg_int32_t _float32_unpack(long val,int *point){
105*bda690e4SXin Li   long   mant=val&0x1fffff;
106*bda690e4SXin Li   int    sign=val&0x80000000;
107*bda690e4SXin Li 
108*bda690e4SXin Li   *point=((val&0x7fe00000L)>>21)-788;
109*bda690e4SXin Li 
110*bda690e4SXin Li   if(mant){
111*bda690e4SXin Li     while(!(mant&0x40000000)){
112*bda690e4SXin Li       mant<<=1;
113*bda690e4SXin Li       *point-=1;
114*bda690e4SXin Li     }
115*bda690e4SXin Li     if(sign)mant= -mant;
116*bda690e4SXin Li   }else{
117*bda690e4SXin Li     *point=-9999;
118*bda690e4SXin Li   }
119*bda690e4SXin Li   return mant;
120*bda690e4SXin Li }
121*bda690e4SXin Li 
122*bda690e4SXin Li /* choose the smallest supported node size that fits our decode table.
123*bda690e4SXin Li    Legal bytewidths are 1/1 1/2 2/2 2/4 4/4 */
_determine_node_bytes(long used,int leafwidth)124*bda690e4SXin Li static int _determine_node_bytes(long used, int leafwidth){
125*bda690e4SXin Li 
126*bda690e4SXin Li   /* special case small books to size 4 to avoid multiple special
127*bda690e4SXin Li      cases in repack */
128*bda690e4SXin Li   if(used<2)
129*bda690e4SXin Li     return 4;
130*bda690e4SXin Li 
131*bda690e4SXin Li   if(leafwidth==3)leafwidth=4;
132*bda690e4SXin Li   if(_ilog(3*used-6)+1 <= leafwidth*4)
133*bda690e4SXin Li     return leafwidth/2?leafwidth/2:1;
134*bda690e4SXin Li   return leafwidth;
135*bda690e4SXin Li }
136*bda690e4SXin Li 
137*bda690e4SXin Li /* convenience/clarity; leaves are specified as multiple of node word
138*bda690e4SXin Li    size (1 or 2) */
_determine_leaf_words(int nodeb,int leafwidth)139*bda690e4SXin Li static int _determine_leaf_words(int nodeb, int leafwidth){
140*bda690e4SXin Li   if(leafwidth>nodeb)return 2;
141*bda690e4SXin Li   return 1;
142*bda690e4SXin Li }
143*bda690e4SXin Li 
144*bda690e4SXin Li /* given a list of word lengths, number of used entries, and byte
145*bda690e4SXin Li    width of a leaf, generate the decode table */
_make_words(char * l,long n,ogg_uint32_t * r,long quantvals,codebook * b,oggpack_buffer * opb,int maptype)146*bda690e4SXin Li static int _make_words(char *l,long n,ogg_uint32_t *r,long quantvals,
147*bda690e4SXin Li                        codebook *b, oggpack_buffer *opb,int maptype){
148*bda690e4SXin Li   long i,j,count=0;
149*bda690e4SXin Li   long top=0;
150*bda690e4SXin Li   ogg_uint32_t marker[MARKER_SIZE];
151*bda690e4SXin Li 
152*bda690e4SXin Li   if (n<1)
153*bda690e4SXin Li     return 1;
154*bda690e4SXin Li 
155*bda690e4SXin Li   if(n<2){
156*bda690e4SXin Li     r[0]=0x80000000;
157*bda690e4SXin Li   }else{
158*bda690e4SXin Li     memset(marker,0,sizeof(marker));
159*bda690e4SXin Li 
160*bda690e4SXin Li     for(i=0;i<n;i++){
161*bda690e4SXin Li       long length=l[i];
162*bda690e4SXin Li       if(length){
163*bda690e4SXin Li         if (length < 0 || length >= MARKER_SIZE) {
164*bda690e4SXin Li           ALOGE("b/23881715");
165*bda690e4SXin Li           return 1;
166*bda690e4SXin Li         }
167*bda690e4SXin Li         ogg_uint32_t entry=marker[length];
168*bda690e4SXin Li         long chase=0;
169*bda690e4SXin Li         if(count && !entry)return -1; /* overpopulated tree! */
170*bda690e4SXin Li 
171*bda690e4SXin Li         /* chase the tree as far as it's already populated, fill in past */
172*bda690e4SXin Li         for(j=0;j<length-1;j++){
173*bda690e4SXin Li           int bit=(entry>>(length-j-1))&1;
174*bda690e4SXin Li           if(chase>=top){
175*bda690e4SXin Li             if (chase < 0 || chase >= n) return 1;
176*bda690e4SXin Li             top++;
177*bda690e4SXin Li             r[chase*2]=top;
178*bda690e4SXin Li             r[chase*2+1]=0;
179*bda690e4SXin Li           }else
180*bda690e4SXin Li             if (chase < 0 || chase >= n || chase*2+bit > n*2+1) return 1;
181*bda690e4SXin Li             if(!r[chase*2+bit])
182*bda690e4SXin Li               r[chase*2+bit]=top;
183*bda690e4SXin Li           chase=r[chase*2+bit];
184*bda690e4SXin Li           if (chase < 0 || chase >= n) return 1;
185*bda690e4SXin Li         }
186*bda690e4SXin Li         {
187*bda690e4SXin Li           int bit=(entry>>(length-j-1))&1;
188*bda690e4SXin Li           if(chase>=top){
189*bda690e4SXin Li             top++;
190*bda690e4SXin Li             r[chase*2+1]=0;
191*bda690e4SXin Li           }
192*bda690e4SXin Li           r[chase*2+bit]= decpack(i,count++,quantvals,b,opb,maptype) |
193*bda690e4SXin Li             0x80000000;
194*bda690e4SXin Li         }
195*bda690e4SXin Li 
196*bda690e4SXin Li         /* Look to see if the next shorter marker points to the node
197*bda690e4SXin Li            above. if so, update it and repeat.  */
198*bda690e4SXin Li         for(j=length;j>0;j--){
199*bda690e4SXin Li           if(marker[j]&1){
200*bda690e4SXin Li             marker[j]=marker[j-1]<<1;
201*bda690e4SXin Li             break;
202*bda690e4SXin Li           }
203*bda690e4SXin Li           marker[j]++;
204*bda690e4SXin Li         }
205*bda690e4SXin Li 
206*bda690e4SXin Li         /* prune the tree; the implicit invariant says all the longer
207*bda690e4SXin Li            markers were dangling from our just-taken node.  Dangle them
208*bda690e4SXin Li            from our *new* node. */
209*bda690e4SXin Li         for(j=length+1;j<MARKER_SIZE;j++)
210*bda690e4SXin Li           if((marker[j]>>1) == entry){
211*bda690e4SXin Li             entry=marker[j];
212*bda690e4SXin Li             marker[j]=marker[j-1]<<1;
213*bda690e4SXin Li           }else
214*bda690e4SXin Li             break;
215*bda690e4SXin Li       }
216*bda690e4SXin Li     }
217*bda690e4SXin Li   }
218*bda690e4SXin Li 
219*bda690e4SXin Li   // following sanity check copied from libvorbis
220*bda690e4SXin Li   /* sanity check the huffman tree; an underpopulated tree must be
221*bda690e4SXin Li      rejected. The only exception is the one-node pseudo-nil tree,
222*bda690e4SXin Li      which appears to be underpopulated because the tree doesn't
223*bda690e4SXin Li      really exist; there's only one possible 'codeword' or zero bits,
224*bda690e4SXin Li      but the above tree-gen code doesn't mark that. */
225*bda690e4SXin Li   if(b->used_entries != 1){
226*bda690e4SXin Li     for(i=1;i<MARKER_SIZE;i++)
227*bda690e4SXin Li       if(marker[i] & (0xffffffffUL>>(32-i))){
228*bda690e4SXin Li           return 1;
229*bda690e4SXin Li       }
230*bda690e4SXin Li   }
231*bda690e4SXin Li 
232*bda690e4SXin Li 
233*bda690e4SXin Li   return 0;
234*bda690e4SXin Li }
235*bda690e4SXin Li 
_make_decode_table(codebook * s,char * lengthlist,long quantvals,oggpack_buffer * opb,int maptype)236*bda690e4SXin Li static int _make_decode_table(codebook *s,char *lengthlist,long quantvals,
237*bda690e4SXin Li                               oggpack_buffer *opb,int maptype){
238*bda690e4SXin Li   int i;
239*bda690e4SXin Li   ogg_uint32_t *work;
240*bda690e4SXin Li 
241*bda690e4SXin Li   if (!lengthlist) return 1;
242*bda690e4SXin Li   if(s->dec_nodeb==4){
243*bda690e4SXin Li     /* Over-allocate by using s->entries instead of used_entries.
244*bda690e4SXin Li      * This means that we can use s->entries to enforce size in
245*bda690e4SXin Li      * _make_words without messing up length list looping.
246*bda690e4SXin Li      * This probably wastes a bit of space, but it shouldn't
247*bda690e4SXin Li      * impact behavior or size too much.
248*bda690e4SXin Li      */
249*bda690e4SXin Li     s->dec_table=_ogg_calloc((s->entries*2+1), sizeof(*work));
250*bda690e4SXin Li     if (!s->dec_table) return 1;
251*bda690e4SXin Li     /* +1 (rather than -2) is to accommodate 0 and 1 sized books,
252*bda690e4SXin Li        which are specialcased to nodeb==4 */
253*bda690e4SXin Li     if(_make_words(lengthlist,s->entries,
254*bda690e4SXin Li                    s->dec_table,quantvals,s,opb,maptype))return 1;
255*bda690e4SXin Li 
256*bda690e4SXin Li     return 0;
257*bda690e4SXin Li   }
258*bda690e4SXin Li 
259*bda690e4SXin Li   if (s->used_entries > INT_MAX/2 ||
260*bda690e4SXin Li       s->used_entries*2 > INT_MAX/((long) sizeof(*work)) - 1) return 1;
261*bda690e4SXin Li   /* Overallocate as above */
262*bda690e4SXin Li   work=calloc((s->entries*2+1),sizeof(*work));
263*bda690e4SXin Li   if (!work) return 1;
264*bda690e4SXin Li   if(_make_words(lengthlist,s->entries,work,quantvals,s,opb,maptype)) goto error_out;
265*bda690e4SXin Li   if (s->used_entries > INT_MAX/(s->dec_leafw+1)) goto error_out;
266*bda690e4SXin Li   if (s->dec_nodeb && s->used_entries * (s->dec_leafw+1) > INT_MAX/s->dec_nodeb) goto error_out;
267*bda690e4SXin Li   s->dec_table=_ogg_calloc((s->used_entries*(s->dec_leafw+1)-2),
268*bda690e4SXin Li                            s->dec_nodeb);
269*bda690e4SXin Li   if (!s->dec_table) goto error_out;
270*bda690e4SXin Li 
271*bda690e4SXin Li   if(s->dec_leafw==1){
272*bda690e4SXin Li     switch(s->dec_nodeb){
273*bda690e4SXin Li     case 1:
274*bda690e4SXin Li       for(i=0;i<s->used_entries*2-2;i++)
275*bda690e4SXin Li           ((unsigned char *)s->dec_table)[i]=(unsigned char)
276*bda690e4SXin Li             (((work[i] & 0x80000000UL) >> 24) | work[i]);
277*bda690e4SXin Li       break;
278*bda690e4SXin Li     case 2:
279*bda690e4SXin Li       for(i=0;i<s->used_entries*2-2;i++)
280*bda690e4SXin Li           ((ogg_uint16_t *)s->dec_table)[i]=(ogg_uint16_t)
281*bda690e4SXin Li             (((work[i] & 0x80000000UL) >> 16) | work[i]);
282*bda690e4SXin Li       break;
283*bda690e4SXin Li     }
284*bda690e4SXin Li 
285*bda690e4SXin Li   }else{
286*bda690e4SXin Li     /* more complex; we have to do a two-pass repack that updates the
287*bda690e4SXin Li        node indexing. */
288*bda690e4SXin Li     long top=s->used_entries*3-2;
289*bda690e4SXin Li     if(s->dec_nodeb==1){
290*bda690e4SXin Li       unsigned char *out=(unsigned char *)s->dec_table;
291*bda690e4SXin Li 
292*bda690e4SXin Li       for(i=s->used_entries*2-4;i>=0;i-=2){
293*bda690e4SXin Li         if(work[i]&0x80000000UL){
294*bda690e4SXin Li           if(work[i+1]&0x80000000UL){
295*bda690e4SXin Li             top-=4;
296*bda690e4SXin Li             out[top]=(work[i]>>8 & 0x7f)|0x80;
297*bda690e4SXin Li             out[top+1]=(work[i+1]>>8 & 0x7f)|0x80;
298*bda690e4SXin Li             out[top+2]=work[i] & 0xff;
299*bda690e4SXin Li             out[top+3]=work[i+1] & 0xff;
300*bda690e4SXin Li           }else{
301*bda690e4SXin Li             top-=3;
302*bda690e4SXin Li             out[top]=(work[i]>>8 & 0x7f)|0x80;
303*bda690e4SXin Li             out[top+1]=work[work[i+1]*2];
304*bda690e4SXin Li             out[top+2]=work[i] & 0xff;
305*bda690e4SXin Li           }
306*bda690e4SXin Li         }else{
307*bda690e4SXin Li           if(work[i+1]&0x80000000UL){
308*bda690e4SXin Li             top-=3;
309*bda690e4SXin Li             out[top]=work[work[i]*2];
310*bda690e4SXin Li             out[top+1]=(work[i+1]>>8 & 0x7f)|0x80;
311*bda690e4SXin Li             out[top+2]=work[i+1] & 0xff;
312*bda690e4SXin Li           }else{
313*bda690e4SXin Li             top-=2;
314*bda690e4SXin Li             out[top]=work[work[i]*2];
315*bda690e4SXin Li             out[top+1]=work[work[i+1]*2];
316*bda690e4SXin Li           }
317*bda690e4SXin Li         }
318*bda690e4SXin Li         work[i]=top;
319*bda690e4SXin Li       }
320*bda690e4SXin Li     }else{
321*bda690e4SXin Li       ogg_uint16_t *out=(ogg_uint16_t *)s->dec_table;
322*bda690e4SXin Li       for(i=s->used_entries*2-4;i>=0;i-=2){
323*bda690e4SXin Li         if(work[i]&0x80000000UL){
324*bda690e4SXin Li           if(work[i+1]&0x80000000UL){
325*bda690e4SXin Li             top-=4;
326*bda690e4SXin Li             out[top]=(work[i]>>16 & 0x7fff)|0x8000;
327*bda690e4SXin Li             out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000;
328*bda690e4SXin Li             out[top+2]=work[i] & 0xffff;
329*bda690e4SXin Li             out[top+3]=work[i+1] & 0xffff;
330*bda690e4SXin Li           }else{
331*bda690e4SXin Li             top-=3;
332*bda690e4SXin Li             out[top]=(work[i]>>16 & 0x7fff)|0x8000;
333*bda690e4SXin Li             out[top+1]=work[work[i+1]*2];
334*bda690e4SXin Li             out[top+2]=work[i] & 0xffff;
335*bda690e4SXin Li           }
336*bda690e4SXin Li         }else{
337*bda690e4SXin Li           if(work[i+1]&0x80000000UL){
338*bda690e4SXin Li             top-=3;
339*bda690e4SXin Li             out[top]=work[work[i]*2];
340*bda690e4SXin Li             out[top+1]=(work[i+1]>>16 & 0x7fff)|0x8000;
341*bda690e4SXin Li             out[top+2]=work[i+1] & 0xffff;
342*bda690e4SXin Li           }else{
343*bda690e4SXin Li             top-=2;
344*bda690e4SXin Li             out[top]=work[work[i]*2];
345*bda690e4SXin Li             out[top+1]=work[work[i+1]*2];
346*bda690e4SXin Li           }
347*bda690e4SXin Li         }
348*bda690e4SXin Li         work[i]=top;
349*bda690e4SXin Li       }
350*bda690e4SXin Li     }
351*bda690e4SXin Li   }
352*bda690e4SXin Li 
353*bda690e4SXin Li   free(work);
354*bda690e4SXin Li   return 0;
355*bda690e4SXin Li error_out:
356*bda690e4SXin Li   free(work);
357*bda690e4SXin Li   return 1;
358*bda690e4SXin Li }
359*bda690e4SXin Li 
360*bda690e4SXin Li /* most of the time, entries%dimensions == 0, but we need to be
361*bda690e4SXin Li    well defined.  We define that the possible vales at each
362*bda690e4SXin Li    scalar is values == entries/dim.  If entries%dim != 0, we'll
363*bda690e4SXin Li    have 'too few' values (values*dim<entries), which means that
364*bda690e4SXin Li    we'll have 'left over' entries; left over entries use zeroed
365*bda690e4SXin Li    values (and are wasted).  So don't generate codebooks like
366*bda690e4SXin Li    that */
367*bda690e4SXin Li /* there might be a straightforward one-line way to do the below
368*bda690e4SXin Li    that's portable and totally safe against roundoff, but I haven't
369*bda690e4SXin Li    thought of it.  Therefore, we opt on the side of caution */
_book_maptype1_quantvals(codebook * b)370*bda690e4SXin Li long _book_maptype1_quantvals(codebook *b){
371*bda690e4SXin Li   /* get us a starting hint, we'll polish it below */
372*bda690e4SXin Li   int bits=_ilog(b->entries);
373*bda690e4SXin Li   int vals=b->entries>>((bits-1)*(b->dim-1)/b->dim);
374*bda690e4SXin Li 
375*bda690e4SXin Li   while(1){
376*bda690e4SXin Li     long acc=1;
377*bda690e4SXin Li     long acc1=1;
378*bda690e4SXin Li     int i;
379*bda690e4SXin Li     for (i = 0; i < b->dim; i++) {
380*bda690e4SXin Li       if (acc > b->entries / vals) {
381*bda690e4SXin Li           break;
382*bda690e4SXin Li       }
383*bda690e4SXin Li       acc *= vals;
384*bda690e4SXin Li       if (acc1 > LONG_MAX / (vals + 1)) {
385*bda690e4SXin Li         acc1 = LONG_MAX;
386*bda690e4SXin Li       } else {
387*bda690e4SXin Li         acc1 *= (vals + 1);
388*bda690e4SXin Li       }
389*bda690e4SXin Li     }
390*bda690e4SXin Li     if (i >= b->dim && acc <= b->entries && acc1 > b->entries) {
391*bda690e4SXin Li       return(vals);
392*bda690e4SXin Li     }else{
393*bda690e4SXin Li       if (i < b->dim || acc > b->entries) {
394*bda690e4SXin Li         vals--;
395*bda690e4SXin Li       }else{
396*bda690e4SXin Li         vals++;
397*bda690e4SXin Li       }
398*bda690e4SXin Li     }
399*bda690e4SXin Li   }
400*bda690e4SXin Li }
401*bda690e4SXin Li 
vorbis_book_clear(codebook * b)402*bda690e4SXin Li void vorbis_book_clear(codebook *b){
403*bda690e4SXin Li   /* static book is not cleared; we're likely called on the lookup and
404*bda690e4SXin Li      the static codebook belongs to the info struct */
405*bda690e4SXin Li   if(b->q_val)_ogg_free(b->q_val);
406*bda690e4SXin Li   if(b->dec_table)_ogg_free(b->dec_table);
407*bda690e4SXin Li   if(b->dec_buf)_ogg_free(b->dec_buf);
408*bda690e4SXin Li 
409*bda690e4SXin Li   memset(b,0,sizeof(*b));
410*bda690e4SXin Li }
411*bda690e4SXin Li 
vorbis_book_unpack(oggpack_buffer * opb,codebook * s)412*bda690e4SXin Li int vorbis_book_unpack(oggpack_buffer *opb,codebook *s){
413*bda690e4SXin Li   char         *lengthlist=NULL;
414*bda690e4SXin Li   int           quantvals=0;
415*bda690e4SXin Li   long          i,j;
416*bda690e4SXin Li   int           maptype;
417*bda690e4SXin Li 
418*bda690e4SXin Li   memset(s,0,sizeof(*s));
419*bda690e4SXin Li 
420*bda690e4SXin Li   /* make sure alignment is correct */
421*bda690e4SXin Li   if(oggpack_read(opb,24)!=0x564342)goto _eofout;
422*bda690e4SXin Li 
423*bda690e4SXin Li   /* first the basic parameters */
424*bda690e4SXin Li   s->dim=oggpack_read(opb,16);
425*bda690e4SXin Li   s->dec_buf=_ogg_calloc(s->dim, sizeof(ogg_int32_t));
426*bda690e4SXin Li   if (s->dec_buf == NULL)
427*bda690e4SXin Li       goto _errout;
428*bda690e4SXin Li   s->entries=oggpack_read(opb,24);
429*bda690e4SXin Li   if(s->entries<=0)goto _eofout;
430*bda690e4SXin Li   if(s->dim<=0)goto _eofout;
431*bda690e4SXin Li   if(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout;
432*bda690e4SXin Li   if (s->dim > INT_MAX/s->entries) goto _eofout;
433*bda690e4SXin Li 
434*bda690e4SXin Li   /* codeword ordering.... length ordered or unordered? */
435*bda690e4SXin Li   switch((int)oggpack_read(opb,1)){
436*bda690e4SXin Li   case 0:
437*bda690e4SXin Li     /* unordered */
438*bda690e4SXin Li     lengthlist=(char *)calloc(s->entries, sizeof(*lengthlist));
439*bda690e4SXin Li     if(!lengthlist) goto _eofout;
440*bda690e4SXin Li 
441*bda690e4SXin Li     /* allocated but unused entries? */
442*bda690e4SXin Li     if(oggpack_read(opb,1)){
443*bda690e4SXin Li       /* yes, unused entries */
444*bda690e4SXin Li 
445*bda690e4SXin Li       for(i=0;i<s->entries;i++){
446*bda690e4SXin Li         if(oggpack_read(opb,1)){
447*bda690e4SXin Li           long num=oggpack_read(opb,5);
448*bda690e4SXin Li           if(num==-1)goto _eofout;
449*bda690e4SXin Li           lengthlist[i]=(char)(num+1);
450*bda690e4SXin Li           s->used_entries++;
451*bda690e4SXin Li           if(num+1>s->dec_maxlength)s->dec_maxlength=num+1;
452*bda690e4SXin Li         }else
453*bda690e4SXin Li           lengthlist[i]=0;
454*bda690e4SXin Li       }
455*bda690e4SXin Li     }else{
456*bda690e4SXin Li       /* all entries used; no tagging */
457*bda690e4SXin Li       s->used_entries=s->entries;
458*bda690e4SXin Li       for(i=0;i<s->entries;i++){
459*bda690e4SXin Li         long num=oggpack_read(opb,5);
460*bda690e4SXin Li         if(num==-1)goto _eofout;
461*bda690e4SXin Li         lengthlist[i]=(char)(num+1);
462*bda690e4SXin Li         if(num+1>s->dec_maxlength)s->dec_maxlength=num+1;
463*bda690e4SXin Li       }
464*bda690e4SXin Li     }
465*bda690e4SXin Li 
466*bda690e4SXin Li     break;
467*bda690e4SXin Li   case 1:
468*bda690e4SXin Li     /* ordered */
469*bda690e4SXin Li     {
470*bda690e4SXin Li       long length=oggpack_read(opb,5)+1;
471*bda690e4SXin Li 
472*bda690e4SXin Li       s->used_entries=s->entries;
473*bda690e4SXin Li       lengthlist=(char *)calloc(s->entries, sizeof(*lengthlist));
474*bda690e4SXin Li       if (!lengthlist) goto _eofout;
475*bda690e4SXin Li 
476*bda690e4SXin Li       for(i=0;i<s->entries;){
477*bda690e4SXin Li         long num=oggpack_read(opb,_ilog(s->entries-i));
478*bda690e4SXin Li         if(num<0)goto _eofout;
479*bda690e4SXin Li         if(length>32) goto _errout;
480*bda690e4SXin Li         for(j=0;j<num && i<s->entries;j++,i++)
481*bda690e4SXin Li           lengthlist[i]=(char)length;
482*bda690e4SXin Li         s->dec_maxlength=length;
483*bda690e4SXin Li         length++;
484*bda690e4SXin Li       }
485*bda690e4SXin Li     }
486*bda690e4SXin Li     break;
487*bda690e4SXin Li   default:
488*bda690e4SXin Li     /* EOF */
489*bda690e4SXin Li     goto _eofout;
490*bda690e4SXin Li   }
491*bda690e4SXin Li 
492*bda690e4SXin Li 
493*bda690e4SXin Li   /* Do we have a mapping to unpack? */
494*bda690e4SXin Li 
495*bda690e4SXin Li   if((maptype=oggpack_read(opb,4))>0){
496*bda690e4SXin Li     s->q_min=_float32_unpack(oggpack_read(opb,32),&s->q_minp);
497*bda690e4SXin Li     s->q_del=_float32_unpack(oggpack_read(opb,32),&s->q_delp);
498*bda690e4SXin Li     s->q_bits=oggpack_read(opb,4)+1;
499*bda690e4SXin Li     s->q_seq=oggpack_read(opb,1);
500*bda690e4SXin Li 
501*bda690e4SXin Li     s->q_del>>=s->q_bits;
502*bda690e4SXin Li     s->q_delp+=s->q_bits;
503*bda690e4SXin Li   }
504*bda690e4SXin Li 
505*bda690e4SXin Li   switch(maptype){
506*bda690e4SXin Li   case 0:
507*bda690e4SXin Li 
508*bda690e4SXin Li     /* no mapping; decode type 0 */
509*bda690e4SXin Li 
510*bda690e4SXin Li     /* how many bytes for the indexing? */
511*bda690e4SXin Li     /* this is the correct boundary here; we lose one bit to
512*bda690e4SXin Li        node/leaf mark */
513*bda690e4SXin Li     s->dec_nodeb=_determine_node_bytes(s->used_entries,_ilog(s->entries)/8+1);
514*bda690e4SXin Li     s->dec_leafw=_determine_leaf_words(s->dec_nodeb,_ilog(s->entries)/8+1);
515*bda690e4SXin Li     s->dec_type=0;
516*bda690e4SXin Li 
517*bda690e4SXin Li     if(_make_decode_table(s,lengthlist,quantvals,opb,maptype)) goto _errout;
518*bda690e4SXin Li     break;
519*bda690e4SXin Li 
520*bda690e4SXin Li   case 1:
521*bda690e4SXin Li 
522*bda690e4SXin Li     /* mapping type 1; implicit values by lattice  position */
523*bda690e4SXin Li     quantvals=_book_maptype1_quantvals(s);
524*bda690e4SXin Li 
525*bda690e4SXin Li     /* dec_type choices here are 1,2; 3 doesn't make sense */
526*bda690e4SXin Li     {
527*bda690e4SXin Li       /* packed values */
528*bda690e4SXin Li       long total1=(s->q_bits*s->dim+8)/8; /* remember flag bit */
529*bda690e4SXin Li       if (s->dim > (INT_MAX-8)/s->q_bits) goto _eofout;
530*bda690e4SXin Li       /* vector of column offsets; remember flag bit */
531*bda690e4SXin Li       long total2=(_ilog(quantvals-1)*s->dim+8)/8+(s->q_bits+7)/8;
532*bda690e4SXin Li 
533*bda690e4SXin Li 
534*bda690e4SXin Li       if(total1<=4 && total1<=total2){
535*bda690e4SXin Li         /* use dec_type 1: vector of packed values */
536*bda690e4SXin Li 
537*bda690e4SXin Li         /* need quantized values before  */
538*bda690e4SXin Li         s->q_val=calloc(sizeof(ogg_uint16_t), quantvals);
539*bda690e4SXin Li         if (!s->q_val) goto _eofout;
540*bda690e4SXin Li         for(i=0;i<quantvals;i++)
541*bda690e4SXin Li           ((ogg_uint16_t *)s->q_val)[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
542*bda690e4SXin Li 
543*bda690e4SXin Li         if(oggpack_eop(opb)){
544*bda690e4SXin Li           goto _eofout;
545*bda690e4SXin Li         }
546*bda690e4SXin Li 
547*bda690e4SXin Li         s->dec_type=1;
548*bda690e4SXin Li         s->dec_nodeb=_determine_node_bytes(s->used_entries,
549*bda690e4SXin Li                                            (s->q_bits*s->dim+8)/8);
550*bda690e4SXin Li         s->dec_leafw=_determine_leaf_words(s->dec_nodeb,
551*bda690e4SXin Li                                            (s->q_bits*s->dim+8)/8);
552*bda690e4SXin Li         if(_make_decode_table(s,lengthlist,quantvals,opb,maptype)){
553*bda690e4SXin Li           goto _errout;
554*bda690e4SXin Li         }
555*bda690e4SXin Li 
556*bda690e4SXin Li         free(s->q_val);
557*bda690e4SXin Li         s->q_val=0;
558*bda690e4SXin Li 
559*bda690e4SXin Li       }else{
560*bda690e4SXin Li         /* use dec_type 2: packed vector of column offsets */
561*bda690e4SXin Li 
562*bda690e4SXin Li         /* need quantized values before */
563*bda690e4SXin Li         if(s->q_bits<=8){
564*bda690e4SXin Li           s->q_val=_ogg_malloc(quantvals);
565*bda690e4SXin Li           if (!s->q_val) goto _eofout;
566*bda690e4SXin Li           for(i=0;i<quantvals;i++)
567*bda690e4SXin Li             ((unsigned char *)s->q_val)[i]=(unsigned char)oggpack_read(opb,s->q_bits);
568*bda690e4SXin Li         }else{
569*bda690e4SXin Li           s->q_val=_ogg_malloc(quantvals*2);
570*bda690e4SXin Li           if (!s->q_val) goto _eofout;
571*bda690e4SXin Li           for(i=0;i<quantvals;i++)
572*bda690e4SXin Li             ((ogg_uint16_t *)s->q_val)[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
573*bda690e4SXin Li         }
574*bda690e4SXin Li 
575*bda690e4SXin Li         if(oggpack_eop(opb))goto _eofout;
576*bda690e4SXin Li 
577*bda690e4SXin Li         s->q_pack=_ilog(quantvals-1);
578*bda690e4SXin Li         s->dec_type=2;
579*bda690e4SXin Li         s->dec_nodeb=_determine_node_bytes(s->used_entries,
580*bda690e4SXin Li                                            (_ilog(quantvals-1)*s->dim+8)/8);
581*bda690e4SXin Li         s->dec_leafw=_determine_leaf_words(s->dec_nodeb,
582*bda690e4SXin Li                                            (_ilog(quantvals-1)*s->dim+8)/8);
583*bda690e4SXin Li         if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout;
584*bda690e4SXin Li 
585*bda690e4SXin Li       }
586*bda690e4SXin Li     }
587*bda690e4SXin Li     break;
588*bda690e4SXin Li   case 2:
589*bda690e4SXin Li 
590*bda690e4SXin Li     /* mapping type 2; explicit array of values */
591*bda690e4SXin Li     quantvals=s->entries*s->dim;
592*bda690e4SXin Li     /* dec_type choices here are 1,3; 2 is not possible */
593*bda690e4SXin Li 
594*bda690e4SXin Li     if( (s->q_bits*s->dim+8)/8 <=4){ /* remember flag bit */
595*bda690e4SXin Li       /* use dec_type 1: vector of packed values */
596*bda690e4SXin Li 
597*bda690e4SXin Li       s->dec_type=1;
598*bda690e4SXin Li       s->dec_nodeb=_determine_node_bytes(s->used_entries,(s->q_bits*s->dim+8)/8);
599*bda690e4SXin Li       s->dec_leafw=_determine_leaf_words(s->dec_nodeb,(s->q_bits*s->dim+8)/8);
600*bda690e4SXin Li       if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout;
601*bda690e4SXin Li 
602*bda690e4SXin Li     }else{
603*bda690e4SXin Li       /* use dec_type 3: scalar offset into packed value array */
604*bda690e4SXin Li 
605*bda690e4SXin Li       s->dec_type=3;
606*bda690e4SXin Li       s->dec_nodeb=_determine_node_bytes(s->used_entries,_ilog(s->used_entries-1)/8+1);
607*bda690e4SXin Li       s->dec_leafw=_determine_leaf_words(s->dec_nodeb,_ilog(s->used_entries-1)/8+1);
608*bda690e4SXin Li       if(_make_decode_table(s,lengthlist,quantvals,opb,maptype))goto _errout;
609*bda690e4SXin Li 
610*bda690e4SXin Li       /* get the vals & pack them */
611*bda690e4SXin Li       s->q_pack=(s->q_bits+7)/8*s->dim;
612*bda690e4SXin Li       s->q_val=_ogg_malloc(s->q_pack*s->used_entries);
613*bda690e4SXin Li 
614*bda690e4SXin Li       if(s->q_bits<=8){
615*bda690e4SXin Li         for(i=0;i<s->used_entries*s->dim;i++)
616*bda690e4SXin Li           ((unsigned char *)(s->q_val))[i]=(unsigned char)oggpack_read(opb,s->q_bits);
617*bda690e4SXin Li       }else{
618*bda690e4SXin Li         for(i=0;i<s->used_entries*s->dim;i++)
619*bda690e4SXin Li           ((ogg_uint16_t *)(s->q_val))[i]=(ogg_uint16_t)oggpack_read(opb,s->q_bits);
620*bda690e4SXin Li       }
621*bda690e4SXin Li     }
622*bda690e4SXin Li     break;
623*bda690e4SXin Li   default:
624*bda690e4SXin Li     goto _errout;
625*bda690e4SXin Li   }
626*bda690e4SXin Li 
627*bda690e4SXin Li   if (s->dec_nodeb==1)
628*bda690e4SXin Li     if (s->dec_leafw == 1)
629*bda690e4SXin Li       s->dec_method = 0;
630*bda690e4SXin Li     else
631*bda690e4SXin Li       s->dec_method = 1;
632*bda690e4SXin Li   else if (s->dec_nodeb==2)
633*bda690e4SXin Li     if (s->dec_leafw == 1)
634*bda690e4SXin Li       s->dec_method = 2;
635*bda690e4SXin Li     else
636*bda690e4SXin Li       s->dec_method = 3;
637*bda690e4SXin Li   else
638*bda690e4SXin Li     s->dec_method = 4;
639*bda690e4SXin Li 
640*bda690e4SXin Li   if(oggpack_eop(opb))goto _eofout;
641*bda690e4SXin Li 
642*bda690e4SXin Li   free(lengthlist);
643*bda690e4SXin Li   return 0;
644*bda690e4SXin Li  _errout:
645*bda690e4SXin Li  _eofout:
646*bda690e4SXin Li   vorbis_book_clear(s);
647*bda690e4SXin Li   free(lengthlist);
648*bda690e4SXin Li   free(s->q_val);
649*bda690e4SXin Li   return -1;
650*bda690e4SXin Li }
651*bda690e4SXin Li 
652*bda690e4SXin Li #ifndef ONLY_C
653*bda690e4SXin Li ogg_uint32_t decode_packed_entry_number(codebook *book,
654*bda690e4SXin Li                                         oggpack_buffer *b);
655*bda690e4SXin Li #else
decode_packed_entry_number(codebook * book,oggpack_buffer * b)656*bda690e4SXin Li static inline ogg_uint32_t decode_packed_entry_number(codebook *book,
657*bda690e4SXin Li                                                       oggpack_buffer *b){
658*bda690e4SXin Li   ogg_uint32_t chase=0;
659*bda690e4SXin Li   int  read=book->dec_maxlength;
660*bda690e4SXin Li   long lok = oggpack_look(b,read),i;
661*bda690e4SXin Li 
662*bda690e4SXin Li   while(lok<0 && read>1)
663*bda690e4SXin Li     lok = oggpack_look(b, --read);
664*bda690e4SXin Li 
665*bda690e4SXin Li   if(lok<0){
666*bda690e4SXin Li     oggpack_adv(b,1); /* force eop */
667*bda690e4SXin Li     return -1;
668*bda690e4SXin Li   }
669*bda690e4SXin Li 
670*bda690e4SXin Li   /* chase the tree with the bits we got */
671*bda690e4SXin Li   switch (book->dec_method)
672*bda690e4SXin Li   {
673*bda690e4SXin Li     case 0:
674*bda690e4SXin Li     {
675*bda690e4SXin Li       /* book->dec_nodeb==1, book->dec_leafw==1 */
676*bda690e4SXin Li       /* 8/8 - Used */
677*bda690e4SXin Li       unsigned char *t=(unsigned char *)book->dec_table;
678*bda690e4SXin Li 
679*bda690e4SXin Li       for(i=0;i<read;i++){
680*bda690e4SXin Li         chase=t[chase*2+((lok>>i)&1)];
681*bda690e4SXin Li         if(chase&0x80UL)break;
682*bda690e4SXin Li       }
683*bda690e4SXin Li       chase&=0x7fUL;
684*bda690e4SXin Li       break;
685*bda690e4SXin Li     }
686*bda690e4SXin Li     case 1:
687*bda690e4SXin Li     {
688*bda690e4SXin Li       /* book->dec_nodeb==1, book->dec_leafw!=1 */
689*bda690e4SXin Li       /* 8/16 - Used by infile2 */
690*bda690e4SXin Li       unsigned char *t=(unsigned char *)book->dec_table;
691*bda690e4SXin Li       for(i=0;i<read;i++){
692*bda690e4SXin Li         int bit=(lok>>i)&1;
693*bda690e4SXin Li         int next=t[chase+bit];
694*bda690e4SXin Li         if(next&0x80){
695*bda690e4SXin Li           chase= (next<<8) | t[chase+bit+1+(!bit || t[chase]&0x80)];
696*bda690e4SXin Li           break;
697*bda690e4SXin Li         }
698*bda690e4SXin Li         chase=next;
699*bda690e4SXin Li       }
700*bda690e4SXin Li       //chase&=0x7fffUL;
701*bda690e4SXin Li       chase&=~0x8000UL;
702*bda690e4SXin Li       break;
703*bda690e4SXin Li     }
704*bda690e4SXin Li     case 2:
705*bda690e4SXin Li     {
706*bda690e4SXin Li       /* book->dec_nodeb==2, book->dec_leafw==1 */
707*bda690e4SXin Li       /* 16/16 - Used */
708*bda690e4SXin Li       for(i=0;i<read;i++){
709*bda690e4SXin Li         chase=((ogg_uint16_t *)(book->dec_table))[chase*2+((lok>>i)&1)];
710*bda690e4SXin Li         if(chase&0x8000UL)break;
711*bda690e4SXin Li       }
712*bda690e4SXin Li       //chase&=0x7fffUL;
713*bda690e4SXin Li       chase&=~0x8000UL;
714*bda690e4SXin Li       break;
715*bda690e4SXin Li     }
716*bda690e4SXin Li     case 3:
717*bda690e4SXin Li     {
718*bda690e4SXin Li       /* book->dec_nodeb==2, book->dec_leafw!=1 */
719*bda690e4SXin Li       /* 16/32 - Used by infile2 */
720*bda690e4SXin Li       ogg_uint16_t *t=(ogg_uint16_t *)book->dec_table;
721*bda690e4SXin Li       for(i=0;i<read;i++){
722*bda690e4SXin Li         int bit=(lok>>i)&1;
723*bda690e4SXin Li         int next=t[chase+bit];
724*bda690e4SXin Li         if(next&0x8000){
725*bda690e4SXin Li           chase= (next<<16) | t[chase+bit+1+(!bit || t[chase]&0x8000)];
726*bda690e4SXin Li           break;
727*bda690e4SXin Li         }
728*bda690e4SXin Li         chase=next;
729*bda690e4SXin Li       }
730*bda690e4SXin Li       //chase&=0x7fffffffUL;
731*bda690e4SXin Li       chase&=~0x80000000UL;
732*bda690e4SXin Li       break;
733*bda690e4SXin Li     }
734*bda690e4SXin Li     case 4:
735*bda690e4SXin Li     {
736*bda690e4SXin Li       //Output("32/32");
737*bda690e4SXin Li       for(i=0;i<read;i++){
738*bda690e4SXin Li         chase=((ogg_uint32_t *)(book->dec_table))[chase*2+((lok>>i)&1)];
739*bda690e4SXin Li         if(chase&0x80000000UL)break;
740*bda690e4SXin Li       }
741*bda690e4SXin Li       //chase&=0x7fffffffUL;
742*bda690e4SXin Li       chase&=~0x80000000UL;
743*bda690e4SXin Li       break;
744*bda690e4SXin Li     }
745*bda690e4SXin Li   }
746*bda690e4SXin Li 
747*bda690e4SXin Li   if(i<read){
748*bda690e4SXin Li     oggpack_adv(b,i+1);
749*bda690e4SXin Li     return chase;
750*bda690e4SXin Li   }
751*bda690e4SXin Li   oggpack_adv(b,read+1);
752*bda690e4SXin Li   return(-1);
753*bda690e4SXin Li }
754*bda690e4SXin Li #endif
755*bda690e4SXin Li 
756*bda690e4SXin Li /* returns the [original, not compacted] entry number or -1 on eof *********/
vorbis_book_decode(codebook * book,oggpack_buffer * b)757*bda690e4SXin Li long vorbis_book_decode(codebook *book, oggpack_buffer *b){
758*bda690e4SXin Li   if(book->dec_type)return -1;
759*bda690e4SXin Li  return decode_packed_entry_number(book,b);
760*bda690e4SXin Li }
761*bda690e4SXin Li 
762*bda690e4SXin Li #ifndef ONLY_C
763*bda690e4SXin Li int decode_map(codebook *s, oggpack_buffer *b, ogg_int32_t *v, int point);
764*bda690e4SXin Li #else
decode_map(codebook * s,oggpack_buffer * b,ogg_int32_t * v,int point)765*bda690e4SXin Li static int decode_map(codebook *s, oggpack_buffer *b, ogg_int32_t *v, int point){
766*bda690e4SXin Li   ogg_uint32_t entry = decode_packed_entry_number(s,b);
767*bda690e4SXin Li   int i;
768*bda690e4SXin Li   if(entry==UINT_MAX)return -1;
769*bda690e4SXin Li   if(oggpack_eop(b))return(-1);
770*bda690e4SXin Li 
771*bda690e4SXin Li   /* 1 used by test file 0 */
772*bda690e4SXin Li 
773*bda690e4SXin Li   /* according to decode type */
774*bda690e4SXin Li   switch(s->dec_type){
775*bda690e4SXin Li   case 1:{
776*bda690e4SXin Li     /* packed vector of values */
777*bda690e4SXin Li     int mask=(1<<s->q_bits)-1;
778*bda690e4SXin Li     for(i=0;i<s->dim;i++){
779*bda690e4SXin Li       v[i]=entry&mask;
780*bda690e4SXin Li       entry>>=s->q_bits;
781*bda690e4SXin Li     }
782*bda690e4SXin Li     break;
783*bda690e4SXin Li   }
784*bda690e4SXin Li   case 2:{
785*bda690e4SXin Li     /* packed vector of column offsets */
786*bda690e4SXin Li     int mask=(1<<s->q_pack)-1;
787*bda690e4SXin Li     for(i=0;i<s->dim;i++){
788*bda690e4SXin Li       if(s->q_bits<=8)
789*bda690e4SXin Li         v[i]=((unsigned char *)(s->q_val))[entry&mask];
790*bda690e4SXin Li       else
791*bda690e4SXin Li         v[i]=((ogg_uint16_t *)(s->q_val))[entry&mask];
792*bda690e4SXin Li       entry>>=s->q_pack;
793*bda690e4SXin Li     }
794*bda690e4SXin Li     break;
795*bda690e4SXin Li   }
796*bda690e4SXin Li   case 3:{
797*bda690e4SXin Li     /* offset into array */
798*bda690e4SXin Li     void *ptr=((char *)s->q_val)+entry*s->q_pack;
799*bda690e4SXin Li 
800*bda690e4SXin Li     if(s->q_bits<=8){
801*bda690e4SXin Li       for(i=0;i<s->dim;i++)
802*bda690e4SXin Li         v[i]=((unsigned char *)ptr)[i];
803*bda690e4SXin Li     }else{
804*bda690e4SXin Li       for(i=0;i<s->dim;i++)
805*bda690e4SXin Li         v[i]=((ogg_uint16_t *)ptr)[i];
806*bda690e4SXin Li     }
807*bda690e4SXin Li     break;
808*bda690e4SXin Li   }
809*bda690e4SXin Li   default:
810*bda690e4SXin Li     return -1;
811*bda690e4SXin Li   }
812*bda690e4SXin Li 
813*bda690e4SXin Li   /* we have the unpacked multiplicands; compute final vals */
814*bda690e4SXin Li   {
815*bda690e4SXin Li     int         shiftM = point-s->q_delp;
816*bda690e4SXin Li     ogg_int32_t add    = point-s->q_minp;
817*bda690e4SXin Li     int         mul    = s->q_del;
818*bda690e4SXin Li 
819*bda690e4SXin Li     if(add>0)
820*bda690e4SXin Li       add= s->q_min >> add;
821*bda690e4SXin Li     else
822*bda690e4SXin Li       add= s->q_min << -add;
823*bda690e4SXin Li     if (shiftM<0)
824*bda690e4SXin Li     {
825*bda690e4SXin Li       mul <<= -shiftM;
826*bda690e4SXin Li       shiftM = 0;
827*bda690e4SXin Li     }
828*bda690e4SXin Li     add <<= shiftM;
829*bda690e4SXin Li 
830*bda690e4SXin Li     ogg_int32_t tmp;
831*bda690e4SXin Li     for(i=0;i<s->dim;i++) {
832*bda690e4SXin Li       if (__builtin_mul_overflow(v[i], mul, &tmp) ||
833*bda690e4SXin Li               __builtin_add_overflow(tmp, add, &tmp)) {
834*bda690e4SXin Li           return -1;
835*bda690e4SXin Li       }
836*bda690e4SXin Li       v[i] = tmp >> shiftM;
837*bda690e4SXin Li     }
838*bda690e4SXin Li 
839*bda690e4SXin Li     if(s->q_seq)
840*bda690e4SXin Li       for(i=1;i<s->dim;i++) {
841*bda690e4SXin Li         if (__builtin_add_overflow(v[i], v[i-1], &v[i])) {
842*bda690e4SXin Li           return -1;
843*bda690e4SXin Li         }
844*bda690e4SXin Li       }
845*bda690e4SXin Li   }
846*bda690e4SXin Li 
847*bda690e4SXin Li   return 0;
848*bda690e4SXin Li }
849*bda690e4SXin Li #endif
850*bda690e4SXin Li 
851*bda690e4SXin Li /* returns 0 on OK or -1 on eof *************************************/
852*bda690e4SXin Li /* decode vector / dim granularity gaurding is done in the upper layer */
vorbis_book_decodevs_add(codebook * book,ogg_int32_t * a,oggpack_buffer * b,int n,int point)853*bda690e4SXin Li long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a,
854*bda690e4SXin Li                               oggpack_buffer *b,int n,int point){
855*bda690e4SXin Li   if(book->used_entries>0){
856*bda690e4SXin Li     int step=n/book->dim;
857*bda690e4SXin Li     ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
858*bda690e4SXin Li     int i,j,o;
859*bda690e4SXin Li     if (!v) return -1;
860*bda690e4SXin Li 
861*bda690e4SXin Li     for (j=0;j<step;j++){
862*bda690e4SXin Li       if(decode_map(book,b,v,point))return -1;
863*bda690e4SXin Li       for(i=0,o=j;i<book->dim;i++,o+=step){
864*bda690e4SXin Li         if (__builtin_add_overflow(a[o], v[i], &a[o])){
865*bda690e4SXin Li            a[o] = v[i] > 0 ? INT32_MAX : INT32_MIN;
866*bda690e4SXin Li         }
867*bda690e4SXin Li       }
868*bda690e4SXin Li     }
869*bda690e4SXin Li   }
870*bda690e4SXin Li   return 0;
871*bda690e4SXin Li }
872*bda690e4SXin Li 
873*bda690e4SXin Li /* decode vector / dim granularity gaurding is done in the upper layer */
vorbis_book_decodev_add(codebook * book,ogg_int32_t * a,oggpack_buffer * b,int n,int point)874*bda690e4SXin Li long vorbis_book_decodev_add(codebook *book,ogg_int32_t *a,
875*bda690e4SXin Li                              oggpack_buffer *b,int n,int point){
876*bda690e4SXin Li   if(book->used_entries>0){
877*bda690e4SXin Li     ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
878*bda690e4SXin Li     int i,j;
879*bda690e4SXin Li 
880*bda690e4SXin Li     if (!v) return -1;
881*bda690e4SXin Li     for(i=0;i<n;){
882*bda690e4SXin Li       if(decode_map(book,b,v,point))return -1;
883*bda690e4SXin Li       for (j=0;j<book->dim && i < n;j++,i++){
884*bda690e4SXin Li         if (__builtin_add_overflow(a[i], v[j], &a[i])) {
885*bda690e4SXin Li            a[i] = v[j] > 0 ? INT32_MAX : INT32_MIN;
886*bda690e4SXin Li         }
887*bda690e4SXin Li       }
888*bda690e4SXin Li     }
889*bda690e4SXin Li   }
890*bda690e4SXin Li   return 0;
891*bda690e4SXin Li }
892*bda690e4SXin Li 
893*bda690e4SXin Li /* unlike the others, we guard against n not being an integer number
894*bda690e4SXin Li    of <dim> internally rather than in the upper layer (called only by
895*bda690e4SXin Li    floor0) */
vorbis_book_decodev_set(codebook * book,ogg_int32_t * a,oggpack_buffer * b,int n,int point)896*bda690e4SXin Li long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a,
897*bda690e4SXin Li                              oggpack_buffer *b,int n,int point){
898*bda690e4SXin Li   if(book->used_entries>0){
899*bda690e4SXin Li     ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
900*bda690e4SXin Li     int i,j;
901*bda690e4SXin Li 
902*bda690e4SXin Li     if (!v) return -1;
903*bda690e4SXin Li     for(i=0;i<n;){
904*bda690e4SXin Li       if(decode_map(book,b,v,point))return -1;
905*bda690e4SXin Li       for (j=0;j<book->dim && i < n;j++)
906*bda690e4SXin Li         a[i++]=v[j];
907*bda690e4SXin Li     }
908*bda690e4SXin Li   }else{
909*bda690e4SXin Li     memset(a, 0, sizeof(*a) * n);
910*bda690e4SXin Li   }
911*bda690e4SXin Li 
912*bda690e4SXin Li   return 0;
913*bda690e4SXin Li }
914*bda690e4SXin Li 
915*bda690e4SXin Li #ifndef ONLY_C
916*bda690e4SXin Li long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
917*bda690e4SXin Li                               long offset,int ch,
918*bda690e4SXin Li                               oggpack_buffer *b,int n,int point);
919*bda690e4SXin Li #else
vorbis_book_decodevv_add(codebook * book,ogg_int32_t ** a,long offset,int ch,oggpack_buffer * b,int n,int point)920*bda690e4SXin Li long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a,
921*bda690e4SXin Li                               long offset,int ch,
922*bda690e4SXin Li                               oggpack_buffer *b,int n,int point){
923*bda690e4SXin Li   if(book->used_entries>0){
924*bda690e4SXin Li 
925*bda690e4SXin Li     ogg_int32_t *v = book->dec_buf;//(ogg_int32_t *)alloca(sizeof(*v)*book->dim);
926*bda690e4SXin Li     long i,j;
927*bda690e4SXin Li     int chptr=0;
928*bda690e4SXin Li 
929*bda690e4SXin Li     if (!v) return -1;
930*bda690e4SXin Li     for(i=offset;i<offset+n;){
931*bda690e4SXin Li       if(decode_map(book,b,v,point))return -1;
932*bda690e4SXin Li       for (j=0;j<book->dim && i < offset + n;j++){
933*bda690e4SXin Li         if (__builtin_add_overflow(a[chptr][i], v[j], &a[chptr][i])) {
934*bda690e4SXin Li            a[chptr][i] = v[j] > 0 ? INT32_MAX : INT32_MIN;
935*bda690e4SXin Li         }
936*bda690e4SXin Li         chptr++;
937*bda690e4SXin Li         if(chptr==ch){
938*bda690e4SXin Li           chptr=0;
939*bda690e4SXin Li           i++;
940*bda690e4SXin Li         }
941*bda690e4SXin Li       }
942*bda690e4SXin Li     }
943*bda690e4SXin Li   }
944*bda690e4SXin Li 
945*bda690e4SXin Li   return 0;
946*bda690e4SXin Li }
947*bda690e4SXin Li #endif
948