Example #1
0
 public static long ogg_page_pageno(ogg_page og)
 {
     return(og.header[18] |
            og.header[19] << 8 |
            og.header[20] << 16 |
            og.header[21] << 24);
 }
Example #2
0
        /* sync the stream and get a page.  Keep trying until we find a page.
         * Suppress 'sync errors' after reporting the first.
         *
         * return values:
         * -1) recapture (hole in data)
         *  0) need more data
         *  1) page returned
         *
         * Returns pointers into buffered data; invalidated by next call to
         * _stream, _clear, _init, or _buffer */

        public static int ogg_sync_pageout(ogg_sync_state oy, ogg_page og)
        {
            if (ogg_sync_check(oy) != 0)
            {
                return(0);
            }

            /* all we need to do is verify a page at the head of the stream
             * buffer.  If it doesn't verify, we look for the next potential
             * frame */

            for (; ;)
            {
                long ret = ogg_sync_pageseek(oy, og);
                if (ret > 0)
                {
                    /* have a page */
                    return(1);
                }
                if (ret == 0)
                {
                    /* need more data */
                    return(0);
                }

                /* head did not start a synced page... skipped some bytes */
                if (oy.unsynced == 0)
                {
                    oy.unsynced = 1;
                    return(-1);
                }

                /* loop. keep looking */
            }
        }
Example #3
0
 public static int ogg_page_serialno(ogg_page og)
 {
     return(og.header[14] |
            og.header[15] << 8 |
            og.header[16] << 16 |
            og.header[17] << 24);
 }
Example #4
0
        public static long ogg_page_granulepos(ogg_page og)
        {
            ArrayPointer page       = og.header;
            long         granulepos = page[13] & (0xff);

#pragma warning disable CS0675 // Bitwise-or operator used on a sign-extended operand
            granulepos = (granulepos << 8) | (page[12] & 0xff);
            granulepos = (granulepos << 8) | (page[11] & 0xff);
            granulepos = (granulepos << 8) | (page[10] & 0xff);
            granulepos = (granulepos << 8) | (page[9] & 0xff);
            granulepos = (granulepos << 8) | (page[8] & 0xff);
            granulepos = (granulepos << 8) | (page[7] & 0xff);
            granulepos = (granulepos << 8) | (page[6] & 0xff);
#pragma warning restore CS0675 // Bitwise-or operator used on a sign-extended operand
            return((long)granulepos);
        }
Example #5
0
        public static void ogg_page_checksum_set(ogg_page og)
        {
            uint crc_reg = 0;

            /* safety; needed for API behavior, but not framing code */
            og.header[22] = 0;
            og.header[23] = 0;
            og.header[24] = 0;
            og.header[25] = 0;

            crc_reg = _os_update_crc(crc_reg, og.header, og.header_len);
            crc_reg = _os_update_crc(crc_reg, og.body, og.body_len);

            og.header[22] = (byte)(crc_reg & 0xff);
            og.header[23] = (byte)((crc_reg >> 8) & 0xff);
            og.header[24] = (byte)((crc_reg >> 16) & 0xff);
            og.header[25] = (byte)((crc_reg >> 24) & 0xff);
        }
Example #6
0
        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");
        }
Example #7
0
 public static int ogg_page_eos(ogg_page og)
 {
     return((int)(og.header[5] & 0x04));
 }
Example #8
0
 public static int ogg_page_continued(ogg_page og)
 {
     return((int)(og.header[5] & 0x01));
 }
Example #9
0
        /* A complete description of Ogg framing exists in docs/framing.html */

        public static int ogg_page_version(ogg_page og)
        {
            return((int)(og.header[4]));
        }
