examples/sfexamples/oggvorbiscodec/src/libvorbis/examples/decoder_example.c

00001 /********************************************************************
00002  *                                                                  *
00003  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
00004  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
00005  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
00006  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
00007  *                                                                  *
00008  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
00009  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
00010  *                                                                  *
00011  ********************************************************************
00012 
00013  function: simple example decoder
00014  last mod: $Id: decoder_example.c 7187 2004-07-20 07:24:27Z xiphmont $
00015 
00016  ********************************************************************/
00017 
00018 /* Takes a vorbis bitstream from stdin and writes raw stereo PCM to
00019    stdout.  Decodes simple and chained OggVorbis files from beginning
00020    to end.  Vorbisfile.a is somewhat more complex than the code below.  */
00021 
00022 /* Note that this is POSIX, not ANSI code */
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include <vorbis/codec.h>
00028 
00029 #if defined(_WIN32) && !defined(__SYMBIAN32__) /* We need the following two to set stdin/stdout to binary */
00030 #include <io.h>
00031 #include <fcntl.h>
00032 #endif
00033 
00034 #if defined(__MACOS__) && defined(__MWERKS__)
00035 #include <console.h>      /* CodeWarrior's Mac "command-line" support */
00036 #endif
00037 
00038 ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */
00039 int convsize=4096;
00040 
00041 extern void _VDBG_dump(void);
00042 
00043 int main(){
00044   ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
00045   ogg_stream_state os; /* take physical pages, weld into a logical
00046                           stream of packets */
00047   ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
00048   ogg_packet       op; /* one raw packet of data for decode */
00049   
00050   vorbis_info      vi; /* struct that stores all the static vorbis bitstream
00051                           settings */
00052   vorbis_comment   vc; /* struct that stores all the bitstream user comments */
00053   vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
00054   vorbis_block     vb; /* local working space for packet->PCM decode */
00055   
00056   char *buffer;
00057   int  bytes;
00058 
00059 #if defined(_WIN32) && !defined(__SYMBIAN32__) /* We need to set stdin/stdout to binary mode. Damn windows. */
00060   /* Beware the evil ifdef. We avoid these where we can, but this one we 
00061      cannot. Don't add any more, you'll probably go to hell if you do. */
00062   _setmode( _fileno( stdin ), _O_BINARY );
00063   _setmode( _fileno( stdout ), _O_BINARY );
00064 #endif
00065 
00066 #if defined(macintosh) && defined(__MWERKS__)
00067   {
00068     int argc;
00069     char **argv;
00070     argc=ccommand(&argv); /* get a "command line" from the Mac user */
00071                      /* this also lets the user set stdin and stdout */
00072   }
00073 #endif
00074 
00075   /********** Decode setup ************/
00076 
00077   ogg_sync_init(&oy); /* Now we can read pages */
00078   
00079   while(1){ /* we repeat if the bitstream is chained */
00080     int eos=0;
00081     int i;
00082 
00083     /* grab some data at the head of the stream.  We want the first page
00084        (which is guaranteed to be small and only contain the Vorbis
00085        stream initial header) We need the first page to get the stream
00086        serialno. */
00087 
00088     /* submit a 4k block to libvorbis' Ogg layer */
00089     buffer=ogg_sync_buffer(&oy,4096);
00090     bytes=fread(buffer,1,4096,stdin);
00091     ogg_sync_wrote(&oy,bytes);
00092     
00093     /* Get the first page. */
00094     if(ogg_sync_pageout(&oy,&og)!=1){
00095       /* have we simply run out of data?  If so, we're done. */
00096       if(bytes<4096)break;
00097       
00098       /* error case.  Must not be Vorbis data */
00099       fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
00100       exit(1);
00101     }
00102   
00103     /* Get the serial number and set up the rest of decode. */
00104     /* serialno first; use it to set up a logical stream */
00105     ogg_stream_init(&os,ogg_page_serialno(&og));
00106     
00107     /* extract the initial header from the first page and verify that the
00108        Ogg bitstream is in fact Vorbis data */
00109     
00110     /* I handle the initial header first instead of just having the code
00111        read all three Vorbis headers at once because reading the initial
00112        header is an easy way to identify a Vorbis bitstream and it's
00113        useful to see that functionality seperated out. */
00114     
00115     vorbis_info_init(&vi);
00116     vorbis_comment_init(&vc);
00117     if(ogg_stream_pagein(&os,&og)<0){ 
00118       /* error; stream version mismatch perhaps */
00119       fprintf(stderr,"Error reading first page of Ogg bitstream data.\n");
00120       exit(1);
00121     }
00122     
00123     if(ogg_stream_packetout(&os,&op)!=1){ 
00124       /* no page? must not be vorbis */
00125       fprintf(stderr,"Error reading initial header packet.\n");
00126       exit(1);
00127     }
00128     
00129     if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
00130       /* error case; not a vorbis header */
00131       fprintf(stderr,"This Ogg bitstream does not contain Vorbis "
00132               "audio data.\n");
00133       exit(1);
00134     }
00135     
00136     /* At this point, we're sure we're Vorbis.  We've set up the logical
00137        (Ogg) bitstream decoder.  Get the comment and codebook headers and
00138        set up the Vorbis decoder */
00139     
00140     /* The next two packets in order are the comment and codebook headers.
00141        They're likely large and may span multiple pages.  Thus we reead
00142        and submit data until we get our two pacakets, watching that no
00143        pages are missing.  If a page is missing, error out; losing a
00144        header page is the only place where missing data is fatal. */
00145     
00146     i=0;
00147     while(i<2){
00148       while(i<2){
00149         int result=ogg_sync_pageout(&oy,&og);
00150         if(result==0)break; /* Need more data */
00151         /* Don't complain about missing or corrupt data yet.  We'll
00152            catch it at the packet output phase */
00153         if(result==1){
00154           ogg_stream_pagein(&os,&og); /* we can ignore any errors here
00155                                          as they'll also become apparent
00156                                          at packetout */
00157           while(i<2){
00158             result=ogg_stream_packetout(&os,&op);
00159             if(result==0)break;
00160             if(result<0){
00161               /* Uh oh; data at some point was corrupted or missing!
00162                  We can't tolerate that in a header.  Die. */
00163               fprintf(stderr,"Corrupt secondary header.  Exiting.\n");
00164               exit(1);
00165             }
00166             vorbis_synthesis_headerin(&vi,&vc,&op);
00167             i++;
00168           }
00169         }
00170       }
00171       /* no harm in not checking before adding more */
00172       buffer=ogg_sync_buffer(&oy,4096);
00173       bytes=fread(buffer,1,4096,stdin);
00174       if(bytes==0 && i<2){
00175         fprintf(stderr,"End of file before finding all Vorbis headers!\n");
00176         exit(1);
00177       }
00178       ogg_sync_wrote(&oy,bytes);
00179     }
00180     
00181     /* Throw the comments plus a few lines about the bitstream we're
00182        decoding */
00183     {
00184       char **ptr=vc.user_comments;
00185       while(*ptr){
00186         fprintf(stderr,"%s\n",*ptr);
00187         ++ptr;
00188       }
00189       fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate);
00190       fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
00191     }
00192     
00193     convsize=4096/vi.channels;
00194 
00195     /* OK, got and parsed all three headers. Initialize the Vorbis
00196        packet->PCM decoder. */
00197     vorbis_synthesis_init(&vd,&vi); /* central decode state */
00198     vorbis_block_init(&vd,&vb);     /* local state for most of the decode
00199                                        so multiple block decodes can
00200                                        proceed in parallel.  We could init
00201                                        multiple vorbis_block structures
00202                                        for vd here */
00203     
00204     /* The rest is just a straight decode loop until end of stream */
00205     while(!eos){
00206       while(!eos){
00207         int result=ogg_sync_pageout(&oy,&og);
00208         if(result==0)break; /* need more data */
00209         if(result<0){ /* missing or corrupt data at this page position */
00210           fprintf(stderr,"Corrupt or missing data in bitstream; "
00211                   "continuing...\n");
00212         }else{
00213           ogg_stream_pagein(&os,&og); /* can safely ignore errors at
00214                                          this point */
00215           while(1){
00216             result=ogg_stream_packetout(&os,&op);
00217 
00218             if(result==0)break; /* need more data */
00219             if(result<0){ /* missing or corrupt data at this page position */
00220               /* no reason to complain; already complained above */
00221             }else{
00222               /* we have a packet.  Decode it */
00223               float **pcm;
00224               int samples;
00225               
00226               if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
00227                 vorbis_synthesis_blockin(&vd,&vb);
00228               /* 
00229                  
00230               **pcm is a multichannel float vector.  In stereo, for
00231               example, pcm[0] is left, and pcm[1] is right.  samples is
00232               the size of each channel.  Convert the float values
00233               (-1.<=range<=1.) to whatever PCM format and write it out */
00234               
00235               while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
00236                 int j;
00237                 int clipflag=0;
00238                 int bout=(samples<convsize?samples:convsize);
00239                 
00240                 /* convert floats to 16 bit signed ints (host order) and
00241                    interleave */
00242                 for(i=0;i<vi.channels;i++){
00243                   ogg_int16_t *ptr=convbuffer+i;
00244                   float  *mono=pcm[i];
00245                   for(j=0;j<bout;j++){
00246 #if 1
00247                     int val=mono[j]*32767.f;
00248 #else /* optional dither */
00249                     int val=mono[j]*32767.f+drand48()-0.5f;
00250 #endif
00251                     /* might as well guard against clipping */
00252                     if(val>32767){
00253                       val=32767;
00254                       clipflag=1;
00255                     }
00256                     if(val<-32768){
00257                       val=-32768;
00258                       clipflag=1;
00259                     }
00260                     *ptr=val;
00261                     ptr+=vi.channels;
00262                   }
00263                 }
00264                 
00265                 if(clipflag)
00266                   fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
00267                 
00268                 
00269                 fwrite(convbuffer,2*vi.channels,bout,stdout);
00270                 
00271                 vorbis_synthesis_read(&vd,bout); /* tell libvorbis how
00272                                                    many samples we
00273                                                    actually consumed */
00274               }     
00275             }
00276           }
00277           if(ogg_page_eos(&og))eos=1;
00278         }
00279       }
00280       if(!eos){
00281         buffer=ogg_sync_buffer(&oy,4096);
00282         bytes=fread(buffer,1,4096,stdin);
00283         ogg_sync_wrote(&oy,bytes);
00284         if(bytes==0)eos=1;
00285       }
00286     }
00287     
00288     /* clean up this logical bitstream; before exit we see if we're
00289        followed by another [chained] */
00290 
00291     ogg_stream_clear(&os);
00292   
00293     /* ogg_page and ogg_packet structs always point to storage in
00294        libvorbis.  They're never freed or manipulated directly */
00295     
00296     vorbis_block_clear(&vb);
00297     vorbis_dsp_clear(&vd);
00298         vorbis_comment_clear(&vc);
00299     vorbis_info_clear(&vi);  /* must be called last */
00300   }
00301 
00302   /* OK, clean up the framer */
00303   ogg_sync_clear(&oy);
00304   
00305   fprintf(stderr,"Done.\n");
00306   return(0);
00307 }

Generated by  doxygen 1.6.2