예제 #1
0
        unsafe void decode_metadata()
        {
            byte x;
            int i, id;
            bool first = true;
            byte[] FLAC__STREAM_SYNC_STRING = new byte[] { (byte)'f', (byte)'L', (byte)'a', (byte)'C' };
            byte[] ID3V2_TAG_ = new byte[] { (byte)'I', (byte)'D', (byte)'3' };

            for (i = id = 0; i < 4; )
            {
                if (_IO.Read(_framesBuffer, 0, 1) == 0)
                    throw new Exception("FLAC stream not found");
                x = _framesBuffer[0];
                if (x == FLAC__STREAM_SYNC_STRING[i])
                {
                    first = true;
                    i++;
                    id = 0;
                    continue;
                }
                if (id < 3 && x == ID3V2_TAG_[id])
                {
                    id++;
                    i = 0;
                    if (id == 3)
                    {
                        if (!skip_bytes(3))
                            throw new Exception("FLAC stream not found");
                        int skip = 0;
                        for (int j = 0; j < 4; j++)
                        {
                            if (0 == _IO.Read(_framesBuffer, 0, 1))
                                throw new Exception("FLAC stream not found");
                            skip <<= 7;
                            skip |= ((int)_framesBuffer[0] & 0x7f);
                        }
                        if (!skip_bytes(skip))
                            throw new Exception("FLAC stream not found");
                    }
                    continue;
                }
                id = 0;
                if (x == 0xff) /* MAGIC NUMBER for the first 8 frame sync bits */
                {
                    do
                    {
                        if (_IO.Read(_framesBuffer, 0, 1) == 0)
                            throw new Exception("FLAC stream not found");
                        x = _framesBuffer[0];
                    } while (x == 0xff);
                    if (x >> 2 == 0x3e) /* MAGIC NUMBER for the last 6 sync bits */
                    {
                        //_IO.Position -= 2;
                        // state = frame
                        throw new Exception("headerless file unsupported");
                    }
                }
                throw new Exception("FLAC stream not found");
            }

            do
            {
                fill_frames_buffer();
                fixed (byte* buf = _framesBuffer)
                {
                    BitReader bitreader = new BitReader(buf, _framesBufferOffset, _framesBufferLength - _framesBufferOffset);
                    bool is_last = bitreader.readbit() != 0;
                    MetadataType type = (MetadataType)bitreader.readbits(7);
                    int len = (int)bitreader.readbits(24);

                    if (type == MetadataType.StreamInfo)
                    {
                        const int FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
                        const int FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */

                        min_block_size = bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN);
                        max_block_size = bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN);
                        min_frame_size = bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN);
                        max_frame_size = bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN);
                        int sample_rate = (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN);
                        int channels = 1 + (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN);
                        int bits_per_sample = 1 + (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN);
                        pcm = new AudioPCMConfig(bits_per_sample, channels, sample_rate);
                        _sampleCount = (long)bitreader.readbits64(FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN);
                        bitreader.skipbits(FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN);
                    }
                    else if (type == MetadataType.Seektable)
                    {
                        int num_entries = len / 18;
                        seek_table = new SeekPoint[num_entries];
                        for (int e = 0; e < num_entries; e++)
                        {
                            seek_table[e].number = (long)bitreader.readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN);
                            seek_table[e].offset = (long)bitreader.readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN);
                            seek_table[e].framesize = (int)bitreader.readbits24(Flake.FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN);
                        }
                    }
                    if (_framesBufferLength < 4 + len)
                    {
                        _IO.Position += 4 + len - _framesBufferLength;
                        _framesBufferLength = 0;
                    }
                    else
                    {
                        _framesBufferLength -= 4 + len;
                        _framesBufferOffset += 4 + len;
                    }
                    if (is_last)
                        break;
                }
            } while (true);
            first_frame_offset = _IO.Position - _framesBufferLength;
        }