Example #10
0
        /* add the incoming page to the stream state; we decompose the page
         * into packet segments here as well. */

        public static int ogg_stream_pagein(ogg_stream_state os, ogg_page og)
        {
            ArrayPointer header   = og.header;
            ArrayPointer body     = og.body;
            long         bodysize = og.body_len;
            int          segptr   = 0;

            int  version    = ogg_page_version(og);
            int  continued  = ogg_page_continued(og);
            int  bos        = ogg_page_bos(og);
            int  eos        = ogg_page_eos(og);
            long granulepos = ogg_page_granulepos(og);
            int  serialno   = ogg_page_serialno(og);
            long pageno     = ogg_page_pageno(og);
            int  segments   = header[26];

            if (ogg_stream_check(os) != 0)
            {
                return(-1);
            }

            /* clean up 'returned data' */
            {
                long lr = os.lacing_returned;
                long br = os.body_returned;

                /* body data */
                if (br != 0)
                {
                    os.body_fill -= br;
                    if (os.body_fill != 0)
                    {
                        memmove(os.body_data, os.body_data + br, os.body_fill);
                    }
                    os.body_returned = 0;
                }

                if (lr != 0)
                {
                    /* segment table */
                    if ((os.lacing_fill - lr) != 0)
                    {
                        memmove(os.lacing_vals, /*os.lacing_vals +*/ lr,
                                (os.lacing_fill - lr) /* * sizeof(*os.lacing_vals)*/);
                        memmove(os.granule_vals, /*os.granule_vals +*/ lr,
                                (os.lacing_fill - lr) /* * sizeof(*os.granule_vals)*/);
                    }
                    os.lacing_fill    -= lr;
                    os.lacing_packet  -= lr;
                    os.lacing_returned = 0;
                }
            }

            /* check the serial number */
            if (serialno != os.serialno)
            {
                return(-1);
            }
            if (version > 0)
            {
                return(-1);
            }

            if (_os_lacing_expand(os, segments + 1) != 0)
            {
                return(-1);
            }

            /* are we in sequence? */
            if (pageno != os.pageno)
            {
                long i;

                /* unroll previous partial packet (if any) */
                for (i = os.lacing_packet; i < os.lacing_fill; i++)
                {
                    os.body_fill -= os.lacing_vals[i] & 0xff;
                }
                os.lacing_fill = os.lacing_packet;

                /* make a note of dropped data in segment table */
                if (os.pageno != -1)
                {
                    os.lacing_vals[os.lacing_fill++] = 0x400;
                    os.lacing_packet++;
                }
            }

            /* are we a 'continued packet' page?  If so, we may need to skip
             * some segments */
            if (continued != 0)
            {
                if (os.lacing_fill < 1 ||
                    (os.lacing_vals[os.lacing_fill - 1] & 0xff) < 255 ||
                    os.lacing_vals[os.lacing_fill - 1] == 0x400)
                {
                    bos = 0;
                    for (; segptr < segments; segptr++)
                    {
                        int val = header[27 + segptr];
                        body     += val;
                        bodysize -= val;
                        if (val < 255)
                        {
                            segptr++;
                            break;
                        }
                    }
                }
            }

            if (bodysize != 0)
            {
                if (_os_body_expand(os, bodysize) != 0)
                {
                    return(-1);
                }
                memcpy(os.body_data + os.body_fill, body, bodysize);
                os.body_fill += bodysize;
            }

            {
                long saved = -1;
                while (segptr < segments)
                {
                    int val = header[27 + segptr];
                    os.lacing_vals[os.lacing_fill]  = val;
                    os.granule_vals[os.lacing_fill] = -1;

                    if (bos != 0)
                    {
                        os.lacing_vals[os.lacing_fill] |= 0x100;
                        bos = 0;
                    }

                    if (val < 255)
                    {
                        saved = os.lacing_fill;
                    }

                    os.lacing_fill++;
                    segptr++;

                    if (val < 255)
                    {
                        os.lacing_packet = os.lacing_fill;
                    }
                }

                /* set the granulepos on the last granuleval of the last full packet */
                if (saved != -1)
                {
                    os.granule_vals[saved] = granulepos;
                }
            }

            if (eos != 0)
            {
                os.e_o_s = 1;
                if (os.lacing_fill > 0)
                {
                    os.lacing_vals[os.lacing_fill - 1] |= 0x200;
                }
            }

            os.pageno = pageno + 1;

            return(0);
        }
Example #11
0
        /* sync the stream.  This is meant to be useful for finding page
         * boundaries.
         *
         * return values for this:
         * -n) skipped n bytes
         * 0) page not ready; more data (no bytes skipped)
         * n) page synced at current location; page length n bytes
         *
         */
        public static long ogg_sync_pageseek(ogg_sync_state oy, ogg_page og)
        {
            ArrayPointer page = oy.data + oy.returned;
            ArrayPointer next;
            long         bytes = oy.fill - oy.returned;

            if (ogg_sync_check(oy) != 0)
            {
                return(0);
            }

            if (oy.headerbytes == 0)
            {
                int headerbytes, i;
                if (bytes < 27)
                {
                    return(0);              /* not enough for a header */
                }
                /* verify capture pattern */
                if (memcmp(page, "OggS", 4) != 0)
                {
                    goto sync_fail;
                }

                headerbytes = page[26] + 27;
                if (bytes < headerbytes)
                {
                    return(0);                       /* not enough for header + seg table */
                }
                /* count up body length in the segment table */

                for (i = 0; i < page[26]; i++)
                {
                    oy.bodybytes += page[27 + i];
                }
                oy.headerbytes = headerbytes;
            }

            if (oy.bodybytes + oy.headerbytes > bytes)
            {
                return(0);
            }

            /* The whole test page is buffered.  Verify the checksum */
            {
                /* Grab the checksum bytes, set the header field to zero */
                var      chksum = new byte[4];
                ogg_page log    = new ogg_page();

                memcpy(chksum, page + 22, 4);
                memset(page + 22, 0, 4);

                /* set up a temp page struct and recompute the checksum */
                log.header     = page;
                log.header_len = oy.headerbytes;
                log.body       = page + oy.headerbytes;
                log.body_len   = oy.bodybytes;
                ogg_page_checksum_set(log);

                /* Compare */
                if (memcmp(chksum, page + 22, 4) != 0)
                {
                    /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
                     * at all) */
                    /* replace the computed checksum with the one actually read in */
                    memcpy(page + 22, chksum, 4);

#if DISABLE_CRC
                    /* Bad checksum. Lose sync */
                    goto sync_fail;
#endif
                }
            }

            /* yes, have a whole page all ready to go */
            {
                og.header     = page;
                og.header_len = oy.headerbytes;
                og.body       = page + oy.headerbytes;
                og.body_len   = oy.bodybytes;

                oy.unsynced    = 0;
                oy.returned   += (int)(bytes = oy.headerbytes + oy.bodybytes);
                oy.headerbytes = 0;
                oy.bodybytes   = 0;
                return(bytes);
            }

sync_fail:

            oy.headerbytes = 0;
            oy.bodybytes   = 0;

            /* search for possible capture */
            next = memchr(page + 1, 'O', bytes - 1);
            if (next == null)
            {
                next = oy.data + oy.fill;
            }

            oy.returned = (int)(next - oy.data);
            return((long)-(next - page));
        }