예제 #1
0
        unsafe void restore_samples_fixed(FlacFrame frame, int ch)
        {
            FlacSubframeInfo sub = frame.subframes[ch];

            AudioSamples.MemCpy(sub.samples, sub.best.residual, sub.best.order);
            int *data = sub.samples + sub.best.order;
            int *residual = sub.best.residual + sub.best.order;
            int  data_len = frame.blocksize - sub.best.order;
            int  s0, s1, s2;

            switch (sub.best.order)
            {
            case 0:
                AudioSamples.MemCpy(data, residual, data_len);
                break;

            case 1:
                s1 = data[-1];
                for (int i = data_len; i > 0; i--)
                {
                    s1       += *(residual++);
                    *(data++) = s1;
                }
                //data[i] = residual[i] + data[i - 1];
                break;

            case 2:
                s2 = data[-2];
                s1 = data[-1];
                for (int i = data_len; i > 0; i--)
                {
                    s0        = *(residual++) + (s1 << 1) - s2;
                    *(data++) = s0;
                    s2        = s1;
                    s1        = s0;
                }
                //data[i] = residual[i] + data[i - 1] * 2  - data[i - 2];
                break;

            case 3:
                for (int i = 0; i < data_len; i++)
                {
                    data[i] = residual[i] + (((data[i - 1] - data[i - 2]) << 1) + (data[i - 1] - data[i - 2])) + data[i - 3];
                }
                break;

            case 4:
                for (int i = 0; i < data_len; i++)
                {
                    data[i] = residual[i] + ((data[i - 1] + data[i - 3]) << 2) - ((data[i - 2] << 2) + (data[i - 2] << 1)) - data[i - 4];
                }
                break;
            }
        }
예제 #2
0
        unsafe void decode_subframe_fixed(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);
            }

            // residual
            decode_residual(bitreader, frame, ch);
        }
예제 #3
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;
            }
        }
예제 #4
0
        unsafe void restore_samples_lpc(FlacFrame frame, int ch)
        {
            FlacSubframeInfo sub  = frame.subframes[ch];
            ulong            csum = 0;

            fixed(int *coefs = sub.best.coefs)
            {
                for (int i = sub.best.order; i > 0; i--)
                {
                    csum += (ulong)Math.Abs(coefs[i - 1]);
                }
                if ((csum << sub.obits) >= 1UL << 32)
                {
                    lpc.decode_residual_long(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift);
                }
                else
                {
                    lpc.decode_residual(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift);
                }
            }
        }
예제 #5
0
        public AudioDecoder(DecoderSettings settings, string path, Stream IO = null)
        {
            m_settings = settings;

            _path = path;
            _IO   = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000);

            crc8 = new Crc8();

            _framesBuffer = new byte[0x20000];
            decode_metadata();

            frame       = new FlacFrame(PCM.ChannelCount);
            framereader = new BitReader();

            //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3);
            if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length)
            {
                byte[] temp = _framesBuffer;
                _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)];
                if (_framesBufferLength > 0)
                {
                    Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength);
                }
                _framesBufferOffset = 0;
            }
            _samplesInBuffer = 0;

            if (PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24)
            {
                throw new Exception("invalid flac file");
            }

            samplesBuffer  = new int[FlakeConstants.MAX_BLOCKSIZE * PCM.ChannelCount];
            residualBuffer = new int[FlakeConstants.MAX_BLOCKSIZE * PCM.ChannelCount];
        }
예제 #6
0
        unsafe void restore_samples(FlacFrame frame)
        {
            for (int ch = 0; ch < PCM.ChannelCount; ch++)
            {
                switch (frame.subframes[ch].best.type)
                {
                case SubframeType.Constant:
                    AudioSamples.MemSet(frame.subframes[ch].samples, frame.subframes[ch].best.residual[0], frame.blocksize);
                    break;

                case SubframeType.Verbatim:
                    AudioSamples.MemCpy(frame.subframes[ch].samples, frame.subframes[ch].best.residual, frame.blocksize);
                    break;

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

                case SubframeType.LPC:
                    restore_samples_lpc(frame, ch);
                    break;
                }
                if (frame.subframes[ch].wbits != 0)
                {
                    int *s = frame.subframes[ch].samples;
                    int  x = (int)frame.subframes[ch].wbits;
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        *(s++) <<= x;
                    }
                }
            }
            if (frame.ch_mode != ChannelMode.NotStereo)
            {
                int *l = frame.subframes[0].samples;
                int *r = frame.subframes[1].samples;
                switch (frame.ch_mode)
                {
                case ChannelMode.LeftRight:
                    break;

                case ChannelMode.MidSide:
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        int mid  = *l;
                        int side = *r;
                        mid  <<= 1;
                        mid   |= (side & 1);                               /* i.e. if 'side' is odd... */
                        *(l++) = (mid + side) >> 1;
                        *(r++) = (mid - side) >> 1;
                    }
                    break;

                case ChannelMode.LeftSide:
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        int _l = *(l++), _r = *r;
                        *(r++) = _l - _r;
                    }
                    break;

                case ChannelMode.RightSide:
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        *(l++) += *(r++);
                    }
                    break;
                }
            }
        }
예제 #7
0
        unsafe void decode_subframes(BitReader bitreader, FlacFrame frame)
        {
            fixed(int *r = residualBuffer, s = samplesBuffer)
            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 * FlakeConstants.MAX_BLOCKSIZE;
                frame.subframes[ch].samples       = s + ch * FlakeConstants.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");
                }
            }
        }
예제 #8
0
        unsafe void decode_subframe_constant(BitReader bitreader, FlacFrame frame, int ch)
        {
            int obits = frame.subframes[ch].obits;

            frame.subframes[ch].best.residual[0] = bitreader.readbits_signed(obits);
        }
예제 #9
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 (FlakeConstants.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 = FlakeConstants.flac_blocksizes[frame.bs_code0];
            }

            // custom sample rate
            if (sr_code0 < 1 || 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 = do_crc ? crc8.ComputeChecksum(bitreader.Buffer, header_start, bitreader.Position - header_start) : (byte)0;

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