private IEnumerator <int> ReadResidualData(FlacBitStreamReader bitReader, int blockSize, int predictorOrder) { const byte RiceCodingWith4BitParameter = 0; const byte RiceCodingWith5BitParameter = 1; uint residualRiceParamSizeType = bitReader.ReadBits(2); int residualRiceParamSize; if (residualRiceParamSizeType == RiceCodingWith4BitParameter) { residualRiceParamSize = 4; } else if (residualRiceParamSizeType == RiceCodingWith5BitParameter) { residualRiceParamSize = 5; } else { throw new FlacException("Reserved residual coding method"); } // rice and rice2 almost the same // read rice partitined method int partitionOrder = (int)bitReader.ReadBits(4); int partitionCount = 1 << partitionOrder; int sampleCount = blockSize >> partitionOrder; if (sampleCount < predictorOrder || sampleCount < 1 || (sampleCount << partitionOrder) != blockSize) { throw new FlacException("Invalid partition order"); } for (int i = 0; i < partitionCount; i++) { int skipSamples = i == 0 ? predictorOrder : 0; int riceParameter = (int)bitReader.ReadBits(residualRiceParamSize); if (riceParameter + 1 == 1 << residualRiceParamSize) { // escape mode int bitsPerSample = (int)bitReader.ReadBits(5); for (int j = skipSamples; j < sampleCount; j++) { yield return(bitReader.ReadSignedBits(bitsPerSample)); } } else { int maxRiceK = int.MaxValue >> riceParameter; for (int j = skipSamples; j < sampleCount; j++) { yield return(bitReader.ReadRice(riceParameter)); } } } }
private IEnumerator<int> ReadResidualData(FlacBitStreamReader bitReader, int blockSize, int predictorOrder) { const byte RiceCodingWith4BitParameter = 0; const byte RiceCodingWith5BitParameter = 1; uint residualRiceParamSizeType = bitReader.ReadBits(2); int residualRiceParamSize; if (residualRiceParamSizeType == RiceCodingWith4BitParameter) residualRiceParamSize = 4; else if (residualRiceParamSizeType == RiceCodingWith5BitParameter) residualRiceParamSize = 5; else throw new FlacException("Reserved residual coding method"); // rice and rice2 almost the same // read rice partitined method int partitionOrder = (int)bitReader.ReadBits(4); int partitionCount = 1 << partitionOrder; int sampleCount = blockSize >> partitionOrder; if (sampleCount < predictorOrder || sampleCount < 1 || (sampleCount << partitionOrder) != blockSize ) throw new FlacException("Invalid partition order"); for (int i = 0; i < partitionCount; i++) { int skipSamples = i == 0 ? predictorOrder : 0; int riceParameter = (int)bitReader.ReadBits(residualRiceParamSize); if (riceParameter + 1 == 1 << residualRiceParamSize) { // escape mode int bitsPerSample = (int)bitReader.ReadBits(5); for (int j = skipSamples; j < sampleCount; j++) { yield return bitReader.ReadSignedBits(bitsPerSample); } } else { int maxRiceK = int.MaxValue >> riceParameter; for (int j = skipSamples; j < sampleCount; j++) { yield return bitReader.ReadRice(riceParameter); } } } }
private void ReadSubframe() { uint zeroPadding = bitReader.ReadBits(1); if (zeroPadding != 0) { throw new FlacException("Subframe zero padding is not zero"); } int subframeType = (int)bitReader.ReadBits(6); SubframeType type; int order = 0; if (subframeType == FlacCommons.ConstantSubframeType) { type = SubframeType.SubframeConstant; } else if (subframeType == FlacCommons.VerbatimSubframeType) { type = SubframeType.SubframeVerbatim; } else if (FlacCommons.FixedSubframeTypeStart <= subframeType && subframeType <= FlacCommons.FixedSubframeTypeEnd) { type = SubframeType.SubframeFixed; order = subframeType - FlacCommons.FixedSubframeTypeStart; } else if (subframeType >= FlacCommons.LpcSubframeTypeStart) { type = SubframeType.SubframeLpc; order = subframeType - FlacCommons.LpcSubframeTypeStart + 1; } else { throw new FlacException("Subframe type is set to reserved"); } uint wastedBitsPerSampleFlag = bitReader.ReadBits(1); if (wastedBitsPerSampleFlag > 0) { this.wastedBitsPerSample = 1 + (int)bitReader.ReadUnary(); } else { this.wastedBitsPerSample = 0; } this.subframeType = type; int subframeBitsPerSample = FrameBitsPerSample; if (ChannelAssignment[subframeIndex] == SoundChannelAssignment.Difference) { subframeBitsPerSample++; // undocumented } switch (type) { case SubframeType.SubframeConstant: PrepareConstantSubframe(subframeBitsPerSample); break; case SubframeType.SubframeVerbatim: PrepareVerbatimSubframe(subframeBitsPerSample); break; case SubframeType.SubframeLpc: PrepareLpcSubframe(order, subframeBitsPerSample); break; case SubframeType.SubframeFixed: PrepareFixedSubframe(order, subframeBitsPerSample); break; } this.recordType = FlacRecordType.Subframe; this.dataRead = false; }