diff --git a/CUERipper/frmCUERipper.Designer.cs b/CUERipper/frmCUERipper.Designer.cs index 664857f..078be7a 100644 --- a/CUERipper/frmCUERipper.Designer.cs +++ b/CUERipper/frmCUERipper.Designer.cs @@ -143,7 +143,6 @@ namespace CUERipper resources.ApplyResources(this.statusStrip1, "statusStrip1"); this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.ShowItemToolTips = true; - this.statusStrip1.SizingGrip = false; // // toolStripStatusLabel1 // @@ -786,9 +785,7 @@ namespace CUERipper this.Controls.Add(this.panel6); this.Controls.Add(this.statusStrip1); this.KeyPreview = true; - this.MaximizeBox = false; this.Name = "frmCUERipper"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.frmCUERipper_FormClosed); this.Load += new System.EventHandler(this.frmCUERipper_Load); this.ClientSizeChanged += new System.EventHandler(this.frmCUERipper_ClientSizeChanged); diff --git a/CUERipper/frmCUERipper.resx b/CUERipper/frmCUERipper.resx index 5ea89c7..8805865 100644 --- a/CUERipper/frmCUERipper.resx +++ b/CUERipper/frmCUERipper.resx @@ -780,7 +780,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABy - CQAAAk1TRnQBSQFMAgEBBAEAAZQBAQGUAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CQAAAk1TRnQBSQFMAgEBBAEAAawBAQGsAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA @@ -930,7 +930,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADy - EAAAAk1TRnQBSQFMAgEBCgEAAZQBAQGUAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + EAAAAk1TRnQBSQFMAgEBCgEAAawBAQGsAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAATADAAEBAQABCAYAAQwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/CUETools.AccurateRip/CDRepair.cs b/CUETools.AccurateRip/CDRepair.cs index 1cc8589..af43fc1 100644 --- a/CUETools.AccurateRip/CDRepair.cs +++ b/CUETools.AccurateRip/CDRepair.cs @@ -304,10 +304,11 @@ namespace CUETools.AccurateRip return count; } - public string GetAffectedSectors(int min, int max) + public string GetAffectedSectors(int min, int max, int offs = 0) { min = Math.Max(2 * min, 2 * pregap + stride - 2 * ActualOffset); max = Math.Min(2 * max, 2 * finalSampleCount - laststride - 2 * ActualOffset); + offs = offs * 2; StringBuilder sb = new StringBuilder(); for (int i = 0; i < correctableErrors; i++) if (erroffsorted[i] >= min && erroffsorted[i] < max) @@ -316,8 +317,8 @@ namespace CUETools.AccurateRip for (j = i + 1; j < correctableErrors; j++) if (erroffsorted[j] - erroffsorted[j - 1] > 2 * 588 * 5) break; - uint sec1 = (uint)(erroffsorted[i] - min) / 2 / 588; - uint sec2 = (uint)(erroffsorted[j - 1] - min) / 2 / 588; + uint sec1 = (uint)(erroffsorted[i] - offs) / 2 / 588; + uint sec2 = (uint)(erroffsorted[j - 1] - offs) / 2 / 588; if (sb.Length != 0) sb.Append(","); sb.Append(CDImageLayout.TimeToString(sec1)); if (sec1 != sec2) sb.Append("-"); @@ -344,7 +345,14 @@ namespace CUETools.AccurateRip for (int pos = firstPos; pos < lastPos; pos++) { if (nexterroff < erroffsorted.Length && sampleCount * 2 + pos == erroffsorted[nexterroff]) - data[pos] ^= forneysorted[nexterroff++]; + { + data[pos] ^= forneysorted[nexterroff++]; + // When we modify sampleBuffer.Bytes, which might have been + // copied from sampleBuffer.Samples, which wasn't modified, + // we need to make sure sampleBuffer.Samples will be reset; + // This strange call makes sure of that. + sampleBuffer.Prepare(sampleBuffer.Bytes, sampleBuffer.Length); + } ushort dd = data[pos]; crc = (crc >> 8) ^ t[(byte)(crc ^ dd)]; diff --git a/CUETools.CTDB/CUEToolsDB.cs b/CUETools.CTDB/CUEToolsDB.cs index d469169..141c1c6 100644 --- a/CUETools.CTDB/CUEToolsDB.cs +++ b/CUETools.CTDB/CUEToolsDB.cs @@ -539,11 +539,11 @@ namespace CUETools.CTDB string confFormat = (this.Total < 10) ? "{0:0}/{1:0}" : (this.Total < 100) ? "{0:00}/{1:00}" : "{0:000}/{1:000}"; string conf = string.Format(confFormat, entry.conf, this.Total); - string dataTrackInfo = !entry.toc[entry.toc.TrackCount].IsAudio && this.toc[entry.toc.TrackCount].IsAudio ? + string dataTrackInfo = !entry.toc[entry.toc.TrackCount].IsAudio && this.toc[this.toc.TrackCount].IsAudio ? string.Format("CD-Extra data track length {0}", entry.toc[entry.toc.TrackCount].LengthMSF) : !entry.toc[1].IsAudio && this.toc[1].IsAudio ? string.Format("Playstation type data track length {0}", entry.toc[entry.toc.FirstAudio].StartMSF) : - (entry.toc[1].IsAudio && !this.toc[1].IsAudio) || (entry.toc[entry.toc.TrackCount].IsAudio && !this.toc[entry.toc.TrackCount].IsAudio) ? + (entry.toc[1].IsAudio && !this.toc[1].IsAudio) || (entry.toc[entry.toc.TrackCount].IsAudio && !this.toc[this.toc.TrackCount].IsAudio) ? "Has no data track" : ""; if (entry.toc.Pregap != this.toc.Pregap) dataTrackInfo = dataTrackInfo + (dataTrackInfo == "" ? "" : ", ") + string.Format("Has pregap length {0}", CDImageLayout.TimeToString(entry.toc.Pregap)); @@ -588,7 +588,7 @@ namespace CUETools.CTDB } resConfidence.Add(entry.conf); - resStatus.Add(string.Format("differs in {0} samples @{1}", diffCount, entry.repair.GetAffectedSectors(min, max))); + resStatus.Add(string.Format("differs in {0} samples @{1}", diffCount, entry.repair.GetAffectedSectors(min, max, min))); continue; } if (entry.trackcrcs != null) diff --git a/CUETools.Codecs.ALAC/ALACWriter.cs b/CUETools.Codecs.ALAC/ALACWriter.cs index 9fdc77b..7e85824 100644 --- a/CUETools.Codecs.ALAC/ALACWriter.cs +++ b/CUETools.Codecs.ALAC/ALACWriter.cs @@ -916,7 +916,7 @@ namespace CUETools.Codecs.ALAC lpc_ctx.GetReflection(max_order, smp, n, frame.window_buffer + iWindow * Alac.MAX_BLOCKSIZE * 2); lpc_ctx.ComputeLPC(lpcs); - lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, max_order, 5.0, 1.0/18); + lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, min_order, max_order, 5.0, 1.0/18); for (i = 0; i < eparams.estimation_depth && i < max_order; i++) encode_residual_lpc_sub(frame, lpcs, iWindow, lpc_ctx.best_orders[i], ch); } @@ -1021,7 +1021,7 @@ namespace CUETools.Codecs.ALAC int stereo_order = Math.Min(8, eparams.max_prediction_order); double alpha = 1.5; // 4.5 + eparams.max_prediction_order / 10.0; lpc_ctx.GetReflection(stereo_order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer); - lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, stereo_order, alpha, 0); + lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 1, stereo_order, alpha, 0); frame.subframes[ch].best.size = (uint)Math.Max(0, lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], alpha, 0)); } break; diff --git a/CUETools.Codecs.FLAKE/FlakeReader.cs b/CUETools.Codecs.FLAKE/FlakeReader.cs index acb1b92..121344f 100644 --- a/CUETools.Codecs.FLAKE/FlakeReader.cs +++ b/CUETools.Codecs.FLAKE/FlakeReader.cs @@ -102,7 +102,7 @@ namespace CUETools.Codecs.FLAKE } _samplesInBuffer = 0; - if ((PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24) || PCM.ChannelCount != 2 || (PCM.SampleRate != 44100 && PCM.SampleRate != 48000)) + if (PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24) throw new Exception("invalid flac file"); samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; @@ -226,7 +226,7 @@ namespace CUETools.Codecs.FLAKE { int* psrc = src; for (int i = 0; i < count; i++) - res[i + i] = *(psrc++); + res[i * PCM.ChannelCount] = *(psrc++); } } } diff --git a/CUETools.Codecs.FLAKE/FlakeWriter.cs b/CUETools.Codecs.FLAKE/FlakeWriter.cs index 5f012f8..d7c1130 100644 --- a/CUETools.Codecs.FLAKE/FlakeWriter.cs +++ b/CUETools.Codecs.FLAKE/FlakeWriter.cs @@ -127,8 +127,8 @@ namespace CUETools.Codecs.FLAKE //if (_pcm.BitsPerSample != 16) // throw new Exception("Bits per sample must be 16."); - if (_pcm.ChannelCount != 2) - throw new Exception("ChannelCount must be 2."); + //if (_pcm.ChannelCount != 2) + // throw new Exception("ChannelCount must be 2."); channels = pcm.ChannelCount; @@ -250,7 +250,7 @@ namespace CUETools.Codecs.FLAKE } _IO.Close(); inited = false; - } + } #if INTEROP long fake, KernelStart, UserStart; @@ -321,7 +321,13 @@ namespace CUETools.Codecs.FLAKE set { eparams.window_method = value; } } - public int MinPrecisionSearch + public int DevelopmentMode + { + get { return eparams.development_mode; } + set { eparams.development_mode = value; } + } + + public int MinPrecisionSearch { get { return eparams.lpc_min_precision_search; } set @@ -401,8 +407,10 @@ namespace CUETools.Codecs.FLAKE } set { - if (value < 1 || value > eparams.max_prediction_order) + if (value < 1) throw new Exception("invalid MinLPCOrder " + value.ToString()); + if (eparams.max_prediction_order < value) + eparams.max_prediction_order = value; eparams.min_prediction_order = value; } } @@ -415,9 +423,11 @@ namespace CUETools.Codecs.FLAKE } set { - if (value > lpc.MAX_LPC_ORDER || value < eparams.min_prediction_order) + if (value > lpc.MAX_LPC_ORDER) throw new Exception("invalid MaxLPCOrder " + value.ToString()); - eparams.max_prediction_order = value; + if (eparams.min_prediction_order > value) + eparams.min_prediction_order = value; + eparams.max_prediction_order = value; } } @@ -748,12 +758,45 @@ namespace CUETools.Codecs.FLAKE } } + static unsafe uint calc_rice_params_sums(RiceContext rc, int pmin, int pmax, ulong* sums, uint n, uint pred_order, int bps) + { + int* parm = stackalloc int[(pmax + 1) * Flake.MAX_PARTITIONS]; + //uint* bits = stackalloc uint[Flake.MAX_PARTITION_ORDER]; + + //assert(pmin >= 0 && pmin <= Flake.MAX_PARTITION_ORDER); + //assert(pmax >= 0 && pmax <= Flake.MAX_PARTITION_ORDER); + //assert(pmin <= pmax); + + // sums for lower levels + calc_lower_sums(pmin, pmax, sums); + + uint opt_bits = AudioSamples.UINT32_MAX; + int opt_porder = pmin; + int opt_method = 0; + for (int i = pmin; i <= pmax; i++) + { + int method = bps > 16 ? 1 : 0; + uint bits = calc_optimal_rice_params(i, parm + i * Flake.MAX_PARTITIONS, sums + i * Flake.MAX_PARTITIONS, n, pred_order, ref method); + if (bits <= opt_bits) + { + opt_bits = bits; + opt_porder = i; + opt_method = method; + } + } + + rc.porder = opt_porder; + rc.coding_method = opt_method; + fixed (int* rparms = rc.rparams) + AudioSamples.MemCpy(rparms, parm + opt_porder * Flake.MAX_PARTITIONS, (1 << opt_porder)); + + return opt_bits; + } + static unsafe uint calc_rice_params(RiceContext rc, int pmin, int pmax, int* data, uint n, uint pred_order, int bps) { uint* udata = stackalloc uint[(int)n]; ulong* sums = stackalloc ulong[(pmax + 1) * Flake.MAX_PARTITIONS]; - int* parm = stackalloc int[(pmax + 1) * Flake.MAX_PARTITIONS]; - //uint* bits = stackalloc uint[Flake.MAX_PARTITION_ORDER]; //assert(pmin >= 0 && pmin <= Flake.MAX_PARTITION_ORDER); //assert(pmax >= 0 && pmax <= Flake.MAX_PARTITION_ORDER); @@ -769,30 +812,8 @@ namespace CUETools.Codecs.FLAKE calc_sums16(pmin, pmax, udata, n, pred_order, sums + pmax * Flake.MAX_PARTITIONS); else calc_sums(pmin, pmax, udata, n, pred_order, sums + pmax * Flake.MAX_PARTITIONS); - // sums for lower levels - calc_lower_sums(pmin, pmax, sums); - uint opt_bits = AudioSamples.UINT32_MAX; - int opt_porder = pmin; - int opt_method = 0; - for (int i = pmin; i <= pmax; i++) - { - int method = bps > 16 ? 1 : 0; - uint bits = calc_optimal_rice_params(i, parm + i * Flake.MAX_PARTITIONS, sums + i * Flake.MAX_PARTITIONS, n, pred_order, ref method); - if (bits <= opt_bits) - { - opt_bits = bits; - opt_porder = i; - opt_method = method; - } - } - - rc.porder = opt_porder; - rc.coding_method = opt_method; - fixed (int* rparms = rc.rparams) - AudioSamples.MemCpy(rparms, parm + opt_porder * Flake.MAX_PARTITIONS, (1 << opt_porder)); - - return opt_bits; + return calc_rice_params_sums(rc, pmin, pmax, sums, n, pred_order, bps); } static int get_max_p_order(int max_porder, int n, int order) @@ -803,74 +824,323 @@ namespace CUETools.Codecs.FLAKE return porder; } - 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; +// private static int[,] best_x = new int[14,8193]; + private static int[][] good_x = new int[][] { +new int[] {}, // 0 +new int[] { // 1 +0x03,0x01,0x00,0x02 +}, +new int[] {// 2 +0x01,0x07,0x06,0x02, 0x03,0x04,0x00,0x05 +}, +new int[] { // 3 +0x0b,0x0f,0x0e,0x0d, 0x03,0x01,0x05,0x02 +}, +new int[] { //4 +0x17,0x09,0x03,0x0a, 0x06,0x1d,0x1f,0x05, 0x1c,0x0d,0x07,0x0c, +}, +new int[] { // 5 +0x2b,0x3d,0x37,0x07, 0x11,0x15,0x36,0x3f, +}, +new int[] { // 6 +0x6b,0x15,0x7e,0x31, 0x07,0x1a,0x29,0x26, 0x5d,0x23,0x6f,0x19, 0x56,0x75 +}, +new int[] { // 7 +0xdb,0xef,0xb5,0x47, 0xee,0x63,0x0b,0xfd, 0x31,0xbe,0xed,0x33, 0xff,0xfb,0xd6,0xbb +}, +new int[] { // 8 +0x1bb,0x1c7,0x069,0x087, 0x1fd,0x16e,0x095,0x1de, 0x066,0x071,0x055,0x09a, +}, +new int[] { // 9 +0x36b,0x3bd,0x097,0x0c3, 0x0e3,0x0b1,0x107,0x2de, 0x3ef,0x2fb,0x3d5,0x139 +}, +new int[] { // 10 +//0x0e3,0x199,0x383,0x307, 0x1e3,0x01f,0x269,0x0f1, 0x266,0x03f,0x2cd,0x1c3, 0x19a,0x387,0x339,0x259, +0x6eb,0x187,0x77d,0x271, 0x195,0x259,0x5ae,0x169, +}, +new int[] { // 11 +0xddb,0xf77,0xb6d,0x587, 0x2c3,0x03b,0xef5,0x1e3, 0xdbe, +}, +new int[] { // 12 +0x1aeb,0x0587,0x0a71,0x1dbd, 0x0559,0x0aa5,0x0a2e,0x0d43, 0x05aa,0x00f3,0x0696,0x03c6, +}, +new int[] { // 13 +0x35d7,0x2f6f,0x0aa3,0x1569, 0x150f,0x3d79,0x0dc3,0x309f/*?*/, +}, +new int[] { // 14 +0x75d7,0x5f7b,0x6a8f,0x29a3, +}, +new int[] { // 15 +0xddd7,0xaaaf,0x55c3,0xf77b, +}, +new int[] { // 16 +0x1baeb,0x1efaf,0x1d5bf,0x1cff3, +}, +new int[] { // 17 +0x36dd7,0x3bb7b,0x3df6f,0x2d547, +}, +new int[] { // 18 +0x75dd7,0x6f77b,0x7aaaf,0x5ddd3, +}, +new int[] { // 19 +0xdddd7,0xf777b,0xd5547,0xb6ddb, +}, +new int[] { // 20 +0x1baeeb,0x1efbaf,0x1aaabf,0x17bbeb, +}, +new int[] { // 21 +0x376dd7,0x3ddf7b,0x2d550f,0x0aaaa3, +}, +new int[] { // 22 +0x6eddd7,0x77777b,0x5dcd4f,0x5d76f9, +}, +new int[] { // 23 +0xdeddd7,0xb5b6eb,0x55552b,0x2aaac3, +}, +new int[] { // 24 +0x1dddbb7,0x1b76eeb,0x17bbf5f,0x1eeaa9f, +}, +new int[] { // 25 +}, +new int[] { // 26 +}, +new int[] { // 27 +}, +new int[] { // 28 +}, +new int[] { // 29 +}, +new int[] { // 30 +}, + }; - 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)); + 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]; - uint cbits = lpc_precision + (uint)i_precision; + 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 = order; - frame.current.window = iWindow; + 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; - 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 (((x >> orig_order) & 1) != 0) + { + frame.current.shift--; + frame.current.cbits--; + if (frame.current.shift < 0 || frame.current.cbits < 2) + continue; + } - if (frame.current.shift < 0 || frame.current.shift > 15) - throw new Exception("negative shift"); + 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]); + } - ulong csum = 0; - for (int i = frame.current.order; i > 0; i--) - csum += (ulong)Math.Abs(coefs[i - 1]); + 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); + } - 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, 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); - } - 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); - } - } + 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>(); + // for (int x = 0; x < (1 << o); x++) + // if (best_x[o, x] != 0) + // s.Add(new KeyValuePair(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(); + // } + //} + } + + public static void SetCoefs(int order, int[] coefs) + { + good_x[order] = new int[coefs.Length]; + for (int i = 0; i < coefs.Length; i++) + good_x[order][i] = coefs[i]; + } + + 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; + frame.current.cbits = (int)cbits; + + 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); + //if (frame.current.size >= frame.subframes[ch].best.size) + // postprocess_coefs(frame, frame.current, ch); + //else + //{ + // frame.ChooseBestSubframe(ch); + // postprocess_coefs(frame, frame.subframes[ch].best, ch); + //} + } + } unsafe void encode_residual_fixed_sub(FlacFrame frame, int order, int ch) { @@ -919,20 +1189,6 @@ namespace CUETools.Codecs.FLAKE 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 || @@ -1009,7 +1265,7 @@ namespace CUETools.Codecs.FLAKE { 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); + lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, min_order, max_order, 4.5, 0.0); break; default: throw new Exception("unknown order method"); @@ -1017,9 +1273,26 @@ namespace CUETools.Codecs.FLAKE for (i = 0; i < eparams.estimation_depth && i < max_order; i++) encode_residual_lpc_sub(frame, lpcs, iWindow, lpc_ctx.best_orders[i], ch); - } - } - } + } + + postprocess_coefs(frame, frame.subframes[ch].best, ch); + } + + // 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_fixed_order && 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); + } + + } unsafe void output_frame_header(FlacFrame frame, BitWriter bitwriter) { @@ -1186,12 +1459,14 @@ namespace CUETools.Codecs.FLAKE 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 = 8; + eparams.max_prediction_order = Math.Min(eparams.max_prediction_order, Math.Max(eparams.min_prediction_order, 8)); eparams.estimation_depth = 1; - encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window); + 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; @@ -1199,6 +1474,7 @@ namespace CUETools.Codecs.FLAKE 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; } unsafe void encode_residual_pass2(FlacFrame frame, int ch) @@ -1250,13 +1526,13 @@ namespace CUETools.Codecs.FLAKE { 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); + lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 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); + for (int ch = 0; ch < subframes; ch++) + encode_residual_pass1(frame, ch, 0); break; case StereoMethod.Search: for (int ch = 0; ch < subframes; ch++) @@ -1910,6 +2186,8 @@ namespace CUETools.Codecs.FLAKE public bool do_seektable; + public int development_mode; + public int flake_set_defaults(int lvl) { compression = lvl; @@ -1937,7 +2215,8 @@ namespace CUETools.Codecs.FLAKE variable_block_size = 0; lpc_min_precision_search = 1; lpc_max_precision_search = 1; - do_seektable = true; + do_seektable = true; + development_mode = -1; // differences from level 7 switch (lvl) diff --git a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp index 0b5f5cc..fc0fa1e 100644 --- a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp +++ b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp @@ -275,7 +275,9 @@ namespace CUETools { namespace Codecs { namespace WavPack { if (_IO_WVC_ungetc != -1) throw gcnew Exception("Double PushBackCallback unsupported."); _IO_WVC_ungetc = c; - } + } + + return 0; } uint32_t LengthCallback (void *id) diff --git a/CUETools.Codecs/LPC.cs b/CUETools.Codecs/LPC.cs index 77aabbb..c457ed6 100644 --- a/CUETools.Codecs/LPC.cs +++ b/CUETools.Codecs/LPC.cs @@ -267,7 +267,7 @@ namespace CUETools.Codecs { error += lpc_in[i] * (1 << sh); q = (int)(error + 0.5); - if (q <= -qmax) q = -qmax + 1; + if (q < -(qmax+1)) q = -(qmax + 1); if (q > qmax) q = qmax; error -= q; lpc_out[i] = q; diff --git a/CUETools.Codecs/LpcContext.cs b/CUETools.Codecs/LpcContext.cs index 1f63565..fc6b970 100644 --- a/CUETools.Codecs/LpcContext.cs +++ b/CUETools.Codecs/LpcContext.cs @@ -94,13 +94,14 @@ namespace CUETools.Codecs /// Sorts orders based on Akaike's criteria /// /// Frame size - public void SortOrdersAkaike(int blocksize, int count, int max_order, double alpha, double beta) + public void SortOrdersAkaike(int blocksize, int count, int min_order, int max_order, double alpha, double beta) { - for (int i = 0; i < max_order; i++) - best_orders[i] = i + 1; - for (int i = 0; i < max_order && i < count; i++) + for (int i = min_order; i <= max_order; i++) + best_orders[i - min_order] = i; + int lim = max_order - min_order + 1; + for (int i = 0; i < lim && i < count; i++) { - for (int j = i + 1; j < max_order; j++) + for (int j = i + 1; j < lim; j++) { if (Akaike(blocksize, best_orders[j], alpha, beta) < Akaike(blocksize, best_orders[i], alpha, beta)) { diff --git a/CUETools.Converter/CUETools.Converter.csproj b/CUETools.Converter/CUETools.Converter.csproj index 92b8632..2a39687 100644 --- a/CUETools.Converter/CUETools.Converter.csproj +++ b/CUETools.Converter/CUETools.Converter.csproj @@ -55,10 +55,6 @@ - - False - ..\ThirdParty\taglib-sharp.dll - @@ -73,6 +69,10 @@ {4911BD82-49EF-4858-8B51-5394F86739A4} CUETools.Processor + + {6B143A39-C7B2-4743-9917-92262C60E9A6} + taglib-sharp + diff --git a/CUETools.Flake/Program.cs b/CUETools.Flake/Program.cs index e30f34d..09d39f5 100644 --- a/CUETools.Flake/Program.cs +++ b/CUETools.Flake/Program.cs @@ -1,3 +1,4 @@ +//#define FINETUNE using System; using System.Collections.Generic; using System.Text; @@ -7,309 +8,515 @@ using CUETools.Codecs.FLAKE; namespace CUETools.FlakeExe { - class Program - { - static void Usage() - { - Console.WriteLine("Usage : CUETools.Flake.exe [options] "); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(); - Console.WriteLine(" -0 .. -11 Compression level, default 7."); - Console.WriteLine(" -o Output filename, or \"-\" for stdout, or nul."); - Console.WriteLine(" -p # Padding bytes."); - Console.WriteLine(" -q --quiet Quiet mode."); - Console.WriteLine(" --verify Verify during encoding."); - Console.WriteLine(" --no-md5 Don't compute MD5 hash."); - Console.WriteLine(" --no-seektable Don't generate a seektable."); - Console.WriteLine(); - Console.WriteLine("Advanced Options:"); - Console.WriteLine(); - Console.WriteLine(" -b # Block size."); - Console.WriteLine(" -v # Variable block size mode (0,4)."); - Console.WriteLine(" -t Prediction type (fixed,levinson,search)."); - Console.WriteLine(" -s Stereo decorrelation (independent,estimate,evaluate,search)."); - Console.WriteLine(" -r #[,#] Rice partition order {max} or {min},{max} (0..8)."); - Console.WriteLine(); - Console.WriteLine("LPC options:"); - Console.WriteLine(); - Console.WriteLine(" -m Prediction order search (akaike)."); - Console.WriteLine(" -e # Prediction order search depth (1..32)."); - Console.WriteLine(" -w [,] One or more window functions (bartlett,welch,hann,flattop,tukey)."); - Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..32)."); - Console.WriteLine(" --window-method Window selection method (estimate,evaluate,search)."); - Console.WriteLine(" --max-precision Coefficients precision search (0..1)."); - Console.WriteLine(); - Console.WriteLine("Fixed prediction options:"); - Console.WriteLine(); - Console.WriteLine(" -f #[,#] Prediction order {max} or {min},{max} (0..4)."); - } +#if FINETUNE + class FineTuneTask + { + public int code; + public int size; + public int no; + public int gen; + public int min_depth; + public List parents; - static int Main(string[] args) - { - TextWriter stdout = Console.Out; - Console.SetOut(Console.Error); + public bool IsImprovement + { + get + { + return this.parents.TrueForAll(p => this.size < p.size); + } + } - DateTime start = DateTime.Now; - TimeSpan lastPrint = TimeSpan.FromMilliseconds(0); - bool debug = false, quiet = false; - string prediction_type = null; - string stereo_method = null; - string window_method = null; - string order_method = null; - string window_function = null; - string input_file = null; - string output_file = null; - int min_partition_order = -1, max_partition_order = -1, - min_lpc_order = -1, max_lpc_order = -1, - min_fixed_order = -1, max_fixed_order = -1, - min_precision = -1, max_precision = -1, - blocksize = -1, estimation_depth = -1; - int level = -1, padding = -1, vbr_mode = -1; - bool do_md5 = true, do_seektable = true, do_verify = false; - bool buffered = false; + public bool done + { + get + { + return this.size != int.MaxValue; + } + } - for (int arg = 0; arg < args.Length; arg++) - { - bool ok = true; - if (args[arg].Length == 0) - ok = false; - else if (args[arg] == "--debug") - debug = true; - else if ((args[arg] == "-q" || args[arg] == "--quiet")) - quiet = true; - else if (args[arg] == "--verify") - do_verify = true; - else if (args[arg] == "--no-seektable") - do_seektable = false; - else if (args[arg] == "--no-md5") - do_md5 = false; - else if (args[arg] == "--buffered") - buffered = true; - else if ((args[arg] == "-o" || args[arg] == "--output") && ++arg < args.Length) - output_file = args[arg]; - else if ((args[arg] == "-t" || args[arg] == "--prediction-type") && ++arg < args.Length) - prediction_type = args[arg]; - else if ((args[arg] == "-s" || args[arg] == "--stereo") && ++arg < args.Length) - stereo_method = args[arg]; - else if ((args[arg] == "-m" || args[arg] == "--order-method") && ++arg < args.Length) - order_method = args[arg]; - else if ((args[arg] == "-w" || args[arg] == "--window") && ++arg < args.Length) - window_function = args[arg]; - else if (args[arg] == "--window-method" && ++arg < args.Length) - window_method = args[arg]; - else if ((args[arg] == "-r" || args[arg] == "--partition-order") && ++arg < args.Length) - { - ok = (args[arg].Split(',').Length == 2 && - int.TryParse(args[arg].Split(',')[0], out min_partition_order) && - int.TryParse(args[arg].Split(',')[1], out max_partition_order)) || - int.TryParse(args[arg], out max_partition_order); - } - else if ((args[arg] == "-l" || args[arg] == "--lpc-order") && ++arg < args.Length) - { - ok = (args[arg].Split(',').Length == 2 && - int.TryParse(args[arg].Split(',')[0], out min_lpc_order) && - int.TryParse(args[arg].Split(',')[1], out max_lpc_order)) || - int.TryParse(args[arg], out max_lpc_order); - } - else if ((args[arg] == "-f" || args[arg] == "--fixed-order") && ++arg < args.Length) - { - ok = (args[arg].Split(',').Length == 2 && - int.TryParse(args[arg].Split(',')[0], out min_fixed_order) && - int.TryParse(args[arg].Split(',')[1], out max_fixed_order)) || - int.TryParse(args[arg], out max_fixed_order); - } - else if ((args[arg] == "-e" || args[arg] == "--estimation-depth") && ++arg < args.Length) - ok = int.TryParse(args[arg], out estimation_depth); - else if ((args[arg] == "-c" || args[arg] == "--max-precision") && ++arg < args.Length) - { - ok = (args[arg].Split(',').Length == 2 && - int.TryParse(args[arg].Split(',')[0], out min_precision) && - int.TryParse(args[arg].Split(',')[1], out max_precision)) || - int.TryParse(args[arg], out max_precision); - } - else if ((args[arg] == "-v" || args[arg] == "--vbr")) - ok = (++arg < args.Length) && int.TryParse(args[arg], out vbr_mode); - else if ((args[arg] == "-b" || args[arg] == "--blocksize") && ++arg < args.Length) - ok = int.TryParse(args[arg], out blocksize); - else if ((args[arg] == "-p" || args[arg] == "--padding") && ++arg < args.Length) - ok = int.TryParse(args[arg], out padding); - else if (args[arg] != "-" && args[arg][0] == '-' && int.TryParse(args[arg].Substring(1), out level)) - ok = level >= 0 && level <= 11; - else if ((args[arg][0] != '-' || args[arg] == "-") && input_file == null) - input_file = args[arg]; - else - ok = false; - if (!ok) - { - Usage(); - return 1; - } - } - if (input_file == null || ((input_file == "-" || Path.GetExtension(input_file) == ".flac") && output_file == null)) - { - Usage(); - return 2; - } + public FineTuneTask(int code, int no) + { + this.code = code; + this.gen = 0; + this.no = no; + this.size = int.MaxValue; + this.min_depth = 0; + this.parents = new List(); + } - if (!quiet) - { - Console.WriteLine("CUETools.Flake, Copyright (C) 2009 Grigory Chudov."); - Console.WriteLine("Based on Flake encoder by Justin Ruggles, ."); - Console.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to"); - Console.WriteLine("the extent permitted by law. for details."); - } + public FineTuneTask(int code, int no, FineTuneTask parent) + : this(code, no) + { + this.gen = parent.gen + 1; + this.parents.Add(parent); + } - IAudioSource audioSource; - if (input_file == "-") - audioSource = new WAVReader("", Console.OpenStandardInput()); - else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".wav") - audioSource = new WAVReader(input_file, null); - else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".flac") - audioSource = new FlakeReader(input_file, null); - else - { - Usage(); - return 3; - } - if (buffered) - audioSource = new AudioPipe(audioSource, 0x10000); - if (output_file == null) - output_file = Path.ChangeExtension(input_file, "flac"); - FlakeWriter flake = new FlakeWriter((output_file == "-" || output_file == "nul") ? "" : output_file, - output_file == "-" ? Console.OpenStandardOutput() : - output_file == "nul" ? new NullStream() : null, - audioSource.PCM); - flake.FinalSampleCount = audioSource.Length; - IAudioDest audioDest = flake; - AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); + public List GetDerivativeCodes(int max_lpc_order) + { + var codes = new List(); + for (int ft = 0; ft < max_lpc_order; ft++) + { + int c1 = this.code ^ (1 << ft); + codes.Add(c1); + } - try - { - if (level >= 0) - flake.CompressionLevel = level; - if (prediction_type != null) - flake.PredictionType = Flake.LookupPredictionType(prediction_type); - if (stereo_method != null) - flake.StereoMethod = Flake.LookupStereoMethod(stereo_method); - if (window_method != null) - flake.WindowMethod = Flake.LookupWindowMethod(window_method); - if (order_method != null) - flake.OrderMethod = Flake.LookupOrderMethod(order_method); - if (window_function != null) - flake.WindowFunction = Flake.LookupWindowFunction(window_function); - if (min_partition_order >= 0) - flake.MinPartitionOrder = min_partition_order; - if (max_partition_order >= 0) - flake.MaxPartitionOrder = max_partition_order; - if (min_lpc_order >= 0) - flake.MinLPCOrder = min_lpc_order; - if (max_lpc_order >= 0) - flake.MaxLPCOrder = max_lpc_order; - if (min_fixed_order >= 0) - flake.MinFixedOrder = min_fixed_order; - if (max_fixed_order >= 0) - flake.MaxFixedOrder = max_fixed_order; - if (max_precision >= 0) - flake.MaxPrecisionSearch = max_precision; - if (min_precision >= 0) - flake.MinPrecisionSearch = min_precision; - if (blocksize >= 0) - flake.BlockSize = blocksize; - if (estimation_depth >= 0) - flake.EstimationDepth = estimation_depth; - if (padding >= 0) - flake.Padding = padding; - if (vbr_mode >= 0) - flake.VBRMode = vbr_mode; - flake.DoSeekTable = do_seektable; - (flake.Settings as FlakeWriterSettings).DoVerify = do_verify; - (flake.Settings as FlakeWriterSettings).DoMD5 = do_md5; - } - catch (Exception ex) - { - Usage(); - Console.WriteLine(""); - Console.WriteLine("Error: {0}.", ex.Message); - return 4; - } + for (int ft = 0; ft < max_lpc_order; ft++) + { + for (int ft1 = ft + 1; ft1 < max_lpc_order; ft1++) + if (((this.code >> ft1) & 1) != ((this.code >> ft) & 1)) + { + int c1 = this.code ^ (1 << ft) ^ (1 << ft1); + codes.Add(c1); + break; + } + + for (int ft1 = ft - 1; ft1 >= 0; ft1--) + if (((this.code >> ft1) & 1) != ((this.code >> ft) & 1)) + { + int c1 = this.code ^ (1 << ft) ^ (1 << ft1); + codes.Add(c1); + break; + } + } - if (!quiet) - { - Console.WriteLine("Filename : {0}", input_file); - Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.PCM.SampleRate)); - } - -#if !DEBUG - try -#endif - { - while (audioSource.Read(buff, -1) != 0) - { - audioDest.Write(buff); - TimeSpan elapsed = DateTime.Now - start; - if (!quiet) - { - if ((elapsed - lastPrint).TotalMilliseconds > 60) - { - Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", - 100.0 * audioSource.Position / audioSource.Length, - audioSource.Position / elapsed.TotalSeconds / audioSource.PCM.SampleRate, - elapsed, - TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length) - ); - lastPrint = elapsed; - } - } - } - audioDest.Close(); - } -#if !DEBUG - catch (Exception ex) - { - Console.Error.Write("\r \r"); - Console.WriteLine("Error : {0}", ex.Message); - audioDest.Delete(); - audioSource.Close(); - return 5; - } + return codes; + } + } #endif - TimeSpan totalElapsed = DateTime.Now - start; - if (!quiet) - { - Console.Error.Write("\r \r"); - Console.WriteLine("Results : {0:0.00}x; {2} bytes in {1} seconds;", - audioSource.Position / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, - totalElapsed, - flake.TotalSize - ); - } - audioSource.Close(); + class Program + { + static void Usage() + { + Console.WriteLine("Usage : CUETools.Flake.exe [options] "); + Console.WriteLine(); + Console.WriteLine("Options:"); + Console.WriteLine(); + Console.WriteLine(" -0 .. -11 Compression level, default 7."); + Console.WriteLine(" -o Output filename, or \"-\" for stdout, or nul."); + Console.WriteLine(" -p # Padding bytes."); + Console.WriteLine(" -q --quiet Quiet mode."); + Console.WriteLine(" --verify Verify during encoding."); + Console.WriteLine(" --no-md5 Don't compute MD5 hash."); + Console.WriteLine(" --no-seektable Don't generate a seektable."); + Console.WriteLine(); + Console.WriteLine("Advanced Options:"); + Console.WriteLine(); + Console.WriteLine(" -b # Block size."); + Console.WriteLine(" -v # Variable block size mode (0,4)."); + Console.WriteLine(" -t Prediction type (fixed,levinson,search)."); + Console.WriteLine(" -s Stereo decorrelation (independent,estimate,evaluate,search)."); + Console.WriteLine(" -r #[,#] Rice partition order {max} or {min},{max} (0..8)."); + Console.WriteLine(); + Console.WriteLine("LPC options:"); + Console.WriteLine(); + Console.WriteLine(" -m Prediction order search (akaike)."); + Console.WriteLine(" -e # Prediction order search depth (1..32)."); + Console.WriteLine(" -w [,] One or more window functions (bartlett,welch,hann,flattop,tukey)."); + Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..32)."); + Console.WriteLine(" --window-method Window selection method (estimate,evaluate,search)."); + Console.WriteLine(" --max-precision Coefficients precision search (0..1)."); + Console.WriteLine(); + Console.WriteLine("Fixed prediction options:"); + Console.WriteLine(); + Console.WriteLine(" -f #[,#] Prediction order {max} or {min},{max} (0..4)."); + } - if (debug) - { - Console.SetOut(stdout); - Console.Out.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}..{7}\t{8}..{9}\t{10}..{11}\t{12}..{13}\t{14}\t{15}", - flake.TotalSize, - flake.UserProcessorTime.TotalSeconds > 0 ? flake.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds, - flake.PredictionType.ToString().PadRight(15), - flake.StereoMethod.ToString().PadRight(15), - (flake.OrderMethod.ToString() + "(" + flake.EstimationDepth.ToString() + ")").PadRight(15), - flake.WindowFunction, - flake.MinPartitionOrder, - flake.MaxPartitionOrder, - flake.MinLPCOrder, - flake.MaxLPCOrder, - flake.MinFixedOrder, - flake.MaxFixedOrder, - flake.MinPrecisionSearch, - flake.MaxPrecisionSearch, - flake.BlockSize, - flake.VBRMode - ); - } - return 0; - } - } + static int Main(string[] args) + { + TextWriter stdout = Console.Out; + Console.SetOut(Console.Error); + + DateTime start = DateTime.Now; + TimeSpan lastPrint = TimeSpan.FromMilliseconds(0); + bool debug = false, quiet = false; + string prediction_type = null; + string stereo_method = null; + string window_method = null; + string order_method = null; + string window_function = null; + string input_file = null; + string output_file = null; + int min_partition_order = -1, max_partition_order = -1, + min_lpc_order = -1, max_lpc_order = -1, + min_fixed_order = -1, max_fixed_order = -1, + min_precision = -1, max_precision = -1, + blocksize = -1, estimation_depth = -1; + int skip_a = 0, skip_b = 0; + int level = -1, padding = -1, vbr_mode = -1, magic = -1; + bool do_md5 = true, do_seektable = true, do_verify = false; + bool buffered = false; + string coeffs = null; +#if FINETUNE + int finetune_depth = -1; +#endif + + for (int arg = 0; arg < args.Length; arg++) + { + bool ok = true; + if (args[arg].Length == 0) + ok = false; + else if (args[arg] == "--debug") + debug = true; + else if ((args[arg] == "-q" || args[arg] == "--quiet")) + quiet = true; + else if (args[arg] == "--verify") + do_verify = true; + else if (args[arg] == "--no-seektable") + do_seektable = false; + else if (args[arg] == "--no-md5") + do_md5 = false; + else if (args[arg] == "--buffered") + buffered = true; + else if ((args[arg] == "-o" || args[arg] == "--output") && ++arg < args.Length) + output_file = args[arg]; + else if ((args[arg] == "-t" || args[arg] == "--prediction-type") && ++arg < args.Length) + prediction_type = args[arg]; + else if ((args[arg] == "-s" || args[arg] == "--stereo") && ++arg < args.Length) + stereo_method = args[arg]; + else if ((args[arg] == "-m" || args[arg] == "--order-method") && ++arg < args.Length) + order_method = args[arg]; + else if ((args[arg] == "-w" || args[arg] == "--window") && ++arg < args.Length) + window_function = args[arg]; + else if (args[arg] == "--window-method" && ++arg < args.Length) + window_method = args[arg]; + else if ((args[arg] == "-r" || args[arg] == "--partition-order") && ++arg < args.Length) + { + ok = (args[arg].Split(',').Length == 2 && + int.TryParse(args[arg].Split(',')[0], out min_partition_order) && + int.TryParse(args[arg].Split(',')[1], out max_partition_order)) || + int.TryParse(args[arg], out max_partition_order); + } + else if ((args[arg] == "-l" || args[arg] == "--lpc-order") && ++arg < args.Length) + { + ok = (args[arg].Split(',').Length == 2 && + int.TryParse(args[arg].Split(',')[0], out min_lpc_order) && + int.TryParse(args[arg].Split(',')[1], out max_lpc_order)) || + int.TryParse(args[arg], out max_lpc_order); + } + else if ((args[arg] == "-f" || args[arg] == "--fixed-order") && ++arg < args.Length) + { + ok = (args[arg].Split(',').Length == 2 && + int.TryParse(args[arg].Split(',')[0], out min_fixed_order) && + int.TryParse(args[arg].Split(',')[1], out max_fixed_order)) || + int.TryParse(args[arg], out max_fixed_order); + } + else if (args[arg] == "--skip" && ++arg < args.Length) + { + ok = (args[arg].Split(',').Length == 2 && + int.TryParse(args[arg].Split(',')[0], out skip_a) && + int.TryParse(args[arg].Split(',')[1], out skip_b)) || + int.TryParse(args[arg], out skip_a); + } + else if ((args[arg] == "-e" || args[arg] == "--estimation-depth") && ++arg < args.Length) + ok = int.TryParse(args[arg], out estimation_depth); + else if ((args[arg] == "-c" || args[arg] == "--max-precision") && ++arg < args.Length) + { + ok = (args[arg].Split(',').Length == 2 && + int.TryParse(args[arg].Split(',')[0], out min_precision) && + int.TryParse(args[arg].Split(',')[1], out max_precision)) || + int.TryParse(args[arg], out max_precision); + } + else if ((args[arg] == "-v" || args[arg] == "--vbr")) + ok = (++arg < args.Length) && int.TryParse(args[arg], out vbr_mode); + else if ((args[arg] == "-b" || args[arg] == "--blocksize") && ++arg < args.Length) + ok = int.TryParse(args[arg], out blocksize); + else if ((args[arg] == "-p" || args[arg] == "--padding") && ++arg < args.Length) + ok = int.TryParse(args[arg], out padding); + else if (args[arg] == "--magic" && ++arg < args.Length) + ok = int.TryParse(args[arg], out magic); +#if FINETUNE + else if (args[arg] == "--depth" && ++arg < args.Length) + ok = int.TryParse(args[arg], out finetune_depth); +#endif + else if (args[arg] == "--coefs" && ++arg < args.Length) + coeffs = args[arg]; + else if (args[arg] != "-" && args[arg][0] == '-' && int.TryParse(args[arg].Substring(1), out level)) + ok = level >= 0 && level <= 11; + else if ((args[arg][0] != '-' || args[arg] == "-") && input_file == null) + input_file = args[arg]; + else + ok = false; + if (!ok) + { + Usage(); + return 1; + } + } + if (input_file == null || ((input_file == "-" || Path.GetExtension(input_file) == ".flac") && output_file == null)) + { + Usage(); + return 2; + } + + if (!quiet) + { + Console.WriteLine("CUETools.Flake, Copyright (C) 2009 Grigory Chudov."); + Console.WriteLine("Based on Flake encoder by Justin Ruggles, ."); + Console.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to"); + Console.WriteLine("the extent permitted by law. for details."); + } + +#if FINETUNE + var prefix = new List(); + if (coeffs != null) + { + var ps = coeffs.Split(','); + for (int i = 0; i < ps.Length; i++) + prefix.Add(ps[i].StartsWith("0x") ? int.Parse(ps[i].Substring(2), System.Globalization.NumberStyles.HexNumber) : int.Parse(ps[i])); + } + string codefmt = "0x{0:x" + (max_lpc_order / 4 + 1).ToString() + "}"; + + int max_prefix = magic >= 0 ? magic : 8; + do + { + FineTuneTask best_task = null; + var tasks = new Dictionary(); + if (prefix.Count == 0) + { + tasks.Add((1 << max_lpc_order) - 1, new FineTuneTask((1 << max_lpc_order) - 1, 1)); + tasks.Add((2 << max_lpc_order) - 1, new FineTuneTask((2 << max_lpc_order) - 1, 2)); + //tasks.Add((3 << max_lpc_order) - 1, new FineTuneTask((3 << max_lpc_order) - 1, 3)); + //tasks.Add((4 << max_lpc_order) - 1, new FineTuneTask((4 << max_lpc_order) - 1, 4)); + } + else + { + foreach (var c in prefix) + { + tasks.Add(c, new FineTuneTask(c, 1)); + tasks.Add((1 << max_lpc_order) ^ c, new FineTuneTask((1 << max_lpc_order) ^ c, 2)); + } + } + int total_added_tasks = tasks.Values.Count; + + do + { + foreach (var task in tasks.Values) + if (!task.done) + { + var prefixc = new List(prefix); + prefixc.Add(task.code); + for (int i = 1; i < max_lpc_order; i++) + FlakeWriter.SetCoefs(i, new int[0]); + FlakeWriter.SetCoefs(max_lpc_order, prefixc.ToArray()); + magic = prefixc.Count; +#endif + + IAudioSource audioSource; + if (input_file == "-") + audioSource = new WAVReader("", Console.OpenStandardInput()); + else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".wav") + audioSource = new WAVReader(input_file, null); + else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".flac") + audioSource = new FlakeReader(input_file, null); + else + { + Usage(); + return 3; + } + + if (buffered) + audioSource = new AudioPipe(audioSource, 0x10000); + if (output_file == null) + output_file = Path.ChangeExtension(input_file, "flac"); + FlakeWriter flake = new FlakeWriter((output_file == "-" || output_file == "nul") ? "" : output_file, + output_file == "-" ? Console.OpenStandardOutput() : + output_file == "nul" ? new NullStream() : null, + audioSource.PCM); + flake.FinalSampleCount = audioSource.Length - skip_a - skip_b; + IAudioDest audioDest = flake; + AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); + + try + { + if (level >= 0) + flake.CompressionLevel = level; + if (prediction_type != null) + flake.PredictionType = Flake.LookupPredictionType(prediction_type); + if (stereo_method != null) + flake.StereoMethod = Flake.LookupStereoMethod(stereo_method); + if (window_method != null) + flake.WindowMethod = Flake.LookupWindowMethod(window_method); + if (order_method != null) + flake.OrderMethod = Flake.LookupOrderMethod(order_method); + if (window_function != null) + flake.WindowFunction = Flake.LookupWindowFunction(window_function); + if (min_partition_order >= 0) + flake.MinPartitionOrder = min_partition_order; + if (max_partition_order >= 0) + flake.MaxPartitionOrder = max_partition_order; + if (min_lpc_order >= 0) + flake.MinLPCOrder = min_lpc_order; + if (max_lpc_order >= 0) + flake.MaxLPCOrder = max_lpc_order; + if (min_fixed_order >= 0) + flake.MinFixedOrder = min_fixed_order; + if (max_fixed_order >= 0) + flake.MaxFixedOrder = max_fixed_order; + if (min_precision >= 0) + flake.MinPrecisionSearch = min_precision; + if (max_precision >= 0) + flake.MaxPrecisionSearch = max_precision; + if (blocksize >= 0) + flake.BlockSize = blocksize; + if (estimation_depth >= 0) + flake.EstimationDepth = estimation_depth; + if (padding >= 0) + flake.Padding = padding; + if (vbr_mode >= 0) + flake.VBRMode = vbr_mode; + if (magic >= 0) + flake.DevelopmentMode = magic; + flake.DoSeekTable = do_seektable; + (flake.Settings as FlakeWriterSettings).DoVerify = do_verify; + (flake.Settings as FlakeWriterSettings).DoMD5 = do_md5; + } + catch (Exception ex) + { + Usage(); + Console.WriteLine(""); + Console.WriteLine("Error: {0}.", ex.Message); + return 4; + } + + if (!quiet) + { + Console.WriteLine("Filename : {0}", input_file); + Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.PCM.SampleRate)); + } + + start = DateTime.Now; + +#if !DEBUG + try +#endif + { + audioSource.Position = skip_a; + while (audioSource.Read(buff, skip_b == 0 ? -1 : (int)audioSource.Remaining - skip_b) != 0) + { + audioDest.Write(buff); + TimeSpan elapsed = DateTime.Now - start; + if (!quiet) + { + if ((elapsed - lastPrint).TotalMilliseconds > 60) + { + Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", + 100.0 * audioSource.Position / audioSource.Length, + audioSource.Position / elapsed.TotalSeconds / audioSource.PCM.SampleRate, + elapsed,//.ToString(@"[-][d’.’]hh’:’mm’:’ss[‘.’ff]"), + TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length) + ); + lastPrint = elapsed; + } + } + } + audioDest.Close(); + } +#if !DEBUG + catch (Exception ex) + { + Console.Error.Write("\r \r"); + Console.WriteLine("Error : {0}", ex.Message); + audioDest.Delete(); + audioSource.Close(); + return 5; + } +#endif + + TimeSpan totalElapsed = DateTime.Now - start; + if (!quiet) + { + Console.Error.Write("\r \r"); + Console.WriteLine("Results : {0:0.00}x; {2} bytes in {1} seconds;", + audioSource.Position / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, + totalElapsed, + flake.TotalSize + ); + } + audioSource.Close(); + +#if FINETUNE + task.size = flake.TotalSize; + Console.SetOut(stdout); + Console.Out.WriteLine("{0}\t{1:0.00}\t{2}..{3}\t{4}\t{5}\t{6}/{7}\t{8}\t{9}\t{10}\t{11}", + flake.TotalSize, + flake.UserProcessorTime.TotalSeconds > 0 ? flake.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds, + flake.MinLPCOrder, + flake.MaxLPCOrder, + flake.BlockSize, + task.gen, + task.no.ToString().PadLeft(total_added_tasks.ToString().Length, '0'), + total_added_tasks, + task.min_depth, + best_task != null && task.size < best_task.size ? "+" + (best_task.size - task.size).ToString() : task.IsImprovement ? "*" : "", + string.Join(",", prefixc.ConvertAll(x => string.Format(codefmt, x)).ToArray()), + string.Join(",", task.parents.ConvertAll(p => string.Format(codefmt, p.code)).ToArray()) + ); +#else + + if (debug) + { + Console.SetOut(stdout); + Console.Out.WriteLine("{0}\t{1:0.00}\t{2}\t{3}\t{4}\t{5}\t{6}..{7}\t{8}..{9}\t{10}..{11}\t{12}..{13}\t{14}\t{15}\t{16}", + flake.TotalSize, + flake.UserProcessorTime.TotalSeconds > 0 ? flake.UserProcessorTime.TotalSeconds : totalElapsed.TotalSeconds, + flake.PredictionType.ToString().PadRight(15), + flake.StereoMethod.ToString().PadRight(15), + (flake.OrderMethod.ToString() + "(" + flake.EstimationDepth.ToString() + ")").PadRight(15), + flake.WindowFunction, + flake.MinPartitionOrder, + flake.MaxPartitionOrder, + flake.MinLPCOrder, + flake.MaxLPCOrder, + flake.MinFixedOrder, + flake.MaxFixedOrder, + flake.MinPrecisionSearch, + flake.MaxPrecisionSearch, + flake.BlockSize, + flake.VBRMode, + coeffs ?? "" + ); + } +#endif + +#if FINETUNE + if (best_task == null || task.size < best_task.size) + best_task = task; + } + + var promising_tasks = new List(); + promising_tasks.AddRange(tasks.Values); + promising_tasks.RemoveAll(task => !task.IsImprovement); + promising_tasks.Sort((task1, task2) => task1.size.CompareTo(task2.size)); + if (finetune_depth >= 0 && promising_tasks.Count > finetune_depth) + promising_tasks.RemoveRange(finetune_depth, promising_tasks.Count - finetune_depth); + total_added_tasks = 0; + foreach (var c in promising_tasks) + { + foreach(var c1 in c.GetDerivativeCodes(max_lpc_order)) + if (!tasks.ContainsKey(c1)) + { + var new_task = new FineTuneTask(c1, ++total_added_tasks, c); + foreach(var c2 in new_task.GetDerivativeCodes(max_lpc_order)) + if (tasks.ContainsKey(c2) && tasks[c2].done && !new_task.parents.Contains(tasks[c2])) + new_task.parents.Add(tasks[c2]); + new_task.min_depth = int.MaxValue; + foreach(var p in new_task.parents) + if (promising_tasks.IndexOf(p) >= 0) + new_task.min_depth = Math.Min(new_task.min_depth, Math.Max(p.min_depth, promising_tasks.IndexOf(p) + 1)); + tasks.Add(c1, new_task); + } + } + if (total_added_tasks == 0) + break; + } while (true); + + prefix.Add(best_task.code); + } while (prefix.Count < max_prefix); + + Console.Out.WriteLine("\t{0}", string.Join(",", prefix.ConvertAll(x => string.Format(codefmt, x)).ToArray())); +#endif + return 0; + } + } } diff --git a/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs b/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs index 69ef28b..1eb5614 100644 --- a/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs +++ b/CUETools/CUETools.TestCodecs/AccurateRipVerifyTest.cs @@ -317,7 +317,21 @@ namespace CUETools.TestCodecs } } } + + [TestMethod()] + [Ignore] + public void asdaTest() + { + //var tempPath = @"C:\Users\user\Downloads\CUETools_2.1.2a\CUE Tools\LocalDB.xml"; + var tempPath = @"C:\Users\user\Downloads\CUETools_2.1.4\CUE Tools\LocalDB.xml"; + var path = tempPath + @".z"; + //using (var fileStream = new System.IO.FileStream(tempPath, System.IO.FileMode.CreateNew)) + //using (var deflateStream = new System.IO.Compression.DeflateStream(fileStream, System.IO.Compression.CompressionMode.Compress)) + using (var fileStream1 = new System.IO.FileStream(tempPath, System.IO.FileMode.CreateNew)) + using (var fileStream2 = new System.IO.FileStream(path, System.IO.FileMode.Open)) + using (var deflateStream = new System.IO.Compression.DeflateStream(fileStream2, System.IO.Compression.CompressionMode.Decompress)) + deflateStream.CopyTo(fileStream1); + } } - } diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index e2f849e..12333fc 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -102,6 +102,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.TTA", "..\CUETools.Codecs.TTA\CUETools.Codecs.TTA.vcxproj", "{1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Converter", "..\CUETools.Converter\CUETools.Converter.csproj", "{115CC5B0-0385-41CD-8A23-6A7EA4C51926}" + ProjectSection(ProjectDependencies) = postProject + {6B143A39-C7B2-4743-9917-92262C60E9A6} = {6B143A39-C7B2-4743-9917-92262C60E9A6} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUEControls", "..\CUEControls\CUEControls.csproj", "{CA4D64E6-6544-4A29-8BA5-7DB08D50D072}" EndProject diff --git a/CUETools/frmCUETools.cs b/CUETools/frmCUETools.cs index 84b1493..977702c 100644 --- a/CUETools/frmCUETools.cs +++ b/CUETools/frmCUETools.cs @@ -942,7 +942,7 @@ namespace JDP dlg.LookupAlbumInfo(_profile._config.advanced.CacheMetadata, true, true, - CTDBMetadataSearch.Default); + _profile._config.advanced.metadataSearch); dlgRes = dlg.ShowDialog(this); _choiceMaxed = dlg.WindowState == FormWindowState.Maximized; if (!_choiceMaxed) @@ -2250,7 +2250,7 @@ namespace JDP if (_choiceMaxed) dlg.WindowState = FormWindowState.Maximized; dlg.CUE = CueSheet; - dlg.LookupAlbumInfo(true, node is FileSystemTreeNodeLocalDBEntry, true, CTDBMetadataSearch.Default); + dlg.LookupAlbumInfo(true, node is FileSystemTreeNodeLocalDBEntry, true, _profile._config.advanced.metadataSearch); var dlgRes = dlg.ShowDialog(this); _choiceMaxed = dlg.WindowState == FormWindowState.Maximized; if (!_choiceMaxed) diff --git a/CUETools/frmCUETools.resx b/CUETools/frmCUETools.resx index d71501e..91e533c 100644 --- a/CUETools/frmCUETools.resx +++ b/CUETools/frmCUETools.resx @@ -126,7 +126,7 @@ - 503, 24 + 401, 24 MiddleLeft @@ -997,7 +997,7 @@ 10, 70 - 51, 17 + 50, 17 16 @@ -1063,7 +1063,7 @@ 10, 53 - 55, 17 + 56, 17 14 @@ -1096,7 +1096,7 @@ 10, 19 - 65, 17 + 64, 17 13 @@ -1585,7 +1585,7 @@ 6, 71 - 106, 17 + 109, 17 6 @@ -1651,7 +1651,7 @@ 6, 37 - 51, 17 + 53, 17 3 @@ -1684,7 +1684,7 @@ 6, 20 - 62, 17 + 60, 17 2 diff --git a/CUETools/frmChoice.cs b/CUETools/frmChoice.cs index d2858a5..65c4472 100644 --- a/CUETools/frmChoice.cs +++ b/CUETools/frmChoice.cs @@ -160,7 +160,7 @@ namespace JDP private void AutoResizeList(ListView list, int mainCol) { list.SuspendLayout(); - int widthAvailable = list.Width - SystemInformation.BorderSize.Width - SystemInformation.VerticalScrollBarWidth; + int widthAvailable = list.ClientSize.Width - 2 * SystemInformation.BorderSize.Width - SystemInformation.VerticalScrollBarWidth; for (int i = 0; i < list.Columns.Count; i++) if (i != mainCol) { diff --git a/taglib-sharp/src/taglib-sharp.csproj b/taglib-sharp/src/taglib-sharp.csproj index 7bc8a2e..1759cd0 100644 --- a/taglib-sharp/src/taglib-sharp.csproj +++ b/taglib-sharp/src/taglib-sharp.csproj @@ -24,7 +24,7 @@ true full true - . + ..\..\bin\Debug\ prompt 4 true