18e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/********************************************************************
28e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
38e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
48e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
58e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
68e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
78e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
88e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
98e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * by the Xiph.Org Foundation http://www.xiph.org/                  *
108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************
128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels function: simple example decoder
148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels last mod: $Id: decoder_example.c 16243 2009-07-10 02:49:31Z xiphmont $
158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************/
178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* Takes a vorbis bitstream from stdin and writes raw stereo PCM to
198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   stdout. Decodes simple and chained OggVorbis files from beginning
208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   to end. Vorbisfile.a is somewhat more complex than the code below.  */
218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* Note that this is POSIX, not ANSI code */
238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <stdio.h>
258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <stdlib.h>
268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <math.h>
278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <vorbis/codec.h>
288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */
308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <io.h>
318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <fcntl.h>
328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#endif
338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#if defined(__MACOS__) && defined(__MWERKS__)
358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <console.h>      /* CodeWarrior's Mac "command-line" support */
368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#endif
378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */
398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsint convsize=4096;
408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsextern void _VDBG_dump(void);
428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsint main(){
448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  ogg_stream_state os; /* take physical pages, weld into a logical
468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                          stream of packets */
478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  ogg_page         og; /* one Ogg bitstream page. Vorbis packets are inside */
488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  ogg_packet       op; /* one raw packet of data for decode */
498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                          settings */
528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_comment   vc; /* struct that stores all the bitstream user comments */
538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  vorbis_block     vb; /* local working space for packet->PCM decode */
558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  char *buffer;
578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int  bytes;
588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* Beware the evil ifdef. We avoid these where we can, but this one we
618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels     cannot. Don't add any more, you'll probably go to hell if you do. */
628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  _setmode( _fileno( stdin ), _O_BINARY );
638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  _setmode( _fileno( stdout ), _O_BINARY );
648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#endif
658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#if defined(macintosh) && defined(__MWERKS__)
678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  {
688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int argc;
698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    char **argv;
708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    argc=ccommand(&argv); /* get a "command line" from the Mac user */
718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                     /* this also lets the user set stdin and stdout */
728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#endif
748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /********** Decode setup ************/
768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  ogg_sync_init(&oy); /* Now we can read pages */
788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  while(1){ /* we repeat if the bitstream is chained */
808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int eos=0;
818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int i;
828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* grab some data at the head of the stream. We want the first page
848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       (which is guaranteed to be small and only contain the Vorbis
858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       stream initial header) We need the first page to get the stream
868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       serialno. */
878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* submit a 4k block to libvorbis' Ogg layer */
898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    buffer=ogg_sync_buffer(&oy,4096);
908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    bytes=fread(buffer,1,4096,stdin);
918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    ogg_sync_wrote(&oy,bytes);
928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* Get the first page. */
948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(ogg_sync_pageout(&oy,&og)!=1){
958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* have we simply run out of data?  If so, we're done. */
968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(bytes<4096)break;
978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* error case.  Must not be Vorbis data */
998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
1008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
1018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* Get the serial number and set up the rest of decode. */
1048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* serialno first; use it to set up a logical stream */
1058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    ogg_stream_init(&os,ogg_page_serialno(&og));
1068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* extract the initial header from the first page and verify that the
1088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       Ogg bitstream is in fact Vorbis data */
1098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* I handle the initial header first instead of just having the code
1118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       read all three Vorbis headers at once because reading the initial
1128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       header is an easy way to identify a Vorbis bitstream and it's
1138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       useful to see that functionality seperated out. */
1148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    vorbis_info_init(&vi);
1168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    vorbis_comment_init(&vc);
1178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(ogg_stream_pagein(&os,&og)<0){
1188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* error; stream version mismatch perhaps */
1198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"Error reading first page of Ogg bitstream data.\n");
1208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
1218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(ogg_stream_packetout(&os,&op)!=1){
1248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* no page? must not be vorbis */
1258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"Error reading initial header packet.\n");
1268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
1278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){
1308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* error case; not a vorbis header */
1318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"This Ogg bitstream does not contain Vorbis "
1328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              "audio data.\n");
1338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      exit(1);
1348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* At this point, we're sure we're Vorbis. We've set up the logical
1378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       (Ogg) bitstream decoder. Get the comment and codebook headers and
1388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       set up the Vorbis decoder */
1398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* The next two packets in order are the comment and codebook headers.
1418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       They're likely large and may span multiple pages. Thus we read
1428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       and submit data until we get our two packets, watching that no
1438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       pages are missing. If a page is missing, error out; losing a
1448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       header page is the only place where missing data is fatal. */
1458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    i=0;
1478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    while(i<2){
1488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      while(i<2){
1498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        int result=ogg_sync_pageout(&oy,&og);
1508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(result==0)break; /* Need more data */
1518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        /* Don't complain about missing or corrupt data yet. We'll
1528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           catch it at the packet output phase */
1538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(result==1){
1548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          ogg_stream_pagein(&os,&og); /* we can ignore any errors here
1558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                         as they'll also become apparent
1568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                         at packetout */
1578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          while(i<2){
1588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            result=ogg_stream_packetout(&os,&op);
1598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(result==0)break;
1608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(result<0){
1618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              /* Uh oh; data at some point was corrupted or missing!
1628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                 We can't tolerate that in a header.  Die. */
1638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              fprintf(stderr,"Corrupt secondary header.  Exiting.\n");
1648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              exit(1);
1658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            }
1668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            result=vorbis_synthesis_headerin(&vi,&vc,&op);
1678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(result<0){
1688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              fprintf(stderr,"Corrupt secondary header.  Exiting.\n");
1698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              exit(1);
1708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            }
1718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            i++;
1728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          }
1738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
1748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
1758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* no harm in not checking before adding more */
1768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      buffer=ogg_sync_buffer(&oy,4096);
1778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      bytes=fread(buffer,1,4096,stdin);
1788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      if(bytes==0 && i<2){
1798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        fprintf(stderr,"End of file before finding all Vorbis headers!\n");
1808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        exit(1);
1818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
1828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      ogg_sync_wrote(&oy,bytes);
1838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* Throw the comments plus a few lines about the bitstream we're
1868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       decoding */
1878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    {
1888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      char **ptr=vc.user_comments;
1898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      while(*ptr){
1908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        fprintf(stderr,"%s\n",*ptr);
1918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        ++ptr;
1928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
1938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate);
1948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
1958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
1968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    convsize=4096/vi.channels;
1988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* OK, got and parsed all three headers. Initialize the Vorbis
2008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       packet->PCM decoder. */
2018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(vorbis_synthesis_init(&vd,&vi)==0){ /* central decode state */
2028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      vorbis_block_init(&vd,&vb);          /* local state for most of the decode
2038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                              so multiple block decodes can
2048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                              proceed in parallel. We could init
2058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                              multiple vorbis_block structures
2068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                              for vd here */
2078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* The rest is just a straight decode loop until end of stream */
2098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      while(!eos){
2108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        while(!eos){
2118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          int result=ogg_sync_pageout(&oy,&og);
2128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(result==0)break; /* need more data */
2138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(result<0){ /* missing or corrupt data at this page position */
2148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            fprintf(stderr,"Corrupt or missing data in bitstream; "
2158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    "continuing...\n");
2168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          }else{
2178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            ogg_stream_pagein(&os,&og); /* can safely ignore errors at
2188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                           this point */
2198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            while(1){
2208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              result=ogg_stream_packetout(&os,&op);
2218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              if(result==0)break; /* need more data */
2238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              if(result<0){ /* missing or corrupt data at this page position */
2248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /* no reason to complain; already complained above */
2258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              }else{
2268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /* we have a packet.  Decode it */
2278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                float **pcm;
2288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                int samples;
2298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
2318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  vorbis_synthesis_blockin(&vd,&vb);
2328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                /*
2338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                **pcm is a multichannel float vector.  In stereo, for
2358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                example, pcm[0] is left, and pcm[1] is right.  samples is
2368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                the size of each channel.  Convert the float values
2378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                (-1.<=range<=1.) to whatever PCM format and write it out */
2388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
2408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  int j;
2418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  int clipflag=0;
2428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  int bout=(samples<convsize?samples:convsize);
2438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  /* convert floats to 16 bit signed ints (host order) and
2458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                     interleave */
2468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  for(i=0;i<vi.channels;i++){
2478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    ogg_int16_t *ptr=convbuffer+i;
2488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    float  *mono=pcm[i];
2498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    for(j=0;j<bout;j++){
2508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#if 1
2518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      int val=floor(mono[j]*32767.f+.5f);
2528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#else /* optional dither */
2538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      int val=mono[j]*32767.f+drand48()-0.5f;
2548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#endif
2558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      /* might as well guard against clipping */
2568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      if(val>32767){
2578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        val=32767;
2588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        clipflag=1;
2598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      }
2608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      if(val<-32768){
2618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        val=-32768;
2628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                        clipflag=1;
2638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      }
2648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      *ptr=val;
2658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                      ptr+=vi.channels;
2668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    }
2678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  }
2688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  if(clipflag)
2708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                    fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
2718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  fwrite(convbuffer,2*vi.channels,bout,stdout);
2748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                  vorbis_synthesis_read(&vd,bout); /* tell libvorbis how
2768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                                      many samples we
2778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                                      actually consumed */
2788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                }
2798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              }
2808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            }
2818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels            if(ogg_page_eos(&og))eos=1;
2828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          }
2838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
2848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if(!eos){
2858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          buffer=ogg_sync_buffer(&oy,4096);
2868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          bytes=fread(buffer,1,4096,stdin);
2878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          ogg_sync_wrote(&oy,bytes);
2888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels          if(bytes==0)eos=1;
2898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        }
2908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      }
2918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      /* ogg_page and ogg_packet structs always point to storage in
2938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels         libvorbis.  They're never freed or manipulated directly */
2948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      vorbis_block_clear(&vb);
2968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      vorbis_dsp_clear(&vd);
2978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }else{
2988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      fprintf(stderr,"Error: Corrupt header during playback initialization.\n");
2998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
3008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    /* clean up this logical bitstream; before exit we see if we're
3028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels       followed by another [chained] */
3038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    ogg_stream_clear(&os);
3058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    vorbis_comment_clear(&vc);
3068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    vorbis_info_clear(&vi);  /* must be called last */
3078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* OK, clean up the framer */
3108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  ogg_sync_clear(&oy);
3118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  fprintf(stderr,"Done.\n");
3138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  return(0);
3148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
315