public void SwapSubframes(int ch1, int ch2) { FlacSubframeInfo tmp = subframes[ch1]; subframes[ch1] = subframes[ch2]; subframes[ch2] = tmp; }
public FlacFrame(int subframes_count) { subframes = new FlacSubframeInfo[subframes_count]; for (int ch = 0; ch < subframes_count; ch++) { subframes[ch] = new FlacSubframeInfo(); } current = new FlacSubframe(); }
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 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 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; } }
output_subframe_lpc(FLACCLTask task, FlacSubframeInfo sub, int index) { FlacFrame frame = task.frame; // warm-up samples for (int i = 0; i < sub.best.order; i++) frame.writer.writebits_signed(sub.obits, sub.samples[i]); // LPC coefficients frame.writer.writebits(4, sub.best.cbits - 1); frame.writer.writebits_signed(5, sub.best.shift); for (int i = 0; i < sub.best.order; i++) frame.writer.writebits_signed(sub.best.cbits, sub.best.coefs[i]); // residual output_residual(task, sub, (sub.obits + sub.best.cbits) * sub.best.order + 9, index); }
measure_subframe(FlacFrame frame, FlacSubframeInfo sub) { switch (sub.best.type) { case SubframeType.Constant: return (uint)sub.obits; case SubframeType.Verbatim: return (uint)(sub.obits * frame.blocksize); case SubframeType.Fixed: return measure_subframe_fixed(frame, sub); case SubframeType.LPC: return measure_subframe_lpc(frame, sub); } throw new Exception("not supported subframe type"); }
public FlacFrame(int subframes_count) { subframes = new FlacSubframeInfo[subframes_count]; for (int ch = 0; ch < subframes_count; ch++) subframes[ch] = new FlacSubframeInfo(); current = new FlacSubframe(); }
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, FlacSubframeInfo sub) { frame.writer.writebits_signed(sub.obits, sub.samples[0]); }
unsafe void output_residual(FLACCLTask task, FlacSubframeInfo sub, int offs0, int index) { FlacFrame frame = task.frame; // rice-encoded block frame.writer.writebits(2, sub.best.rc.coding_method); // partition order int porder = sub.best.rc.porder; //assert(porder >= 0); frame.writer.writebits(4, porder); if (task.UseGPURice) { int len = task.BestResidualTasks[index].size - task.BestResidualTasks[index].headerLen; int pos = task.BestResidualTasks[index].encodingOffset; if (task.BestResidualTasks[index].size != (int)sub.best.size) throw new Exception("Encoding offset mismatch"); if (task.BestResidualTasks[index].headerLen != offs0 + 6) throw new Exception("Encoding offset mismatch"); if (pos % 8 != frame.writer.BitLength % 8) throw new Exception("Encoding offset mismatch"); //Console.WriteLine("{0:x} => {1:x}", _totalSize + frame.writer.BitLength / 8, _totalSize + (frame.writer.BitLength + len) / 8); // task.BestResidualTasks[index].headerLen frame.writer.writeints(len, pos, (byte*)task.clRiceOutputPtr); } else { int psize = frame.blocksize >> porder; int res_cnt = psize - sub.best.order; // residual int j = sub.best.order; fixed (byte* fixbuf = frame.writer.Buffer) for (int p = 0; p < (1 << porder); p++) { int k = sub.best.rc.rparams[p]; frame.writer.writebits(4 + sub.best.rc.coding_method, k); if (p == 1) res_cnt = psize; int cnt = Math.Min(res_cnt, frame.blocksize - j); frame.writer.write_rice_block_signed(fixbuf, k, sub.best.residual + j, cnt); j += cnt; } } }
unsafe int measure_residual(FlacFrame frame, FlacSubframeInfo sub) { // partition order int porder = sub.best.rc.porder; int psize = frame.blocksize >> porder; //assert(porder >= 0); int size = 6 + ((4 + sub.best.rc.coding_method) << porder); size += measure_residual(frame, sub, sub.best.order, psize - sub.best.order, sub.best.rc.rparams[0]); // residual for (int p = 1; p < (1 << porder); p++) size += measure_residual(frame, sub, p * psize, psize, sub.best.rc.rparams[p]); return size; }
unsafe int measure_residual(FlacFrame frame, FlacSubframeInfo sub, int pos, int cnt, int k) { int q = 0; for (int i = pos; i < pos + cnt; i++) { int v = sub.best.residual[i]; uint uv = (uint)((v << 1) ^ (v >> 31)); q += (int)(uv >> k); } return (k + 1) * cnt + q; }
output_subframe_constant(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub) { bitwriter.writebits_signed(sub.obits, sub.best.residual[0]); }
output_subframe_fixed(FLACCLTask task, FlacSubframeInfo sub, int index) { FlacFrame frame = task.frame; // warm-up samples for (int i = 0; i < sub.best.order; i++) frame.writer.writebits_signed(sub.obits, sub.samples[i]); // residual output_residual(task, sub, sub.obits * sub.best.order, index); }
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. }
measure_subframe_fixed(FlacFrame frame, FlacSubframeInfo sub) { return (uint)(sub.best.order * sub.obits + measure_residual(frame, sub)); }
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); }
output_subframe_lpc(FlacFrame frame, FlacSubframeInfo sub) { // warm-up samples for (int i = 0; i < sub.best.order; i++) frame.writer.writebits_signed(sub.obits, sub.samples[i]); // LPC coefficients frame.writer.writebits(4, sub.best.cbits - 1); frame.writer.writebits_signed(5, sub.best.shift); for (int i = 0; i < sub.best.order; i++) frame.writer.writebits_signed(sub.best.cbits, sub.best.coefs[i]); // residual output_residual(frame, sub); }