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; } }
unsafe void Decode_subframe_lpc(BitReader bitreader, FlacFrame frame, int ch) { // warm-up samples int obits = frame.subframes[ch].obits; for (int i = 0; i < frame.subframes[ch].best.order; i++) { frame.subframes[ch].best.residual[i] = bitreader.Readbits_signed(obits); } // LPC coefficients frame.subframes[ch].best.cbits = (int)bitreader.Readbits(4) + 1; // lpc_precision frame.subframes[ch].best.shift = bitreader.Readbits_signed(5); if (frame.subframes[ch].best.shift < 0) { throw new Exception("negative shift"); } for (int i = 0; i < frame.subframes[ch].best.order; i++) { frame.subframes[ch].best.coefs[i] = bitreader.Readbits_signed(frame.subframes[ch].best.cbits); } // residual Decode_residual(bitreader, frame, ch); }
public unsafe int DecodeFrame(byte[] buffer, int pos, int len) { fixed(byte *buf = buffer) { framereader.Reset(buf, pos, len); Decode_frame_header(framereader, frame); Decode_subframes(framereader, frame); framereader.Flush(); ushort crc_1 = DoCRC ? crc16.ComputeChecksum(framereader.Buffer + pos, framereader.Position - pos) : (ushort)0; ushort crc_2 = (ushort)framereader.Readbits(16); if (DoCRC && crc_1 != crc_2) { throw new Exception("frame crc mismatch"); } Restore_samples(frame); _samplesInBuffer = frame.blocksize; return(framereader.Position - pos); } }
unsafe void Decode_metadata() { byte x; int i, id; byte[] FLAC__STREAM_SYNC_STRING = new byte[] { (byte)'f', (byte)'L', (byte)'a', (byte)'C' }; byte[] ID3V2_TAG_ = new byte[] { (byte)'I', (byte)'D', (byte)'3' }; for (i = id = 0; i < 4;) { if (_IO.Read(_framesBuffer, 0, 1) == 0) { throw new Exception("FLAC stream not found"); } x = _framesBuffer[0]; if (x == FLAC__STREAM_SYNC_STRING[i]) { i++; id = 0; continue; } if (id < 3 && x == ID3V2_TAG_[id]) { id++; i = 0; if (id == 3) { if (!Skip_bytes(3)) { throw new Exception("FLAC stream not found"); } int skip = 0; for (int j = 0; j < 4; j++) { if (0 == _IO.Read(_framesBuffer, 0, 1)) { throw new Exception("FLAC stream not found"); } skip <<= 7; skip |= ((int)_framesBuffer[0] & 0x7f); } if (!Skip_bytes(skip)) { throw new Exception("FLAC stream not found"); } } continue; } id = 0; if (x == 0xff) /* MAGIC NUMBER for the first 8 frame sync bits */ { do { if (_IO.Read(_framesBuffer, 0, 1) == 0) { throw new Exception("FLAC stream not found"); } x = _framesBuffer[0]; } while (x == 0xff); if (x >> 2 == 0x3e) /* MAGIC NUMBER for the last 6 sync bits */ { //_IO.Position -= 2; // state = frame throw new Exception("headerless file unsupported"); } } throw new Exception("FLAC stream not found"); } do { Fill_frames_buffer(); fixed(byte *buf = _framesBuffer) { BitReader bitreader = new BitReader(buf, _framesBufferOffset, _framesBufferLength - _framesBufferOffset); bool is_last = bitreader.Readbit() != 0; MetadataType type = (MetadataType)bitreader.Readbits(7); int len = (int)bitreader.Readbits(24); if (type == MetadataType.StreamInfo) { const int FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */ const int FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */ min_block_size = bitreader.Readbits(FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN); max_block_size = bitreader.Readbits(FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN); min_frame_size = bitreader.Readbits(FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN); max_frame_size = bitreader.Readbits(FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN); int sample_rate = (int)bitreader.Readbits(FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN); int channels = 1 + (int)bitreader.Readbits(FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN); int bits_per_sample = 1 + (int)bitreader.Readbits(FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN); PCM = new AudioPCMConfig(bits_per_sample, channels, sample_rate); Length = (long)bitreader.Readbits64(FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN); bitreader.Skipbits(FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN); } else if (type == MetadataType.Seektable) { int num_entries = len / 18; seek_table = new SeekPoint[num_entries]; for (int e = 0; e < num_entries; e++) { seek_table[e].number = (long)bitreader.Readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN); seek_table[e].offset = (long)bitreader.Readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN); seek_table[e].framesize = (int)bitreader.Readbits24(Flake.FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN); } } if (_framesBufferLength < 4 + len) { _IO.Position += 4 + len - _framesBufferLength; _framesBufferLength = 0; } else { _framesBufferLength -= 4 + len; _framesBufferOffset += 4 + len; } if (is_last) { break; } } } while (true); first_frame_offset = _IO.Position - _framesBufferLength; }
unsafe void Decode_subframes(BitReader bitreader, FlacFrame frame) { fixed(int *r = residualBuffer, s = Samples) 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"); } } }
unsafe void Decode_frame_header(BitReader bitreader, FlacFrame frame) { int header_start = bitreader.Position; if (bitreader.Readbits(15) != 0x7FFC) { throw new Exception("invalid frame"); } uint vbs = bitreader.Readbit(); frame.bs_code0 = (int)bitreader.Readbits(4); uint sr_code0 = bitreader.Readbits(4); frame.ch_mode = (ChannelMode)bitreader.Readbits(4); uint bps_code = bitreader.Readbits(3); if (Flake.flac_bitdepths[bps_code] != PCM.BitsPerSample) { throw new Exception("unsupported bps coding"); } uint t1 = bitreader.Readbit(); // == 0????? if (t1 != 0) { throw new Exception("unsupported frame coding"); } frame.frame_number = (int)bitreader.Read_utf8(); // custom block size if (frame.bs_code0 == 6) { frame.bs_code1 = (int)bitreader.Readbits(8); frame.blocksize = frame.bs_code1 + 1; } else if (frame.bs_code0 == 7) { frame.bs_code1 = (int)bitreader.Readbits(16); frame.blocksize = frame.bs_code1 + 1; } else { frame.blocksize = Flake.flac_blocksizes[frame.bs_code0]; } // custom sample rate if (sr_code0 < 4 || sr_code0 > 11) { // sr_code0 == 12 -> sr == bitreader.readbits(8) * 1000; // sr_code0 == 13 -> sr == bitreader.readbits(16); // sr_code0 == 14 -> sr == bitreader.readbits(16) * 10; throw new Exception("invalid sample rate mode"); } int frame_channels = (int)frame.ch_mode + 1; if (frame_channels > 11) { throw new Exception("invalid channel mode"); } if (frame_channels == 2 || frame_channels > 8) // Mid/Left/Right Side Stereo { frame_channels = 2; } else { frame.ch_mode = ChannelMode.NotStereo; } if (frame_channels != PCM.ChannelCount) { throw new Exception("invalid channel mode"); } // CRC-8 of frame header byte crc = DoCRC ? crc8.ComputeChecksum(bitreader.Buffer, header_start, bitreader.Position - header_start) : (byte)0; frame.crc8 = (byte)bitreader.Readbits(8); if (DoCRC && frame.crc8 != crc) { throw new Exception("header crc mismatch"); } }