Exemplo n.º 1
0
        private unsafe void RestoreSignal(FlacSubFrameData subframeData, int length, int order)
        {
            //see ftp://svr-ftp.eng.cam.ac.uk/pub/reports/auto-pdf/robinson_tr156.pdf chapter 3.2
            int* residual = subframeData.ResidualBuffer + order;
            int* destBuffer = subframeData.DestinationBuffer + order;

            switch (order)
            {
                case 0:
                    for (int i = 0; i < length; i++)
                    {
                        destBuffer[i] = residual[i];
                    }
                    //ILUtils.MemoryCopy(data, residual, length);
                    break;

                case 1:
                    for (int i = 0; i < length; i++)
                    {
                        //s(t-1)
                        destBuffer[i] = residual[i] + destBuffer[i - 1];
                    }
                    break;

                case 2:
                    for (int i = 0; i < length; i++)
                    {
                        //2s(t-1) - s(t-2)
                        destBuffer[i] = residual[i] + 2 * destBuffer[i - 1] - destBuffer[i - 2];
                    }

                    break;

                case 3:
                    for (int t = 0; t < length; t++)
                    {
                        //3s(t-1) - 3s(t-2) + s(t-3)
                        destBuffer[t] = residual[t] +
                            3 * (destBuffer[t - 1]) - 3 * (destBuffer[t - 2]) + destBuffer[t - 3];
                    }
                    break;

                case 4:
                    //"FLAC adds a fourth-order predictor to the zero-to-third-order predictors used by Shorten." (see https://xiph.org/flac/format.html#prediction)
                    for (int t = 0; t < length; t++)
                    {
                        destBuffer[t] = residual[t] +
                            4 * destBuffer[t - 1] - 6 * destBuffer[t - 2] + 4 * destBuffer[t - 3] - destBuffer[t - 4];
                    }
                    break;

                default:
                    Debug.WriteLine("Invalid FlacFixedSubFrame predictororder.");
                    return;
            }
        }
