Mercurial > hg > sv-dependency-builds
comparison src/libvorbis-1.3.3/examples/decoder_example.c @ 86:98c1576536ae
Bring in flac, ogg, vorbis
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 19 Mar 2013 17:37:49 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
85:545efbb81310 | 86:98c1576536ae |
---|---|
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-2009 * | |
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 16243 2009-07-10 02:49:31Z 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 | |
38 ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */ | |
39 int convsize=4096; | |
40 | |
41 extern void _VDBG_dump(void); | |
42 | |
43 int 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 read | |
142 and submit data until we get our two packets, 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 result=vorbis_synthesis_headerin(&vi,&vc,&op); | |
167 if(result<0){ | |
168 fprintf(stderr,"Corrupt secondary header. Exiting.\n"); | |
169 exit(1); | |
170 } | |
171 i++; | |
172 } | |
173 } | |
174 } | |
175 /* no harm in not checking before adding more */ | |
176 buffer=ogg_sync_buffer(&oy,4096); | |
177 bytes=fread(buffer,1,4096,stdin); | |
178 if(bytes==0 && i<2){ | |
179 fprintf(stderr,"End of file before finding all Vorbis headers!\n"); | |
180 exit(1); | |
181 } | |
182 ogg_sync_wrote(&oy,bytes); | |
183 } | |
184 | |
185 /* Throw the comments plus a few lines about the bitstream we're | |
186 decoding */ | |
187 { | |
188 char **ptr=vc.user_comments; | |
189 while(*ptr){ | |
190 fprintf(stderr,"%s\n",*ptr); | |
191 ++ptr; | |
192 } | |
193 fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate); | |
194 fprintf(stderr,"Encoded by: %s\n\n",vc.vendor); | |
195 } | |
196 | |
197 convsize=4096/vi.channels; | |
198 | |
199 /* OK, got and parsed all three headers. Initialize the Vorbis | |
200 packet->PCM decoder. */ | |
201 if(vorbis_synthesis_init(&vd,&vi)==0){ /* central decode state */ | |
202 vorbis_block_init(&vd,&vb); /* local state for most of the decode | |
203 so multiple block decodes can | |
204 proceed in parallel. We could init | |
205 multiple vorbis_block structures | |
206 for vd here */ | |
207 | |
208 /* The rest is just a straight decode loop until end of stream */ | |
209 while(!eos){ | |
210 while(!eos){ | |
211 int result=ogg_sync_pageout(&oy,&og); | |
212 if(result==0)break; /* need more data */ | |
213 if(result<0){ /* missing or corrupt data at this page position */ | |
214 fprintf(stderr,"Corrupt or missing data in bitstream; " | |
215 "continuing...\n"); | |
216 }else{ | |
217 ogg_stream_pagein(&os,&og); /* can safely ignore errors at | |
218 this point */ | |
219 while(1){ | |
220 result=ogg_stream_packetout(&os,&op); | |
221 | |
222 if(result==0)break; /* need more data */ | |
223 if(result<0){ /* missing or corrupt data at this page position */ | |
224 /* no reason to complain; already complained above */ | |
225 }else{ | |
226 /* we have a packet. Decode it */ | |
227 float **pcm; | |
228 int samples; | |
229 | |
230 if(vorbis_synthesis(&vb,&op)==0) /* test for success! */ | |
231 vorbis_synthesis_blockin(&vd,&vb); | |
232 /* | |
233 | |
234 **pcm is a multichannel float vector. In stereo, for | |
235 example, pcm[0] is left, and pcm[1] is right. samples is | |
236 the size of each channel. Convert the float values | |
237 (-1.<=range<=1.) to whatever PCM format and write it out */ | |
238 | |
239 while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){ | |
240 int j; | |
241 int clipflag=0; | |
242 int bout=(samples<convsize?samples:convsize); | |
243 | |
244 /* convert floats to 16 bit signed ints (host order) and | |
245 interleave */ | |
246 for(i=0;i<vi.channels;i++){ | |
247 ogg_int16_t *ptr=convbuffer+i; | |
248 float *mono=pcm[i]; | |
249 for(j=0;j<bout;j++){ | |
250 #if 1 | |
251 int val=floor(mono[j]*32767.f+.5f); | |
252 #else /* optional dither */ | |
253 int val=mono[j]*32767.f+drand48()-0.5f; | |
254 #endif | |
255 /* might as well guard against clipping */ | |
256 if(val>32767){ | |
257 val=32767; | |
258 clipflag=1; | |
259 } | |
260 if(val<-32768){ | |
261 val=-32768; | |
262 clipflag=1; | |
263 } | |
264 *ptr=val; | |
265 ptr+=vi.channels; | |
266 } | |
267 } | |
268 | |
269 if(clipflag) | |
270 fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence)); | |
271 | |
272 | |
273 fwrite(convbuffer,2*vi.channels,bout,stdout); | |
274 | |
275 vorbis_synthesis_read(&vd,bout); /* tell libvorbis how | |
276 many samples we | |
277 actually consumed */ | |
278 } | |
279 } | |
280 } | |
281 if(ogg_page_eos(&og))eos=1; | |
282 } | |
283 } | |
284 if(!eos){ | |
285 buffer=ogg_sync_buffer(&oy,4096); | |
286 bytes=fread(buffer,1,4096,stdin); | |
287 ogg_sync_wrote(&oy,bytes); | |
288 if(bytes==0)eos=1; | |
289 } | |
290 } | |
291 | |
292 /* ogg_page and ogg_packet structs always point to storage in | |
293 libvorbis. They're never freed or manipulated directly */ | |
294 | |
295 vorbis_block_clear(&vb); | |
296 vorbis_dsp_clear(&vd); | |
297 }else{ | |
298 fprintf(stderr,"Error: Corrupt header during playback initialization.\n"); | |
299 } | |
300 | |
301 /* clean up this logical bitstream; before exit we see if we're | |
302 followed by another [chained] */ | |
303 | |
304 ogg_stream_clear(&os); | |
305 vorbis_comment_clear(&vc); | |
306 vorbis_info_clear(&vi); /* must be called last */ | |
307 } | |
308 | |
309 /* OK, clean up the framer */ | |
310 ogg_sync_clear(&oy); | |
311 | |
312 fprintf(stderr,"Done.\n"); | |
313 return(0); | |
314 } |