예제 #1
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");
        }
예제 #2
0
        public static void vorbis_info_clear(vorbis_info vi)
        {
            codec_setup_info ci = vi.codec_setup;
            int i;

            if (ci != null)
            {
                for (i = 0; i < ci.modes; i++)
                {
                    if (ci.mode_param[i] != null) //_ogg_free(ci.mode_param[i]);
                    {
                        ci.mode_param[i] = null;
                    }
                }

                for (i = 0; i < ci.maps; i++)    /* unpack does the range checking */
                {
                    if (ci.map_param[i] != null) /* this may be cleaning up an aborted
                                                  * unpack, in which case the below type
                                                  * cannot be trusted */
                                                 //_mapping_P[ci.map_type[i]].free_info(ci.map_param[i]);
                    {
                        ci.map_param[i] = null;
                    }
                }

                for (i = 0; i < ci.floors; i++)    /* unpack does the range checking */
                {
                    if (ci.floor_param[i] != null) /* this may be cleaning up an aborted
                                                    * unpack, in which case the below type
                                                    * cannot be trusted */
                                                   //_floor_P[ci.floor_type[i]].free_info(ci.floor_param[i]);
                    {
                        ci.floor_param[i] = null;
                    }
                }

                for (i = 0; i < ci.residues; i++)    /* unpack does the range checking */
                {
                    if (ci.residue_param[i] != null) /* this may be cleaning up an aborted
                                                      * unpack, in which case the below type
                                                      * cannot be trusted */
                                                     //_residue_P[ci.residue_type[i]].free_info(ci.residue_param[i]);
                    {
                        ci.residue_param[i] = null;
                    }
                }

                for (i = 0; i < ci.books; i++)
                {
                    if (ci.book_param[i] != null)
                    {
                        /* knows if the book was not alloced */
                        vorbis_staticbook_destroy(ci.book_param[i]);
                    }
                    //if (ci.fullbooks != null)
                    //    vorbis_book_clear(ci.fullbooks + i);
                }
                if (ci.fullbooks != null)
                {
                    //_ogg_free(ci.fullbooks);
                    ci.fullbooks = null;
                }

                for (i = 0; i < ci.psys; i++)
                {
                    //_vi_psy_free(ci.psy_param[i]);
                    ci.psy_param[i] = null;
                }

                //_ogg_free(ci);
                vi.codec_setup = null;
            }

            //memset(vi, 0, sizeof(*vi));
        }
