Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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;
            }
        }
Ejemplo n.º 3
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
        }
Ejemplo n.º 4
0
        public unsafe static 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 & 0x20) != 0) //100000 = 0x20
            {
                order    = (int)(subframeType & 0x1F) + 1;
                subFrame = new FlacSubFrameLPC(reader, header, data, bitsPerSample, order);
            }
            else if ((subframeType & 0x08) != 0) //001000 = 0x08
            {
                order = (int)(subframeType & 0x07);
                if (order > 4)
                {
                    return(null);
                }
                subFrame = new FlacSubFrameFixed(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);
        }
Ejemplo n.º 5
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);

            if (coefPrecision == 0x0F)
            {
                throw new FlacException("Invalid \"quantized linear predictor coefficients' precision in bits\" was invalid. Must not be 0x0F.",
                                        FlacLayer.SubFrame);
            }
            coefPrecision += 1;

            int shiftNeeded = reader.ReadBitsSigned(5);

            if (shiftNeeded < 0)
            {
                throw new FlacException("'\"Quantized linear predictor coefficient shift needed in bits\" 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
        }