unsafe void Decode_residual(BitReader bitreader, FlacFrame frame, int ch) { // rice-encoded block // coding method frame.subframes[ch].best.rc.coding_method = (int)bitreader.Readbits(2); // ????? == 0 if (frame.subframes[ch].best.rc.coding_method != 0 && frame.subframes[ch].best.rc.coding_method != 1) { throw new Exception("unsupported residual coding"); } // partition order frame.subframes[ch].best.rc.porder = (int)bitreader.Readbits(4); if (frame.subframes[ch].best.rc.porder > 8) { throw new Exception("invalid partition order"); } int psize = frame.blocksize >> frame.subframes[ch].best.rc.porder; int res_cnt = psize - frame.subframes[ch].best.order; int rice_len = 4 + frame.subframes[ch].best.rc.coding_method; // residual int j = frame.subframes[ch].best.order; int *r = frame.subframes[ch].best.residual + j; for (int p = 0; p < (1 << frame.subframes[ch].best.rc.porder); p++) { if (p == 1) { res_cnt = psize; } int n = Math.Min(res_cnt, frame.blocksize - j); int k = frame.subframes[ch].best.rc.rparams[p] = (int)bitreader.Readbits(rice_len); if (k == (1 << rice_len) - 1) { k = frame.subframes[ch].best.rc.esc_bps[p] = (int)bitreader.Readbits(5); for (int i = n; i > 0; i--) { *(r++) = bitreader.Readbits_signed((int)k); } } else { bitreader.Read_rice_block(n, (int)k, r); r += n; } j += n; } }