Exemplo n.º 2
0
        public unsafe FlacSubFrameLPC(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps, int order)
            : base(header)
        {
            //warmup
            _warmup = new int[FlacConstant.MAX_LPC_ORDER];
            for (int i = 0; i < order; i++)
            {
                _warmup[i] = data.residualBuffer[i] = reader.ReadBitsSigned(bps);
            }

            //header
            int u32 = (int)reader.ReadBits(FlacConstant.SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN);
            if (u32 == (1 << FlacConstant.SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1)
            {
                Debug.WriteLine("Invalid FlacLPC qlp coeff precision.");
                return; //return false;
            }
            _qlpCoeffPrecision = u32 + 1;

            int level = reader.ReadBitsSigned(FlacConstant.SUBFRAME_LPC_QLP_SHIFT_LEN);
            if (level < 0)
                throw new Exception("negative shift");
            _lpcShiftNeeded = level;

            _qlpCoeffs = new int[FlacConstant.MAX_LPC_ORDER];

            //qlp coeffs
            for (int i = 0; i < order; i++)
            {
                _qlpCoeffs[i] = reader.ReadBitsSigned(_qlpCoeffPrecision);
            }

            //QLPCoeffs = coeffs;

            Residual = new FlacResidual(reader, header, data, order);

            for (int i = 0; i < order; i++)
            {
                data.destBuffer[i] = data.residualBuffer[i];
            }

            if (bps + _qlpCoeffPrecision + CSMath.ILog(order) <= 32)
            {
                if (bps <= 16 && _qlpCoeffPrecision <= 16)
                    RestoreLPCSignal(data.residualBuffer + order, data.destBuffer + order, header.BlockSize - order, order); //Restore(data.residualBuffer + order, data.destBuffer, Header.BlockSize - order, order, order);
                else
                    RestoreLPCSignal(data.residualBuffer + order, data.destBuffer + order, header.BlockSize - order, order);
            }
            else
            {
                RestoreLPCSignalWide(data.residualBuffer + order, data.destBuffer + order, header.BlockSize - order, order);//RestoreWide(data.residualBuffer + order, data.destBuffer, Header.BlockSize - order, order, order);
            }

            //Warmup = warmup;
        }
Exemplo n.º 3
0
        public unsafe FlacSubFrameFixed(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bps, int order)
            : base(header)
        {
            for (int i = 0; i < order; i++)
            {
                data.residualBuffer[i] = data.destBuffer[i] = reader.ReadBitsSigned(bps);
            }

            Residual = new FlacResidual(reader, header, data, order);
            RestoreSignal(data, header.BlockSize - order, order);
        }
Exemplo n.º 4
0
        public unsafe FlacSubFrameLPC(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bitsPerSample, int order)
            : base(header)
        {
            var warmup = new int[order];
            for (int i = 0; i < order; i++)
            {
                warmup[i] = data.ResidualBuffer[i] = reader.ReadBitsSigned(bitsPerSample);
            }

            int coefPrecision = (int)reader.ReadBits(4) + 1;
            if (coefPrecision == 0x0F)
            {
                Debug.WriteLine("Invalid linear predictor coefficients' precision. Must not be 0x0F.");
                return;
            }

            int shiftNeeded = reader.ReadBitsSigned(5);
            if (shiftNeeded < 0)
                throw new FlacException("\"Quantized linear predictor coefficient shift needed.\" was negative.", FlacLayer.SubFrame);

            var q = new int[order];
            for (int i = 0; i < order; i++)
            {
                q[i] = reader.ReadBitsSigned(coefPrecision);
            }

            //decode the residual
            var residual = new FlacResidual(reader, header, data, order);
            for (int i = 0; i < order; i++)
            {
                data.DestinationBuffer[i] = data.ResidualBuffer[i];
            }

            int* residualBuffer0 = data.ResidualBuffer + order;
            int* destinationBuffer0 = data.DestinationBuffer + order;
            int blockSizeToProcess = header.BlockSize - order;

            if (bitsPerSample + coefPrecision + Log2(order) <= 32)
            {
                RestoreLPCSignal32(residualBuffer0, destinationBuffer0, blockSizeToProcess, order, q, shiftNeeded);
            }
            else
            {
                RestoreLPCSignal64(residualBuffer0, destinationBuffer0, blockSizeToProcess, order, q, shiftNeeded);
            }

            #if FLAC_DEBUG
            QLPCoeffPrecision = coefPrecision;
            LPCShiftNeeded = shiftNeeded;
            Warmup = warmup;
            Residual = residual;
            QLPCoeffs = q;
            #endif
        }
Exemplo n.º 5
0
        public unsafe FlacSubFrameFixed(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int bitsPerSample, int order)
            : base(header)
        {
            for (int i = 0; i < order; i++) //order = predictor order
            {
                data.ResidualBuffer[i] = data.DestinationBuffer[i] = reader.ReadBitsSigned(bitsPerSample);
            }

            var residual = new FlacResidual(reader, header, data, order); //necessary for decoding
            RestoreSignal(data, header.BlockSize - order, order);

            #if FLAC_DEBUG
            Residual = residual;
            #endif
        }
Exemplo n.º 6
0
        public unsafe bool ProcessResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order)
        {
            data.Content.UpdateSize(PartitionOrder);

            int porder = PartitionOrder;
            FlacEntropyCoding codingMethod = CodingMethod;

            int psize = header.BlockSize >> porder;
            int res_cnt = psize - order;

            int ricelength = 4 + (int)codingMethod; //4bit = RICE I | 5bit = RICE II

            //residual
            int j = order;
            int* r = data.residualBuffer + j;

            int partitioncount = 1 << porder;

            for (int p = 0; p < partitioncount; p++)
            {
                if (p == 1) res_cnt = psize;
                int n = Math.Min(res_cnt, header.BlockSize - j);

                int k = Content.parameters[p] = (int)reader.ReadBits(ricelength);
                if (k == (1 << ricelength) - 1)
                {
                    k = (int)reader.ReadBits(5);
                    for (int i = n; i > 0; i--)
                    {
                        *(r) = reader.ReadBitsSigned((int)k);
                    }
                }
                else
                {
                    ReadFlacRiceBlock(reader, n, (int)k, r);
                    r += n;
                }
                j += n;
            }

            return true;
        }
