////------------------------------------------------------------------------------------------------------------------------------ public static FlacRicePartition Read(StreamBuffer sb, int partitionNumber, int partitionOrder, int predictOrder, int blockSize, FlacResidualCodingMethod codingMethod) { FlacRicePartition ricePartition = new FlacRicePartition { _riceParameter = sb.ReadBigEndianInt32(), _codingMethod = codingMethod }; int riceParameter = ricePartition._riceParameter & ((codingMethod == FlacResidualCodingMethod.PartitionedRice) ? 0x1F : 0xF); if (partitionOrder == 0) ricePartition.Samples = blockSize - predictOrder; else if (partitionNumber == 0) ricePartition.Samples = (blockSize >> partitionOrder) - predictOrder; else ricePartition.Samples = blockSize >> partitionOrder; ricePartition.Residuals = new int[ricePartition.Samples]; if ((riceParameter < 0xF) || ((codingMethod == FlacResidualCodingMethod.PartitionedRice2) && (riceParameter < 0x1F))) { for (int i = 0; i < ricePartition.Samples; i++) { long msbs = sb.ReadUnaryInt(); long lsbs = sb.ReadBigEndianInt32() & (0xFFFFFFFF >> (32 - riceParameter)); long value = (msbs << riceParameter) | lsbs; ricePartition.Residuals[i] = ((value & 0x01) == 0x01) ? -((int)(value >> 1)) - 1 : (int)(value >> 1); } } else { // residuals in unencoded form, sample size read from the next 5 // bits in the stream. int size = sb.ReadBigEndianInt32(); for (int i = 0; i < ricePartition.Samples; i++) ricePartition.Residuals[i] = sb.ReadBigEndianInt32(); } return ricePartition; }
public static unsafe void ProcessResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order, int partitionOrder, FlacResidualCodingMethod codingMethod) { data.Content.UpdateSize(partitionOrder); bool isRice2 = codingMethod == FlacResidualCodingMethod.PartitionedRice2; int riceParameterLength = isRice2 ? 5 : 4; int escapeCode = isRice2 ? 31 : 15; //11111 : 1111 int samplesPerPartition; int partitionCount = 1 << partitionOrder; //2^partitionOrder -> There will be 2^order partitions. -> "order" = partitionOrder in this case int* residualBuffer = data.ResidualBuffer + order; for (int p = 0; p < partitionCount; p++) { 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 (int i = 0; i < samplesPerPartition; i++) { int sample = reader.ReadBitsSigned((int)raw); *(residualBuffer) = sample; residualBuffer++; } } else { ReadFlacRiceBlock(reader, samplesPerPartition, (int)riceParameter, residualBuffer); residualBuffer += samplesPerPartition; } } }
public FlacResidual(FlacBitReader reader, FlacFrameHeader header, FlacSubFrameData data, int order) { FlacResidualCodingMethod codingMethod = (FlacResidualCodingMethod)reader.ReadBits(2); // 2 Bit if (codingMethod == FlacResidualCodingMethod.PartitionedRice || codingMethod == FlacResidualCodingMethod.PartitionedRice2) { int partitionOrder = (int)reader.ReadBits(4); //"Partition order." see https://xiph.org/flac/format.html#partitioned_rice and https://xiph.org/flac/format.html#partitioned_rice2 FlacPartitionedRice.ProcessResidual(reader, header, data, order, partitionOrder, codingMethod); #if FLAC_DEBUG CodingMethodMethod = codingMethod; PartitionOrder = partitionOrder; #endif } else { throw new FlacException("Not supported RICE-Coding-Method. Stream unparseable!", FlacLayer.SubFrame); } }