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