Ejemplo n.º 1
0
        unsafe void Decode_residual(BitReader bitreader, FlacFrame frame, int ch)
        {
            // rice-encoded block
            // coding method
            frame.subframes[ch].best.rc.coding_method = (int)bitreader.Readbits(2);             // ????? == 0
            if (frame.subframes[ch].best.rc.coding_method != 0 && frame.subframes[ch].best.rc.coding_method != 1)
            {
                throw new Exception("unsupported residual coding");
            }
            // partition order
            frame.subframes[ch].best.rc.porder = (int)bitreader.Readbits(4);
            if (frame.subframes[ch].best.rc.porder > 8)
            {
                throw new Exception("invalid partition order");
            }
            int psize   = frame.blocksize >> frame.subframes[ch].best.rc.porder;
            int res_cnt = psize - frame.subframes[ch].best.order;

            int rice_len = 4 + frame.subframes[ch].best.rc.coding_method;
            // residual
            int  j = frame.subframes[ch].best.order;
            int *r = frame.subframes[ch].best.residual + j;

            for (int p = 0; p < (1 << frame.subframes[ch].best.rc.porder); p++)
            {
                if (p == 1)
                {
                    res_cnt = psize;
                }
                int n = Math.Min(res_cnt, frame.blocksize - j);

                int k = frame.subframes[ch].best.rc.rparams[p] = (int)bitreader.Readbits(rice_len);
                if (k == (1 << rice_len) - 1)
                {
                    k = frame.subframes[ch].best.rc.esc_bps[p] = (int)bitreader.Readbits(5);
                    for (int i = n; i > 0; i--)
                    {
                        *(r++) = bitreader.Readbits_signed((int)k);
                    }
                }
                else
                {
                    bitreader.Read_rice_block(n, (int)k, r);
                    r += n;
                }
                j += n;
            }
        }
Ejemplo n.º 2
0
        unsafe void Decode_subframe_lpc(BitReader bitreader, FlacFrame frame, int ch)
        {
            // warm-up samples
            int obits = frame.subframes[ch].obits;

            for (int i = 0; i < frame.subframes[ch].best.order; i++)
            {
                frame.subframes[ch].best.residual[i] = bitreader.Readbits_signed(obits);
            }

            // LPC coefficients
            frame.subframes[ch].best.cbits = (int)bitreader.Readbits(4) + 1;             // lpc_precision
            frame.subframes[ch].best.shift = bitreader.Readbits_signed(5);
            if (frame.subframes[ch].best.shift < 0)
            {
                throw new Exception("negative shift");
            }
            for (int i = 0; i < frame.subframes[ch].best.order; i++)
            {
                frame.subframes[ch].best.coefs[i] = bitreader.Readbits_signed(frame.subframes[ch].best.cbits);
            }

            // residual
            Decode_residual(bitreader, frame, ch);
        }
Ejemplo n.º 3
0
        public unsafe int DecodeFrame(byte[] buffer, int pos, int len)
        {
            fixed(byte *buf = buffer)
            {
                framereader.Reset(buf, pos, len);
                Decode_frame_header(framereader, frame);
                Decode_subframes(framereader, frame);
                framereader.Flush();
                ushort crc_1 = DoCRC ? crc16.ComputeChecksum(framereader.Buffer + pos, framereader.Position - pos) : (ushort)0;
                ushort crc_2 = (ushort)framereader.Readbits(16);

                if (DoCRC && crc_1 != crc_2)
                {
                    throw new Exception("frame crc mismatch");
                }
                Restore_samples(frame);
                _samplesInBuffer = frame.blocksize;
                return(framereader.Position - pos);
            }
        }
Ejemplo n.º 4
0
        unsafe void Decode_metadata()
        {
            byte x;
            int  i, id;

            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])
                {
                    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);
                        Length = (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;
        }
