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