xref: /aosp_15_r20/external/tremolo/Tremolo/treminfo.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: maintain the info structure, info <-> header packets
35*bda690e4SXin Li 
36*bda690e4SXin Li  ************************************************************************/
37*bda690e4SXin Li 
38*bda690e4SXin Li /* general handling of the header and the vorbis_info structure (and
39*bda690e4SXin Li    substructures) */
40*bda690e4SXin Li 
41*bda690e4SXin Li #include <stdlib.h>
42*bda690e4SXin Li #include <string.h>
43*bda690e4SXin Li #include <ctype.h>
44*bda690e4SXin Li #include "ogg.h"
45*bda690e4SXin Li #include "ivorbiscodec.h"
46*bda690e4SXin Li #include "codec_internal.h"
47*bda690e4SXin Li #include "codebook.h"
48*bda690e4SXin Li #include "misc.h"
49*bda690e4SXin Li #include "os.h"
50*bda690e4SXin Li 
51*bda690e4SXin Li /* helpers */
_v_readstring(oggpack_buffer * o,char * buf,int bytes)52*bda690e4SXin Li static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
53*bda690e4SXin Li   while(bytes--){
54*bda690e4SXin Li     *buf++=(char)oggpack_read(o,8);
55*bda690e4SXin Li   }
56*bda690e4SXin Li }
57*bda690e4SXin Li 
vorbis_comment_init(vorbis_comment * vc)58*bda690e4SXin Li void vorbis_comment_init(vorbis_comment *vc){
59*bda690e4SXin Li   memset(vc,0,sizeof(*vc));
60*bda690e4SXin Li }
61*bda690e4SXin Li 
62*bda690e4SXin Li /* This is more or less the same as strncasecmp - but that doesn't exist
63*bda690e4SXin Li  * everywhere, and this is a fairly trivial function, so we include it */
tagcompare(const char * s1,const char * s2,int n)64*bda690e4SXin Li static int tagcompare(const char *s1, const char *s2, int n){
65*bda690e4SXin Li   int c=0;
66*bda690e4SXin Li   while(c < n){
67*bda690e4SXin Li     if(toupper(s1[c]) != toupper(s2[c]))
68*bda690e4SXin Li       return !0;
69*bda690e4SXin Li     c++;
70*bda690e4SXin Li   }
71*bda690e4SXin Li   return 0;
72*bda690e4SXin Li }
73*bda690e4SXin Li 
vorbis_comment_query(vorbis_comment * vc,char * tag,int count)74*bda690e4SXin Li char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
75*bda690e4SXin Li   long i;
76*bda690e4SXin Li   int found = 0;
77*bda690e4SXin Li   int taglen = strlen(tag)+1; /* +1 for the = we append */
78*bda690e4SXin Li   char *fulltag = (char *)alloca(taglen+ 1);
79*bda690e4SXin Li 
80*bda690e4SXin Li   strcpy(fulltag, tag);
81*bda690e4SXin Li   strcat(fulltag, "=");
82*bda690e4SXin Li 
83*bda690e4SXin Li   for(i=0;i<vc->comments;i++){
84*bda690e4SXin Li     if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
85*bda690e4SXin Li       if(count == found)
86*bda690e4SXin Li 	/* We return a pointer to the data, not a copy */
87*bda690e4SXin Li       	return vc->user_comments[i] + taglen;
88*bda690e4SXin Li       else
89*bda690e4SXin Li 	found++;
90*bda690e4SXin Li     }
91*bda690e4SXin Li   }
92*bda690e4SXin Li   return NULL; /* didn't find anything */
93*bda690e4SXin Li }
94*bda690e4SXin Li 
vorbis_comment_query_count(vorbis_comment * vc,char * tag)95*bda690e4SXin Li int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
96*bda690e4SXin Li   int i,count=0;
97*bda690e4SXin Li   int taglen = strlen(tag)+1; /* +1 for the = we append */
98*bda690e4SXin Li   char *fulltag = (char *)alloca(taglen+1);
99*bda690e4SXin Li   strcpy(fulltag,tag);
100*bda690e4SXin Li   strcat(fulltag, "=");
101*bda690e4SXin Li 
102*bda690e4SXin Li   for(i=0;i<vc->comments;i++){
103*bda690e4SXin Li     if(!tagcompare(vc->user_comments[i], fulltag, taglen))
104*bda690e4SXin Li       count++;
105*bda690e4SXin Li   }
106*bda690e4SXin Li 
107*bda690e4SXin Li   return count;
108*bda690e4SXin Li }
109*bda690e4SXin Li 
vorbis_comment_clear(vorbis_comment * vc)110*bda690e4SXin Li void vorbis_comment_clear(vorbis_comment *vc){
111*bda690e4SXin Li   if(vc){
112*bda690e4SXin Li     long i;
113*bda690e4SXin Li     for(i=0;i<vc->comments;i++)
114*bda690e4SXin Li       if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
115*bda690e4SXin Li     if(vc->user_comments)_ogg_free(vc->user_comments);
116*bda690e4SXin Li 	if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
117*bda690e4SXin Li     if(vc->vendor)_ogg_free(vc->vendor);
118*bda690e4SXin Li   }
119*bda690e4SXin Li   memset(vc,0,sizeof(*vc));
120*bda690e4SXin Li }
121*bda690e4SXin Li 
122*bda690e4SXin Li /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
123*bda690e4SXin Li    They may be equal, but short will never ge greater than long */
vorbis_info_blocksize(vorbis_info * vi,int zo)124*bda690e4SXin Li int vorbis_info_blocksize(vorbis_info *vi,int zo){
125*bda690e4SXin Li   codec_setup_info *ci = (codec_setup_info *)vi->codec_setup;
126*bda690e4SXin Li   return ci ? ci->blocksizes[zo] : -1;
127*bda690e4SXin Li }
128*bda690e4SXin Li 
129*bda690e4SXin Li /* used by synthesis, which has a full, alloced vi */
vorbis_info_init(vorbis_info * vi)130*bda690e4SXin Li void vorbis_info_init(vorbis_info *vi){
131*bda690e4SXin Li   memset(vi,0,sizeof(*vi));
132*bda690e4SXin Li   vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info));
133*bda690e4SXin Li }
134*bda690e4SXin Li 
vorbis_info_clear(vorbis_info * vi)135*bda690e4SXin Li void vorbis_info_clear(vorbis_info *vi){
136*bda690e4SXin Li   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
137*bda690e4SXin Li   int i;
138*bda690e4SXin Li 
139*bda690e4SXin Li   if(ci){
140*bda690e4SXin Li 
141*bda690e4SXin Li     if(ci->mode_param)_ogg_free(ci->mode_param);
142*bda690e4SXin Li 
143*bda690e4SXin Li     if(ci->map_param){
144*bda690e4SXin Li       for(i=0;i<ci->maps;i++) /* unpack does the range checking */
145*bda690e4SXin Li 	mapping_clear_info(ci->map_param+i);
146*bda690e4SXin Li       _ogg_free(ci->map_param);
147*bda690e4SXin Li     }
148*bda690e4SXin Li 
149*bda690e4SXin Li     if(ci->floor_param){
150*bda690e4SXin Li       for(i=0;i<ci->floors;i++) /* unpack does the range checking */
151*bda690e4SXin Li 	if(ci->floor_type[i])
152*bda690e4SXin Li 	  floor1_free_info(ci->floor_param[i]);
153*bda690e4SXin Li 	else
154*bda690e4SXin Li 	  floor0_free_info(ci->floor_param[i]);
155*bda690e4SXin Li       _ogg_free(ci->floor_param);
156*bda690e4SXin Li       _ogg_free(ci->floor_type);
157*bda690e4SXin Li     }
158*bda690e4SXin Li 
159*bda690e4SXin Li     if(ci->residue_param){
160*bda690e4SXin Li       for(i=0;i<ci->residues;i++) /* unpack does the range checking */
161*bda690e4SXin Li 	res_clear_info(ci->residue_param+i);
162*bda690e4SXin Li       _ogg_free(ci->residue_param);
163*bda690e4SXin Li     }
164*bda690e4SXin Li 
165*bda690e4SXin Li     if(ci->book_param){
166*bda690e4SXin Li       for(i=0;i<ci->books;i++)
167*bda690e4SXin Li 	vorbis_book_clear(ci->book_param+i);
168*bda690e4SXin Li       _ogg_free(ci->book_param);
169*bda690e4SXin Li     }
170*bda690e4SXin Li 
171*bda690e4SXin Li     _ogg_free(ci);
172*bda690e4SXin Li   }
173*bda690e4SXin Li 
174*bda690e4SXin Li   memset(vi,0,sizeof(*vi));
175*bda690e4SXin Li }
176*bda690e4SXin Li 
177*bda690e4SXin Li /* Header packing/unpacking ********************************************/
178*bda690e4SXin Li 
_vorbis_unpack_info(vorbis_info * vi,oggpack_buffer * opb)179*bda690e4SXin Li int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
180*bda690e4SXin Li   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
181*bda690e4SXin Li   if(!ci)return(OV_EFAULT);
182*bda690e4SXin Li 
183*bda690e4SXin Li   vi->version=oggpack_read(opb,32);
184*bda690e4SXin Li   if(vi->version!=0)return(OV_EVERSION);
185*bda690e4SXin Li 
186*bda690e4SXin Li   vi->channels=oggpack_read(opb,8);
187*bda690e4SXin Li   vi->rate=oggpack_read(opb,32);
188*bda690e4SXin Li 
189*bda690e4SXin Li   vi->bitrate_upper=oggpack_read(opb,32);
190*bda690e4SXin Li   vi->bitrate_nominal=oggpack_read(opb,32);
191*bda690e4SXin Li   vi->bitrate_lower=oggpack_read(opb,32);
192*bda690e4SXin Li 
193*bda690e4SXin Li   ci->blocksizes[0]=1<<oggpack_read(opb,4);
194*bda690e4SXin Li   ci->blocksizes[1]=1<<oggpack_read(opb,4);
195*bda690e4SXin Li 
196*bda690e4SXin Li #ifdef LIMIT_TO_64kHz
197*bda690e4SXin Li   if(vi->rate>=64000 || ci->blocksizes[1]>4096)goto err_out;
198*bda690e4SXin Li #else
199*bda690e4SXin Li   if(vi->rate<64000 && ci->blocksizes[1]>4096)goto err_out;
200*bda690e4SXin Li #endif
201*bda690e4SXin Li 
202*bda690e4SXin Li   if(vi->rate<1)goto err_out;
203*bda690e4SXin Li   if(vi->channels<1)goto err_out;
204*bda690e4SXin Li   if(ci->blocksizes[0]<64)goto err_out;
205*bda690e4SXin Li   if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
206*bda690e4SXin Li   if(ci->blocksizes[1]>8192)goto err_out;
207*bda690e4SXin Li 
208*bda690e4SXin Li   if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
209*bda690e4SXin Li 
210*bda690e4SXin Li   return(0);
211*bda690e4SXin Li  err_out:
212*bda690e4SXin Li   vorbis_info_clear(vi);
213*bda690e4SXin Li   return(OV_EBADHEADER);
214*bda690e4SXin Li }
215*bda690e4SXin Li 
_vorbis_unpack_comment(vorbis_comment * vc,oggpack_buffer * opb)216*bda690e4SXin Li int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
217*bda690e4SXin Li   int i;
218*bda690e4SXin Li   int vendorlen=oggpack_read(opb,32);
219*bda690e4SXin Li   if(vendorlen<0)goto err_out;
220*bda690e4SXin Li   vc->vendor=(char *)_ogg_calloc(vendorlen+1,1);
221*bda690e4SXin Li   if(!vc->vendor)goto err_out;
222*bda690e4SXin Li   _v_readstring(opb,vc->vendor,vendorlen);
223*bda690e4SXin Li   vc->comments=oggpack_read(opb,32);
224*bda690e4SXin Li   if(vc->comments<0)goto err_out;
225*bda690e4SXin Li   vc->user_comments=(char **)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
226*bda690e4SXin Li   if (!vc->user_comments){
227*bda690e4SXin Li       vc->comments=0;
228*bda690e4SXin Li       goto err_out;
229*bda690e4SXin Li   }
230*bda690e4SXin Li   vc->comment_lengths=(int *)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
231*bda690e4SXin Li   if (!vc->comment_lengths)goto err_out;
232*bda690e4SXin Li 
233*bda690e4SXin Li   for(i=0;i<vc->comments;i++){
234*bda690e4SXin Li     int len=oggpack_read(opb,32);
235*bda690e4SXin Li     if(len<0)goto err_out;
236*bda690e4SXin Li 	vc->comment_lengths[i]=len;
237*bda690e4SXin Li     vc->user_comments[i]=(char *)_ogg_calloc(len+1,1);
238*bda690e4SXin Li     if(!vc->user_comments[i])goto err_out;
239*bda690e4SXin Li     _v_readstring(opb,vc->user_comments[i],len);
240*bda690e4SXin Li   }
241*bda690e4SXin Li   if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
242*bda690e4SXin Li 
243*bda690e4SXin Li   return(0);
244*bda690e4SXin Li  err_out:
245*bda690e4SXin Li   vorbis_comment_clear(vc);
246*bda690e4SXin Li   return(OV_EBADHEADER);
247*bda690e4SXin Li }
248*bda690e4SXin Li 
249*bda690e4SXin Li /* all of the real encoding details are here.  The modes, books,
250*bda690e4SXin Li    everything */
_vorbis_unpack_books(vorbis_info * vi,oggpack_buffer * opb)251*bda690e4SXin Li int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
252*bda690e4SXin Li   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
253*bda690e4SXin Li   int i;
254*bda690e4SXin Li   if(!ci)return(OV_EFAULT);
255*bda690e4SXin Li 
256*bda690e4SXin Li   /* codebooks */
257*bda690e4SXin Li   ci->books=oggpack_read(opb,8)+1;
258*bda690e4SXin Li   ci->book_param=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->book_param));
259*bda690e4SXin Li   if(!ci->book_param){
260*bda690e4SXin Li     ci->books=0;
261*bda690e4SXin Li     goto err_out;
262*bda690e4SXin Li   }
263*bda690e4SXin Li   for(i=0;i<ci->books;i++)
264*bda690e4SXin Li     if(vorbis_book_unpack(opb,ci->book_param+i))goto err_out;
265*bda690e4SXin Li 
266*bda690e4SXin Li   /* time backend settings, not actually used */
267*bda690e4SXin Li   i=oggpack_read(opb,6);
268*bda690e4SXin Li   for(;i>=0;i--)
269*bda690e4SXin Li     if(oggpack_read(opb,16)!=0)goto err_out;
270*bda690e4SXin Li 
271*bda690e4SXin Li   /* floor backend settings */
272*bda690e4SXin Li   ci->floors=oggpack_read(opb,6)+1;
273*bda690e4SXin Li   ci->floor_param=_ogg_calloc(ci->floors, sizeof(*ci->floor_param));
274*bda690e4SXin Li   ci->floor_type=_ogg_calloc(ci->floors, sizeof(*ci->floor_type));
275*bda690e4SXin Li   if(!ci->floor_param || !ci->floor_type){
276*bda690e4SXin Li     ci->floors=0;
277*bda690e4SXin Li     goto err_out;
278*bda690e4SXin Li   }
279*bda690e4SXin Li   for(i=0;i<ci->floors;i++){
280*bda690e4SXin Li     ci->floor_type[i]=(char)oggpack_read(opb,16);
281*bda690e4SXin Li     if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
282*bda690e4SXin Li     if(ci->floor_type[i])
283*bda690e4SXin Li       ci->floor_param[i]=floor1_info_unpack(vi,opb);
284*bda690e4SXin Li     else
285*bda690e4SXin Li       ci->floor_param[i]=floor0_info_unpack(vi,opb);
286*bda690e4SXin Li     if(!ci->floor_param[i])goto err_out;
287*bda690e4SXin Li   }
288*bda690e4SXin Li 
289*bda690e4SXin Li   /* residue backend settings */
290*bda690e4SXin Li   ci->residues=oggpack_read(opb,6)+1;
291*bda690e4SXin Li   ci->residue_param=_ogg_calloc(ci->residues, sizeof(*ci->residue_param));
292*bda690e4SXin Li   if (!ci->residue_param){
293*bda690e4SXin Li     ci->residues=0;
294*bda690e4SXin Li     goto err_out;
295*bda690e4SXin Li   }
296*bda690e4SXin Li   for(i=0;i<ci->residues;i++)
297*bda690e4SXin Li     if(res_unpack(ci->residue_param+i,vi,opb))goto err_out;
298*bda690e4SXin Li 
299*bda690e4SXin Li   /* map backend settings */
300*bda690e4SXin Li   ci->maps=oggpack_read(opb,6)+1;
301*bda690e4SXin Li   ci->map_param=_ogg_calloc(ci->maps, sizeof(*ci->map_param));
302*bda690e4SXin Li   if (!ci->map_param){
303*bda690e4SXin Li     ci->maps=0;
304*bda690e4SXin Li     goto err_out;
305*bda690e4SXin Li   }
306*bda690e4SXin Li   for(i=0;i<ci->maps;i++){
307*bda690e4SXin Li     if(oggpack_read(opb,16)!=0)goto err_out;
308*bda690e4SXin Li     if(mapping_info_unpack(ci->map_param+i,vi,opb))goto err_out;
309*bda690e4SXin Li   }
310*bda690e4SXin Li 
311*bda690e4SXin Li   /* mode settings */
312*bda690e4SXin Li   ci->modes=oggpack_read(opb,6)+1;
313*bda690e4SXin Li   ci->mode_param=
314*bda690e4SXin Li     (vorbis_info_mode *)_ogg_calloc(ci->modes, sizeof(*ci->mode_param));
315*bda690e4SXin Li   if (!ci->mode_param){
316*bda690e4SXin Li     ci->modes=0;
317*bda690e4SXin Li     goto err_out;
318*bda690e4SXin Li   }
319*bda690e4SXin Li   for(i=0;i<ci->modes;i++){
320*bda690e4SXin Li     ci->mode_param[i].blockflag=(unsigned char)oggpack_read(opb,1);
321*bda690e4SXin Li     if(oggpack_read(opb,16))goto err_out;
322*bda690e4SXin Li     if(oggpack_read(opb,16))goto err_out;
323*bda690e4SXin Li     ci->mode_param[i].mapping=(unsigned char)oggpack_read(opb,8);
324*bda690e4SXin Li     if(ci->mode_param[i].mapping>=ci->maps)goto err_out;
325*bda690e4SXin Li   }
326*bda690e4SXin Li 
327*bda690e4SXin Li   if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
328*bda690e4SXin Li 
329*bda690e4SXin Li   return(0);
330*bda690e4SXin Li  err_out:
331*bda690e4SXin Li   vorbis_info_clear(vi);
332*bda690e4SXin Li   return(OV_EBADHEADER);
333*bda690e4SXin Li }
334*bda690e4SXin Li 
335*bda690e4SXin Li /* The Vorbis header is in three packets; the initial small packet in
336*bda690e4SXin Li    the first page that identifies basic parameters, a second packet
337*bda690e4SXin Li    with bitstream comments and a third packet that holds the
338*bda690e4SXin Li    codebook. */
339*bda690e4SXin Li 
vorbis_dsp_headerin(vorbis_info * vi,vorbis_comment * vc,ogg_packet * op)340*bda690e4SXin Li int vorbis_dsp_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
341*bda690e4SXin Li   oggpack_buffer opb;
342*bda690e4SXin Li 
343*bda690e4SXin Li   if(op){
344*bda690e4SXin Li     oggpack_readinit(&opb,op->packet);
345*bda690e4SXin Li 
346*bda690e4SXin Li     /* Which of the three types of header is this? */
347*bda690e4SXin Li     /* Also verify header-ness, vorbis */
348*bda690e4SXin Li     {
349*bda690e4SXin Li       char buffer[6];
350*bda690e4SXin Li       int packtype=oggpack_read(&opb,8);
351*bda690e4SXin Li       memset(buffer,0,6);
352*bda690e4SXin Li       _v_readstring(&opb,buffer,6);
353*bda690e4SXin Li       if(memcmp(buffer,"vorbis",6)){
354*bda690e4SXin Li 	/* not a vorbis header */
355*bda690e4SXin Li 	return(OV_ENOTVORBIS);
356*bda690e4SXin Li       }
357*bda690e4SXin Li       switch(packtype){
358*bda690e4SXin Li       case 0x01: /* least significant *bit* is read first */
359*bda690e4SXin Li 	if(!op->b_o_s){
360*bda690e4SXin Li 	  /* Not the initial packet */
361*bda690e4SXin Li 	  return(OV_EBADHEADER);
362*bda690e4SXin Li 	}
363*bda690e4SXin Li 	if(vi->rate!=0){
364*bda690e4SXin Li 	  /* previously initialized info header */
365*bda690e4SXin Li 	  return(OV_EBADHEADER);
366*bda690e4SXin Li 	}
367*bda690e4SXin Li 
368*bda690e4SXin Li 	return(_vorbis_unpack_info(vi,&opb));
369*bda690e4SXin Li 
370*bda690e4SXin Li       case 0x03: /* least significant *bit* is read first */
371*bda690e4SXin Li 	if(vi->rate==0){
372*bda690e4SXin Li 	  /* um... we didn't get the initial header */
373*bda690e4SXin Li 	  return(OV_EBADHEADER);
374*bda690e4SXin Li 	}
375*bda690e4SXin Li 
376*bda690e4SXin Li 	return(_vorbis_unpack_comment(vc,&opb));
377*bda690e4SXin Li 
378*bda690e4SXin Li       case 0x05: /* least significant *bit* is read first */
379*bda690e4SXin Li 	if(vi->rate==0 || vc->vendor==NULL){
380*bda690e4SXin Li 	  /* um... we didn;t get the initial header or comments yet */
381*bda690e4SXin Li 	  return(OV_EBADHEADER);
382*bda690e4SXin Li 	}
383*bda690e4SXin Li 
384*bda690e4SXin Li 	return(_vorbis_unpack_books(vi,&opb));
385*bda690e4SXin Li 
386*bda690e4SXin Li       default:
387*bda690e4SXin Li 	/* Not a valid vorbis header type */
388*bda690e4SXin Li 	return(OV_EBADHEADER);
389*bda690e4SXin Li 	break;
390*bda690e4SXin Li       }
391*bda690e4SXin Li     }
392*bda690e4SXin Li   }
393*bda690e4SXin Li   return(OV_EBADHEADER);
394*bda690e4SXin Li }
395*bda690e4SXin Li 
396