Example #1
0
        // seek to a sample offset relative to the decompressed pcm stream
        // returns zero on success, nonzero on failure
        private int pcm_seek(long pos)
        {
            int  link  = -1;
            long total = pcm_total(-1);

            if (pos < 0 || pos > total)
            {
                // goto seek_error;
                pcm_offset = -1;
                decode_clear();
                return(-1);
            }

            // which bitstream section does this pcm offset occur in?
            for (link = links - 1; link >= 0; link--)
            {
                total -= pcmlengths[link];
                if (pos >= total)
                {
                    break;
                }
            }

            // search within the logical bitstream for the page with the highest
            // pcm_pos preceeding (or equal to) pos. There is a danger here;
            // missing pages or incorrect frame number information in the
            // bitstream could make our task impossible. Account for that (it
            // would be an error condition)
            {
                long target = pos - total;
                long end    = offsets[link + 1];
                long begin  = offsets[link];
                int  best   = (int)begin;

                Page og = new Page();
                while (begin < end)
                {
                    long bisect;
                    int  ret;

                    if (end - begin < CHUNKSIZE)
                    {
                        bisect = begin;
                    }
                    else
                    {
                        bisect = (end + begin) / 2;
                    }

                    seek_helper(bisect);
                    ret = get_next_page(og, end - bisect);

                    if (ret == -1)
                    {
                        end = bisect;
                    }
                    else
                    {
                        long granulepos = og.granulepos();
                        if (granulepos < target)
                        {
                            best  = ret;    // raw offset of packet with granulepos
                            begin = offset; // raw offset of next packet
                        }
                        else
                        {
                            end = bisect;
                        }
                    }
                }
                // found our page. seek to it (call raw_seek).
                if (raw_seek(best) != 0)
                {
                    // goto seek_error;
                    pcm_offset = -1;
                    decode_clear();
                    return(-1);
                }
            }

            // verify result
            if (pcm_offset >= pos)
            {
                // goto seek_error;
                pcm_offset = -1;
                decode_clear();
                return(-1);
            }
            if (pos > pcm_total(-1))
            {
                // goto seek_error;
                pcm_offset = -1;
                decode_clear();
                return(-1);
            }

            // discard samples until we reach the desired position. Crossing a
            // logical bitstream boundary with abandon is OK.
            while (pcm_offset < pos)
            {
                float[][]   pcm;
                int         target  = (int)(pos - pcm_offset);
                float[][][] _pcm    = new float[1][][];
                int         samples = vd.synthesis_pcmout(_pcm, _index);
                pcm = _pcm[0];

                if (samples > target)
                {
                    samples = target;
                }
                vd.synthesis_read(samples);
                pcm_offset += samples;

                if (samples < target)
                {
                    if (process_packet(1) == 0)
                    {
                        pcm_offset = pcm_total(-1); // eof
                    }
                }
            }
            return(0);

            // seek_error:
            // dump machine so we're in a known state
            // pcm_offset=-1;
            // decode_clear();
            // return -1;
        }