Ejemplo n.º 5
0
        unsafe void Decode_subframes(BitReader bitreader, FlacFrame frame)
        {
            fixed(int *r = residualBuffer, s = Samples)
            for (int ch = 0; ch < PCM.ChannelCount; ch++)
            {
                // subframe header
                uint t1 = bitreader.Readbit();                 // ?????? == 0

                if (t1 != 0)
                {
                    throw new Exception("unsupported subframe coding (ch == " + ch.ToString() + ")");
                }
                int type_code = (int)bitreader.Readbits(6);

                frame.subframes[ch].wbits = (int)bitreader.Readbit();
                if (frame.subframes[ch].wbits != 0)
                {
                    frame.subframes[ch].wbits += (int)bitreader.Read_unary();
                }

                frame.subframes[ch].obits = PCM.BitsPerSample - frame.subframes[ch].wbits;
                switch (frame.ch_mode)
                {
                case ChannelMode.MidSide: frame.subframes[ch].obits += ch; break;

                case ChannelMode.LeftSide: frame.subframes[ch].obits += ch; break;

                case ChannelMode.RightSide: frame.subframes[ch].obits += 1 - ch; break;
                }

                frame.subframes[ch].best.type  = (SubframeType)type_code;
                frame.subframes[ch].best.order = 0;

                if ((type_code & (uint)SubframeType.LPC) != 0)
                {
                    frame.subframes[ch].best.order = (type_code - (int)SubframeType.LPC) + 1;
                    frame.subframes[ch].best.type  = SubframeType.LPC;
                }
                else if ((type_code & (uint)SubframeType.Fixed) != 0)
                {
                    frame.subframes[ch].best.order = (type_code - (int)SubframeType.Fixed);
                    frame.subframes[ch].best.type  = SubframeType.Fixed;
                }

                frame.subframes[ch].best.residual = r + ch * Flake.MAX_BLOCKSIZE;
                frame.subframes[ch].samples       = s + ch * Flake.MAX_BLOCKSIZE;

                // subframe
                switch (frame.subframes[ch].best.type)
                {
                case SubframeType.Constant:
                    Decode_subframe_constant(bitreader, frame, ch);
                    break;

                case SubframeType.Verbatim:
                    Decode_subframe_verbatim(bitreader, frame, ch);
                    break;

                case SubframeType.Fixed:
                    Decode_subframe_fixed(bitreader, frame, ch);
                    break;

                case SubframeType.LPC:
                    Decode_subframe_lpc(bitreader, frame, ch);
                    break;

                default:
                    throw new Exception("invalid subframe type");
                }
            }
        }
Ejemplo n.º 6
0
        unsafe void Decode_frame_header(BitReader bitreader, FlacFrame frame)
        {
            int header_start = bitreader.Position;

            if (bitreader.Readbits(15) != 0x7FFC)
            {
                throw new Exception("invalid frame");
            }
            uint vbs = bitreader.Readbit();

            frame.bs_code0 = (int)bitreader.Readbits(4);
            uint sr_code0 = bitreader.Readbits(4);

            frame.ch_mode = (ChannelMode)bitreader.Readbits(4);
            uint bps_code = bitreader.Readbits(3);

            if (Flake.flac_bitdepths[bps_code] != PCM.BitsPerSample)
            {
                throw new Exception("unsupported bps coding");
            }
            uint t1 = bitreader.Readbit();             // == 0?????

            if (t1 != 0)
            {
                throw new Exception("unsupported frame coding");
            }
            frame.frame_number = (int)bitreader.Read_utf8();

            // custom block size
            if (frame.bs_code0 == 6)
            {
                frame.bs_code1  = (int)bitreader.Readbits(8);
                frame.blocksize = frame.bs_code1 + 1;
            }
            else if (frame.bs_code0 == 7)
            {
                frame.bs_code1  = (int)bitreader.Readbits(16);
                frame.blocksize = frame.bs_code1 + 1;
            }
            else
            {
                frame.blocksize = Flake.flac_blocksizes[frame.bs_code0];
            }

            // custom sample rate
            if (sr_code0 < 4 || sr_code0 > 11)
            {
                // sr_code0 == 12 -> sr == bitreader.readbits(8) * 1000;
                // sr_code0 == 13 -> sr == bitreader.readbits(16);
                // sr_code0 == 14 -> sr == bitreader.readbits(16) * 10;
                throw new Exception("invalid sample rate mode");
            }

            int frame_channels = (int)frame.ch_mode + 1;

            if (frame_channels > 11)
            {
                throw new Exception("invalid channel mode");
            }
            if (frame_channels == 2 || frame_channels > 8)             // Mid/Left/Right Side Stereo
            {
                frame_channels = 2;
            }
            else
            {
                frame.ch_mode = ChannelMode.NotStereo;
            }
            if (frame_channels != PCM.ChannelCount)
            {
                throw new Exception("invalid channel mode");
            }

            // CRC-8 of frame header
            byte crc = DoCRC ? crc8.ComputeChecksum(bitreader.Buffer, header_start, bitreader.Position - header_start) : (byte)0;

            frame.crc8 = (byte)bitreader.Readbits(8);
            if (DoCRC && frame.crc8 != crc)
            {
                throw new Exception("header crc mismatch");
            }
        }