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