public static int ogg_stream_packetout(ogg_stream_state os, ogg_packet op) { if (ogg_stream_check(os) != 0) { return(0); } return(_packetout(os, op, 1)); }
static ushort[] convbuffer = new ushort[4096]; /* take 8k out of the data segment, not the stack */ //static long convsize = 4096; public static void Main(string[] args) { /* sync and verify incoming physical bitstream */ var oy = new ogg_sync_state(); /* take physical pages, weld into a logical stream of packets */ var os = new ogg_stream_state(); /* one Ogg bitstream page. Vorbis packets are inside */ var og = new ogg_page(); /* one raw packet of data for decode */ var op = new ogg_packet(); /* struct that stores all the static vorbis bitstream settings */ var vi = new vorbis_info(); /* struct that stores all the bitstream user comments */ var vc = new vorbis_comment(); /* central working state for the packet->PCM decoder */ var vd = new vorbis_dsp_state(); /* local working space for packet->PCM decode */ var vb = new vorbis_block(); var stdin = Console.OpenStandardInput(); var stdout = Console.OpenStandardOutput(); var stderr = Console.OpenStandardError(); /********** Decode setup ************/ ogg_sync_init(oy); /* Now we can read pages */ while (true) { /* we repeat if the bitstream is chained */ /* 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 */ var buffer = ogg_sync_buffer(oy, 4096); int bytes = fread(buffer, 1, 4096, stdin); ogg_sync_wrote(oy, bytes); /* Get the first page. */ if (ogg_sync_pageout(oy, 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 */ fprintf(stderr, "Input does not appear to be an Ogg bitstream.\n"); exit(1); } /* get the serial number and set up the rest of decode. */ /* serialno first; use it to set up a logical stream */ ogg_stream_init(os, ogg_page_serialno(og)); /* 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. */ vorbis_info_init(vi); vorbis_comment_init(vc); if (ogg_stream_pagein(os, og) < 0) { /* error; stream version mismatch perhaps */ fprintf(stderr, "error reading first page of ogg bitstream data.\n"); exit(1); } if (ogg_stream_packetout(os, op) != 1) { /* no page? must not be vorbis */ fprintf(stderr, "error reading initial header packet.\n"); exit(1); } if (vorbis_synthesis_headerin(vi, vc, op) < 0) { /* error case; not a vorbis header */ fprintf(stderr, "this ogg bitstream does not contain vorbis audio data.\n"); exit(1); } //// /* 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 read //// and submit data until we get our two packets, 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. */ //// i = 0; //// while (i < 2) //// { //// while (i < 2) //// { //// int result = ogg_sync_pageout(oggSyncState, oggPage); //// 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) //// { //// ogg_stream_pagein(oggStreamState, oggPage); /* we can ignore any errors here //// as they'll also become apparent //// at packetout */ //// while (i < 2) //// { //// result = ogg_stream_packetout(oggStreamState, oggPacket); //// if (result == 0) break; //// if (result < 0) //// { //// /* Uh oh; data at some point was corrupted or missing! //// We can't tolerate that in a header. Die. */ //// fprintf(stderr, "Corrupt secondary header. Exiting.\n"); //// exit(1); //// } //// result = vorbis_synthesis_headerin(vorbisInfo, vorbisComment, oggPacket); //// if (result < 0) //// { //// fprintf(stderr, "Corrupt secondary header. Exiting.\n"); //// exit(1); //// } //// i++; //// } //// } //// } //// /* no harm in not checking before adding more */ //// buffer = ogg_sync_buffer(oggSyncState, 4096); //// bytes = fread(buffer, 1, 4096, stdin); //// if (bytes == 0 && i < 2) //// { //// fprintf(stderr, "End of file before finding all Vorbis headers!\n"); //// exit(1); //// } //// ogg_sync_wrote(oggSyncState, bytes); //// } //// /* Throw the comments plus a few lines about the bitstream we're //// decoding */ //// { //// char** ptr = vorbisComment.user_comments; //// while (*ptr) //// { //// fprintf(stderr, "%s\n", *ptr); //// ++ptr; //// } //// fprintf(stderr, "\nBitstream is %d channel, %ldHz\n", vorbisInfo.channels, vorbisInfo.rate); //// fprintf(stderr, "Encoded by: %s\n\n", vorbisComment.vendor); //// } //// convsize = 4096 / vorbisInfo.channels; //// /* OK, got and parsed all three headers. Initialize the Vorbis //// packet->PCM decoder. */ //// if (vorbis_synthesis_init(vorbisDspState, vorbisInfo) == 0) //// { /* central decode state */ //// vorbis_block_init(vorbisDspState, vorbisBlock); /* 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 */ //// /* The rest is just a straight decode loop until end of stream */ //// while (eos == 0) //// { //// while (eos == 0) //// { //// int result = ogg_sync_pageout(oggSyncState, oggPage); //// if (result == 0) break; /* need more data */ //// if (result < 0) //// { /* missing or corrupt data at this page position */ //// fprintf(stderr, "Corrupt or missing data in bitstream; " //// "continuing...\n"); //// } //// else //// { //// ogg_stream_pagein(oggStreamState, oggPage); /* can safely ignore errors at //// this point */ //// while (1) //// { //// result = ogg_stream_packetout(&oggStreamState, &oggPacket); //// if (result == 0) break; /* need more data */ //// if (result < 0) //// { /* missing or corrupt data at this page position */ //// /* no reason to complain; already complained above */ //// } //// else //// { //// /* we have a packet. Decode it */ //// float** pcm; //// int samples; //// if (vorbis_synthesis(&vorbisBlock, &oggPacket) == 0) /* test for success! */ //// vorbis_synthesis_blockin(&vorbisDspState, &vorbisBlock); //// /* //// **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 = vorbis_synthesis_pcmout(&vorbisDspState, &pcm)) > 0) //// { //// int j; //// int clipflag = 0; //// int bout = (samples < convsize ? samples : convsize); //// /* convert floats to 16 bit signed ints (host order) and //// interleave */ //// for (i = 0; i < vorbisInfo.channels; i++) //// { //// ogg_int16_t* ptr = convbuffer + i; //// float* mono = pcm[i]; //// for (j = 0; j < bout; j++) //// { ////#if 1 //// int val=floor(mono[j]*32767.f+.5f); ////#else /* optional dither */ //// int val = mono[j] * 32767.f + drand48() - 0.5f; ////#endif //// /* might as well guard against clipping */ //// if (val > 32767) //// { //// val = 32767; //// clipflag = 1; //// } //// if (val < -32768) //// { //// val = -32768; //// clipflag = 1; //// } //// *ptr = val; //// ptr += vorbisInfo.channels; //// } //// } //// if (clipflag) //// fprintf(stderr, "Clipping in frame %ld\n", (long)(vorbisDspState.sequence)); //// fwrite(convbuffer, 2 * vorbisInfo.channels, bout, stdout); //// vorbis_synthesis_read(vorbisDspState, bout); /* tell libvorbis how //// many samples we //// actually consumed */ //// } //// } //// } //// if (ogg_page_eos(oggPage) != 0) eos = 1; //// } //// } //// if (eos == 0) //// { //// buffer = ogg_sync_buffer(oggSyncState, 4096); //// bytes = fread(buffer, 1, 4096, stdin); //// ogg_sync_wrote(oggSyncState, bytes); //// if (bytes == 0) eos = 1; //// } //// } //// /* ogg_page and ogg_packet structs always point to storage in //// libvorbis. They're never freed or manipulated directly */ //// vorbis_block_clear(vorbisBlock); //// vorbis_dsp_clear(vorbisDspState); //// } //// else //// { //// fprintf(stderr, "Error: Corrupt header during playback initialization.\n"); //// } //// /* clean up this logical bitstream; before exit we see if we're //// followed by another [chained] */ //// ogg_stream_clear(oggStreamState); //// vorbis_comment_clear(vorbisComment); //// vorbis_info_clear(vorbisInfo); /* must be called last */ } /* OK, clean up the framer */ ogg_sync_clear(oy); fprintf(stderr, "Done.\n"); }
public static int _packetout(ogg_stream_state os, ogg_packet op, int adv) { /* The last part of decode. We have the stream broken into packet * segments. Now we need to group them into packets (or return the * out of sync markers) */ long ptr = os.lacing_returned; if (os.lacing_packet <= ptr) { return(0); } if ((os.lacing_vals[ptr] & 0x400) != 0) { /* we need to tell the codec there's a gap; it might need to * handle previous packet dependencies. */ os.lacing_returned++; os.packetno++; return(-1); } if (op == null && adv == 0) { return(1); /* just using peek as an inexpensive way * to ask if there's a whole packet * waiting */ } /* Gather the whole packet. We'll have no holes or a partial packet */ { int size = os.lacing_vals[ptr] & 0xff; long bytes = size; int eos = os.lacing_vals[ptr] & 0x200; /* last packet of the stream? */ int bos = os.lacing_vals[ptr] & 0x100; /* first packet of the stream? */ while (size == 255) { int val = os.lacing_vals[++ptr]; size = val & 0xff; if ((val & 0x200) != 0) { eos = 0x200; } bytes += size; } if (op != null) { op.e_o_s = eos; op.b_o_s = bos; op.packet = os.body_data + os.body_returned; op.packetno = os.packetno; op.granulepos = os.granule_vals[ptr]; op.bytes = bytes; } if (adv != 0) { os.body_returned += bytes; os.lacing_returned = ptr + 1; os.packetno++; } } return(1); }
/* The Vorbis header is in three packets; the initial small packet in * the first page that identifies basic parameters, a second packet * with bitstream comments and a third packet that holds the * codebook. */ public static int vorbis_synthesis_headerin(vorbis_info vi, vorbis_comment vc, ogg_packet op) { oggpack_buffer opb = new oggpack_buffer(); if (op != null) { oggpack_readinit(opb, op.packet, op.bytes); /* Which of the three types of header is this? */ /* Also verify header-ness, vorbis */ { var buffer = new ArrayPointer(); long packtype = oggpack_read(opb, 8); //memset(buffer, 0, 6); _v_readstring(opb, buffer, 6); if (memcmp(buffer, "vorbis", 6) != 0) { /* not a vorbis header */ return(OV_ENOTVORBIS); } switch (packtype) { case 0x01: /* least significant *bit* is read first */ if (op.b_o_s == 0) { /* Not the initial packet */ return(OV_EBADHEADER); } if (vi.rate != 0) { /* previously initialized info header */ return(OV_EBADHEADER); } return(_vorbis_unpack_info(vi, opb)); case 0x03: /* least significant *bit* is read first */ if (vi.rate == 0) { /* um... we didn't get the initial header */ return(OV_EBADHEADER); } if (vc.vendor != null) { /* previously initialized comment header */ return(OV_EBADHEADER); } return(_vorbis_unpack_comment(vc, opb)); case 0x05: /* least significant *bit* is read first */ if (vi.rate == 0 || vc.vendor == null) { /* um... we didn;t get the initial header or comments yet */ return(OV_EBADHEADER); } if (vi.codec_setup == null) { /* improperly initialized vorbis_info */ return(OV_EFAULT); } if (((codec_setup_info)vi.codec_setup).books > 0) { /* previously initialized setup header */ return(OV_EBADHEADER); } return(_vorbis_unpack_books(vi, opb)); default: /* Not a valid vorbis header type */ return(OV_EBADHEADER); //break; } } } return(OV_EBADHEADER); }