예제 #3
0
        /* 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);
        }
예제 #4
0
        /* all of the real encoding details are here.  The modes, books,
         * everything */
        public static int _vorbis_unpack_books(vorbis_info vi, oggpack_buffer opb)
        {
            codec_setup_info ci = vi.codec_setup;
            int i;

            /* codebooks */
            ci.books = (int)oggpack_read(opb, 8) + 1;
            if (ci.books <= 0)
            {
                goto err_out;
            }
            for (i = 0; i < ci.books; i++)
            {
                ci.book_param[i] = vorbis_staticbook_unpack(opb);
                if (ci.book_param[i] == null)
                {
                    goto err_out;
                }
            }

            /* time backend settings; hooks are unused */
            {
                int times = (int)oggpack_read(opb, 6) + 1;
                if (times <= 0)
                {
                    goto err_out;
                }
                for (i = 0; i < times; i++)
                {
                    int test = (int)oggpack_read(opb, 16);
                    if (test < 0 || test >= VI_TIMEB)
                    {
                        goto err_out;
                    }
                }
            }

            /* floor backend settings */
            ci.floors = (int)oggpack_read(opb, 6) + 1;
            if (ci.floors <= 0)
            {
                goto err_out;
            }
            for (i = 0; i < ci.floors; i++)
            {
                ci.floor_type[i] = (int)oggpack_read(opb, 16);
                if (ci.floor_type[i] < 0 || ci.floor_type[i] >= VI_FLOORB)
                {
                    goto err_out;
                }
                ci.floor_param[i] = _floor_P[ci.floor_type[i]].unpack(vi, opb);
                if (ci.floor_param[i] == null)
                {
                    goto err_out;
                }
            }

            /* residue backend settings */
            ci.residues = (int)oggpack_read(opb, 6) + 1;
            if (ci.residues <= 0)
            {
                goto err_out;
            }
            for (i = 0; i < ci.residues; i++)
            {
                ci.residue_type[i] = (int)oggpack_read(opb, 16);
                if (ci.residue_type[i] < 0 || ci.residue_type[i] >= VI_RESB)
                {
                    goto err_out;
                }
                ci.residue_param[i] = _residue_P[ci.residue_type[i]].unpack(vi, opb);
                if (ci.residue_param[i] == null)
                {
                    goto err_out;
                }
            }

            /* map backend settings */
            ci.maps = (int)oggpack_read(opb, 6) + 1;
            if (ci.maps <= 0)
            {
                goto err_out;
            }
            for (i = 0; i < ci.maps; i++)
            {
                ci.map_type[i] = (int)oggpack_read(opb, 16);
                if (ci.map_type[i] < 0 || ci.map_type[i] >= VI_MAPB)
                {
                    goto err_out;
                }
                ci.map_param[i] = _mapping_P[ci.map_type[i]].unpack(vi, opb);
                if (ci.map_param[i] == null)
                {
                    goto err_out;
                }
            }

            /* mode settings */
            ci.modes = (int)oggpack_read(opb, 6) + 1;
            if (ci.modes <= 0)
            {
                goto err_out;
            }
            for (i = 0; i < ci.modes; i++)
            {
                ci.mode_param[i]               = new vorbis_info_mode(); //_ogg_calloc(1, sizeof(*ci.mode_param[i]));
                ci.mode_param[i].blockflag     = (int)oggpack_read(opb, 1);
                ci.mode_param[i].windowtype    = (int)oggpack_read(opb, 16);
                ci.mode_param[i].transformtype = (int)oggpack_read(opb, 16);
                ci.mode_param[i].mapping       = (int)oggpack_read(opb, 8);

                if (ci.mode_param[i].windowtype >= VI_WINDOWB)
                {
                    goto err_out;
                }
                if (ci.mode_param[i].transformtype >= VI_WINDOWB)
                {
                    goto err_out;
                }
                if (ci.mode_param[i].mapping >= ci.maps)
                {
                    goto err_out;
                }
                if (ci.mode_param[i].mapping < 0)
                {
                    goto err_out;
                }
            }

            if (oggpack_read(opb, 1) != 1)
            {
                goto err_out;                            /* top level EOP check */
            }
            return(0);

err_out:
            vorbis_info_clear(vi);
            return(OV_EBADHEADER);
        }
예제 #5
0
 /* used by synthesis, which has a full, alloced vi */
 public static void vorbis_info_init(vorbis_info vi)
 {
     vi.codec_setup = new codec_setup_info();
 }
예제 #6
0
        /* Header packing/unpacking ********************************************/

        public static int _vorbis_unpack_info(vorbis_info vi, oggpack_buffer opb)
        {
            codec_setup_info ci = vi.codec_setup;
            int bs;

            if (ci == null)
            {
                return(OV_EFAULT);
            }

            vi.version = oggpack_read(opb, 32);
            if (vi.version != 0)
            {
                return(OV_EVERSION);
            }

            vi.channels = oggpack_read(opb, 8);
            vi.rate     = oggpack_read(opb, 32);

            vi.bitrate_upper   = (int)oggpack_read(opb, 32);
            vi.bitrate_nominal = (int)oggpack_read(opb, 32);
            vi.bitrate_lower   = (int)oggpack_read(opb, 32);

            bs = (int)oggpack_read(opb, 4);
            if (bs < 0)
            {
                goto err_out;
            }
            ci.blocksizes[0] = 1 << bs;
            bs = (int)oggpack_read(opb, 4);
            if (bs < 0)
            {
                goto err_out;
            }
            ci.blocksizes[1] = 1 << bs;

            if (vi.rate < 1)
            {
                goto err_out;
            }
            if (vi.channels < 1)
            {
                goto err_out;
            }
            if (ci.blocksizes[0] < 64)
            {
                goto err_out;
            }
            if (ci.blocksizes[1] < ci.blocksizes[0])
            {
                goto err_out;
            }
            if (ci.blocksizes[1] > 8192)
            {
                goto err_out;
            }

            if (oggpack_read(opb, 1) != 1)
            {
                goto err_out;                            /* EOP check */
            }
            return(0);

err_out:
            vorbis_info_clear(vi);
            return(OV_EBADHEADER);
        }