public FlakeReader(string path, Stream IO) { _path = path; _IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000); crc8 = new Crc8(); crc16 = new Crc16(); _framesBuffer = new byte[0x20000]; decode_metadata(); frame = new FlacFrame(PCM.ChannelCount); framereader = new BitReader(); //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3); if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length) { byte[] temp = _framesBuffer; _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)]; if (_framesBufferLength > 0) Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength); _framesBufferOffset = 0; } _samplesInBuffer = 0; if ((PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24) || PCM.ChannelCount != 2 || (PCM.SampleRate != 44100 && PCM.SampleRate != 48000)) throw new Exception("invalid flac file"); samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; }
public FlakeReader(Stream IO) { if (IO == null) { throw new ArgumentNullException("IO"); } _IO = IO; crc8 = new Crc8(); _framesBuffer = new byte[0x20000]; decode_metadata(); frame = new FlacFrame(PCM.ChannelCount); framereader = new BitReader(); //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3); if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length) { byte[] temp = _framesBuffer; _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)]; if (_framesBufferLength > 0) Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength); _framesBufferOffset = 0; } _samplesInBuffer = 0; if (PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24) throw new Exception("invalid flac file"); samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; }
unsafe void restore_samples_fixed(FlacFrame frame, int ch) { FlacSubframeInfo sub = frame.subframes[ch]; AudioSamples.MemCpy(sub.samples, sub.best.residual, sub.best.order); int *data = sub.samples + sub.best.order; int *residual = sub.best.residual + sub.best.order; int data_len = frame.blocksize - sub.best.order; int s0, s1, s2; switch (sub.best.order) { case 0: AudioSamples.MemCpy(data, residual, data_len); break; case 1: s1 = data[-1]; for (int i = data_len; i > 0; i--) { s1 += *(residual++); *(data++) = s1; } //data[i] = residual[i] + data[i - 1]; break; case 2: s2 = data[-2]; s1 = data[-1]; for (int i = data_len; i > 0; i--) { s0 = *(residual++) + (s1 << 1) - s2; *(data++) = s0; s2 = s1; s1 = s0; } //data[i] = residual[i] + data[i - 1] * 2 - data[i - 2]; break; case 3: for (int i = 0; i < data_len; i++) { data[i] = residual[i] + (((data[i - 1] - data[i - 2]) << 1) + (data[i - 1] - data[i - 2])) + data[i - 3]; } break; case 4: for (int i = 0; i < data_len; i++) { data[i] = residual[i] + ((data[i - 1] + data[i - 3]) << 2) - ((data[i - 2] << 2) + (data[i - 2] << 1)) - data[i - 4]; } break; } }
public FlakeReader(AudioPCMConfig _pcm) { pcm = _pcm; crc8 = new Crc8(); crc16 = new Crc16(); samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; frame = new FlacFrame(PCM.ChannelCount); framereader = new BitReader(); }
unsafe void Decode_subframe_fixed(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); } // residual Decode_residual(bitreader, frame, ch); }
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 Restore_samples_lpc(FlacFrame frame, int ch) { FlacSubframeInfo sub = frame.subframes[ch]; ulong csum = 0; fixed(int *coefs = sub.best.coefs) { for (int i = sub.best.order; i > 0; i--) { csum += (ulong)Math.Abs(coefs[i - 1]); } if ((csum << sub.obits) >= 1UL << 32) { Lpc.Decode_residual_long(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); } else { Lpc.Decode_residual(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); } } }
public FlakeReader(Stream IO) { if (IO == null) { throw new ArgumentNullException("IO"); } _IO = IO; crc8 = new Crc8(); _framesBuffer = new byte[0x20000]; decode_metadata(); frame = new FlacFrame(PCM.ChannelCount); framereader = new BitReader(); //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3); if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length) { byte[] temp = _framesBuffer; _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)]; if (_framesBufferLength > 0) { Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength); } _framesBufferOffset = 0; } _samplesInBuffer = 0; if (PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24) { throw new Exception("invalid flac file"); } samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; }
unsafe void postprocess_coefs(FlacFrame frame, FlacSubframe sf, int ch) { if (eparams.development_mode < 0) return; if (sf.type != SubframeType.LPC || sf.order > 30) return; int orig_window = sf.window; int orig_order = sf.order; int orig_shift = sf.shift; int orig_cbits = sf.cbits; uint orig_size = sf.size; var orig_coefs = stackalloc int[orig_order]; for (int i = 0; i < orig_order; i++) orig_coefs[i] = sf.coefs[i]; int orig_xx = -1; int orig_seq = 0; int maxxx = Math.Min(good_x[orig_order].Length, eparams.development_mode); var pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, orig_order); var pmin = Math.Min(eparams.min_partition_order, pmax); ulong* sums = stackalloc ulong[(pmax + 1) * Flake.MAX_PARTITIONS]; while (true) { var best_coefs = stackalloc int[orig_order]; int best_shift = orig_shift; int best_cbits = orig_cbits; uint best_size = orig_size; int best_xx = -1; for (int xx = -1; xx < maxxx; xx++) { int x = xx; if (xx < 0) { if (orig_xx < 0 || maxxx < 1/*3*/)// || (orig_xx >> orig_order) != 0) continue; x = orig_xx; orig_seq++; } else { orig_seq = 0; if (orig_order < good_x.Length && good_x[orig_order] != null) x = good_x[orig_order][xx]; } frame.current.type = SubframeType.LPC; frame.current.order = orig_order; frame.current.window = orig_window; frame.current.shift = orig_shift; frame.current.cbits = orig_cbits; if (((x >> orig_order) & 1) != 0) { frame.current.shift--; frame.current.cbits--; if (frame.current.shift < 0 || frame.current.cbits < 2) continue; } ulong csum = 0; int qmax = (1 << (frame.current.cbits - 1)) - 1; for (int i = 0; i < frame.current.order; i++) { int shift = (x >> orig_order) & 1; int increment = (x == 1 << orig_order) ? 0 : (((x >> i) & 1) << 1) - 1; frame.current.coefs[i] = (orig_coefs[i] + (increment << orig_seq)) >> shift; if (frame.current.coefs[i] < -(qmax + 1)) frame.current.coefs[i] = -(qmax + 1); if (frame.current.coefs[i] > qmax) frame.current.coefs[i] = qmax; csum += (ulong)Math.Abs(frame.current.coefs[i]); } fixed (int* coefs = frame.current.coefs) { if ((csum << frame.subframes[ch].obits) >= 1UL << 32) lpc.encode_residual_long(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift); else lpc.encode_residual(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift); } var cur_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample); frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits + 4 + 5 + frame.current.order * frame.current.cbits + 6 + (int)cur_size); if (frame.current.size < best_size) { //var dif = best_size - frame.current.size; for (int i = 0; i < frame.current.order; i++) best_coefs[i] = frame.current.coefs[i]; best_shift = frame.current.shift; best_cbits = frame.current.cbits; best_size = frame.current.size; best_xx = x; frame.ChooseBestSubframe(ch); //if (dif > orig_order * 5) // break; } if (xx < 0 && best_size < orig_size) break; } if (best_size < orig_size) { //if (best_xx >= 0) best_x[order, best_xx]++; //if (orig_size != 0x7FFFFFFF) // System.Console.Write(string.Format(" {0}[{1:x}]", orig_size - best_size, best_xx)); for (int i = 0; i < orig_order; i++) orig_coefs[i] = best_coefs[i]; orig_shift = best_shift; orig_cbits = best_cbits; orig_size = best_size; orig_xx = best_xx; } else { break; } } //if (orig_size != 0x7FFFFFFF) // System.Console.WriteLine(); //if (frame_count % 0x400 == 0) //{ // for (int o = 0; o < best_x.GetLength(0); o++) // { // //for (int x = 0; x <= (1 << o); x++) // // if (best_x[o, x] != 0) // // System.Console.WriteLine(string.Format("{0:x2}\t{1:x4}\t{2}", o, x, best_x[o, x])); // var s = new List<KeyValuePair<int, int>>(); // for (int x = 0; x < (1 << o); x++) // if (best_x[o, x] != 0) // s.Add(new KeyValuePair<int, int>(x, best_x[o, x])); // s.Sort((x, y) => y.Value.CompareTo(x.Value)); // foreach (var x in s) // System.Console.WriteLine(string.Format("{0:x2}\t{1:x4}\t{2}", o, x.Key, x.Value)); // int i = 0; // foreach (var x in s) // { // System.Console.Write(string.Format(o <= 8 ? "0x{0:x2}," : "0x{0:x3},", x.Key)); // if ((++i) % 16 == 0) // System.Console.WriteLine(); // } // System.Console.WriteLine(); // } //} }
unsafe void restore_samples(FlacFrame frame) { for (int ch = 0; ch < PCM.ChannelCount; ch++) { switch (frame.subframes[ch].best.type) { case SubframeType.Constant: AudioSamples.MemSet(frame.subframes[ch].samples, frame.subframes[ch].best.residual[0], frame.blocksize); break; case SubframeType.Verbatim: AudioSamples.MemCpy(frame.subframes[ch].samples, frame.subframes[ch].best.residual, frame.blocksize); break; case SubframeType.Fixed: restore_samples_fixed(frame, ch); break; case SubframeType.LPC: restore_samples_lpc(frame, ch); break; } if (frame.subframes[ch].wbits != 0) { int* s = frame.subframes[ch].samples; int x = (int) frame.subframes[ch].wbits; for (int i = frame.blocksize; i > 0; i--) *(s++) <<= x; } } if (frame.ch_mode != ChannelMode.NotStereo) { int* l = frame.subframes[0].samples; int* r = frame.subframes[1].samples; switch (frame.ch_mode) { case ChannelMode.LeftRight: break; case ChannelMode.MidSide: for (int i = frame.blocksize; i > 0; i--) { int mid = *l; int side = *r; mid <<= 1; mid |= (side & 1); /* i.e. if 'side' is odd... */ *(l++) = (mid + side) >> 1; *(r++) = (mid - side) >> 1; } break; case ChannelMode.LeftSide: for (int i = frame.blocksize; i > 0; i--) { int _l = *(l++), _r = *r; *(r++) = _l - _r; } break; case ChannelMode.RightSide: for (int i = frame.blocksize; i > 0; i--) *(l++) += *(r++); break; } } }
public FlakeWriter(string path, Stream IO, AudioPCMConfig pcm) { _pcm = pcm; //if (_pcm.BitsPerSample != 16) // throw new Exception("Bits per sample must be 16."); if (_pcm.ChannelCount != 2) throw new Exception("ChannelCount must be 2."); channels = pcm.ChannelCount; // flake_validate_params _path = path; _IO = IO; samplesBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 4 : channels)]; residualBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 10 : channels + 1)]; windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS]; windowScale = new double[lpc.MAX_LPC_WINDOWS]; eparams.flake_set_defaults(_compressionLevel); eparams.padding_size = 8192; crc8 = new Crc8(); crc16 = new Crc16(); frame = new FlacFrame(channels * 2); }
unsafe void encode_residual_pass2(FlacFrame frame, int ch) { encode_residual(frame, ch, eparams.prediction_type, eparams.order_method, 2, estimate_best_window(frame, ch)); }
unsafe void output_subframes(FlacFrame frame, BitWriter bitwriter) { for (int ch = 0; ch < channels; ch++) { FlacSubframeInfo sub = frame.subframes[ch]; // subframe header int type_code = (int) sub.best.type; if (sub.best.type == SubframeType.Fixed) type_code |= sub.best.order; if (sub.best.type == SubframeType.LPC) type_code |= sub.best.order - 1; bitwriter.writebits(1, 0); bitwriter.writebits(6, type_code); bitwriter.writebits(1, sub.wbits != 0 ? 1 : 0); if (sub.wbits > 0) bitwriter.writebits((int)sub.wbits, 1); // subframe switch (sub.best.type) { case SubframeType.Constant: output_subframe_constant(frame, bitwriter, sub); break; case SubframeType.Verbatim: output_subframe_verbatim(frame, bitwriter, sub); break; case SubframeType.Fixed: output_subframe_fixed(frame, bitwriter, sub); break; case SubframeType.LPC: output_subframe_lpc(frame, bitwriter, sub); break; } } }
output_subframe_fixed(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub) { // warm-up samples for (int i = 0; i < sub.best.order; i++) bitwriter.writebits_signed(sub.obits, sub.best.residual[i]); // residual output_residual(frame, bitwriter, sub); }
output_subframe_constant(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub) { bitwriter.writebits_signed(sub.obits, sub.best.residual[0]); }
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); }
unsafe void Decode_subframe_constant(BitReader bitreader, FlacFrame frame, int ch) { int obits = frame.subframes[ch].obits; frame.subframes[ch].best.residual[0] = bitreader.Readbits_signed(obits); }
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"); } }
unsafe void restore_samples_lpc(FlacFrame frame, int ch) { FlacSubframeInfo sub = frame.subframes[ch]; ulong csum = 0; fixed (int* coefs = sub.best.coefs) { for (int i = sub.best.order; i > 0; i--) csum += (ulong)Math.Abs(coefs[i - 1]); if ((csum << sub.obits) >= 1UL << 32) lpc.decode_residual_long(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); else lpc.decode_residual(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); } }
unsafe void restore_samples_fixed(FlacFrame frame, int ch) { FlacSubframeInfo sub = frame.subframes[ch]; AudioSamples.MemCpy(sub.samples, sub.best.residual, sub.best.order); int* data = sub.samples + sub.best.order; int* residual = sub.best.residual + sub.best.order; int data_len = frame.blocksize - sub.best.order; int s0, s1, s2; switch (sub.best.order) { case 0: AudioSamples.MemCpy(data, residual, data_len); break; case 1: s1 = data[-1]; for (int i = data_len; i > 0; i--) { s1 += *(residual++); *(data++) = s1; } //data[i] = residual[i] + data[i - 1]; break; case 2: s2 = data[-2]; s1 = data[-1]; for (int i = data_len; i > 0; i--) { s0 = *(residual++) + (s1 << 1) - s2; *(data++) = s0; s2 = s1; s1 = s0; } //data[i] = residual[i] + data[i - 1] * 2 - data[i - 2]; break; case 3: for (int i = 0; i < data_len; i++) data[i] = residual[i] + (((data[i - 1] - data[i - 2]) << 1) + (data[i - 1] - data[i - 2])) + data[i - 3]; break; case 4: for (int i = 0; i < data_len; i++) data[i] = residual[i] + ((data[i - 1] + data[i - 3]) << 2) - ((data[i - 2] << 2) + (data[i - 2] << 1)) - data[i - 4]; break; } }
unsafe void output_frame_header(FlacFrame frame, BitWriter bitwriter) { bitwriter.writebits(15, 0x7FFC); bitwriter.writebits(1, eparams.variable_block_size > 0 ? 1 : 0); bitwriter.writebits(4, frame.bs_code0); bitwriter.writebits(4, sr_code0); if (frame.ch_mode == ChannelMode.NotStereo) bitwriter.writebits(4, ch_code); else bitwriter.writebits(4, (int) frame.ch_mode); bitwriter.writebits(3, bps_code); bitwriter.writebits(1, 0); bitwriter.write_utf8(frame_count); // custom block size if (frame.bs_code1 >= 0) { if (frame.bs_code1 < 256) bitwriter.writebits(8, frame.bs_code1); else bitwriter.writebits(16, frame.bs_code1); } // custom sample rate if (sr_code1 > 0) { if (sr_code1 < 256) bitwriter.writebits(8, sr_code1); else bitwriter.writebits(16, sr_code1); } // CRC-8 of frame header bitwriter.flush(); byte crc = crc8.ComputeChecksum(frame_buffer, 0, bitwriter.Length); bitwriter.writebits(8, crc); }
unsafe void output_residual(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub) { // rice-encoded block bitwriter.writebits(2, sub.best.rc.coding_method); // partition order int porder = sub.best.rc.porder; int psize = frame.blocksize >> porder; //assert(porder >= 0); bitwriter.writebits(4, porder); int res_cnt = psize - sub.best.order; int rice_len = 4 + sub.best.rc.coding_method; // residual int j = sub.best.order; fixed (byte* fixbuf = &frame_buffer[0]) for (int p = 0; p < (1 << porder); p++) { int k = sub.best.rc.rparams[p]; bitwriter.writebits(rice_len, k); if (p == 1) res_cnt = psize; int cnt = Math.Min(res_cnt, frame.blocksize - j); bitwriter.write_rice_block_signed(fixbuf, k, sub.best.residual + j, cnt); j += cnt; } }
unsafe void decode_subframe_fixed(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); // residual decode_residual(bitreader, frame, ch); }
output_subframe_verbatim(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub) { int n = frame.blocksize; for (int i = 0; i < n; i++) bitwriter.writebits_signed(sub.obits, sub.samples[i]); // Don't use residual here, because we don't copy samples to residual for verbatim frames. }
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"); } } }
output_subframe_lpc(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub) { // warm-up samples for (int i = 0; i < sub.best.order; i++) bitwriter.writebits_signed(sub.obits, sub.best.residual[i]); // LPC coefficients int cbits = 1; for (int i = 0; i < sub.best.order; i++) while (cbits < 16 && sub.best.coefs[i] != (sub.best.coefs[i] << (32 - cbits)) >> (32 - cbits)) cbits++; bitwriter.writebits(4, cbits - 1); bitwriter.writebits_signed(5, sub.best.shift); for (int i = 0; i < sub.best.order; i++) bitwriter.writebits_signed(cbits, sub.best.coefs[i]); // residual output_residual(frame, bitwriter, sub); }
unsafe uint measure_frame_size(FlacFrame frame, bool do_midside) { // crude estimation of header/footer size uint total = (uint)(32 + ((BitReader.log2i(frame_count) + 4) / 5) * 8 + (eparams.variable_block_size != 0 ? 16 : 0) + 16); if (do_midside) { uint bitsBest = AudioSamples.UINT32_MAX; ChannelMode modeBest = ChannelMode.LeftRight; if (bitsBest > frame.subframes[2].best.size + frame.subframes[3].best.size) { bitsBest = frame.subframes[2].best.size + frame.subframes[3].best.size; modeBest = ChannelMode.MidSide; } if (bitsBest > frame.subframes[3].best.size + frame.subframes[1].best.size) { bitsBest = frame.subframes[3].best.size + frame.subframes[1].best.size; modeBest = ChannelMode.RightSide; } if (bitsBest > frame.subframes[3].best.size + frame.subframes[0].best.size) { bitsBest = frame.subframes[3].best.size + frame.subframes[0].best.size; modeBest = ChannelMode.LeftSide; } if (bitsBest > frame.subframes[0].best.size + frame.subframes[1].best.size) { bitsBest = frame.subframes[0].best.size + frame.subframes[1].best.size; modeBest = ChannelMode.LeftRight; } frame.ch_mode = modeBest; return total + bitsBest; } for (int ch = 0; ch < channels; ch++) total += frame.subframes[ch].best.size; return total; }
unsafe void encode_residual_pass1(FlacFrame frame, int ch, int best_window) { int max_prediction_order = eparams.max_prediction_order; int max_fixed_order = eparams.max_fixed_order; int min_fixed_order = eparams.min_fixed_order; int lpc_min_precision_search = eparams.lpc_min_precision_search; int lpc_max_precision_search = eparams.lpc_max_precision_search; int max_partition_order = eparams.max_partition_order; int estimation_depth = eparams.estimation_depth; eparams.min_fixed_order = 2; eparams.max_fixed_order = 2; eparams.lpc_min_precision_search = eparams.lpc_max_precision_search; eparams.max_prediction_order = 8; eparams.estimation_depth = 1; encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window); eparams.min_fixed_order = min_fixed_order; eparams.max_fixed_order = max_fixed_order; eparams.max_prediction_order = max_prediction_order; eparams.lpc_min_precision_search = lpc_min_precision_search; eparams.lpc_max_precision_search = lpc_max_precision_search; eparams.max_partition_order = max_partition_order; eparams.estimation_depth = estimation_depth; }
unsafe int encode_frame(out int size) { fixed (int* s = samplesBuffer, r = residualBuffer) fixed (float* window = windowBuffer) { frame.InitSize(eparams.block_size, eparams.variable_block_size != 0); if (frame.blocksize != _windowsize && frame.blocksize > 4) { _windowsize = frame.blocksize; _windowcount = 0; calculate_window(window, lpc.window_welch, WindowFunction.Welch); calculate_window(window, lpc.window_tukey, WindowFunction.Tukey); calculate_window(window, lpc.window_flattop, WindowFunction.Flattop); calculate_window(window, lpc.window_hann, WindowFunction.Hann); calculate_window(window, lpc.window_bartlett, WindowFunction.Bartlett); if (_windowcount == 0) throw new Exception("invalid windowfunction"); } if (channels != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent) { frame.window_buffer = window; frame.current.residual = r + channels * Flake.MAX_BLOCKSIZE; frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight; for (int ch = 0; ch < channels; ch++) frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE, _pcm.BitsPerSample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); for (int ch = 0; ch < channels; ch++) encode_residual_pass2(frame, ch); } else { //channel_decorrelation(s, s + Flake.MAX_BLOCKSIZE, s + 2 * Flake.MAX_BLOCKSIZE, s + 3 * Flake.MAX_BLOCKSIZE, frame.blocksize); frame.window_buffer = window; frame.current.residual = r + 4 * Flake.MAX_BLOCKSIZE; for (int ch = 0; ch < 4; ch++) frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE, _pcm.BitsPerSample + (ch == 3 ? 1 : 0), get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); //for (int ch = 0; ch < 4; ch++) // for (int iWindow = 0; iWindow < _windowcount; iWindow++) // frame.subframes[ch].lpc_ctx[iWindow].GetReflection(32, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2); estimate_frame(frame, true); uint fs = measure_frame_size(frame, true); if (0 != eparams.variable_block_size) { FlacFrame frame2 = new FlacFrame(channels * 2); FlacFrame frame3 = new FlacFrame(channels * 2); int tumbler = 1; while ((frame.blocksize & 1) == 0 && frame.blocksize >= 1024) { frame2.InitSize(frame.blocksize / 2, true); frame2.window_buffer = frame.window_buffer + frame.blocksize; frame2.current.residual = r + tumbler * 5 * Flake.MAX_BLOCKSIZE; for (int ch = 0; ch < 4; ch++) frame2.subframes[ch].Init(frame.subframes[ch].samples, frame2.current.residual + (ch + 1) * frame2.blocksize, frame.subframes[ch].obits + frame.subframes[ch].wbits, frame.subframes[ch].wbits); estimate_frame(frame2, true); uint fs2 = measure_frame_size(frame2, true); uint fs3 = fs2; if (eparams.variable_block_size == 2 || eparams.variable_block_size == 4) { frame3.InitSize(frame2.blocksize, true); frame3.window_buffer = frame2.window_buffer; frame3.current.residual = frame2.current.residual + 5 * frame2.blocksize; for (int ch = 0; ch < 4; ch++) frame3.subframes[ch].Init(frame2.subframes[ch].samples + frame2.blocksize, frame3.current.residual + (ch + 1) * frame3.blocksize, frame.subframes[ch].obits + frame.subframes[ch].wbits, frame.subframes[ch].wbits); estimate_frame(frame3, true); fs3 = measure_frame_size(frame3, true); } if (fs2 + fs3 > fs) break; FlacFrame tmp = frame; frame = frame2; frame2 = tmp; fs = fs2; if (eparams.variable_block_size <= 2) break; tumbler = 1 - tumbler; } } frame.ChooseSubframes(); encode_estimated_frame(frame); } BitWriter bitwriter = new BitWriter(frame_buffer, 0, max_frame_size); output_frame_header(frame, bitwriter); output_subframes(frame, bitwriter); output_frame_footer(bitwriter); if (bitwriter.Length >= max_frame_size) throw new Exception("buffer overflow"); if (frame_buffer != null) { if (eparams.variable_block_size > 0) frame_count += frame.blocksize; else frame_count++; } size = frame.blocksize; return bitwriter.Length; } }
unsafe int estimate_best_window(FlacFrame frame, int ch) { if (_windowcount == 1) return 0; switch (eparams.window_method) { case WindowMethod.Estimate: { int best_window = -1; double best_error = 0; int order = 2; for (int i = 0; i < _windowcount; i++) { frame.subframes[ch].lpc_ctx[i].GetReflection(order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer + i * Flake.MAX_BLOCKSIZE * 2); double err = frame.subframes[ch].lpc_ctx[i].prediction_error[order - 1] / frame.subframes[ch].lpc_ctx[i].autocorr_values[0]; //double err = frame.subframes[ch].lpc_ctx[i].autocorr_values[0] / frame.subframes[ch].lpc_ctx[i].autocorr_values[2]; if (best_window == -1 || best_error > err) { best_window = i; best_error = err; } } return best_window; } case WindowMethod.Evaluate: encode_residual_pass1(frame, ch, -1); return frame.subframes[ch].best.type == SubframeType.LPC ? frame.subframes[ch].best.window : -1; case WindowMethod.Search: return -1; } return -1; }
unsafe void encode_residual_fixed_sub(FlacFrame frame, int order, int ch) { if ((frame.subframes[ch].done_fixed & (1U << order)) != 0) return; // already calculated; frame.current.order = order; frame.current.type = SubframeType.Fixed; encode_residual_fixed(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order); int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order); int pmin = Math.Min(eparams.min_partition_order, pmax); frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits) + 6 + calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, PCM.BitsPerSample); frame.subframes[ch].done_fixed |= (1U << order); frame.ChooseBestSubframe(ch); }
unsafe void estimate_frame(FlacFrame frame, bool do_midside) { int subframes = do_midside ? channels * 2 : channels; switch (eparams.stereo_method) { case StereoMethod.Estimate: for (int ch = 0; ch < subframes; ch++) { LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0]; lpc_ctx.GetReflection(4, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer); lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 4, 4.5, 0.0); frame.subframes[ch].best.size = (uint)Math.Max(0, lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], 4.5, 0.0) + 7.1 * frame.subframes[ch].obits * eparams.max_prediction_order); } break; case StereoMethod.Evaluate: for (int ch = 0; ch < subframes; ch++) encode_residual_pass1(frame, ch, 0); break; case StereoMethod.Search: for (int ch = 0; ch < subframes; ch++) encode_residual_pass2(frame, ch); break; } }
unsafe void decode_subframe_verbatim(BitReader bitreader, FlacFrame frame, int ch) { int obits = frame.subframes[ch].obits; for (int i = 0; i < frame.blocksize; i++) frame.subframes[ch].best.residual[i] = bitreader.readbits_signed(obits); }
unsafe void encode_estimated_frame(FlacFrame frame) { switch (eparams.stereo_method) { case StereoMethod.Estimate: for (int ch = 0; ch < channels; ch++) { frame.subframes[ch].best.size = AudioSamples.UINT32_MAX; encode_residual_pass2(frame, ch); } break; case StereoMethod.Evaluate: for (int ch = 0; ch < channels; ch++) encode_residual_pass2(frame, ch); break; case StereoMethod.Search: break; } }
unsafe void Restore_samples(FlacFrame frame) { for (int ch = 0; ch < PCM.ChannelCount; ch++) { switch (frame.subframes[ch].best.type) { case SubframeType.Constant: AudioSamples.MemSet(frame.subframes[ch].samples, frame.subframes[ch].best.residual[0], frame.blocksize); break; case SubframeType.Verbatim: AudioSamples.MemCpy(frame.subframes[ch].samples, frame.subframes[ch].best.residual, frame.blocksize); break; case SubframeType.Fixed: Restore_samples_fixed(frame, ch); break; case SubframeType.LPC: Restore_samples_lpc(frame, ch); break; } if (frame.subframes[ch].wbits != 0) { int *s = frame.subframes[ch].samples; int x = (int)frame.subframes[ch].wbits; for (int i = frame.blocksize; i > 0; i--) { *(s++) <<= x; } } } if (frame.ch_mode != ChannelMode.NotStereo) { int *l = frame.subframes[0].samples; int *r = frame.subframes[1].samples; switch (frame.ch_mode) { case ChannelMode.LeftRight: break; case ChannelMode.MidSide: for (int i = frame.blocksize; i > 0; i--) { int mid = *l; int side = *r; mid <<= 1; mid |= (side & 1); /* i.e. if 'side' is odd... */ *(l++) = (mid + side) >> 1; *(r++) = (mid - side) >> 1; } break; case ChannelMode.LeftSide: for (int i = frame.blocksize; i > 0; i--) { int _l = *(l++), _r = *r; *(r++) = _l - _r; } break; case ChannelMode.RightSide: for (int i = frame.blocksize; i > 0; i--) { *(l++) += *(r++); } break; } } }
unsafe void encode_residual_lpc_sub(FlacFrame frame, float* lpcs, int iWindow, int order, int ch) { // select LPC precision based on block size uint lpc_precision; if (frame.blocksize <= 192) lpc_precision = 7U; else if (frame.blocksize <= 384) lpc_precision = 8U; else if (frame.blocksize <= 576) lpc_precision = 9U; else if (frame.blocksize <= 1152) lpc_precision = 10U; else if (frame.blocksize <= 2304) lpc_precision = 11U; else if (frame.blocksize <= 4608) lpc_precision = 12U; else if (frame.blocksize <= 8192) lpc_precision = 13U; else if (frame.blocksize <= 16384) lpc_precision = 14U; else lpc_precision = 15; for (int i_precision = eparams.lpc_min_precision_search; i_precision <= eparams.lpc_max_precision_search && lpc_precision + i_precision < 16; i_precision++) // check if we already calculated with this order, window and precision if ((frame.subframes[ch].lpc_ctx[iWindow].done_lpcs[i_precision] & (1U << (order - 1))) == 0) { frame.subframes[ch].lpc_ctx[iWindow].done_lpcs[i_precision] |= (1U << (order - 1)); uint cbits = lpc_precision + (uint)i_precision; frame.current.type = SubframeType.LPC; frame.current.order = order; frame.current.window = iWindow; fixed (int* coefs = frame.current.coefs) { lpc.quantize_lpc_coefs(lpcs + (frame.current.order - 1) * lpc.MAX_LPC_ORDER, frame.current.order, cbits, coefs, out frame.current.shift, 15, 0); if (frame.current.shift < 0 || frame.current.shift > 15) throw new Exception("negative shift"); ulong csum = 0; for (int i = frame.current.order; i > 0; i--) csum += (ulong)Math.Abs(coefs[i - 1]); if ((csum << frame.subframes[ch].obits) >= 1UL << 32) lpc.encode_residual_long(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift); else lpc.encode_residual(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift); } int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order); int pmin = Math.Min(eparams.min_partition_order, pmax); uint best_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, PCM.BitsPerSample); // not working //for (int o = 1; o <= frame.current.order; o++) //{ // if (frame.current.coefs[o - 1] > -(1 << frame.current.shift)) // { // for (int i = o; i < frame.blocksize; i++) // frame.current.residual[i] += frame.subframes[ch].samples[i - o] >> frame.current.shift; // frame.current.coefs[o - 1]--; // uint new_size = calc_rice_params(ref frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order); // if (new_size > best_size) // { // for (int i = o; i < frame.blocksize; i++) // frame.current.residual[i] -= frame.subframes[ch].samples[i - o] >> frame.current.shift; // frame.current.coefs[o - 1]++; // } // } //} frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits + 4 + 5 + frame.current.order * (int)cbits + 6 + (int)best_size); frame.ChooseBestSubframe(ch); } }
public FlakeWriter(Stream IO, FlakeWriterSettings settings) { m_settings = settings; //if (Settings.PCM.BitsPerSample != 16) // throw new Exception("Bits per sample must be 16."); //if (Settings.PCM.ChannelCount != 2) // throw new Exception("ChannelCount must be 2."); channels = Settings.PCM.ChannelCount; // flake_validate_params //_path = path; if (IO == null) { throw new ArgumentNullException("IO"); } _IO = IO; samplesBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 4 : channels)]; residualBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 10 : channels + 1)]; windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS]; windowScale = new double[lpc.MAX_LPC_WINDOWS]; var _compressionLevel = Settings.EncoderModeIndex; eparams.flake_set_defaults(_compressionLevel); crc8 = new Crc8(); frame = new FlacFrame(channels * 2); }
unsafe void encode_residual(FlacFrame frame, int ch, PredictionType predict, OrderMethod omethod, int pass, int best_window) { int* smp = frame.subframes[ch].samples; int i, n = frame.blocksize; // save best.window, because we can overwrite it later with fixed frame // CONSTANT for (i = 1; i < n; i++) { if (smp[i] != smp[0]) break; } if (i == n) { frame.subframes[ch].best.type = SubframeType.Constant; frame.subframes[ch].best.residual[0] = smp[0]; frame.subframes[ch].best.size = (uint)frame.subframes[ch].obits; return; } // VERBATIM frame.current.type = SubframeType.Verbatim; frame.current.size = (uint)(frame.subframes[ch].obits * frame.blocksize); frame.ChooseBestSubframe(ch); if (n < 5 || predict == PredictionType.None) return; // FIXED if (predict == PredictionType.Fixed || (predict == PredictionType.Search && pass != 1) || //predict == PredictionType.Search || //(pass == 2 && frame.subframes[ch].best.type == SubframeType.Fixed) || n <= eparams.max_prediction_order) { int max_fixed_order = Math.Min(eparams.max_fixed_order, 4); int min_fixed_order = Math.Min(eparams.min_fixed_order, max_fixed_order); for (i = min_fixed_order; i <= max_fixed_order; i++) encode_residual_fixed_sub(frame, i, ch); } // LPC if (n > eparams.max_prediction_order && (predict == PredictionType.Levinson || predict == PredictionType.Search) //predict == PredictionType.Search || //(pass == 2 && frame.subframes[ch].best.type == SubframeType.LPC)) ) { float* lpcs = stackalloc float[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER]; int min_order = eparams.min_prediction_order; int max_order = eparams.max_prediction_order; for (int iWindow = 0; iWindow < _windowcount; iWindow++) { if (best_window != -1 && iWindow != best_window) continue; LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow]; lpc_ctx.GetReflection(max_order, smp, n, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2); lpc_ctx.ComputeLPC(lpcs); //int frameSize = n; //float* F = stackalloc float[frameSize]; //float* B = stackalloc float[frameSize]; //float* PE = stackalloc float[max_order + 1]; //float* arp = stackalloc float[max_order]; //float* rc = stackalloc float[max_order]; //for (int j = 0; j < frameSize; j++) // F[j] = B[j] = smp[j]; //for (int K = 1; K <= max_order; K++) //{ // // BURG: // float denominator = 0.0f; // //float denominator = F[K - 1] * F[K - 1] + B[frameSize - K] * B[frameSize - K]; // for (int j = 0; j < frameSize - K; j++) // denominator += F[j + K] * F[j + K] + B[j] * B[j]; // denominator /= 2; // // Estimate error // PE[K - 1] = denominator / (frameSize - K); // float reflectionCoeff = 0.0f; // for (int j = 0; j < frameSize - K; j++) // reflectionCoeff += F[j + K] * B[j]; // reflectionCoeff /= denominator; // rc[K - 1] = arp[K - 1] = reflectionCoeff; // // Levinson-Durbin // for (int j = 0; j < (K - 1) >> 1; j++) // { // float arptmp = arp[j]; // arp[j] -= reflectionCoeff * arp[K - 2 - j]; // arp[K - 2 - j] -= reflectionCoeff * arptmp; // } // if (((K - 1) & 1) != 0) // arp[(K - 1) >> 1] -= reflectionCoeff * arp[(K - 1) >> 1]; // for (int j = 0; j < frameSize - K; j++) // { // float f = F[j + K]; // float b = B[j]; // F[j + K] = f - reflectionCoeff * b; // B[j] = b - reflectionCoeff * f; // } // for (int j = 0; j < K; j++) // lpcs[(K - 1) * lpc.MAX_LPC_ORDER + j] = (float)arp[j]; //} switch (omethod) { case OrderMethod.Akaike: //lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, max_order, 7.1, 0.0); lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, max_order, 4.5, 0.0); break; default: throw new Exception("unknown order method"); } for (i = 0; i < eparams.estimation_depth && i < max_order; i++) encode_residual_lpc_sub(frame, lpcs, iWindow, lpc_ctx.best_orders[i], ch); } } }
unsafe void encode_residual_pass1(FlacFrame frame, int ch, int best_window) { int max_prediction_order = eparams.max_prediction_order; int max_fixed_order = eparams.max_fixed_order; int min_fixed_order = eparams.min_fixed_order; int lpc_min_precision_search = eparams.lpc_min_precision_search; int lpc_max_precision_search = eparams.lpc_max_precision_search; int max_partition_order = eparams.max_partition_order; int estimation_depth = eparams.estimation_depth; var development_mode = eparams.development_mode; eparams.min_fixed_order = 2; eparams.max_fixed_order = 2; eparams.lpc_min_precision_search = eparams.lpc_max_precision_search; eparams.max_prediction_order = Math.Min(eparams.max_prediction_order, Math.Max(eparams.min_prediction_order, 8)); eparams.estimation_depth = 1; eparams.development_mode = Math.Min(eparams.development_mode, -1); encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window); eparams.min_fixed_order = min_fixed_order; eparams.max_fixed_order = max_fixed_order; eparams.max_prediction_order = max_prediction_order; eparams.lpc_min_precision_search = lpc_min_precision_search; eparams.lpc_max_precision_search = lpc_max_precision_search; eparams.max_partition_order = max_partition_order; eparams.estimation_depth = estimation_depth; eparams.development_mode = development_mode; }