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]; var output = new List<FlacSubFrameData>(); for (var c = 0; c < Header.Channels; c++) { fixed (int* ptrDestBuffer = _destBuffer, ptrResidualBuffer = _residualBuffer) { _handle1 = GCHandle.Alloc(_destBuffer, GCHandleType.Pinned); _handle2 = GCHandle.Alloc(_residualBuffer, GCHandleType.Pinned); var data = new FlacSubFrameData { DestinationBuffer = _destBuffer.AsMemory(c * Header.BlockSize), ResidualBuffer = _residualBuffer.AsMemory(c * Header.BlockSize) }; output.Add(data); } } return output; }
public static void ProcessResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order, int partitionOrder, FlacResidualCodingMethod codingMethod) { data.Content.UpdateSize(partitionOrder); var isRice2 = codingMethod == FlacResidualCodingMethod.PartitionedRice2; var riceParameterLength = isRice2 ? 5 : 4; var escapeCode = isRice2 ? 31 : 15; //11111 : 1111 var partitionCount = 1 << partitionOrder; //2^partitionOrder -> There will be 2^order partitions. -> "order" = partitionOrder in this case var residualBuffer = data.ResidualBuffer.Span.Slice(order); for (var p = 0; p < partitionCount; p++) { int samplesPerPartition; if (partitionOrder == 0) { samplesPerPartition = header.BlockSize - order; } else if (p > 0) { samplesPerPartition = header.BlockSize >> partitionOrder; } else { samplesPerPartition = (header.BlockSize >> partitionOrder) - order; } var riceParameter = reader.ReadBits(riceParameterLength); data.Content.Parameters[p] = (int)riceParameter; if (riceParameter >= escapeCode) { var raw = reader.ReadBits(5); //raw is always 5 bits (see ...(+5)) data.Content.RawBits[p] = (int)raw; for (var i = 0; i < samplesPerPartition; i++) { var sample = reader.ReadBitsSigned((int)raw); residualBuffer[i] = sample; } } else { ReadFlacRiceBlock(reader, samplesPerPartition, (int)riceParameter, residualBuffer); } residualBuffer = residualBuffer.Slice(samplesPerPartition); } }