unsafe void decode_subframes(BitReader bitreader, FlacFrame frame) { fixed (int *r = residualBuffer, s = samplesBuffer) for (int ch = 0; ch < PCM.ChannelCount; ch++) { // subframe header uint t1 = bitreader.readbit(); // ?????? == 0 if (t1 != 0) throw new Exception("unsupported subframe coding (ch == " + ch.ToString() + ")"); int type_code = (int)bitreader.readbits(6); frame.subframes[ch].wbits = (int)bitreader.readbit(); if (frame.subframes[ch].wbits != 0) frame.subframes[ch].wbits += (int)bitreader.read_unary(); frame.subframes[ch].obits = PCM.BitsPerSample - frame.subframes[ch].wbits; switch (frame.ch_mode) { case ChannelMode.MidSide: frame.subframes[ch].obits += ch; break; case ChannelMode.LeftSide: frame.subframes[ch].obits += ch; break; case ChannelMode.RightSide: frame.subframes[ch].obits += 1 - ch; break; } frame.subframes[ch].best.type = (SubframeType)type_code; frame.subframes[ch].best.order = 0; if ((type_code & (uint)SubframeType.LPC) != 0) { frame.subframes[ch].best.order = (type_code - (int)SubframeType.LPC) + 1; frame.subframes[ch].best.type = SubframeType.LPC; } else if ((type_code & (uint)SubframeType.Fixed) != 0) { frame.subframes[ch].best.order = (type_code - (int)SubframeType.Fixed); frame.subframes[ch].best.type = SubframeType.Fixed; } frame.subframes[ch].best.residual = r + ch * Flake.MAX_BLOCKSIZE; frame.subframes[ch].samples = s + ch * Flake.MAX_BLOCKSIZE; // subframe switch (frame.subframes[ch].best.type) { case SubframeType.Constant: decode_subframe_constant(bitreader, frame, ch); break; case SubframeType.Verbatim: decode_subframe_verbatim(bitreader, frame, ch); break; case SubframeType.Fixed: decode_subframe_fixed(bitreader, frame, ch); break; case SubframeType.LPC: decode_subframe_lpc(bitreader, frame, ch); break; default: throw new Exception("invalid subframe type"); } } }