Kill some warnings. Oh, and make examples compile again under
[platform/upstream/libvorbis.git] / examples / decoder_example.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13  function: simple example decoder
14  last mod: $Id: decoder_example.c,v 1.24 2001/12/19 23:13:32 segher Exp $
15
16  ********************************************************************/
17
18 /* Takes a vorbis bitstream from stdin and writes raw stereo PCM to
19    stdout.  Decodes simple and chained OggVorbis files from beginning
20    to end.  Vorbisfile.a is somewhat more complex than the code below.  */
21
22 /* Note that this is POSIX, not ANSI code */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <math.h>
27 #include <vorbis/codec.h>
28
29 #ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */
30 #include <io.h>
31 #include <fcntl.h>
32 #endif
33
34 #if defined(macintosh) && defined(__MWERKS__)
35 #include <console.h>      /* CodeWarrior's Mac "command-line" support */
36 #endif
37
38 ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */
39 int convsize=4096;
40
41 int main(){
42   ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
43   ogg_stream_state os; /* take physical pages, weld into a logical
44                           stream of packets */
45   ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
46   ogg_packet       op; /* one raw packet of data for decode */
47   
48   vorbis_info      vi; /* struct that stores all the static vorbis bitstream
49                           settings */
50   vorbis_comment   vc; /* struct that stores all the bitstream user comments */
51   vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
52   vorbis_block     vb; /* local working space for packet->PCM decode */
53   
54   char *buffer;
55   int  bytes;
56
57 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
58   /* Beware the evil ifdef. We avoid these where we can, but this one we 
59      cannot. Don't add any more, you'll probably go to hell if you do. */
60   _setmode( _fileno( stdin ), _O_BINARY );
61   _setmode( _fileno( stdout ), _O_BINARY );
62 #endif
63
64 #if defined(macintosh) && defined(__MWERKS__)
65   {
66     int argc;
67     char **argv;
68     argc=ccommand(&argv); /* get a "command line" from the Mac user */
69                      /* this also lets the user set stdin and stdout */
70   }
71 #endif
72
73   /********** Decode setup ************/
74
75   ogg_sync_init(&oy); /* Now we can read pages */
76   
77   while(1){ /* we repeat if the bitstream is chained */
78     int eos=0;
79     int i;
80
81     /* grab some data at the head of the stream.  We want the first page
82        (which is guaranteed to be small and only contain the Vorbis
83        stream initial header) We need the first page to get the stream
84        serialno. */
85
86     /* submit a 4k block to libvorbis' Ogg layer */
87     buffer=ogg_sync_buffer(&oy,4096);
88     bytes=fread(buffer,1,4096,stdin);
89     ogg_sync_wrote(&oy,bytes);
90     
91     /* Get the first page. */
92     if(ogg_sync_pageout(&oy,&og)!=1){
93       /* have we simply run out of data?  If so, we're done. */
94       if(bytes<4096)break;
95       
96       /* error case.  Must not be Vorbis data */
97       fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
98       exit(1);
99     }
100   
101     /* Get the serial number and set up the rest of decode. */
102     /* serialno first; use it to set up a logical stream */
103     ogg_stream_init(&os,ogg_page_serialno(&og));
104     
105     /* extract the initial header from the first page and verify that the
106        Ogg bitstream is in fact Vorbis data */
107     
108     /* I handle the initial header first instead of just having the code
109        read all three Vorbis headers at once because reading the initial
110        header is an easy way to identify a Vorbis bitstream and it's
111        useful to see that functionality seperated out. */
112     
113     vorbis_info_init(&vi);
114     vorbis_comment_init(&vc);
115     if(ogg_stream_pagein(&os,&og)<0){ 
116       /* error; stream version mismatch perhaps */
117       fprintf(stderr,"Error reading first page of Ogg bitstream data.\n");
118       exit(1);
119     }
120     
121     if(ogg_stream_packetout(&os,&op)!=1){ 
122       /* no page? must not be vorbis */
123       fprintf(stderr,"Error reading initial header packet.\n");
124       exit(1);
125     }
126     
127     if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
128       /* error case; not a vorbis header */
129       fprintf(stderr,"This Ogg bitstream does not contain Vorbis "
130               "audio data.\n");
131       exit(1);
132     }
133     
134     /* At this point, we're sure we're Vorbis.  We've set up the logical
135        (Ogg) bitstream decoder.  Get the comment and codebook headers and
136        set up the Vorbis decoder */
137     
138     /* The next two packets in order are the comment and codebook headers.
139        They're likely large and may span multiple pages.  Thus we reead
140        and submit data until we get our two pacakets, watching that no
141        pages are missing.  If a page is missing, error out; losing a
142        header page is the only place where missing data is fatal. */
143     
144     i=0;
145     while(i<2){
146       while(i<2){
147         int result=ogg_sync_pageout(&oy,&og);
148         if(result==0)break; /* Need more data */
149         /* Don't complain about missing or corrupt data yet.  We'll
150            catch it at the packet output phase */
151         if(result==1){
152           ogg_stream_pagein(&os,&og); /* we can ignore any errors here
153                                          as they'll also become apparent
154                                          at packetout */
155           while(i<2){
156             result=ogg_stream_packetout(&os,&op);
157             if(result==0)break;
158             if(result<0){
159               /* Uh oh; data at some point was corrupted or missing!
160                  We can't tolerate that in a header.  Die. */
161               fprintf(stderr,"Corrupt secondary header.  Exiting.\n");
162               exit(1);
163             }
164             vorbis_synthesis_headerin(&vi,&vc,&op);
165             i++;
166           }
167         }
168       }
169       /* no harm in not checking before adding more */
170       buffer=ogg_sync_buffer(&oy,4096);
171       bytes=fread(buffer,1,4096,stdin);
172       if(bytes==0 && i<2){
173         fprintf(stderr,"End of file before finding all Vorbis headers!\n");
174         exit(1);
175       }
176       ogg_sync_wrote(&oy,bytes);
177     }
178     
179     /* Throw the comments plus a few lines about the bitstream we're
180        decoding */
181     {
182       char **ptr=vc.user_comments;
183       while(*ptr){
184         fprintf(stderr,"%s\n",*ptr);
185         ++ptr;
186       }
187       fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate);
188       fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
189     }
190     
191     convsize=4096/vi.channels;
192
193     /* OK, got and parsed all three headers. Initialize the Vorbis
194        packet->PCM decoder. */
195     vorbis_synthesis_init(&vd,&vi); /* central decode state */
196     vorbis_block_init(&vd,&vb);     /* local state for most of the decode
197                                        so multiple block decodes can
198                                        proceed in parallel.  We could init
199                                        multiple vorbis_block structures
200                                        for vd here */
201     
202     /* The rest is just a straight decode loop until end of stream */
203     while(!eos){
204       while(!eos){
205         int result=ogg_sync_pageout(&oy,&og);
206         if(result==0)break; /* need more data */
207         if(result<0){ /* missing or corrupt data at this page position */
208           fprintf(stderr,"Corrupt or missing data in bitstream; "
209                   "continuing...\n");
210         }else{
211           ogg_stream_pagein(&os,&og); /* can safely ignore errors at
212                                          this point */
213           while(1){
214             result=ogg_stream_packetout(&os,&op);
215
216             if(result==0)break; /* need more data */
217             if(result<0){ /* missing or corrupt data at this page position */
218               /* no reason to complain; already complained above */
219             }else{
220               /* we have a packet.  Decode it */
221               float **pcm;
222               int samples;
223               
224               if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
225                 vorbis_synthesis_blockin(&vd,&vb);
226               /* 
227                  
228               **pcm is a multichannel float vector.  In stereo, for
229               example, pcm[0] is left, and pcm[1] is right.  samples is
230               the size of each channel.  Convert the float values
231               (-1.<=range<=1.) to whatever PCM format and write it out */
232               
233               while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
234                 int j;
235                 int clipflag=0;
236                 int bout=(samples<convsize?samples:convsize);
237                 
238                 /* convert floats to 16 bit signed ints (host order) and
239                    interleave */
240                 for(i=0;i<vi.channels;i++){
241                   ogg_int16_t *ptr=convbuffer+i;
242                   float  *mono=pcm[i];
243                   for(j=0;j<bout;j++){
244 #if 1
245                     int val=mono[j]*32767.f;
246 #else /* optional dither */
247                     int val=mono[j]*32767.f+drand48()-0.5f;
248 #endif
249                     /* might as well guard against clipping */
250                     if(val>32767){
251                       val=32767;
252                       clipflag=1;
253                     }
254                     if(val<-32768){
255                       val=-32768;
256                       clipflag=1;
257                     }
258                     *ptr=val;
259                     ptr+=vi.channels;
260                   }
261                 }
262                 
263                 if(clipflag)
264                   fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
265                 
266                 
267                 fwrite(convbuffer,2*vi.channels,bout,stdout);
268                 
269                 vorbis_synthesis_read(&vd,bout); /* tell libvorbis how
270                                                    many samples we
271                                                    actually consumed */
272               }     
273             }
274           }
275           if(ogg_page_eos(&og))eos=1;
276         }
277       }
278       if(!eos){
279         buffer=ogg_sync_buffer(&oy,4096);
280         bytes=fread(buffer,1,4096,stdin);
281         ogg_sync_wrote(&oy,bytes);
282         if(bytes==0)eos=1;
283       }
284     }
285     
286     /* clean up this logical bitstream; before exit we see if we're
287        followed by another [chained] */
288
289     ogg_stream_clear(&os);
290   
291     /* ogg_page and ogg_packet structs always point to storage in
292        libvorbis.  They're never freed or manipulated directly */
293     
294     vorbis_block_clear(&vb);
295     vorbis_dsp_clear(&vd);
296         vorbis_comment_clear(&vc);
297     vorbis_info_clear(&vi);  /* must be called last */
298   }
299
300   /* OK, clean up the framer */
301   ogg_sync_clear(&oy);
302   
303   fprintf(stderr,"Done.\n");
304   return(0);
305 }