Exemplo n.º 7
0
        //http://www.hpl.hp.com/techreports/1999/HPL-1999-144.pdf
        private unsafe bool RestoreSignal(FlacSubFrameData subframeData, int length, int predictorOrder)
        {
            int* residual = subframeData.residualBuffer + predictorOrder;
            int* data = subframeData.destBuffer + predictorOrder;

            int t0, t1, t2; //temp

            switch (predictorOrder)
            {
                case 0:
                    for (int i = 0; i < length; i++)
                    {
                        *(data++) = *(residual++);
                    }
                    break;

                case 1:
                    t1 = data[-1];
                    for (int i = 0; i < length; i++)
                    {
                        t1 += *(residual++);
                        *(data++) = t1;
                    }
                    break;

                case 2:
                    t2 = data[-2];
                    t1 = data[-1];
                    for (int i = 0; i < length; i++)
                    {
                        *(data++) = t0 = ((t1 << 1) + *(residual++)) - t2;
                        t2 = t1;
                        t1 = t0;
                    }
                    break;

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

                        data++;
                        residual++;
                    }
                    break;

                case 4:
                    for (int i = 0; i < length; i++)
                    {
                        *(data) = *(residual) +
                                    ((data[-1] + data[-3]) << 2) -
                                    ((data[-2] << 2) + (data[-2] << 1)) -
                                    data[-4];

                        data++;
                        residual++;
                    }
                    break;

                default:
                    Debug.WriteLine("Invalid FlacFixedSubFrame predictororder.");
                    return false;
            }

            return true;
        }
Exemplo n.º 8
0
        public static unsafe FlacSubFrameBase GetSubFrame(FlacBitReader reader, FlacSubFrameData data, FlacFrameHeader header, int bitsPerSample)
        {
            int wastedBits = 0, order;

            uint firstByte = reader.ReadBits(8);

            if ((firstByte & 0x80) != 0) //Zero bit padding, to prevent sync-fooling string of 1s
            {
                Debug.WriteLine("Flacdecoder subframe-header got no zero-bit padding.");
                return null;
            }

            bool hasWastedBits = (firstByte & 1) != 0; //Wasted bits-per-sample' flag
            if (hasWastedBits)
            {
                int k = (int)reader.ReadUnary();
                wastedBits = k + 1; //"k-1" follows -> add 1
                bitsPerSample -= wastedBits;
            }

            FlacSubFrameBase subFrame;
            var subframeType = (firstByte & 0x7E) >> 1; //0111 1110

            if (subframeType == 0) //000000
            {
                subFrame = new FlacSubFrameConstant(reader, header, data, bitsPerSample);
            }
            else if (subframeType == 1) //000001
            {
                subFrame = new FlacSubFrameVerbatim(reader, header, data, bitsPerSample);
            }
            else if ((subframeType & 0x08) != 0) //001000 = 0x08
            {
                order = (int) (subframeType & 0x07);
                subFrame = new FlacSubFrameFixed(reader, header, data, bitsPerSample, order);
            }
            else if ((subframeType & 0x20) != 0) //100000 = 0x20
            {
                order = (int) (subframeType & 0x1F) + 1;
                subFrame = new FlacSubFrameLPC(reader, header, data, bitsPerSample, order);
            }
            else
            {
                Debug.WriteLine(String.Format("Invalid Flac-SubframeType. SubframeType: 0x{0:x}.", subframeType));
                return null;
            }

            if (hasWastedBits)
            {
                int* destination = data.DestinationBuffer;
                for (int i = 0; i < header.BlockSize; i++)
                {
                    *(destination++) <<= wastedBits;
                }
            }

            #if FLAC_DEBUG
            subFrame.WastedBits = wastedBits;
            #endif
            return subFrame;
        }
