Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/libvorbis-1.2.0/examples/decoder_example.c @ 16

Last change on this file since 16 was 16, checked in by landauf, 16 years ago

added libvorbis

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