001/* JOrbis 002 * Copyright (C) 2000 ymnk, JCraft,Inc. 003 * 004 * Written by: 2000 ymnk<ymnk@jcaft.com> 005 * 006 * Many thanks to 007 * Monty <monty@xiph.org> and 008 * The XIPHOPHORUS Company http://www.xiph.org/ . 009 * JOrbis has been based on their awesome works, Vorbis codec. 010 * 011 * This program is free software; you can redistribute it and/or 012 * modify it under the terms of the GNU Library General Public License 013 * as published by the Free Software Foundation; either version 2 of 014 * the License, or (at your option) any later version. 015 016 * This program is distributed in the hope that it will be useful, 017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 019 * GNU Library General Public License for more details. 020 * 021 * You should have received a copy of the GNU Library General Public 022 * License along with this program; if not, write to the Free Software 023 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 024 */ 025 026package com.jcraft.jorbis; 027 028import com.jcraft.jogg.*; 029 030// Takes a vorbis bitstream from stdin and writes raw stereo PCM to 031// stdout. Decodes simple and chained OggVorbis files from beginning 032// to end. Vorbisfile.a is somewhat more complex than the code below. 033 034class DecodeExample{ 035 static int convsize=4096*2; 036 static byte[] convbuffer=new byte[convsize]; // take 8k out of the data segment, not the stack 037 038 public static void main(String[] arg){ 039 java.io.InputStream input=System.in; 040 if(arg.length>0){ 041 try{ 042 input=new java.io.FileInputStream(arg[0]); 043 } 044 catch(Exception e){ 045 System.err.println(e); 046 } 047 } 048 049 SyncState oy=new SyncState(); // sync and verify incoming physical bitstream 050 StreamState os=new StreamState(); // take physical pages, weld into a logical stream of packets 051 Page og=new Page(); // one Ogg bitstream page. Vorbis packets are inside 052 Packet op=new Packet(); // one raw packet of data for decode 053 054 Info vi=new Info(); // struct that stores all the static vorbis bitstream settings 055 Comment vc=new Comment(); // struct that stores all the bitstream user comments 056 DspState vd=new DspState(); // central working state for the packet->PCM decoder 057 Block vb=new Block(vd); // local working space for packet->PCM decode 058 059 byte[] buffer; 060 int bytes=0; 061 062 // Decode setup 063 064 oy.init(); // Now we can read pages 065 066 while(true){ // we repeat if the bitstream is chained 067 int eos=0; 068 069 // grab some data at the head of the stream. We want the first page 070 // (which is guaranteed to be small and only contain the Vorbis 071 // stream initial header) We need the first page to get the stream 072 // serialno. 073 074 // submit a 4k block to libvorbis' Ogg layer 075 int index=oy.buffer(4096); 076 buffer=oy.data; 077 try{ 078 bytes=input.read(buffer, index, 4096); 079 } 080 catch(Exception e){ 081 System.err.println(e); 082 System.exit(-1); 083 } 084 oy.wrote(bytes); 085 086 // Get the first page. 087 if(oy.pageout(og)!=1){ 088 // have we simply run out of data? If so, we're done. 089 if(bytes<4096)break; 090 091 // error case. Must not be Vorbis data 092 System.err.println("Input does not appear to be an Ogg bitstream."); 093 System.exit(1); 094 } 095 096 // Get the serial number and set up the rest of decode. 097 // serialno first; use it to set up a logical stream 098 os.init(og.serialno()); 099 100 // extract the initial header from the first page and verify that the 101 // Ogg bitstream is in fact Vorbis data 102 103 // I handle the initial header first instead of just having the code 104 // read all three Vorbis headers at once because reading the initial 105 // header is an easy way to identify a Vorbis bitstream and it's 106 // useful to see that functionality seperated out. 107 108 vi.init(); 109 vc.init(); 110 if(os.pagein(og)<0){ 111 // error; stream version mismatch perhaps 112 System.err.println("Error reading first page of Ogg bitstream data."); 113 System.exit(1); 114 } 115 116 if(os.packetout(op)!=1){ 117 // no page? must not be vorbis 118 System.err.println("Error reading initial header packet."); 119 System.exit(1); 120 } 121 122 if(vi.synthesis_headerin(vc,op)<0){ 123 // error case; not a vorbis header 124 System.err.println("This Ogg bitstream does not contain Vorbis audio data."); 125 System.exit(1); 126 } 127 128 // At this point, we're sure we're Vorbis. We've set up the logical 129 // (Ogg) bitstream decoder. Get the comment and codebook headers and 130 // set up the Vorbis decoder 131 132 // The next two packets in order are the comment and codebook headers. 133 // They're likely large and may span multiple pages. Thus we reead 134 // and submit data until we get our two pacakets, watching that no 135 // pages are missing. If a page is missing, error out; losing a 136 // header page is the only place where missing data is fatal. */ 137 138 int i=0; 139 while(i<2){ 140 while(i<2){ 141 142 int result=oy.pageout(og); 143 if(result==0) break; // Need more data 144 // Don't complain about missing or corrupt data yet. We'll 145 // catch it at the packet output phase 146 147 if(result==1){ 148 os.pagein(og); // we can ignore any errors here 149 // as they'll also become apparent 150 // at packetout 151 while(i<2){ 152 result=os.packetout(op); 153 if(result==0)break; 154 if(result==-1){ 155 // Uh oh; data at some point was corrupted or missing! 156 // We can't tolerate that in a header. Die. 157 System.err.println("Corrupt secondary header. Exiting."); 158 System.exit(1); 159 } 160 vi.synthesis_headerin(vc,op); 161 i++; 162 } 163 } 164 } 165 // no harm in not checking before adding more 166 index=oy.buffer(4096); 167 buffer=oy.data; 168 try{ 169 bytes=input.read(buffer, index, 4096); 170 } 171 catch(Exception e){ 172 System.err.println(e); 173 System.exit(1); 174 } 175 if(bytes==0 && i<2){ 176 System.err.println("End of file before finding all Vorbis headers!"); 177 System.exit(1); 178 } 179 oy.wrote(bytes); 180 } 181 182 // Throw the comments plus a few lines about the bitstream we're 183 // decoding 184 { 185 byte[][] ptr=vc.user_comments; 186 for(int j=0; j<ptr.length;j++){ 187 if(ptr[j]==null) break; 188 System.err.println(new String(ptr[j], 0, ptr[j].length-1)); 189 } 190 System.err.println("\nBitstream is "+vi.channels+" channel, "+vi.rate+"Hz"); 191 System.err.println("Encoded by: "+new String(vc.vendor, 0, vc.vendor.length-1)+"\n"); 192 } 193 194 convsize=4096/vi.channels; 195 196 // OK, got and parsed all three headers. Initialize the Vorbis 197 // packet->PCM decoder. 198 vd.synthesis_init(vi); // central decode state 199 vb.init(vd); // local state for most of the decode 200 // so multiple block decodes can 201 // proceed in parallel. We could init 202 // multiple vorbis_block structures 203 // for vd here 204 205 float[][][] _pcm=new float[1][][]; 206 int[] _index=new int[vi.channels]; 207 // The rest is just a straight decode loop until end of stream 208 while(eos==0){ 209 while(eos==0){ 210 211 int result=oy.pageout(og); 212 if(result==0)break; // need more data 213 if(result==-1){ // missing or corrupt data at this page position 214 System.err.println("Corrupt or missing data in bitstream; continuing..."); 215 } 216 else{ 217 os.pagein(og); // can safely ignore errors at 218 // this point 219 while(true){ 220 result=os.packetout(op); 221 222 if(result==0)break; // need more data 223 if(result==-1){ // missing or corrupt data at this page position 224 // no reason to complain; already complained above 225 } 226 else{ 227 // we have a packet. Decode it 228 int samples; 229 if(vb.synthesis(op)==0){ // test for success! 230 vd.synthesis_blockin(vb); 231 } 232 233 // **pcm is a multichannel float vector. In stereo, for 234 // example, pcm[0] is left, and pcm[1] is right. samples is 235 // the size of each channel. Convert the float values 236 // (-1.<=range<=1.) to whatever PCM format and write it out 237 238 while((samples=vd.synthesis_pcmout(_pcm, _index))>0){ 239 float[][] pcm=_pcm[0]; 240 boolean clipflag=false; 241 int bout=(samples<convsize?samples:convsize); 242 243 // convert floats to 16 bit signed ints (host order) and 244 // interleave 245 for(i=0;i<vi.channels;i++){ 246 int ptr=i*2; 247 //int ptr=i; 248 int mono=_index[i]; 249 for(int j=0;j<bout;j++){ 250 int val=(int)(pcm[i][mono+j]*32767.); 251// short val=(short)(pcm[i][mono+j]*32767.); 252// int val=(int)Math.round(pcm[i][mono+j]*32767.); 253 // might as well guard against clipping 254 if(val>32767){ 255 val=32767; 256 clipflag=true; 257 } 258 if(val<-32768){ 259 val=-32768; 260 clipflag=true; 261 } 262 if(val<0) val=val|0x8000; 263 convbuffer[ptr]=(byte)(val); 264 convbuffer[ptr+1]=(byte)(val>>>8); 265 ptr+=2*(vi.channels); 266 } 267 } 268 269 //if(clipflag) 270 // System.err.println("Clipping in frame "+vd.sequence); 271 272 System.out.write(convbuffer, 0, 2*vi.channels*bout); 273 274 vd.synthesis_read(bout); // tell libvorbis how 275 // many samples we 276 // actually consumed 277 } 278 } 279 } 280 if(og.eos()!=0)eos=1; 281 } 282 } 283 if(eos==0){ 284 index=oy.buffer(4096); 285 buffer=oy.data; 286 try{ 287 bytes=input.read(buffer,index,4096); 288 } 289 catch(Exception e){ 290 System.err.println(e); 291 System.exit(1); 292 } 293 oy.wrote(bytes); 294 if(bytes==0)eos=1; 295 } 296 } 297 298 // clean up this logical bitstream; before exit we see if we're 299 // followed by another [chained] 300 301 os.clear(); 302 303 // ogg_page and ogg_packet structs always point to storage in 304 // libvorbis. They're never freed or manipulated directly 305 306 vb.clear(); 307 vd.clear(); 308 vi.clear(); // must be called last 309 } 310 311 // OK, clean up the framer 312 oy.clear(); 313 System.err.println("Done."); 314 } 315} 316