Exemplo n.º 9
0
        private unsafe List<FlacSubFrameData> AllocOuputMemory()
        {
            if (_destBuffer == null || _destBuffer.Length < (Header.Channels * Header.BlockSize))
                _destBuffer = new int[Header.Channels * Header.BlockSize];
            if (_residualBuffer == null || _residualBuffer.Length < (Header.Channels * Header.BlockSize))
                _residualBuffer = new int[Header.Channels * Header.BlockSize];

            List<FlacSubFrameData> output = new List<FlacSubFrameData>();

            for (int c = 0; c < Header.Channels; c++)
            {
                fixed (int* ptrDestBuffer = _destBuffer, ptrResidualBuffer = _residualBuffer)
                {
                    _handle1 = GCHandle.Alloc(_destBuffer, GCHandleType.Pinned);
                    _handle2 = GCHandle.Alloc(_residualBuffer, GCHandleType.Pinned);

                    FlacSubFrameData data = new FlacSubFrameData
                    {
                        DestinationBuffer = (ptrDestBuffer + c * Header.BlockSize),
                        ResidualBuffer = (ptrResidualBuffer + c * Header.BlockSize)
                    };
                    output.Add(data);
                }
            }

            return output;
        }
Exemplo n.º 10
0
        public static unsafe FlacSubFrameBase GetSubFrame(FlacBitReader reader, FlacSubFrameData data, FlacFrameHeader header, int bps)
        {
            uint x;
            int wastedBits = 0, totalBits = 0, order = 0;

            x = reader.ReadBits(8);
            bool haswastedBits = (x & 1) != 0;
            x &= 0xFE; //1111 1110

            if (haswastedBits)
            {
                int u = (int)reader.ReadUnary();
                wastedBits = u + 1;
                bps -= wastedBits;
                totalBits = bps;
            }

            if ((x & 0x80) != 0)
            {
                Debug.WriteLine("Flacdecoder lost sync while reading FlacSubFrameHeader. [x & 0x80].");
                return null;
            }

            FlacSubFrameBase subFrame = null;

            if ((x > 2 && x < 16) ||
                 (x > 24 && x < 64))
            {
                Debug.WriteLine("Invalid FlacSubFrameHeader. [" + x.ToString("x") + "]");
                return null;
            }
            else if (x == 0)
            {
                subFrame = new FlacSubFrameConstant(reader, header, data, bps);
            }
            else if (x == 2)
            {
                //verbatim
                subFrame = new FlacSubFrameVerbatim(reader, header, data, bps);
            }
            else if (x >= 16 && x <= 24)
            {
                //fixed
                order = (int)((x >> 1) & 7);
                subFrame = new FlacSubFrameFixed(reader, header, data, bps, order);
            }
            else if (x >= 64)
            {
                //lpc
                order = (int)(((x >> 1) & 31) + 1);
                subFrame = new FlacSubFrameLPC(reader, header, data, bps, order);
            }
            else
            {
                Debug.WriteLine("Invalid Flac-SubframeType: x = " + x + ".");
                return null;
            }

            if (haswastedBits)
            {
                int* ptrDest = data.destBuffer;
                for (int i = 0; i < header.BlockSize; i++)
                {
                    *(ptrDest++) <<= wastedBits;
                }
            }

            //System.Diagnostics.Debug.WriteLine(subFrame.GetType().Name);

            if (subFrame != null)
                subFrame.WastedBits = wastedBits;
            else
                Debug.WriteLine("Unknown error while reading FlacSubFrameHeader");

            return subFrame;
        }
Exemplo n.º 11
0
        private unsafe List<FlacSubFrameData> AllocOuputMemory()
        {
            if (destBuffer == null || destBuffer.Length < (Header.Channels * Header.BlockSize))
                destBuffer = new int[Header.Channels * Header.BlockSize];
            if (residualBuffer == null || residualBuffer.Length < (Header.Channels * Header.BlockSize))
                residualBuffer = new int[Header.Channels * Header.BlockSize];

            List<FlacSubFrameData> output = new List<FlacSubFrameData>();

            for (int c = 0; c < Header.Channels; c++)
            {
                fixed (int* ptrDestBuffer = destBuffer, ptrResidualBuffer = residualBuffer)
                {
                    handle1 = GCHandle.Alloc(destBuffer, GCHandleType.Pinned);
                    handle2 = GCHandle.Alloc(residualBuffer, GCHandleType.Pinned);

                    FlacSubFrameData data = new FlacSubFrameData();
                    data.destBuffer = (ptrDestBuffer + c * Header.BlockSize);
                    data.residualBuffer = (ptrResidualBuffer + c * Header.BlockSize);
                    output.Add(data);
                }
            }

            return output;
        }