override public Object unpack(Info vi , csBuffer opb) { InfoFloor0 info=new InfoFloor0(); info.order=opb.read(8); info.rate=opb.read(16); info.barkmap=opb.read(16); info.ampbits=opb.read(6); info.ampdB=opb.read(8); info.numbooks=opb.read(4)+1; if((info.order<1)|| (info.rate<1)|| (info.barkmap<1)|| (info.numbooks<1)) { //free_info(info); return(null); } for(int j=0;j<info.numbooks;j++) { info.books[j]=opb.read(8); if(info.books[j]<0 || info.books[j]>=vi.books) { //free_info(info); return(null); } } return(info); // err_out: // free_info(info); // return(NULL); }
override public void pack(Info vi, Object imap, csBuffer opb) { InfoMapping0 info=(InfoMapping0)imap; /* another 'we meant to do it this way' hack... up to beta 4, we packed 4 binary zeros here to signify one submapping in use. We now redefine that to mean four bitflags that indicate use of deeper features; bit0:submappings, bit1:coupling, bit2,3:reserved. This is backward compatable with all actual uses of the beta code. */ if(info.submaps>1) { opb.write(1,1); opb.write(info.submaps-1,4); } else { opb.write(0,1); } if(info.coupling_steps>0) { opb.write(1,1); opb.write(info.coupling_steps-1,8); for(int i=0;i<info.coupling_steps;i++) { opb.write(info.coupling_mag[i],ilog2(vi.channels)); opb.write(info.coupling_ang[i],ilog2(vi.channels)); } } else { opb.write(0,1); } opb.write(0,2); /* 2,3:reserved */ /* we don't write the channel submappings if we only have one... */ if(info.submaps>1) { for(int i=0;i<vi.channels;i++) opb.write(info.chmuxlist[i],4); } for(int i=0;i<info.submaps;i++) { opb.write(info.timesubmap[i],8); opb.write(info.floorsubmap[i],8); opb.write(info.residuesubmap[i],8); } }
override public Object unpack(Info vi, csBuffer opb) { int acc=0; InfoResidue0 info=new InfoResidue0(); info.begin=opb.read(24); info.end=opb.read(24); info.grouping=opb.read(24)+1; info.partitions=opb.read(6)+1; info.groupbook=opb.read(8); for(int j=0;j<info.partitions;j++) { int cascade=opb.read(3); if(opb.read(1)!=0) { cascade|=(opb.read(5)<<3); } info.secondstages[j]=cascade; acc+=icount(cascade); } for(int j=0;j<acc;j++) { info.booklist[j]=opb.read(8); // if(info.booklist[j]==255)info.booklist[j]=-1; } if(info.groupbook>=vi.books) { free_info(info); return(null); } for(int j=0;j<acc;j++) { if(info.booklist[j]>=vi.books) { free_info(info); return(null); } } return(info); // errout: // free_info(info); // return(NULL); }
public abstract Object unpack(Info info , csBuffer buffer);
override public Object unpack(Info vi , csBuffer opb) { int count=0,maxclass=-1,rangebits; InfoFloor1 info=new InfoFloor1(); /* read partitions */ info.partitions=opb.read(5); /* only 0 to 31 legal */ for(int j=0;j<info.partitions;j++) { info.partitionclass[j]=opb.read(4); /* only 0 to 15 legal */ if(maxclass<info.partitionclass[j]) maxclass=info.partitionclass[j]; } /* read partition classes */ for(int j=0;j<maxclass+1;j++) { info.class_dim[j]=opb.read(3)+1; /* 1 to 8 */ info.class_subs[j]=opb.read(2); /* 0,1,2,3 bits */ if(info.class_subs[j]<0) { //goto err_out; info.free(); return(null); } if(info.class_subs[j]!=0) { info.class_book[j]=opb.read(8); } if(info.class_book[j]<0 || info.class_book[j]>=vi.books) { //goto err_out; info.free(); return(null); } for(int k=0;k<(1<<info.class_subs[j]);k++) { info.class_subbook[j][k]=opb.read(8)-1; if(info.class_subbook[j][k]<-1 || info.class_subbook[j][k]>=vi.books) { //goto err_out; info.free(); return(null); } } } /* read the post list */ info.mult=opb.read(2)+1; /* only 1,2,3,4 legal now */ rangebits=opb.read(4); for(int j=0,k=0;j<info.partitions;j++) { count+=info.class_dim[info.partitionclass[j]]; for(;k<count;k++) { int t=info.postlist[k+2]=opb.read(rangebits); if(t<0 || t>=(1<<rangebits)) { //goto err_out; info.free(); return(null); } } } info.postlist[0]=0; info.postlist[1]=1<<rangebits; return(info); // err_out: // info.free(); // return(null); }
public abstract void pack(Info info , Object imap, csBuffer buffer);
public abstract void pack(Info info, Object imap, csBuffer buffer);
/// <summary> /// Decodes a stream of Ogg Vorbis data into wav file format. /// </summary> /// <returns> /// A MemoryStream with the entire decoded stream. /// </returns> /// <param name='input'> /// Ogg Vorbis data to be decoded /// </param> /// <param name='output'> /// <para>Stream to write wav data.</para> /// <para>If writeWavHeader is true then this stream must be seekable.</para> /// </param> /// <param name='writeWavHeader'> /// Write wav header in the beginning of the returned stream. /// </param> public static void DecodeStream(Stream input, Stream output, bool writeWavHeader) { int convsize = 4096 * 2; byte[] convbuffer = new byte[convsize]; // take 8k out of the data segment, not the stack long start = output.Position; DebugWriter s_err = new DebugWriter(); if (writeWavHeader && !output.CanSeek) throw new ArgumentException("To write wav header, the output stream must be seekable.", "output"); if (writeWavHeader) output.Seek(HEADER_SIZE, SeekOrigin.Current); // reserve place for WAV header SyncState oy = new SyncState(); // sync and verify incoming physical bitstream StreamState os = new StreamState(); // take physical pages, weld into a logical stream of packets Page og = new Page(); // one Ogg bitstream page. Vorbis packets are inside Packet op = new Packet(); // one raw packet of data for decode Info vi = new Info(); // struct that stores all the static vorbis bitstream settings Comment vc = new Comment(); // struct that stores all the bitstream user comments DspState vd = new DspState(); // central working state for the packet->PCM decoder Block vb = new Block(vd); // local working space for packet->PCM decode int bytes = 0; // Decode setup oy.init(); // Now we can read pages // we repeat if the bitstream is chained while (true) { int eos = 0; // grab some data at the head of the stream. We want the first page // (which is guaranteed to be small and only contain the Vorbis // stream initial header) We need the first page to get the stream // serialno. // submit a 4k block to libvorbis' Ogg layer int index = oy.buffer(4096); bytes = input.Read(oy.data, index, 4096); oy.wrote(bytes); // Get the first page. if (oy.pageout(og) != 1) { // have we simply run out of data? If so, we're done. if (bytes < 4096) break; // error case. Must not be Vorbis data s_err.WriteLine("Input does not appear to be an Ogg bitstream."); } // Get the serial number and set up the rest of decode. // serialno first; use it to set up a logical stream os.init(og.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data // I handle the initial header first instead of just having the code // read all three Vorbis headers at once because reading the initial // header is an easy way to identify a Vorbis bitstream and it's // useful to see that functionality seperated out. vi.init(); vc.init(); if (os.pagein(og) < 0) { // error; stream version mismatch perhaps s_err.WriteLine("Error reading first page of Ogg bitstream data."); } if (os.packetout(op) != 1) { // no page? must not be vorbis s_err.WriteLine("Error reading initial header packet."); } if (vi.synthesis_headerin(vc, op) < 0) { // error case; not a vorbis header s_err.WriteLine("This Ogg bitstream does not contain Vorbis audio data."); } // At this point, we're sure we're Vorbis. We've set up the logical // (Ogg) bitstream decoder. Get the comment and codebook headers and // set up the Vorbis decoder // The next two packets in order are the comment and codebook headers. // They're likely large and may span multiple pages. Thus we reead // and submit data until we get our two pacakets, watching that no // pages are missing. If a page is missing, error out; losing a // header page is the only place where missing data is fatal. */ int i = 0; while (i < 2) { while (i < 2) { int result = oy.pageout(og); if (result == 0) break; // Need more data // Don't complain about missing or corrupt data yet. We'll // catch it at the packet output phase if (result == 1) { os.pagein(og); // we can ignore any errors here // as they'll also become apparent // at packetout while (i < 2) { result = os.packetout(op); if (result == 0) break; if (result == -1) { // Uh oh; data at some point was corrupted or missing! // We can't tolerate that in a header. Die. s_err.WriteLine("Corrupt secondary header. Exiting."); } vi.synthesis_headerin(vc, op); i++; } } } // no harm in not checking before adding more index = oy.buffer(4096); bytes = input.Read(oy.data, index, 4096); if (bytes == 0 && i < 2) { s_err.WriteLine("End of file before finding all Vorbis headers!"); } oy.wrote(bytes); } // Throw the comments plus a few lines about the bitstream we're // decoding { byte[][] ptr = vc.user_comments; for (int j = 0; j < vc.user_comments.Length; j++) { if (ptr [j] == null) break; s_err.WriteLine(vc.getComment(j)); } s_err.WriteLine("\nBitstream is " + vi.channels + " channel, " + vi.rate + "Hz"); s_err.WriteLine("Encoded by: " + vc.getVendor() + "\n"); } convsize = 4096 / vi.channels; // OK, got and parsed all three headers. Initialize the Vorbis // packet->PCM decoder. vd.synthesis_init(vi); // central decode state vb.init(vd); // local state for most of the decode // so multiple block decodes can // proceed in parallel. We could init // multiple vorbis_block structures // for vd here float[][][] _pcm = new float[1][][]; int[] _index = new int[vi.channels]; // The rest is just a straight decode loop until end of stream while (eos == 0) { while (eos == 0) { int result = oy.pageout(og); if (result == 0) break; // need more data if (result == -1) { // missing or corrupt data at this page position s_err.WriteLine("Corrupt or missing data in bitstream; continuing..."); } else { os.pagein(og); // can safely ignore errors at // this point while (true) { result = os.packetout(op); if (result == 0) break; // need more data if (result == -1) { // missing or corrupt data at this page position // no reason to complain; already complained above } else { // we have a packet. Decode it int samples; if (vb.synthesis(op) == 0) { // test for success! vd.synthesis_blockin(vb); } // **pcm is a multichannel float vector. In stereo, for // example, pcm[0] is left, and pcm[1] is right. samples is // the size of each channel. Convert the float values // (-1.<=range<=1.) to whatever PCM format and write it out while ((samples = vd.synthesis_pcmout(_pcm, _index)) > 0) { float[][] pcm = _pcm [0]; bool clipflag = false; int bout = (samples < convsize ? samples : convsize); // convert floats to 16 bit signed ints (host order) and // interleave for (i = 0; i < vi.channels; i++) { int ptr = i * 2; //int ptr=i; int mono = _index [i]; for (int j = 0; j < bout; j++) { int val = (int)(pcm [i] [mono + j] * 32767.0); // short val=(short)(pcm[i][mono+j]*32767.); // int val=(int)Math.round(pcm[i][mono+j]*32767.); // might as well guard against clipping if (val > 32767) { val = 32767; clipflag = true; } if (val < -32768) { val = -32768; clipflag = true; } if (val < 0) val = val | 0x8000; convbuffer [ptr] = (byte)(val); convbuffer [ptr + 1] = (byte)((uint)val >> 8); ptr += 2 * (vi.channels); } } if (clipflag) { //s_err.WriteLine("Clipping in frame "+vd.sequence); } output.Write(convbuffer, 0, 2 * vi.channels * bout); vd.synthesis_read(bout); // tell libvorbis how // many samples we // actually consumed } } } if (og.eos() != 0) eos = 1; } } if (eos == 0) { index = oy.buffer(4096); bytes = input.Read(oy.data, index, 4096); oy.wrote(bytes); if (bytes == 0) eos = 1; } } // clean up this logical bitstream; before exit we see if we're // followed by another [chained] os.clear(); // ogg_page and ogg_packet structs always point to storage in // libvorbis. They're never freed or manipulated directly vb.clear(); vd.clear(); vi.clear(); // must be called last } // OK, clean up the framer oy.clear(); s_err.WriteLine("Done."); if (writeWavHeader) { long end = output.Position; int length = (int)(end - (start + HEADER_SIZE)); output.Seek(start, SeekOrigin.Begin); WriteHeader(output, length, vi.rate, (ushort)16, (ushort)vi.channels); output.Seek(end, SeekOrigin.Begin); } }
/// <summary> /// Constructor for SoundType class /// </summary> /// <param name="FileName">String of the filepath</param> /// <param name="IsToBeStreaming">Is it to be streamed?</param> public SoundType(string FileName, bool IsToBeStreaming) { if (!System.IO.File.Exists(FileName)) { throw new Exception("Missing sound file!"); } File = FileName; Streaming = IsToBeStreaming; if (!Streaming) { BufferID = AL.GenBuffer(); } else { BufferID = -1; } // This makes the program take some time to load... FileToBuffer = new VorbisFile(File); FileInfoVO = FileToBuffer.getInfo(-1); alf = 0; /*int asd = FileToBuffer.bitrate(-1); int asd2 = FileToBuffer.bitrate_instant();*/ if (FileInfoVO.channels == 1) // mono { alf = ALFormat.Mono16; } else if (FileInfoVO.channels == 2) // sterio { alf = ALFormat.Stereo16; } else if (alf == 0) { throw new Exception("Wrong number of channels in sound file."); } }
// last step of the OggVorbis_File initialization; get all the // vorbis_info structs and PCM positions. Only called by the seekable // initialization (local stream storage is hacked slightly; pay // attention to how that's done) public void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset, VorbisFileInstance instance) { Page og=new Page(); int ret; vi=new Info[links]; vc=new Comment[links]; dataoffsets=new long[links]; pcmlengths=new long[links]; serialnos=new int[links]; for(int i=0;i<links;i++) { if(first_i!=null && first_c!=null && i==0) { // we already grabbed the initial header earlier. This just // saves the waste of grabbing it again // !!!!!!!!!!!!! vi[i]=first_i; //memcpy(vf->vi+i,first_i,sizeof(vorbis_info)); vc[i]=first_c; //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); dataoffsets[i]=dataoffset; } else { // seek to the location of the initial header seek_helper(offsets[i], instance); //!!! if (fetch_headers(vi[i], vc[i], null, null, instance) == -1) { Console.Error.WriteLine("Error opening logical bitstream #"+(i+1)+"\n"); dataoffsets[i]=-1; } else { dataoffsets[i]=offset; instance.os.clear(); } } // get the serial number and PCM length of this link. To do this, // get the last page of the stream long end=offsets[i+1]; //!!! seek_helper(end, instance); while(true) { ret=get_prev_page(og, instance); if(ret==-1) { // this should not be possible Console.Error.WriteLine("Could not find last page of logical "+ "bitstream #"+(i)+"\n"); vi[i].clear(); vc[i].clear(); break; } if(og.granulepos()!=-1) { serialnos[i]=og.serialno(); pcmlengths[i]=og.granulepos(); break; } } } }
public int synthesis_init(Info vi) { init(vi, false); // Adjust centerW to allow an easier mechanism for determining output pcm_returned=centerW; centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4; granulepos=-1; sequence=-1; return(0); }
public override Object unpack(Info vi , csBuffer opb) { return ""; }
Stream DecodeStream( Stream input, bool skipWavHeader ) { int convsize = 4096 * 2; byte [] convbuffer = new byte [ convsize ]; Stream output = new MemoryStream (); if ( !skipWavHeader ) output.Seek ( HEADER_SIZE, SeekOrigin.Begin ); SyncState oy = new SyncState (); StreamState os = new StreamState (); Page og = new Page (); Packet op = new Packet (); Info vi = new Info (); Comment vc = new Comment (); DspState vd = new DspState (); Block vb = new Block ( vd ); byte [] buffer; int bytes = 0; oy.init (); while ( true ) { int eos = 0; int index = oy.buffer ( 4096 ); buffer = oy.data; bytes = input.Read ( buffer, index, 4096 ); oy.wrote ( bytes ); if ( oy.pageout ( og ) != 1 ) { if ( bytes < 4096 ) break; throw new Exception ( "Input does not appear to be an Ogg bitstream." ); } os.init ( og.serialno () ); vi.init (); vc.init (); if ( os.pagein ( og ) < 0 ) { throw new Exception ( "Error reading first page of Ogg bitstream data." ); } if ( os.packetout ( op ) != 1 ) { throw new Exception ( "Error reading initial header packet." ); } if ( vi.synthesis_headerin ( vc, op ) < 0 ) { throw new Exception ( "This Ogg bitstream does not contain Vorbis audio data." ); } int i = 0; while ( i < 2 ) { while ( i < 2 ) { int result = oy.pageout ( og ); if ( result == 0 ) break; if ( result == 1 ) { os.pagein ( og ); while ( i < 2 ) { result = os.packetout ( op ); if ( result == 0 ) break; if ( result == -1 ) { throw new Exception ( "Corrupt secondary header. Exiting." ); } vi.synthesis_headerin ( vc, op ); i++; } } } index = oy.buffer ( 4096 ); buffer = oy.data; bytes = input.Read ( buffer, index, 4096 ); if ( bytes == 0 && i < 2 ) { throw new Exception ( "End of file before finding all Vorbis headers!" ); } oy.wrote ( bytes ); } { byte [] [] ptr = vc.user_comments; for ( int j = 0; j < vc.user_comments.Length; j++ ) { if ( ptr [ j ] == null ) break; } } convsize = 4096 / vi.channels; vd.synthesis_init ( vi ); vb.init ( vd ); float [] [] [] _pcm = new float [ 1 ] [][]; int [] _index = new int [ vi.channels ]; while ( eos == 0 ) { while ( eos == 0 ) { int result = oy.pageout ( og ); if ( result == 0 ) break; if ( result == -1 ) throw new Exception ( "Corrupt or missing data in bitstream; continuing..." ); else { os.pagein ( og ); while ( true ) { result = os.packetout ( op ); if ( result == 0 ) break; if ( result == -1 ) { } else { int samples; if ( vb.synthesis ( op ) == 0 ) { vd.synthesis_blockin ( vb ); } while ( ( samples = vd.synthesis_pcmout ( _pcm, _index ) ) > 0 ) { float [] [] pcm = _pcm [ 0 ]; bool clipflag = false; int bout = ( samples < convsize ? samples : convsize ); for ( i = 0; i < vi.channels; i++ ) { int ptr = i * 2; int mono = _index [ i ]; for ( int j = 0; j < bout; j++ ) { int val = ( int ) ( pcm [ i ] [ mono + j ] * 32767.0 ); if ( val > 32767 ) { val = 32767; clipflag = true; } if ( val < -32768 ) { val = -32768; clipflag = true; } if ( val < 0 ) val = val | 0x8000; convbuffer [ ptr ] = ( byte ) ( val ); convbuffer [ ptr + 1 ] = ( byte ) ( ( uint ) val >> 8 ); ptr += 2 * ( vi.channels ); } } if ( clipflag ) { } output.Write ( convbuffer, 0, 2 * vi.channels * bout ); vd.synthesis_read ( bout ); } } } if ( og.eos () != 0 ) eos = 1; } } if ( eos == 0 ) { index = oy.buffer ( 4096 ); buffer = oy.data; bytes = input.Read ( buffer, index, 4096 ); oy.wrote ( bytes ); if ( bytes == 0 ) eos = 1; } } os.clear (); vb.clear (); vd.clear (); vi.clear (); } oy.clear (); output.Seek ( 0, SeekOrigin.Begin ); if ( !skipWavHeader ) { WriteHeader ( output, ( int ) ( output.Length - HEADER_SIZE ), vi.rate, ( ushort ) 16, ( ushort ) vi.channels ); output.Seek ( 0, SeekOrigin.Begin ); } return output; }
public abstract Object unpack(Info info, csBuffer buffer);
override public Object unpack(Info vi, csBuffer opb) { int count = 0, maxclass = -1, rangebits; InfoFloor1 info = new InfoFloor1(); /* read partitions */ info.partitions = opb.read(5); /* only 0 to 31 legal */ for (int j = 0; j < info.partitions; j++) { info.partitionclass[j] = opb.read(4); /* only 0 to 15 legal */ if (maxclass < info.partitionclass[j]) { maxclass = info.partitionclass[j]; } } /* read partition classes */ for (int j = 0; j < maxclass + 1; j++) { info.class_dim[j] = opb.read(3) + 1; /* 1 to 8 */ info.class_subs[j] = opb.read(2); /* 0,1,2,3 bits */ if (info.class_subs[j] < 0) { //goto err_out; info.free(); return(null); } if (info.class_subs[j] != 0) { info.class_book[j] = opb.read(8); } if (info.class_book[j] < 0 || info.class_book[j] >= vi.books) { //goto err_out; info.free(); return(null); } for (int k = 0; k < (1 << info.class_subs[j]); k++) { info.class_subbook[j][k] = opb.read(8) - 1; if (info.class_subbook[j][k] < -1 || info.class_subbook[j][k] >= vi.books) { //goto err_out; info.free(); return(null); } } } /* read the post list */ info.mult = opb.read(2) + 1; /* only 1,2,3,4 legal now */ rangebits = opb.read(4); for (int j = 0, k = 0; j < info.partitions; j++) { count += info.class_dim[info.partitionclass[j]]; for (; k < count; k++) { int t = info.postlist[k + 2] = opb.read(rangebits); if (t < 0 || t >= (1 << rangebits)) { //goto err_out; info.free(); return(null); } } } info.postlist[0] = 0; info.postlist[1] = 1 << rangebits; return(info); // err_out: // info.free(); // return(null); }
public override Object unpack(Info vi, csBuffer opb) { return(""); }
/// <summary> /// Dispose method /// </summary> /// <param name="disposing">Is it disposing?</param> protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { // free managed resources if (BufferID >= 0) //??? { AL.DeleteBuffer(BufferID); } FileToBuffer = null; FileInfoVO.clear(); FileInfoVO = null; } // free native resources if there are any. disposed = true; System.Diagnostics.Debug.WriteLine(this.GetType().ToString() + " disposed."); } }
int open_nonseekable() { //System.err.println("open_nonseekable"); // we cannot seek. Set up a 'single' (current) logical bitstream entry links=1; vi=new Info[links]; vi[0]=new Info(); // ?? vc=new Comment[links]; vc[0]=new Comment(); // ?? bug? // Try to fetch the headers, maintaining all the storage int[]foo=new int[1]; if(fetch_headers(vi[0], vc[0], foo, null)==-1)return(-1); current_serialno=foo[0]; make_decode_ready(); return 0; }
public override Object unpack(Info vi, csBuffer opb) { // also responsible for range checking InfoMapping0 info=new InfoMapping0(); // !!!! if(opb.read(1)!=0) { info.submaps=opb.read(4)+1; } else { info.submaps=1; } if(opb.read(1)!=0) { info.coupling_steps=opb.read(8)+1; for(int i=0;i<info.coupling_steps;i++) { int testM=info.coupling_mag[i]=opb.read(ilog2(vi.channels)); int testA=info.coupling_ang[i]=opb.read(ilog2(vi.channels)); if(testM<0 || testA<0 || testM==testA || testM>=vi.channels || testA>=vi.channels) { //goto err_out; info.free(); return(null); } } } if(opb.read(2)>0) { /* 2,3:reserved */ //goto err_out; info.free(); return(null); } if(info.submaps>1) { for(int i=0;i<vi.channels;i++) { info.chmuxlist[i]=opb.read(4); if(info.chmuxlist[i]>=info.submaps) { //goto err_out; info.free(); return(null); } } } for(int i=0;i<info.submaps;i++) { info.timesubmap[i]=opb.read(8); if(info.timesubmap[i]>=vi.times) { //goto err_out; info.free(); return(null); } info.floorsubmap[i]=opb.read(8); if(info.floorsubmap[i]>=vi.floors) { //goto err_out; info.free(); return(null); } info.residuesubmap[i]=opb.read(8); if(info.residuesubmap[i]>=vi.residues) { //goto err_out; info.free(); return(null); } } return info; //err_out: //free_info(info); //return(NULL); }
DspState(Info vi) : this() { init(vi, false); // Adjust centerW to allow an easier mechanism for determining output pcm_returned=centerW; centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4; granulepos=-1; sequence=-1; }
public int synthesis(Packet op) { Info vi = vd.vi; // first things first. Make sure decode is ready // ripcord(); opb.readinit(op.packet_base, op.packet, op.bytes); // Check the packet type if (opb.read(1) != 0) { // Oops. This is not an audio data packet return(-1); } // read our mode and pre/post windowsize int _mode = opb.read(vd.modebits); if (_mode == -1) { return(-1); } mode = _mode; W = vi.mode_param[mode].blockflag; if (W != 0) { lW = opb.read(1); nW = opb.read(1); if (nW == -1) { return(-1); } } else { lW = 0; nW = 0; } // more setup granulepos = op.granulepos; sequence = op.packetno - 3; // first block is third packet eofflag = op.e_o_s; // alloc pcm passback storage pcmend = vi.blocksizes[W]; //pcm=alloc(vi.channels); if (pcm.Length < vi.channels) { pcm = new float[vi.channels][]; } for (int i = 0; i < vi.channels; i++) { if (pcm[i] == null || pcm[i].Length < pcmend) { pcm[i] = new float[pcmend]; //pcm[i]=alloc(pcmend); } else { for (int j = 0; j < pcmend; j++) { pcm[i][j] = 0; } } } // unpack_header enforces range checking int type = vi.map_type[vi.mode_param[mode].mapping]; return(FuncMapping.mapping_P[type].inverse(this, vd.mode[mode])); }
// Analysis side code, but directly related to blocking. Thus it's // here and not in analysis.c (which is for analysis transforms only). // The init is here because some of it is shared int init(Info vi, bool encp) { //memset(v,0,sizeof(vorbis_dsp_state)); this.vi=vi; modebits=ilog2(vi.modes); transform[0]=new Object[VI_TRANSFORMB]; transform[1]=new Object[VI_TRANSFORMB]; // MDCT is tranform 0 transform[0][0]=new Mdct(); transform[1][0]=new Mdct(); ((Mdct)transform[0][0]).init(vi.blocksizes[0]); ((Mdct)transform[1][0]).init(vi.blocksizes[1]); wnd[0][0][0]=new float[VI_WINDOWB][]; wnd[0][0][1]=wnd[0][0][0]; wnd[0][1][0]=wnd[0][0][0]; wnd[0][1][1]=wnd[0][0][0]; wnd[1][0][0]=new float[VI_WINDOWB][]; wnd[1][0][1]=new float[VI_WINDOWB][]; wnd[1][1][0]=new float[VI_WINDOWB][]; wnd[1][1][1]=new float[VI_WINDOWB][]; for(int i=0;i<VI_WINDOWB;i++) { wnd[0][0][0][i]= window(i,vi.blocksizes[0],vi.blocksizes[0]/2,vi.blocksizes[0]/2); wnd[1][0][0][i]= window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[0]/2); wnd[1][0][1][i]= window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[1]/2); wnd[1][1][0][i]= window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[0]/2); wnd[1][1][1][i]= window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[1]/2); } // if(encp){ // encode/decode differ here // // finish the codebooks // fullbooks=new CodeBook[vi.books]; // for(int i=0;i<vi.books;i++){ // fullbooks[i]=new CodeBook(); // fullbooks[i].init_encode(vi.book_param[i]); // } // analysisp=1; // } // else{ // finish the codebooks fullbooks=new CodeBook[vi.books]; for(int i=0;i<vi.books;i++) { fullbooks[i]=new CodeBook(); fullbooks[i].init_decode(vi.book_param[i]); } // } // initialize the storage vectors to a decent size greater than the // minimum pcm_storage=8192; // we'll assume later that we have // a minimum of twice the blocksize of // accumulated samples in analysis pcm=new float[vi.channels][]; //pcmret=new float[vi.channels][]; { for(int i=0;i<vi.channels;i++) { pcm[i]=new float[pcm_storage]; } } // all 1 (large block) or 0 (small block) // explicitly set for the sake of clarity lW=0; // previous window size W=0; // current window size // all vector indexes; multiples of samples_per_envelope_step centerW=vi.blocksizes[1]/2; pcm_current=centerW; // initialize all the mapping/backend lookups mode=new Object[vi.modes]; for(int i=0;i<vi.modes;i++) { int mapnum=vi.mode_param[i].mapping; int maptype=vi.map_type[mapnum]; mode[i]=FuncMapping.mapping_P[maptype].look(this,vi.mode_param[i], vi.map_param[mapnum]); } return(0); }
// uses the local ogg_stream storage in vf; this is important for // non-streaming input sources int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr) { //System.err.println("fetch_headers"); Page og=new Page(); Packet op=new Packet(); int ret; if(og_ptr==null) { ret=get_next_page(og, CHUNKSIZE); if(ret==OV_EREAD)return OV_EREAD; if(ret<0) return OV_ENOTVORBIS; og_ptr=og; } if(serialno!=null)serialno[0]=og_ptr.serialno(); os.init(og_ptr.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data vi.init(); vc.init(); int i=0; while(i<3) { os.pagein(og_ptr); while(i<3) { int result=os.packetout(op); if(result==0)break; if(result==-1) { Console.Error.WriteLine("Corrupt header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } if(vi.synthesis_headerin(vc, op)!=0) { Console.Error.WriteLine("Illegal header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } i++; } if(i<3) if(get_next_page(og_ptr, 1)<0) { Console.Error.WriteLine("Missing header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); os.clear(); return -1; } } return 0; }
public abstract Object unpack(Info vi , csBuffer opb);
// last step of the OggVorbis_File initialization; get all the // vorbis_info structs and PCM positions. Only called by the seekable // initialization (local stream storage is hacked slightly; pay // attention to how that's done) void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset) { Page og=new Page(); int ret; vi=new Info[links]; vc=new Comment[links]; dataoffsets=new long[links]; pcmlengths=new long[links]; serialnos=new int[links]; for(int i=0;i<links;i++) { if(first_i!=null && first_c!=null && i==0) { // we already grabbed the initial header earlier. This just // saves the waste of grabbing it again // !!!!!!!!!!!!! vi[i]=first_i; //memcpy(vf->vi+i,first_i,sizeof(vorbis_info)); vc[i]=first_c; //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); dataoffsets[i]=dataoffset; } else { // seek to the location of the initial header seek_helper(offsets[i]); //!!! if(fetch_headers(vi[i], vc[i], null, null)==-1) { Console.Error.WriteLine("Error opening logical bitstream #"+(i+1)+"\n"); dataoffsets[i]=-1; } else { dataoffsets[i]=offset; os.clear(); } } // get the serial number and PCM length of this link. To do this, // get the last page of the stream long end=offsets[i+1]; //!!! seek_helper(end); while(true) { ret=get_prev_page(og); if(ret==-1) { // this should not be possible Console.Error.WriteLine("Could not find last page of logical "+ "bitstream #"+(i)+"\n"); vi[i].clear(); vc[i].clear(); break; } if(og.granulepos()!=-1) { serialnos[i]=og.serialno(); pcmlengths[i]=og.granulepos(); break; } } } }
// uses the local ogg_stream storage in vf; this is important for // non-streaming input sources public int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr, VorbisFileInstance instance) { //System.err.println("fetch_headers"); Page og=new Page(); Packet op=new Packet(); int ret; if(og_ptr==null) { ret = get_next_page(og, CHUNKSIZE, instance); if(ret==OV_EREAD)return OV_EREAD; if(ret<0) return OV_ENOTVORBIS; og_ptr=og; } if(serialno!=null)serialno[0]=og_ptr.serialno(); instance.os.init(og_ptr.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data vi.init(); vc.init(); int i=0; while(i<3) { instance.os.pagein(og_ptr); while(i<3) { int result = instance.os.packetout(op); if(result==0)break; if(result==-1) { Console.Error.WriteLine("Corrupt header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); instance.os.clear(); return -1; } if(vi.synthesis_headerin(vc, op)!=0) { Console.Error.WriteLine("Illegal header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); instance.os.clear(); return -1; } i++; } if(i<3) if(get_next_page(og_ptr, 1, instance)<0) { Console.Error.WriteLine("Missing header in logical bitstream."); //goto bail_header; vi.clear(); vc.clear(); instance.os.clear(); return -1; } } return 0; }
public AudioSample OggToWav(Stream ogg, float volume, float pitch) { AudioSample sample = new AudioSample(); TextWriter s_err = new StringWriter(); Stream input = null; MemoryStream output = null; input = ogg; output = new MemoryStream(); SyncState oy = new SyncState(); StreamState os = new StreamState(); Page og = new Page(); Packet op = new Packet(); Info vi = new Info(); Comment vc = new Comment(); DspState vd = new DspState(); Block vb = new Block(vd); byte[] buffer; int bytes = 0; oy.init(); while (true) { int eos = 0; int index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); if (oy.pageout(og) != 1) { if (bytes < 4096) break; s_err.WriteLine("Input does not appear to be an Ogg bitstream."); } os.init(og.serialno()); vi.init(); vc.init(); if (os.pagein(og) < 0) { s_err.WriteLine("Error reading first page of Ogg bitstream data."); } if (os.packetout(op) != 1) { s_err.WriteLine("Error reading initial header packet."); } if (vi.synthesis_headerin(vc, op) < 0) { s_err.WriteLine("This Ogg bitstream does not contain Vorbis audio data."); } int i = 0; while (i < 2) { while (i < 2) { int result = oy.pageout(og); if (result == 0) break; if (result == 1) { os.pagein(og); while (i < 2) { result = os.packetout(op); if (result == 0) break; vi.synthesis_headerin(vc, op); i++; } } } index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); } sample.Channels = vi.channels; sample.Rate = (int)((float)vi.rate * pitch); convsize = 4096 / vi.channels; vd.synthesis_init(vi); vb.init(vd); float[][][] _pcm = new float[1][][]; int[] _index = new int[vi.channels]; while (eos == 0) { while (eos == 0) { int result = oy.pageout(og); if (result == 0) break; if (result != -1) { os.pagein(og); while (true) { result = os.packetout(op); if (result == 0) break; if (result != -1) { int samples; if (vb.synthesis(op) == 0) { vd.synthesis_blockin(vb); } while ((samples = vd.synthesis_pcmout(_pcm, _index)) > 0) { float[][] pcm = _pcm[0]; int bout = (samples < convsize ? samples : convsize); for (i = 0; i < vi.channels; i++) { int ptr = i * 2; int mono = _index[i]; for (int j = 0; j < bout; j++) { int val = (int)(pcm[i][mono + j] * 32767.0); if (val > 32767) { val = 32767; } if (val < -32768) { val = -32768; } val = (int)((float)val * volume); if (val < 0) val = val | 0x8000; convbuffer[ptr] = (byte)(val); convbuffer[ptr + 1] = (byte)((uint)val >> 8); ptr += 2 * (vi.channels); } } output.Write(convbuffer, 0, 2 * vi.channels * bout); vd.synthesis_read(bout); } } } if (og.eos() != 0) eos = 1; } } if (eos == 0) { index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); if (bytes == 0) eos = 1; } } os.clear(); vb.clear(); vd.clear(); vi.clear(); break; } oy.clear(); input.Close(); sample.Pcm = output.ToArray(); return sample; }
int open_seekable() { VorbisFileInstance instance = makeInstance(); Info initial_i=new Info(); Comment initial_c=new Comment(); int serialno; long end; int ret; int dataoffset; Page og=new Page(); // is this even vorbis...? int[] foo=new int[1]; ret = fetch_headers(initial_i, initial_c, foo, null, instance); serialno=foo[0]; dataoffset=(int)offset; //!! instance.os.clear(); if(ret==-1)return(-1); // we can seek, so set out learning all about this file skable=true; //(callbacks.seek_func)(datasource, 0, SEEK_END); fseek(datasource, 0, SEEK_END); //offset=end=(callbacks.tell_func)(datasource); offset=ftell(datasource); end=offset; // We get the offset for the last page of the physical bitstream. // Most OggVorbis files will contain a single logical bitstream end=get_prev_page(og, instance); // moer than one logical bitstream? if(og.serialno()!=serialno) { // Chained bitstream. Bisect-search each logical bitstream // section. Do so based on serial number only if(bisect_forward_serialno(0,0,end+1,serialno,0, instance)<0) { clear(); return OV_EREAD; } } else { // Only one logical bitstream if(bisect_forward_serialno(0,end,end+1,serialno,0, instance)<0) { clear(); return OV_EREAD; } } prefetch_all_headers(initial_i, initial_c, dataoffset, instance); //return(raw_seek(0)); return 0; }
static MemoryStream DecodeStream(Stream input, bool skipWavHeader, out Info vi) { int convsize = 4096 * 2; byte[] convbuffer = new byte[convsize]; // take 8k out of the data segment, not the stack TextWriter s_err = new DebugWriter(); var output = new MemoryStream(); if (!skipWavHeader) { output.Seek(HEADER_SIZE, SeekOrigin.Begin); // reserve place for WAV header } SyncState oy = new SyncState(); // sync and verify incoming physical bitstream StreamState os = new StreamState(); // take physical pages, weld into a logical stream of packets Page og = new Page(); // one Ogg bitstream page. Vorbis packets are inside Packet op = new Packet(); // one raw packet of data for decode vi = new Info(); // struct that stores all the static vorbis bitstream settings Comment vc = new Comment(); // struct that stores all the bitstream user comments DspState vd = new DspState(); // central working state for the packet->PCM decoder Block vb = new Block(vd); // local working space for packet->PCM decode byte[] buffer; int bytes = 0; // Decode setup oy.init(); // Now we can read pages while (true) { // we repeat if the bitstream is chained int eos = 0; // grab some data at the head of the stream. We want the first page // (which is guaranteed to be small and only contain the Vorbis // stream initial header) We need the first page to get the stream // serialno. // submit a 4k block to libvorbis' Ogg layer int index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); // Get the first page. if (oy.pageout(og) != 1) { // have we simply run out of data? If so, we're done. if (bytes < 4096) { break; } // error case. Must not be Vorbis data s_err.WriteLine("Input does not appear to be an Ogg bitstream."); } // Get the serial number and set up the rest of decode. // serialno first; use it to set up a logical stream os.init(og.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data // I handle the initial header first instead of just having the code // read all three Vorbis headers at once because reading the initial // header is an easy way to identify a Vorbis bitstream and it's // useful to see that functionality seperated out. vi.init(); vc.init(); if (os.pagein(og) < 0) { // error; stream version mismatch perhaps s_err.WriteLine("Error reading first page of Ogg bitstream data."); } if (os.packetout(op) != 1) { // no page? must not be vorbis s_err.WriteLine("Error reading initial header packet."); } if (vi.synthesis_headerin(vc, op) < 0) { // error case; not a vorbis header s_err.WriteLine("This Ogg bitstream does not contain Vorbis audio data."); } // At this point, we're sure we're Vorbis. We've set up the logical // (Ogg) bitstream decoder. Get the comment and codebook headers and // set up the Vorbis decoder // The next two packets in order are the comment and codebook headers. // They're likely large and may span multiple pages. Thus we reead // and submit data until we get our two pacakets, watching that no // pages are missing. If a page is missing, error out; losing a // header page is the only place where missing data is fatal. */ int i = 0; while (i < 2) { while (i < 2) { int result = oy.pageout(og); if (result == 0) { break; // Need more data } // Don't complain about missing or corrupt data yet. We'll // catch it at the packet output phase if (result == 1) { os.pagein(og); // we can ignore any errors here // as they'll also become apparent // at packetout while (i < 2) { result = os.packetout(op); if (result == 0) { break; } if (result == -1) { // Uh oh; data at some point was corrupted or missing! // We can't tolerate that in a header. Die. s_err.WriteLine("Corrupt secondary header. Exiting."); } vi.synthesis_headerin(vc, op); i++; } } } // no harm in not checking before adding more index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } if (bytes == 0 && i < 2) { s_err.WriteLine("End of file before finding all Vorbis headers!"); } oy.wrote(bytes); } // Throw the comments plus a few lines about the bitstream we're // decoding { byte[][] ptr = vc.user_comments; for (int j = 0; j < vc.user_comments.Length; j++) { if (ptr[j] == null) { break; } s_err.WriteLine(vc.getComment(j)); } s_err.WriteLine("\nBitstream is " + vi.channels + " channel, " + vi.rate + "Hz"); s_err.WriteLine("Encoded by: " + vc.getVendor() + "\n"); } convsize = 4096 / vi.channels; // OK, got and parsed all three headers. Initialize the Vorbis // packet->PCM decoder. vd.synthesis_init(vi); // central decode state vb.init(vd); // local state for most of the decode // so multiple block decodes can // proceed in parallel. We could init // multiple vorbis_block structures // for vd here float[][][] _pcm = new float[1][][]; int[] _index = new int[vi.channels]; // The rest is just a straight decode loop until end of stream while (eos == 0) { while (eos == 0) { int result = oy.pageout(og); if (result == 0) { break; // need more data } if (result == -1) { // missing or corrupt data at this page position s_err.WriteLine("Corrupt or missing data in bitstream; continuing..."); } else { os.pagein(og); // can safely ignore errors at // this point while (true) { result = os.packetout(op); if (result == 0) { break; // need more data } if (result == -1) { // missing or corrupt data at this page position // no reason to complain; already complained above } else { // we have a packet. Decode it int samples; if (vb.synthesis(op) == 0) { // test for success! vd.synthesis_blockin(vb); } // **pcm is a multichannel float vector. In stereo, for // example, pcm[0] is left, and pcm[1] is right. samples is // the size of each channel. Convert the float values // (-1.<=range<=1.) to whatever PCM format and write it out while ((samples = vd.synthesis_pcmout(_pcm, _index)) > 0) { float[][] pcm = _pcm[0]; bool clipflag = false; int bout = (samples < convsize ? samples : convsize); // convert floats to 16 bit signed ints (host order) and // interleave for (i = 0; i < vi.channels; i++) { int ptr = i * 2; //int ptr=i; int mono = _index[i]; for (int j = 0; j < bout; j++) { int val = (int)(pcm[i][mono + j] * 32767.0); // short val=(short)(pcm[i][mono+j]*32767.); // int val=(int)Math.round(pcm[i][mono+j]*32767.); // might as well guard against clipping if (val > 32767) { val = 32767; clipflag = true; } if (val < -32768) { val = -32768; clipflag = true; } if (val < 0) { val = val | 0x8000; } convbuffer[ptr] = (byte)(val); convbuffer[ptr + 1] = (byte)((uint)val >> 8); ptr += 2 * (vi.channels); } } if (clipflag) { //s_err.WriteLine("Clipping in frame "+vd.sequence); } output.Write(convbuffer, 0, 2 * vi.channels * bout); vd.synthesis_read(bout); // tell libvorbis how // many samples we // actually consumed } } } if (og.eos() != 0) { eos = 1; } } } if (eos == 0) { index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); if (bytes == 0) { eos = 1; } } } // clean up this logical bitstream; before exit we see if we're // followed by another [chained] os.clear(); // ogg_page and ogg_packet structs always point to storage in // libvorbis. They're never freed or manipulated directly vb.clear(); vd.clear(); vi.clear(); // must be called last } // OK, clean up the framer oy.clear(); s_err.WriteLine("Done."); output.Seek(0, SeekOrigin.Begin); if (!skipWavHeader) { WriteHeader(output, (int)(output.Length - HEADER_SIZE), vi.rate, (ushort)16, (ushort)vi.channels); output.Seek(0, SeekOrigin.Begin); } return(output); }